Skip to main content

MCP server for managing VPS via SSH - gives AI agents secure access to remote servers

Project description

PyPI Python License Downloads

🔐 SSH MCP Server

Give AI agents secure access to your VPS servers via SSH
Execute commands, transfer files, manage processes — all through Model Context Protocol

Quick StartFeaturesIDE IntegrationToolsSecurity


🚀 Quick Start

Install

# Via pip
pip install mcp-ssh-vps

# Via uvx (recommended for MCP)
uvx mcp-ssh-vps

Add Your First Server

# Interactive setup
uvx mcp-ssh-vps --help

# Or use the CLI
sshmcp-cli server add --name prod --host 192.168.1.100 --user deploy
sshmcp-cli server test prod

Connect to Your AI Agent

Add to your AI IDE config and start managing servers with natural language!

"Deploy my app to the production server"
"Check disk space on all servers"
"Restart nginx on web1 and web2"

✨ Features

Feature Description
🖥️ Execute Commands Run any shell command on remote servers
📁 File Operations Read, write, and list files via SFTP
📂 Directory Transfer rsync-like upload/download/sync directories
🔗 SSH Tunnels Local and remote port forwarding
💻 Interactive Shell PTY-based shell sessions for interactive work
⚙️ Process Management Control systemd, pm2, supervisor services
📊 Command History Track and search executed commands
🚨 Monitoring Alerts CPU/memory/disk usage alerts
🏷️ Server Tags Group servers with tags for batch operations
🔄 Batch Execution Run commands on multiple servers in parallel
🔒 Security Profiles Strict, moderate, or full access levels
📝 Audit Logging Track all operations for compliance
🔑 SSH Keys & Passwords Key, password, and SSH-agent authentication

🔌 IDE Integration

Note: Config is auto-loaded from ~/.sshmcp/machines.json by default. No env variables required!

Claude Code

claude mcp add ssh-vps -- uvx mcp-ssh-vps

Or add to ~/.claude.json:

{
  "mcpServers": {
    "ssh-vps": {
      "command": "uvx",
      "args": ["mcp-ssh-vps"]
    }
  }
}

Factory Droid

droid mcp add ssh-vps "uvx mcp-ssh-vps"

Or add to ~/.factory/mcp.json:

{
  "mcpServers": {
    "ssh-vps": {
      "command": "uvx",
      "args": ["mcp-ssh-vps"]
    }
  }
}

Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "ssh-vps": {
      "command": "uvx",
      "args": ["mcp-ssh-vps"]
    }
  }
}

Qwen Code

qwen mcp add ssh-vps uvx mcp-ssh-vps

Or add to ~/.qwen/settings.json:

{
  "mcpServers": {
    "ssh-vps": {
      "command": "uvx",
      "args": ["mcp-ssh-vps"]
    }
  }
}

Claude Desktop

Add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "ssh-vps": {
      "command": "uvx",
      "args": ["mcp-ssh-vps"]
    }
  }
}

VS Code + Continue

Add to .continue/config.json:

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "stdio",
          "command": "uvx",
          "args": ["mcp-ssh-vps"]
        }
      }
    ]
  }
}

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "ssh-vps": {
      "command": "uvx",
      "args": ["mcp-ssh-vps"]
    }
  }
}

OpenAI Codex CLI

codex --mcp-config '{"ssh-vps": {"command": "uvx", "args": ["mcp-ssh-vps"]}}'

Any MCP-Compatible Client

Generic stdio configuration:

{
  "command": "uvx",
  "args": ["mcp-ssh-vps"]
}

Custom config path? Add "env": {"SSHMCP_CONFIG_PATH": "/custom/path.json"}


🛠️ Tools Reference

Command Execution

Tool Description Example
execute_command Run command on server execute_command("prod", "docker ps")
execute_command_streaming Run with progress updates execute_command_streaming("prod", "apt update")
execute_on_multiple Run on multiple servers execute_on_multiple(["*"], "uptime")

Server Management

Tool Description Example
list_servers List all servers list_servers() or list_servers(tag="web")
add_server Add new server add_server("web1", "1.2.3.4", "root")
remove_server Remove server remove_server("old-server")
test_connection Test SSH connection test_connection("prod")

File Operations

Tool Description Example
read_file Read remote file read_file("prod", "/var/log/app.log")
upload_file Upload file upload_file("prod", "/tmp/script.sh", "#!/bin/bash\n...")
list_files List directory list_files("prod", "/var/log")

Process Management

Tool Description Example
manage_process Control services manage_process("prod", "restart", "nginx")

Help & Info

Tool Description Example
get_help Get documentation get_help("examples")
get_allowed_commands View security config get_allowed_commands("prod")
get_server_info Server details get_server_info("prod")

Interactive Shell Sessions

Tool Description Example
shell_start Start PTY shell shell_start("prod")
shell_send Send to shell shell_send(session_id, "ls -la")
shell_recv Receive output shell_recv(session_id)
shell_close Close session shell_close(session_id)
shell_list List sessions shell_list()

Command History

Tool Description Example
get_command_history View history get_command_history(host="prod", limit=50)
search_command_history Search search_command_history("docker")
get_command_stats Statistics get_command_stats()

Directory Transfer (rsync-like)

Tool Description Example
upload_directory Upload dir to remote upload_directory("prod", "./dist", "/var/www")
download_directory Download dir download_directory("prod", "/var/log", "./logs")
sync_directory Sync with delete sync_directory("prod", "./app", "/opt/app", "upload")

Port Forwarding (SSH Tunnels)

Tool Description Example
forward_local Local tunnel forward_local("prod", 5433, "localhost", 5432)
forward_remote Reverse tunnel forward_remote("prod", 8080, "localhost", 3000)
list_forwards List tunnels list_forwards()
close_forward Close tunnel close_forward("local-1")

