mcpdockery
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcpdockery list all containers and their status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcpdockery
An MCP server that gives an LLM (Claude, etc.) direct, natural-language control over your local Docker daemon — containers, images, volumes, networks, and Compose stacks.
Built with FastMCP and the Docker SDK for Python.
Table of contents
Related MCP server: portainer-mcp-server
Requirements
Requirement | Notes |
Python >= 3.14 | Interpreter version pinned in |
Docker Desktop or Docker Engine, running locally | |
Docker Compose v2 CLI |
|
| |
| |
Used for dependency management and running the server |
For pulling from or pushing to a private registry (Docker Hub, AWS ECR, GCR, etc.), authenticate with that registry beforehand using your normal docker login flow — this server never accepts or stores credentials itself.
Installation
Clone the repository:
git clone <this-repo> cd mcpdockeryInstall dependencies:
uv syncThis creates a
.venvand installs the exact dependency versions pinned inuv.lock.Confirm Docker is running:
docker infoIf this command fails, start Docker Desktop (or your Docker Engine) before continuing.
Running the server
uv run src/main.pyThe server communicates over stdio, so it's meant to be launched by an MCP client rather than run standalone in a terminal.
Connecting to an MCP client
Add an entry to your MCP client's configuration (e.g. claude_desktop_config.json for Claude Desktop, or your project's .mcp.json for Claude Code):
{
"mcpServers": {
"mcpdockery": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/mcpdockery", "run", "src/main.py"]
}
}
}Replace /absolute/path/to/mcpdockery with the actual path where you cloned the repository, then restart the client. The tools listed below will become available to the model.
Available tools
Containers (containers.py)
Tool | Description |
| Runs a container from an image, mapping a container port to a host port |
| Stops a running container |
| Starts a stopped container |
| Restarts a container |
| Force-removes a container (stops it first if needed). Destructive — requires |
| Lists all containers and their status |
| Fetches the last N log lines from a container. Secret-shaped values (passwords, tokens, API keys) are redacted |
| Reports live CPU % and memory usage |
| Shows env vars, mounts, network IPs, and health status. Secret-shaped env values are redacted |
| Executes a shell command inside a running container. Secret-shaped values in the output are redacted |
Images (images.py)
Tool | Description |
| Lists all local images, including untagged/intermediate ones, with size |
| Pulls an image from a registry without running it; defaults to the |
| Builds an image from a Dockerfile already on disk |
| Tags and pushes a local image to a registry (requires prior |
| Force-removes a local image. Destructive — requires |
Volumes (volumes.py)
Tool | Description |
| Lists volumes with driver and mountpoint |
| Creates a new volume |
| Deletes a volume (fails if still in use). Destructive — requires |
Networks (networks.py)
Tool | Description |
| Lists networks with driver and scope |
| Creates a new network |
Optimization (optimization.py)
Tool | Description |
| Detects whether a Dockerfile would benefit from a multi-stage build (build-tool commands in a single-stage image); returns reasoning + raw content for the model to draft the rewrite |
Diagnostics (diagnostics.py)
Tool | Description |
| Scans all containers and reports only the ones needing attention: OOM kills, restart loops, unhealthy checks, crashes, high CPU/memory |
| Flags running containers with sensitive ports (databases, admin panels, Docker daemon API) or any port bound to all network interfaces |
Security (security.py)
Tool | Description |
| Scans an image for known vulnerabilities using Trivy; defaults to CRITICAL/HIGH severity only |
| Generates a Software Bill of Materials (SBOM) for an image using Trivy, in CycloneDX or SPDX-JSON format |
| Scans a Dockerfile for misconfigurations (root user, |
| Lints a Dockerfile with Hadolint for best-practice/style issues (unpinned versions, |
| Combined report: |
Compose stacks (stacks.py)
Tool | Description |
| Deploys a stack from an inline |
| Stops a stack's containers without removing them |
| Stops and removes a stack, including its volumes ( |
| Lists all compose projects, including stopped ones |
| Shows the status of a stack's containers ( |
| Collects logs from every container in a stack |
Usage examples
Once connected, you can drive the server with natural-language requests. A few examples of what to expect:
You ask | Tool(s) the model will likely use |
"Pull the alpine version of redis" |
|
"Run an nginx container on port 8080" |
|
"Show me the logs for my-app from the last hour" |
|
"What's using all the CPU right now?" |
|
"Is anything broken right now?" |
|
"Is anything exposed to the network that shouldn't be?" |
|
"Deploy this docker-compose file as 'staging'" |
|
"Push my-app:latest to my ECR repo" |
|
"Clean up the my-app container and its image" |
|
"Scan my-app:latest for vulnerabilities" |
|
"Generate an SBOM for my-app:latest" |
|
"Check my Dockerfile for security issues before I build it" |
|
"Lint my Dockerfile for best practices" |
|
"Check/review my Dockerfile" |
|
"Should this Dockerfile use multi-stage builds?" |
|
The model chooses which tool(s) to call based on your request — you don't need to name the tool yourself.
Project structure
src/
main.py # Entrypoint: registers tool modules and starts the MCP server
server.py # Shared FastMCP server instance
docker_client.py # Lazy singleton Docker SDK client
compose_client.py # Thin wrapper around the `docker compose` CLI
helper.py # Shared helpers (path normalization, image tag parsing, Trivy wrapper)
containers.py # Container lifecycle & inspection tools
images.py # Image pull/build/push/list/delete tools
volumes.py # Volume tools
networks.py # Network tools
stacks.py # Compose stack tools
security.py # Image/Dockerfile vulnerability & misconfiguration scanning tools
diagnostics.py # Cross-container health triage tools
optimization.py # Dockerfile efficiency analysis toolsSafety notes
This server gives the model real, unsandboxed control over your Docker daemon:
delete_container,delete_image,remove_volume, andremove_stackare destructive and require an explicitconfirm=Trueargument. The first call (confirm defaults toFalse) performs no action and only returns a preview of what would be deleted — the model is instructed to only passconfirm=Trueafter you've explicitly agreed in the conversation. This is a safety net against a misread request, not a hard permission system: any client with tool access can still passconfirm=Truedirectly.remove_stackdeletes volumes (-v), which is destructive and irreversible for stateful data.container_execruns arbitrary shell commands inside a container.container_logs,container_exec, andcontainer_inspectredact values that look like secrets (keys matching PASSWORD/TOKEN/API_KEY/etc., inKEY=value,KEY: value, or"key": "value"form) before returning them. This is a best-effort heuristic, not a guarantee — anything that doesn't match the pattern (or that a container prints in an unusual format) is returned as-is, and remember that tool output is sent to the model provider as part of the conversation regardless of how "local" the Docker daemon is.push_imageandpull_imageuse your existing local Docker credentials — the model can push to or pull from any registry you're currently authenticated with. Note that AWS ECR tokens expire after 12 hours; if a push/pull suddenly fails with an auth error, re-run yourdocker login/aws ecr get-login-passwordflow rather than assuming the tool is broken.The Docker socket grants root-equivalent access to the host. Giving a model tool access to this server is equivalent to giving it that level of access to your machine, whether or not the daemon is reachable over the network.
Only connect this server to clients/agents you trust, and be deliberate about which containers and stacks you let it touch.
License
No license specified.
Available Tools
34 toolsanalyze_multistageA
Analyzes a Dockerfile and reports whether it would benefit from a multi-stage build. Detects build-tool commands (npm install/build, mvn, gradle, go build, cargo build, pip install with compilers, dotnet build/publish, make/cmake/gcc) combined with a single-stage FROM, which usually means build tools and dev dependencies end up shipped in the final image unnecessarily — increasing image size and attack surface.
This tool only analyzes and returns reasoning plus the raw Dockerfile content — it does NOT generate the rewritten Dockerfile itself. If it reports multi-stage as recommended, use the returned content and detected build system to draft a multi-stage version yourself: a "builder" stage that runs the build commands, and a slim runtime stage that only COPYs the compiled artifact from the builder stage.
Args: dockerfile_path: full path to an existing Dockerfile on this machine. Accepts either a Windows path ("C:\path\Dockerfile") or a Git Bash style path ("/c/path/Dockerfile").
Inputs: dockerfile_path (required). Returns: result
audit_dockerfileA
Runs a full pre-build Dockerfile audit: Trivy's security misconfiguration
scan plus Hadolint's best-practice/style lint, combined into one report,
plus the raw Dockerfile content. Use this for a general "check/review/audit
my Dockerfile" request when the user hasn't specified security vs. style
specifically. For a narrower, single-tool check, use scan_dockerfile
(security only) or lint_dockerfile (style only) instead — those return
findings only, not the raw content, so they're cheaper when a rewrite
isn't needed.
Requires both trivy (https://trivy.dev) and hadolint
(https://github.com/hadolint/hadolint) installed and on PATH.
Args: dockerfile_path: full path to an existing Dockerfile on this machine. Accepts either a Windows path ("C:\path\Dockerfile") or a Git Bash style path ("/c/path/Dockerfile"). severity: comma-separated Trivy severities to include (default "CRITICAL,HIGH")
Inputs: dockerfile_path (required), severity. Returns: result
build_imageA
Builds a Docker image from a Dockerfile already saved on disk. The build context is the folder containing the Dockerfile, so COPY/ADD of other files in that same folder works normally. Accepts either a Windows path ("C:\path\Dockerfile") or a Git Bash style path ("/c/path/Dockerfile"). Args: image_tag: tag to give the built image, e.g. "my-app:latest" dockerfile_path: full path to an existing Dockerfile on this machine
Inputs: image_tag (required), dockerfile_path (required). Returns: result
check_exposed_portsA
Scans all running containers' published port bindings and flags anything worth a second look: known database/admin-panel ports (Postgres, MySQL, Redis, MongoDB, Elasticsearch, the Docker daemon API, etc.) and any port bound to 0.0.0.0/all interfaces rather than localhost. Meant to catch services that ended up reachable from the network when they were only meant for local access. Does not distinguish trusted vs. untrusted networks — a flagged binding may be fine on an isolated host, so review findings in context.
Inputs: no named parameters. Returns: result
container_execA
Executes a shell command inside a running container and returns its output. Values that look like secrets (PASSWORD=, "token": "...", etc.) are redacted before being returned. Args: container_name: Docker Container name command: shell command to run inside the container, e.g. "ls -la /app"
Inputs: command (required), container_name (required). Returns: result
container_inspectB
Returns detailed information about a container: environment variables, mounts, network IP, and health status. Env var values that look like secrets (PASSWORD, TOKEN, API_KEY, etc.) are redacted. Args: container_name: Docker Container name
Inputs: container_name (required). Returns: result
container_logsA
Collect and display the logs for a container. Values that look like secrets (PASSWORD=, "token": "...", etc.) are redacted before being returned. Args: container_name: Container name to collect logs tail: Number of log lines to return (default 200)
Inputs: container_name (required), tail. Returns: result
container_restartD
Restarting a container Args: container_name: name to restart the container
Inputs: container_name (required). Returns: result
container_startC
Starting a container Args: container_name: name to start the container
Inputs: container_name (required). Returns: result
container_statsA
Shows live CPU and memory usage for a running container. Args: container_name: Docker Container name
Inputs: container_name (required). Returns: result
create_networkA
Creates a new Docker network. Args: network_name: name to give the new network driver: network driver to use, e.g. "bridge" (default), "overlay" (swarm), "macvlan"
Inputs: network_name (required), driver. Returns: result
create_volumeC
Creates a new Docker volume. Args: volume_name: name to give the new volume driver: volume driver to use (default "local")
Inputs: volume_name (required), driver. Returns: result
delete_containerA
Delete a container by its name. Stops it first if it's still running. Destructive and irreversible. The first call (confirm=False, the default) does NOT delete anything — it only previews what would happen. Only pass confirm=True after the user has explicitly agreed to the deletion. Args: container_name: Container name that should be deleted confirm: must be True to actually perform the deletion (default False)
Inputs: container_name (required), confirm. Returns: result
delete_imageA
Delete a Docker image by tag or ID. Removed even if still referenced by a stopped container (force). Destructive and irreversible. The first call (confirm=False, the default) does NOT delete anything — it only previews what would happen. Only pass confirm=True after the user has explicitly agreed to the deletion. Args: image_name: image name to be deleted confirm: must be True to actually perform the deletion (default False)
Inputs: image_name (required), confirm. Returns: result
deploy_stackA
Deploys a multi-container application from a docker-compose YAML definition. Args: project_name: unique name for this stack, used to group/manage its containers compose_yaml: full contents of a docker-compose.yml describing the services
Inputs: compose_yaml (required), project_name (required). Returns: result
docker_doctorA
Scans every container and reports only the ones that need attention: OOM kills, restart loops, unhealthy health checks, crashed containers, or high CPU/memory usage. Returns a clean-bill-of-health message if nothing is flagged — use this instead of checking containers one by one.
Args: cpu_threshold: CPU %% above which a running container is flagged (default 80.0) mem_threshold: memory %% of its limit above which a container is flagged (default 80.0)
Inputs: cpu_threshold, mem_threshold. Returns: result
generate_sbomA
Generates a Software Bill of Materials (SBOM) for a Docker image using
Trivy — a full inventory of every OS package and language dependency the
image contains. Useful for supply-chain compliance, license audits, and
tracking exposure when a new CVE is disclosed (search the SBOM instead of
re-scanning). Requires the trivy CLI installed and on PATH
(https://trivy.dev).
Args: image: image to generate an SBOM for, e.g. "nginx:latest" or "my-app:v1" format: SBOM format, "cyclonedx" (default) or "spdx-json"
Inputs: image (required), format. Returns: result
lint_dockerfileA
Lints a Dockerfile with Hadolint for best-practice and style issues —
unpinned package/base image versions, missing --no-install-recommends,
use of ADD instead of COPY, sudo usage, missing WORKDIR before relative
paths, and similar. Complements scan_dockerfile (Trivy), which focuses
on security misconfigurations rather than style/best-practice rules.
Requires the hadolint CLI installed and on PATH
(https://github.com/hadolint/hadolint).
Args: dockerfile_path: full path to an existing Dockerfile on this machine. Accepts either a Windows path ("C:\path\Dockerfile") or a Git Bash style path ("/c/path/Dockerfile").
Inputs: dockerfile_path (required). Returns: result
list_containersB
Returns all containers with their status
Inputs: no named parameters. Returns: result
list_imagesA
Lists all local Docker images, including untagged/intermediate ones. Each line shows: short ID, tags, and size in MB.
Inputs: no named parameters. Returns: result
list_networksA
Lists all Docker networks with their driver and scope
Inputs: no named parameters. Returns: result
list_stacksA
Lists all compose projects, including stopped ones
Inputs: no named parameters. Returns: result
list_volumesA
Lists all Docker volumes with their driver and mountpoint
Inputs: no named parameters. Returns: result
pull_imageA
Pulls a Docker image from a registry (Docker Hub, ECR, GCR, etc.) without
running it. Requires prior docker login if the registry needs auth —
this tool does not accept credentials.
Defaults to the "alpine" tag (smaller, faster to pull) when no tag is specified. Only pass a different tag (e.g. "latest" or a specific version) if the user explicitly asks for the full/standard image — not every image publishes an "alpine" variant, in which case the pull will fail and you should retry with "latest".
Args:
image: repository name, e.g. "nginx" or "myregistry.com:5000/my-app".
Can include a tag directly (e.g. "nginx:1.27"), in which case
the tag argument is ignored.
tag: tag to pull if not already included in image (default "alpine")
platform: optional, e.g. "linux/amd64" or "linux/arm64" — force a
specific architecture on multi-arch images
Inputs: image (required), tag, platform. Returns: result
push_imageA
Tags a local Docker image with a registry repository name and pushes it
(e.g. Docker Hub, AWS ECR). Requires that you have already run docker login
locally — this tool does not accept credentials.
Args:
local_image: the image currently on your machine, e.g. "my-app:latest"
repository: full destination repository name, e.g. "myusername/my-app"
or "123456789012.dkr.ecr.eu-west-1.amazonaws.com/my-app"
image_tag: tag to push, e.g. "latest" or "v1.0"
Inputs: repository (required), local_image (required), image_tag. Returns: result
remove_stackA
Stops and permanently removes a compose stack: containers, networks, and volumes (data is deleted). The first call (confirm=False, the default) does NOT remove anything — it only previews what would happen. Only pass confirm=True after the user has explicitly agreed to the removal. Args: project_name: unique name for this stack, used to group/manage its containers confirm: must be True to actually perform the removal (default False)
Inputs: project_name (required), confirm. Returns: result
remove_volumeA
Deletes a Docker volume by name. Data stored in it is permanently lost. Fails if the volume is currently in use by a container. The first call (confirm=False, the default) does NOT delete anything — it only previews what would happen. Only pass confirm=True after the user has explicitly agreed to the deletion. Args: volume_name: name of the volume to remove confirm: must be True to actually perform the deletion (default False)
Inputs: volume_name (required), confirm. Returns: result
run_containerA
Runs a Docker container locally for testing Args: image: Docker image to run, e.g. "nginx:latest" If no tag is specified, then usel alpine for default.It is smaller and faster to pull container_name: container name container_port: port the app listens on INSIDE the container, e.g. "80" for nginx host_port: port on your machine to access it, e.g. "8080" → http://localhost:8080
Inputs: image (required), host_port (required), container_name (required), container_port (required). Returns: result
scan_dockerfileA
Scans a Dockerfile for security misconfigurations using Trivy's config
scanner — BEFORE the image is even built. Flags things like: missing
USER directive (container would run as root), use of the "latest" tag,
hardcoded secrets in ENV/ARG, missing HEALTHCHECK, and use of ADD instead
of COPY. Requires the trivy CLI installed and on PATH (https://trivy.dev).
Args: dockerfile_path: full path to an existing Dockerfile on this machine. Accepts either a Windows path ("C:\path\Dockerfile") or a Git Bash style path ("/c/path/Dockerfile"). severity: comma-separated severities to include (default "CRITICAL,HIGH")
Inputs: dockerfile_path (required), severity. Returns: result
scan_imageA
Scans a Docker image for known vulnerabilities using Trivy. Requires the
trivy CLI installed and on PATH (https://trivy.dev). The first scan on
a fresh machine downloads Trivy's vulnerability database, which can take
a moment.
Defaults to showing only CRITICAL and HIGH severity findings to keep the output compact. Widen it by passing e.g. severity="CRITICAL,HIGH,MEDIUM,LOW".
Args: image: image to scan, e.g. "nginx:latest" or "my-app:v1" severity: comma-separated severities to include (default "CRITICAL,HIGH")
Inputs: image (required), severity. Returns: result
stack_logsA
Collects logs from all containers in a compose stack. Args: project_name: unique name for this stack, used to group/manage its containers tail: number of log lines to return per container (default 200)
Inputs: project_name (required), tail. Returns: result
stack_statusA
Shows the status of all containers in a compose stack (like docker compose ps). Args: project_name: unique name for this stack, used to group/manage its containers
Inputs: project_name (required). Returns: result
stop_containerC
User will pass the container name that we need to stop Args: container_name: Docker Container name
Inputs: container_name (required). Returns: result
stop_stackA
Stops all containers in a compose stack without removing them, so it can be started again later. Args: project_name: unique name for this stack, used to group/manage its containers
Inputs: project_name (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 34 tools
Most tools have clear, distinct purposes (e.g., container_logs vs. container_stats vs. docker_doctor), but a few overlap in intent (scan_dockerfile vs. lint_dockerfile vs. audit_dockerfile) and could confuse an agent if descriptions are not read carefully.
Naming is inconsistent: some tools use object_verb (container_logs, container_restart), others use verb_object (stop_container, delete_container), and some have no clear pattern (docker_doctor, generate_sbom). This makes it harder to predict tool names.
With 34 tools, the server is heavy for a typical MCP, but it covers a broad Docker domain comprehensively. Each tool has a distinct function, so the count is justified, though it exceeds the typical 3-15 range.
The toolset covers all major Docker operations: container lifecycle, image management, Dockerfile analysis, volumes, networks, and health/security checks. No obvious gaps for common Docker workflows.
Related MCP Connectors
Linux server administration over OAuth MCP: shell, Docker, systemd, files and monitoring.
Remote MCP server exposing your Node Command fleet (files, shell, processes, browser) to AI hosts.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that allows managing Docker containers through natural language, enabling users to compose, introspect, and debug containers without running commands themselves.3,908 PyPI753GPL 3.0
- AlicenseBqualityDmaintenanceMCP server for Portainer REST API that enables AI assistants to manage Docker containers, stacks, images, networks, and volumes through natural language.1840 npmMIT
- FlicenseBqualityDmaintenanceAn MCP server that gives LLMs direct control over a local Docker daemon, enabling container, image, volume, network, and Compose stack management through natural language.234-
- AlicenseBqualityDmaintenanceMCP server for managing Docker containers, images, and Compose services via natural language, with configurable tool permissions and safety annotations.16MIT