Skip to main content
Glama
mordanov

VPS Docker MCP (Advanced)

by mordanov

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 Compose

The 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
└── github.py          # GitHub Actions tools

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.

Requirements

  • Python 3.11+

  • uv

  • SSH access

  • Docker on VPS

  • Docker Compose v2 if Compose tools are used

  • deploy user with permission to run Docker

  • gh CLI installed and authenticated on the VPS if GitHub Actions tools are used

Installation

uv sync

Configure:

cp .env.example .env

Example:

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=20000

Test SSH independently:

ssh -i ~/.ssh/vps_mcp deploy@YOUR_VPS_IP docker ps

Test MCP:

uv run vps-docker-mcp

It 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:

/mcp

Depending on the Claude Code version, MCP servers can also be managed with the Claude Code CLI.

Tool groups

VPS diagnostics

  • system_info

  • disk_usage

  • top_processes

  • network_info

  • systemd_failed

  • journal_errors

  • diagnose_vps

Docker read-only

  • docker_ps

  • docker_logs

  • docker_inspect

  • docker_stats

  • docker_health

  • docker_images

  • docker_volumes

  • docker_networks

  • docker_disk_usage

Docker mutations

  • docker_restart

  • docker_start

  • docker_stop

Docker Compose

Read-only:

  • docker_compose_ps

  • docker_compose_config

  • docker_compose_logs

Mutating:

  • docker_compose_restart

  • docker_compose_pull

  • docker_compose_up

GitHub Actions

Read-only:

  • gh_workflow_list — list all workflows in a repo

  • gh_run_list — list recent runs, filterable by workflow, status, and limit

  • gh_run_view — show summary and job status for a specific run

  • gh_run_logs — fetch full or failed-only logs for a run

  • gh_job_logs — fetch logs for a single job within a run

  • gh_diagnose_failure — find the latest failed run and show its error logs in one call

Mutating:

  • gh_run_cancel — cancel an in-progress run

  • gh_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_vps

For a broken container:

Find out why news-bot is unhealthy.

A useful diagnostic sequence is:

docker_health
docker_ps
docker_logs
docker_stats
docker_inspect

For 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_usage

Then:

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_failure

This 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)

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)

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/mordanov/vps_mcp'

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