Docker MCP Server Configuration Guide
Manage Docker containers, images, and volumes through your AI agent using the Docker MCP server. Build, run, and monitor containers with natural language.
claude_desktop_config.json{
"mcpServers": {
"docker": {
"command": "npx",
"args": [
"-y",
"mcp-server-docker"
]
}
}
}Generate & Test Docker MCP Server Config
One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.
Docker MCP Server Configuration Guide
Container virtualization has become the universal runtime standard for backend microservices, ephemeral integration test suites, and reproducible developer environments. When engineering teams debug service failures or test microservice architectures, developers repeatedly switch between their code editors and terminal consoles to run docker ps, tail log files from crash-looping containers, and prune orphaned volumes.
By integrating the Docker engine directly into the Model Context Protocol (MCP), developers can provide AI assistants in Claude Desktop, Cursor, or OpenAI Codex CLI with structured, programmatic control over local container lifecycles. An agent can inspect container health metrics, diagnose exit codes, summarize recent standard output logs, and spin up isolated test dependencies.
However, connecting an autonomous reasoning model to the Docker engine introduces severe security risks. Access to the Docker daemon socket is equivalent to root privileges on the host system. Operating a Docker MCP server safely requires socket proxies, unprivileged API scoping, and log tail budgeting.
This guide provides an end-to-end architectural manual, multi-host configurations, a complete production TypeScript MCP server, and security hardening procedures for managing Docker through the Model Context Protocol.
1. System Architecture: Daemon Communication and Socket Isolation
The Docker MCP server runs as a local child process that bridges JSON-RPC tool calls from the AI host into Docker REST API calls across local communication channels:
Communication Channels Across Operating Systems
- ▸Linux and macOS UNIX Domain Socket: Communication flows over
/var/run/docker.sock. Because the socket owner isroot, unprivileged users must be assigned to thedockeruser group. - ▸Windows Named Pipe: Communication flows over the Windows named pipe
//./pipe/docker_engine. When configuring client environments on Windows, path formatting must account for pipe naming conventions. - ▸The Root Access Hazard: Because a client with unrestricted Docker socket access can spawn a privileged container mounting the host filesystem (
-v /:/host), production implementations should insert an intermediary socket filter proxy (such astecnativa/docker-socket-proxy) to block arbitrary container creation.
2. Environment Prerequisites and Software Matrix
Verify that your workstation satisfies the following software requirements:
| Component | Minimum Version | Installation Verification | Purpose |
|---|---|---|---|
| Docker Engine | >= 24.0.0 | docker --version | Container runtime engine |
| Docker Desktop | >= 4.25.0 | Check GUI or version | Desktop daemon provider for macOS/Windows |
| Node.js | >= 20.0.0 | node -v | Server runtime environment |
| dockerode | >= 3.3.5 | Package manifest | Official Docker REST API client for Node.js |
| @modelcontextprotocol/sdk | >= 1.2.0 | Package manifest | Core Model Context Protocol framework |
Ensure the Docker daemon is running before launching the server:
docker info3. Multi-Host Configuration Snippets
Configure your MCP clients to launch the Docker server over standard input and output (stdio).
Claude Desktop Configuration (claude_desktop_config.json)
On macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
On Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"docker": {
"command": "node",
"args": ["/opt/mcp-servers/docker/dist/index.js"],
"env": {
"DOCKER_SOCKET_PATH": "/var/run/docker.sock",
"MAX_LOG_TAIL_LINES": "100"
}
}
}
}Cursor IDE Configuration (.cursor/mcp.json)
{
"mcpServers": {
"docker": {
"command": "node",
"args": ["./dist/index.js"]
}
}
}OpenAI Codex CLI Configuration (~/.codex/config.toml)
[mcp_servers.docker]
command = "node"
args = ["/opt/mcp-servers/docker/dist/index.js"]
[mcp_servers.docker.env]
DOCKER_SOCKET_PATH = "/var/run/docker.sock"
MAX_LOG_TAIL_LINES = "100"4. Production TypeScript Docker MCP Server Implementation
The following implementation provides three foundational diagnostic tools: list_containers, get_container_logs, and get_container_stats. Save this as src/index.ts:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import Docker from 'dockerode';
const isWindows = process.platform === 'win32';
const socketPath = process.env.DOCKER_SOCKET_PATH || (isWindows ? '//./pipe/docker_engine' : '/var/run/docker.sock');
const docker = new Docker({ socketPath });
const server = new Server(
{ name: 'docker-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'list_containers',
description: 'List active and stopped Docker containers with their status, image, and exposed ports.',
inputSchema: {
type: 'object',
properties: {
all: { type: 'boolean', default: false, description: 'Include stopped containers' }
}
}
},
{
name: 'get_container_logs',
description: 'Retrieve the most recent stdout and stderr logs from a container.',
inputSchema: {
type: 'object',
properties: {
container_id: { type: 'string', description: 'Container ID or name' },
tail_lines: { type: 'number', default: 50, maximum: 100, description: 'Number of lines to tail' }
},
required: ['container_id']
}
},
{
name: 'get_container_stats',
description: 'Retrieve a snapshot of container CPU and memory usage statistics.',
inputSchema: {
type: 'object',
properties: {
container_id: { type: 'string', description: 'Container ID or name' }
},
required: ['container_id']
}
}
]
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
if (name === 'list_containers') {
const showAll = Boolean(args?.all);
const containers = await docker.listContainers({ all: showAll });
const simplified = containers.map(c => ({
id: c.Id.slice(0, 12),
names: c.Names,
image: c.Image,
state: c.State,
status: c.Status,
ports: c.Ports.map(p => `${p.PublicPort || ''}:${p.PrivatePort}`).filter(Boolean)
}));
return {
content: [{ type: 'text', text: JSON.stringify(simplified, null, 2) }]
};
}
if (name === 'get_container_logs') {
const containerId = args?.container_id as string;
const tail = Math.min(Number(args?.tail_lines) || 50, 100);
const container = docker.getContainer(containerId);
const logsBuffer = await container.logs({
stdout: true,
stderr: true,
tail: tail,
timestamps: true
});
// Strip Docker multiplexed stream headers
const cleanLogs = logsBuffer.toString('utf8').replace(/[\x00-\x09\x0B-\x1F]/g, '');
return {
content: [{ type: 'text', text: cleanLogs }]
};
}
if (name === 'get_container_stats') {
const containerId = args?.container_id as string;
const container = docker.getContainer(containerId);
const stats = await container.stats({ stream: false });
const memoryUsageMB = (stats.memory_stats.usage / (1024 * 1024)).toFixed(2);
const memoryLimitMB = (stats.memory_stats.limit / (1024 * 1024)).toFixed(2);
const result = {
container_id: containerId,
memory_usage_mb: memoryUsageMB,
memory_limit_mb: memoryLimitMB,
pids: stats.pids_stats.current || 0
};
return {
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
};
}
throw new Error(`Tool '${name}' is not recognized.`);
} catch (err: any) {
return {
isError: true,
content: [{ type: 'text', text: `Docker API Error: ${err.message}` }]
};
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((err) => {
process.stderr.write(`Fatal server error: ${err.message}\n`);
process.exit(1);
});5. JSON-RPC 2.0 Wire Payloads
Inspecting the underlying protocol frames helps confirm clean JSON-RPC messaging across host and client.
Tool Invocation Request (tools/call)
{
"jsonrpc": "2.0",
"id": "docker-list-01",
"method": "tools/call",
"params": {
"name": "list_containers",
"arguments": {
"all": false
}
}
}Result Payload
{
"jsonrpc": "2.0",
"id": "docker-list-01",
"result": {
"content": [
{
"type": "text",
"text": "[\n {\"id\": \"e4a19b88c2f1\", \"names\": [\"/redis-cache\"], \"image\": \"redis:7-alpine\", \"state\": \"running\", \"status\": \"Up 3 hours\"}\n]"
}
]
}
}6. Common Errors and Production Troubleshooting
When operating the Docker MCP server on developer workstations, monitor for the following standard issues:
Error: connect EACCES /var/run/docker.sock
- ▸Root Cause: The user executing the AI host application lacks read/write permissions to the Docker socket.
- ▸Resolution: On Linux, add your local user to the
dockergroup:sudo usermod -aG docker $USER. Log out and log back in to apply group membership.
Error: connect ENOENT /var/run/docker.sock
- ▸Root Cause: The Docker daemon is stopped, or Docker Desktop has not enabled the default system socket symlink.
- ▸Resolution: In Docker Desktop Settings, navigate to Advanced and enable Allow the default Docker socket to be used.
Error: Windows Named Pipe Connection Failure
- ▸Root Cause: The MCP server defaulted to the Linux socket path
/var/run/docker.sockon a Windows operating system. - ▸Resolution: Set
DOCKER_SOCKET_PATH="//./pipe/docker_engine"in your client environment configuration.
7. External Citations and Security Guardrails
Running Docker tools through generative models requires defense-in-depth security safeguards:
- ▸Socket Proxying: In shared or multi-user environments, never mount the raw Docker socket directly. Use
tecnativa/docker-socket-proxyconfigured withPOST=0to physically block container creation and volume mounting. - ▸Official Standards and Repositories:
Weekly Protocol Diffs & Verified Drops
New server guides, benchmarks, and security audits. No spam. Unsubscribe anytime.
Zero marketing spam. 1-click unsubscribe anytime.
Build your full agent toolstack in the Visual Generator
Combine Docker with databases, search APIs, and memory graphs in a single configuration file.
Did this setup guide work with your AI host?
Help test this configuration across Claude, Cursor, and Codex CLI. Be the first to report:
Docker MCP Server Configuration Guide FAQ
What is the Docker MCP Server Configuration Guide?
Manage Docker containers, images, and volumes through your AI agent using the Docker MCP server. Build, run, and monitor containers with natural language.
How do I configure Docker MCP Server Configuration Guide in Claude Desktop or Cursor?
You can copy the configuration JSON from our guide or launch the interactive MCP Codex Config Generator at https://mcp-codex.com/generator to export valid configs in 1 click.
Can I use Docker MCP Server Configuration Guide with the OpenAI Codex CLI?
Yes, OpenAI Codex CLI supports Model Context Protocol. You can add it directly to ~/.codex/config.toml or pass arguments to codex mcp add.
Specializing in Model Context Protocol (MCP) integrations, autonomous AI agent orchestration, and distributed developer toolchains. Researches and benchmarks production MCP client-server architectures across OpenAI Codex, Claude, and Cursor.
Related Guides
OpenCode Free AI Agent Guide
Guide to running OpenCode coding agent completely free without API keys using Zen free tier, local LLMs, and OAuth accounts.
Dev ToolsSelf-Correcting Verification Loops in Agents
Build robust self-correcting /loop verification harnesses for AI agents using Test-Driven Agent Development, dual-agent critics, and MCP test sandboxes.
Dev ToolsAutomated Doc Verification Loops with Claude CLI
Build automated documentation verification loops with Claude CLI and MCP. Validate code snippets, test tool schemas, and sync SDK docs in CI/CD. Verified.