Skip to main content
Glama

🐳 Docker MCP Server

Chat with your Docker host. A Model Context Protocol server that turns any MCP‑capable AI — Claude Desktop, Cursor, Continue, Zed — into a natural‑language DevOps copilot for Docker & Docker Compose.

“Restart the api container.” · “Why did web crash — show me the last 100 log lines.” · “Deploy the stack in ./prod and confirm it’s healthy.”

CI Node TypeScript MCP Docker npm npm downloads License: MIT

Designed, built & maintained by SoyRage Agency · https://soyrage.es/

⚡ New here? Install in one command → Quick install.


✨ New in this release

🌐

Run it beside the daemon, not on your laptop

MCP normally means one server process per client, on the client's machine — backwards when the daemon you are managing lives on a server. Set DOCKER_MCP_HTTP=true and one instance serves every machine on your network over HTTP. Bearer token, loopback by default. → Run it over the network

🩺

"Is anything wrong?" in one call

host_health checks failing healthchecks, crash loops, containers down despite a restart policy, and disk pressure. find_restart_loops returns the offenders with the tail of their logs. find_unused_resources breaks down what is safe to clean. → Diagnostics

💬

Workflows your client offers you

MCP prompts — debug this container, audit my host, review my Compose file, free up disk. You no longer have to know which tool to ask for. → Guided workflows

See the roadmap for what comes next.


Related MCP server: Docker MCP Server

📑 Table of contents


⚡ Quick install (one command)

Already use an MCP client? Point it at the published package — nothing to clone or build:

"docker": {
  "command": "npx",
  "args": ["-y", "@soyrageagency/docker-mcp"],
  "env": { "DOCKER_MCP_READONLY": "false" }
}

Or open the live web panel straight away: npx -y -p @soyrageagency/docker-mcp docker-mcp-panel

Option A — standalone binary (no Node, no npm) · recommended for the CLI/TUI/panel

Since v1.1 you can install a single self-contained ragedocker executable — a Node runtime and the whole app fused into one file. Nothing else to install.

Windows (PowerShell):

irm https://raw.githubusercontent.com/soyrageagency/docker-mcp-server/main/scripts/install.ps1 | iex

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/soyrageagency/docker-mcp-server/main/scripts/install.sh | sh

