Skip to main content
Glama
gilberth

mcp-ssh-multi

mcp-ssh-multi

MCP server for managing multiple SSH servers through AI assistants. Provides 11 tools for remote command execution, file operations, and system monitoring.

Features

  • Multi-server management — Configure and manage multiple SSH servers from a single YAML file

  • Connection pooling — Automatic connection reuse with per-server locks and retry on stale connections

  • 11 MCP tools — Execute commands, transfer files, read/write files, tail logs, list processes

  • Two transports — stdio (for local MCP clients) and streamable-http (for web/remote)

  • Cloudflare Tunnel compatible — Deploy behind a tunnel for remote access

  • MCP tool annotations — Hints for destructive, read-only, idempotent, and open-world operations

  • MCP resourcesssh://servers resource for listing configured servers

  • Pagination — Directory listings support limit/offset for large directories

  • Input validation — Path and filter sanitization to prevent command injection

  • Structured errors — Consistent error responses with codes, messages, and suggestions

Related MCP server: mcp-remote-ssh

Installation

uv tool install mcp-ssh-multi

Using pip

pip install mcp-ssh-multi

Using uvx (one-shot)

uvx --from mcp-ssh-multi ssh-mcp

From source

git clone https://github.com/gilberth/mcp-ssh-multi.git
cd mcp-ssh-multi
uv sync

Configuration

1. SSH Servers (ssh_servers.yaml)

Create a ssh_servers.yaml file with your server definitions:

servers:
  proxmox:
    host: 192.168.1.100
    port: 22
    username: root
    key_file: ~/.ssh/id_rsa
    description: "Proxmox VE hypervisor"

  truenas:
    host: 192.168.1.101
    port: 22
    username: root
    password: "my-password"  # or use key_file
    description: "TrueNAS storage server"

2. Environment Variables (.env)

Copy .env.example to .env and customize:

cp .env.example .env

Variable

Default

Description

SSH_SERVERS_FILE

ssh_servers.yaml

Path to servers config

SSH_TIMEOUT

30

Default command timeout (seconds)

LOG_LEVEL

INFO

Logging level

MCP_PORT

8086

HTTP server port

MCP_SECRET_PATH

/mcp

HTTP endpoint path

Usage

stdio mode (local MCP clients)

ssh-mcp

Or with uvx:

uvx --from mcp-ssh-multi ssh-mcp

HTTP mode (web/remote MCP clients)

ssh-mcp-web

The server will listen on http://0.0.0.0:8086/mcp by default.

MCP Client Configuration

Add to your MCP client config (e.g., Claude Desktop):

{
  "mcpServers": {
    "ssh": {
      "command": "uvx",
      "args": ["--from", "mcp-ssh-multi", "ssh-mcp"],
      "env": {
        "SSH_SERVERS_FILE": "/path/to/ssh_servers.yaml"
      }
    }
  }
}

For HTTP mode:

{
  "mcpServers": {
    "ssh": {
      "url": "http://localhost:8086/mcp"
    }
  }
}

Tool Reference

Connection Management

Tool

Description

ssh_list_servers

List all configured servers with connection status

ssh_disconnect

Disconnect from a specific server

Command Execution

Tool

Description

ssh_execute

Execute a shell command on a remote server

File Operations

Tool

Description

ssh_upload

Upload a local file to a remote server

ssh_download

Download a file from a remote server

ssh_file_exists

Check if a file/directory exists on a server

ssh_list_dir

List contents of a remote directory (supports pagination with limit/offset)

ssh_read_file

Read a text file from a remote server

ssh_write_file

Write content to a file on a remote server

System Monitoring

Tool

Description

ssh_tail_log

Tail a log file on a remote server

ssh_process_list

List running processes (optionally filtered)

MCP Resources

The server exposes the following MCP resources:

Resource URI

Description

ssh://servers

List of all configured SSH servers with connection status

Changelog

v0.2.0

  • Per-server connection locks — Replaced global lock with per-server async locks for better concurrency

  • Connection retry — Automatic single retry on stale/lost SSH connections

  • MCP tool annotations — Added destructiveHint, readOnlyHint, idempotentHint, openWorldHint to all tools

  • MCP resource — Added ssh://servers resource endpoint

  • Directory paginationssh_list_dir now supports limit and offset parameters

  • Input validation — Path sanitization for ssh_tail_log and filter validation for ssh_process_list

  • Structured errors — Consistent error format with ErrorCode enum across all tools

  • Dynamic versioning — Version sourced from importlib.metadata instead of hardcoded strings

  • Test suite — Added tests for pagination, retry logic, input validation, and version consistency

v0.1.1

  • Initial public release with 11 SSH tools, stdio and HTTP transports

