Four servers, read from their own repositories: what they let a model run on a remote host, and what breaks long before you get there.
Most SSH failures an agent hits are not remote failures. The host is fine; the agent's own environment is broken. It runs in a subprocess that never inherited SSH_AUTH_SOCK, so the key it needs is loaded in an agent it cannot see. It hits a host key that changed when the instance was rebuilt. It gets Permission denied (publickey) and has no way to tell which of five causes it is. Then it guesses, and you spend an afternoon reading the guesses. That is the problem an SSH MCP server can solve, and it is a different problem from "run a command over SSH" -- which is why the servers in this space diverge so sharply.
known_hosts. OpenSSH refuses loudly and correctly, and the repair is to remove the stale entry and re-scan -- deliberately, because the same symptom is what a real interception looks like.None of these are exotic, and all three are mechanically diagnosable. The interesting question when choosing a server is whether it tries, and what it will let the model do once it is connected.
One thing to establish first, because it shapes everything else: there is no official SSH MCP server. The reference repository ships Everything, Fetch, Filesystem, Git, Memory, Sequential Thinking and Time, and no SSH server appears in that list or in its archived one. Every option here is community-maintained, which makes reading the repository part of the selection, not an optional extra.
The most security-engineered of the four, and it is not close. MIT, TypeScript, published to npm as ssh-mcp, 718 stars as of September 2026 and actively developed. Eleven tools, and it refuses every one of them until you have written a TOML config -- the server starts so a client can complete the handshake, then declines to do anything until configured. Commands are classified as read-only, safe, destructive or privileged, and checked against a role-by-tier matrix (viewer, operator, admin against dev, staging, prod). A profile with no explicit group has its tier guessed from its name, and an unrecognized name resolves to prod, the strictest tier -- a good default, because it fails toward caution when you forget to label a host. A separate forbidden list is never allowed at any role: rm -rf /, mkfs, fork bombs, writes to authorized_keys. Destructive work prompts a human through MCP elicitation, and if the client cannot elicit, the command is refused rather than allowed. It also ships an audit log, a per-day command quota, host-key pinning, and SSH CA certificate support.
Twenty-one tools, MIT, Node via npx, and the emphasis is the failure modes above rather than policy. Roughly a third of the surface is environment repair: ssh_diagnose checks agent, keys, config, known_hosts and connectivity and returns fix commands; ssh_agent_ensure starts an agent; ssh_key_load loads a key; ssh_known_hosts_fix removes a stale entry and re-scans; ssh_git_check tests Git-over-SSH auth specifically, since that is where the failure usually surfaces. When any remote operation fails, diagnostics run automatically and ride along in the error, so the model is told what broke instead of inferring it. The rest is operations: exec, SFTP reads and writes, ssh_multi_exec fan-out across hosts, structured ssh_find and ssh_tail, plus connection pooling and ProxyJump. It reads your existing ~/.ssh/config, so host aliases work without re-describing them. The install line is on the server card, and the wider problem it grew out of is covered in managing SSH connections across multiple servers.
The most-starred of the four at 851 as of September 2026, published as @fangjunjie/ssh-mcp-server under ISC, and the smallest surface: four tools (execute-command, upload, download, list-servers). Its command restriction is stricter than ours in one specific and worthwhile way -- with a whitelist enabled, commands containing ;, &, |, backticks, $(), redirection or line breaks are rejected before matching, so chaining cannot slip past the pattern. It offers both exec and shell transports for bastion and jump-host setups, keeps credentials out of the model's context, and ships an AI skill that configures the client for you.
MIT, 99 stars as of September 2026, published as @aiondadotcom/mcp-ssh, seven functions, and a distinctive implementation choice: it shells out to native ssh and scp rather than using a JavaScript SSH library. That means whatever your OpenSSH supports, it supports -- certificates, unusual key exchanges, agent behaviour -- with no second implementation to drift. It discovers hosts from ~/.ssh/config and known_hosts, and installs into Claude Desktop as a double-clickable .mcpb bundle. Its README also contains the bluntest threat statement of the four, which is worth more than a feature: "runRemoteCommand is full remote code execution on every host you have configured."
There is a long tail beyond these -- several Python and JavaScript SSH MCP servers in the single-digit-to-low-double-digit star range. They are left out for adoption and recency, not quality.
| Capability | @yawlabs/ssh-mcp | tufantunc/ssh-mcp | @fangjunjie/ssh-mcp-server | AiondaDotCom/mcp-ssh |
|---|---|---|---|---|
| Tools | 21 | 11 | 4 | 7 |
| Local SSH diagnostics and repair | Agent, keys, config, known_hosts, git auth; auto-runs on failure | Not its focus | Not its focus | Connectivity check |
| Command policy | Regex allow/deny, ssh_exec and ssh_multi_exec only | Classification plus role-by-tier matrix and a never-allowed list | Regex allow/deny; blocks shell metacharacters | None documented in its README |
| Human approval gate | No | Yes, via MCP elicitation; fails closed | No | No |
| Audit log / quota | No | Yes, both | No | No |
| Config required before use | No; reads ~/.ssh/config | Yes; tool calls refused until configured | Per-host CLI arguments | No; discovers hosts |
| File transfer | SFTP read, write, upload, download, ls, stat, mkdir, delete | sftp-upload, sftp-download | upload, download | uploadFile, downloadFile (scp) |
| Multi-host | ssh_multi_exec, parallel | Per-profile sessions | Multi-connection config | Sequential batch, one host |
| Bastion / jump host | ProxyJump from ssh config | via profile field | shell transport | Via ssh config |
| Implementation | Node, ssh2 library | Node, ssh2 library | Node | Node, wraps native ssh/scp |
| License | MIT | MIT | ISC | MIT |
If your requirement is "an agent may touch production hosts, and I need to be able to say afterwards what it did", tufantunc/ssh-mcp is the better choice and ours is not a close second. We have no approval prompt, no audit log, no command classification, no per-day quota, and no role matrix. Those are not features we have a cheaper version of; we do not have them. Their approval gate also fails in the right direction: a client that cannot show an elicitation prompt gets a refusal rather than a silent allow, which is the behaviour you want from a gate that exists precisely for the cases where nobody is watching.
Two smaller credits. @fangjunjie/ssh-mcp-server rejects shell metacharacters before whitelist matching, which closes a bypass class that pattern-matching alone does not -- our own documentation describes the substring-pattern footgun that this design avoids. And AiondaDotCom's decision to wrap the native ssh binary means it inherits your OpenSSH's behaviour exactly, including certificate setups that a library-based client may handle differently.
An SSH MCP server is the highest-blast-radius tool most people will install, so the honest framing is not "is it safe" but "what is the worst a prompt-injected model can do with it". Two limits in our own server are worth stating plainly rather than leaving in the README for you to find.
Unknown host keys are accepted by default. A known host whose key changed is rejected, as it should be. A host with no known_hosts entry at all is accepted -- and because connecting never writes an entry, nothing is pinned by connecting, so this is trust-always rather than trust-on-first-use. Set SSH_MCP_STRICT_HOST_KEY=1 to require an entry, and add hosts deliberately with ssh_known_hosts_fix or ssh-keyscan so that later changes are caught.
The command policy does not cover the SFTP tools. SSH_MCP_COMMAND_WHITELIST and SSH_MCP_COMMAND_BLACKLIST gate ssh_exec and ssh_multi_exec, which build a command string a regex can match. The mutating SFTP tools build no command string, so a blacklist of ^rm does not stop ssh_delete, and a whitelist of ^ls does not stop ssh_write_file. If you need to prevent remote mutation, drop those tools in your client's tool allowlist; the env vars cannot do it.
The same discipline applies whichever server you choose: a dedicated non-root account, the least privilege that does the job, a key that is not your personal one, and an awareness that any untrusted text the model reads is an input to the commands it will propose. tufantunc's README puts the two rules that matter most at the top -- never point it at a root account, and never set automatic approval on a production profile. That advice is good regardless of which of these you install. The broader version of this checklist is in our MCP security checklist.
Add it to any MCP client, or let Yaw MCP fan one config out to every client on the machine:
npx -y @yawlabs/ssh-mcpSource: github.com/YawLabs/ssh-mcp. The alternatives are at tufantunc/ssh-mcp, classfang/ssh-mcp-server and AiondaDotCom/mcp-ssh.
No. The Model Context Protocol reference repository ships Everything, Fetch, Filesystem, Git, Memory, Sequential Thinking and Time, and no SSH server appears in that list or in its archived one. Every option is community-maintained, so the repository is the documentation and reading it before you wire one in is the whole job.
It is remote code execution by design, so treat it that way rather than asking whether it is safe in general. The measures that actually reduce blast radius are a dedicated non-root user with the least privilege that does the job, a command allowlist or an approval gate, strict host-key checking, a key that is not your personal one, and no path from untrusted text to the tool without a human in between. The servers differ a lot in how much of that they give you.
For production hosts where you want command classification, human approval and an audit trail, tufantunc/ssh-mcp is the most security-engineered of the four and the better starting point. For fixing a broken local SSH environment and reading across a fleet, ours leans that way, with about a third of its 21 tools built around diagnosis and repair. For the smallest surface area, the four-tool @fangjunjie/ssh-mcp-server is easy to reason about. For native ssh and scp behaviour with a one-click desktop install, AiondaDotCom/mcp-ssh fits.
Jeff Yaw, Yaw Labs. Follow along at tokenlimit.news for weekly notes on AI infrastructure.
Published by Yaw Labs.