Then just run ragedocker for an interactive menu, or ragedocker tui / ragedocker panel / ragedocker ia login. Re-run the installer any time to update. (How it's built and how to reuse this across repos: docs/DISTRIBUTION.md.)

Option B — via Node · configures Claude Desktop for you

Prefer the MCP-server-for-Claude-Desktop path? The installer clones the project, builds it, and configures Claude Desktop for you — no manual JSON editing. You need Git and Node.js ≥ 18.

Windows (PowerShell):

irm https://raw.githubusercontent.com/soyrageagency/docker-mcp-server/main/install.ps1 | iex

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/soyrageagency/docker-mcp-server/main/install.sh | bash

Already cloned the repo? Just run:

npm run setup          # builds + configures Claude Desktop

Then restart Claude Desktop and ask: “What Docker containers are running?” 🎉 The installer backs up your existing config and merges the entry, so any other MCP servers you have are preserved. Prefer to see the snippet without writing anything? node scripts/install.mjs --print.


🧭 What is this?

The Model Context Protocol (MCP) is an open standard that lets AI assistants talk to external tools through a well‑defined JSON‑RPC interface. Docker MCP Server is an MCP server that speaks that protocol over stdio and exposes your Docker host as a set of safe, richly‑described tools.

Point any MCP‑capable assistant at it and you can operate containers and Compose stacks in plain language — the model reads each tool’s schema, decides which to call, and reports the results back to you. No more memorising flags or copy‑pasting container IDs.

In one line: it’s the bridge between “I wish I could just tell my server what to do” and your actual Docker daemon.


💡 Why it exists

Day‑to‑day container work is a stream of small, repetitive commands:

docker ps -a
docker logs --tail 100 -f my-api
docker compose -f ./prod/compose.yaml up -d --build
docker stats my-api

Every one of those is trivial once you remember the exact syntax. The friction is the memorisation and the context‑switching. This server removes that friction by letting the AI do the translation, while keeping you in control through:

  • Read‑only mode for safe demos and production insight.

  • A container allowlist so the assistant can only touch what you allow.

  • Opt‑in exec so arbitrary in‑container commands are never available by accident.

  • Confirmation‑friendly design — destructive tools are clearly described so the model asks before it acts.

Built by SoyRage Agency for the self‑hosting and home‑lab community — and equally at home on a CI runner or a production VM behind read‑only mode.


🚀 Feature overview

Area

Capabilities

🔎 Insight

List containers · inspect full config · live CPU/memory/network stats · tail logs with time windows · list images / networks / volumes · host summary · disk usage.

⚙️ Lifecycle

Start · stop · restart · remove containers — with graceful stop timeouts.

📦 Compose

Validate config · list services & health · deploy (up -d, optional --build) · tear down · restart · pull — via the official docker compose CLI.

🛡️ Safety

Global read‑only mode · container allowlist · opt‑in exec.

🔌 Transport

Local Unix socket · Windows named pipe · secured remote TCP + TLS.

🎨 Identity

ASCII welcome banner · about tool · MCP instructions that credit SoyRage Agency to the AI on connect.

🖥️ Interactive panel

Tabbed web dashboard: live monitoring, terminal with smart command suggestions, file explorer, snapshots & scheduled backups, networks/volumes, auto‑restart watchdog, alerts & log watch, inspect, search and lifecycle actions — with a demo mode.

⌨️ Terminal UI

A creative, lazydocker‑style TUI with a SoyRage welcome, live gauges and one‑key actions — zero curses dependencies.

📈 Monitoring

Built‑in Prometheus /metrics endpoint — scrape it from Prometheus, Grafana, Zabbix, VictoriaMetrics, …

🧩 Modular

Every capability is a toggleable plugin; enable exactly the surface you want via config.

🧱 Engineering

100% TypeScript, strict mode · one module per concern · tiny dependency surface · stderr‑only logging.


🖥️ The interactive panel

Beyond the conversational interface, the project ships a minimalist web dashboard (docker-mcp-panel) for when you want a fast, visual, point‑and‑click view of your host. It reuses the exact same configuration, Docker client and safety rails as the MCP server — so read‑only mode and the allowlist apply here too.

npm run build
ragedocker panel       # → http://127.0.0.1:4600   (or: npm run panel)
npm run panel:demo     # same, but with realistic mock data (no daemon needed)

One command for everything. Since v1.1 a single ragedocker launcher fronts the whole toolkit — run ragedocker with no arguments for an interactive menu, or:

ragedocker tui        # the lazydocker-style terminal dashboard
ragedocker panel      # the web panel + monitoring API
ragedocker mcp        # the MCP server (Claude Desktop, Cursor, Continue…)
ragedocker ia login   # sign in to Claude or ChatGPT (see below)
ragedocker doctor     # check Docker, the AI and your configuration

The original docker-mcp-tui / docker-mcp-panel / docker-mcp-server binaries still work as aliases.

🔑 AI copilot — sign in once with ragedocker ia login

The TUI copilot (press a) and the panel's AI terminal need a model. A short wizard sets one up — pick Claude (Anthropic, used natively) or ChatGPT (OpenAI), paste your key, and it's verified before saving:

ragedocker ia login        # set up your main AI account
ragedocker ia secundaria   # add a second account to switch to
ragedocker ia use secondary
ragedocker ia list         # show what's configured (keys masked)
ragedocker ia test         # call the model once and report back

Keys are stored at ~/.ragedocker/ai.json, owner‑readable only (0600), and are never echoed or logged. The legacy DOCKER_MCP_AI_* environment variables still take precedence for unattended deployments.

Dashboard — live host stats, containers & images

One‑click log tailing

Terminal — run docker commands with smart suggestions (Tab / ↑↓ / Enter)

Snapshots & scheduled backups — with email/cloud delivery

File explorer + editor — view & edit files inside a container

Browse a container's filesystem

System — networks & volumes

Alerts & log watch — with a live auto‑restart watchdog

Read‑only mode — actions safely disabled

Screenshots rendered in demo mode · watermarked © SoyRage Agency · soyrage.es

Panel highlights

  • Tabbed layout — Overview, Terminal, Files, Backups, System and Alerts, with a live alert badge in the header.

  • Live monitoring + Trends — CPU‑load and memory‑used cards with meters, per‑container CPU % and memory bars, and historical sparkline charts (sampled every 5s) for CPU and memory over time.

  • ⌨️ AI‑powered terminal — type docker … for typo‑tolerant, context‑aware completions (Tab/↑↓/Enter), or type a request in plain English (“why did web crash”) and pick Ask AI — the copilot proposes a command you review, then run. Commands are parsed to an argv array and spawned without a shell; a deny‑list blocks dangerous verbs and write verbs respect read‑only mode. AI uses any OpenAI‑compatible endpoint (OpenAI, Ollama, LM Studio…); without one it falls back to rule‑based suggestions.

  • 📁 File explorer + editor — browse any container's filesystem (breadcrumbs, up‑navigation), open and edit text/.sh/config files, and Save back into the container. An AI edit button rewrites the file from a plain‑English instruction. Safe, shell‑free exec; edits are blocked in read‑only mode.

  • 📸 Snapshots & scheduled backups — snapshot a container as an image (commit) or a filesystem export (.tar) to a chosen directory; schedule a daily backup (time, containers, type); a webhook forwards each backup to email, Google Drive or S3 via Zapier / Make / n8n.

  • 🧩 System tab — networks and volumes at a glance; per‑container inspect details (env redacted, mounts, ports, restart policy) in the drawer.

  • ♻️ Auto‑restart watchdog — flip the Auto toggle and a background watchdog restarts a container whenever it exits (respects read‑only mode).

  • 🚨 Alerts & log watch — down/unhealthy containers, high CPU/memory, watchdog events, and error/warn lines scanned from recent logs.

  • Container grid — colour‑coded state dots, ports as chips, filter/search, auto‑refresh toggle, and per‑row actions (details · files · snapshot · start/stop/restart).

  • Prometheus /metrics — footer link exposes the scrape endpoint (see Monitoring).

  • Demo mode — DOCKER_MCP_PANEL_DEMO=true serves fabricated‑but‑realistic data (with gentle live jitter), perfect for previews and client demos with no daemon.

  • Zero UI dependencies — hand‑written HTML/CSS/JS served by a Node‑core HTTP server.

Panel REST API (all local): /api/snapshot · /api/history · /api/containers · /api/images · /api/logs · /api/action · /api/run · /api/ai · /api/files · /api/file (GET read / POST save) · /api/inspect · /api/networks · /api/volumes · /api/backups · /api/backup · /api/schedule · /api/alerts · /api/autorestart · /metrics.

AI copilot (optional): set DOCKER_MCP_AI_ENDPOINT (+ DOCKER_MCP_AI_KEY, DOCKER_MCP_AI_MODEL) to power the AI terminal and AI file‑editing. Works with OpenAI, Ollama (http://localhost:11434/v1, free & local), LM Studio, or any OpenAI‑compatible API. Demo mode simulates it so you can try the UX offline.

🖼️ Regenerate the screenshots yourself with npm run shots (requires npx playwright install chromium).

🔒 Panel security & networking (VPN, IPs, ports)

The panel and terminal can control your host, so treat access like SSH.

  • Bind locally by default — the panel listens on 127.0.0.1:4600. Reach a remote host by tunnelling over a VPN — WireGuard or Tailscale — and browsing to the host's VPN IP. Do not port‑forward the panel to the public Internet.

  • If you must bind to the LAN, set DOCKER_MCP_PANEL_HOST=0.0.0.0. On startup the server prints every IP address it is reachable on and a warning, e.g.:

    Panel ready at http://0.0.0.0:4600
      reachable at http://127.0.0.1:4600
      reachable at http://10.8.0.3:4600      ← your WireGuard IP
      reachable at http://192.168.1.42:4600  ← your LAN IP
    Panel is bound to ALL interfaces … keep it behind a VPN or an authenticated reverse proxy.
  • Change the port with DOCKER_MCP_PANEL_PORT (e.g. 8443) to avoid clashes or sit behind a reverse proxy.

  • Port‑forwarding / reverse proxy — if you expose it, put an authenticated proxy (Caddy/nginx/Traefik with Basic‑Auth or SSO + TLS) in front; never forward the raw port. Combine with DOCKER_MCP_READONLY=true for view‑only deployments, and DOCKER_MCP_PANEL_TERMINAL=false to disable the command runner.


⌨️ The terminal UI (TUI)

Prefer the terminal? Launch docker-mcp-tui — a creative, lazydocker‑style dashboard that opens with a SoyRage Agency welcome and then drops you into a live, keyboard‑driven view. It’s hand‑rolled ANSI (no curses library), so it adds zero dependencies.

ragedocker tui     # → interactive terminal dashboard  (or: npm run tui)
npm run tui:demo   # same, with realistic mock data (no daemon needed)

A warm welcome — “thank you for using our repository ⭐”

Live dashboard — gauges, details & one‑key actions

AI copilot — give an order in plain English

AI copilot. Press a (or :) to open the copilot bar and type what you want — “restart the web container”, “stop the backup job”, “show every container”. The copilot turns it into the exact docker command, shows it to you, and runs it only after you confirm with y. It speaks to any OpenAI‑compatible endpoint (DOCKER_MCP_AI_ENDPOINT / DOCKER_MCP_AI_KEY / DOCKER_MCP_AI_MODEL) and falls back to a built‑in rule engine in demo mode, so you can try it with zero setup.

Action menu. Press Enter (or m) over any container to open a menu of everything you can do to it — logs, inspect, shell, start/stop/restart, snapshot, restore, attach a volume, edit compose, copy id — arrow‑key navigable, so you never have to memorise a key. Every action also has a one‑key shortcut for power users.

Animated status. Containers no longer show a plain red/green dot: healthy ones breathe (●↔◉), starting/restarting ones spin (⠋⠙⠹…), unhealthy ones blink (▲), paused show ⏸, exited ○ — a glance across the list reads like a heartbeat monitor.

Keys: Enter/m menu · ↑/↓ (or j/k) navigate · g/G top/bottom · / filter · o sort (O reverse) · space pause live updates · l logs (f follow, +/- tail) · i inspect · e shell · c edit compose · y copy id · n/v/A networks/volumes/alerts · a AI · S/s/R lifecycle · b snapshot · B restore · V attach volume · u what's new · ? help · q quit. Live CPU/memory gauges refresh automatically; the details pane shows lazydocker‑level info (health, uptime, command, restart policy, networks, mounts, env), lifecycle actions play a spinner animation, and read‑only mode hides the mutating keys (the copilot still explains, but never runs a mutating command).

Update notices. When a new version is published, both the TUI (a banner + u for the changelog) and the web panel (a dismissable banner) tell you — read from a single updates.json in the repo. It's silent on any failure and can be turned off with DOCKER_MCP_NO_UPDATE_CHECK=1.


📈 Monitoring: Prometheus, Zabbix & more

The panel doubles as a metrics exporter. It serves a standard Prometheus text endpoint at /metrics, so your Docker host becomes a first‑class monitoring target with no extra agent.

npm run panel                      # metrics on by default
curl http://127.0.0.1:4600/metrics

Exposed series (labelled by name, state, image where relevant):

Metric

Type

Meaning

dockermcp_up

gauge

1 when the exporter is running.

dockermcp_build_info

gauge

Build/author metadata (product, author = SoyRage Agency, version, url).

dockermcp_host_cpus

gauge

Logical CPUs on the host.

dockermcp_host_memory_bytes

gauge

Total host memory.

dockermcp_containers_total / _running

gauge

Container counts.

dockermcp_images_total

gauge

Cached images.

dockermcp_cpu_percent_total

gauge

Aggregate container CPU %.

dockermcp_memory_used_bytes

gauge

Aggregate container memory.

dockermcp_container_running{…}

gauge

1 if a given container is running.

dockermcp_container_cpu_percent{…}

gauge

Per‑container CPU %.

dockermcp_container_memory_bytes{…}

gauge

Per‑container memory.

dockermcp_container_autorestart{…}

gauge

1 if auto‑restart is enabled for it.

dockermcp_autorestart_enabled

gauge

Count of containers with auto‑restart on.

dockermcp_alerts_active

gauge

Number of active state‑based alerts.

Prometheus

# prometheus.yml
scrape_configs:
  - job_name: docker-mcp
    static_configs:
      - targets: ["your-host:4600"]

Zabbix

Use an HTTP agent item pointed at http://your-host:4600/metrics, then add dependent items with the Prometheus pattern preprocessing step, e.g. dockermcp_containers_running or dockermcp_container_cpu_percent{name="api"}. Grafana, Grafana Agent, VictoriaMetrics and Netdata can scrape the same endpoint.

Turn the exporter off with DOCKER_MCP_PANEL_METRICS=false if you only want the UI.


🧩 Modular plugin architecture

The server is assembled from independent plugins, each owning one capability group. Which plugins load is driven entirely by configuration, so you can expose exactly the surface you want — from insight only to the full toolbox — without touching code. This also makes the project easy to extend.

Plugin

Category

Type

Tools

about 🔒

identity

read

about, list_plugins

containers

insight

read

list_containers, inspect_container, container_stats

logs

insight

read

container_logs

images

insight

read

list_images

system

system

read

system_info, disk_usage, list_networks, list_volumes

compose

compose

read/write

compose_ps, compose_config, deploy_stack, compose_down, compose_restart, compose_pull

lifecycle

lifecycle

write

start/stop/restart/remove_container, exec_in_container

🔒 The about plugin is locked — it carries the SoyRage Agency identity and cannot be disabled.

Toggle plugins via environment variables or the config file:

# Expose ONLY read-only insight (a safe, curated surface)
DOCKER_MCP_PLUGINS=containers,logs,images,system

# Load everything except container lifecycle
DOCKER_MCP_DISABLED_PLUGINS=lifecycle

Ask the assistant “list the plugins” any time to see what’s enabled.

Config file

For a reproducible setup, drop a docker-mcp.config.json in the project root (or point DOCKER_MCP_CONFIG at one). Environment variables always override it. See examples/docker-mcp.config.json:

{
  "readOnly": false,
  "allowExec": false,
  "containerAllowlist": ["web", "api"],
  "plugins": { "enabled": [], "disabled": ["lifecycle"] },
  "panel": { "host": "127.0.0.1", "port": 4600, "demo": false }
}

Configuration precedence (lowest → highest): built‑in defaults → docker-mcp.config.json → .env → real environment variables.


🛠️ How it works

                 ┌──────────────────────────────────────────────┐
   You  ◀──────▶ │  AI assistant (Claude / Cursor / Continue …)  │
                 └───────────────────────┬──────────────────────┘
                              stdio · JSON‑RPC (MCP)
                 ┌───────────────────────▼──────────────────────┐
                 │              Docker MCP Server                │
                 │                                               │
                 │  1. Client sends `initialize` → server        │
                 │     replies with tool schemas + SoyRage       │
                 │     `instructions` (identity & welcome).      │
                 │  2. Model picks a tool and sends `tools/call`.│
                 │  3. Server executes it against Docker and     │
                 │     returns human‑readable text.              │
                 └───────────┬───────────────────────┬──────────┘
                  Engine API  │             spawn      │  docker compose
                 ┌───────────▼───────────┐ ┌──────────▼──────────┐
                 │     Docker Engine      │ │   Compose plugin     │
                 └───────────────────────┘ └─────────────────────┘
  • Engine operations (containers, images, stats, logs, system info) use the Docker Engine API through dockerode.

  • Compose operations shell out to the official docker compose CLI with a shell‑free, fully argument‑quoted spawn (no string interpolation, no injection surface).

  • stdout is sacred: it carries only the JSON‑RPC stream. Every log line goes to stderr.


✅ Requirements

Requirement

Notes

Node.js ≥ 18

ES modules + modern APIs. Node 20+ recommended.

A reachable Docker Engine

Local socket by default; remote TCP/TLS supported.

docker CLI on PATH

Only needed for the Compose tools. Insight/lifecycle tools work without it.

An MCP client

Claude Desktop, Cursor, Continue, Zed, or the MCP Inspector.


📦 Installation

# 1. Clone
git clone https://github.com/<your-user>/docker-mcp-server.git
cd docker-mcp-server

# 2. Install dependencies
npm install

# 3. Build to dist/
npm run build

Kick the tyres with the official MCP Inspector (no AI client required):

npm run inspect

This opens a UI where you can list tools and call them by hand — perfect for verifying your Docker connection before wiring up an assistant.


🔌 Connecting to your AI client

Claude Desktop

Edit your Claude Desktop config file:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "docker": {
      "command": "npx",
      "args": ["-y", "@soyrageagency/docker-mcp"],
      "env": {
        "DOCKER_MCP_READONLY": "false",
        "DOCKER_MCP_ALLOW_EXEC": "false",
        "DOCKER_MCP_DEFAULT_LOG_TAIL": "200"
      }
    }
  }
}

