VPS Docker MCP (Advanced)
This MCP server provides safe VPS diagnostics and Docker/Compose management over SSH.
Docker read-only: list containers, logs, inspect, stats, health, images, volumes, networks, disk usage.
Docker mutations: restart, start, stop containers.
Docker Compose read-only: ps, config, logs.
Docker Compose mutations: restart, pull, up.
VPS diagnostics: system info, disk usage, top processes, network info, failed systemd services, journal errors, diagnose_vps.
Restricted diagnostic_command: run fixed read-only commands (pwd, whoami, date, df, free, uptime, docker_version, docker_info).
Provides tools for managing Docker containers and Docker Compose projects on a remote VPS, including diagnostics, container operations, and compose management.
Click on "Deploy 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., "@VPS Docker MCP (Advanced) Check the VPS health and show Docker container status."
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.
VPS Docker MCP — Advanced
MCP server for Claude Code that provides safe VPS diagnostics and Docker/Docker Compose management over SSH.
Architecture
Claude Code
|
| MCP / stdio
v
Local Python MCP server
|
| SSH / AsyncSSH
v
VPS
|
+-- systemd
+-- Docker
+-- Docker ComposeThe MCP server runs locally. Nothing needs to listen on the VPS.
Module layout
src/vps_docker_mcp/
├── server.py # MCP instance, wires modules together
├── ssh.py # SSH config, run_ssh/run_many helpers
├── docker.py # Docker and Docker Compose tools
├── infrastructure.py # VPS diagnostics tools
├── database.py # PostgreSQL backup and stats tools
└── github.py # GitHub Actions toolsRelated MCP server: VPS-Guardian-MCP
Security model
This project intentionally does not expose arbitrary shell execution.
There is no:
ssh(command)
execute(command)
bash(command)Instead, every operation is a predefined MCP tool.
Arguments such as container and service names are validated with a restrictive allow-list pattern and shell-quoted before being inserted into commands.
SSH host key checking is enabled through VPS_KNOWN_HOSTS.
Use a dedicated non-root SSH account, e.g. deploy, with Docker access.
Credential isolation
SSH key — The VPS SSH key path lives only in .env and is loaded inside ssh.py at connection time. Agents never see the key. Enforced via Claude Code's permissions.deny rules:
"deny": ["Bash(ssh *)", "Bash(scp *)", "Bash(sftp *)", "Bash(rsync *)"]GitHub token — The gh CLI is authenticated on the VPS. All GitHub operations run over SSH through this MCP server. Agents cannot call gh directly. Enforced via:
"deny": ["Bash(gh *)"]Add both deny rules to ~/.claude/settings.json to lock down access.
Requirements
Python 3.11+
uvSSH access
Docker on VPS
Docker Compose v2 if Compose tools are used
deployuser with permission to run DockerghCLI installed and authenticated on the VPS if GitHub Actions tools are used
Installation
uv syncConfigure:
cp .env.example .envExample:
VPS_HOST=YOUR_VPS_IP
VPS_PORT=22
VPS_USER=deploy
VPS_SSH_KEY=~/.ssh/vps_mcp
VPS_KNOWN_HOSTS=~/.ssh/known_hosts
DOCKER_COMPOSE_DIR=/opt/news-bot
GITHUB_REPO=acme/api
MAX_OUTPUT_CHARS=20000Test SSH independently:
ssh -i ~/.ssh/vps_mcp deploy@YOUR_VPS_IP docker psTest MCP:
uv run vps-docker-mcpIt will wait for MCP stdio input. That is expected.
Claude Code configuration
Copy .mcp.json.example to the project-level .mcp.json used by Claude Code and replace the absolute path.
Example:
{
"mcpServers": {
"vps-docker": {
"type": "stdio",
"command": "uv",
"args": [
"--directory",
"/home/me/projects/vps-docker-mcp-advanced",
"run",
"vps-docker-mcp"
]
}
}
}Then start/restart Claude Code and inspect MCP status with:
/mcpDepending on the Claude Code version, MCP servers can also be managed with the Claude Code CLI.
Tool groups
VPS diagnostics
system_infodisk_usagetop_processesnetwork_infosystemd_failedjournal_errorsdiagnose_vps
Docker read-only
docker_psdocker_logsdocker_inspectdocker_statsdocker_healthdocker_imagesdocker_volumesdocker_networksdocker_disk_usage
Docker mutations
docker_restartdocker_startdocker_stop
Docker Compose
Read-only:
docker_compose_psdocker_compose_configdocker_compose_logs
Mutating:
docker_compose_restartdocker_compose_pulldocker_compose_up
Database (PostgreSQL)
Read-only:
postgres_stats— show database sizes, active queries, and optionally top tables by size for a specific databasepostgres_list_backups— list backup files on the server, newest first
Mutating:
postgres_backup_database— dump a single database to a custom-format.dumpfile; restore withpg_restorepostgres_backup_all— dump all databases viapg_dumpall, compressed with gzip; restore withgunzip | psqlpostgres_download_backup— download a backup file from the server to a local directory via SFTP
All tools default to the container, user, and backup directory configured in .env (POSTGRES_CONTAINER, POSTGRES_USER, POSTGRES_BACKUP_DIR).
GitHub Actions
Read-only:
gh_workflow_list— list all workflows in a repogh_run_list— list recent runs, filterable by workflow, status, and limitgh_run_view— show summary and job status for a specific rungh_run_logs— fetch full or failed-only logs for a rungh_job_logs— fetch logs for a single job within a rungh_diagnose_last_run— fetch the most recent run (any status) and show its failed-step logs; answers "why did the last run fail?" in one callgh_diagnose_failure— find the latest failed run and show its error logs in one call
Mutating:
gh_run_cancel— cancel an in-progress rungh_run_rerun— re-run a run, optionally failed jobs only
All tools accept a repo parameter (owner/repo). If omitted, they fall back to the GITHUB_REPO env var.
Restricted diagnostics
diagnostic_command only permits a fixed list:
pwd
whoami
date
df
free
uptime
docker_version
docker_info
It does not accept arbitrary shell syntax.
Example Claude Code requests
Check the VPS health.Claude can use:
diagnose_vpsFor a broken container:
Find out why news-bot is unhealthy.A useful diagnostic sequence is:
docker_health
docker_ps
docker_logs
docker_stats
docker_inspectFor a general resource problem:
Check whether the VPS is running out of RAM or disk space.Claude can inspect:
system_info
disk_usage
top_processes
docker_stats
docker_disk_usageThen:
Restart news-bot if the diagnosis indicates that a restart is appropriate.The restart operation is a separate mutating tool.
For a broken CI build:
Why did the last build fail?Claude can call:
gh_diagnose_failureThis finds the most recent failed run and returns the failed-step logs in one call. To scope it to a specific workflow:
gh_diagnose_failure(workflow="deploy.yml")To browse recent runs and then dig into a specific one:
gh_run_list(status="failure", limit=5)
gh_run_logs(run_id="<id>", failed_only=True)Development
Setup
uv sync
uv pip install -e ".[dev]"Tests
pytest77 tests cover all modules: utils, github, docker, infrastructure, database, and ssh. Tests use a FakeMCP helper that captures registered tool closures without starting a real MCP server. asyncssh.connect is mocked so SSH tests run without a real host.
Lint and type check
ruff check src tests
ruff format src tests
mypy src/vps_docker_mcpPre-commit
pre-commit installRuns ruff check --fix and ruff format on every commit.
CI
GitHub Actions runs on every push to main and on pull requests: checkout → install → ruff → mypy → pytest.
Important production recommendation
Keep Claude Code's own permission/approval mechanism enabled for mutating operations.
The MCP server intentionally labels mutating tools in their descriptions, but MCP itself should not be treated as an authorization boundary.
For a production VPS, do not add arbitrary shell execution unless you deliberately accept the risk.
Future improvements
Good next additions would be:
application-specific health checks
Docker container restart-loop detection
OOM detection
disk growth detection
systemd service restart tools
configurable allow-list of Compose projects
audit logging
command execution timeouts per tool
separate read-only and write SSH credentials
GitHub Actions workflow dispatch (trigger a run)
Available Tools
26 toolsdiagnose_vpsA
Run a compact VPS health check covering resources, disk, systemd and Docker.
Inputs: no named parameters. Returns: result
diagnostic_commandB
Run one of a small predefined set of read-only diagnostic commands.
Inputs: command (required). Returns: result
disk_usageB
Show filesystem space and inode usage.
Inputs: no named parameters. Returns: result
docker_compose_configB
Render and validate the Docker Compose configuration.
Inputs: no named parameters. Returns: result
docker_compose_logsB
Show Docker Compose logs, optionally for one service.
Inputs: tail, service. Returns: result
docker_compose_psC
Show Docker Compose services.
Inputs: no named parameters. Returns: result
docker_compose_pullB
Pull Docker Compose images. This changes local Docker image state.
Inputs: no named parameters. Returns: result
docker_compose_restartB
Restart Docker Compose services. This changes server state.
Inputs: service. Returns: result
docker_compose_upA
Start/update the Docker Compose stack with detached mode. This changes server state.
Inputs: no named parameters. Returns: result
docker_disk_usageB
Show Docker disk usage.
Inputs: no named parameters. Returns: result
docker_healthB
Show container state, restart count and health status.
Inputs: container (required). Returns: result
docker_imagesB
List Docker images.
Inputs: no named parameters. Returns: result
docker_inspectC
Inspect a Docker container.
Inputs: container (required). Returns: result
docker_logsC
Show recent logs from a Docker container.
Inputs: container (required), tail. Returns: result
docker_networksB
List Docker networks.
Inputs: no named parameters. Returns: result
docker_psA
List Docker containers. Set all_containers=true to include stopped containers.
Inputs: all_containers. Returns: result
docker_restartB
Restart a Docker container. This changes server state.
Inputs: container (required). Returns: result
docker_startB
Start a Docker container. This changes server state.
Inputs: container (required). Returns: result
docker_statsA
Show current CPU, memory, network and block I/O usage of containers.
Inputs: no named parameters. Returns: result
docker_stopC
Stop a Docker container. This changes server state.
Inputs: container (required). Returns: result
docker_volumesB
List Docker volumes.
Inputs: no named parameters. Returns: result
journal_errorsC
Show recent system journal errors.
Inputs: hours, lines. Returns: result
network_infoB
Show network interfaces, routes and listening TCP/UDP ports.
Inputs: no named parameters. Returns: result
systemd_failedA
Show failed systemd services.
Inputs: no named parameters. Returns: result
system_infoA
Show VPS uptime, OS, CPU, memory, swap, load and kernel information.
Inputs: no named parameters. Returns: result
top_processesC
Show processes consuming the most CPU and memory.
Inputs: limit. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 26 tools
Most tools have clearly distinct purposes (e.g., docker_ps vs docker_inspect, system_info vs disk_usage). However, diagnose_vps overlaps with several individual system tools, and diagnostic_command is vague, creating some ambiguity.
Tools follow snake_case with clear prefixes (docker_, docker_compose_, system_, etc.). Docker tools use verb_noun pattern, but system tools are mostly noun_noun (e.g., system_info, disk_usage). This mix is not fully consistent but still readable.
26 tools is on the higher side but appropriate for the 'Advanced' scope covering Docker, Docker Compose, and VPS diagnostics. The set is well-scoped, though a few tools could be merged (e.g., diagnose_vps and individual checks).
The tool surface covers monitoring and basic state changes for Docker and VPS, but lacks container creation/removal, Docker Compose down, and deeper system management. The diagnostic_command is undefined. Notable gaps exist for a truly 'Advanced' server.
Related MCP Connectors
Linux server administration over OAuth MCP: shell, Docker, systemd, files and monitoring.
1Scoped, audited SSH exec, sessions, and SFTP on your saved servers without exposing credentials
Manage remote servers, SSH terminals, files, databases and proxies with scoped access and approvals.
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables secure, read-only inspection of a VPS over SSH through approved operations such as system health, disk usage, container logs, and service status, without giving the AI unrestricted shell access.81MIT
- AlicenseAqualityBmaintenanceEnables AI agents to safely monitor Linux VPS health, inspect Docker containers, retrieve service logs, and execute whitelisted recovery actions via MCP.31260 npm35 PyPIMIT
- AlicenseAqualityCmaintenanceEnables MCP clients to inspect and manage a Dokku host over SSH with structured tools, read-only defaults, and explicit guardrails for safe operations.10MIT
- FlicenseNot gradedqualityBmaintenanceEnables controlled diagnostics and limited actions on a VPS through safe, auditable tools instead of an unrestricted root terminal, including read-only checks, basic Docker status, allowed-path file reading/searching, and YAML/JSON validation.-