ssh-mcp-server
# SSH MCP Server
**English** | [简体中文](README.zh-CN.md)
[](https://github.com/yuyi-clip/ssh-mcp-server/actions/workflows/ci.yml)
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
A structured SSH management service for Codex and other MCP clients. It exposes command
execution, file transfer, background jobs, GPU monitoring, systemd operations, and port
forwarding as MCP tools with explicit input schemas, structured outputs, and accurate safety
annotations.
## Features
- Connects only to explicit `Host` aliases declared in `~/.ssh/config`.
- Searches hosts by keyword, alias, environment, and tags, then runs bounded batch commands with
per-host failure isolation.
- Strictly verifies `known_hosts` by default and rejects unknown or changed host keys.
- Reuses AsyncSSH connections and rebuilds stale connections automatically.
- Transfers files and directories over SFTP without invoking an external `scp` command; single
files support bounded-memory resume, overwrite control, and final progress statistics.
- Streams files between two SSH servers through bounded local memory without exposing credentials
to either remote host.
- Safely previews, creates, updates, and deletes single-alias OpenSSH blocks with backups and
atomic replacement.
- Runs background jobs in isolated process groups with persistent identity, logs, exit status,
status discovery, safe cancellation, and cleanup.
- Calculates remote file growth rate, progress, and estimated completion time.
- Reports NVIDIA GPU metrics, system resources, systemd service state, and journal logs.
- Binds SSH tunnels only to `127.0.0.1` and exposes status, explicit restart, and per-host stop-all.
- Applies MCP safety annotations to arbitrary commands, file overwrites, and service control.
## Quick Start
### Requirements
- Python 3.11 or later
- [uv](https://docs.astral.sh/uv/)
- An OpenSSH `config` file and a verified `known_hosts` file
### Install and Run
```powershell
git clone https://github.com/yuyi-clip/ssh-mcp-server.git
Set-Location ssh-mcp-server
uv sync --locked
uv run ssh-mcp-server
```
### Configure an SSH Host
The server accepts explicit aliases, not arbitrary IP addresses or hostnames:
```ssh-config
# description: GPU inference server
# environment: development
# tags: gpu,video
Host gpu-01
HostName 192.0.2.10
User operator
IdentityFile ~/.ssh/id_ed25519
Port 22
```
`192.0.2.10` is a documentation-only address. Replace it with your server address, verify the
host fingerprint through a trusted channel, and add it to `~/.ssh/known_hosts` before connecting.
### Connect from Codex
Register the stdio MCP server with the Codex CLI:
```powershell
codex mcp add ssh -- uv --directory "D:\path\to\ssh-mcp-server" run ssh-mcp-server
```
Alternatively, add it to `~/.codex/config.toml` manually:
```toml
[mcp_servers.ssh]
command = "uv"
args = [
"--directory",
"D:\\path\\to\\ssh-mcp-server",
"run",
"ssh-mcp-server",
]
startup_timeout_sec = 20
tool_timeout_sec = 120
default_tools_approval_mode = "writes"
```
Restart Codex after editing the configuration and use `/mcp` to verify the server status.
## Tool Overview
| Category | Tools |
|---|---|
| Hosts and commands | `ssh_list_servers`, `ssh_search_servers`, `ssh_check`, `ssh_execute`, `ssh_execute_batch` |
| SSH configuration | `ssh_config_create`, `ssh_config_update`, `ssh_config_delete` |
| File transfer | `ssh_upload`, `ssh_download`, `ssh_transfer_between_servers` |
| Background jobs | `ssh_start_job`, `ssh_job_status`, `ssh_job_list`, `ssh_cancel_job`, `ssh_job_cleanup` |
| Download monitoring | `ssh_file_progress` |
| Host monitoring | `ssh_gpu_status`, `ssh_system_status` |
| systemd and journal | `ssh_service_status`, `ssh_service_control`, `ssh_read_journal` |
| Tunnels | `ssh_tunnel_start`, `ssh_tunnel_list`, `ssh_tunnel_status`, `ssh_tunnel_stop`, `ssh_tunnel_stop_all`, `ssh_tunnel_restart` |
See the [tool reference](docs/tools.md) for parameters, safety properties, and usage guidance.
## Optional Environment Variables
| Variable | Purpose |
|---|---|
| `SSH_MCP_CONFIG` | Use a custom OpenSSH config path |
| `SSH_MCP_KNOWN_HOSTS` | Use a custom `known_hosts` path |
| `SSH_MCP_ALLOW_UNKNOWN_HOSTS=1` | Temporarily allow unknown hosts; not recommended |
| `SSH_MCP_PASSWORD_<ALIAS>` | Supply a temporary password for one alias |
Non-alphanumeric characters in an alias are converted to underscores and the result is
uppercased. For example, `gpu-01` maps to `SSH_MCP_PASSWORD_GPU_01`. Prefer key authentication
and avoid long-lived password environment variables.
## Documentation
- [Architecture](docs/architecture.md)
- [Tool reference](docs/tools.md)
- [Troubleshooting](docs/troubleshooting.md)
- [Contributing](CONTRIBUTING.md)
- [Security policy](SECURITY.md)
- [Changelog](CHANGELOG.md)
The detailed documents are currently maintained in Chinese. English documentation can be added
incrementally without changing the tool interfaces described here.
## Development and Verification
```powershell
uv sync --locked
uv run ruff format --check .
uv run ruff check .
uv run pytest -q
```
The test suite covers configuration parsing, input validation, tool registration, connection
behavior, background job lifecycle, and a real MCP stdio initialization handshake. Linux CI also
executes the real process-group lifecycle test.
## Current Limitations
- Remote shell and systemd workflows target Unix-like hosts, with full background-job support
requiring Linux.
- SFTP tools return final progress statistics but do not emit live MCP progress events.
- Server-to-server transfer uses bounded local-memory streaming, not direct remote `scp` or
`rsync`; throughput therefore depends on the MCP host's network path.
- Background jobs require Linux `/proc`, `sh`, `setsid`, `nohup`, `tail`, and common Coreutils.
- Jobs created by older versions can still be inspected, but cannot be safely cancelled because
they lack process identity files.
- Tunnel state exists only in the current MCP process and is closed when the process exits;
failed tunnels require an explicit restart.
- OpenSSH configuration backups are intentionally retained beside the config file and must be
managed like other sensitive SSH configuration artifacts.
## License
This repository does not currently declare an open-source license. Public visibility does not
grant permission to copy, modify, or distribute the code; contact the maintainer before reuse.
TDQS
Scored across 19 tools
Most tools have clearly distinct purposes (execute, upload, service control, tunnel management), but ssh_check and ssh_system_status both report host health, and ssh_job_status versus ssh_job_list overlap in querying jobs. Descriptions help disambiguate, but the boundaries aren't perfectly sharp.
All names use snake_case with a consistent ssh_ prefix and mostly a verb-first pattern (list, execute, start, cancel). However, ssh_service_control and ssh_file_progress deviate from the verb-noun structure, creating minor inconsistency.
19 tools is on the higher end but justified by the broad scope covering execution, file transfer, job lifecycle, services, monitoring, and tunnels. The count feels slightly heavy but each tool serves a distinct area without redundancy.
The toolset provides strong lifecycle coverage for jobs, services, files, and tunnels, plus system and GPU monitoring. Minor gaps like remote directory listing or file deletion are absent but workaroundable, so core workflows are well-supported.