A ready‑to‑edit copy lives in examples/claude_desktop_config.json.

No install step needed: npx fetches the package on first run and keeps it up to date. Restart Claude Desktop and ask: “What containers are running?”

Cursor / Continue / Zed

Any MCP‑capable client works the same way — register a stdio server whose command is npx with the arguments -y @soyrageagency/docker-mcp, passing the same environment variables. Consult your client’s MCP documentation for the exact config location; the server block is identical.


🌐 Run it over the network (HTTP)

By default an MCP server talks over stdio: your AI client starts a copy of it as a child process, on your machine. That is fine for a laptop tool and awkward for a homelab, where the Docker daemon lives on a server — and where you probably want your desktop and your laptop talking to the same thing.

Set one variable and it serves Streamable HTTP instead:

DOCKER_MCP_HTTP=true DOCKER_MCP_HTTP_TOKEN="$(openssl rand -hex 32)" npx -y @soyrageagency/docker-mcp

Then point any MCP client at it:

{
  "mcpServers": {
    "docker": {
      "type": "http",
      "url": "http://10.0.0.5:8620/mcp",
      "headers": { "Authorization": "Bearer <the token you generated>" }
    }
  }
}

Variable

Default

What it does

DOCKER_MCP_HTTP

false

Serve over HTTP instead of stdio.

