SSH MCP Server
Capability-bound SSH MCP for autonomous DevOps agents: composable primitives, deterministic long-running jobs, bounded context, and atomic remote edits.
ssh-mcp is a Rust Model Context Protocol server that gives an AI agent secure, narrowly-scoped control of a remote Linux host over a single persistent SSH session. It exposes five base tools plus two explicitly privileged sudo variants and is built to keep agent context small and operations deterministic.
Why
- Capability-bound surface. Five base tools and two optional sudo variants, no open-ended remote API. The agent can only run commands, read files, patch one file, transfer files, and inspect background jobs.
- Deterministic long-running jobs.
background=truereturns{job_id, pid, log_path}immediately; output streams to a local log you poll withcheck_process, avoiding client RPC deadlines. - Bounded context.
readdefaults to a safe preview with token estimates; shell output is capped by--max-output-tokens. Large files cannot bomb the agent's context window. - Atomic remote edits.
apply_patchedits as the SSH user; the separately gatedsudo_apply_patchpreserves the same conflict detection and atomic commit under sudo.
Tools
| Tool | Purpose |
|---|---|
shell |
Run a command via POSIX sh as the connected user; background=true for long tasks. |
sudo_shell |
Same, under sudo (uses --sudo-password); can be disabled with --disable-sudo. |
check_process |
Poll a background job by job_id and read the tail of its local log. |
read |
Read a remote UTF-8 file with preview / head / tail / full modes and token estimates. |
apply_patch |
Create, update, or delete one remote UTF-8 file with an exact patch (atomic, conflict-checked). |
sudo_apply_patch |
Same exact patch flow under sudo; can be disabled with --disable-sudo. |
transfer |
Move files/directories (put/get) via auto → rsync → sftp → scp → exec-raw. |
Full parameter schemas are served to the client at runtime; deeper references live in Docs/.
Installation
Pre-built binaries (recommended)
Download the latest rolling release from the Releases page:
| Platform | Download |
|---|---|
| Linux x86_64 | ssh-mcp-linux-x86_64 |
| Windows x86_64 | ssh-mcp-windows-x86_64.exe |
| macOS ARM64 | ssh-mcp-macos-aarch64 |
&&
Cargo (crates.io)
Build from source
Requires the Rust toolchain plus pkg-config and OpenSSL headers (libssl-dev on Debian/Ubuntu).
&&
Adding to MCP clients
OpenCode
Add to opencode.jsonc (SSH key recommended; password auth uses the exec-raw transfer transport):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ssh-remote": {
"type": "local",
"command": [
"/absolute/path/to/ssh-mcp",
"--host=192.168.1.10",
"--port=22",
"--user=agent-nc",
"--key=/path/to/private/key"
],
"enabled": true
}
}
}
Use --password=your-password instead of --key=... for password authentication.
Add to your project's .mcp.json (shared via git) or to ~/.claude.json under the top-level mcpServers key:
Set --strict-host-key-checking=yes and point at a pre-populated known_hosts file (works in any client config):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ssh-remote": {
"type": "local",
"command": [
"/absolute/path/to/ssh-mcp",
"--host=example.com",
"--user=alice",
"--key=/home/alice/.ssh/id_ed25519",
"--strict-host-key-checking=yes",
"--known-hosts=/home/alice/.ssh/known_hosts"
],
"enabled": true
}
}
}
Configuration
Every flag also has an SSH_MCP_* environment variable. Required: --host, --user, and one of --password / --key.
| Argument | Env | Description |
|---|---|---|
--host |
SSH_MCP_HOST |
SSH host (required) |
--user |
SSH_MCP_USER |
SSH username (required) |
--port |
SSH_MCP_PORT |
SSH port (default: 22) |
--password |
SSH_MCP_PASSWORD |
SSH password (alternative to key) |
--key |
SSH_MCP_KEY |
Path to private key file |
--sudo-password |
SSH_MCP_SUDO_PASSWORD |
Password for sudo commands |
--timeout |
SSH_MCP_TIMEOUT |
Command timeout in ms (default: 300000) |
--max-output-tokens |
SSH_MCP_MAX_OUTPUT_TOKENS |
Shell/read output token limit (default: 16000 ≈ 64KB; none to disable) |
--disable-sudo |
SSH_MCP_DISABLE_SUDO |
Disable the sudo_shell and sudo_apply_patch tools |
Run ssh-mcp --help for the full list (logging, keepalive, reconnect, host-key options).
SSH host key verification
ssh-mcp verifies the server host key before authentication to prevent silent man-in-the-middle replacement:
accept-new(default): trust and record an unknown key on first connection; reject later changes.yes: require the key to already exist inknown_hosts; reject unknown or changed keys.no: disable verification; only for disposable test environments.
Long-running jobs
Start potentially long commands with background=true. A foreground timeout_ms controls SSH execution only and cannot extend the MCP client's own deadline. You immediately get {job_id, pid, log_path}, where log_path is a local log on the MCP server (default /tmp/ssh-mcp/<job_id>.log). Poll with check_process:
check_process returns a strict state — running, completed, failed, or state_lost — plus the log tail. Sleep between checks (2–5s, then 10–30s for long jobs) rather than tight-polling; a job is done when the state is terminal and an exit_code is present.
Background tracking requires the MCP server and its SSH session to remain alive; jobs are not guaranteed to survive an MCP server restart.
Safety
- Stdio transport. JSON-RPC over stdin/stdout — no exposed network ports.
- Credentials in memory only. Passwords and keys are never logged.
- Logs to stderr. Internal logging stays off the MCP protocol channel.
- Path validation. Rejects control characters, traversal (
..), and shell-injection shapes. - Binary protection. Text tools reject non-UTF-8 content to prevent corruption.
- Atomic edits. Staging with automatic cleanup and conflict detection; no silent overwrites.
- Explicit elevation.
apply_patchnever retries under sudo; privileged edits require an explicitsudo_apply_patchcall.
Documentation
Deeper references live in Docs/:
ssh-remote-file-editing-reference.md— the SSH file-editing workflow.diff-generation-reference.md— diff generation for file operations.backup-manager-reference.md— backup manager implementation.rmcp-sdk.md/russh-library.md— SDK and SSH library notes.
License
MIT — see LICENSE for details.