{
  "markdown": "# MCP SSH Manager - SSH Remote Server Management via Model Context Protocol 🚀\n\nA Model Context Protocol (MCP) server that enables **Claude Code** and **OpenAI Codex** to manage multiple SSH connections. Execute commands, transfer files, manage databases, create backups, monitor health, and automate DevOps tasks across your servers — directly from your AI assistant.\n\n<div align=\"center\">\n\n[![npm version](https://img.shields.io/npm/v/mcp-ssh-manager.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/mcp-ssh-manager)\n[![npm downloads](https://img.shields.io/npm/dt/mcp-ssh-manager.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/mcp-ssh-manager)\n[![Version](https://img.shields.io/badge/Version-3.8.5-brightgreen?style=for-the-badge)](https://github.com/bvisible/mcp-ssh-manager/releases/tag/v3.8.5)\n[![Claude Code](https://img.shields.io/badge/Claude_Code-Compatible-5A67D8?style=for-the-badge&logo=anthropic)](https://claude.ai/code)\n[![OpenAI Codex](https://img.shields.io/badge/OpenAI_Codex-Compatible-00A67E?style=for-the-badge&logo=openai)](https://openai.com/codex)\n[![MCP](https://img.shields.io/badge/MCP-Server-orange?style=for-the-badge)](https://modelcontextprotocol.io)\n[![OpenSSF Scorecard](https://img.shields.io/ossf-scorecard/github.com/bvisible/mcp-ssh-manager?style=for-the-badge&label=OpenSSF)](https://scorecard.dev/viewer/?uri=github.com/bvisible/mcp-ssh-manager)\n[![License](https://img.shields.io/badge/License-MIT-blue?style=for-the-badge)](LICENSE)\n\n[![MCP Toplist](https://mcptoplist.com/badge/glama%2Fbvisible%2Fmcp-ssh-manager.svg)](https://mcptoplist.com/server/glama%2Fbvisible%2Fmcp-ssh-manager)\n\n</div>\n\n<p align=\"center\">\n  <img src=\"docs/images/ssh-manager-cli-menu.png\" alt=\"ssh-manager interactive CLI menu\" width=\"900\">\n</p>\n\n---\n\n## 🎉 What's New in v3.8.5\n\n**🔒 Security release — three command-injection advisories fixed, one of which defeated `readonly` mode** (Released: August 28, 2026)\n\n**Upgrade if you use `ssh_backup_*`, `ssh_db_dump`, `ssh_service_status` or `ssh_tail` — and especially if you rely on the `readonly` / `restricted` security modes.**\n\n- **🔴 RCE bypassing `readonly` / `restricted`** (GHSA-m793-whw6-f537) — `ssh_service_status` and `ssh_tail` are read-only, so they stay enabled on servers you locked down, and neither quoted its arguments nor consulted the policy layer. A service name like `nginx; id > /tmp/pwned` executed. This defeated the exact control those modes exist to provide.\n- **🔴 RCE through `ssh_db_dump`** (GHSA-796j-h5q5-jx6p) — the `stat` command run after the dump interpolated the output path raw. The v3.6.7 patch had stopped one line short.\n- **🟠 RCE through every `ssh_backup_*` tool** (GHSA-qwwm-vrm9-4mw8) — `backup-manager.js` had **zero** shell escaping across its 9 builders, while `database-manager.js` had 95. The v3.6.7 fix was never extended to it.\n\nThe quoting helper now lives in one module (`src/shell-quote.js`) so \"did this builder quote its inputs?\" has a single answer, and a new test drives **340 builder × argument × payload combinations** through a real shell to prove none of them execute.\n\n[Read full changelog →](CHANGELOG.md#385---2026-08-28)\n\n---\n\n## 🔐 Giving an agent SSH access, safely\n\nAn MCP SSH server is the most dangerous tool you can hand an AI agent: a shell on\nmachines that matter. This one is built so you decide how far the agent can go —\n**per server**, not globally.\n\n| Mode | What the agent can do |\n|---|---|\n| `unrestricted` *(default)* | Everything. Same behaviour as any other SSH MCP server. |\n| `readonly` | Mutating tools are refused outright — no deploy, no upload, no sudo, no database import. Read commands still work. |\n| `restricted` | Every command must match an allow pattern **and** no deny pattern. Anything else is refused before it reaches the host. |\n\n```env\nSSH_SERVER_PROD_MODE=readonly\nSSH_SERVER_STAGING_MODE=restricted\nSSH_SERVER_STAGING_ALLOW_PATTERNS=^systemctl (status|restart) myapp$;^tail -n \\d+ /var/log/\n```\n\nAlongside that:\n\n- **The sudo password never reaches the remote command line.** It travels on the\n  SSH channel's stdin, so it is not visible in `ps`, in `/proc/<pid>/cmdline`, or\n  in an `auditd` trail — unlike the `echo \"$pass\" | sudo -S` pattern common in\n  this category ([#34](https://github.com/bvisible/mcp-ssh-manager/issues/34)).\n- **Every database argument is shell-quoted** through one centralised helper,\n  guarded by a 648-combination injection test.\n- **Read-only SQL is enforced**, not suggested: `ssh_db_query` refuses anything\n  that is not a `SELECT`.\n- **Vulnerabilities are published, not buried.** See [SECURITY.md](SECURITY.md)\n  for the reporting process and the advisories already fixed.\n- **Reproducible installs**: the lockfile is committed, CI installs with\n  `npm ci`, and a test enforces that every dependency resolves to\n  registry.npmjs.org with an integrity hash and no unreviewed install scripts.\n\n---\n\n## Previous Releases\n\n<details>\n<summary><b>📜 Release history — v3.8.4 down to v1.0.0</b> (click to expand)</summary>\n\n### v3.8.4 - Secrets stop reaching the log, CodeQL on every commit (August 28, 2026)\n\n- **🔒 The logger no longer writes secrets in clear text** — it writes to `~/.ssh-manager.log` and stderr (which your MCP host captures), so one call site handing it a server config would have persisted a production password. Redaction now happens inside the logger. Also: CodeQL on every push, every action pinned by SHA, and a broken example that never parsed. [Full changelog →](CHANGELOG.md#384---2026-08-28)\n\n### v3.8.2 / v3.8.3 - Sudo password leak fixed, MCP Registry, signed releases (August 28, 2026)\n\n- **🔒 The sudo password no longer reaches the remote command line** ([#34](https://github.com/bvisible/mcp-ssh-manager/issues/34)) — it travelled through `echo \"<password>\" | sudo -S`, readable in `ps` and `/proc/<pid>/cmdline` by every account on the host. It now goes over the SSH channel's stdin. Also: listed in the **official MCP Registry** as `io.github.bvisible/mcp-ssh-manager`, releases published from CI with **SLSA provenance** and a CycloneDX SBOM, and the per-server security modes documented at last. [Full changelog →](CHANGELOG.md#383---2026-08-28)\n\n### v3.8.1 - Reproducible installs and blocking quality gates (August 28, 2026)\n\n- **Committed lockfile** ([#60](https://github.com/bvisible/mcp-ssh-manager/pull/60) — contributed by [@cudatuda](https://github.com/cudatuda)) plus `npm run test:lockfile` guarding it against drift and tampering. CI installs with `npm ci`; ESLint and the JSDoc typecheck became blocking gates after being purely decorative. [Full changelog →](CHANGELOG.md#381---2026-08-28)\n\n### v3.8.0 - Groups in your config, `ssh_sync` on Windows, tunnel crash fix (August 14, 2026)\n\n- **👥 New optional `group` field per server** ([#56](https://github.com/bvisible/mcp-ssh-manager/pull/56) — contributed by [@ice616](https://github.com/ice616), requested in [#55](https://github.com/bvisible/mcp-ssh-manager/issues/55)) — tag a server with `group = \"production\"` and it *is* in that group: `ssh_execute_group` resolves members straight from your `.env`/TOML, union'd with any `.server-groups.json` you already keep. Also: `ssh_sync` fixed from a Windows host ([#59](https://github.com/bvisible/mcp-ssh-manager/pull/59) — contributed by [@2836603852](https://github.com/2836603852)), a tunnel on a busy port no longer takes the whole MCP server down, the `@modelcontextprotocol/sdk` floor raised to `^1.30.0` over three advisories, and JSDoc type-checking added to CI. [Full changelog →](CHANGELOG.md#380---2026-08-14)\n\n### v3.7.0 - Per-server SSH agent forwarding (July 13, 2026)\n\n- **🔗 New opt-in `FORWARD_AGENT` / `forward_agent` option** ([#53](https://github.com/bvisible/mcp-ssh-manager/pull/53) — requested by [@raphaelbahat](https://github.com/raphaelbahat) in [#52](https://github.com/bvisible/mcp-ssh-manager/issues/52)) — the equivalent of OpenSSH's `ForwardAgent yes`, per server: processes on the remote host authenticate to *other* SSH hosts with the keys in your local `ssh-agent`, without copying any private key. Requires a running agent and defaults to `false`. [Full changelog →](CHANGELOG.md#370---2026-07-13)\n\n### v3.6.7 - Security: command injection fix in the database helpers (July 11, 2026)\n\n- **🔒 Every `ssh_db_*` argument is now shell-quoted** ([#51](https://github.com/bvisible/mcp-ssh-manager/pull/51) — responsibly disclosed by **Ugur Ozer, Aeon AI Risk Management** (http://airiskmanagement.ca), see [#48](https://github.com/bvisible/mcp-ssh-manager/issues/48)) — caller-controlled values (`ssh_db_list` most notably, which stayed allowed in `readonly`/`restricted` modes) were interpolated into shell-evaluated strings, allowing arbitrary command execution on the SSH target. A centralized `shellQuote()` now wraps every value across all 15 builders, guarded by a 648-combination injection test. [Full changelog →](CHANGELOG.md#367---2026-07-11)\n\n### v3.6.6 - `SUDO_PASSWORD` / `DEFAULT_DIR` / `ssh_sync` key auth work again (July 11, 2026)\n\n- **🔑 camelCase config field reads** ([#50](https://github.com/bvisible/mcp-ssh-manager/pull/50) — thanks [@egoan82](https://github.com/egoan82)) — since the v3.0.0 ConfigLoader refactor, `ssh_execute_sudo` ignored `SUDO_PASSWORD`, `DEFAULT_DIR` was ignored by `ssh_execute`/`ssh_group_execute`/`ssh_list_servers`, and `ssh_sync` never passed the configured SSH key to rsync. All aligned with the loader's camelCase fields, with a regression test locking the loader output shape. [Full changelog →](CHANGELOG.md#366---2026-07-11)\n\n### v3.6.5 - `ssh_db_query` shell-injection security fix + real row_count (June 30, 2026)\n\n- **🔒 Queries are delivered on stdin via a single-quoted heredoc** ([#44](https://github.com/bvisible/mcp-ssh-manager/pull/44), [#45](https://github.com/bvisible/mcp-ssh-manager/pull/45) — thanks [@technophile77](https://github.com/technophile77)) — the remote shell no longer parses backticks/`$(…)` inside queries (which corrupted backtick identifiers **and** let the \"SELECT-only\" tool run arbitrary shell commands), and `row_count` now reflects each engine's real output instead of counting wrapper lines. [Full changelog →](CHANGELOG.md#365---2026-06-30)\n\n### v3.6.4 - Internal cleanup + a dead-code quality gate (June 18, 2026)\n\n- **🧹 Dead-code removal (−343 lines), zero behavioral change** — removed 27 unused exports and 2 duplicate exports; the MCP server and CLI behave identically (command builders/parsers byte-identical, all 37 tools verified end-to-end). A calibrated `knip.json` plus a **blocking** `knip` CI step keep unused code from creeping back. [Full changelog →](CHANGELOG.md#364---2026-06-18)\n\n### v3.6.3 - `ssh_sync` reports the real transfer count (June 18, 2026)\n\n- **📊 No more false \"No files needed to be transferred\"** ([#42](https://github.com/bvisible/mcp-ssh-manager/pull/42) — thanks [@MakksSh](https://github.com/MakksSh)) — fixed rsync `--stats` parsing: `--stats` is always passed now, and rsync 2.x/3.x wording, openrsync's `B` suffix, and locale separators are all handled. [Full changelog →](CHANGELOG.md#363---2026-06-18)\n\n### v3.6.2 - Richer tool descriptions (June 9, 2026)\n\n- **📝 All 37 tool descriptions rewritten** — every MCP tool now documents its real behavior (side effects, destructive vs read-only nature, idempotency, sudo/auth requirements, security-mode gating, parameter semantics) instead of a 4-to-10-word summary. Agents now know the consequences before invoking a tool; no behavioral change — only `description` strings changed. [Full changelog →](CHANGELOG.md#362---2026-06-09)\n\n### v3.6.1 - Teardown hygiene follow-up (June 9, 2026)\n\n- **🔌 Module-level timers no longer pin the event loop** (follow-up to [#41](https://github.com/bvisible/mcp-ssh-manager/pull/41)) — `tunnel-manager.js` and `session-manager.js` registered module-level `setInterval`s that were never `unref()`'d, so importing either module kept Node's event loop alive. Both are now `unref()`'d. [Full changelog →](CHANGELOG.md#361---2026-06-09)\n\n### v3.6.0 - Live config hot reload + stdio lifecycle fix (June 9, 2026)\n\n- **♻️ Configuration hot reload** ([#40](https://github.com/bvisible/mcp-ssh-manager/pull/40) — thanks [@EnjoySR](https://github.com/EnjoySR)) — add or edit a server in your `.env`/TOML and the running MCP server picks it up on the next call, no restart. A `ServerConfigManager` reloads lazily on file-signature change (path + `mtime` + size); a failed reload keeps the last known-good config; real `process.env` vars keep top priority. No watcher, no polling.\n- **🔌 No more orphaned stdio processes** ([#41](https://github.com/bvisible/mcp-ssh-manager/pull/41) — thanks [@LegendaryGatz](https://github.com/LegendaryGatz)) — a stdio MCP server is torn down by stdin EOF / SIGTERM, not SIGINT; with only a `SIGINT` handler every session leaked a ~83 MB node process. Shutdown is now idempotent across `SIGINT`/`SIGTERM`/`SIGHUP`/stdin-close, timers are `unref()`'d, and the process exits **~10 ms** after teardown instead of never. [Full changelog →](CHANGELOG.md#360---2026-06-09)\n\n### v3.5.1 - Robust SSH ping health-check on Windows/OpenSSH (May 26, 2026)\n\n- **🪟 Healthy Windows sessions no longer reported as `Dead`** ([#39](https://github.com/bvisible/mcp-ssh-manager/pull/39) — thanks [@username77](https://github.com/username77)) — the liveness probe ran `echo \"ping\"` and `cmd.exe` echoed the quotes literally, failing a strict `=== 'ping'` check and needlessly rebuilding live connections. Now uses `echo ping` parsed by a null-safe `isPingAlive(stdout)` helper (CRLF/quote/case-normalized), covered by `tests/test-ssh-ping.js`. [Full changelog →](CHANGELOG.md#351---2026-05-26)\n\n### v3.5.0 - Per-server security modes — `readonly` / `restricted` + audit log (May 18, 2026)\n\nA second authorization layer that filters tool invocations **inside the MCP server**, complementing the existing client-side `autoApprove`. Useful when sharing the MCP with a third-party agent, a CI bot, or any client where `ssh_execute` shouldn't be unconditionally trusted.\n\n- **🔒 Three modes, opt-in per server** (no `MODE` field = identical to v3.4.x):\n  - **`unrestricted`** (default) — strict no-op. `evaluatePolicy()` early-returns on the first line, zero overhead.\n  - **`readonly`** — blocks mutating tools (`ssh_upload`, `ssh_deploy`, `ssh_sync`, `ssh_execute_sudo`, `ssh_backup_*`, `ssh_db_import/dump`, plus action-gated `ssh_key_manage accept|remove`, `ssh_alert_setup set`, `ssh_process_manager kill`) AND applies a built-in denylist on `ssh_execute` (rm, mv, dd, mkfs, chmod, chown, sudo, systemctl restart/stop, docker rm/stop, pipe-to-sh, redirect outside `/tmp`, curl|sh, etc.).\n  - **`restricted`** — every command must match at least one `ALLOW_PATTERNS` regex AND no `DENY_PATTERNS` regex. **DENY wins**. With no `ALLOW_PATTERNS` everything is refused (fail-closed).\n- **📝 Audit log** — opt-in JSONL per server (`SSH_SERVER_<N>_AUDIT_LOG=/path/to/audit.jsonl`). Records `ts`, `server`, `tool`, args, `allowed`, `reason` on denial, `exitCode`/`success` on execution. Sensitive arg fields (`password`, `passphrase`, `sudoPassword`, `token`, `secret`, `apikey`) are replaced with `***`.\n- **🪄 Command aliases expanded BEFORE policy evaluation** — a `DENY` pattern can't be bypassed via an alias.\n- **♻️ Backward-compatible by design** — a v3.4.x `.env` or TOML loads identically. No `MODE` field → zero behavior change. The interactive wizard (`ssh-manager server add`) defaults all three new prompts to skip. All 13 pre-existing tests pass unmodified. New `tests/test-policy.js` adds 26 tests covering modes, DENY > ALLOW precedence, invalid-regex handling, redaction, and the backward-compat fast path. [Full reference →](docs/SECURITY_MODES.md)\n\n### v3.4.1 - Modern OpenSSH 9.x compatibility (May 16, 2026)\n\n- **🔐 Expanded SSH algorithm list — handshake against OpenSSH 9.x out of the box** ([#32](https://github.com/bvisible/mcp-ssh-manager/pull/32))\n  - **KEX**: `curve25519-sha256` (+`@libssh.org`), `diffie-hellman-group15-sha512`, `diffie-hellman-group16-sha512`\n  - **Server host key**: `rsa-sha2-512`, `rsa-sha2-256` (RFC 8332)\n  - **Cipher**: `aes128-gcm@openssh.com`, `aes256-gcm@openssh.com`\n  - **HMAC**: `hmac-sha2-256-etm@openssh.com`, `hmac-sha2-512-etm@openssh.com`, `hmac-sha1-etm@openssh.com`\n  - Backward-compatible — legacy algorithms preserved at lower preference, older servers (CentOS 7, Debian 10) keep working. Thanks [@YoungHong1992](https://github.com/YoungHong1992).\n\n### v3.4.0 - Windows OpenSSH support + shell-agnostic session sync (May 7, 2026)\n\n- **🪟 Windows OpenSSH encoding & syntax fixes** — UTF-16LE base64 PowerShell payloads (Ansible-style) + `Set-Location` replacing `cd && ` ([#31](https://github.com/bvisible/mcp-ssh-manager/pull/31), thanks [@WenKingSu](https://github.com/WenKingSu))\n- **🎯 Marker-based SSH session sync** — UUID v4 protocol boundaries with `ECHO: 0` PTY, real `$?` exit codes, no more \"Timeout waiting for shell prompt\" on custom/slow/AIX shells ([#30](https://github.com/bvisible/mcp-ssh-manager/pull/30), thanks [@MakksSh](https://github.com/MakksSh))\n\n### v3.3.0 - ProxyCommand & Critical Fixes (May 2, 2026)\n\n- **🔌 ProxyCommand support** for SOCKS5 / custom proxy commands ([#24](https://github.com/bvisible/mcp-ssh-manager/pull/24))\n- **⏱️ `ssh_execute` timeout silently capped at 30 s** — fixed ([#28](https://github.com/bvisible/mcp-ssh-manager/issues/28), [#29](https://github.com/bvisible/mcp-ssh-manager/pull/29))\n- **🪟 Windows global install `/bin/bash` shim error** — fixed ([#22](https://github.com/bvisible/mcp-ssh-manager/issues/22), [#23](https://github.com/bvisible/mcp-ssh-manager/pull/23))\n- **🔧 `server add` blocked by missing `rsync`** — `rsync` now optional ([#26](https://github.com/bvisible/mcp-ssh-manager/pull/26))\n- **🔡 Hyphenated server names silently dropped** — validation hardened ([#25](https://github.com/bvisible/mcp-ssh-manager/issues/25), [#27](https://github.com/bvisible/mcp-ssh-manager/pull/27))\n\n### v3.2.2 - Global Install Fix & CLI Binary (April 7, 2026)\n\n- **🔧 Global install fixed**: `.env` path resolution now uses a fallback chain instead of hardcoded `__dirname` — works correctly with `npm install -g` ([#16](https://github.com/bvisible/mcp-ssh-manager/issues/16), [#19](https://github.com/bvisible/mcp-ssh-manager/issues/19))\n  - Fallback chain: `~/.ssh-manager/.env` → `cwd/.env` → `~/.env` → project `.env`\n  - Auto-creates `~/.ssh-manager/.env` on first `ssh-manager server add`\n- **📦 `ssh-manager` CLI registered as binary**: `npm install -g` now creates both `mcp-ssh-manager` and `ssh-manager` commands ([#18](https://github.com/bvisible/mcp-ssh-manager/issues/18))\n- **⚡ Race condition fix**: Server config is now fully loaded before the MCP server accepts requests\n\n### v3.2.0 - ProxyJump / Bastion Host Support (March 18, 2026)\n\n- **🔀 ProxyJump support**: Connect to servers behind bastion/jump hosts with a simple `PROXYJUMP` config field ([#15](https://github.com/bvisible/mcp-ssh-manager/issues/15))\n  - Chain multiple jumps (A → B → C) via recursive connections\n  - Circular dependency detection prevents infinite loops\n  - All tools work transparently through jump hosts\n- **📦 npx support fixed**: `npx mcp-ssh-manager` now works correctly ([#14](https://github.com/bvisible/mcp-ssh-manager/issues/14))\n\n### v3.1.5 - SSH Agent & Passphrase Support (March 5, 2026)\n\n- **🔑 SSH Agent support**: Automatically uses `ssh-agent` when `SSH_AUTH_SOCK` is available — passphrase-protected keys work transparently\n- **🔐 Passphrase configuration**: New `passphrase` field for both `.env` and TOML formats\n\nThanks to [@snjax](https://github.com/snjax) for the original contribution ([#12](https://github.com/bvisible/mcp-ssh-manager/pull/12)).\n\n### v3.1.4 - Windows SSH Host Support (February 22, 2026)\n\n- **🪟 Windows SSH host fix**: Commands no longer fail on Windows hosts running OpenSSH ([#10](https://github.com/bvisible/mcp-ssh-manager/issues/10))\n- New per-server `platform` config field (`SSH_SERVER_FOO_PLATFORM=windows` or `platform = \"windows\"` in TOML)\n- When `platform=windows`, the Linux `timeout`/`sh -c` command wrapper is skipped and the SSH library's native timeout is used instead\n- All tools (`ssh_execute`, `ssh_tail`, `ssh_monitor`, `ssh_deploy`, `ssh_execute_sudo`, `ssh_group_execute`) are platform-aware\n\n### v3.1.2 - Windows Compatibility Fix (February 9, 2026)\n\n- **🪟 Windows support**: Fixed crash on Windows where `process.env.HOME` is undefined ([#8](https://github.com/bvisible/mcp-ssh-manager/issues/8))\n- Now uses `os.homedir()` for cross-platform compatibility (Linux, macOS, Windows)\n\n### v3.1.0 - Tool Activation System (November 15, 2025)\n\n### 🎯 Context Usage Optimization\n- **92% context reduction**: Enable only the tools you need (minimal mode: 5 tools vs all 37)\n- **Tool management CLI**: `ssh-manager tools list/configure/enable/disable`\n- **6 tool groups**: Core, Sessions, Monitoring, Backup, Database, Advanced\n- **Auto-approval export**: Generate Claude Code auto-approval configs\n\n### v3.0.0 - Enterprise DevOps Platform (October 1, 2025)\n\nThis release adds **12 new MCP tools** transforming SSH Manager into a comprehensive DevOps automation platform:\n\n### 💾 Backup & Restore System (4 tools)\n- **Automated backups** for MySQL, PostgreSQL, MongoDB, and file systems\n- **Smart scheduling** with cron integration and retention policies\n- **One-click restore** with cross-database support\n- **Metadata tracking** for audit and compliance\n\n### 🏥 Health & Monitoring (4 tools)\n- **Real-time health checks** with CPU, RAM, Disk, and Network metrics\n- **Service monitoring** for nginx, mysql, docker, and custom services\n- **Process management** with CPU/RAM sorting and kill capabilities\n- **Alert thresholds** with configurable notifications\n\n### 🗄️ Database Management (4 tools)\n- **Safe database dumps** with compression and selective exports\n- **Database imports** with automatic decompression\n- **Schema exploration** listing databases, tables, and collections\n- **Secure queries** with SQL injection prevention (SELECT-only)\n\n**📊 Total: 37 MCP Tools** | **🔧 ~4,100 Lines of Code Added** | **✅ Production Ready**\n\n[Read Full Changelog →](CHANGELOG.md#300---2025-10-01)\n\n</details>\n\n---\n\n## 📑 Table of Contents\n\n- [Features](#-features)\n- [Tool Management](#-tool-management--context-optimization)\n- [Prerequisites](#-prerequisites)\n- [Quick Start - Claude Code](#-quick-start---claude-code)\n- [Quick Start - OpenAI Codex](#-quick-start---openai-codex)\n- [Available MCP Tools](#-available-mcp-tools)\n- [Configuration](#-configuration)\n- [Usage Examples](#-usage-examples)\n- [Security](#-security-best-practices)\n- [Troubleshooting](#-troubleshooting)\n- [Known Limitations](#known-limitations)\n- [Contributing](#-contributing)\n- [License](#-license)\n\n---\n\n## 🌟 Features\n\n### Core Features\n- **🔗 Multiple SSH Connections** - Manage unlimited SSH servers from a single interface\n- **🔐 Secure Authentication** - Support for password, SSH key, and ssh-agent authentication (including passphrase-protected keys)\n- **🔀 ProxyJump / Bastion Host** - Connect to servers behind jump hosts with chained multi-hop support\n- **🔌 ProxyCommand / Custom Proxy** - Connect through SOCKS5 proxies or custom proxy commands (ncat, ssh -W, etc.)\n- **📁 File Operations** - Upload and download files between local and remote systems\n- **⚡ Command Execution** - Run commands on remote servers with working directory support\n- **📂 Default Directories** - Set default working directories per server for convenience\n- **🎯 Easy Configuration** - Simple `.env` file setup with guided configuration tool\n\n### Enterprise DevOps Features (v3.0) 🎉\n- **💾 Backup & Restore** - Automated backups for MySQL, PostgreSQL, MongoDB, and files\n- **🏥 Health Monitoring** - Real-time server health checks (CPU, RAM, Disk, Services)\n- **🗄️ Database Management** - Safe database operations with SQL injection prevention\n- **📊 Process Management** - Monitor and control server processes\n- **⚠️ Smart Alerts** - Configurable health thresholds and notifications\n\n### v2.0 Features\n- **🚀 Bash CLI** - Lightning-fast pure Bash CLI for server management\n- **📊 Advanced Logging** - Comprehensive logging system with levels and history\n- **🔄 Rsync Integration** - Bidirectional file sync with rsync support\n- **💻 Persistent Sessions** - Maintain shell context across multiple commands\n- **👥 Server Groups** - Execute commands on multiple servers simultaneously\n- **🔧 SSH Tunnels** - Local/remote port forwarding and SOCKS proxy support\n- **📈 System Monitoring** - Real-time monitoring of CPU, memory, disk, and network\n- **🏷️ Server Aliases** - Use short aliases instead of full server names\n- **🚀 Smart Deployment** - Automated file deployment with permission handling\n- **🔑 Sudo Support** - Execute commands with sudo privileges securely\n- **📝 OpenAI Codex Support** - Compatible with OpenAI Codex via TOML configuration\n\n---\n\n## ⚙️ Tool Management & Context Optimization\n\n**NEW in v3.1**: Reduce Claude Code context usage by 92% with tool activation management!\n\nMCP SSH Manager includes **37 tools** organized into **6 groups**. By default, all tools are enabled, but you can optimize for your specific workflow:\n\n### Quick Setup\n\n```bash\n# Interactive configuration wizard\nssh-manager tools configure\n\n# View current configuration\nssh-manager tools list\n\n# Enable/disable specific groups\nssh-manager tools enable monitoring\nssh-manager tools disable backup\n```\n\n### Configuration Modes\n\n| Mode | Tools | Context Usage | Best For |\n|------|-------|---------------|----------|\n| **All** (default) | 37 tools | ~43.5k tokens | Full feature set, most users |\n| **Minimal** | 5 tools | ~3.5k tokens | Basic SSH operations only |\n| **Custom** | 5-37 tools | Varies | Tailored to your workflow |\n\n### Tool Groups\n\n- **Core** (5 tools) - Always enabled: list, execute, upload, download, sync\n- **Sessions** (4 tools) - Persistent SSH sessions\n- **Monitoring** (6 tools) - Health checks, service status, process management\n- **Backup** (4 tools) - Database and file backups\n- **Database** (4 tools) - MySQL, PostgreSQL, MongoDB operations\n- **Advanced** (14 tools) - Deployment, sudo, tunnels, groups, aliases, etc.\n\n### Benefits\n\n- **92% context reduction** in minimal mode (~40k tokens saved)\n- **Fewer approval prompts** in Claude Code\n- **Faster loading** and cleaner interface\n- **Auto-approval configuration** export for Claude Code\n\n📖 [**Complete Tool Management Guide →**](docs/TOOL_MANAGEMENT.md)\n\n---\n\n## 📋 Prerequisites\n\n- Node.js (v18 or higher)\n- npm (comes with Node.js)\n- **Platforms**: Linux, macOS, Windows\n- **For Claude Code**: Claude Code CLI installed\n- **For OpenAI Codex**: Codex CLI configured\n- Bash 4.0+ (for CLI management tools)\n- rsync (for file synchronization)\n- sshpass (optional, for rsync with password authentication)\n  - macOS: `brew install hudochenkov/sshpass/sshpass`\n  - Linux: `apt-get install sshpass`\n\n## 🚀 Quick Start - Claude Code\n\n### 1. Install MCP SSH Manager\n\n**Option A: Install from npm (recommended)**\n\n```bash\n# Install globally from npm\nnpm install -g mcp-ssh-manager\n\n# Or install locally\nnpx mcp-ssh-manager\n```\n\n**Option B: Install from source**\n\n```bash\n# Clone and install\ngit clone https://github.com/bvisible/mcp-ssh-manager.git\ncd mcp-ssh-manager\nnpm install\n\n# Install the Bash CLI\ncd cli && ./install.sh\n\n# Configure your first server\nssh-manager server add\n```\n\n### 2. Install to Claude Code\n\n```bash\n# For personal use (current user only)\nclaude mcp add ssh-manager node /path/to/mcp-ssh-manager/src/index.js\n\n# For team sharing (creates .mcp.json in project)\nclaude mcp add ssh-manager --scope project node /path/to/mcp-ssh-manager/src/index.js\n\n# For all your projects\nclaude mcp add ssh-manager --scope user node /path/to/mcp-ssh-manager/src/index.js\n```\n\n### 3. Configure Auto-Approval (Optional but Recommended)\n\nTo avoid being prompted for approval on every SSH command, add auto-approve configuration:\n\nEdit `~/.config/claude-code/claude_code_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"ssh-manager\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/to/mcp-ssh-manager/src/index.js\"],\n      \"autoApprove\": [\n        \"mcp__ssh-manager__ssh_execute\",\n        \"mcp__ssh-manager__ssh_list_servers\",\n        \"mcp__ssh-manager__ssh_upload\",\n        \"mcp__ssh-manager__ssh_download\",\n        \"mcp__ssh-manager__ssh_sync\",\n        \"mcp__ssh-manager__ssh_alias\"\n      ]\n    }\n  }\n}\n```\n\n**Important**: Restart Claude Code after making this change.\n\nFor full auto-approval of all SSH tools, see the complete list in [examples/claude-code-config.example.json](examples/claude-code-config.example.json).\n\n### 3.5. Security Modes (Optional, v3.5.0+)\n\n`autoApprove` is all-or-nothing per tool: once `ssh_execute` is approved, anything goes. If you want a **second layer** that filters what the MCP server actually accepts to run — useful when sharing the MCP with a third-party agent, a CI bot, or a client's server — declare a per-server **security mode**.\n\n```bash\n# In your .env — three optional fields. Omit them all to keep v3.4.x behavior exactly.\nSSH_SERVER_CLIENT_PROD_HOST=client-prod.example.com\nSSH_SERVER_CLIENT_PROD_USER=consultant\nSSH_SERVER_CLIENT_PROD_KEYPATH=~/.ssh/consultant_ed25519\n\nSSH_SERVER_CLIENT_PROD_MODE=readonly                          # unrestricted | readonly | restricted\nSSH_SERVER_CLIENT_PROD_AUDIT_LOG=~/.ssh-manager/audit.jsonl   # opt-in JSONL audit trail\n# For mode=restricted, provide an allowlist of regex (DENY wins over ALLOW):\n# SSH_SERVER_CI_ALLOW_PATTERNS=\"^docker (ps|logs);^kubectl get \"\n```\n\n- **`unrestricted`** (default, no field needed) — identical to pre-v3.5.0 behavior. Zero overhead.\n- **`readonly`** — blocks `ssh_upload`, `ssh_deploy`, `ssh_sync`, `ssh_execute_sudo`, backup/db write tools, and built-in destructive commands (`rm`, `mv`, `sudo`, `systemctl restart`, redirects outside `/tmp`, `curl | sh`, …).\n- **`restricted`** — every `ssh_execute` command must match at least one `ALLOW_PATTERNS` regex AND no `DENY_PATTERNS` regex.\n\nExisting configs are unaffected — no field is mandatory, no behavior changes unless you opt in. See **[docs/SECURITY_MODES.md](docs/SECURITY_MODES.md)** for the full reference, recipes, and limitations.\n\n### 4. Start Using!\n\nIn Claude Code, you can now:\n\n```\n\"List all my SSH servers\"\n\"Execute 'ls -la' on production server\"  # Uses default directory if set\n\"Run 'docker ps' on staging\"\n\"Upload config.json to production:/etc/app/config.json\"\n\"Download logs from staging:/var/log/app.log\"\n```\n\n**With Default Directories:**\nIf you set `/var/www/html` as default for production, these commands are equivalent:\n- `\"Run 'ls' on production\"` → executes in `/var/www/html`\n- `\"Run 'ls' on production in /tmp\"` → executes in `/tmp` (overrides default)\n\n---\n\n## 🚀 Quick Start - OpenAI Codex\n\n### 1. Install MCP SSH Manager\n\nSame installation as Claude Code (see above), then configure for Codex:\n\n```bash\n# Set up Codex integration\nssh-manager codex setup\n\n# Migrate existing servers to TOML format (if you have .env servers)\nssh-manager codex migrate\n\n# Test the integration\nssh-manager codex test\n```\n\n### 2. Manual Configuration (Optional)\n\nIf you prefer manual setup, add to `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.ssh-manager]\ncommand = \"node\"\nargs = [\"/absolute/path/to/mcp-ssh-manager/src/index.js\"]\nenv = { SSH_CONFIG_PATH = \"/Users/you/.codex/ssh-config.toml\" }\nstartup_timeout_ms = 20000\n```\n\n### 3. Configure Servers in TOML Format\n\nCreate or edit `~/.codex/ssh-config.toml`:\n\n```toml\n[ssh_servers.production]\nhost = \"prod.example.com\"\nuser = \"admin\"\npassword = \"secure_password\"  # or use key_path\nkey_path = \"~/.ssh/id_rsa\"   # for SSH key auth (recommended)\npassphrase = \"key_passphrase\" # optional, for passphrase-protected keys\nport = 22\ndefault_dir = \"/var/www\"\ngroup = \"production\"          # optional, free-form label for grouping/import-export\ndescription = \"Production server\"\n\n[ssh_servers.staging]\nhost = \"staging.example.com\"\nuser = \"deploy\"\nkey_path = \"~/.ssh/staging_key\"\nport = 2222\ndefault_dir = \"/home/deploy/app\"\n\n[ssh_servers.winhost]\nhost = \"192.168.1.90\"\nuser = \"svc-ssh\"\nkey_path = \"~/.ssh/winhost_key\"\nport = 2222\nplatform = \"windows\"\ndescription = \"Windows host via OpenSSH\"\n\n[ssh_servers.bastion]\nhost = \"bastion.example.com\"\nuser = \"jumpuser\"\nkey_path = \"~/.ssh/bastion_key\"\n\n[ssh_servers.internal]\nhost = \"10.0.0.5\"\nuser = \"admin\"\nkey_path = \"~/.ssh/internal_key\"\nproxy_jump = \"bastion\"\ndescription = \"Private server behind bastion\"\n```\n\n💡 **See [examples/codex-ssh-config.example.toml](examples/codex-ssh-config.example.toml) for more complete examples!**\n\n### 4. Start Using in Codex!\n\nIn OpenAI Codex, you can now:\n\n```\n\"List my SSH servers\"\n\"Execute 'docker ps' on production\"\n\"Upload file.txt to staging:/tmp/\"\n\"Monitor CPU usage on all servers\"\n\"Download production:/var/log/app.log to ./logs/\"\n```\n\n### Converting Between Formats\n\nSwitch easily between Claude Code (.env) and Codex (TOML):\n\n```bash\n# Convert .env to TOML (for Codex)\nssh-manager codex convert to-toml\n\n# Convert TOML back to .env (for Claude Code)\nssh-manager codex convert to-env\n```\n\nBoth formats can coexist! The system supports both simultaneously.\n\n---\n\n## 🛠️ Available MCP Tools\n\n### Core Tools\n\n#### `ssh_list_servers`\nLists all configured SSH servers with their details.\n\n#### `ssh_execute`\nExecute commands on remote servers.\n- Parameters: `server` (name), `command`, `cwd` (optional working directory)\n- **Note**: If no `cwd` is provided, uses the server's default directory if configured\n\n#### `ssh_upload`\nUpload files to remote servers.\n- Parameters: `server`, `local_path`, `remote_path`\n\n#### `ssh_download`\nDownload files from remote servers.\n- Parameters: `server`, `remote_path`, `local_path`\n\n### Backup & Restore Tools (v2.1+) 🔄\n\n#### `ssh_backup_create`\nCreate backup of database or files on remote server.\n- Types: MySQL, PostgreSQL, MongoDB, Files\n- Parameters: `server`, `type`, `name`, `database`, `paths`, `retention`\n- Automatic compression and metadata tracking\n- See [Backup Guide](docs/BACKUP_GUIDE.md) for detailed usage\n\n#### `ssh_backup_list`\nList all available backups on remote server.\n- Parameters: `server`, `type` (optional filter)\n- Returns backup details with size, date, and retention info\n\n#### `ssh_backup_restore`\nRestore from a previous backup.\n- Parameters: `server`, `backupId`, `database`, `targetPath`\n- Supports cross-database restoration\n\n#### `ssh_backup_schedule`\nSchedule automatic backups using cron.\n- Parameters: `server`, `schedule` (cron format), `type`, `name`\n- Automatic cleanup based on retention policy\n\n### Health & Monitoring Tools (v2.2+) 🏥\n\n#### `ssh_health_check`\nPerform comprehensive health check on remote server.\n- Checks: CPU, Memory, Disk, Network, Uptime, Load average\n- Returns overall health status (healthy/warning/critical)\n- Optional detailed mode for extended metrics\n\n#### `ssh_service_status`\nCheck status of services (nginx, mysql, docker, etc.).\n- Parameters: `server`, `services` (array)\n- Returns running/stopped status for each service\n- Works with both systemd and sysv init systems\n\n#### `ssh_process_manager`\nList, monitor, or kill processes on remote server.\n- Actions: list (top processes), kill (terminate), info (details)\n- Sort by CPU or memory usage\n- Filter processes by name\n\n#### `ssh_alert_setup`\nConfigure health monitoring alerts and thresholds.\n- Actions: set (configure), get (view), check (test thresholds)\n- Configurable CPU, memory, and disk thresholds\n- Automatic alert triggering when thresholds exceeded\n\n### Database Management Tools (v2.3+) 🗄️\n\n#### `ssh_db_dump`\nCreate database dump/backup on remote server.\n- Supports: MySQL, PostgreSQL, MongoDB\n- Parameters: `server`, `type`, `database`, `outputFile`, `dbUser`, `dbPassword`, `dbHost`, `dbPort`\n- Optional: `compress` (gzip), `tables` (specific tables only)\n- Returns dump size and location\n\n#### `ssh_db_import`\nImport SQL dump or restore database on remote server.\n- Supports: MySQL, PostgreSQL, MongoDB\n- Parameters: `server`, `type`, `database`, `inputFile`, `dbUser`, `dbPassword`, `dbHost`, `dbPort`\n- Handles compressed (.gz) files automatically\n- Optional: `drop` (drop database before restore for MongoDB)\n\n#### `ssh_db_list`\nList databases or tables on remote server.\n- Parameters: `server`, `type`, `database` (optional), `dbUser`, `dbPassword`, `dbHost`, `dbPort`\n- Without database: lists all databases (filters system DBs)\n- With database: lists all tables/collections\n- Returns structured list with count\n\n#### `ssh_db_query`\nExecute read-only SQL queries on remote database.\n- Parameters: `server`, `type`, `database`, `query`, `dbUser`, `dbPassword`, `dbHost`, `dbPort`\n- **Security**: Only SELECT queries allowed for safety\n- MongoDB: Use `collection` parameter for find queries\n- Returns query results with row count\n\n### Deployment Tools (v1.2+)\n\n#### `ssh_deploy` 🚀\nDeploy files with automatic permission and backup handling.\n- Parameters: `server`, `files` (array), `options` (owner, permissions, backup, restart)\n- Automatically handles permission issues and creates backups\n\n#### `ssh_execute_sudo` 🔐\nExecute commands with sudo privileges.\n- Parameters: `server`, `command`, `password` (optional), `cwd` (optional)\n- Securely handles sudo password without exposing in logs\n\n### Server Management\n\n#### `ssh_alias` 🏷️\nManage server aliases for easier access.\n- Parameters: `action` (add/remove/list), `alias`, `server`\n- Example: Create alias \"prod\" for \"production\" server\n\n#### `ssh_command_alias` 📝\nManage command aliases for frequently used commands.\n- Parameters: `action` (add/remove/list/suggest), `alias`, `command`\n- Aliases loaded from active profile\n- Example: Custom aliases for your project\n\n#### `ssh_hooks` 🎣\nManage automation hooks for SSH operations.\n- Parameters: `action` (list/enable/disable/status), `hook`\n- Hooks loaded from active profile\n- Example: Project-specific validation and automation\n\n#### `ssh_profile` 📚\nManage configuration profiles for different project types.\n- Parameters: `action` (list/switch/current), `profile`\n- Available profiles: default, frappe, docker, nodejs\n- Example: Switch between different project configurations\n\n## 🔧 Configuration\n\n### Profiles\n\nSSH Manager uses profiles to configure aliases and hooks for different project types:\n\n1. **Set active profile**: \n   - Environment variable: `export SSH_MANAGER_PROFILE=frappe`\n   - Configuration file: Create `.ssh-manager-profile` with profile name\n   - Default: Uses `default` profile if not specified\n\n2. **Available profiles**:\n   - `default` - Basic SSH operations\n   - `frappe` - Frappe/ERPNext specific\n   - `docker` - Docker container management\n   - `nodejs` - Node.js applications\n   - Create custom profiles in `profiles/` directory\n\n### Environment Variables\n\nServers are configured in the `.env` file with this pattern:\n\n```env\n# Server configuration pattern\nSSH_SERVER_[NAME]_HOST=hostname_or_ip\nSSH_SERVER_[NAME]_USER=username\nSSH_SERVER_[NAME]_PASSWORD=password  # For password auth\nSSH_SERVER_[NAME]_KEYPATH=~/.ssh/key  # For SSH key auth\nSSH_SERVER_[NAME]_PASSPHRASE=key_passphrase  # Optional, for passphrase-protected keys\nSSH_SERVER_[NAME]_PORT=22  # Optional, defaults to 22\nSSH_SERVER_[NAME]_DEFAULT_DIR=/path/to/dir  # Optional, default working directory\nSSH_SERVER_[NAME]_DESCRIPTION=Description  # Optional\nSSH_SERVER_[NAME]_GROUP=production  # Optional, free-form label for grouping/import-export\nSSH_SERVER_[NAME]_PLATFORM=windows  # Optional: \"linux\" (default) or \"windows\"\nSSH_SERVER_[NAME]_PROXYJUMP=bastion  # Optional: name of another server to use as jump host\nSSH_SERVER_[NAME]_PROXYCOMMAND=command  # Optional: custom proxy command (ncat, ssh -W, etc.)\nSSH_SERVER_[NAME]_FORWARD_AGENT=true  # Optional: forward local ssh-agent to remote (needs SSH_AUTH_SOCK; security risk — see SSH Agent section)\n\n# Example: Linux server\nSSH_SERVER_PRODUCTION_HOST=prod.example.com\nSSH_SERVER_PRODUCTION_USER=admin\nSSH_SERVER_PRODUCTION_PASSWORD=secure_password\nSSH_SERVER_PRODUCTION_PORT=22\nSSH_SERVER_PRODUCTION_DEFAULT_DIR=/var/www/html\nSSH_SERVER_PRODUCTION_DESCRIPTION=Production Server\nSSH_SERVER_PRODUCTION_SUDO_PASSWORD=secure_sudo_pass  # Optional, for automated deployments\n\n# Example: Windows server (OpenSSH for Windows)\nSSH_SERVER_WINHOST_HOST=192.168.1.90\nSSH_SERVER_WINHOST_USER=svc-ssh\nSSH_SERVER_WINHOST_KEYPATH=~/.ssh/winhost_key\nSSH_SERVER_WINHOST_PORT=2222\nSSH_SERVER_WINHOST_PLATFORM=windows\nSSH_SERVER_WINHOST_DESCRIPTION=Windows host via OpenSSH\n\n# Example: Server behind a bastion/jump host\nSSH_SERVER_BASTION_HOST=bastion.example.com\nSSH_SERVER_BASTION_USER=jumpuser\nSSH_SERVER_BASTION_KEYPATH=~/.ssh/bastion_key\n\nSSH_SERVER_INTERNAL_HOST=10.0.0.5\nSSH_SERVER_INTERNAL_USER=admin\nSSH_SERVER_INTERNAL_KEYPATH=~/.ssh/internal_key\nSSH_SERVER_INTERNAL_PROXYJUMP=bastion\nSSH_SERVER_INTERNAL_DESCRIPTION=Private server behind bastion\n```\n\n### Server Management Tool\n\nThe Python management tool (`tools/server_manager.py`) provides:\n\n1. **List servers** - View all configured servers\n2. **Add server** - Interactive server configuration\n3. **Test connection** - Verify server connectivity\n4. **Remove server** - Delete server configuration\n5. **Update Claude Code** - Configure MCP in Claude Code\n6. **Install dependencies** - Setup required packages\n\n## 📁 Project Structure\n\n```\nmcp-ssh-manager/\n├── src/\n│   ├── index.js              # Main MCP server (37 tools)\n│   ├── ssh-manager.js        # SSH connection handling\n│   ├── config-loader.js      # .env & TOML config loading\n│   ├── session-manager.js    # Persistent SSH sessions\n│   ├── backup-manager.js     # Backup & restore\n│   ├── health-monitor.js     # Health checks & alerts\n│   ├── database-manager.js   # Database operations\n│   ├── tunnel-manager.js     # SSH tunnel management\n│   ├── server-groups.js      # Group operations\n│   └── ...\n├── cli/\n│   ├── ssh-manager           # Bash CLI entrypoint\n│   ├── commands/              # CLI command modules\n│   └── lib/                   # CLI libraries\n├── profiles/                  # Configuration profiles (frappe, docker, nodejs...)\n├── examples/                  # Example configs\n├── docs/                      # Documentation\n└── package.json\n```\n\n## 🧪 Testing\n\n### Test Server Connection\n\n```bash\npython tools/test-connection.py production\n```\n\n### Verify MCP Installation\n\n```bash\nclaude mcp list\n```\n\n### Check Server Status in Claude Code\n\n```\n/mcp\n```\n\n## 🔒 Security Best Practices\n\n1. **Never commit `.env` files** - Always use `.env.example` as template\n2. **Use SSH keys when possible** - More secure than passwords\n3. **Limit server access** - Use minimal required permissions\n4. **Rotate credentials** - Update passwords and keys regularly\n\n### 🔑 Passphrase-Protected SSH Keys\n\nMCP SSH Manager supports passphrase-protected SSH keys in two ways:\n\n**Option 1: SSH Agent (recommended)**\n\nIf your SSH key is loaded into `ssh-agent`, MCP SSH Manager will use it automatically — no configuration changes needed:\n\n```bash\n# Add your key to the agent (enter passphrase once)\nssh-add ~/.ssh/your_key\n\n# Verify the key is loaded\nssh-add -l\n```\n\nThe server detects the `SSH_AUTH_SOCK` environment variable and connects to the running agent. This is the same mechanism that regular `ssh` uses for GUI passphrase prompts.\n\n**Option 2: Passphrase in configuration**\n\nYou can store the passphrase directly in the server config:\n\n`.env` format:\n```env\nSSH_SERVER_MYSERVER_KEYPATH=~/.ssh/id_rsa\nSSH_SERVER_MYSERVER_PASSPHRASE=\"your_passphrase\"\n```\n\nTOML format:\n```toml\n[ssh_servers.myserver]\nkey_path = \"~/.ssh/id_rsa\"\npassphrase = \"your_passphrase\"\n```\n\n> **Note:** SSH Agent is preferred over storing passphrases in config files for better security.\n\n### 🔗 SSH Agent Forwarding\n\nEnable per-server agent forwarding (the equivalent of OpenSSH's `ForwardAgent yes`) so processes on the remote host can authenticate to *other* SSH hosts using the keys in your **local** `ssh-agent` — e.g. `git clone` over SSH on a remote server using your local GitHub key, without copying any private key to the server.\n\nIt is **opt-in per server** and defaults to `false`. It requires a running local agent (`SSH_AUTH_SOCK` present); when the agent is unavailable the flag is simply ignored.\n\n`.env` format:\n```env\nSSH_SERVER_MYSERVER_FORWARD_AGENT=true\n```\n\nTOML format:\n```toml\n[ssh_servers.myserver]\nforward_agent = true\n```\n\n> ⚠️ **Security warning:** agent forwarding lets any process that can read the forwarded agent socket on the remote host — including anyone with **root** there — use your loaded keys to impersonate you against other hosts *for the life of the connection*. Only enable it for servers you trust, mirroring the same caution `ssh_config(5)` advises for `ForwardAgent`.\n\n## 📚 Advanced Usage\n\n### ProxyJump / Bastion Host\n\nConnect to servers behind a bastion or jump host. The connection is tunneled through the jump server transparently — all tools (execute, upload, download, sync) work as usual.\n\n```env\n# Define the bastion server\nSSH_SERVER_BASTION_HOST=bastion.example.com\nSSH_SERVER_BASTION_USER=jumpuser\nSSH_SERVER_BASTION_KEYPATH=~/.ssh/bastion_key\n\n# Point the target server to the bastion\nSSH_SERVER_PRIVATE_HOST=10.0.0.5\nSSH_SERVER_PRIVATE_USER=admin\nSSH_SERVER_PRIVATE_PROXYJUMP=bastion\n```\n\nOr in TOML:\n```toml\n[ssh_servers.bastion]\nhost = \"bastion.example.com\"\nuser = \"jumpuser\"\nkey_path = \"~/.ssh/bastion_key\"\n\n[ssh_servers.private]\nhost = \"10.0.0.5\"\nuser = \"admin\"\nproxy_jump = \"bastion\"\n```\n\n**Chained jumps** are supported: if `bastion` itself has a `proxy_jump`, the chain is followed recursively. Circular references are detected and rejected.\n\n### ProxyCommand / Custom Proxy\n\nConnect through SOCKS5 proxies or custom proxy commands. The proxy command executes locally and forwards traffic to the remote host.\n\n```env\n# SOCKS5 proxy via ncat\nSSH_SERVER_SOCKS_HOST=target.example.com\nSSH_SERVER_SOCKS_USER=admin\nSSH_SERVER_SOCKS_PROXYCOMMAND=\"ncat --proxy 127.0.0.1:1080 --proxy-type socks5 %h %p\"\n\n# Windows SSH proxy command\nSSH_SERVER_WINPROXY_HOST=internal.example.com\nSSH_SERVER_WINPROXY_USER=admin\nSSH_SERVER_WINPROXY_PROXYCOMMAND=\"C:\\Windows\\System32\\OpenSSH\\ssh.exe -W %h:%p user@jump-host\"\n```\n\nOr in TOML:\n```toml\n[ssh_servers.socks]\nhost = \"target.example.com\"\nuser = \"admin\"\nproxy_command = \"ncat --proxy 127.0.0.1:1080 --proxy-type socks5 %h %p\"\n\n[ssh_servers.winproxy]\nhost = \"internal.example.com\"\nuser = \"admin\"\nproxy_command = \"C:\\\\Windows\\\\System32\\\\OpenSSH\\\\ssh.exe -W %h:%p user@jump-host\"\n```\n\nThe proxy command must be a valid command that reads from stdin and writes to stdout, accepting `%h` and `%p` placeholders for host and port.\n\n### Server Groups\n\nTag a server with `group` and it becomes part of that group — no extra file to maintain. The label is free-form and travels with the server definition, so it survives an export to (or import from) another tool.\n\n```env\nSSH_SERVER_WEB1_HOST=10.0.0.1\nSSH_SERVER_WEB1_USER=deploy\nSSH_SERVER_WEB1_GROUP=production\n\nSSH_SERVER_WEB2_HOST=10.0.0.2\nSSH_SERVER_WEB2_USER=deploy\nSSH_SERVER_WEB2_GROUP=production\n```\n\nOr in TOML:\n```toml\n[ssh_servers.web1]\nhost = \"10.0.0.1\"\nuser = \"deploy\"\ngroup = \"production\"\n```\n\nBoth servers are then reachable as a group:\n\n```\nRun \"uptime\" on the production group     → ssh_execute_group\nList my server groups                    → ssh_group_manage (action: list)\n```\n\n`ssh_list_servers` also reports the group of each server, so you can see membership without opening the config.\n\n**How it combines with `ssh_group_manage`:** groups you create with `ssh_group_manage` live in `.server-groups.json` and carry execution settings (strategy, delay, stop-on-error). Groups implied by the `group` field carry membership only. When a name exists on both sides, **membership is the union** — the stored list plus every server tagged with that name — and the stored execution settings apply. Group names are case-insensitive.\n\nA group that exists only through the `group` field is read-only for `ssh_group_manage`: to change who belongs to it, edit the servers' `group` in your `.env`/TOML. Creating a group of the same name with `ssh_group_manage` is still allowed and simply adds stored members and settings on top.\n\n### Documentation\n- [DEPLOYMENT_GUIDE.md](docs/DEPLOYMENT_GUIDE.md) - Deployment strategies and permission handling\n- [ALIASES_AND_HOOKS.md](docs/ALIASES_AND_HOOKS.md) - Command aliases and automation hooks\n- Real-world examples and best practices\n\n## 🐛 Troubleshooting\n\n### Claude Code Crashes / Interruptions\n\n**Symptoms:**\n- Claude shows \"Interrupted: What should Claude do instead?\"\n- MCP tools execute but Claude stops working\n- Commands succeed but Claude freezes\n\n**Solution:** v3.1.1 includes automatic fixes:\n- ✅ Output auto-truncated to prevent context overflow\n- ✅ Timeout increased to 2 minutes (default), max 5 minutes\n- ✅ Standardized error responses\n\n**Performance Tuning** (add to `.env`):\n```bash\n# Reduce output size (default: 10000 characters)\nMCP_SSH_MAX_OUTPUT_LENGTH=5000\n\n# Increase timeout for slow commands (default: 120000ms)\nMCP_SSH_DEFAULT_TIMEOUT=180000\n\n# Use compact JSON to save tokens (default: false)\nMCP_SSH_COMPACT_JSON=true\n```\n\n**For large outputs:**\n```bash\n# Instead of: cat huge-log.txt\n# Use: tail -n 100 huge-log.txt\n# Or: grep ERROR huge-log.txt | tail -n 50\n```\n\nSee [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for complete guide.\n\n### MCP Tools Not Available\n\n1. Ensure MCP is installed: `claude mcp list`\n2. Restart Claude Code after installation\n3. Check server logs for errors\n\n### Connection Failed\n\n1. Test connection: `ssh-manager server test [server_name]`\n2. Verify network connectivity\n3. Check firewall rules\n4. Ensure SSH service is running on remote server\n\n### Permission Denied\n\n1. Verify username and password/key\n2. Check SSH key permissions: `chmod 600 ~/.ssh/your_key`\n3. Ensure user has necessary permissions on remote server\n\n## 📚 Usage Examples\n\n### Backup & Restore\n\n```\n\"Backup production MySQL database before deployment\"\n\"List all backups on production server\"\n\"Restore backup from yesterday\"\n\"Schedule daily database backup at 2 AM\"\n\"Backup website files excluding cache and logs\"\n```\n\nFor detailed backup examples, see [examples/backup-workflow.md](examples/backup-workflow.md) and [docs/BACKUP_GUIDE.md](docs/BACKUP_GUIDE.md).\n\n### Using the Bash CLI\n\n```bash\n# Basic server management\nssh-manager server list\nssh-manager server add\nssh-manager ssh prod1\n\n# File synchronization\nssh-manager sync push prod1 ./app /var/www/\nssh-manager sync pull prod1 /var/log/app.log ./\n\n# SSH tunnels\nssh-manager tunnel create prod1 local 3307:localhost:3306\nssh-manager tunnel list\n\n# Execute commands\nssh-manager exec prod1 \"docker ps\"\n```\n\n### Using in Claude Code or OpenAI Codex\n\nOnce installed, simply ask your AI assistant:\n\n**Claude Code examples:**\n- \"List my SSH servers\"\n- \"Execute 'df -h' on production server\"\n- \"Upload this file to staging:/var/www/\"\n- \"Create an SSH tunnel to access remote MySQL\"\n- \"Monitor CPU usage on all servers\"\n- \"Start a persistent session on prod1\"\n\n**OpenAI Codex examples:**\n- \"Show my SSH servers\"\n- \"Run df -h on production\"\n- \"Upload file.txt to staging:/tmp/\"\n- \"Check CPU usage on all servers\"\n\nBoth AI assistants support the same MCP tools! 🚀\n\n---\n\n## 🤝 Contributing\n\nWe welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n### Development Setup\n\n1. Fork the repository\n2. Clone and install dependencies\n3. **Setup pre-commit hooks** for code quality:\n   ```bash\n   ./scripts/setup-hooks.sh\n   ```\n4. Create your feature branch\n5. Make your changes (hooks will validate on commit)\n6. Push to your branch\n7. Open a Pull Request\n\n### Code Quality\n\nThis project uses automated quality checks:\n- **ESLint** for JavaScript linting\n- **Black** for Python formatting\n- **Flake8** for Python linting\n- **Prettier** for code formatting\n- **Pre-commit hooks** for automated validation\n- **Secret detection** to prevent credential leaks\n\nRun validation manually: `./scripts/validate.sh`\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🙏 Acknowledgments\n\n- Built for [Claude Code](https://claude.ai/code)\n- Uses the [Model Context Protocol](https://modelcontextprotocol.io)\n- SSH handling via [node-ssh](https://www.npmjs.com/package/node-ssh)\n- Server management with [Paramiko](https://www.paramiko.org)\n\n---\n\n## Known Limitations\n\n### Command Timeout\n- The timeout parameter for SSH commands is advisory only\n- Due to SSH2 library limitations, commands may continue running on the server even after timeout\n- On Linux/macOS hosts, a system `timeout` wrapper is used for reliable command termination\n- **Windows hosts**: Set `PLATFORM=windows` in your server config to skip the Linux `timeout`/`sh -c` wrapper (which is incompatible with Windows OpenSSH)\n\n### SSH Sync (rsync)\n- Password authentication requires `sshpass` to be installed\n- SSH key authentication is recommended for better security and reliability\n- **Windows MCP hosts**: pass native local paths such as `local:C:\\project` or `local:.\\project`; `ssh_sync` converts drive-letter and UNC paths to MSYS2 format before launching rsync. Prefer native paths, since Node checks them on disk using Windows path semantics — a path already written as `/c/...` or `//server/share` is passed through to rsync untouched rather than converted twice.\n- Large file transfers may take time and appear to hang - be patient\n\n### Connection Management\n- Connections are pooled and reused for performance\n- If a connection becomes stale, it will be automatically reconnected on next use\n- Force reconnection by using the `ssh_connection_status` tool with `reconnect` action\n\n## 📧 Support\n\nFor issues, questions, or suggestions:\n- Open an issue on [GitHub Issues](https://github.com/bvisible/mcp-ssh-manager/issues)\n- Check existing issues before creating new ones\n\n---\n\n<div align=\"center\">\n\nMade with ❤️ for the Claude Code community\n\n<br/><br/>\n\n<a href=\"https://glama.ai/mcp/servers/@bvisible/mcp-ssh-manager\">\n  <img width=\"380\" height=\"200\" src=\"https://glama.ai/mcp/servers/@bvisible/mcp-ssh-manager/badge\" alt=\"SSH Manager MCP server\" />\n</a>\n\n</div>\n",
  "bytes": 54399,
  "sha": "192f0f501cf2c67c7e0e013a96be5204b8c025b0941386875b003c3e68927195",
  "repo_slug": "bvisible/mcp-ssh-manager",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_bvisible_mcp_ssh_manager_d8198418/readme"
}