DOCKER_MCP_HTTP_HOST

127.0.0.1

Interface to bind. Use 0.0.0.0 only behind a VPN.

DOCKER_MCP_HTTP_PORT

8620

TCP port.

DOCKER_MCP_HTTP_PATH

/mcp

Endpoint path.

DOCKER_MCP_HTTP_TOKEN

(none)

Bearer token required on every request. Set this.

DOCKER_MCP_HTTP_ALLOWED_HOSTS

derived

Host headers accepted (DNS-rebinding protection).

DOCKER_MCP_HTTP_ALLOWED_ORIGINS

(none)

Origin values accepted, for browser clients.

Read this before you expose it. The Docker socket is root on your host, so anyone who can reach this port can do anything to it. It binds loopback by default and warns loudly if you start it without a token. Put it behind your VPN, and consider pairing it with DOCKER_MCP_READONLY=true or a container allowlist for anything you do not fully trust.

There is also GET /health, which needs no token, for container healthchecks.


🩺 Diagnostics

Three read-only tools aimed at the questions you actually ask, rather than at the API surface:

host_health — one call that answers is anything wrong? Failing healthchecks, containers crash-looping, containers that are down despite a restart policy (the failure nobody notices), and disk pressure from reclaimable images and volumes. Findings ranked by severity, not a data dump.

