Skip to content

About

MCP server for Komodo Docker/container management

Resources

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

Komodo MCP Server

An MCP (Model Context Protocol) server that exposes Komodo — a Docker/container management and deployment system — to AI assistants.

Highlights

  • 35 tools across read / execute / write categories
  • Streamable HTTP transport (default) per the latest MCP spec, plus legacy SSE and stdio
  • Per-session McpServer — concurrent clients are isolated
  • Official komodo_client 2.1.1 for the upstream API contract
  • Bearer-token auth with constant-time compare; loopback-only fallback when no token is configured
  • DNS-rebinding defense via a default Host allow-list and an optional Origin allow-list
  • Helmet security headers; CORS allow-list
  • Pino structured logs with Authorization/X-Api-Secret/X-Api-Key redaction
  • Graceful shutdown on SIGTERM/SIGINT
  • Strict input schemas: bounded tail, terms, compose_contents, and contents; update configs reject keys beginning with API-key, API-secret, password, secret, webhook-secret, or token variants
  • Shared upstream adapter with Undici pooling, an absolute timeout, a 16 MiB response cap, p-limit concurrency control, and secret redaction; requests are not retried

Quick Start

Local (loopback) with Docker Compose

git clone https://github.com/nicolasestrem/komodo-mcp.git
cd komodo-mcp
export KOMODO_ADDRESS=http://host.docker.internal:9120
export KOMODO_API_KEY='YOUR_KEY'
export KOMODO_API_SECRET='YOUR_SECRET'
export MCP_AUTH_TOKEN="$(openssl rand -hex 32)"
docker compose up -d

Plain docker compose automatically loads the local-development override and passes these environment variables into the container. The container binds 0.0.0.0:3113 internally but docker-compose.yml publishes the port only to host loopback (127.0.0.1:3113:3113). Docker requests still cross a container-network boundary, so use the generated bearer token. Front the service with a reverse proxy when you need network access.

Add to Claude Code (.mcp.json)

Local npm process / loopback (no token needed when MCP_AUTH_TOKEN is unset):

{
  "mcpServers": {
    "komodo": {
      "type": "http",
      "url": "http://127.0.0.1:3113/mcp"
    }
  }
}

Docker (token required):

{
  "mcpServers": {
    "komodo": {
      "type": "http",
      "url": "http://127.0.0.1:3113/mcp",
      "headers": { "Authorization": "Bearer ${MCP_AUTH_TOKEN}" }
    }
  }
}

For a networked deployment, replace the URL with the TLS endpoint exposed by your reverse proxy.

Local development (npm)

npm install
npm run build
npm start         # default streamable HTTP on 127.0.0.1:3113
npm run dev:sse   # legacy SSE transport with a dev token

Configuration

Komodo upstream

Variable Description Default
KOMODO_ADDRESS Komodo Core URL (http(s) only; trailing slash normalized); also reads from KOMODO_ADDRESS_FILE required
KOMODO_API_KEY API key — also reads from KOMODO_API_KEY_FILE for Docker secrets required
KOMODO_API_SECRET API secret — also reads from KOMODO_API_SECRET_FILE required
KOMODO_TIMEOUT_MS Absolute per-request timeout 30000
KOMODO_MAX_CONCURRENCY In-flight request semaphore 8
KOMODO_MAX_RESPONSE_BYTES Maximum upstream response body size 16777216 (16 MiB)

MCP server

Variable Description Default
MCP_TRANSPORT streamable (default), sse (legacy), or stdio streamable
MCP_PORT HTTP listener port 3113
MCP_BIND_HOST Host to bind on 127.0.0.1 (use 0.0.0.0 inside Docker)
MCP_AUTH_TOKEN Bearer token (also MCP_AUTH_TOKEN_FILE). When unset, only loopback callers are admitted. unset
MCP_ALLOWED_ORIGINS Comma-separated Origin allow-list (browser CSRF defense). Empty = no Origin enforcement. unset
MCP_ALLOWED_HOSTS Comma-separated Host-header allow-list (DNS-rebinding defense). 127.0.0.1,localhost
MCP_MAX_SESSIONS Maximum simultaneous HTTP sessions; invalid values fall back to the default 100
MCP_SESSION_IDLE_TIMEOUT_MS Idle lifetime for HTTP sessions before cleanup 1800000 (30 minutes)
LOG_LEVEL Pino log level info

Getting Komodo API credentials

  1. Open the Komodo web UI
  2. Go to Settings → API Keys
  3. Click Create API Key, copy the key and secret

Security model

This server holds Komodo admin credentials. A successful tool call can deploy code, prune systems, or destroy stacks on every Komodo-managed host. Treat it as privileged.

