Remote SSH MCP
Exposes persistent, stateful remote Bash sessions to AI agents via SSH, enabling command execution with preserved working directory and environment.
README
Remote SSH MCP
English | 简体中文
A local MCP server that exposes persistent, stateful remote Bash sessions to AI agents. Reusing the same session ID preserves the working directory, environment variables, and shell side effects. Open a new session whenever a clean environment is required.
Remote SSH MCP uses the system OpenSSH client instead of reimplementing SSH.
Your existing ~/.ssh/config, known hosts, SSH agent, ProxyJump routes, and
hardware-key policies continue to work.
Why
Running ssh host "command" for every remote action repeatedly reconnects,
loses shell state, reproduces banners and environment probes, and wastes model
context. Remote SSH MCP keeps one remote shell alive behind a small, explicit
tool interface:
ssh_open(host) → session id
ssh_run(id, command) → same cwd and environment
ssh_peek(id) / ssh_interrupt(id) → observe or recover a stuck command
ssh_close(id) → release the shell and connection
Features
- Persistent remote Bash sessions with stable IDs
- Working-directory and environment persistence within each session
- Separate
stdoutandstderrin tool results - Non-blocking observation of long commands with a separate hard timeout
- Safe fail-closed behavior when shell recovery cannot be confirmed
- Head-and-tail output truncation with valid UTF-8 boundaries
- Exact SSH Host alias allowlist from
ssh_configand explicit configuration - Session limits, idle reaping, command auditing, and a minimal safety denylist
- MCP stdio support for both legacy and current protocol handshakes
- No password, private-key text, or arbitrary SSH option arguments
MCP tools
| Tool | Purpose |
|---|---|
ssh_open |
Open a clean persistent shell for an allowed SSH Host alias |
ssh_run |
Run a non-interactive command in an existing session |
ssh_peek |
Inspect status and the latest N output lines (default 50) |
ssh_interrupt |
Send Ctrl-C and wait for confirmed shell recovery |
ssh_list |
List sessions, cwd, state, idle countdown, and capacity |
ssh_close |
Clean up and close a session |
Requirements
- Node.js 20 or newer
- An OpenSSH client
- A remote host with Bash,
base64,stty,mkdir,cat, andrm - A configured SSH Host alias and a known host key
The server enforces BatchMode=yes and StrictHostKeyChecking=yes. Complete
first-connection host-key confirmation and authentication setup in a normal
terminal before using the MCP server. It never opens password or confirmation
prompts.
Install
git clone https://github.com/the-nine-nation/remote-ssh-mcp.git
cd remote-ssh-mcp
npm install
npm run build
npm test
Run the server directly:
node /absolute/path/to/remote-ssh-mcp/dist/index.js
Or, after installing it as a package, use the remote-ssh-mcp executable.
MCP host configuration
Most stdio MCP hosts accept a configuration shaped like this; the outer key may differ by host:
{
"mcpServers": {
"remote-ssh": {
"command": "node",
"args": [
"/absolute/path/to/remote-ssh-mcp/dist/index.js"
],
"env": {
"SSH_MCP_ALLOWED_HOSTS": "prod,staging"
}
}
}
}
SSH_MCP_ALLOWED_HOSTS adds explicit aliases to the allowlist. By default, the
server also discovers exact Host aliases from ~/.ssh/config and its
Include files. Patterns containing *, ?, or ! are ignored. Tool inputs
accept only safe aliases, not user@host, ports, or extra SSH options.
Configuration
The optional configuration file defaults to:
~/.config/remote-ssh-mcp/config.json
Example:
{
"allowedHosts": ["prod", "staging"],
"sshConfigPath": "~/.ssh/config",
"sshPath": "ssh",
"maxTimeoutSec": 1800,
"defaultWaitSec": 10,
"maxWaitSec": 30,
"openTimeoutSec": 20,
"idleTimeoutSec": 1800,
"interruptGraceSec": 5,
"maxSessions": 8,
"outputMaxBytes": 32768,
"outputHeadBytes": 4096,
"auditLogPath": "~/.local/state/remote-ssh-mcp/audit.jsonl"
}
Environment variables override file settings:
| Environment variable | Purpose |
|---|---|
SSH_MCP_CONFIG |
Configuration file path |
SSH_MCP_ALLOWED_HOSTS |
Comma-separated additional Host aliases |
SSH_MCP_SSH_CONFIG |
SSH config path |
SSH_MCP_SSH_PATH |
OpenSSH executable |
SSH_MCP_MAX_TIMEOUT_SEC |
Maximum explicitly requested command timeout |
SSH_MCP_DEFAULT_WAIT_SEC |
How long ssh_run waits before returning running |
SSH_MCP_MAX_WAIT_SEC |
Maximum permitted wait_sec |
SSH_MCP_OPEN_TIMEOUT_SEC |
Connection and handshake timeout |
SSH_MCP_IDLE_TIMEOUT_SEC |
Idle session lifetime |
SSH_MCP_INTERRUPT_GRACE_SEC |
Marker recovery grace period after Ctrl-C |
SSH_MCP_MAX_SESSIONS |
Maximum live sessions |
SSH_MCP_OUTPUT_MAX_BYTES |
Per-stream retained output limit |
SSH_MCP_OUTPUT_HEAD_BYTES |
Retained head bytes when truncating |
SSH_MCP_AUDIT_LOG |
JSONL audit-log path |
The audit log is created with mode 0600. It records the session, host,
result, duration, command length, command name, and SHA-256 hash. Full command
arguments are intentionally omitted to reduce the chance of logging secrets.
Execution semantics
- One session accepts only one foreground command at a time. Concurrent
ssh_runcalls returnbusyinstead of being queued. wait_seclimits only how long the MCP call waits. If it expires,ssh_runreturnsstatus: "running"while the remote command continues. Do not start the command again. Pollssh_peek, stop it withssh_interrupt, or open another session for concurrent work.- Commands have no automatic execution timeout by default. The model owns
their lifecycle. Only an explicitly supplied
timeout_seccreates a hard deadline that sends Ctrl-C. ssh_peekreturns the newest 50 lines from stdout and stderr by default. Passlines(maximum 1,000) when a different tail length is needed. Byte limits still apply, so a very long individual line remains bounded.- User-command stdin is
/dev/null. Do not runvim,top, interactive installers, or other TUI/input-driven programs. - A timeout sends Ctrl-C. If a complete protocol marker arrives during the grace period, the session returns to idle. Otherwise, the session is closed to prevent an unknown foreground process from corrupting the next command.
stdoutandstderrindependently retain their beginning and end. Responses always end on valid UTF-8 boundaries.- The built-in denylist blocks only a few obviously destructive patterns. It is not a complete policy engine.
- This project targets a trusted local developer environment. It is not a multi-tenant remote execution service.
- If the MCP host exits or its stdio/parent connection disappears, the server
closes every tracked SSH connection, including connections still opening.
Normal foreground processes end with their PTY; deliberately detached
processes such as
nohup,setsid, services, and containers may continue.
For example, start a docker pull with wait_sec: 10 and omit
timeout_sec. A running result means the original pull remains active—not
that it should be retried. Call ssh_peek with the same session ID until it
becomes idle, interrupt it explicitly, or open another session for parallel
work.
Development
npm run typecheck
npm test
npm run build
npm audit --omit=dev
The test suite covers MCP stdio discovery and calls, persistent cwd/environment state, stream separation, framing across arbitrary chunk boundaries, timeout fail-closed behavior, shell death, allowlist discovery, output truncation, and the safety denylist.
Security
Please do not report security vulnerabilities through public GitHub issues. Until a private security-advisory workflow is configured, contact the maintainer through the email listed on their GitHub profile.
Remote commands can have irreversible side effects even when the MCP transport works correctly. Review host permissions, use least-privilege accounts, and keep the allowlist narrow.
License
The wire protocol and detailed design decisions are documented in 远程SSH-MCP设计.md.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。