find_restart_loops — the containers that keep dying, with the exit code and the tail of their logs, which is where the reason almost always is. It saves the usual ps → inspect → logs round trip that takes three messages.

find_unused_resources — what is safe to clean and what it would return, split into images, volumes and long-dead containers. It refuses to be glib about volumes: an unreferenced volume is very often the database of a stack you stopped on purpose, and docker volume prune is not undoable.

All three are read-only, so they stay available with DOCKER_MCP_READONLY=true.


💬 Guided workflows (prompts & resources)

Tools only answer a question you already knew how to ask. MCP prompts are the other half: your client lists them, so the workflow is discoverable without knowing which tool to reach for or in what order.

Prompt

What it does

debug-container

Works out why a container is unhealthy or restarting, from its logs, config and environment — and says so when the logs do not actually support a conclusion.

audit-host

Read-only sweep of health, waste and risky configuration. Narrow it with health, disk or security.

review-compose

Reads your Compose file and points out what bites later: latest tags, missing healthchecks, state not in a volume, ports on 0.0.0.0, secrets in the file.

free-up-disk

Finds reclaimable space and ranks it by space returned ÷ risk.

Each prompt also tells the assistant what a good answer looks like: verdict first, findings ranked, no padding, and an explicit instruction not to change anything.

Resources expose the host as attachable context, so the model can be handed the current picture instead of spending three tool calls rebuilding it:

  • docker://host/overview — containers, images and disk usage in one snapshot.

  • docker://server/capabilities — which plugins are loaded, whether the server is read-only, whether exec is allowed, and what the allowlist permits.


⚙️ Configuration reference

Every setting is an environment variable. A local .env file (next to package.json) is loaded automatically at startup; values already present in the process environment always win, so your MCP client can override the file. See .env.example for a commented template.

Variable

Default

Description

DOCKER_HOST

platform socket

Engine endpoint. Accepts unix:///var/run/docker.sock, npipe:////./pipe/docker_engine, or tcp://host:port. Empty = platform default.

DOCKER_CERT_PATH

—

Directory containing ca.pem, cert.pem, key.pem for a TLS‑secured remote daemon.

DOCKER_TLS_VERIFY

false

1/true to verify the daemon certificate (recommended for remote hosts).

DOCKER_MCP_READONLY

false

When true, all state‑changing tools are hidden — the server exposes insight only.

DOCKER_MCP_ALLOW_EXEC

false

When true, registers the exec_in_container tool (arbitrary in‑container commands).

DOCKER_MCP_CONTAINER_ALLOWLIST

—

Comma‑separated container names or prefixes the server may operate on. Empty = all. Prefix matching means web covers web-1, web-2.

DOCKER_MCP_DEFAULT_LOG_TAIL

200

Default number of log lines returned by container_logs when tail is omitted.

DOCKER_MCP_COMPOSE_CWD

process cwd

Base directory used to resolve relative Compose file paths.

DOCKER_MCP_LOG_LEVEL

info

Diagnostic verbosity written to stderr: debug | info | warn | error.

DOCKER_MCP_PLUGINS

—

Load only these plugins (comma‑separated). Empty = all.

DOCKER_MCP_DISABLED_PLUGINS

—

Disable these plugins (comma‑separated). about is locked.

DOCKER_MCP_PANEL_HOST

127.0.0.1

Bind address for the interactive panel.

DOCKER_MCP_PANEL_PORT

4600

Port for the interactive panel.

DOCKER_MCP_PANEL_DEMO

false

Serve fabricated demo data in the panel/TUI.

DOCKER_MCP_PANEL_METRICS

true

Expose the Prometheus /metrics endpoint.

DOCKER_MCP_PANEL_TERMINAL

true

Enable the in‑panel command terminal.

DOCKER_MCP_BACKUP_DIR

./snapshots

Directory for container snapshots/exports.

DOCKER_MCP_BACKUP_WEBHOOK

—

Webhook called after each backup (email/cloud bridge).

DOCKER_MCP_AI_ENDPOINT

—

OpenAI‑compatible base URL for the AI copilot (empty = off).

DOCKER_MCP_AI_KEY

—

Bearer key for the AI endpoint.

DOCKER_MCP_AI_MODEL

gpt-4o-mini

Model name for the AI endpoint.

DOCKER_MCP_CONFIG

docker-mcp.config.json

Path to the optional JSON config file.

Boolean parsing: any of 1, true, yes, on (case‑insensitive) counts as true. A JSON config file provides defaults for all of the above — see Config file.


🌐 Connecting to remote / TLS daemons

Manage a Docker host over the network by pointing DOCKER_HOST at its TCP endpoint. For anything beyond localhost, always use TLS.

# Plain TCP (trusted networks only!)
DOCKER_HOST=tcp://192.168.1.50:2375

# Secured TCP with mutual TLS
DOCKER_HOST=tcp://docker.internal:2376
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/home/you/.docker/certs

When TLS is enabled the server reads ca.pem, cert.pem and key.pem from DOCKER_CERT_PATH and connects over HTTPS (default port 2376; plain TCP defaults to 2375).


🛡️ Security model

This server can control your infrastructure, so it ships with defence‑in‑depth defaults. You decide how much power to grant.

Control

What it does

Recommended for

Read‑only mode (DOCKER_MCP_READONLY=true)

Hides every state‑changing tool. The model literally cannot see stop, remove, deploy_stack, etc.

Demos, dashboards, production insight.

Container allowlist (DOCKER_MCP_CONTAINER_ALLOWLIST)

Restricts all container tools to matching names/prefixes. Anything else returns a clear “not allowed” error.

Multi‑tenant hosts, “manage the app, never the database”.

Opt‑in exec (DOCKER_MCP_ALLOW_EXEC)

The powerful exec_in_container tool is not registered unless you enable it.

Keep disabled unless you specifically need it.

Shell‑free Compose

Compose commands are spawned as argument arrays — no shell, no interpolation.

Always on.

Graceful errors

A failing tool returns an isError text result instead of crashing the transport, so a bad call never takes the session down.

Always on.

