ssh-mcp logo

ssh-mcp

Fairmont77/ssh-mcp
0 starsMITUpdated 2026-06-21Community

Is this your server?

Add your score badge to your README and get your server in front of 45k+ builders a month.

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Provides persistent SSH access to servers using OpenSSH ControlMaster multiplexing, allowing AI agents to run commands on registered hosts by name without re-entering credentials.

README.md

ssh-mcp

A small, reliable MCP server that gives an AI agent (Claude Code, etc.) persistent SSH access to your servers — register a host once, then run commands by name.

Why

Stock SSH MCP servers reimplement the SSH transport in-process: they drop connections, lose credentials between sessions, and force the agent to fall back to raw ssh -i key user@host shell-outs (which leak creds into command history and break on reconnect).

This server does not reimplement SSH. It wraps the system ssh/scp binaries with OpenSSH ControlMaster multiplexing:

  • A background control socket (ControlPersist=10m) keeps one authenticated connection warm — reconnects are instant and survive MCP restarts.
  • Credentials live in a registry file (~/.ssh/ssh_mcp_hosts.json), set once, reused by host name.
  • The agent calls ssh_exec(host="myserver", command=...) — no keys or IPs in every call.

Tools

| Tool | Purpose | |---|---| | host_add | Register/overwrite a named host (name, host, user, port?, key?, note?) | | host_list | List registered hosts | | host_remove | Remove a host by name | | ssh_exec | Run one non-interactive command on a host (one-shot) | | sftp_put | Upload a local file via scp | | sftp_get | Download a remote file via scp |

Execution model — one-shot

Each ssh_exec is an independent command. State does not persist between calls:

  • cwd does not persist → use absolute paths or cd /path && cmd.
  • env does not persist → set inline (VAR=x cmd).
  • No interactive TUI (vim, top, less) and no prompts → pass -y/--yes.
  • Long jobs: nohup cmd >/tmp/x.log 2>&1 &, then tail the log in a later call.

First connect with a password (auto key-provisioning)

For a host that only accepts a password (a factory-default device, a fresh VPS), let the server mint a dedicated key for it:

  1. host_add(name="cam1", host="10.0.0.180", user="root") — no key.
  2. ssh_exec(host="cam1", command="uname -a") → fails with Permission denied plus a hint.
  3. Put the password in a file so it never enters the transcript:

umask 077; printf %s 'THE_PASSWORD' > /tmp/sshpw_cam1

  1. ssh_exec(host="cam1", command="uname -a", password_file="/tmp/sshpw_cam1")

The server generates ~/.ssh/ssh_mcp_cam1_ed25519, installs it via ssh-copy-id, records the key path in the registry, shreds the password file, and runs the command. Every later call authenticates by key — no password needed. One dedicated key per host; the password is read from the file (never argv) and is never logged.

Requires sshpass and ssh-copy-id on PATH for this flow.

Requirements

  • Node.js 23.6+ (runs TypeScript directly via type-stripping — no build step)
  • OpenSSH client (ssh, scp) on PATH
  • sshpass + ssh-copy-id (only for password-based auto-provisioning)

Install

pnpm install

Register with your MCP client (e.g. Claude Code ~/.claude.json):

{
  "mcpServers": {
    "ssh": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/ssh_mcp/src/index.ts"]
    }
  }
}

Restart the client, then add a host:

host_add(name="myserver", host="1.2.3.4", user="root", key="~/.ssh/id_ed25519")
ssh_exec(host="myserver", command="uname -a")

License

MIT

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use AI & ML servers.