# Komodo Mcp

> MCP server for Komodo Docker/container management

- **Type:** MCP server
- **Install:** `agentstack add mcp-nicolasestrem-komodo-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [nicolasestrem](https://agentstack.voostack.com/s/nicolasestrem)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [nicolasestrem](https://github.com/nicolasestrem)
- **Source:** https://github.com/nicolasestrem/komodo-mcp

## Install

```sh
agentstack add mcp-nicolasestrem-komodo-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Komodo MCP Server

An MCP (Model Context Protocol) server that exposes [Komodo](https://komo.do) — 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

```bash
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):
```json
{
  "mcpServers": {
    "komodo": {
      "type": "http",
      "url": "http://127.0.0.1:3113/mcp"
    }
  }
}
```

**Docker** (token required):
```json
{
  "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)

```bash
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`](docs/DEPLOYMENT.md) and [`docs/RUNBOOK.md`](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`](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

```bash
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`](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](https://komo.do/docs/api). It sends JSON POST requests to `/read/`, `/write/`, or `/execute/`, with the operation parameters as the request body and API-key headers:

```bash
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](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

- [Komodo documentation](https://komo.do/docs)
- [Komodo GitHub](https://github.com/moghtech/komodo)
- [MCP protocol](https://modelcontextprotocol.io)

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [nicolasestrem](https://github.com/nicolasestrem)
- **Source:** [nicolasestrem/komodo-mcp](https://github.com/nicolasestrem/komodo-mcp)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-nicolasestrem-komodo-mcp
- Seller: https://agentstack.voostack.com/s/nicolasestrem
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