Safety recipes

# Give a live demo with zero risk of mutation
DOCKER_MCP_READONLY=true

# Let the AI manage only the app tier, never data stores
DOCKER_MCP_CONTAINER_ALLOWLIST=web,api,worker

# Never allow shelling into containers (this is the default)
DOCKER_MCP_ALLOW_EXEC=false

⚠️ Principle of least privilege. Start read‑only, add an allowlist, and only enable writes/exec once you trust the setup. Treat the assistant as a very fast junior engineer: helpful, but you sign off on the destructive stuff.


🧰 Complete tool reference

Tools marked W change state and are hidden when DOCKER_MCP_READONLY=true. exec_in_container is additionally hidden unless DOCKER_MCP_ALLOW_EXEC=true.

Identity

Tool

Parameters

Description

about

—

Returns the welcome banner, version and credits.

list_plugins

—

Lists the modular capability plugins and whether each is enabled.

Insight (read‑only)

Tool

Parameters

Description

list_containers

all?: boolean

List containers with state, image, status and published ports. all includes stopped ones.

inspect_container

container: string

Full low‑level config for one container (env, mounts, network, restart policy, health) plus a readable summary.

container_stats

container: string

One‑shot snapshot of live CPU %, memory usage/limit and network RX/TX.

container_logs

container: string, tail?: number, since?: string, timestamps?: boolean

Tail stdout/stderr. since accepts a Unix timestamp or a relative value like 10m, 2h, 1d. Docker stream headers are demultiplexed automatically.

list_images

—

Locally cached images with repo:tag, short ID, size and age; plus total disk footprint.

system_info

—

Engine version, host OS/arch, kernel, CPU/RAM, storage driver and object counts.

disk_usage

—

Reclaimable space across images/containers/volumes (docker system df).

list_networks

—

Networks with driver and scope.

list_volumes

—

Named volumes with driver and mountpoint.

Compose — read‑only

Tool

Parameters

Description

compose_ps

file: string, project?: string

List a stack’s services and their state/health. file is a compose file or a directory containing one.

compose_config

file, project?

Validate and render the fully‑resolved Compose configuration (a non‑zero result means the file has errors).

Lifecycle (W)

Tool

Parameters

Description

start_container

container

Start a stopped container (no‑op if already running).

stop_container

container, timeout?: number

Graceful stop (SIGTERM → SIGKILL after timeout seconds, default 10).

restart_container

container, timeout?: number

Restart a container.

remove_container

container, force?: boolean, removeVolumes?: boolean

Remove a container. Destructive; force required if running.

exec_in_container

container, command: string[], workdir?: string

Run a one‑off command (argument array, no shell) inside a running container. Opt‑in only.

Compose — state‑changing (W)

Tool

Parameters

Description

deploy_stack

file, project?, build?: boolean, services?: string[]

docker compose up -d --remove-orphans — deploy/refresh a stack, optionally rebuilding and scoped to services.

compose_down

file, project?, removeVolumes?: boolean

Stop and remove a stack. removeVolumes also deletes named volumes (destructive).

compose_restart

file, project?, services?: string[]

Restart all or selected services.

compose_pull

file, project?, services?: string[]

Pull the latest images for a stack (pair with deploy_stack for a rolling update).


💬 Example conversations

Natural‑language prompts and the tools the model will typically reach for:

You say…

The assistant calls…

“What’s running right now?”

list_containers

“Show me everything, including stopped ones.”

list_containers { all: true }

“Why did api crash? Last 100 lines.”

container_logs { container: "api", tail: 100 }

“Anything in the web logs from the last 15 minutes?”

container_logs { container: "web", since: "15m" }

“Is db using a lot of memory?”

container_stats { container: "db" }

“Restart nginx.”

restart_container { container: "nginx" }

“Deploy the stack in ./prod and rebuild.”

deploy_stack { file: "./prod", build: true }

“Which services are up in the demo stack?”

compose_ps { file: "examples/demo-stack" }

“How much disk is Docker using?”

disk_usage

“Who built this integration?”

about

Want a stack to practise on? examples/demo-stack/compose.yaml spins up nginx + redis. Try: “Deploy the demo stack, then show me its services and the web logs.”


🗂️ Project structure

docker-mcp-server/
├── assets/
│   ├── soyrage-banner.svg    # SoyRage Agency identity banner (this README)
│   └── screenshots/          # Watermarked panel screenshots
├── examples/
│   ├── claude_desktop_config.json
│   ├── docker-mcp.config.json  # Reproducible config-file example
│   └── demo-stack/
│       └── compose.yaml      # nginx + redis playground
├── install.sh / install.ps1  # One-command bootstrap for beginners
├── scripts/
│   ├── install.mjs           # Cross-platform Claude Desktop configurator
│   ├── copy-public.mjs       # Copies panel assets into dist/ after build
│   ├── shots.mjs             # Regenerates the panel screenshots (Playwright)
│   └── tui-shot.mjs          # Renders the TUI to PNG (ANSI→HTML→Playwright)
├── src/
│   ├── index.ts              # MCP entry point: banner, wiring
│   ├── branding.ts           # SoyRage identity, ASCII banner, MCP instructions
│   ├── plugins.ts            # Modular plugin catalogue & selection loader
│   ├── config.ts             # Layered config (defaults → file → .env → env)
│   ├── logger.ts             # stderr‑only structured logger (stdout is sacred)
│   ├── docker/
│   │   ├── client.ts         # Typed dockerode wrapper + allowlist enforcement
│   │   └── compose.ts        # Safe, shell‑free `docker compose` driver
│   ├── tools/                # One module per plugin's tools
│   │   ├── context.ts        # Shared dependency bundle + plugin metadata
│   │   ├── about.ts          # about / list_plugins (identity, locked)
│   │   ├── containers.ts     # list / inspect / stats
│   │   ├── logs.ts           # log tailing with stream demultiplexing
│   │   ├── lifecycle.ts      # start / stop / restart / remove / exec
│   │   ├── images.ts         # image inventory
│   │   ├── system.ts         # system_info / disk_usage / networks / volumes
│   │   └── compose.ts        # deploy / down / restart / pull / ps / config
│   ├── panel/                # Interactive web dashboard
│   │   ├── index.ts          # Panel entry point (docker-mcp-panel binary)
│   │   ├── server.ts         # Node‑core HTTP server + REST API + /metrics
│   │   ├── service.ts        # UI/monitoring data layer, stats & Prometheus
│   │   └── public/           # Hand‑written SPA (index.html, styles.css, app.js)
│   ├── tui/                  # Terminal UI (docker-mcp-tui binary)
│   │   ├── index.ts          # TUI entry point (+ --frame/--splash snapshots)
│   │   ├── app.ts            # Interactive app: welcome, gauges, key handling
│   │   ├── box.ts            # Rounded box renderer
│   │   └── ansi.ts           # ANSI colours, cursor control, width-aware pads
│   └── utils/
│       ├── format.ts         # tables, byte & time humanisers
│       └── result.ts         # MCP result helpers + error guard
├── docker-mcp.config.json    # (optional) your config file
├── .env.example              # Commented configuration template
├── LICENSE                   # MIT License
└── README.md

