SSH MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@SSH MCP Serverrunuptimeon 192.168.1.100 and show me the output"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SSH MCP Server (paramiko)
Paramiko-based SSH MCP server that can run commands on remote machines and move files over SFTP. It is available on two transports, selectable with an environment variable / flag:
http– MCP streamable-http endpoint on the/mcppath (this is where Cherry Studio connects), plus a documented OpenAPI/Swagger interface (/docs,/openapi.json).stdio– classic MCP stdio transport (for local launch /docker exec).
IMPORTANT about ports: 2222 is the MCP server port that Cherry Studio connects to. This is NOT the remote machine's SSH port! The remote machine's SSH port is usually 22 (
SSH_PORT). So: Cherry Studio →http://<host-IP>:2222/mcp→ MCP server → paramiko → the remote machine's SSH port 22.
Available MCP tools
Stateless tools — simple, one-off operations
Tool | Description |
| Tests the connection and authentication to a remote machine. |
| Runs a SINGLE shell command in a fresh connection (stdout / stderr / exit code). No memory: the |
| Uploads a local file to the remote machine over SFTP. |
| Downloads a file from the remote machine over SFTP. |
Stateful, interactive session tools — live shell
These keep a live shell open, where the state persists across calls (directory changes after cd, export-ed variables, handling interactive prompts: sudo password, apt [Y/n], etc.).
Tool | Description |
| Step 1 – opens a new interactive shell and returns a |
| Step 2 – sends text (a command or a prompt response) to the session. The |
| Step 3 (optional) – reads further output without sending anything (for slow/long-running commands). |
| Step 4 – closes the session. Always close it when you are done. |
| Lists the open sessions (host, user, idle time), for example if a |
The tool descriptions (docstrings) intentionally contain a very detailed, plain-English "USE THIS WHEN..." guide so that the consuming model clearly knows when and how to use each tool.
Every tool's parameters (host, port, username, password, private_key, private_key_path, passphrase, timeout) can be specified:
per call, individually, or
as defaults in the
.envfile (SSH_*variables). Anything not given in the call is taken from theSSH_*environment variables.
Supported authentication: password and key (inline PEM or file path, optionally with a passphrase). Unknown host keys are automatically accepted by the server (AutoAddPolicy) so that automation works smoothly.
Related MCP server: SSH MCP Server
Stateless vs. stateful (interactive) use
Which one when?
A single, standalone command (e.g.
ls,uptime,df -h) →ssh_execute. Every call opens a fresh connection, runs one command, and closes. No memory: thecdandexportdo not survive to the next call, and it cannot respond to interactive prompts.Anything interactive or multi-step (state retention after
cd/export, entering a sudo password, answering apt[Y/n], sequential commands that build on one another) → interactive session:ssh_open_session→ssh_send→ssh_read→ssh_close_session.
Recommended workflow (session)
ssh_open_session→ you get asession_idback (and the login banner / first prompt ininitial_output).ssh_send→ you type a command or respond to a prompt. Thesession_idmust be passed in every call. It also sends an Enter by default.ssh_read(optional) → collect further output for slow / long-running commands without sending anything.ssh_close_session→ once you are done, close the session.
With ssh_list_sessions you can view open sessions at any time (host, user, idle time), for example if a session_id was lost.
Examples (via REST endpoints)
Opening a session:
curl -X POST http://localhost:2222/api/ssh/session/open \
-H "Content-Type: application/json" \
-d '{"host":"192.168.1.100","username":"user","password":"secret"}'
# -> {"ok":true,"session_id":"<ID>", "initial_output":"...prompt..."}Changing directory, which persists (stateful):
curl -X POST http://localhost:2222/api/ssh/session/send \
-H "Content-Type: application/json" \
-d '{"session_id":"<ID>","input":"cd /var/log && pwd"}'
# a következő ssh_send már a /var/log-ban futnaSudo command + responding to the password prompt:
# 1) elindítod a sudo parancsot
curl -X POST http://localhost:2222/api/ssh/session/send \
-H "Content-Type: application/json" \
-d '{"session_id":"<ID>","input":"sudo apt-get update"}'
# 2) a kimenetben megjelenik a "[sudo] password for user:" prompt -> beküldöd a jelszót
curl -X POST http://localhost:2222/api/ssh/session/send \
-H "Content-Type: application/json" \
-d '{"session_id":"<ID>","input":"my_sudo_password"}'Responding to apt [Y/n]:
curl -X POST http://localhost:2222/api/ssh/session/send \
-H "Content-Type: application/json" \
-d '{"session_id":"<ID>","input":"sudo apt-get install htop","read_timeout":5}'
# amikor jön a "Do you want to continue? [Y/n]" kérdés:
curl -X POST http://localhost:2222/api/ssh/session/send \
-H "Content-Type: application/json" \
-d '{"session_id":"<ID>","input":"Y"}'Closing the session:
curl -X POST http://localhost:2222/api/ssh/session/close \
-H "Content-Type: application/json" \
-d '{"session_id":"<ID>"}'Timeout / idleness / errors: every session operation opportunistically closes sessions that have been idle longer than the
SSH_SESSION_IDLE_TIMEOUT(default 600 seconds), as well as those whose channel has died. At mostSSH_MAX_SESSIONS(default 20) sessions can be open at the same time — reaching the limit yields a clear error message. If asession_idno longer exists, the response tells you exactly what to do (open a new session, or check withssh_list_sessions).
Project structure
ssh-mcp-server/
├── app/
│ ├── __init__.py
│ ├── ssh_ops.py # paramiko SSH/SFTP műveletek (közös logika)
│ └── server.py # MCP tool-ok + FastAPI/OpenAPI + transport választás
├── requirements.txt
├── Dockerfile
├── docker-compose.yml # 2222:2222 publikálás
├── .env.example
└── README.md1. Quick start with Docker (recommended)
Prerequisites
cd ssh-mcp-server
cp .env.example .env
# szerkeszd a .env-et: add meg a távoli gép adatait (SSH_HOST, SSH_USERNAME, stb.)Build and start (HTTP mode)
docker compose up -d --buildThis starts the server in HTTP mode and publishes the 2222 port to the host (ports: "2222:2222").
Verification
curl http://localhost:2222/health
# {"status":"ok","service":"ssh-mcp-server","mcp_endpoint":"/mcp"}Swagger UI (in a browser):
http://localhost:2222/docsOpenAPI JSON:
http://localhost:2222/openapi.jsonMCP endpoint (Cherry Studio):
http://<host-IP>:2222/mcp
Shutdown
docker compose down2. HTTP mode manually (without Docker, for development)
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
export TRANSPORT=http HOST=0.0.0.0 PORT=2222
python -m app.server3. stdio mode
With the server running in a container, using docker exec:
docker exec -i -e TRANSPORT=stdio ssh-mcp-server python -m app.serverOr directly, without Docker:
TRANSPORT=stdio python -m app.server4. Cherry Studio integration
A) HTTP (streamable-http) mode – recommended, also works over the network
The container runs on your laptop in Docker, and Cherry Studio uses the host IP and port 2222.
Start the server:
docker compose up -d --buildFind the IP address of the machine (host) where the Docker is running:
Linux:
hostname -I→ e.g.192.168.1.50If Cherry Studio is running on the same machine,
localhost/127.0.0.1is fine too.
Cherry Studio → Settings → MCP Servers → Add / New server.
Enter the following:
Type:
Streamable HTTP(if not available, useSSE/HTTP)URL / Endpoint:
http://<host-IP>:2222/mcpe.g.
http://192.168.1.50:2222/mcpsame machine:
http://localhost:2222/mcp
Save and enable it. Cherry Studio then loads the
ssh_test,ssh_execute,ssh_upload,ssh_downloadtools.
If you are connecting from a remote machine, make sure that port 2222 is reachable (allow it in the firewall) and that Docker is listening on
0.0.0.0(default).
B) stdio mode
If Cherry Studio expects a stdio MCP server (it launches a command):
Command:
dockerArguments:
exec -i -e TRANSPORT=stdio ssh-mcp-server python -m app.server(For this, the sf-mcp-server container must be running — docker compose up -d.)
5. .env configuration
Variable | Description | Default |
|
|
|
| MCP HTTP bind address |
|
| MCP HTTP port (reached by Cherry Studio) |
|
| Remote machine address | – |
| SSH port of the remote machine |
|
| SSH username | – |
| SSH password (or use a key) | – |
| Inline PEM private key | – |
| Path to the private key file (inside the container) | – |
| Passphrase for the private key | – |
| Connection timeout (in seconds) |
|
| Automatically close idle interactive sessions after this many seconds (0 = none) |
|
| Maximum number of open interactive sessions at once |
|
Key-based authentication in Docker
Mount the keys into the container and set the path. In docker-compose.yml, uncomment the volumes line:
volumes:
- ./keys:/keys:rothen in .env:
SSH_PRIVATE_KEY_PATH=/keys/id_ed255196. REST endpoints for testing (OpenAPI)
In HTTP mode, in addition to the Cherry Studio MCP endpoint, REST endpoints are also available — these perform the same SSH operations and can be easily used with curl / from the Swagger UI:
Method | Path | Operation |
GET |
| Status |
GET |
| Server info |
POST |
| Connection test |
POST |
| Command execution |
POST |
| File upload (SFTP) |
POST |
| File download (SFTP) |
POST |
| Open interactive session (step 1) |
POST |
| Send input to the session (step 2) |
POST |
| Read output without sending (step 3) |
POST |
| Close the session (step 4) |
GET |
| List open sessions |
Example (stateless single-command run):
curl -X POST http://localhost:2222/api/ssh/execute \
-H "Content-Type: application/json" \
-d '{"host":"192.168.1.100","username":"user","password":"secret","command":"uname -a"}'Security notes
Secrets are never in the code — everything is read from
.env/ call parameters.The
.envfile is excluded by.dockerignoreand typically also.gitignore— do not commit it to version control.The server uses
AutoAddPolicy(automatic acceptance of unknown host keys). Convenient on closed networks; in stricter environments, it is advisable to use known host keys.Expose the
2222MCP port only on a trusted network.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceEnables AI assistants to execute commands and transfer files on remote servers over SSH connections.1MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to securely execute commands, transfer files, and manage port forwarding on remote servers via SSH.9836Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to securely execute commands on remote hosts via SSH and SFTP, with persistent shells, file transfers, screenshots, and an audit log.1MIT
Related MCP Connectors
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Persistent memory and cross-session learning for AI coding assistants (hosted remote MCP).
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/vait90/ssh-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server