A cross-platform MCP (Model Context Protocol) server that lets Claude Code — or any MCP client — read, write, edit, search, run commands, transfer files, and use git on a remote Linux server over SSH. The server runs on your local machine; nothing is installed on the remote.
It uses a pure-Python SSH transport (Paramiko), so
it runs natively on Windows, macOS, and Linux — no WSL, no native ssh
client, no SSH ControlMaster. Authentication uses your SSH key / agent /
~/.ssh/config; credentials never pass through the MCP channel.
Sometimes the remote box is great for the code but can't run the agent — e.g. the network blocks the model's API, or you don't want to install/authenticate an agent on a shared server. SSH MCP flips it: the agent runs locally (with internet + your credentials) and reaches into the remote host over plain SSH.
┌──────────────┐ MCP (stdio) ┌──────────────┐ SSH / SFTP ┌───────────────┐
│ Claude Code │ ◄───────────────► │ ssh-mcp │ ◄─────────────► │ Remote server │
│ (local) │ tool calls │ (Paramiko) │ exec + files │ (Linux / bash) │
└──────────────┘ └──────────────┘ └───────────────┘
- 22 MCP tools — files, line-edits, commands, background jobs, search, git, and binary-safe file transfer.
- Binary-safe upload/download over SFTP —
.db, images, archives, etc., streamed (large files don't load into memory). - Zero remote install — uses standard tools already on the remote.
- Flexible auth — keys, ssh-agent,
~/.ssh/config,ProxyCommand. - Atomic writes, output truncation, binary-file detection, background jobs.
- Python 3.10+
- An SSH key / agent /
~/.ssh/configentry that can reach the remote host - uv (recommended) or pip
- Claude Code (optional, to use it as an MCP server)
git clone <your-repo-url> ssh-mcp
cd ssh-mcp
uv tool install . # puts the `ssh-mcp` command on your PATHOr with pip:
python -m venv .venv && . .venv/bin/activate # Windows: .\.venv\Scripts\activate
pip install -e .Create ~/.config/ssh-mcp/config.yaml from the example and edit it:
mkdir -p ~/.config/ssh-mcp
cp config.example.yaml ~/.config/ssh-mcp/config.yaml# Windows (PowerShell)
mkdir "$env:USERPROFILE\.config\ssh-mcp" -Force
copy config.example.yaml "$env:USERPROFILE\.config\ssh-mcp\config.yaml"Minimal config:
default_host: myserver
hosts:
myserver:
ssh_host: server.example.com # hostname/IP or a ~/.ssh/config alias
user: jdoe
key_path: "~/.ssh/id_ed25519" # omit to use agent / default keys / ssh_config
default_cwd: "~/project"claude mcp add --scope user ssh-mcp -- ssh-mcpThen run claude and ask: "List the files in ~/project on the remote server."
Commands: ssh_run · ssh_run_background · ssh_job_status
Connection: ssh_check_connection
Files: ssh_read_file · ssh_write_file · ssh_patch_file ·
ssh_append_file · ssh_insert_lines · ssh_replace_lines · ssh_list_dir ·
ssh_file_info · ssh_mkdir · ssh_move · ssh_delete
Transfer (binary-safe, SFTP): ssh_upload · ssh_download
Search: ssh_grep · ssh_find_files
Git: ssh_git_status · ssh_git_diff · ssh_git_log
Text vs binary:
ssh_write_fileis for text (UTF-8). For binary files (.db, images, archives) usessh_upload/ssh_download, which use SFTP and preserve bytes exactly.
| Key | Default | Meaning |
|---|---|---|
ssh_host |
— (required) | hostname/IP or ~/.ssh/config alias |
user |
ssh_config / system | SSH username |
port |
22 |
SSH port |
key_path |
— | private key file (else agent / default keys / ssh_config) |
password |
— | password auth (discouraged) |
use_ssh_config |
true |
read ~/.ssh/config for this host |
strict_host_key_checking |
false |
reject unknown host keys |
proxy_command |
— | ProxyCommand for bastion / IAP |
connect_timeout |
20 |
connect timeout (s) |
preamble |
— | shell sourced before each command |
default_cwd |
~ |
working directory |
command_timeout / file_timeout |
30 / 60 |
timeouts (s) |
max_file_size |
10485760 |
text read/write cap (binary transfer is unbounded) |
max_output_lines |
5000 |
command output truncation |
Config path: ~/.config/ssh-mcp/config.yaml (override with SSH_MCP_CONFIG or
ssh-mcp --config <path>).
uv sync --extra dev
uv run pytest -qAGPL-3.0 — see LICENSE and NOTICE. This project is a modified version of a third-party AGPL-3.0 work and remains under the same license.