🧠 Design principles

  1. stdout is reserved for the JSON‑RPC protocol stream; every diagnostic goes to stderr. Violating this corrupts the MCP connection — the logger enforces it.

  2. No shell interpolation. Compose commands are spawned with an argument array, never a shell string, eliminating command‑injection risk.

  3. Fail soft. A handler that throws returns a clean isError text result the model can read and recover from, instead of tearing down the transport.

  4. One concern per module. Tools are grouped by capability; each group is a small, focused file that receives its dependencies explicitly (no globals).

  5. Tiny dependency surface. A hand‑rolled .env loader keeps dotenv out; only @modelcontextprotocol/sdk, dockerode and zod are runtime dependencies.

  6. Safety by construction. Read‑only mode and the allowlist are checked at the boundary, so an unsafe call can’t slip through a forgotten branch.


🧪 Development

npm run dev        # hot‑reload the MCP server with tsx
npm run typecheck  # strict type check, no emit
npm run build      # compile to dist/ and copy panel assets
npm run start      # run the built MCP server
npm run inspect    # launch the MCP Inspector against the built server
npm run panel      # run the interactive panel (with /metrics)
npm run panel:dev  # hot‑reload the panel with tsx
npm run panel:demo # run the panel with demo data
npm run tui        # run the terminal UI
npm run tui:demo   # run the terminal UI with demo data
npm run shots      # regenerate panel screenshots (needs Playwright chromium)
npm run clean      # remove dist/

Coding standards: TypeScript strict with noUnusedLocals, noUnusedParameters, noImplicitReturns and noFallthroughCasesInSwitch.

Continuous integration: .github/workflows/ci.yml runs on every push/PR — install, type‑check, build, then the deep end‑to‑end suite (node scripts/deep-test.mjs, 70 checks) against a headless demo panel. Run it locally anytime:

npm run build
DOCKER_MCP_PANEL_DEMO=true DOCKER_MCP_PANEL_PORT=4600 node dist/panel/index.js &
node scripts/deep-test.mjs

🩺 Troubleshooting & FAQ

The server started but couldn’t connect to Docker. Check that:

  • Docker Desktop / the daemon is running.

  • DOCKER_HOST is correct for your platform (empty = default socket).

  • On Linux, your user can access the socket (docker group) or you’re running with sufficient permissions.

The server intentionally keeps running so tool calls return a friendly error inside your chat client instead of crashing.

The Compose tools shell out to docker compose. Install Docker Desktop or the docker-compose-plugin, and make sure docker is on the PATH of the environment your MCP client launches the server in.

You’re probably in read‑only mode. Set DOCKER_MCP_READONLY=false (the default) and restart your MCP client so it re‑reads the tool list.

DOCKER_MCP_CONTAINER_ALLOWLIST is set and the target doesn’t match. Add its name/prefix to the list, or clear the variable to allow all.

No. This server talks only to your Docker daemon and your MCP client over local stdio. It makes no outbound network calls of its own.


🗺️ Roadmap

The full roadmap — what is shipped, what is next, and what is deliberately not planned — lives in ROADMAP.md.

The short version: a multi-arch ghcr.io image and a socket-proxy recipe, then finer-grained permissions than the current read-only/read-write switch. Image update checking and metrics history are further out because doing them badly means confidently wrong answers.

Explicitly not planned: replacing Portainer, autonomous action without confirmation, and telemetry of any kind.


🤝 Contributing

Contributions are welcome! Please:

  1. Open an issue describing the change before large PRs.

  2. Keep the stderr‑only logging and shell‑free Compose invariants intact.

  3. Run npm run typecheck && npm run build before submitting.


🏢 About SoyRage Agency

SoyRage Agency is a full‑stack development & infrastructure studio based in Valencia, Spain, building tools where DevOps meets AI. We craft polished, production‑minded software for developers and the self‑hosting community.

  • 🌐 Web: soyrage.es

  • 🧑‍💻 Focus: full‑stack development · infrastructure engineering · AI tooling

  • 📫 Work with us: soyrage.es

If this project is useful to you, a ⭐ on the repo and a link back to soyrage.es genuinely help us keep building in the open. Thank you! 🙌


🧰 More from the SoyRage self‑hosting suite

Docker MCP Server is part of a family of open‑source infrastructure tools built with the same care — same design language, same safety‑first defaults, same "chat with your infra" philosophy:

Project

What it does

🐳 Docker MCP Server

(you are here) Chat with your Docker host — containers, logs, Compose, a live panel & a TUI copilot.

🖧 Proxmox MCP Server

Chat with your Proxmox VE cluster — nodes, VMs & LXC, snapshots and full guest CRUD, plus a tabbed terminal dashboard with an AI command bar.

🚚 VMware → Proxmox Toolkit (V2P)

Leaving vSphere after the Broadcom price hikes? Inventory vCenter, score compatibility, estimate cost & time, plan disk conversion and export a professional PDF assessment.

