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.1.tar.gz (101.4 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.1-py3-none-any.whl (91.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mcp_ssh_vps-0.7.1.tar.gz
  • Upload date:
  • Size: 101.4 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.1.tar.gz
Algorithm Hash digest
SHA256 2c4d92a21c6ba1cdb5faedd22466060696769261e658f6da4985f940413afc33
MD5 f6288c23c919031666f653ceebefa701
BLAKE2b-256 c8d56ded8edb7819cb995f59993fa80e5601e24fc2d1666f5a92595ea9c48bb7

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_ssh_vps-0.7.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: mcp_ssh_vps-0.7.1-py3-none-any.whl
  • Upload date:
  • Size: 91.5 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 467aff3677568300eaf7baf663a0fd621b03dc4a084bac147d3cebfdef3dc60f
MD5 6e34f6d19e8f4e8965786a9c4d9310a4
BLAKE2b-256 dc6437afc31a20a295b49967b39ff7a430681ef67b15199aa385dd3ff297d1f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_ssh_vps-0.7.1-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