Labsco
MCP SERVER

Python SSH MCP

by Nightreaver

Real SSH across many hosts for an agent, gated four ways — read-only by default, with strict known_hosts, path allowlists per tool, and a hashed audit line for every call.

Editors, Terminals & Local Dev Environment
Summary
The setup cost is the security model.

Pinning host keys by hand and starting with every tier off is slower than pasting a config, and that is the trade being offered: an assistant that can only reach the hosts, paths and commands you named. If you want a single `ssh_exec` tool the README says so itself — this is built for the case where more than one host is in play.

What it is

An SSH server for MCP built on FastMCP, aimed at operators who want an assistant on their fleet without handing it a shell. Hosts, keys, allowlists and sudo mode are declared per host in `hosts.toml`; capability is granted by flipping tier flags, and the tools outside the granted tiers are not visible to the client at all.

What you get
  • 100 tools across ten groups — `host`, `session`, `sftp-read`, `file-ops`, `exec`, `sudo`, `shell`, `docker`, `systemctl`, `pkg` — trimmed per assistant with `SSH_ENABLED_GROUPS`
  • Read-only probes on the default tier: `ssh_host_ping`, `ssh_host_info`, `ssh_sftp_list`, `ssh_find`, `ssh_file_hash`, disk usage, processes, alerts and known-hosts verification
  • `ssh_read_redacted` — read a `.env` or `.yml` with secrets replaced inline by HMAC-SHA256 hash markers, so the model gets the structure and never the plaintext
  • Low-access file operations — cp, mv, mkdir, delete, edit, patch, upload, deploy, link, transfer — SFTP-first with atomic writes, and a `local_path=` streaming mode so large files skip the base64 channel
  • An exec tier with per-call timeouts, a streaming variant, broadcast across hosts, and a cheatsheet that catches `cat`/`tee` and reroutes to the native tool
  • A sudo tier where `ssh_sudo_exec` sits beside five path-bearing tools — `ssh_sudo_read`, `_read_redacted`, `_write`, `_edit`, `_sftp_list` — so root-owned files stay inside path policy instead of escaping through raw `sudo cat`
  • 27 Docker tools, 17 systemctl tools, 8 journalctl and list helpers, and 9 APT tools including `apt_list`, `apt_search`, `apt_install`, `apt_upgrade`, `apt_remove`, `apt_mark`
  • `ssh_server_info` and the `mcp://ssh-mcp/server-info` resource, so the model can ask which tiers are unlocked instead of guessing
  • Optional BM25 tool search that swaps `tools/list` for `search_tools` plus `call_tool` when the catalog starts eating context
Requirements

SSH keys already loaded into an agent — the server talks to your running SSH agent and does not take passwords in env, which are hard-rejected at startup. Python 3.11-3.13; run it with `uvx --from git+https://github.com/Nightreaver/python-ssh-mcp ssh-mcp`. Two files do the real work: `hosts.toml` for hosts, users, path allowlists and sudo mode, and `.env` for the tier flags `ALLOW_LOW_ACCESS_TOOLS`, `ALLOW_DANGEROUS_TOOLS` and `ALLOW_SUDO`, all false to start. `known_hosts` is strict with no auto-accept, so you pin each target's fingerprint out of band before the first connection. Point `SSH_CONFIG_FILE` at `~/.ssh/config` to inherit aliases and ProxyJump. Package `python-ssh-mcp` at 1.5.2, GPL-3.

Setup effort

One command plus a key — uvx --from git+https://github.com/Nightreaver/python-ssh-mcp ssh-mcp, then supply credentials