{"id":31055436,"url":"https://github.com/knuckles-team/tunnel-manager","last_synced_at":"2026-05-10T03:24:22.204Z","repository":{"id":314514198,"uuid":"1055820120","full_name":"Knuckles-Team/tunnel-manager","owner":"Knuckles-Team","description":"Create SSH Tunnels to your remote hosts and host as an MCP Server for Agentic AI!","archived":false,"fork":false,"pushed_at":"2026-04-10T05:10:02.000Z","size":398,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T07:23:44.295Z","etag":null,"topics":["a2a","a2a-server","ag-ui","agentic-ai","ai","mcp-server","paramiko","python","ssh","tunneling"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Knuckles-Team.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-09-12T21:27:47.000Z","updated_at":"2026-04-10T05:08:52.000Z","dependencies_parsed_at":"2025-10-29T03:20:34.393Z","dependency_job_id":"3facc29f-4ac7-486f-8f2e-5c6f4ed7adfa","html_url":"https://github.com/Knuckles-Team/tunnel-manager","commit_stats":null,"previous_names":["knuckles-team/tunnel-manager"],"tags_count":62,"template":false,"template_full_name":null,"purl":"pkg:github/Knuckles-Team/tunnel-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Knuckles-Team%2Ftunnel-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Knuckles-Team%2Ftunnel-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Knuckles-Team%2Ftunnel-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Knuckles-Team%2Ftunnel-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Knuckles-Team","download_url":"https://codeload.github.com/Knuckles-Team/tunnel-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Knuckles-Team%2Ftunnel-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31922399,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a2a","a2a-server","ag-ui","agentic-ai","ai","mcp-server","paramiko","python","ssh","tunneling"],"created_at":"2025-09-15T04:48:13.827Z","updated_at":"2026-05-10T03:24:22.189Z","avatar_url":"https://github.com/Knuckles-Team.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tunnel Manager - A2A | AG-UI | MCP\n\n![PyPI - Version](https://img.shields.io/pypi/v/tunnel-manager)\n![MCP Server](https://badge.mcpx.dev?type=server 'MCP Server')\n![PyPI - Downloads](https://img.shields.io/pypi/dd/tunnel-manager)\n![GitHub Repo stars](https://img.shields.io/github/stars/Knuckles-Team/tunnel-manager)\n![GitHub forks](https://img.shields.io/github/forks/Knuckles-Team/tunnel-manager)\n![GitHub contributors](https://img.shields.io/github/contributors/Knuckles-Team/tunnel-manager)\n![PyPI - License](https://img.shields.io/pypi/l/tunnel-manager)\n![GitHub](https://img.shields.io/github/license/Knuckles-Team/tunnel-manager)\n\n![GitHub last commit (by committer)](https://img.shields.io/github/last-commit/Knuckles-Team/tunnel-manager)\n![GitHub pull requests](https://img.shields.io/github/issues-pr/Knuckles-Team/tunnel-manager)\n![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/Knuckles-Team/tunnel-manager)\n![GitHub issues](https://img.shields.io/github/issues/Knuckles-Team/tunnel-manager)\n\n![GitHub top language](https://img.shields.io/github/languages/top/Knuckles-Team/tunnel-manager)\n![GitHub language count](https://img.shields.io/github/languages/count/Knuckles-Team/tunnel-manager)\n![GitHub repo size](https://img.shields.io/github/repo-size/Knuckles-Team/tunnel-manager)\n![GitHub repo file count (file type)](https://img.shields.io/github/directory-file-count/Knuckles-Team/tunnel-manager)\n![PyPI - Wheel](https://img.shields.io/pypi/wheel/tunnel-manager)\n![PyPI - Implementation](https://img.shields.io/pypi/implementation/tunnel-manager)\n\n*Version: 1.9.0*\n\n## Overview\n\nThis project provides a Python-based `Tunnel` class for secure SSH connections and file transfers, integrated with a FastMCP server (`mcp_server.py`) to expose these capabilities as tools for AI-driven workflows. The implementation supports both standard SSH (e.g., for local networks) and Teleport's secure access platform, leveraging the `paramiko` library for SSH operations.\n\n### Features\n\n#### Tunnel Class\n- **Purpose**: Facilitates secure SSH connections, file transfers, and key management for single or multiple hosts.\n- **Key Functionality**:\n    - **Run Remote Commands**: Execute shell commands on a remote host and retrieve output.\n    - **File Upload/Download**: Transfer files to/from a single host or all hosts in an inventory group using SFTP.\n    - **Passwordless SSH Setup**: Configure key-based authentication for secure, passwordless access, with support for RSA and Ed25519 key types.\n    - **SSH Config Management**: Copy local SSH config files to remote hosts.\n    - **Key Rotation**: Generate and deploy new SSH key pairs (RSA or Ed25519), updating `authorized_keys`.\n    - **Inventory Support**: Operate on multiple hosts defined in an Ansible-style YAML inventory, with group targeting (e.g., `all`, `homelab`, `poweredge`).\n    - **Teleport Support**: Seamlessly integrates with Teleport's certificate-based authentication and proxying.\n    - **Configuration Flexibility**: Loads SSH settings from `~/.ssh/config` by default, with optional overrides for username, password, identity files, certificates, and proxy commands.\n    - **Logging**: Optional file-based logging for debugging and auditing.\n    - **Parallel Execution**: Support for parallel operations across multiple hosts with configurable thread limits.\n    - **Key Type Support**: Explicit support for both RSA and Ed25519 keys in authentication, generation, and rotation for enhanced security and compatibility.\n    - **Host Management**: Managed host inventory with `HostManager` class for storing and retrieving host configurations.\n\n#### FastMCP Server\n- **Purpose**: Exposes `Tunnel` class functionality as a FastMCP server, enabling AI tools to perform remote operations programmatically.\n- **Tools Provided**:\n  - **Host Management Tools**:\n    - `list_hosts`: List all managed hosts in the inventory\n    - `add_host`: Add a new host to the managed inventory\n    - `remove_host`: Remove a host from the managed inventory\n  - **Single Host Operations**:\n    - `run_command_on_remote_host`: Runs a shell command on a single remote host\n    - `send_file_to_remote_host`: Uploads a file to a single remote host via SFTP\n    - `receive_file_from_remote_host`: Downloads a file from a single remote host via SFTP\n    - `check_ssh_server`: Checks if the SSH server is running and configured for key-based authentication\n    - `test_key_auth`: Tests key-based authentication for a host\n    - `setup_passwordless_ssh`: Sets up passwordless SSH for a single host\n    - `copy_ssh_config`: Copies an SSH config file to a single remote host\n    - `rotate_ssh_key`: Rotates SSH keys for a single host\n    - `remove_host_key`: Removes a host's key from the local `known_hosts` file\n  - **Inventory Operations**:\n    - `configure_key_auth_on_inventory`: Sets up passwordless SSH for all hosts in an inventory group\n    - `run_command_on_inventory`: Runs a command on all hosts in an inventory group\n    - `copy_ssh_config_on_inventory`: Copies an SSH config file to all hosts in an inventory group\n    - `rotate_ssh_key_on_inventory`: Rotates SSH keys for all hosts in an inventory group\n    - `send_file_to_inventory`: Uploads a file to all hosts in an inventory group via SFTP\n    - `receive_file_from_inventory`: Downloads a file from all hosts in an inventory group via SFTP\n  - **Operation Management Tools**:\n    - `start_operation`: Start a new operation with progress tracking\n    - `get_operation_progress`: Get the progress of a running operation\n    - `cancel_operation`: Cancel a running operation\n    - `get_resource_metrics`: Get resource metrics during operations\n    - `list_active_sessions`: List active SSH sessions\n  - **System Intelligence Tools**:\n    - `get_system_info`: Get comprehensive system information (OS, hardware, packages, uptime)\n    - `discover_services`: Discover running services, processes, and open ports\n    - `analyze_logs`: Analyze log files for specified patterns\n    - `network_topology`: Map network interfaces, routes, and active connections\n  - **Advanced File Operations Tools**:\n    - `recursive_file_operations`: Perform recursive directory operations (copy, move, delete, list, chmod, chown)\n    - `file_content_search`: Search for file content across directories\n    - `file_watch_monitor`: Monitor files/directories for real-time changes\n    - `file_diff_compare`: Compare files across two different hosts\n    - `smart_backup`: Create automated backups with versioning and compression\n  - **Security Auditing Tools**:\n    - `security_audit`: Perform comprehensive security assessment\n    - `compliance_check`: Check compliance against security standards (CIS, PCI DSS, HIPAA)\n    - `vulnerability_scan`: Scan for known vulnerabilities\n    - `access_control_audit`: Audit access controls and permissions\n- **Transport Options**: Supports `stdio` (for local scripting), `http`, and `sse` transport modes.\n- **Progress Reporting**: Integrates with FastMCP's `Context` for progress updates during operations.\n- **Logging**: Comprehensive logging to a file or console output.\n- **Error Handling**: Consistent error responses using `ResponseBuilder` for all tools.\n\n#### Enhanced Capabilities for Agentic Frameworks\nThe tunnel-manager now includes advanced capabilities specifically designed for AI-driven workflows:\n\n**Operation Management**\n- Track long-running operations with streaming progress updates\n- Monitor CPU, memory, and disk usage during operations\n- Maintain persistent SSH connection pools for efficiency\n- Cancel in-progress operations gracefully\n- Tools: start_operation, get_operation_progress, cancel_operation, get_resource_metrics, list_active_sessions\n\n**System Intelligence \u0026 Discovery**\n- Gather comprehensive system information (OS, hardware, packages, uptime)\n- Discover running services, processes, and open ports\n- Analyze log files for patterns and security events\n- Map network topology (interfaces, routes, DNS, connections)\n- Tools: get_system_info, discover_services, analyze_logs, network_topology\n\n**Advanced File Operations**\n- Perform recursive directory operations (copy, move, delete, chmod, chown)\n- Search file content across multiple directories with grep-like functionality\n- Monitor files/directories for real-time changes\n- Compare files across different hosts\n- Create automated backups with compression and versioning\n- Tools: recursive_file_operations, file_content_search, file_watch_monitor, file_diff_compare, smart_backup\n\n**Security \u0026 Compliance Automation**\n- Perform comprehensive security assessments with scoring (0-100)\n- Check compliance against industry standards (CIS Benchmark, PCI DSS, HIPAA)\n- Scan for known vulnerabilities in packages and configurations\n- Audit access controls, user permissions, sudo configuration, and SSH settings\n- Tools: security_audit, compliance_check, vulnerability_scan, access_control_audit\n\n#### Testing Infrastructure\n- **Comprehensive Test Suite**: 212 tests covering core functionality with enhanced capabilities (98.6% pass rate)\n- **Test Coverage**:\n  - `tunnel_manager.py`: 74% coverage\n  - `agent_server.py`: 96% coverage\n  - `__init__.py`: 89% coverage\n  - `operation_manager.py`: Full test coverage (37 tests)\n  - `system_intelligence.py`: Full test coverage (27 tests)\n  - `advanced_file_manager.py`: Full test coverage (32 tests)\n  - `security_auditor.py`: Full test coverage (28 tests)\n- **Test Categories**:\n  - Unit tests for `HostManager` class\n  - Unit tests for `Tunnel` class (SSH operations, file transfers, key management)\n  - Unit tests for MCP server helper functions\n  - Unit tests for agent server functionality\n  - Integration tests for SSH operations\n  - Tests for enhanced operation management with progress tracking\n  - Tests for system intelligence and discovery\n  - Tests for advanced file operations\n  - Tests for security and compliance auditing\n- **Testing Framework**: pytest with pytest-asyncio for async testing\n\n## Usage\n\n### CLI\n| Short Flag | Long Flag            | Description                                              | Required | Default Value |\n|------------|----------------------|----------------------------------------------------------|----------|---------------|\n| -h         | --help               | Show usage for the script                                | No       | None          |\n|            | --log-file           | Log to specified file (default: console output)           | No       | Console       |\n|            | setup-all            | Setup passwordless SSH for all hosts in inventory         | Yes*     | None          |\n|            | --inventory          | YAML inventory path                                      | Yes      | None          |\n|            | --shared-key-path    | Path to shared private key                               | No       | ~/.ssh/id_shared |\n|            | --key-type           | Key type (rsa or ed25519)                                | No       | ed25519       |\n|            | --group              | Inventory group to target                                 | No       | all           |\n|            | --parallel           | Run operation in parallel                                | No       | False         |\n|            | --max-threads        | Max threads for parallel execution                       | No       | 5             |\n|            | run-command          | Run a shell command on all hosts in inventory            | Yes*     | None          |\n|            | --remote-command     | Shell command to run                                     | Yes      | None          |\n|            | copy-config          | Copy SSH config to all hosts in inventory                | Yes*     | None          |\n|            | --local-config-path  | Local SSH config path                                    | Yes      | None          |\n|            | --remote-config-path | Remote path for SSH config                               | No       | ~/.ssh/config |\n|            | rotate-key           | Rotate SSH keys for all hosts in inventory               | Yes*     | None          |\n|            | --key-prefix         | Prefix for new key paths (appends hostname)              | No       | ~/.ssh/id_    |\n|            | --key-type           | Key type (rsa or ed25519)                                | No       | ed25519       |\n|            | send-file            | Upload a file to all hosts in inventory                  | Yes*     | None          |\n|            | --local-path         | Local file path to upload                                | Yes      | None          |\n|            | --remote-path        | Remote destination path                                  | Yes      | None          |\n|            | receive-file         | Download a file from all hosts in inventory              | Yes*     | None          |\n|            | --remote-path        | Remote file path to download                             | Yes      | None          |\n|            | --local-path-prefix  | Local directory path prefix to save files                | Yes      | None          |\n\n### Notes\nOne of the commands (`setup-all`, `run-command`, `copy-config`, `rotate-key`, `send-file`, `receive-file`) must be specified as the first argument to `tunnel_manager.py`. Each command has required arguments that must be specified with flags:\n- `setup-all`: Requires `--inventory`.\n- `run-command`: Requires `--inventory` and `--remote-command`.\n- `copy-config`: Requires `--inventory` and `--local-config-path`.\n- `rotate-key`: Requires `--inventory`.\n- `send-file`: Requires `--inventory`, `--local-path`, and `--remote-path`.\n- `receive-file`: Requires `--inventory`, `--remote-path`, and `--local-path-prefix`.\n\n### Additional Notes\n- Ensure `ansible_host` values in `inventory.yml` are resolvable IPs or hostnames.\n- Update `ansible_ssh_private_key_file` in the inventory after running `rotate-key`.\n- Use `--log-file` for file-based logging or omit for console output.\n- The `--parallel` option speeds up operations but may overload resources; adjust `--max-threads` as needed.\n- The `receive-file` command saves files to `local_path_prefix/\u003chostname\u003e/\u003cfilename\u003e` to preserve original filenames and avoid conflicts.\n- Ed25519 keys are recommended for better security and performance over RSA, but RSA is supported for compatibility with older systems.\n\n#### 1. Setup Passwordless SSH\nSet up passwordless SSH for hosts in the inventory, distributing a shared key. Use `--key-type` to specify RSA or Ed25519 (default: ed25519).\n- **Target `all` group (sequential, Ed25519)**:\n  ```bash\n  tunnel-manager setup-all --inventory inventory.yml --shared-key-path ~/.ssh/id_shared --key-type ed25519\n  ```\n- **Target `homelab` group (parallel, 3 threads, RSA)**:\n  ```bash\n  tunnel-manager setup-all --inventory inventory.yml --shared-key-path ~/.ssh/id_shared_rsa --key-type rsa --group homelab --parallel --max-threads 3\n  ```\n- **Target `poweredge` group (sequential, Ed25519)**:\n  ```bash\n  tunnel-manager --log-file setup_poweredge.log setup-all --inventory inventory.yml --shared-key-path ~/.ssh/id_shared --key-type ed25519 --group poweredge\n  ```\n\n#### 2. Run a Command\nExecute a shell command on all hosts in the specified group.\n- **Run `uptime` on `all` group (sequential)**:\n  ```bash\n  tunnel-manager run-command --inventory inventory.yml --remote-command \"uptime\"\n  ```\n- **Run `df -h` on `homelab` group (parallel, 5 threads)**:\n  ```bash\n  tunnel-manager run-command --inventory inventory.yml --remote-command \"df -h\" --group homelab --parallel --max-threads 5\n  ```\n- **Run `whoami` on `poweredge` group (sequential)**:\n  ```bash\n  tunnel-manager run-command --inventory inventory.yml --remote-command \"whoami\" --group poweredge\n  ```\n\n#### 3. Copy SSH Config\nCopy a local SSH config file to the remote hosts’ `~/.ssh/config`.\n- **Copy to `all` group (sequential)**:\n  ```bash\n  tunnel-manager copy-config --inventory inventory.yml --local-config-path ~/.ssh/config\n  ```\n- **Copy to `homelab` group (parallel, 4 threads)**:\n  ```bash\n  tunnel-manager copy-config --inventory inventory.yml --local-config-path ~/.ssh/config --group homelab --parallel --max-threads 4\n  ```\n- **Copy to `poweredge` group with custom remote path**:\n  ```bash\n  tunnel-manager --log-file copy_config.log copy-config --inventory inventory.yml --local-config-path ~/.ssh/config --remote-config-path ~/.ssh/custom_config --group poweredge\n  ```\n\n#### 4. Rotate SSH Keys\nRotate SSH keys for hosts, generating new keys with a prefix. Use `--key-type` to specify RSA or Ed25519 (default: ed25519).\n- **Rotate keys for `all` group (sequential, Ed25519)**:\n  ```bash\n  tunnel-manager rotate-key --inventory inventory.yml --key-prefix ~/.ssh/id_ --key-type ed25519\n  ```\n- **Rotate keys for `homelab` group (parallel, 3 threads, RSA)**:\n  ```bash\n  tunnel-manager rotate-key --inventory inventory.yml --key-prefix ~/.ssh/id_rsa_ --key-type rsa --group homelab --parallel --max-threads 3\n  ```\n- **Rotate keys for `poweredge` group (sequential, Ed25519)**:\n  ```bash\n  tunnel-manager --log-file rotate.log rotate-key --inventory inventory.yml --key-prefix ~/.ssh/id_ --key-type ed25519 --group poweredge\n  ```\n\n#### 5. Upload a File\nUpload a local file to all hosts in the specified group.\n- **Upload to `all` group (sequential)**:\n  ```bash\n  tunnel-manager send-file --inventory inventory.yml --local-path ./myfile.txt --remote-path /home/user/myfile.txt\n  ```\n- **Upload to `homelab` group (parallel, 3 threads)**:\n  ```bash\n  tunnel-manager send-file --inventory inventory.yml --local-path ./myfile.txt --remote-path /home/user/myfile.txt --group homelab --parallel --max-threads 3\n  ```\n- **Upload to `poweredge` group (sequential)**:\n  ```bash\n  tunnel-manager --log-file upload_poweredge.log send-file --inventory inventory.yml --local-path ./myfile.txt --remote-path /home/user/myfile.txt --group poweredge\n  ```\n\n#### 6. Download a File\nDownload a file from all hosts in the specified group, saving to host-specific subdirectories (e.g., `downloads/R510/myfile.txt`).\n- **Download from `all` group (sequential)**:\n  ```bash\n  tunnel-manager receive-file --inventory inventory.yml --remote-path /home/user/myfile.txt --local-path-prefix ./downloads\n  ```\n- **Download from `homelab` group (parallel, 3 threads)**:\n  ```bash\n  tunnel-manager receive-file --inventory inventory.yml --remote-path /home/user/myfile.txt --local-path-prefix ./downloads --group homelab --parallel --max-threads 3\n  ```\n- **Download from `poweredge` group (sequential)**:\n  ```bash\n  tunnel-manager --log-file download_poweredge.log receive-file --inventory inventory.yml --remote-path /home/user/myfile.txt --local-path-prefix ./downloads --group poweredge\n  ```\n\n### Tunnel Manager Inventory\n\n**Inventory File Example (`inventory.yml`)**:\n\n```yaml\nall:\n  hosts:\n    r510:\n      ansible_host: 192.168.1.10\n      ansible_user: admin\n      ansible_ssh_private_key_file: \"~/.ssh/id_ed25519\"\n    r710:\n      ansible_host: 192.168.1.11\n      ansible_user: admin\n      ansible_ssh_pass: mypassword\n    gr1080:\n      ansible_host: 192.168.1.14\n      ansible_user: admin\n      ansible_ssh_private_key_file: \"~/.ssh/id_rsa\"\nhomelab:\n  hosts:\n    r510:\n      ansible_host: 192.168.1.10\n      ansible_user: admin\n      ansible_ssh_private_key_file: \"~/.ssh/id_ed25519\"\n    r710:\n      ansible_host: 192.168.1.11\n      ansible_user: admin\n      ansible_ssh_pass: mypassword\n    gr1080:\n      ansible_host: 192.168.1.14\n      ansible_user: admin\n      ansible_ssh_private_key_file: \"~/.ssh/id_rsa\"\npoweredge:\n  hosts:\n    r510:\n      ansible_host: 192.168.1.10\n      ansible_user: admin\n      ansible_ssh_private_key_file: \"~/.ssh/id_ed25519\"\n    r710:\n      ansible_host: 192.168.1.11\n      ansible_user: admin\n      ansible_ssh_pass: mypassword\n```\n\nReplace IPs, usernames, and passwords with your actual values.\n\n\n### MCP CLI\n\n| Short Flag | Long Flag                          | Description                                                                 |\n|------------|------------------------------------|-----------------------------------------------------------------------------|\n| -h         | --help                             | Display help information                                                    |\n| -t         | --transport                        | Transport method: 'stdio', 'http', or 'sse' [legacy] (default: stdio)       |\n| -s         | --host                             | Host address for HTTP transport (default: 0.0.0.0)                          |\n| -p         | --port                             | Port number for HTTP transport (default: 8000)                              |\n|            | --auth-type                        | Authentication type: 'none', 'static', 'jwt', 'oauth-proxy', 'oidc-proxy', 'remote-oauth' (default: none) |\n|            | --token-jwks-uri                   | JWKS URI for JWT verification                                              |\n|            | --token-issuer                     | Issuer for JWT verification                                                |\n|            | --token-audience                   | Audience for JWT verification                                              |\n|            | --oauth-upstream-auth-endpoint     | Upstream authorization endpoint for OAuth Proxy                             |\n|            | --oauth-upstream-token-endpoint    | Upstream token endpoint for OAuth Proxy                                    |\n|            | --oauth-upstream-client-id         | Upstream client ID for OAuth Proxy                                         |\n|            | --oauth-upstream-client-secret     | Upstream client secret for OAuth Proxy                                     |\n|            | --oauth-base-url                   | Base URL for OAuth Proxy                                                   |\n|            | --oidc-config-url                  | OIDC configuration URL                                                     |\n|            | --oidc-client-id                   | OIDC client ID                                                             |\n|            | --oidc-client-secret               | OIDC client secret                                                         |\n|            | --oidc-base-url                    | Base URL for OIDC Proxy                                                    |\n|            | --remote-auth-servers              | Comma-separated list of authorization servers for Remote OAuth             |\n|            | --remote-base-url                  | Base URL for Remote OAuth                                                  |\n|            | --allowed-client-redirect-uris     | Comma-separated list of allowed client redirect URIs                       |\n|            | --eunomia-type                     | Eunomia authorization type: 'none', 'embedded', 'remote' (default: none)   |\n|            | --eunomia-policy-file              | Policy file for embedded Eunomia (default: mcp_policies.json)              |\n|            | --eunomia-remote-url               | URL for remote Eunomia server                                              |\n\n### Using as an MCP Server\n\nThe MCP Server can be run in two modes: `stdio` (for local testing) or `http` (for networked access). To start the server, use the following commands:\n\n### A2A CLI\n#### Endpoints\n- **Web UI**: `http://localhost:8000/` (if enabled)\n- **A2A**: `http://localhost:8000/a2a` (Discovery: `/a2a/.well-known/agent.json`)\n- **AG-UI**: `http://localhost:8000/ag-ui` (POST)\n\n| Short Flag | Long Flag         | Description                                                            |\n|------------|-------------------|------------------------------------------------------------------------|\n| -h         | --help            | Display help information                                               |\n|            | --host            | Host to bind the server to (default: 0.0.0.0)                          |\n|            | --port            | Port to bind the server to (default: 9000)                             |\n|            | --reload          | Enable auto-reload                                                     |\n|            | --provider        | LLM Provider: 'openai', 'anthropic', 'google', 'huggingface'           |\n|            | --model-id        | LLM Model ID (default: nvidia/nemotron-3-super)                                       |\n|            | --base-url        | LLM Base URL (for OpenAI compatible providers)                         |\n|            | --api-key         | LLM API Key                                                            |\n|            | --mcp-url         | MCP Server URL (default: http://localhost:8000/mcp)                    |\n|            | --web             | Enable Pydantic AI Web UI                                              | False (Env: ENABLE_WEB_UI) |\n\n\n\n\n#### Run in stdio mode (default):\n```bash\ntunnel-manager-mcp --transport \"stdio\"\n```\n\n#### Run in HTTP mode:\n```bash\ntunnel-manager-mcp --transport \"http\"  --host \"0.0.0.0\"  --port \"8000\"\n```\n\n### Tunnel Class\nThe `Tunnel` class can be used standalone for SSH operations. Examples:\n\n#### Using RSA Keys\n```python\nfrom tunnel_manager.tunnel_manager import Tunnel\n\n# Initialize with a remote host (assumes ~/.ssh/config or explicit params)\ntunnel = Tunnel(\n    remote_host=\"192.168.1.10\",\n    username=\"admin\",\n    password=\"mypassword\",\n    identity_file=\"/path/to/id_rsa\",\n    certificate_file=\"/path/to/cert\",  # Optional for Teleport\n    proxy_command=\"tsh proxy ssh %h\",  # Optional for Teleport\n    ssh_config_file=\"~/.ssh/config\",\n)\n\n# Connect and run a command\ntunnel.connect()\nout, err = tunnel.run_command(\"ls -la /tmp\")\nprint(f\"Output: {out}\\nError: {err}\")\n\n# Upload a file\ntunnel.send_file(\"/local/file.txt\", \"/remote/file.txt\")\n\n# Download a file\ntunnel.receive_file(\"/remote/file.txt\", \"/local/downloaded.txt\")\n\n# Setup passwordless SSH with RSA\ntunnel.setup_passwordless_ssh(local_key_path=\"~/.ssh/id_rsa\", key_type=\"rsa\")\n\n# Copy SSH config\ntunnel.copy_ssh_config(\"/local/ssh_config\", \"~/.ssh/config\")\n\n# Rotate SSH key with RSA\ntunnel.rotate_ssh_key(\"/path/to/new_rsa_key\", key_type=\"rsa\")\n\n# Close the connection\ntunnel.close()\n```\n\n#### Using Ed25519 Keys\n```python\nfrom tunnel_manager.tunnel_manager import Tunnel\n\n# Initialize with a remote host (assumes ~/.ssh/config or explicit params)\ntunnel = Tunnel(\n    remote_host=\"192.168.1.10\",\n    username=\"admin\",\n    password=\"mypassword\",\n    identity_file=\"/path/to/id_ed25519\",\n    certificate_file=\"/path/to/cert\",  # Optional for Teleport\n    proxy_command=\"tsh proxy ssh %h\",  # Optional for Teleport\n    ssh_config_file=\"~/.ssh/config\",\n)\n\n# Connect and run a command\ntunnel.connect()\nout, err = tunnel.run_command(\"ls -la /tmp\")\nprint(f\"Output: {out}\\nError: {err}\")\n\n# Upload a file\ntunnel.send_file(\"/local/file.txt\", \"/remote/file.txt\")\n\n# Download a file\ntunnel.receive_file(\"/remote/file.txt\", \"/local/downloaded.txt\")\n\n# Setup passwordless SSH with Ed25519\ntunnel.setup_passwordless_ssh(local_key_path=\"~/.ssh/id_ed25519\", key_type=\"ed25519\")\n\n# Copy SSH config\ntunnel.copy_ssh_config(\"/local/ssh_config\", \"~/.ssh/config\")\n\n# Rotate SSH key with Ed25519\ntunnel.rotate_ssh_key(\"/path/to/new_ed25519_key\", key_type=\"ed25519\")\n\n# Close the connection\ntunnel.close()\n```\n\n### Deploy MCP Server as a Service\n\nThe MCP server can be deployed using Docker, with configurable authentication, middleware, and Eunomia authorization.\n\n#### Using Docker Run\n\n```bash\ndocker pull knucklessg1/tunnel-manager:latest\n\ndocker run -d \\\n  --name tunnel-manager-mcp \\\n  -p 8004:8004 \\\n  -e HOST=0.0.0.0 \\\n  -e PORT=8004 \\\n  -e TRANSPORT=http \\\n  -e AUTH_TYPE=none \\\n  -e EUNOMIA_TYPE=none \\\n  knucklessg1/tunnel-manager:latest\n```\n\nFor advanced authentication (e.g., JWT, OAuth Proxy, OIDC Proxy, Remote OAuth) or Eunomia, add the relevant environment variables:\n\n```bash\ndocker run -d \\\n  --name tunnel-manager-mcp \\\n  -p 8004:8004 \\\n  -e HOST=0.0.0.0 \\\n  -e PORT=8004 \\\n  -e TRANSPORT=http \\\n  -e AUTH_TYPE=oidc-proxy \\\n  -e OIDC_CONFIG_URL=https://provider.com/.well-known/openid-configuration \\\n  -e OIDC_CLIENT_ID=your-client-id \\\n  -e OIDC_CLIENT_SECRET=your-client-secret \\\n  -e OIDC_BASE_URL=https://your-server.com \\\n  -e ALLOWED_CLIENT_REDIRECT_URIS=http://localhost:*,https://*.example.com/* \\\n  -e EUNOMIA_TYPE=embedded \\\n  -e EUNOMIA_POLICY_FILE=/app/mcp_policies.json \\\n  knucklessg1/tunnel-manager:latest\n```\n\n#### Using Docker Compose\n\nCreate a `docker-compose.yml` file:\n\n```yaml\nservices:\n  tunnel-manager-mcp:\n    image: knucklessg1/tunnel-manager:latest\n    environment:\n      - HOST=0.0.0.0\n      - PORT=8004\n      - TRANSPORT=http\n      - AUTH_TYPE=none\n      - EUNOMIA_TYPE=none\n    ports:\n      - 8004:8004\n```\n\nFor advanced setups with authentication and Eunomia:\n\n```yaml\nservices:\n  tunnel-manager-mcp:\n    image: knucklessg1/tunnel-manager:latest\n    environment:\n      - HOST=0.0.0.0\n      - PORT=8004\n      - TRANSPORT=http\n      - AUTH_TYPE=oidc-proxy\n      - OIDC_CONFIG_URL=https://provider.com/.well-known/openid-configuration\n      - OIDC_CLIENT_ID=your-client-id\n      - OIDC_CLIENT_SECRET=your-client-secret\n      - OIDC_BASE_URL=https://your-server.com\n      - ALLOWED_CLIENT_REDIRECT_URIS=http://localhost:*,https://*.example.com/*\n      - EUNOMIA_TYPE=embedded\n      - EUNOMIA_POLICY_FILE=/app/mcp_policies.json\n    ports:\n      - 8004:8004\n    volumes:\n      - ./mcp_policies.json:/app/mcp_policies.json\n```\n\nRun the service:\n\n```bash\ndocker-compose up -d\n```\n\n#### Configure `mcp.json` for AI Integration\n\n```json\n{\n  \"mcpServers\": {\n    \"tunnel_manager\": {\n      \"command\": \"uv\",\n      \"args\": [\n        \"run\",\n        \"--with\",\n        \"tunnel-manager\",\n        \"tunnel_manager_mcp\"\n      ],\n      \"env\": {\n        \"TUNNEL_REMOTE_HOST\": \"192.168.1.12\",      // Optional\n        \"TUNNEL_USERNAME\": \"admin\",                // Optional\n        \"TUNNEL_PASSWORD\": \"\",                     // Optional\n        \"TUNNEL_REMOTE_PORT\": \"22\",                // Optional\n        \"TUNNEL_IDENTITY_FILE\": \"\",                // Optional\n        \"TUNNEL_INVENTORY\": \"~/inventory.yaml\",    // Optional\n        \"TUNNEL_INVENTORY_GROUP\": \"all\",           // Optional\n        \"TUNNEL_PARALLEL\": \"true\",                 // Optional\n        \"TUNNEL_CERTIFICATE\": \"\",                  // Optional\n        \"TUNNEL_PROXY_COMMAND\": \"\",                // Optional\n        \"TUNNEL_LOG_FILE\": \"~/tunnel_log.txt\",     // Optional\n        \"TUNNEL_MAX_THREADS\": \"6\"                  // Optional\n      },\n      \"timeout\": 200000\n    }\n  }\n}\n```\n\n## Install Python Package\n```bash\npython -m pip install tunnel-manager\n```\n\nor\n\n```bash\nuv pip install --upgrade tunnel-manager\n```\n\n## Repository Owners\n\n\n\u003cimg width=\"100%\" height=\"180em\" src=\"https://github-readme-stats.vercel.app/api?username=Knucklessg1\u0026show_icons=true\u0026hide_border=true\u0026\u0026count_private=true\u0026include_all_commits=true\" /\u003e\n\n![GitHub followers](https://img.shields.io/github/followers/Knucklessg1)\n![GitHub User's stars](https://img.shields.io/github/stars/Knucklessg1)\n\n\n## MCP Configuration Examples\n\n### 1. Standard IO (stdio) Deployment\n\n```json\n{\n  \"mcpServers\": {\n    \"tunnel-manager\": {\n      \"command\": \"uv\",\n      \"args\": [\n        \"run\",\n        \"tunnel-manager-mcp\"\n      ],\n      \"env\": {\n        \"ADVANCED_FILE_OPERATIONSTOOL\": \"True\",\n        \"AGENT_DESCRIPTION\": \"\u003cYOUR_AGENT_DESCRIPTION\u003e\",\n        \"AGENT_SYSTEM_PROMPT\": \"\u003cYOUR_AGENT_SYSTEM_PROMPT\u003e\",\n        \"DEFAULT_AGENT_NAME\": \"\u003cYOUR_DEFAULT_AGENT_NAME\u003e\",\n        \"HOST_MANAGEMENTTOOL\": \"True\",\n        \"LLM_API_KEY\": \"\u003cYOUR_LLM_API_KEY\u003e\",\n        \"LLM_BASE_URL\": \"\u003cYOUR_LLM_BASE_URL\u003e\",\n        \"MCP_URL\": \"\u003cYOUR_MCP_URL\u003e\",\n        \"MISCTOOL\": \"True\",\n        \"MODEL_ID\": \"\u003cYOUR_MODEL_ID\u003e\",\n        \"OPERATION_MANAGEMENTTOOL\": \"True\",\n        \"REMOTE_ACCESSTOOL\": \"True\",\n        \"SECURITY_AUDITINGTOOL\": \"True\",\n        \"SYSTEM_INTELLIGENCETOOL\": \"True\",\n        \"TUNNEL_CERTIFICATE\": \"\u003cYOUR_TUNNEL_CERTIFICATE\u003e\",\n        \"TUNNEL_IDENTITY_FILE\": \"\u003cYOUR_TUNNEL_IDENTITY_FILE\u003e\",\n        \"TUNNEL_INVENTORY\": \"\u003cYOUR_TUNNEL_INVENTORY\u003e\",\n        \"TUNNEL_INVENTORY_GROUP\": \"\u003cYOUR_TUNNEL_INVENTORY_GROUP\u003e\",\n        \"TUNNEL_LOG_FILE\": \"\u003cYOUR_TUNNEL_LOG_FILE\u003e\",\n        \"TUNNEL_MAX_THREADS\": \"\u003cYOUR_TUNNEL_MAX_THREADS\u003e\",\n        \"TUNNEL_PARALLEL\": \"\u003cYOUR_TUNNEL_PARALLEL\u003e\",\n        \"TUNNEL_PASSWORD\": \"\u003cYOUR_TUNNEL_PASSWORD\u003e\",\n        \"TUNNEL_PROXY_COMMAND\": \"\u003cYOUR_TUNNEL_PROXY_COMMAND\u003e\",\n        \"TUNNEL_REMOTE_HOST\": \"\u003cYOUR_TUNNEL_REMOTE_HOST\u003e\",\n        \"TUNNEL_REMOTE_PORT\": \"\u003cYOUR_TUNNEL_REMOTE_PORT\u003e\",\n        \"TUNNEL_USERNAME\": \"\u003cYOUR_TUNNEL_USERNAME\u003e\"\n      }\n    }\n  }\n}\n```\n\n### 2. Streamable HTTP (SSE) Deployment\n\n```json\n{\n  \"mcpServers\": {\n    \"tunnel-manager\": {\n      \"command\": \"uv\",\n      \"args\": [\n        \"run\",\n        \"tunnel-manager-mcp\",\n        \"--transport\",\n        \"http\",\n        \"--host\",\n        \"0.0.0.0\",\n        \"--port\",\n        \"8000\"\n      ],\n      \"env\": {\n        \"ADVANCED_FILE_OPERATIONSTOOL\": \"True\",\n        \"AGENT_DESCRIPTION\": \"\u003cYOUR_AGENT_DESCRIPTION\u003e\",\n        \"AGENT_SYSTEM_PROMPT\": \"\u003cYOUR_AGENT_SYSTEM_PROMPT\u003e\",\n        \"DEFAULT_AGENT_NAME\": \"\u003cYOUR_DEFAULT_AGENT_NAME\u003e\",\n        \"HOST_MANAGEMENTTOOL\": \"True\",\n        \"LLM_API_KEY\": \"\u003cYOUR_LLM_API_KEY\u003e\",\n        \"LLM_BASE_URL\": \"\u003cYOUR_LLM_BASE_URL\u003e\",\n        \"MCP_URL\": \"\u003cYOUR_MCP_URL\u003e\",\n        \"MISCTOOL\": \"True\",\n        \"MODEL_ID\": \"\u003cYOUR_MODEL_ID\u003e\",\n        \"OPERATION_MANAGEMENTTOOL\": \"True\",\n        \"REMOTE_ACCESSTOOL\": \"True\",\n        \"SECURITY_AUDITINGTOOL\": \"True\",\n        \"SYSTEM_INTELLIGENCETOOL\": \"True\",\n        \"TUNNEL_CERTIFICATE\": \"\u003cYOUR_TUNNEL_CERTIFICATE\u003e\",\n        \"TUNNEL_IDENTITY_FILE\": \"\u003cYOUR_TUNNEL_IDENTITY_FILE\u003e\",\n        \"TUNNEL_INVENTORY\": \"\u003cYOUR_TUNNEL_INVENTORY\u003e\",\n        \"TUNNEL_INVENTORY_GROUP\": \"\u003cYOUR_TUNNEL_INVENTORY_GROUP\u003e\",\n        \"TUNNEL_LOG_FILE\": \"\u003cYOUR_TUNNEL_LOG_FILE\u003e\",\n        \"TUNNEL_MAX_THREADS\": \"\u003cYOUR_TUNNEL_MAX_THREADS\u003e\",\n        \"TUNNEL_PARALLEL\": \"\u003cYOUR_TUNNEL_PARALLEL\u003e\",\n        \"TUNNEL_PASSWORD\": \"\u003cYOUR_TUNNEL_PASSWORD\u003e\",\n        \"TUNNEL_PROXY_COMMAND\": \"\u003cYOUR_TUNNEL_PROXY_COMMAND\u003e\",\n        \"TUNNEL_REMOTE_HOST\": \"\u003cYOUR_TUNNEL_REMOTE_HOST\u003e\",\n        \"TUNNEL_REMOTE_PORT\": \"\u003cYOUR_TUNNEL_REMOTE_PORT\u003e\",\n        \"TUNNEL_USERNAME\": \"\u003cYOUR_TUNNEL_USERNAME\u003e\"\n      }\n    }\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknuckles-team%2Ftunnel-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknuckles-team%2Ftunnel-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknuckles-team%2Ftunnel-manager/lists"}