dockerbro
# DockerBro
**DockerBro** is a **proper MCP-compliant** Docker management server. Speaks JSON-RPC 2.0 over stdin/stdout and talks to your local Docker daemon.
Works with **Zed**, **Claude**, **Cursor**, **VS Code**, and any other MCP-compatible AI editor.
Runs on **macOS**, **Linux**, and **Windows**.
```bash
pip install dockerbro
```
---
## Features
| Tool | What it does | Safety |
|---|---|---|
| `list_containers` | List all containers with status, image, ports | Read-only |
| `inspect_container` | Detailed container info (network, mounts, env) | Read-only |
| `start_container` | Start a stopped container | Reversible |
| `stop_container` | Stop a running container | Reversible |
| `restart_container` | Restart a container | Reversible |
| `remove_container` | Remove a container (with optional force) | ⚠️ Destructive |
| `logs_container` | Get recent log output | Read-only |
| `exec_container` | Run a command inside a running container | ⚠️ Destructive |
| `list_images` | List local Docker images | Read-only |
| `pull_image` | Pull an image from a registry | Reversible |
| `run_container` | Run a new container with ports, env, etc. | Reversible |
| `remove_image` | Remove a local image | ⚠️ Destructive |
| `docker_compose_ps` | List Compose services | Read-only |
| `docker_compose_up` | Start Compose services | Reversible |
| `docker_compose_down` | Stop and remove Compose services | ⚠️ Destructive |
| `docker_compose_logs` | Get Compose service logs | Read-only |
---
## Pre-approving tools
Each tool is annotated with [MCP spec annotations](https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/annotations) (`readOnlyHint`, `destructiveHint`, `idempotentHint`) so spec-aware clients (Claude Code, Cursor, etc.) can auto-approve read-only tools without prompting.
You can also **restrict tools at the server level** via environment variables, enforced before anything reaches the client:
| Env var | Effect |
|---|---|
| `DOCKER_MCP_ALLOW_TOOLS` | Comma-separated allowlist — only these tools are exposed and callable |
| `DOCKER_MCP_DENY_TOOLS` | Comma-separated denylist — always blocked (deny wins over allow) |
### Example: only safe read-only tools
Pass the env var in your Zed config (add to the `env` object):
```json
"env": {
"DOCKER_MCP_ALLOW_TOOLS": "list_containers,inspect_container,logs_container,list_images,docker_compose_ps,docker_compose_logs"
}
```
If a tool is not pre-approved, the server returns an error:
```
Tool 'remove_container' is not pre-approved (blocked by server allow/deny config).
```
> **Note:** Client-side approval (e.g. Zed's `agent.tool_permissions`) and server-side pre-approval are independent. The server-side list controls which tools are *visible and callable* at all; the client controls which of those require a confirmation prompt.
---
## Requirements
- **Python 3.9+**
- **Docker** installed and running
---
## Install
### Option A: From PyPI (recommended — all platforms)
| Platform | Command |
|---|---|
| macOS / Linux | `pip3 install dockerbro` |
| Windows | `pip install dockerbro` |
| Any (if `pip` isn't on PATH) | `python3 -m pip install dockerbro` |
> **`command not found: pip`?** On macOS and many Linux distros, Python 3 installs it as `pip3`. On Windows it's usually `pip` or `py -m pip`. When in doubt, `python3 -m pip install dockerbro` works everywhere.
This puts a `dockerbro` command on your PATH, so your editor config needs **no file paths at all**.
Verify it works:
```bash
dockerbro --version 2>/dev/null; echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | dockerbro
```
### Option B: Run from source
```bash
git clone https://github.com/ramanailearning-cpu/dockerbro.git
cd dockerbro
pip install -e .
```
### Option C: Run in a Docker container
Build it:
```bash
docker build -t dockerbro .
```
Run it — the socket mount differs per platform:
**macOS / Linux:**
```bash
docker run --rm -i -v /var/run/docker.sock:/var/run/docker.sock dockerbro
```
**Windows (PowerShell):**
```powershell
docker run --rm -i -v //./pipe/docker_engine://./pipe/docker_engine dockerbro
```
---
## Connecting to the Docker daemon
DockerBro auto-detects your daemon, so this usually needs zero configuration:
| Platform | Default endpoint |
|---|---|
| Linux | `/var/run/docker.sock` |
| macOS (Docker Desktop) | `/var/run/docker.sock`, or `~/.docker/run/docker.sock` on 4.13+ |
| Windows | Named pipe `//./pipe/docker_engine` |
To point at a different or remote daemon, set `DOCKER_HOST` in your config's `env` block:
```json
"env": { "DOCKER_HOST": "tcp://192.168.1.50:2375" }
```
> **macOS Docker Desktop note:** if you get a connection error, enable **Settings → Advanced → Allow the default Docker socket**, or set `DOCKER_HOST` to `unix:///Users/YOUR_NAME/.docker/run/docker.sock`.
---
## Zed Configuration
Add this to your Zed settings file (`Cmd-Shift-P` → **Open Settings** on macOS, `Ctrl-Shift-P` on Linux/Windows):
```json
"context_servers": {
"dockerbro": {
"command": "dockerbro",
"env": {
"DOCKER_MCP_LOG": "/tmp/dockerbro.log"
}
}
}
```
### Restricting tools server-side
Optionally, add env vars to limit which tools are exposed:
```json
"env": {
"DOCKER_MCP_LOG": "/tmp/dockerbro.log",
"DOCKER_MCP_DENY_TOOLS": "remove_container,remove_image,exec_container,docker_compose_down"
}
```
Reload Zed (`Cmd-Shift-P` on macOS / `Ctrl-Shift-P` on Linux or Windows → **Reload Window**). The agent will have 16 Docker tools available.
> **Windows note:** If the `dockerbro` command isn't found by Zed, use the full path shown by `where dockerbro` in your terminal.
---
## Claude Desktop Configuration
### macOS
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"dockerbro": {
"command": "dockerbro",
"env": {
"DOCKER_MCP_LOG": "/tmp/dockerbro.log"
}
}
}
}
```
### Linux
Edit `~/.config/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"dockerbro": {
"command": "dockerbro",
"env": {
"DOCKER_MCP_LOG": "/tmp/dockerbro.log"
}
}
}
}
```
### Windows
Edit `%APPDATA%\Claude\claude_desktop_config.json` (paste the path into Explorer's address bar):
```json
{
"mcpServers": {
"dockerbro": {
"command": "dockerbro",
"env": {
"DOCKER_MCP_LOG": "C:\\Users\\YOU\\dockerbro.log"
}
}
}
}
```
---
## Testing
### Via terminal (pipe JSON-RPC)
```bash
# Initialize
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | dockerbro
# List tools
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | dockerbro
# Call a tool
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_containers","arguments":{"all":true}}}' | dockerbro
```
### Via MCP Inspector
```bash
npx @modelcontextprotocol/inspector dockerbro
```
---
## Architecture
```
AI Editor (Zed / Claude / Cursor / VS Code)
| (stdin/stdout: JSON-RPC 2.0)
v
dockerbro (Python)
| (Docker SDK)
v
Docker Daemon
```
---
## License
MIT
TDQS
Scored across 16 tools
Each tool targets a distinct Docker resource and action. Container management tools (list, inspect, start, stop, restart, remove, logs, exec, run) are clearly separated from image tools (list, pull, remove) and compose tools (up, down, logs, ps). No two tools have overlapping purposes.
Most tools follow a verb_noun pattern (e.g., list_containers, start_container, remove_image). The Docker Compose tools consistently use a docker_compose_ prefix with a verb suffix, which is a slight deviation from the main pattern but remains predictable and internally consistent.
With 16 tools, the server is well-scoped for Docker management. Each tool covers a distinct operation, and the count is appropriate for handling containers, images, and Compose workflows without being overwhelming or sparse.
The tool set covers the core Docker lifecycle: container run/start/stop/restart/remove/logs/exec, image list/pull/remove, and Compose up/down/logs/ps. Missing operations like image build/push or container stats are notable but not critical for common workflows, allowing agents to work around the gaps.