Production Deployment (LXC + Cloudflare Tunnel)

Full deployment guide for running mcp-ssh-multi as a systemd service behind a Cloudflare Tunnel on a Proxmox LXC container.

Prerequisites

  • A Proxmox LXC container (Debian 12/13)

  • A Cloudflare account with a domain

  • uv and cloudflared installed on the LXC

1. Install dependencies

# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \
  -o cloudflared.deb && dpkg -i cloudflared.deb

2. Create SSH servers config

mkdir -p /ssh-mcp
cat > /ssh-mcp/ssh_servers.yaml << 'EOF'
servers:
  my-server:
    host: 192.168.1.100
    port: 22
    username: root
    password: "my-password"  # or use key_file
    description: "My server"
EOF

3. Create the Cloudflare Tunnel

# Login to Cloudflare (opens browser)
cloudflared tunnel login

# Create the named tunnel
cloudflared tunnel create ssh-mcp

# Route DNS to your domain
cloudflared tunnel route dns ssh-mcp ssh-mcp.yourdomain.com

4. Configure the tunnel

The tunnel create command outputs the tunnel UUID (e.g. 2687c640-38df-40f9-...) and creates a credentials file at /root/.cloudflared/<TUNNEL-ID>.json. If you need to find it later, run cloudflared tunnel list.

# Replace <TUNNEL-ID> with the UUID from "cloudflared tunnel create" output
cat > /root/.cloudflared/config.yml << 'EOF'
tunnel: <TUNNEL-ID>
credentials-file: /root/.cloudflared/<TUNNEL-ID>.json

ingress:
  - hostname: ssh-mcp.yourdomain.com
    service: http://localhost:8086
  - service: http_status:404
EOF

5. Create systemd services

mcp-ssh-multi service:

cat > /etc/systemd/system/mcp-ssh-multi.service << 'EOF'
[Unit]
Description=MCP SSH Multi Server
After=network.target

[Service]
Type=simple
Environment=SSH_SERVERS_FILE=/ssh-mcp/ssh_servers.yaml
Environment=MCP_SECRET_PATH=/your-secret-path
ExecStart=/root/.local/bin/uvx --from mcp-ssh-multi@latest ssh-mcp-web
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

cloudflared service:

cloudflared service install

Enable and start both:

systemctl daemon-reload
systemctl enable --now mcp-ssh-multi
systemctl enable --now cloudflared

6. Verify

# Check services
systemctl status mcp-ssh-multi
systemctl status cloudflared

# Test the endpoint
curl -s -X POST "https://ssh-mcp.yourdomain.com/your-secret-path" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

7. Configure your MCP client

{
  "mcpServers": {
    "ssh": {
      "type": "remote",
      "url": "https://ssh-mcp.yourdomain.com/your-secret-path"
    }
  }
}

Service management

# View logs
journalctl -u mcp-ssh-multi -f
journalctl -u cloudflared -f

# Restart services
systemctl restart mcp-ssh-multi
systemctl restart cloudflared

Environment Variables

Variable

Default

Description

SSH_SERVERS_FILE

ssh_servers.yaml

Path to servers config

SSH_TIMEOUT

30

Default command timeout (seconds)

LOG_LEVEL

INFO

Logging level

MCP_PORT

8086

HTTP server port

MCP_SECRET_PATH

/mcp

HTTP endpoint path (use a secret value)

Development

# Install with dev dependencies
uv sync --group dev

# Run linting
uv run ruff check src/ tests/ --fix
uv run ruff format src/ tests/

# Run type checking
uv run mypy src/

# Run tests
uv run pytest tests/ -v

License

MIT

Install Server
A
license - permissive license
A
quality
C
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
3Releases (12mo)
Commit activity

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    MCP server giving AI agents full SSH access with persistent sessions, structured command output, SFTP file transfer, and port forwarding.
    Last updated
    18
    5
    MIT
  • A
    license
    -
    quality
    A
    maintenance
    MCP server enabling AI assistants to securely operate remote servers via persistent SSH sessions, with tools for command execution, file transfer, directory listing, and system monitoring.
    Last updated
    2
    MIT
  • A
    license
    -
    quality
    D
    maintenance
    An MCP server that gives AI agents SSH capabilities to execute commands, transfer files, and inspect remote systems through a preconfigured host list.
    Last updated
    77
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for Gainium — manage trading bots, deals, and balances via AI assistants

  • Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.

  • MCP server for AI dialogue using various LLM models via AceDataCloud

View all MCP Connectors

Latest Blog Posts

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/gilberth/mcp-ssh-multi'

If you have feedback or need assistance with the MCP directory API, please join our Discord server