MCP server for AI agents to connect and interact with remote servers over SSH.
1.6K
A Model Context Protocol (MCP) server that lets an agent connect to remote machines over SSH to manage systems. It supports local execution (stdio) and remote deployment over HTTP using Streamable HTTP transport.
# Build
docker build -t ssh-mcp .
# Run (persist SSH keys)
docker volume create ssh-data
docker run -p 8000:8000 -v ssh-data:/data --name ssh-mcp ssh-mcp
HTTP endpoint:
http://localhost:8000/mcppip install .
# Stdio mode (for local MCP hosts)
python -m ssh
# HTTP server (Streamable HTTP transport)
uvicorn ssh.server_all:app --host 0.0.0.0 --port 8000
All tools are exposed via MCP. Each tool accepts a target parameter (default: "primary") to specify which SSH connection to use.
| Tool | Description |
|---|---|
connect(host, username, port, alias, via) | Open SSH connection to a remote server |
disconnect(alias) | Close one or all SSH connections |
identity() | Get server's public SSH key for authorized_keys |
sync(source_node, source_path, dest_node, dest_path) | Stream file between two nodes |
| Tool | Description |
|---|---|
run(command) | Execute any shell command |
info() | Get OS/kernel/shell info |
| Tool | Description |
|---|---|
read(path) | Read remote file content |
write(path, content) | Create/overwrite remote file |
edit(path, old_text, new_text) | Safe text replacement |
list_dir(path) | List directory contents (JSON) |
| Tool | Description |
|---|---|
docker_ps(all) | List Docker containers |
net_stat(port) | List listening ports |
list_services(failed_only) | List system services (Systemd/OpenRC) |
| Tool | Description |
|---|---|
usage() | System resource usage (CPU/RAM/Disk) |
logs(path, lines, grep) | Tail log files |
ps(sort_by, limit) | Top processes |
| Tool | Description |
|---|---|
db_query(container, db_type, query, ...) | Execute SQL/CQL/MongoDB query in container |
db_schema(container, db_type, database, ...) | Get database schema (tables/collections) |
db_describe_table(container, db_type, table, ...) | Describe table/collection structure |
list_db_containers() | Find database containers |
Supported databases: PostgreSQL, MySQL, ScyllaDB, Cassandra, MongoDB
db_query options:
timeout (default: 60s) - Query timeoutread_only (default: false) - Block destructive queriesmax_rows (default: 1000) - Limit result rowsYou can connect to multiple hosts in a single session by choosing different alias values.
Example:
connect(host="10.0.0.10", username="ubuntu", alias="web1")connect(host="10.0.0.11", username="ubuntu", alias="web2")run("uptime", target="web1")run("df -h", target="web2")sync(source_node="web1", source_path="/var/log/nginx/access.log", dest_node="web2", dest_path="/tmp/web1-access.log")If a node is not reachable directly from where the MCP server runs, you can connect through a jump host.
Example:
connect(host="bastion.company.com", username="ubuntu", alias="bastion")connect(host="10.0.1.25", username="ubuntu", alias="db1", via="bastion")From then on, you can use:
run("systemctl status postgresql", target="db1")By default the server keeps a managed SSH key pair in /data (container volume):
/data/id_ed25519/data/id_ed25519.pub (comment: Origon)To use managed identity:
identity() and copy the public key.~/.ssh/authorized_keys on the target host(s).connect(...) without password/private_key_path.You can also provide password or private_key_path per connection.
| Variable | Description | Default |
|---|---|---|
PORT | The port the HTTP server listens on. | 8000 |
ALLOWED_ROOT | Restricts file operations to a specific path. | / (unrestricted) |
SSH_MCP_GLOBAL_STATE | If set to true, share connections across sessions. | false |
SSH_MCP_SESSION_HEADER | Header to use for smart session caching. | X-Session-Key |
SSH_MCP_SESSION_TIMEOUT | Idle timeout for cached sessions (seconds). | 300 (5 mins) |
A common challenge with AI Agents is that they are often "stateless" HTTP clients—they open a new connection for every request. By default, this would cause the SSH connection to close and reopen constantly, breaking state (like cd commands).
This server solves this with three strategies:
X-Session-Key).X-Session-Key: my-agent-1 with every request.my-agent-1, it is reused.SSH_MCP_GLOBAL_STATE=true./mcpSSHManager to use.SSHManager holds multiple SSH connections keyed by alias.MIT
Content type
Image
Digest
sha256:ef4fcdaad…
Size
4 MB
Last updated
7 months ago
docker pull firstfinger/ssh-mcp