The defaults aim for "secure by accident":

  • Bind is 127.0.0.1 unless explicitly opened.
  • MCP_AUTH_TOKEN is required for any non-loopback caller.
  • The default Host allow-list blocks DNS rebinding even if a browser is tricked into reaching the loopback port; MCP_ALLOWED_ORIGINS adds optional browser Origin enforcement.
  • All requests, including loopback, go through Helmet + CORS.
  • Errors emitted to MCP clients have the API key/secret scrubbed from upstream bodies.

For non-loopback deployments use a reverse proxy that terminates TLS, set a random MCP_AUTH_TOKEN (openssl rand -hex 32), and configure MCP_ALLOWED_HOSTS/MCP_ALLOWED_ORIGINS for your domain. See docs/DEPLOYMENT.md and docs/RUNBOOK.md.

Available tools

35 tools are registered from a single declarative table in src/tools/registry.ts. Read tools carry readOnlyHint and idempotentHint; start/stop/restart and pull operations carry idempotentHint; prune/destroy/delete and komodo_write_stack_contents carry destructiveHint. Exact operation mappings and schemas are in docs/API.md.

Read (15)

Tool Description
komodo_list_servers List all connected servers
komodo_list_stacks List stacks with state
komodo_list_deployments List deployments
komodo_get_stack Stack details
komodo_get_stack_log Stack deployment logs
komodo_get_container_log Container logs (tail 1–5000, default 100)
komodo_list_containers Containers on a server
komodo_inspect_container Inspect a container
komodo_get_system_stats CPU/memory/disk for a server
komodo_list_images Docker images
komodo_list_networks Docker networks
komodo_list_volumes Docker volumes
komodo_get_alerts Komodo alerts
komodo_search_logs Search container logs (1–20 terms, max 256 chars each)
komodo_get_stack_services Stack services summary (requires stack)

Execute (12)

Tool Hint Description
komodo_deploy_stack non-idempotent Deploy/redeploy a stack
komodo_start_stack idempotent Start a stopped stack
komodo_stop_stack idempotent Stop a running stack
komodo_restart_stack idempotent Restart a stack
komodo_destroy_stack destructive Stop and remove
komodo_pull_stack idempotent Pull latest images
komodo_start_container idempotent Start a container
komodo_stop_container idempotent Stop a container
komodo_restart_container idempotent Restart a container
komodo_prune_images destructive Prune unused images
komodo_prune_networks destructive Prune unused networks
komodo_prune_system destructive Full Docker system prune

Write (8)

Tool Hint Description
komodo_create_stack non-idempotent Create a stack
komodo_update_stack non-idempotent Update stack config (rejects secret-like keys)
komodo_delete_stack destructive Delete a stack
komodo_write_stack_contents destructive Overwrite compose contents; requires stack, file_path, and contents (max string length 256,000)
komodo_create_server non-idempotent Add a server
komodo_update_server non-idempotent Update server config (rejects secret-like keys)
komodo_delete_server destructive Remove a server
komodo_rename_stack non-idempotent Rename a stack

Example prompts

  • "List all my Komodo stacks"
  • "Show me the logs for the nginx stack"
  • "Restart the wordpress stack"
  • "What containers are running on my server?"
  • "Deploy the staging stack"

Development

npm install
npm run lint     # biome
npm run build    # tsc
npm test         # node:test suites (auth/secret/tool/format/smoke)
npm run dev      # tsc --watch

Architecture

src/
├── index.ts            # Express factory, transports, auth/Origin/Host gates, SIGTERM
├── server.ts           # createServer({ client? }) — DI-friendly factory
├── komodo-client.ts    # Official client adapter: shared Undici pool, timeout/size/concurrency guards
└── tools/
    ├── registry.ts     # Declarative TOOLS table + registerAll(server, client)
    └── utils.ts        # formatResult + toolHandler (errors → MCP isError)

See docs/ARCHITECTURE.md for diagrams and the request-flow walk-through.

API reference

The server uses the official komodo_client 2.1.1 package for the Komodo Core API. It sends JSON POST requests to /read/<Operation>, /write/<Operation>, or /execute/<Operation>, with the operation parameters as the request body and API-key headers:

curl -X POST http://your-komodo:9120/read/ListStacks \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_KEY" \
  -H "X-Api-Secret: YOUR_SECRET" \
  -d '{}'

Streamable HTTP and legacy SSE each create a separate McpServer per session while sharing one upstream adapter. Idle sessions are closed after MCP_SESSION_IDLE_TIMEOUT_MS; requests carrying an unknown session ID receive HTTP 404. CORS exposes the mcp-session-id response header to allowed browser clients.

License

MIT — see LICENSE.

Dependency note: the official komodo_client package declares GPL-3.0. Redistribution scenarios should receive a separate licensing review; this note is not a legal conclusion.

Links

About

MCP server for Komodo Docker/container management

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages