Docker MCP Server
@GavinLucas
About Docker MCP Server
More than just a fully featured MCP server that lets AI agents manage Docker — containers, images, networks, volumes, swarm services, secrets, configs, nodes, plugins, etc., it helps you create workflows to easily manage your Docker environments.
Basic information
Config
Add this server to your MCP-compatible client using the configuration below.
{
"mcpServers": {
"docker-mcp-server": {
"command": "uvx",
"args": [
"docker-mcp-server"
],
"env": {}
}
}
}Tools
162Build an image with BuildKit via `docker buildx build`. Replaces the legacy `build_image` tool when you need any of: multi-platform output (`platforms`), modern cache export (`cache_from`/`cache_to`), SBOM or provenance attestations, build secrets, or multi-stage builds with `target`. Always runs with `--progress=plain` so output is captured rather than redrawn on a TTY. args: context - Build context: a filesystem path or Git/HTTP URL (verbatim; no `~`/glob expansion). The `-` stdin-tarball form is NOT supported (stdin isn't forwarded — it'd block on the server's own stdin); serve a pre-packed tarball over HTTP instead. tags - Image references to apply (`-t`, repeatable) platforms - Target platforms, e.g. ["linux/amd64", "linux/arm64"] file - Dockerfile path (relative to context unless absolute) build_args - Build-time variables (each becomes `--build-arg KEY=VALUE`) build_contexts - Additional named build contexts (e.g. {"deps": "./vendor"}) labels - Image labels (each becomes `--label KEY=VALUE`) annotations - OCI manifest annotations (passed verbatim, repeatable) target - Target build stage to stop at push - Push the result to the registry (mutually exclusive with `load`) load - Load the result into the local image store (single-platform builds only) output - Custom `--output` specs (e.g. ["type=tar,dest=out.tar"]) no_cache - Do not use cache when building no_cache_filter - Stage names to exclude from caching pull - Always attempt to pull a newer version of each base image cache_from - Cache import specs, e.g. ["type=registry,ref=user/img:cache"] cache_to - Cache export specs builder - Override the active builder sbom - Shorthand for `--attest=type=sbom`; pass "true" or a config string provenance - Shorthand for `--attest=type=provenance`; pass "true", "false", or a config string attest - Custom attestation specs (repeatable) secret - Secret specs (e.g. ["id=npmrc,src=/home/user/.npmrc"] or ["id=npmrc,env=NPM_TOKEN"]). `~` in `src=` is NOT expanded (by this tool or the CLI) — use an absolute path. ssh - SSH agent socket/key specs (e.g. ["default"], using $SSH_AUTH_SOCK) timeout_seconds - Subprocess timeout (default 1800s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Build multiple targets defined in a bake file (HCL, JSON, or compose). args: targets - Bake targets to build (default: the `default` group) files - Bake file paths (`-f`, repeatable) set_overrides - Per-target overrides, e.g. ["app.platform=linux/amd64"] push - Push results to the registry load - Load results into the local image store no_cache - Do not use cache when building pull - Always pull a newer base image builder - Override the active builder cwd - Working directory containing the bake file (defaults to the server's cwd) timeout_seconds - Subprocess timeout (default 1800s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Inspect a manifest in a registry without pulling. Replaces `docker manifest inspect`. The standalone `docker manifest` command is in maintenance mode and lacks support for OCI image indexes, attestations, and annotations — `buildx imagetools inspect` is the path forward and handles both single-platform manifests and multi-platform manifest lists / OCI indexes. args: image - Image reference, e.g. "alpine:3.19" or "ghcr.io/org/repo@sha256:..." raw - Return the raw manifest bytes (a JSON document) instead of the human-rendered tree format - Go template format string (mutually exclusive with `raw`) builder - Override the active builder returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}. When `raw=True` or `format="{{json .}}"`, `stdout` is a JSON document the caller can parse.
Create a manifest list / OCI image index from existing per-platform tags. Replaces `docker manifest create` + `docker manifest push` — builds the index and pushes it in one operation. Source tags must already be pushed; this only stitches them together. args: target - Tag for the new manifest list (`-t`) sources - Source image references to combine append - Append to the existing manifest at `target` rather than replacing dry_run - Print the resulting manifest without pushing annotations - OCI annotations (repeatable; passed verbatim) platforms - Filter source platforms when combining files - Read source descriptors from files instead of refs builder - Override the active builder timeout_seconds - Subprocess timeout (default 600s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
List builder instances. returns: list - One dict per builder (parsed from `--format '{{json .}}'`). If the captured stdout was truncated by MAX_CLI_OUTPUT_BYTES the last (likely partial) record is dropped before parsing.
List recent build records (BuildKit build history), parsed from `--format '{{json .}}'`. Each record is a past build with its ref, name, status, step counts, and timestamps — useful for finding a build to drill into with `buildx_history_inspect`. Requires buildx >= v0.13 (older versions have no `history` subcommand and this raises with the CLI's "unknown command" error). args: builder - Builder instance to read history from (defaults to the active builder) returns: list - One dict per build record (ref, name, status, total/completed/cached steps, times)
Inspect a single build record by ref, parsed from `--format json`. Returns the full record for one build — duration, materials, attestations, error (if any) — for debugging a failed or slow build found via `buildx_history_ls`. Requires buildx >= v0.13. args: ref - Build record ref. Pass the `ref` field from `buildx_history_ls` directly — it reports a qualified "<builder>/<node>/<id>", but `history inspect` only accepts the bare id, so this reduces it to the id and (unless `builder` is given) targets the builder named in the ref. Empty/omitted inspects the most recent build; the `^N` syntax (e.g. "^0" = latest) is also valid. builder - Builder instance the build ran on (defaults to the one in `ref`, else active) returns: dict - The parsed build record (or {"raw": <stdout>} if the output isn't a JSON object)
Inspect a builder instance. args: name - Builder name (defaults to the active builder) bootstrap - Boot the builder if it isn't already running returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}. stdout is human-readable; parse with the agent or call buildx_ls for JSON.
Report BuildKit cache disk usage as a list of records. A large cache can easily generate more output than MAX_CLI_OUTPUT_BYTES; if that happens the captured stdout is truncated and this tool drops the final (partial) record before parsing. For an exhaustive accounting on a busy builder, run `docker buildx du --format '{{json .}}'` on the host directly. args: builder - Override the active builder returns: list - One dict per cache record (parsed from `--format '{{json .}}'`)
Remove BuildKit cache entries. Destructive: this tool always passes `--force` because no interactive prompt is available under MCP. Pair with `buildx_du` first to inventory what would be removed. args: all - Include internal/frontend images filter - Filter values (e.g. {"until": "24h", "type": "exec.cachemount"}) keep_storage - DEPRECATED; older buildx flag. Use `reserved_space` instead. reserved_space - Amount of disk to always keep (e.g. "10GB") max_used_space - Maximum disk space the cache may use (e.g. "20GB") min_free_space - Target amount of free disk after pruning (e.g. "5GB") builder - Override the active builder timeout_seconds - Subprocess timeout (default 600s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Create a new builder instance. args: name - Name for the new builder (defaults to a generated name) driver - BuildKit driver (e.g. "docker-container", "kubernetes", "remote") driver_opts - Driver-specific options (each becomes `--driver-opt KEY=VALUE`) use - Set the new builder as the current one bootstrap - Boot the builder immediately platforms - Platforms the builder advertises config - Path to a buildkitd config file node_name - Node name within the builder (for multi-node builders) append - Append a node to an existing builder named `name` returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Select the active builder for subsequent buildx operations. Without `default` or `global_default` the switch applies only to the current CLI session. `default` persists the choice for the current Docker context; `global_default` persists across all Docker contexts. Use `buildx_ls` to see available builders and their current status. To avoid switching the global default, pass a specific builder name directly via `buildx_build`'s `builder` parameter instead. args: name - Builder name to activate (from `buildx_ls`) default - Persist as default builder for the current Docker context global_default - Persist as default builder across all Docker contexts returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Remove a builder instance. args: name - Builder name to remove (mutually exclusive with `all_inactive`) all_inactive - Remove every inactive builder keep_state - Keep the BuildKit state volume keep_daemon - Keep the BuildKit daemon process running force - Force removal even if the builder is in use returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Check that the Docker server is responsive. returns: bool - True if the daemon responded successfully
Return Docker server version information. returns: dict - Version information from the Docker daemon
Return system-wide Docker information. returns: dict - System information from the Docker daemon
Return Docker disk usage information. returns: dict - Data usage information for images, containers and volumes
List the Docker hosts configured via DOCKER_MCP_SERVER_HOSTS. With a single host (or the var unset) this is the one resolved daemon; with several it is the set the `host` argument selects from. The `default` entry is the one used when `host` is omitted. returns: list[dict] - one per host: name; url (resolved daemon URL, null = docker-py platform default); read_only; tls (whether a per-host cert dir is configured); default (the omitted-host fallback)
Authenticate with a Docker registry. Security: the password is sent as a tool argument, which many MCP clients log verbatim. Prefer running `docker login` once on the host so the `docker` module reuses the credentials cached in `~/.docker/config.json`, and avoid calling this tool from an agent loop. args: username - Registry username password - Registry password or token email - Registry account email registry - URL to the registry (defaults to Docker Hub) reauth - Force re-authentication even if valid credentials exist dockercfg_path - Path to a custom dockercfg file host - host label whose client caches the credentials (default: the default host) returns: dict - The server response from the login request
Clear cached registry credentials from this server's in-memory Docker client. docker-py / the Engine have no true logout: `login` validates against the registry (the daemon's `/auth` is stateless) and caches credentials in-process. This drops that in-memory cache; it does NOT contact the daemon or touch the host's `~/.docker/config.json`. With no `registry`, clears every cached credential; pass one to clear just that entry (key must match `login`; Docker Hub is cached under "docker.io"). `close`/`reconnect` also clear it by discarding the client. Reaches into a private docker-py attribute (`api._auth_configs`); degrades to clearing nothing if that internal shape changes. args: registry - Registry key to clear, or None to clear every cached credential host - host label whose client cache to clear (default: the default host) returns: dict - {"cleared": [<registry keys removed>]}
Stream real-time events from the Docker server, bounded by `limit` events or `timeout_seconds`. Returns when `limit` events are collected or `timeout_seconds` elapses, whichever comes first (`limit` caps memory; `timeout_seconds` caps how long the call blocks — without it a quiet daemon would block indefinitely, since the stream only yields on an actual event). Caveat for `ssh://` daemons: docker-py can't cancel an SSH stream, so the `timeout_seconds` watchdog can't interrupt a fully idle stream — bound with `until`/`limit` (or a non-SSH endpoint). args: since - Show events created since this timestamp until - Show events created until this timestamp filters - Filters to apply to the event stream limit - Max events to return (default 100) timeout_seconds - Max wall-clock seconds before returning what was collected (default 30) returns: list - A list of decoded event dicts (length <= limit)
Close and drop pooled Docker client connection(s); each is rebuilt lazily on next use. Use this to force a stale or errored connection to be discarded. Prefer `reconnect` when you want to immediately re-establish the connection rather than wait for the next tool call to trigger a lazy rebuild. Closing all clients does not affect running containers. args: host - host label to close; omit to close every pooled client returns: bool - True once closed
Rebuild a pooled Docker client from its configured endpoint, to recover a wedged connection. Validates the rebuilt client before swapping in (and only then closes the old one), so a failed rebuild leaves the working client in place. It CANNOT retarget to a different daemon — to add or change a daemon, edit DOCKER_MCP_SERVER_HOSTS and restart. args: host - host label to rebuild, or None for the default host returns: dict - the rebuilt host's version info (same shape as `version`), confirming connectivity
Bring up a Docker Compose project, detached. Always runs detached (`-d`) so it can't block the server. Use `compose_ps` to confirm services are running, or `wait=True` to block until they're healthy. args: project_dir - Dir with the compose file (default: server cwd; paths verbatim, no shell expansion) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override profiles - Profiles to activate services - Specific services to bring up (default: all) build - Build images before starting pull - Pull strategy: "always", "missing", "never", or "policy" (compose default) remove_orphans - Remove containers for services not in the compose file wait - Block until services are healthy (adds `--wait`) timeout_seconds - Subprocess timeout (default 600s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Stop and remove containers, networks (and optionally volumes) for a compose project. args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override profiles - Profiles to consider volumes - Also remove named volumes declared by the project (destructive) remove_orphans - Remove containers not declared in the compose file timeout_seconds - Subprocess timeout (default 300s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
List containers in a compose project, parsed from `--format json`. args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override services - Restrict output to these services all - Include stopped containers as well returns: dict - {"services": list[dict], "raw": <CliResult dict>}; on non-zero exit `services` is an empty list and the caller should inspect `raw.stderr`.
Fetch a bounded slice of logs from a compose project (never follows). args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override services - Restrict to these services (default: all) tail - Lines per container (default 200; 0 = all, still capped at MAX_CLI_OUTPUT_BYTES) since - Show logs since this timestamp/duration (e.g. "10m", "2024-01-01T00:00:00") until - Show logs before this timestamp/duration timestamps - Include per-line timestamps returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Render the canonical compose configuration after merges, profiles, and variable substitution. args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override profiles - Profiles to activate before rendering services_only - List service names only (`--services`) format - "yaml" (default) or "json" returns: dict - {"config": str|dict|None, "raw": <CliResult dict>}; `config` is a parsed dict when format="json" and parsing succeeds, otherwise the rendered text from stdout.
Build images for a compose project. args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override services - Specific services to build (default: all) pull - Always attempt to pull a newer base image no_cache - Do not use cache when building timeout_seconds - Subprocess timeout (default 1800s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Pre-fetch images for a compose project's services without starting them. Use this to stage images before an outage window, to refresh cached images before `compose_up`, or to verify images are accessible without starting containers. For registry-authenticated pulls ensure the daemon is logged in first with `login`. `compose_up --pull always` does the same as part of startup; use this tool when you want to separate the pull step. args: project_dir - Dir containing the compose file (default: server cwd) files - Explicit compose file paths, passed as `-f` (overrides auto-discovery) project_name - Override the compose project name services - Pull only these services; omit to pull all ignore_pull_failures - Continue if an individual image pull fails timeout_seconds - Subprocess timeout (default 1800s for large image pulls) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Stop then start services without recreating containers or applying config changes. Use this to bounce a service (e.g. to pick up a runtime file change or clear an in-memory state). If the compose file has changed (new image, environment, volumes, ports) use `compose_up` instead — it recreates affected containers to apply the diff. `stop_timeout_seconds` controls the SIGTERM grace period before Docker sends SIGKILL. args: project_dir - Dir containing the compose file (default: server cwd) files - Explicit compose file paths, passed as `-f` project_name - Override the compose project name services - Restart only these services; omit to restart all stop_timeout_seconds - Seconds to wait for graceful stop before SIGKILL timeout_seconds - Subprocess timeout (default 300s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Stop services in a compose project without removing their containers. Unlike `compose_down`, containers/networks/volumes survive — use `compose_start` to bring them back. args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override services - Specific services to stop (default: all) stop_timeout_seconds - Grace period before SIGKILL (passed as `--timeout`) timeout_seconds - Subprocess timeout (default 300s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Start existing (stopped) containers of a compose project. Counterpart to `compose_stop`: starts existing containers without recreating them. Use `compose_up` to (re)create containers from the compose file. args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override services - Specific services to start (default: all) timeout_seconds - Subprocess timeout (default 600s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Run a one-off command against a compose service. Always passes `-T` (no TTY under MCP). Defaults to detached with `--rm` so the call returns promptly. args: service - Service name from the compose file command - Command + args to run (exec-form; no shell unless you invoke one) project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override detach - Run detached (default True) rm - Remove the container after the run (default True) no_deps - Don't start linked services workdir - Working directory inside the container user - User to run as inside the container (uid or name) env - Environment variables to set inside the container name - Optional container name timeout_seconds - Subprocess timeout (default 600s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Run a command inside an already-running compose service container. Always passes `-T` (no TTY). Pass an exec-form argv (e.g. `["python", "-V"]`); a `["sh", "-c", "..."]` form interprets shell metacharacters in untrusted substrings. args: service - Service name from the compose file command - Argv to execute inside the container project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override index - Container index when the service has multiple replicas (default 1) workdir - Working directory inside the container user - User to run as inside the container (uid or name) env - Environment variables to set for the exec session timeout_seconds - Subprocess timeout (default 60s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
List the images used by a compose project's services, parsed from `--format json`. args: project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override services - Restrict to these services (default: all) returns: list - One dict per container image (service, container, repository, tag, id, size)
Resolve the host binding for a service's container port. The compose equivalent of `docker port`: which host address/port a service's private port is published on. `published` is None when the port isn't published. args: service - Service name from the compose file private_port - The container-internal port to look up protocol - "tcp" (default) or "udp" index - Container index when the service has multiple replicas (default 1) project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override returns: dict - {"service", "private_port", "protocol", "published": "host:port"|None, "host": str|None, "port": int|None, "bindings": list[str]}. `published`/`host`/`port` describe the first binding; `bindings` lists every line (a port can be published on more than one address, e.g. IPv4 and IPv6).
Block until the named service containers stop, then return their exit codes. For one-shot / batch services. A long-running service that never exits blocks until `timeout_seconds`, then the subprocess is killed (TimeoutExpired) — bound it sensibly. Exit codes are on stdout. args: services - One or more services to wait on. At least one is required. project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override timeout_seconds - Subprocess timeout (default 300s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Show the running processes of a compose project's containers. Output is the `ps`-style process table per service (not JSON); read it from `stdout`. args: services - Restrict to these services (default: all) project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Copy files/folders between a service container and the server host's filesystem. Exactly one of `source`/`dest` is `SERVICE:PATH`; the other is a path on the host running this MCP server, read/written as the server's user (same host exposure as the file-path archive tools — see SECURITY.md). Copying to stdout (`dest="-"`) is unsupported; use the container-archive tools. args: source - `SERVICE:SRC_PATH` or a host path dest - `SERVICE:DEST_PATH` or a host path (not "-") index - Container index when the service has multiple replicas (default 1) all_containers - Copy to/from all containers of the service (`--all`) project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override timeout_seconds - Subprocess timeout (default 300s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Send a signal to a compose project's containers (default SIGKILL). args: services - Restrict to these services (default: all) signal - Signal to send (default "SIGKILL"; e.g. "SIGTERM", "SIGHUP") remove_orphans - Also remove containers for services not in the compose file project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Pause the containers of a compose project (freezes their processes). args: services - Restrict to these services (default: all) project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Unpause the containers of a compose project (resumes paused processes). args: services - Restrict to these services (default: all) project_dir - Dir with the compose file (default: server cwd) files - Explicit compose file paths (repeatable, `-f`) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
List compose projects known to the daemon (across all directories). args: all - Include stopped projects returns: list - One dict per project (parsed from `--format json`)
Create an immutable Swarm config object; requires a swarm manager. Configs store non-sensitive configuration files (nginx.conf, app.yaml, etc.) and mount them into service containers at a specified path. Unlike secrets, config data is not encrypted at rest — use `create_secret` for credentials or keys. `data` is raw bytes; encode strings first (e.g. `"my config".encode()`). Once created, a config is immutable: to update it, create a new config with a new name and update the service to reference it, then remove the old config with `remove_config`. args: name - Unique config name within the swarm data - Raw bytes content of the config file labels - Labels to apply to the config object templating - Templating driver config (e.g. {"Name": "golang"} for Go template syntax) returns: dict - The created config's attrs including its id
Get a swarm config by id. args: config_id - The config id returns: dict - The config's attrs
List swarm configs. args: filters - Filter by attributes (e.g. id, name, label) returns: list - A list of config attrs dicts
Remove a swarm config. args: config_id - The config id returns: bool - True after removal
Run a container from an image. args: image - The image to run command - The command to run in the container name - Name to assign to the container detach - Run in the background and return container info environment - Environment variables to set ports - Port mappings, e.g. {'2222/tcp': 3333} volumes - Volumes to mount network - Name of the network to attach hostname - Optional hostname for the container user - Username or UID to run as working_dir - Working directory inside the container entrypoint - Entrypoint to override the image default restart_policy - Restart policy, e.g. {'Name': 'on-failure', 'MaximumRetryCount': 3} labels - Labels to set on the container remove - Remove the container when it exits (only with detach=False) auto_remove - Enable auto-removal of the container on daemon side privileged - Give extended privileges to the container tty - Allocate a pseudo-TTY stdin_open - Keep STDIN open mem_limit - Memory limit cpu_count - Number of CPUs extra_kwargs - Additional keyword arguments forwarded to ContainerCollection.run returns: dict | str - Container attrs when detach=True, otherwise stdout/stderr as a string
Create a container without starting it. args: image - The image to use command - The command to run when started extra_kwargs - Additional keyword arguments forwarded to ContainerCollection.create returns: dict - The created container's attrs
Return the full inspect detail for a single container. Use this when you need complete information about one container — config, state, network settings, mounts, environment variables, and resource limits. For a quick overview of many containers use `list_containers` instead (returns a summary per container). For just logs or stats use `container_logs` / `container_stats`. args: id_or_name - Container id (full or short) or name returns: dict - Full container inspect attrs (equivalent to `docker inspect`)
List containers. args: all - Show all containers, including stopped ones since - Only show containers created after this id or name before - Only show containers created before this id or name limit - Maximum number of results filters - Filter by attributes (e.g. status, label) sparse - Skip inspect calls and return less detail ignore_removed - Ignore containers removed during listing managed_only - Only return containers created by this MCP server (filters on the docker-mcp-server.managed label); combines with any `filters` given returns: list - A list of container attrs dicts
Remove all stopped containers to reclaim disk space. Only removes containers that are not running — running containers are never affected. Use `list_containers(all=True)` to preview what would be removed before calling this. Valid filter keys: `until` (RFC3339 timestamp or duration like "24h" — removes containers stopped before that point), `label` (key or key=value). For a broader cleanup of containers plus unused images, networks, and volumes see the `prune_managed` prompt. args: filters - Narrow which stopped containers to remove; omit to remove all stopped returns: dict - {"ContainersDeleted": [...], "SpaceReclaimed": <bytes>}
Start an existing stopped container. Use this to restart a container that was previously created or stopped without removing it. To create and start a new container in one step use `run_container` instead. Calling on an already-running container has no effect (the daemon returns 304 and no error is raised). To stop then start a running container use `restart_container`. args: id_or_name - Container id (full or short) or name returns: dict - The container's full attrs after starting
Stop a container. args: id_or_name - The container id or name timeout - Seconds to wait before forcing termination returns: dict - The container's attrs after stop
Restart a container. args: id_or_name - The container id or name timeout - Seconds to wait before forcing restart returns: dict - The container's attrs after restart
Send a signal to a container. args: id_or_name - The container id or name signal - Signal to send (defaults to SIGKILL) returns: dict - The container's attrs after kill
Pause all processes in a container. args: id_or_name - The container id or name returns: dict - The container's attrs after pause
Resume all processes in a paused container. args: id_or_name - The container id or name returns: dict - The container's attrs after unpause
Remove a container. args: id_or_name - The container id or name v - Also remove anonymous volumes link - Remove the specified link force - Force remove a running container returns: bool - True after removal completes
Get the logs of a container. args: id_or_name - The container id or name stdout - Include stdout stderr - Include stderr timestamps - Include timestamps tail - Number of lines from the end, or the literal "all" since - Only return logs created after this unix timestamp until - Only return logs created before this unix timestamp returns: str - Decoded log output
Tail a container's log stream, bounded by `limit_lines`, `timeout_seconds`, or container exit. Returns when `limit_lines` lines are collected, `timeout_seconds` elapses, or the container exits, whichever comes first — so the agent can watch live output without blocking forever (`limit_lines` bounds memory, `timeout_seconds` bounds wall-clock for a quiet but long-lived container). Caveat for `ssh://` daemons: docker-py can't cancel an SSH stream, so the `timeout_seconds` watchdog can't interrupt a fully silent container — use `container_logs` (one-shot, non-streaming) there if you need a hard time bound. args: id_or_name - The container id or name limit_lines - Max lines to collect before returning (default 200) stdout - Include stdout stderr - Include stderr timestamps - Include timestamps since - Only return logs created after this unix timestamp timeout_seconds - Max wall-clock seconds to follow before returning what was collected (default 30) returns: str - Decoded log output containing up to `limit_lines` lines
Get a single resource usage stats snapshot for a container. args: id_or_name - The container id or name returns: dict - Decoded stats snapshot
Show the running processes inside a container. args: id_or_name - The container id or name ps_args - Arguments to pass to ps inside the container returns: dict - Output of the top command
Run a command inside a running container. Security: when any element of `cmd` is agent-controlled, use an exec-form argv list that does not invoke a shell (e.g. `["python", "-V"]`, `["ls", path]`). A string `cmd`, or a shell form like `["sh", "-c", template]`, interprets shell metacharacters in the untrusted parts. args: id_or_name - The container id or name cmd - Command to execute (prefer exec-form argv, no shell, when any element is agent-controlled) stdout - Attach to stdout stderr - Attach to stderr stdin - Attach to stdin tty - Allocate a pseudo-TTY privileged - Run with extended privileges user - User to run the command as detach - Detach from the exec environment - Environment variables workdir - Working directory inside the container demux - Return stdout and stderr separately returns: dict - Mapping with exit_code and output keys
Snapshot a container's current filesystem state as a new image. Useful for capturing a debugging state or saving manual changes made inside a container. For repeatable builds use a Dockerfile instead. The container is paused by default during the snapshot to ensure filesystem consistency — set `pause=False` only if the container cannot be paused. `changes` accepts Dockerfile instructions to apply on top of the snapshot, e.g. `["CMD ["python", "app.py"]", "ENV FOO=bar"]`. args: id_or_name - Container id or name to snapshot repository - Repository name for the new image, e.g. "myorg/myimage" tag - Tag for the new image (default: "latest") message - Commit message stored in the image metadata author - Author string stored in the image metadata pause - Pause the container during commit for consistency (default True) changes - Dockerfile instructions (CMD, ENV, EXPOSE, etc.) to apply to the image conf - Additional image configuration overrides as a dict returns: dict - The new image's attrs
Inspect changes on a container's filesystem. args: id_or_name - The container id or name returns: list - Filesystem changes since the image was created
Rename a container. args: id_or_name - The container id or name name - The new name returns: dict - The container's attrs after rename
Resize the tty session of a container. args: id_or_name - The container id or name height - New tty height in characters width - New tty width in characters returns: bool - True after the resize completes
Update resource limits on a container without recreating it. Changes take effect immediately on Linux (cgroups); not all fields are updatable on every platform. Common `updates` keys: `mem_limit` (bytes, e.g. 134217728 for 128 MB), `memswap_limit` (memory+swap in bytes; -1 = unlimited), `cpu_shares` (relative weight, default 1024), `cpu_period` / `cpu_quota` (microseconds for CFS throttling), `cpuset_cpus` (e.g. "0-1"), `restart_policy` (dict with `Name` such as "on-failure"/"always"/"unless-stopped" and optional `MaximumRetryCount`). To change image, env, or volumes the container must be recreated. args: id_or_name - Container id or name to update updates - Resource fields to update; see description for valid keys returns: dict - The container's full attrs after the update
Block until a container stops, then return its exit info. The default `timeout` is finite (600s) so the call can't block the MCP server indefinitely on a container that never reaches `condition`. When the timeout is exceeded a RuntimeError is raised (poll `get_container` instead, or pass a larger `timeout`). Pass `timeout=None` to restore the old unbounded behavior — only do so if you are sure the wait will complete. args: id_or_name - The container id or name timeout - Maximum seconds to wait before raising (default 600; None waits forever) condition - State to wait for: "not-running" (default), "next-exit", or "removed" returns: dict - The wait result with StatusCode and Error keys
Poll a container until its healthcheck reports `healthy` (or it stops, or the timeout elapses). Complements `wait_container` (which waits for *exit*): this waits for a running container to become *healthy*. Re-inspects every `poll_interval`s, never blocks past `timeout` (no exception on timeout — the result carries `timed_out: true`). Health comes from the container's HEALTHCHECK. With none defined, once the container is `running` the tool returns promptly with `health: null` and `healthy: false` (false = "not confirmed healthy", not "unhealthy" — check `health` to tell them apart). A container that exits before becoming healthy returns its terminal `status` and `healthy: false`. args: id_or_name - The container id or name timeout - Max seconds to wait before returning timed_out (default 120) poll_interval - Seconds between re-inspections (default 2, > 0); also capped by the time left, so a large value can't push the total wait past `timeout` returns: dict - {"container", "healthy", "health", "status", "waited_seconds", "timed_out"}; `health` is "starting"/"healthy"/"unhealthy" or null when no healthcheck is defined.
Export a container's filesystem as a tar archive, returned in band. For anything but a small container prefer `export_container_to_file`, which streams to a host path; the in-band bytes here are capped (default 32 MiB) because MCP base64-encodes them. args: id_or_name - The container id or name max_bytes - Abort with ValueError if the export exceeds this many bytes (defaults to 32 MiB) returns: bytes - The tar archive contents
Export a container's filesystem as a tar archive written to a file on the server host. Streams straight to disk (no in-band byte cap), so it handles large containers. The file is written by the server's user; `~` is expanded and an existing file is refused unless `overwrite=True`. args: id_or_name - The container id or name dest_path - Destination path on the server host for the tarball overwrite - Replace dest_path if it already exists (default False) returns: dict - {"path": <resolved path>, "bytes_written": int}
Retrieve a file or directory from a container as a tar archive, returned in band. For large paths prefer `get_container_archive_to_file`, which streams to a host path; the in-band bytes here are capped (default 32 MiB) because MCP base64-encodes them. args: id_or_name - The container id or name path - Path inside the container max_bytes - Abort with ValueError if the archive exceeds this many bytes (defaults to 32 MiB) returns: dict - Mapping with archive (bytes) and stat (dict) keys
Retrieve a file or directory from a container as a tar archive written to a file on the server host. Streams straight to disk (no in-band byte cap). The file is written by the server's user; `~` is expanded and an existing file is refused unless `overwrite=True`. args: id_or_name - The container id or name path - Path inside the container dest_path - Destination path on the server host for the tarball overwrite - Replace dest_path if it already exists (default False) returns: dict - {"path": <resolved path>, "bytes_written": int, "stat": dict}
Upload a tar archive to a path inside a container. For a tarball already on the server host, prefer `put_container_archive_from_file` — it streams from disk instead of carrying the (base64-encoded) bytes through the MCP protocol. args: id_or_name - The container id or name path - Destination path inside the container data - Tar archive bytes returns: bool - True if the upload succeeded
Upload a tar archive from a file on the server host to a path inside a container. Streams the file straight to the daemon, so it handles large archives that would be impractical to pass in band via `put_container_archive`. `file_path` is read by the server's user; `~` is expanded. args: id_or_name - The container id or name path - Destination path inside the container (must already exist) file_path - Path on the server host to the tar archive to upload returns: bool - True if the upload succeeded
List Docker CLI contexts known to the host running this MCP server. Contexts are a CLI concept (stored in the docker config dir) letting one CLI target multiple daemons. This server uses whatever DOCKER_HOST / current-context resolved to at startup, so changing contexts only affects future subprocess-based tools, not the docker-py SDK client. returns: list - One dict per context with at least name, description, dockerEndpoint, and current
Return the full configuration for a single Docker context. args: name - Context name (use the `Name` field from `context_ls`) returns: dict - The parsed `docker context inspect` entry for that context
Create a new Docker CLI context pointing at a daemon endpoint. args: name - Name for the new context (must not already exist) docker_host - Daemon URL, e.g. "tcp://10.0.0.5:2376" or "unix:///var/run/docker.sock" description - Optional human description shown in `context ls` tls_ca - Path on the local host to the CA cert (for TLS daemons) tls_cert - Path on the local host to the client cert tls_key - Path on the local host to the client key skip_tls_verify - Disable TLS verification (insecure; for testing only) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Set the active Docker context for the CLI on the host running this MCP server. Note: this does not retarget the long-lived docker-py client — SDK-backed tools keep using the endpoint they connected to at startup. To retarget those, restart the server with a different DOCKER_HOST / DOCKER_CONTEXT. args: name - Existing context name to set as default returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Remove a Docker CLI context. args: name - Context name to remove force - Force removal even if the context is the current one returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Build an image from a Dockerfile using the daemon's classic builder. Use this for simple single-platform builds from a local context. For multi-platform builds, BuildKit cache export/import, or advanced build features prefer `buildx_build`. `path` must be a directory accessible on the host running this server (it is the build context sent to the daemon). `dockerfile` is relative to `path`; omit to use the default `Dockerfile`. args: path - Build context directory path on the server host tag - Name and optional tag in "name:tag" format to apply to the built image quiet - Suppress verbose build output (final image id still returned) nocache - Ignore the layer cache and rebuild all layers rm - Remove intermediate containers on success (default True) pull - Always pull a newer version of each FROM base image before building forcerm - Remove intermediate containers even on build failure dockerfile - Dockerfile filename relative to path (default: "Dockerfile") buildargs - Build-time variables passed as `--build-arg`; dict of str→str container_limits - Resource limits for the build container, e.g. {"memory": 134217728} shmsize - Size of /dev/shm in bytes for build steps that need shared memory labels - Labels to apply to the resulting image; dict of str→str cache_from - List of image references to use as layer cache sources target - Stop at this named build stage (multi-stage Dockerfiles) network_mode - Network mode for RUN instructions during build (e.g. "host", "none") squash - Squash all new layers into one (experimental; requires daemon flag) extra_hosts - Additional /etc/hosts entries during build; dict of hostname→ip platform - Target platform, e.g. "linux/amd64" (single platform only; use buildx for multi) isolation - Windows isolation technology ("default", "process", "hyperv") use_config_proxy - Forward proxy env vars from Docker client config to build returns: dict - The built image's attrs
Get an image by name or id. args: name - The image name or id returns: dict - The image's attrs
Get registry data for an image without pulling it. Security: `auth_config` carries registry credentials, which many MCP clients log verbatim. Prefer `docker login` on the host so the `docker` module reuses credentials cached in `~/.docker/config.json`, and leave `auth_config` unset. args: name - Image reference auth_config - Optional registry authentication config returns: dict - Registry data attrs
List images on the server. args: name - Only show images of this repository all - Show intermediate image layers filters - Filter by attributes (label, dangling, before, since, etc.) returns: list - A list of image attrs dicts
Pull an image of the given name. args: repository - The image repository tag - The image tag (ignored when all_tags=True) all_tags - Pull all tags from the repository platform - Platform in os/arch format returns: dict | list - Pulled image attrs (or a list of attrs if all_tags=True)
Push an image or repository to a registry. Security: `auth_config` carries registry credentials, which many MCP clients log verbatim. Prefer `docker login` on the host so the `docker` module reuses credentials cached in `~/.docker/config.json`, and leave `auth_config` unset. args: repository - The image repository tag - The tag to push auth_config - Optional registry authentication config returns: str - Push output as a string
Remove a local image by name or id. Fails without `force` if the image is tagged by multiple names (untag first with `tag_image`) or if stopped containers reference it. Running containers always block removal regardless of `force`. `noprune` keeps untagged parent layers that would otherwise be removed as a side-effect; leave False unless you need to preserve the parent layers for another purpose. args: image - Image name (with optional tag/digest) or id to remove force - Remove even if referenced by stopped containers or multiple tags noprune - Do not delete untagged intermediate parent layers returns: bool - True after removal completes
Search Docker Hub for public images matching a term. Searches Docker Hub only — not GHCR, ECR, or other registries. For listing tags on a specific image from any OCI registry use `registry_list_tags` instead. Each result dict includes `name`, `description`, `star_count`, `is_official`, and `is_automated`. args: term - Search keyword, e.g. "nginx" or "python" limit - Maximum number of results to return (Docker Hub default is 25) returns: list - List of matching image dicts from Docker Hub
Remove unused local images to reclaim disk space. Without filters removes only "dangling" images — untagged layers not referenced by any tag or container. To remove all images not used by any container (including tagged ones) pass `filters={"dangling": False}`. Valid filter keys: `dangling` (bool as string "true"/"false"), `until` (RFC3339 timestamp or duration like "24h"), `label` (key or key=value). Use `df` first to see how much space is reclaimable. args: filters - Narrow which images to remove; omit to remove dangling images only returns: dict - {"ImagesDeleted": [...], "SpaceReclaimed": <bytes>}
Load an image from a tarball produced by save_image. For a tarball already on the host running this server, prefer `load_image_from_file` — it streams from disk instead of carrying the (base64-encoded) bytes through the MCP protocol. args: data - Tarball contents returns: list - A list of loaded image attrs dicts
Load an image from a tar archive on the host running this MCP server. Streams the file straight to the daemon, so it handles arbitrarily large images that would be impractical to pass in band via `load_image`. The path is read by the server's user; `~` is expanded. args: file_path - Path to a tarball produced by `docker save` / `save_image_to_file` returns: list - A list of loaded image attrs dicts
Save an image as a tar archive, returned in band. For anything but a small image prefer `save_image_to_file`, which streams to a host path; the in-band bytes here are capped (default 32 MiB) because MCP base64-encodes them into the agent's context. args: name - Image name or id named - Whether to keep the image name when saving max_bytes - Abort with ValueError if the tarball exceeds this many bytes (defaults to 32 MiB) returns: bytes - The tarball contents
Save an image as a tar archive written to a file on the host running this MCP server. Streams the archive straight to disk (no in-band byte cap), so it handles large images. The file is written by the server's user; `~` is expanded and an existing file is refused unless `overwrite=True`. args: name - Image name or id dest_path - Destination path on the server host for the tarball named - Whether to keep the image name when saving overwrite - Replace dest_path if it already exists (default False) returns: dict - {"path": <resolved path>, "bytes_written": int}
Tag an image into a repository. args: name - The source image name or id repository - Target repository name tag - Optional tag for the new image force - Force the tag returns: bool - True if the image was tagged
Return the layer history of an image. Useful for auditing what commands built each layer and diagnosing image size. Each entry includes `Id` (layer digest or "<missing>" for imported layers), `Created` (unix timestamp), `CreatedBy` (the Dockerfile command that produced the layer, e.g. a RUN or COPY), `Size` (bytes added by that layer), and `Comment`. For full image metadata use `get_image` instead. args: name - Image name (with optional tag/digest) or id returns: list - Layer history entries, newest first
Create a network. args: name - The name of the network driver - Driver name (e.g. bridge, overlay) options - Driver-specific options ipam - IPAM configuration as a dict check_duplicate - Reject creation if a duplicate name exists internal - Restrict external access labels - Labels to set on the network enable_ipv6 - Enable IPv6 networking attachable - Allow standalone containers to attach (swarm) scope - Network scope (local, global, swarm) ingress - Make this an ingress network for swarm routing-mesh returns: dict - The created network's attrs
Get a network by id or name. args: network_id - The network id or name returns: dict - The network's attrs
List networks. args: names - Filter by network names ids - Filter by network ids filters - Additional filters greedy - Fetch extended details per network managed_only - Only return networks created by this MCP server (filters on the docker-mcp-server.managed label); combines with any `filters` given returns: list - A list of network attrs dicts
Remove networks that have no active container endpoints. Built-in networks (bridge, host, none) are never removed. Only networks with zero connected containers are eligible. Valid filter keys: `until` (RFC3339 timestamp or duration — removes networks created before that point), `label` (key or key=value). args: filters - Narrow which networks to remove; omit to remove all unused custom networks returns: dict - {"NetworksDeleted": [...]}
Remove a network. args: network_id - The network id or name returns: bool - True after removal
Attach a running container to an additional network without restarting it. Use this to give a container access to services on a network it was not started with. `aliases` sets extra DNS names for this container within the network (other containers can reach it by those names in addition to its container name). `ipv4_address` / `ipv6_address` assign a specific IP on the network; omit to let the driver assign one. `links` is a legacy feature (deprecated; prefer DNS aliases). Use `disconnect_network` to undo. args: network_id - Network id or name to connect the container to container - Container id or name to attach aliases - Additional DNS names for this container within the network links - Legacy container links (deprecated) ipv4_address - Static IPv4 address to assign on this network ipv6_address - Static IPv6 address to assign on this network link_local_ips - Link-local IP addresses to assign driver_opt - Driver-specific endpoint options returns: bool - True after the container is connected
Disconnect a container from a network. args: network_id - The network id or name container - The container id or name force - Force disconnect returns: bool - True after the container is disconnected
Get a swarm node by id or name. args: id_or_name - The node id or name returns: dict - The node's attrs
List swarm nodes. args: filters - Filter by attributes (id, name, membership, role) returns: list - A list of node attrs dicts
Update a node's spec (availability, name, role, labels). args: id_or_name - The node id or name node_spec - The new node spec returns: bool - True after the update
Remove a node from the swarm. A node should normally be drained (`update_node` with Availability "drain") and have left the swarm first, so its tasks reschedule cleanly. Removing an active/reachable node requires `force=True`. args: node_id - The node id or name to remove force - Force removal of an active/reachable node returns: bool - True after the node is removed
Get an installed plugin by name. args: name - The plugin name returns: dict - The plugin's attrs
Install a plugin from Docker Hub. `remote_name` is a Docker Hub reference in `author/name:tag` form, e.g. `vieux/sshfs:latest`. The daemon handles permission grants non-interactively. After installation use `get_plugin` to confirm the plugin's enabled state, then call `enable_plugin` to activate it if needed, and optionally `configure_plugin` first if it requires settings. Use `list_plugins` to list all plugins, or `remove_plugin` to uninstall. args: remote_name - Docker Hub plugin reference, e.g. "vieux/sshfs:latest" local_name - Alias to refer to the plugin locally; defaults to remote_name returns: dict - The installed plugin's attrs
List installed plugins. returns: list - A list of plugin attrs dicts
Set runtime configuration options on an installed plugin. Use `get_plugin` first to see which keys the plugin exposes under `Settings.Env`; pass those same keys as a plain dict, e.g. `{"DEBUG": "1", "SOCKET": "/run/x.sock"}`. The plugin must be disabled before reconfiguring — call `disable_plugin` first if it is currently active, then `enable_plugin` afterwards to apply the new settings. args: name - Plugin name or id (e.g. "vieux/sshfs:latest") options - Key/value settings to apply, matching the plugin's declared env keys returns: bool - True after configuration
Disable a plugin so it stops intercepting Docker API calls; the plugin remains installed. A disabled plugin cannot be used by new containers but existing containers that already have it attached are unaffected. Use `force=True` to disable even if active containers are still using it — this may cause those containers to lose access to plugin-provided resources (e.g. a volume driver). Re-enable with `enable_plugin`. args: name - Plugin name or id force - Disable even if active containers are using the plugin (may disrupt them) returns: bool - True after the plugin is disabled
Activate an installed plugin so Docker routes relevant API calls through it. Activates a plugin that is currently disabled — either freshly installed or previously disabled via `disable_plugin`. If the plugin exposes configuration (check via `get_plugin`), call `configure_plugin` while it is still disabled before enabling it. `timeout` controls how long Docker waits for the plugin process to become healthy; 0 means wait indefinitely. args: name - Plugin name or id to enable timeout - Seconds to wait for the plugin to become healthy (0 = no timeout) returns: bool - True after the plugin is enabled
Push a locally built or pulled plugin image to a remote registry. The daemon must already be authenticated with the target registry — call `login` first if needed. `name` must include the registry host for any registry other than Docker Hub, e.g. "registry.example.com/myplugin:1.0". The plugin must already exist locally (installed via `install_plugin` or built externally with `docker plugin create`). args: name - Plugin name including tag, e.g. "myorg/myplugin:latest" returns: dict - Push progress/status events returned by the daemon
Remove a plugin. args: name - The plugin name force - Force removal even if the plugin is enabled returns: bool - True after removal
Upgrade a plugin. args: name - The plugin name remote - Remote reference to upgrade from (defaults to current name) returns: bool - True after the upgrade completes
List tags for an image in an OCI v2 registry without pulling. Works against Docker Hub, GHCR, ECR, GAR, and any OCI-compliant registry; anonymous if no credentials are passed. Talks directly to the registry over HTTPS and does NOT read `~/.docker/config.json` — for private registries prefer the DOCKER_MCP_SERVER_REGISTRY_USERNAME / DOCKER_MCP_SERVER_REGISTRY_PASSWORD env vars (keeps secrets out of tool args, which clients often log). args: image - Image ref, e.g. "alpine", "ghcr.io/org/repo"; any `:tag`/`@digest` is stripped username - Optional registry username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME) password - Optional registry password/token (overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD) limit - Max tags to return (default 1000, >= 1); pagination capped at 50 pages returns: dict - {"name": <repo>, "registry": <host>, "tags": [..], "truncated": bool}
Fetch the manifest for an image reference without pulling. May return a single-platform image manifest or a multi-platform manifest list / OCI image index, depending on what the registry serves for that tag. args: image - Image ref, e.g. "ghcr.io/org/repo"; `:tag`/`@digest` is stripped — pass via `reference` reference - Tag or digest (default "latest") username - Optional registry username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME; no config.json) password - Optional registry password/token (overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD) returns: dict - {"name", "registry", "reference", "media_type", "digest", "manifest": <JSON body>}
Fetch and parse an image's config blob from a registry without pulling. Answers "what's inside this image?" — env vars, entrypoint/cmd, workdir, exposed ports, user, labels, layer history (what `registry_inspect_manifest` only points at via `config.digest`). Resolves in up to three hops: manifest -> (if multi-platform) the `platform` entry's manifest -> the config blob. args: image - Image ref, e.g. "ghcr.io/org/repo"; `:tag`/`@digest` is stripped — pass via `reference` reference - Tag or digest (default "latest") platform - Platform to select from a multi-platform image, "os/arch[/variant]" (default "linux/amd64"); ignored for single-platform images username - Optional registry username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME) password - Optional registry password/token (overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD) returns: dict - {"name", "registry", "reference", "platform", "config_digest", "config": <parsed>}; `platform` is the selected platform (None if single-platform)
List tags on a Docker Hub repository with Hub-specific metadata. Hits the Hub UI API (hub.docker.com) for richer per-tag data than `registry_list_tags` — last pushed date, per-platform sizes, digest. Public repos only: sends no auth and does NOT read `~/.docker/config.json`; private repos return 404/401 (use `registry_list_tags` against registry-1.docker.io with credentials). args: repository - Hub repository, e.g. "library/alpine" or "myorg/myimage" limit - Max tags to return (default 100, >= 1); pagination capped at 50 pages returns: dict - {"name": <repo>, "tags": [{name, full_size, last_updated, digest, images}, ...], "truncated": bool}
Fetch Docker Hub metadata for a repository. Public repos only: sends no auth and does NOT read the local Docker credential store; private repos return 404/401. args: repository - Hub repository, e.g. "library/alpine" or "myorg/myimage" returns: dict - The Hub /v2/repositories/<repo>/ response (description, star_count, pull_count, last_updated, is_private, etc.)
Report the caller's remaining Docker Hub pull-rate-limit budget. Sends a HEAD to the `ratelimitpreview/test` manifest (a HEAD isn't metered as a pull, so the check costs no budget) and reads the RateLimit-Limit / RateLimit-Remaining headers. Call it before a large `compose_pull` / `pull_image` to avoid hitting the cap mid-deploy. Credentials raise the limit and switch metering from per-IP to per-account; falls back to DOCKER_MCP_SERVER_REGISTRY_USERNAME / DOCKER_MCP_SERVER_REGISTRY_PASSWORD, does NOT read `~/.docker/config.json`. Plans with no limit return no headers — reported as `"unlimited": true`. args: username - Optional Hub username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME) password - Optional Hub password/token (overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD) returns: dict - {"authenticated", "limit", "remaining", "window_seconds", "unlimited"}
List vulnerabilities (CVEs) in an image via Docker Scout. Anonymous scans work for public images; Hub policy enforcement and richer recommendations need `docker login` on the host running this MCP server. args: image - Image reference (a tag or a digest) only_fixed - Only report CVEs with a fixed version available only_severity - Filter to severities: "critical", "high", "medium", "low", "unspecified" ignore_base - Exclude CVEs introduced by the base image format - Output format: "json" (default; parsed into the return dict), "sarif", "spdx", "list", "markdown", or "text" platform - Platform of the image to analyze, e.g. "linux/amd64" returns: dict - {"format": <format>, "result": <parsed-json-or-raw-text>, "raw": <CliResult dict>}
Render a compact summary of an image's CVE posture. args: image - Image reference format - Output format: "json" (default) or "text" platform - Platform of the image to analyze, e.g. "linux/amd64" returns: dict - {"format": <format>, "result": <parsed-json-or-raw-text>, "raw": <CliResult dict>}
Suggest base-image upgrades for an image. Computed against Docker Scout's catalog; generally needs `docker login` on the host running this MCP server to return useful results for private or rarely-scanned base images. args: image - Image reference only_refresh - Only show "refresh" recommendations (same major/minor) only_update - Only show "update" recommendations (newer minor/major) tag - Restrict to suggestions matching this tag pattern format - Output format: "json" (default) or "text" platform - Platform of the image to analyze returns: dict - {"format": <format>, "result": <parsed-json-or-raw-text>, "raw": <CliResult dict>}
Compare two image references and report the CVE delta. Exactly one of `to`, `to_env`, or `to_latest=True` must be supplied to identify the comparison target. args: image - The new / candidate image reference to - Compare against this image reference, directory, or archive to_env - Compare against an image associated with this Scout environment to_latest - Compare against the latest scan of `image` only_severity - Filter to severities ("critical", "high", "medium", "low", "unspecified") ignore_unchanged - Exclude unchanged packages from the diff format - Output format: "json" (default), "markdown", or "text" platform - Platform of the image to analyze returns: dict - {"format": <format>, "result": <parsed-json-or-raw-text>, "raw": <CliResult dict>}
Generate a Software Bill of Materials (SBOM) for an image. SBOMs can be large; captured stdout is subject to MAX_CLI_OUTPUT_BYTES and may be truncated for big images. If that's a concern, run `docker scout sbom -o file.json …` on the host and load the file separately. args: image - Image reference format - SBOM format: "spdx" (default, SPDX JSON), "cyclonedx" (CycloneDX JSON), "json" (Scout's native JSON), "list" (plain-text package list) platform - Platform of the image to analyze returns: dict - {"format", "result", "raw": <CliResult dict>}. `result` is a parsed dict when `format` is "spdx"/"cyclonedx"/"json" and stdout parses cleanly; for "list" or a parse failure it's the raw text.
Create a swarm secret. args: name - The name of the secret data - The secret payload labels - Labels to apply driver - Optional secret driver configuration returns: dict - The created secret's attrs
Get a swarm secret by id. args: secret_id - The secret id returns: dict - The secret's attrs
List swarm secrets. args: filters - Filter by attributes (e.g. id, name, label) returns: list - A list of secret attrs dicts
Remove a Swarm secret; requires a swarm manager. Removing a secret does not immediately affect running service tasks — tasks that already have the secret mounted retain access until they are restarted or the service is updated. Use `list_services` and inspect each service's spec via `get_service` to identify services that mount the secret before removing it (service filters do not support filtering by secret reference). The secret id (not name) is required; retrieve it from `list_secrets` or `get_secret`. args: secret_id - The secret id to remove returns: bool - True after removal
Create a Swarm service; requires a swarm manager node. Use this instead of `run_container` when you need replicated or global scheduling, rolling updates, or automatic restart across the swarm. Common `extra_kwargs` keys: `name` (str), `env` (list of "KEY=VAL"), `mode` ({"Replicated": {"Replicas": N}} or {"Global": {}}), `networks` (list of network names/ids), `endpoint_spec` ({"Ports": [{"PublishedPort": 80, "TargetPort": 8080}]}), `labels` (dict), `restart_policy` ({"Condition": "on-failure", "MaxAttempts": 3}), `resources` ({"Limits": {"NanoCPUs": 500000000, "MemoryBytes": 134217728}}). args: image - Image to run service tasks from (e.g. "nginx:alpine") command - Override the image's default command; string or list of strings extra_kwargs - Additional docker-py ServiceCollection.create keyword arguments returns: dict - The created service's attrs
Get a swarm service by id or name. args: service_id - The service id or name insert_defaults - Merge default values into the output returns: dict - The service's attrs
List swarm services. args: filters - Filter by attributes (id, name, label, mode) managed_only - Only return services created by this MCP server (filters on the docker-mcp-server.managed label); combines with any `filters` given returns: list - A list of service attrs dicts
Update a swarm service's configuration. args: service_id - The service id or name updates - Fields to update on the service returns: bool - True after the update
Stop and remove a swarm service. args: service_id - The service id or name returns: bool - True after the service is removed
List the tasks of a swarm service. args: service_id - The service id or name filters - Filter by id, name, node, label, desired-state returns: list - A list of task dicts
Get a bounded snapshot of a swarm service's logs (never follows). `follow` is intentionally not exposed: the stream is joined into one string before returning, so following would block forever and grow unbounded. Collection is capped at `max_bytes` (ValueError if exceeded) so a noisy service can't OOM the server. The default `tail="all"` returns the whole buffer, which can be huge on long-running services and exceed the agent's context — pass an integer (e.g. `tail=500`) or use `since` to constrain output. args: service_id - The service id or name details - Show extra details stdout - Include stdout stderr - Include stderr since - Show logs since this Unix timestamp timestamps - Include timestamps tail - Number of lines from the end, or the literal "all" max_bytes - Abort with ValueError if the buffered logs exceed this many bytes (default 32 MiB) returns: str - Decoded log output
Scale a swarm service to a number of replicas. args: service_id - The service id or name replicas - The desired number of replicas returns: bool - True after scaling
Force update a swarm service even if its config has not changed. args: service_id - The service id or name returns: bool - True after the force update
Roll a swarm service back to its previous spec (the docker `service rollback` equivalent). Re-applies the service's `PreviousSpec` — the spec from before the most recent `update_service` / `scale_service` / `force_update_service`. Raises ValueError if the service has no PreviousSpec (it has never been updated, or was already rolled back). The high-level SDK exposes no rollback, so this reads the current version and previous spec via the low-level APIClient and submits them with `update_service`. args: service_id - The service id or name returns: dict - The daemon response (a dict with a "Warnings" key)
Deploy (or update) a stack to the swarm from one or more Compose files. Requires the target daemon to be a swarm manager. Re-running with the same `stack_name` updates the stack in place. Defaults to `detach=True` (returns once specs are submitted, not on convergence); set `detach=False` to wait for the rollout (give it a generous `timeout_seconds`). args: stack_name - Name of the stack to create or update compose_files - One or more Compose file paths (repeated `-c`; later override earlier). At least one required. with_registry_auth - Send registry credentials to swarm agents (needed for private images) prune - Remove services no longer defined in the Compose file resolve_image - Image-digest resolution: "always" (default), "changed", or "never" detach - Return immediately after submitting specs (True) vs wait for convergence (False) cwd - Working directory for resolving relative Compose paths (defaults to the server's cwd) timeout_seconds - Subprocess timeout (default 1800s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
List the stacks deployed to the swarm, parsed from `--format '{{json .}}'`. Requires the target daemon to be a swarm manager (raises otherwise). returns: list - One dict per stack (name, services count, orchestrator)
List the tasks of a stack, parsed from `--format '{{json .}}'`. args: stack_name - The stack to list tasks for no_trunc - Do not truncate task IDs / errors in the output filters - Repeatable `--filter` expressions, e.g. ["desired-state=running"] returns: list - One dict per task (id, name, node, image, desired/current state, error)
List the services of a stack, parsed from `--format '{{json .}}'`. args: stack_name - The stack to list services for filters - Repeatable `--filter` expressions, e.g. ["name=web"] returns: list - One dict per service (id, name, mode, replicas, image, ports)
Remove one or more stacks from the swarm (tears down their services, networks, and secrets). Destructive: this stops and deletes every service in the named stack(s). Defaults to `detach=True` so the call returns once removal is requested rather than waiting for teardown. args: stack_names - One or more stack names to remove. At least one is required. detach - Return immediately (True) vs wait for the stack(s) to be fully removed (False) timeout_seconds - Subprocess timeout (default 300s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}
Initialize a new swarm on this Engine. args: advertise_addr - Externally reachable address advertised to other nodes listen_addr - Listen address used for inter-manager communication force_new_cluster - Force a new cluster from current state default_addr_pool - IP address pools for swarm overlay networks subnet_size - Subnet size for the IP pool data_path_addr - Address to use for data path traffic data_path_port - Port number for data path traffic name - Name of the swarm labels - User-defined key/value metadata autolock_managers - Encrypt manager keys at rest log_driver - Default log driver configuration returns: str - The node id of the newly created swarm manager
Join an existing swarm. args: remote_addrs - Addresses of swarm managers to connect to join_token - The swarm join token listen_addr - Listen address for inter-manager communication advertise_addr - Advertised address data_path_addr - Data path address returns: bool - True after the engine joins the swarm
Leave the current swarm. args: force - Force leave even if the node is a manager returns: bool - True after leaving the swarm
Update swarm-wide settings; currently exposes token and unlock-key rotation. Must be called on a swarm manager node. Token rotation invalidates the old join token immediately — nodes that have not yet joined using the old token must use the new one. Existing joined nodes are unaffected. Use `get_swarm_join_tokens` to retrieve the new tokens after rotation. Rotating the unlock key requires all managers to be re-unlocked on restart with the new key; retrieve it immediately via `get_swarm_unlock_key`. args: rotate_worker_token - Issue a new worker join token, invalidating the current one rotate_manager_token - Issue a new manager join token, invalidating the current one rotate_manager_unlock_key - Issue a new autolock unlock key for manager restart returns: bool - True after the update completes
Reload the swarm and return its current attrs. returns: dict - The swarm's current attrs
Unlock a manager node that is locked after restart due to autolock being enabled. When autolock is enabled (via `init_swarm` or `update_swarm`), manager nodes require the unlock key after every restart before they can rejoin the swarm and resume scheduling. Must be called on the locked manager node directly. Retrieve the current unlock key with `get_swarm_unlock_key` from any unlocked manager — store it securely when enabling autolock. A locked node cannot serve API requests and cannot return its own key while locked; other unlocked managers in the swarm can still serve the key. Once unlocked the manager resumes automatically. args: key - The swarm unlock key (from `get_swarm_unlock_key`) returns: bool - True after the swarm is unlocked
Return the swarm unlock key. returns: dict - The unlock key info
Return the swarm's worker and manager join tokens. These are the tokens a new node passes to `join_swarm` — without one, `join_swarm` cannot be called, so this closes the init -> join loop. The tokens are secret bearer credentials (anyone holding the manager token can join as a manager); treat the result as sensitive and avoid logging it. Reads `swarm.attrs["JoinTokens"]` after a reload, so it always reflects the current tokens. returns: dict - {"Worker": <worker join token>, "Manager": <manager join token>}
Rotate the worker and/or manager join token, then return the fresh tokens. Rotating invalidates the old token immediately — nodes that have already joined are unaffected, but any pending invitations using the old token will fail. At least one of `rotate_worker` / `rotate_manager` must be True. Wraps `swarm.update(rotate_*_token=...)` and re-reads the tokens so the caller gets the new value in one step. args: rotate_worker - Rotate the worker join token rotate_manager - Rotate the manager join token returns: dict - {"Worker": <worker join token>, "Manager": <manager join token>} after rotation
Create a volume managed by Docker. Named volumes persist after their containers stop or are removed; use them for databases, uploads, or any data that must outlive a container. Anonymous volumes (no `name`) are only removed automatically when the container was started with `--rm` or removed with `docker rm -v`; otherwise they accumulate and must be pruned manually. Common `driver_opts` for the default `local` driver: bind-mount an existing host path with `{"type": "none", "device": "/host/path", "o": "bind"}`, or mount an NFS share with `{"type": "nfs", "device": "server:/export", "o": "addr=server,rw"}`. Third-party drivers (e.g. `rexray`, `convoy`) accept their own option keys. args: name - Volume name; auto-generated if omitted (creates an anonymous volume) driver - Volume driver to use (default: "local") driver_opts - Driver-specific options dict labels - Labels to set on the volume returns: dict - The created volume's attrs
Get a volume by name. args: volume_id - The volume name returns: dict - The volume's attrs
List volumes. args: filters - Filter by attributes (e.g. dangling, name, label) managed_only - Only return volumes created by this MCP server (filters on the docker-mcp-server.managed label); combines with any `filters` given returns: list - A list of volume attrs dicts
Remove unused volumes. args: filters - Filters to apply returns: dict - Information on deleted volumes and reclaimed space
Remove a volume. args: volume_id - The volume name force - Force removal returns: bool - True after removal
Overview
What is Docker MCP Server?
Docker MCP Server is a fully featured Model Context Protocol server that lets AI agents manage Docker environments—containers, images, networks, volumes, swarm services, secrets, configs, nodes, plugins, and more. It works out of the box with no configuration, auto‑discovers your local Docker socket, and supports advanced setups with multiple local or remote daemons (over TCP, TLS, or SSH) and read‑only modes.
How to use Docker MCP Server?
Install and run the server; it automatically discovers your local Docker socket and exposes the full command surface to your AI agent. For advanced use, configure multiple daemons and mark some as read‑only. The server can be run natively, as an mcpb bundle (desktop extension), or containerized.
Key features of Docker MCP Server
- Manages containers, images, networks, volumes, swarm services.
- Supports multiple Docker daemons (local and remote) in one session.
- Read‑only and no‑destructive tool modes for safe monitoring.
- Exposes container logs and stats as MCP resources.
- Optimized for lazy tool loading; can exclude tool domains.
- Runs entirely locally with no telemetry.
Use cases of Docker MCP Server
- Monitor and triage container crashes using live logs.
- Check the health and state of a Docker Swarm.
- Diagnose memory pressure in Docker environments.
- Analyze disk usage of Docker volumes
More Cloud & Infrastructure MCP servers
AWS MCP
RafalWilinskiTalk with your AWS using Claude. Model Context Protocol (MCP) server for AWS. Better Amazon Q alternative.
tfmcp: Terraform Model Context Protocol Tool
nwiizo🌍 Terraform Model Context Protocol (MCP) Tool - An experimental CLI tool that enables AI assistants to manage and operate Terraform environments. Supports reading Terraform configurations, analyzing plans, applying configurations, and managing state with Claude Desktop integrati
MCP Gateway
mcp-ecosystem🧩 MCP Gateway - A lightweight gateway service that instantly transforms existing MCP Servers and APIs into MCP servers with zero code changes. Features Docker deployment and management UI, requiring no infrastructure modifications.
MCP Server that interacts with Azure AI Foundry (experimental)
azure-ai-foundryA MCP Server for Azure AI Foundry: it's now moved to cloud, check the new Foundry MCP Server
Azure DevOps MCP Server
Tiberriver256An MCP server for Azure DevOps
Comments