SSH MCP Server
Provides LLM clients with safe, persistent SSH access to remote machines through the Model Context Protocol. Maintains shell sessions that preserve environment state between commands, enabling multi-step workflows and interactive diagnostics on remote systems.
README
SSH MCP Server
A Model Context Protocol (MCP) server that gives LLM clients safe, persistent SSH access to remote machines.
Table of Contents
- Overview
- Key Features
- Architecture
- Installation
- Running the Server
- Client Integrations
- Host Configuration
- Session Management
- Authentication Modes
- Timeouts & Inactivity Handling
- Directory Structure
- Using the MCP Tools
- Testing
- Troubleshooting
- Security Considerations
- Contributing
- License
Overview
ssh-mcp lets MCP-compatible clients (such as Claude Code, Cursor, or custom MCP inspectors) control remote machines through SSH. Once hosts are registered, the server maintains persistent shell sessions that retain environment state between commands—ideal for multi-step workflows, long-running processes, or interactive diagnostics.
The server is implemented in TypeScript on top of the official @modelcontextprotocol/sdk.
Key Features
- MCP-compliant: exposes functionality through standard MCP tool definitions.
- Persistent sessions: keep shell sessions alive, preserving working directory, environment variables, and process state across multiple commands.
- Stored host profiles: manage SSH targets through durable JSON configuration (
~/.ssh-mcp/hosts.json). - Flexible authentication: supports passwords, private keys, and SSH agent forwarding (fallback).
- Timeout & cleanup safeguards: sessions auto-close after prolonged inactivity; commands are marked and monitored for completion.
- Structured listings: query active sessions and saved hosts directly from the MCP client.
Architecture
MCP Client ─┬─> add-host / edit-host / remove-host
│
├─> list-hosts
│
├─> start-session ─┬─> PersistentSession (ssh2 shell)
│ ├─> exec (reuses shell, captures stdout/stderr)
│ └─> close-session / auto-timeout
│
└─> list-sessions
Persistent configuration → ~/.ssh-mcp/hosts.json
Each active session maintains:
- SSH connection via
ssh2 - Interactive shell (
conn.shell) to support multi-command pipelines - Buffered output with unique UUID markers to detect command completion
- Inactivity timer (defaults to 2 hours)
Installation
Install the published package from npm so the ssh-mcp-sessions executable is available in your environment.
Global install (preferred)
npm install -g ssh-mcp-sessions
Launch the server anywhere by running ssh-mcp-sessions.
Project-local install
Inside your project:
npm install ssh-mcp-sessions
Run the server with npx ssh-mcp-sessions (or reference ./node_modules/.bin/ssh-mcp-sessions).
Building from source is only required for contributing. See the Contributing section if you plan to work on the codebase itself.
Claude Desktop
Add an entry to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the appropriate config path on Windows/Linux:
{
"mcpServers": {
"ssh-mcp": {
"command": "npx",
"args": [
"ssh-mcp-sessions"
]
}
}
}
Restart Claude Desktop after saving the file. You can now use the MCP Inspector or the command palette (Cmd/Ctrl+Shift+O) to call tools like add-host and start-session.
Claude Code (VS Code extension)
Update the Claude Code workspace settings (.vscode/settings.json or global settings) with:
{
"claude.mcpServers": {
"ssh-mcp": {
"command": "npx",
"args": [
"ssh-mcp-sessions"
]
}
}
}
Reload the window. The MCP panel will list ssh-mcp, and commands are available via the command palette (Ctrl/Cmd+Shift+P → “Claude: Run MCP Tool”).
Codex (OpenAI GPT-4o/5 with MCP)
Create or edit ~/.config/openai-codex/mcp.toml (the path may differ per platform—use the location documented by the client). Add:
[mcpServers."ssh-mcp"]
command = "npx"
args = ["ssh-mcp-sessions"]
Restart Codex or re-open the MCP inspector. The ssh-mcp tools will appear under the configured servers list.
Cursor IDE
Open Cursor settings → “Model Context Protocol” (or edit ~/Library/Application Support/Cursor/mcp.json directly) and include:
{
"mcpServers": {
"ssh-mcp": {
"command": "npx",
"args": [
"ssh-mcp-sessions"
]
}
}
}
After saving, reload Cursor. The MCP sidebar exposes the server; you can invoke tools via chat or the command palette (Cmd/Ctrl+Shift+L).
Tip: If you prefer an explicit path instead of relying on
npx, replace the command/args with the absolute path to the executable (node_modules/.bin/ssh-mcp-sessionsfor local installs or/usr/local/lib/node_modules/ssh-mcp-sessions/build/index.jsfor global installs).
Running the Server
ssh-mcp-sessions
The server is purely stdio-based. Once running it prints:
SSH MCP Server running on stdio
You can register it with Claude Code or any other MCP client by pointing to the executable installed from npm:
{
"mcpServers": {
"ssh-mcp": {
"command": "npx",
"args": [
"ssh-mcp-sessions"
]
}
}
}
If you prefer to rely on PATH resolution (e.g., after a global install), you can simplify the entry to { "command": "ssh-mcp-sessions" }.
Note: The server no longer accepts CLI arguments for host/user/password. Everything is configured dynamically via MCP tools.
Host Configuration
Host Storage
- Hosts are persisted in
~/.ssh-mcp/hosts.json. - The directory is created automatically if it does not exist.
- File format:
{
"hosts": [
{
"id": "host",
"host": "host.local",
"port": 22,
"username": "user",
"password": "...", // optional
"keyPath": "~/.ssh/id_rsa" // optional
}
]
}
Fields:
id(string) — unique identifier used by all session commands.host(string) — hostname or IP.port(number, default 22) — SSH port.username(string) — SSH user.password(optional string) — password auth.keyPath(optional string) — private key path; tilde expansion supported.- If neither
passwordnorkeyPathis provided, the server attempts to use the local SSH agent viaSSH_AUTH_SOCK(with agent forwarding enabled).
- If neither
The MCP tools ensure this file remains well-formed; never edit it manually unless you know what you’re doing.
Adding Hosts
Tool: add-host
{
"host_id": "user@host.local",
"host": "host.local",
"port": 22,
"username": "user",
"password": "optional",
"keyPath": "optional"
}
host_id: new identifier. Must be unique.host: hostname or IP.port: optional (defaults to 22); provide integer > 0.username: SSH user.passwordorkeyPath: optional; configure one or rely on agent.
Example (Claude Code command palette or inspector):
/mcp mcp-remote-ssh add-host {"host_id":"host","host":"host.local","username":"user"}
Listing Hosts
Tool: list-hosts
Returns text with one host per line:
id=host host=host.local:22 user=user auth=agent
auth values:
password— password field presentkey— keyPath presentagent— neither password nor keyPath; agent fallback active
Editing Hosts
Tool: edit-host
{
"host_id": "user@host.local",
"port": 2222,
"password": "new-pass"
}
Only supply the properties you want to change. Omitted fields remain unchanged; providing null to a field is not supported—set an empty string or remove the host instead.
Removing Hosts
Tool: remove-host
{
"host_id": "user@host.local"
}
Deletes the entry from hosts.json. Active sessions using that host must be closed manually.
Session Management
Starting a Session
Tool: start-session
{
"host_id": "user@host.local"
}
Optionally you can supply sessionId; otherwise, a UUID is returned.
Example response:
Listing Sessions
Tool: list-sessions
Shows all active sessions with metadata:
session=fff4… host=host.local:22 user=user uptime=3m12s lastCommand=ls -la
Executing Commands
Tool: exec
{
"session_id": "fff4b34b-56dd-4711-9555-c04e8b64249b",
"command": "pwd"
}
- Commands are sanitized (trimmed, length-limited).
- Output is captured from the persistent shell and returned as plain text.
- Non-zero exit codes raise
McpErrorwith stderr in the message.
Example output:
/home/user
Closing Sessions
Tool: close-session
{
"sessionId": "fff4b34b-56dd-4711-9555-c04e8b64249b"
}
Note: session IDs for
close-sessionusesessionId(camelCase) to remain backwards compatible with the underlying tool definition.
Legacy Helper
Function execSshCommand(hostId, command, sessionId?) remains exported for programmatic use and simply delegates through the session machinery described above.
Authentication Modes
- Password — stored in
hosts.json; transmitted tossh2during connection. - Private key —
keyPathread at runtime; supports encrypted keys (prompt user to setSSH_MCP_KEY_PASSPHRASEbefore launch if needed). - SSH agent (fallback) — if neither password nor key is set and
SSH_AUTH_SOCKis present, the agent is passed tossh2(agentForward: true).
Timeouts & Inactivity Handling
- Each session has a global inactivity timeout (default 2 hours). Timer resets whenever a command executes successfully.
- If the timer elapses, the session cleans up the SSH connection, shell, and resolver buffer, and removes itself from
activeSessions. - Command completion uses a UUID marker:
printf '__MCP_DONE__{uuid}%d\n' $?. Output before the marker is returned; numeric code after the marker becomes the exit status.
Directory Structure
ssh-mcp/
├── build/ # Compiled JS output (npm run build)
├── src/index.ts # Primary MCP server implementation
├── test/ # Vitest tests (CLI-only; integration tests skipped)
├── package.json
├── README.md # This document
└── ~/.ssh-mcp/hosts.json # Created at runtime (per user)
Using the MCP Tools
Below is a typical workflow using Claude Code (commands start with /mcp), but the same JSON payloads apply to any MCP inspector.
-
Add host
/mcp mcp-remote-ssh add-host {"host_id":"host","host":"host.local","username":"user"} -
Start session
/mcp mcp-remote-ssh start-session {"host_id":"host"}→ returns
session_id -
Run commands
/mcp mcp-remote-ssh exec {"session_id":"<id>","command":"pwd"} /mcp mcp-remote-ssh exec {"session_id":"<id>","command":"ls -la"} -
Inspect
/mcp mcp-remote-ssh list-sessions /mcp mcp-remote-ssh list-hosts -
Close session
/mcp mcp-remote-ssh close-session {"sessionId":"<id>"}
Testing
Unit tests (Vitest):
npm run test
Integration smoke tests for SSH are not included by default because they require external infrastructure. You can manually validate with the workflow above.
Troubleshooting
| Symptom | Possible Cause | Suggested Action |
|---|---|---|
Host 'xyz' already exists |
Duplicate host_id |
Use edit-host or pick a new ID. |
Host 'xyz' not found |
Missing entry | Run list-hosts to confirm; add host again if needed. |
Error (code X): … |
Remote command returned non-zero | Inspect the command output. The session remains open. |
Session disappears from list-sessions |
Inactivity timeout reached | Start a new session or reduce idle periods. |
| Permission denied (publickey) | Missing credentials | Ensure keyPath or agent has the right key. |
Invalid key path |
keyPath resolved to undefined or missing file |
Provide an absolute/tilde path that exists. |
Security Considerations
- Treat
~/.ssh-mcp/hosts.jsonas sensitive; it may contain passwords or key paths. - Prefer key-based or agent authentication where possible.
- Limit
hosts.jsonpermissions:chmod 600 ~/.ssh-mcp/hosts.json. - Sessions inherit all privileges of the configured SSH user.
- Long-running sessions can be closed manually or rely on the inactivity timeout.
Contributing
- Fork the repo and create a branch.
- Make your changes with tests and documentation updates.
- Run
npm run buildandnpm run testbefore submitting a PR. - Follow the Code of Conduct.
Issues and feature requests are welcome via GitHub.
License
Happy automating! If this project improves your workflow, please star the repository or share feedback. Your contributions help make remote development safer and simpler for everyone.
推荐服务器
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 模型以安全和受控的方式获取实时的网络信息。