🗺️ NetAtlas

Living infrastructure documentation — agentless discovery that auto-generates a network diagram, inventory, VLAN & service-dependency maps, and tells you what changed since last time.

🛡️ MailAegis

Corporate email threat analyzer — VirusTotal, ClamAV and an in-house phishing/BEC engine, inside a mail client.


💙 Support the project

Docker MCP Server is free and MIT licensed. If it saves you time, you can support development on PayPal — a ⭐ on the repo helps just as much.


🖋️ Credits & License

Designed, built and maintained by SoyRage Agency — https://soyrage.es/

Released under the MIT License — use it, modify it, self-host it, ship it commercially.

If you build something on top of it, a link back to soyrage.es is appreciated but never required.

© 2026 SoyRage Agency — https://soyrage.es/

Made with ❤ in Valencia, Spain.

Available Tools

21 tools
aboutAbout this serverA

Show who built this Docker MCP Server and how it is licensed. Call this to greet the user with the SoyRage Agency welcome banner, or whenever they ask who made this integration.

Inputs: no named parameters.

compose_configCompose: validate configA

Validate a Compose file and render its fully-resolved configuration (interpolated variables, merged overrides). A non-zero result means the file has errors.

Inputs: file (required), project.

compose_downCompose: tear down stackA

Stop and remove a Compose stack (compose down). Set removeVolumes to also delete named volumes — destructive.

Inputs: file (required), project, removeVolumes.

compose_psCompose: list servicesA

List the services defined by a Compose stack and their current state/health. Point file at the compose file or its directory.

Inputs: file (required), project.

compose_pullCompose: pull imagesA

Pull the latest images referenced by a stack without starting it. Pair with deploy_stack to perform a rolling update.

Inputs: file (required), project, services.

compose_restartCompose: restart servicesA

Restart all services in a stack, or only the ones you name.

Inputs: file (required), project, services.

container_logsRead container logsA

Fetch the most recent log lines from a container's stdout/stderr. Use this to diagnose crashes, watch startup output or confirm a deployment. Supports an optional time window via since.

Inputs: container (required), tail, since, timestamps.

container_statsContainer resource statsA

Take a one-shot snapshot of a container's live CPU %, memory usage and network I/O. Useful to answer 'why is my server slow?'.

Inputs: container (required).

deploy_stackCompose: deploy stackA

Deploy or update a Compose stack in the background (compose up -d). Optionally rebuild images and/or scope to specific services. This is the one-shot 'ship it' action.

Inputs: file (required), build, project, services.

disk_usageDisk usageA

Report Docker disk usage across images, containers and volumes (equivalent to docker system df), highlighting reclaimable space.

Inputs: no named parameters.

inspect_containerInspect containerA

Return the full low-level configuration of a single container (environment, mounts, network settings, restart policy, health, …). Accepts a container name, short id or full id.

Inputs: container (required).

list_containersList containersA

List Docker containers with their status, image, ports and uptime. By default only running containers are shown; set all to include stopped ones. This is the best starting point to understand what is deployed on the host.

Inputs: all.

list_imagesList imagesA

List Docker images cached on the host, including repository:tag, size and how long ago they were created. Handy for spotting stale or oversized images before a cleanup.

Inputs: no named parameters.

list_networksList networksA

List Docker networks with their driver and scope. Useful to understand how containers can reach one another.

Inputs: no named parameters.

list_pluginsList pluginsA

Show the modular capability plugins this server exposes and whether each is currently enabled. Handy to understand what the AI can do.

Inputs: no named parameters.

list_volumesList volumesA

List named Docker volumes and their storage driver. These persist data beyond a container's lifecycle.

Inputs: no named parameters.

remove_containerRemove containerA

Remove a container. Requires force to remove a running one. This is destructive and cannot be undone — prefer stopping first.

Inputs: container (required), force, removeVolumes.

restart_containerRestart containerC

Restart a container. This is the go-to fix for 'turn it off and on again' style requests.

Inputs: container (required), timeout.

start_containerStart containerA

Start a stopped container. No-op if it is already running. Returns the resulting state.

Inputs: container (required).

stop_containerStop containerA

Gracefully stop a running container (SIGTERM, then SIGKILL after a grace period). No-op if it is already stopped.

Inputs: container (required), timeout.

system_infoSystem infoA

Summarise the Docker daemon: engine version, host OS/architecture, CPU and memory available, and how many containers/images exist. Use this to answer 'what does this server look like?'.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 21 tools

    Disambiguation5/5

    Each tool has a clear, distinct purpose. Compose tools (e.g., compose_config, compose_down) handle separate stack operations, and container lifecycle tools (list_containers, start_container, stop_container, etc.) are each focused on specific tasks. No two tools overlap in function.

    Naming Consistency3/5

    Naming is mixed: some tools follow a verb_noun pattern (list_containers, start_container), while others are noun_verb (compose_down, container_logs) or atypical (about, disk_usage). This inconsistency may cause confusion for agents trying to predict tool names.

    Tool Count5/5

    21 tools is well-scoped for a Docker management server. It covers container lifecycle, Compose stacks, system info, and utilities without being overly numerous or sparse.

    Completeness3/5

    Core container and Compose operations are covered, but notable gaps exist: no volume create/remove, no network create/remove, no image build or generic pull, and no exec/run command. This limits the ability to perform some common Docker workflows.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables natural language management of Docker containers, images, networks, and volumes with support for both local and remote Docker engines. Features automated container composition, debugging capabilities, and persistent data management through an intuitive conversational interface.
      GPL 3.0
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to manage Docker containers, deploy stacks, and monitor services across multiple Docker hosts from one centralized location. Supports container lifecycle management, Docker Compose operations, and infrastructure orchestration through natural language commands.
      6
      MIT
    • A
      license
      Not graded
      quality
      Not graded
      maintenance
      Enables AI assistants to interact with Docker containers through safe, permission-controlled access to inspect, manage, and diagnose containers, images, and compose services with built-in timeouts and AI-powered analysis.
      -