
SSH MCP Server (tufantunc): Setup for Claude, Cursor and Other Apps
Lets your AI assistant run commands and move files on your Linux or Windows servers over SSH, under role and approval rules you set.
It runs on your computer and reaches your servers over SSH using your own keys or SSH agent. Nothing works until you write a config file that lists your hosts, roles and approval rules. Commands are classified and logged, but ordinary changes are not blocked by default, so treat it as real shell access.
Good for
- Developers and admins who want Claude or Cursor to check logs and servers
- Teams that need an audit log and approval step for every AI command
- People who manage several hosts through a bastion
Works in
12 should work
Tap an app to see how to set it up and any known problems.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Supports local MCP servers.
Client does not support this transport.
Client does not support this transport.
Install SSH — policy-gated remote access MCP
Claude Code
- 1
Copy this prompt.
Add the SSH — policy-gated remote access MCP server to Claude Code. Run this command: claude mcp add ssh-policy-gated-access -- npx -y ssh-mcp Then check that it loaded and tell me if I need to sign in or restart.
- 2
Paste it into Claude Code. It shows the change and asks before running it.
Requires Node.js.
Read-only mode: Set `readOnly = true` on the profile in config.toml, or give it the viewer role.
Create the config file first, or every tool call is refused. On Linux it is ~/.config/ssh-mcp/config.toml, on macOS ~/Library/Application Support/ssh-mcp/config.toml, and on Windows %APPDATA%\ssh-mcp\config.toml; list each host as a [[profiles]] entry and run chmod 700 on the folder and chmod 600 on the file. For a quick test without a file you can pass --host, --user and --group=dev to the command. Set a password with SSH_MCP_PASSWORD, or use an SSH agent or key file instead.
Built from the package data we hold. Not yet tested by us.
Tools
Shows the servers you set up and which are connected
Lists the SSH profiles from your config file and whether each one is connected. The assistant uses it to learn which hosts it may use.
Try: “Which servers can you reach?”
Read ·
list-connectionsRuns a safe, read-only command on a server
Runs one command from a fixed allowlist, such as ls, cat, grep, find or df. It cannot change the server, and it refuses commands with line breaks.
Try: “Show the last 50 lines of /var/log/nginx/error.log on web-1.”
Network ·
read-commandRuns any shell command on a server
Runs one command on the remote host. Risky commands go through the approval step you set for that profile, but ordinary changes such as editing files or restarting services do not.
Try: “Restart the app service on staging and tell me if it comes back up.”
Delete ·
run-commandRuns a command with sudo
Runs a command with sudo. It always goes through the approval step for the profile, and the sudo password is passed over stdin and not on the command line.
Try: “Use sudo to install the security updates on build-box.”
Delete ·
privileged-commandLists files in a remote folder
Lists a folder over SFTP. The number of entries and the size of the answer are capped.
Try: “List the files in /var/www/releases on web-1.”
Network ·
sftp-listReads a remote file into the chat
Downloads one file over SFTP and hands its contents to the assistant.
Try: “Fetch /etc/nginx/nginx.conf and explain the proxy rules.”
Network ·
sftp-downloadWrites text to a file on a server
Uploads content to a path over SFTP. It overwrites an existing file with no warning and has no option to refuse that.
Try: “Upload this config to /etc/myapp/config.yml on staging.”
Write ·
sftp-uploadSends a local file to a server
Streams a file from your computer to the server without passing it through the model. It only works inside the transfer folder you set in config, and refuses if none is set.
Try: “Upload build.tar.gz from my transfer folder to /opt/releases on web-1.”
Write ·
sftp-upload-fileSaves a remote file to your computer
Streams a file from the server to your disk without passing it through the model. It only writes inside the transfer folder you set in config, and refuses if none is set.
Try: “Download the 2 GB database dump from backup-1 to my transfer folder.”
Write ·
sftp-download-fileStarts a named shell or background job
Opens a named session on a host. An interactive one keeps its folder and variables between commands, and a background one runs a long job such as a log tail.
Try: “Open a background session that follows /var/log/syslog on web-1.”
Runs code ·
open-sessionLists open sessions on a server
Shows the sessions that are currently open for one host.
Try: “What sessions are open on web-1?”
Read ·
list-sessionsReads output from a background job
Returns the most recent lines from a background session, for example a log you are following.
Try: “Show the latest 20 lines from the logs session.”
Read ·
read-session-outputEnds a session
Closes a named session. For a background job it first signals the command (INT, then TERM, then KILL) so it stops.
Try: “Close the logs session.”
Runs code ·
close-sessionStops or interrupts a remote process
Sends INT, TERM or KILL to a process ID on the server.
Try: “Kill process 4821 on web-1, it is stuck.”
Runs code ·
signal-processChecks or reloads the config file
Shows the config file path and last load result, or re-reads the file and applies it if it passes validation. It never shows the file contents.
Try: “Reload the SSH config and tell me if it was accepted.”
Files ·
reload-config
Read from the source code
Permissions
high risk · 5 things to watch · 14 advisories
High risk
The assistant can run arbitrary commands, including sudo, and upload or delete files on any host in your config. Use a low-privilege account, set readOnly = true on profiles you only monitor, and use ask-all approval on production.
What it can do
- Read your data
- Create and change things
- Delete things
- Read-only modeHow to turn it on
Watch out for
It runs arbitrary commands on your servers
run-command and privileged-command can change or delete anything the SSH user can. Use a dedicated low-privilege account and a restrictive role. github.com
The default approval step is narrow
The default ask-destructive mode prompts only for patterns such as rm -rf, interpreter one-liners, uploads and sudo. Ordinary writes, service control and signals run without a prompt, so use ask-all on production. github.com
sftp-upload overwrites files without warning
It replaces an existing file at the path and has no overwrite flag. Use profiles without write roles on hosts where that matters. github.com
It tells your hosts an AI agent connected
Each command sends AI_AGENT=ssh-mcp to the host by default. Clear announceAgent on a profile for a host you do not control. github.com
The HTTP mode needs a bearer token
If you start it with --transport=http it requires --bearerToken and listens on 127.0.0.1 by default. Put TLS in front of it before exposing it. github.com
Security advisories
14 known advisories, all fixed in a newer version.
- Command classifier can be made to read a different command than the shell runs, defeating readOnly and the approval gatecritical · Fixed in 2.6.0 · GHSA-qvx5-rxrj-9vfh
- Approval-gate bypass: a command behind an exec wrapper's own operands, or spelled with .exe or another case, classifies safehigh · Fixed in 2.22.0 · GHSA-x567-334m-mr3c
- Approval-gate bypass: never-allowed destructive commands are not covered when flags are respelled or separatedhigh · Fixed in 2.20.2 · GHSA-5cjr-rc2p-f66f
- Common exec carriers classify safe, bypassing the approval gatehigh · Fixed in 2.20.0 · GHSA-cm4c-4q74-mgmj
- A backslash Windows path hides an interpreter from the classifier, so powershell -EncodedCommand classifies safehigh · Fixed in 2.14.0 · GHSA-972x-g47g-3922
Show all 14Show fewer
- A readOnly profile can change system state through the read-only allowlist: DISQUALIFYING_ARGS covers 2 of ~70 readershigh · Fixed in 2.13.0 · GHSA-mwmj-jr2h-q546
- F6 interpreter-carrier allowlist is still incomplete: osascript (always present on macOS), lua, deno, bun, Rscript launder the command class to safehigh · Fixed in 2.12.0 · GHSA-qmx6-47vm-3vf7
- Variable-headed commands bypass the classifier, letting a 'safe'-only role run unapproved root commandshigh · Fixed in 2.4.2 · GHSA-fj9r-f47j-c73x
- Command-substitution classifier bypass lets a 'safe'-only role run unapproved root commandshigh · Fixed in 2.4.1 · GHSA-v8jh-gv7v-3gvq
- Read-only and approval-gate bypass in classifyCommand via exec wrappers and find action flagshigh · Fixed in 2.2.4 · GHSA-6f54-mjqq-2jp8
- [Security] Read-only policy bypass via command substitution in classifyCommand (CWE-88/CWE-863)high · Fixed in 2.0.4 · GHSA-r8hm-vpm8-cfh6
- privileged-command leaks the sudo password on stdin when sudo does not promptmedium · Fixed in 2.19.2 · GHSA-9m75-x2ch-j4jr
- The never-allowed list does not refuse most writes to authorized_keys, /etc/cron or /etc/systemdmedium · Fixed in 2.19.0 · GHSA-rrxj-hcj2-vwm6
- SSH credentials exposed via command-line argumentsmedium · Fixed in 2.0.0 · GHSA-j4q8-xwr2-344g
Technical details
| Turning on read-only | Set readOnly = true on a profile in config.toml, or give the profile the viewer role. |
|---|---|
| Talks to | The SSH hosts in your config. Optional HTTP listener, 127.0.0.1:3000 by default |
| Sign-in and keys | Passwords come from SSH_MCP_PASSWORD (or a per-profile SSH_MCP_<PROFILE>_PASSWORD) and key paths from SSH_MCP_KEY. It also supports an SSH agent and the OS keychain. Passwords are never taken as command-line arguments. |
| Scopes |
|
Questions
Is the ssh-mcp server by tufantunc official?
No. It is a community project by tufantunc. It is not made by OpenSSH or any SSH vendor.
Why does every tool say it is refused after I install it?
You have not made the config file yet. Without it the server starts but refuses every tool call until config.toml exists in the path for your system. The README gives the path for Linux, macOS and Windows.
Do I need an API key?
No. It logs into your servers with your SSH key, an SSH agent, the OS keychain or a password. Set SSH_MCP_PASSWORD for password logins or SSH_MCP_KEY for a key file path, and SSH_MCP_PASSPHRASE for an encrypted key.
Can it run read-only?
Yes. Set readOnly = true on a profile or give it the viewer role. Then the assistant can only use read-only commands and listings on that host.
Can it use sudo?
Yes, through the privileged-command tool, if the role and policy allow it. It needs SSH_MCP_SUDO_PASSWORD unless sudo needs no password. By default the admin role is refused sudo on hosts treated as production.
Does it run locally or send data to a third party?
It runs on your computer and connects straight to your hosts. It has an optional HTTP mode if you start it with --transport=http, which needs a bearer token.
Which apps does it work with?
Claude Code, Claude Desktop, Cursor and Windsurf are named in the README. Use the install box for the exact steps, and create the config file first.
Information
updated Nov 2, 2026
- Publisher
- Community
- Package
ssh-mcp- Registry
- npm
- Transport
- stdio, Streamable HTTP
- Auth
- token in env
- Version
- 2.22.0
- License
- MIT
- Last commit
- Oct 26, 2026
- Open issues
- 1
- Listed in
- Official MCP registry
Sources
Docs, issue trackers and discussions this page is built from. Issues, quotes and findings above link to their own source.
Show all 2Hide
- ssh-mcp README (v2.22.1) · github.com
- ssh-mcp tool descriptions (v2.22.1) · github.com