Monitoring & Alerts

Tool Description Example
get_alerts View alerts get_alerts(host="prod")
get_active_alerts Active only get_active_alerts()
clear_alert Clear alert clear_alert("prod", "cpu")

🏷️ Server Tags & Batch Operations

Add servers with tags

add_server("web1", "192.168.1.10", "deploy", tags=["production", "web"])
add_server("web2", "192.168.1.11", "deploy", tags=["production", "web"])
add_server("db1", "192.168.1.20", "deploy", tags=["production", "database"])

Filter by tag

list_servers(tag="web")           # Only web servers
list_servers(tag="production")    # All production servers

Execute on tagged servers

execute_on_multiple(["tag:web"], "nginx -t")           # All web servers
execute_on_multiple(["tag:production"], "uptime")      # All production
execute_on_multiple(["*"], "df -h")                    # ALL servers

🔒 Security

Security Profiles

Profile Allowed Commands Use Case
strict git, ls, cat, df, uptime Read-only monitoring
moderate + docker, npm, systemctl, pm2 Standard DevOps
full All commands (except rm -rf /) Full access

Set security level

add_server("prod", "1.2.3.4", "root", security_level="full")

Audit Logging

All commands are logged with timestamps, user, and results:

2024-01-15T10:30:00Z | prod | root | docker ps | exit_code=0 | 150ms

📁 Configuration

Config Location

~/.sshmcp/machines.json

Example Config

{
  "machines": [
    {
      "name": "production",
      "host": "192.168.1.100",
      "port": 22,
      "user": "deploy",
      "auth": {
        "type": "key",
        "key_path": "~/.ssh/id_rsa"
      },
      "security": {
        "allowed_commands": [".*"],
        "forbidden_commands": [".*rm\\s+-rf\\s+/$"],
        "timeout_seconds": 120
      },
      "tags": ["production", "web"],
      "description": "Main production server"
    }
  ]
}

Environment Variable

export SSHMCP_CONFIG_PATH=/custom/path/machines.json

📖 Usage Examples

Check status of all servers

User: Check the status of all my servers
AI: I'll run uptime on all configured servers...

execute_on_multiple(["*"], "uptime && df -h | head -5")

Deploy application

User: Deploy the latest code to production
AI: I'll pull the latest changes and restart the service...

execute_command("prod", "cd /app && git pull origin main")
execute_command("prod", "npm install --production")
execute_command("prod", "pm2 restart all")

Debug server issues

User: Why is the web server slow?
AI: Let me check system resources and logs...

execute_command("web1", "top -bn1 | head -20")
execute_command("web1", "tail -50 /var/log/nginx/error.log")
execute_command("web1", "free -m && df -h")

🚀 Advanced Features

Transport Modes

# Default stdio (for MCP clients like Claude Code)
uvx mcp-ssh-vps

# SSE transport for web integration  
uvx mcp-ssh-vps --transport sse

# Streamable HTTP for production
uvx mcp-ssh-vps --transport streamable-http

WebSocket Shell (Real-time)

For real-time interactive shells, integrate with your web app:

from fastapi import FastAPI, WebSocket
from sshmcp.ws import ShellWebSocketHandler

app = FastAPI()
handler = ShellWebSocketHandler()

@app.websocket("/ws/shell/{host}")
async def shell(websocket: WebSocket, host: str):
    await handler.handle(websocket, host)

Client protocol:

// Connect
const ws = new WebSocket("ws://localhost:8000/ws/shell/prod");

// Send command
ws.send(JSON.stringify({type: "input", data: "ls -la\n"}));

// Resize terminal
ws.send(JSON.stringify({type: "resize", width: 120, height: 40}));

// Receive output
ws.onmessage = (e) => {
    const msg = JSON.parse(e.data);
    if (msg.type === "output") terminal.write(msg.data);
};

Streaming Commands

For long-running commands with progress updates:

# Regular (waits for completion)
execute_command("prod", "apt update")

# Streaming (reports progress)
execute_command_streaming("prod", "apt update")

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

git clone https://github.com/LuxVTZ/sshmcp.git
cd sshmcp
pip install -e ".[dev]"
pytest

📄 License

MIT License - see LICENSE for details.


Made with ❤️ for the AI agent ecosystem
PyPIGitHubIssues

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_ssh_vps-0.7.0.tar.gz (101.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_ssh_vps-0.7.0-py3-none-any.whl (91.3 kB view details)

Uploaded Python 3

File details

Details for the file mcp_ssh_vps-0.7.0.tar.gz.

File metadata

  • Download URL: mcp_ssh_vps-0.7.0.tar.gz
  • Upload date:
  • Size: 101.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mcp_ssh_vps-0.7.0.tar.gz
Algorithm Hash digest
SHA256 9de788202f0042b48b5b9465ed359c46069e57ea9a1fd841136a79a297daa9b0
MD5 3f506cdc82b75dc2ebffe7632cba383f
BLAKE2b-256 1ce0676d35dc427629d8dee36dd929b5bbf23ea7c80f81520f594c88b7707e9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_ssh_vps-0.7.0.tar.gz:

Publisher: publish.yml on data-zen-ru/sshmcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mcp_ssh_vps-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_ssh_vps-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 91.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mcp_ssh_vps-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b9008dac9e96e5efa8929541f04cc6b038fe4882fd4b230e9e1b9a5ebd532f3
MD5 9e532dafb1e7e7250549cb8148440314
BLAKE2b-256 85ed65dda0074dc10a4186a2100850952433e3752929f5c74b3fabbc4fdb9a99

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_ssh_vps-0.7.0-py3-none-any.whl:

Publisher: publish.yml on data-zen-ru/sshmcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page