Skip to main content
Glama
README.md
# SSH MCP Server

**English** | [简体中文](README.zh-CN.md)

[![CI](https://github.com/yuyi-clip/ssh-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/yuyi-clip/ssh-mcp-server/actions/workflows/ci.yml)
[![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-3776AB)](https://www.python.org/)
[![MCP](https://img.shields.io/badge/MCP-2.0-6f42c1)](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

B3.4/5.0

Scored across 19 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count4/5

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.

Completeness4/5

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues