Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
DOCKER_HOSTNoDocker daemon endpoint (e.g., tcp://..., unix://..., ssh://...). Used when DOCKER_MCP_SERVER_HOSTS is not set.
SSH_AUTH_SOCKNoPath to SSH agent socket for SSH-based remote daemon connections.
DOCKER_CONTEXTNoName of Docker context to use for resolving the default daemon.
DOCKER_CERT_PATHNoPath to directory containing TLS certificates (ca.pem, cert.pem, key.pem).
DOCKER_TLS_VERIFYNoSet to '1' to enable TLS verification for the Docker daemon connection.
DOCKER_MCP_SERVER_HOSTSNoComma-separated list of name=endpoint pairs for multiple daemons. e.g., 'local=auto, prod=ssh://user@host(ro)'
DOCKER_MCP_SERVER_DISABLENoComma-separated list of domains to disable (e.g., 'swarm,buildx,scout').
DOCKER_MCP_SERVER_READONLYNoSet to '1', 'true', 'yes', or 'on' to register only read-only tools.
DOCKER_MCP_SERVER_NO_LABELSNoSet to '1' to disable provenance labels on created Docker objects.
DOCKER_MCP_SERVER_NO_DESTRUCTIVENoSet to '1', 'true', 'yes', or 'on' to register everything except destructive tools.
DOCKER_MCP_SERVER_REGISTRY_PASSWORDNoPassword or token for private registry authentication.
DOCKER_MCP_SERVER_REGISTRY_USERNAMENoUsername for private registry authentication (fallback when not provided in tool call).
DOCKER_MCP_SERVER_ALLOW_SELF_TERMINATENoSet to '1' to allow destructive actions on the server's own container (bypasses self-termination guard).

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
buildx_buildA

Build an image with BuildKit via docker buildx build.

Replaces the legacy image_build 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. With no local buildx plugin and an ssh:// target, the build runs on that host: a local context directory is copied there honouring .dockerignore, as are file, build_contexts and secret paths. Raises RuntimeError in that case for output/cache_to with a filesystem dest=, cache_from with a local src=, or any ssh= — each would resolve on the remote machine, losing the output or silently changing the build.

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. Copied to the target host when it names a local directory and there is no local plugin. tags - Image references to apply (-t, repeatable) platforms - Target platforms, e.g. ["linux/amd64", "linux/arm64"] file - Dockerfile path. A relative path resolves against this server's working directory (buildx's own rule), NOT against context — pass e.g. "ctx/Dockerfile" for a Dockerfile inside the context directory "ctx". build_args - Build-time variables (each becomes --build-arg KEY=VALUE) build_contexts - Additional named build contexts (e.g. {"deps": "./vendor"}) labels - Labels to set on the resulting image (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"]). A filesystem dest= is refused when the build has to run on a remote host; dest=- (stdout) is fine. 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). Refused when the build has to run on a remote host: the socket read would be that host's. timeout_seconds - Subprocess timeout (default 1800s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

buildx_bakeA

Build multiple targets defined in a bake file (HCL, JSON, or compose).

Use it for multi-target builds declared in docker-bake.hcl/compose files; for a single Dockerfile target use buildx_build. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

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; copied to the target host if no local plugin) timeout_seconds - Subprocess timeout (default 1800s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

buildx_imagetools_inspectA

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. Uses the docker CLI's credential store; registry_manifest answers the same question over direct HTTPS with no daemon or plugin.

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.

buildx_imagetools_createA

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. Verify the result with buildx_imagetools_inspect. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

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 descriptor_files - Files to read source descriptors from, instead of refs (copied to the target host if no local plugin) builder - Override the active builder timeout_seconds - Subprocess timeout (default 600s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

buildx_listA

List builder instances.

Machine-parsed view of every builder; use buildx_inspect for one builder's human-readable detail and buildx_use to switch the default. Raises RuntimeError if the CLI call fails.

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.

buildx_history_listA

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)

buildx_history_inspectA

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_list. Requires buildx >= v0.13. Raises RuntimeError if the CLI call fails.

args: ref - Build record ref. Pass the ref field from buildx_history_list directly — it reports a qualified "//", 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": } if the output isn't a JSON object)

buildx_inspectA

Inspect a builder instance.

Human-readable detail (driver, status, supported platforms) for one builder; buildx_list returns machine-parsed JSON for all builders. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

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_list for JSON.

buildx_duA

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. Reclaim the cache with buildx_prune (system_df covers daemon-side disk, not builder cache). Raises RuntimeError if the CLI call fails.

args: builder - Override the active builder returns: list - One dict per cache record (parsed from --format '{{json .}}')

buildx_pruneA

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 filters - Filter by attributes (e.g. {"until": "24h", "type": "exec.cachemount"}) 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}

buildx_createA

Create a new BuildKit builder instance.

Needed when the default docker driver falls short: multi-platform builds and cache export require a docker-container (or kubernetes/remote) builder. Pass use=True to make it the default for later buildx_build calls (else switch with buildx_use); bootstrap=True starts the builder now rather than on first build. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

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 (copied to the target host if no local plugin); passed as --buildkitd-config, so this argument needs buildx >= 0.17 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}

buildx_useA

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_list 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_list) 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}

buildx_removeA

Remove a builder instance.

Deletes a builder made by buildx_create, including its build cache unless keep_state=True; use buildx_prune to reclaim cache while keeping the builder. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

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}

system_pingA

Check that the Docker server is responsive.

The cheapest daemon health check. A failure here usually means connection config rather than daemon load — system_reconnect rebuilds a wedged client, host_list shows the configured endpoints. For daemon details use system_version / system_info.

returns: bool - True if the daemon responded successfully

system_versionA

Return Docker server version information.

Engine version, API level, and per-component versions — the first thing to check for feature availability. system_info reports runtime state (counts, drivers, swarm role) instead.

returns: dict - {"Version", "ApiVersion", "MinAPIVersion", "Os", "Arch", "Components", ...}

system_infoA

Return system-wide Docker information, like docker info.

Daemon runtime state: container/image counts, storage and logging drivers, swarm role, and daemon warnings. Use system_version for version/API level and system_df for disk usage.

returns: dict - {"Containers", "Images", "Driver", "ServerVersion", "Swarm", "Warnings", ...}

system_dfA

Summarize Docker disk usage: layer storage plus per-object sizes for images, containers, volumes, build cache.

Equivalent to docker system df. Use it to find what to reclaim before image_prune / container_prune / volume_prune / buildx_prune; use system_info for daemon config and counts rather than sizes. The reply enumerates every object on the daemon, so expect a large payload on busy hosts.

returns: dict - {"LayersSize", "Images", "Containers", "Volumes", "BuildCache"} with per-object size fields

host_listA

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 that the host argument selects from. The default entry is the one used when host is omitted; pass a name as the host argument of daemon-backed tools (system_ping(host=...) checks one entry). The docker-mcp://hosts resource mirrors this tool.

returns: list[dict] - one per host: name; url (resolved daemon URL, null = docker-py platform default); read_only; non_destructive (blocks destructive calls only); tls (whether a per-host cert dir is configured); default (the omitted-host fallback)

system_loginA

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. Credentials let image_pull / image_push reach private repositories; system_logout clears them.

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 returns: dict - The login response: {"Status"} always; "IdentityToken" only when the registry issues one

system_logoutA

Clear cached registry credentials from this server's in-memory Docker client.

docker-py / the Engine have no true logout: system_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 system_login; Docker Hub is cached under "docker.io"). system_close/system_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 returns: dict - {"cleared": []}

system_eventsA

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).

"Wait for the next matching event" idiom: pass limit=1 with filters narrowed to what you care about (e.g. {"type": "container", "event": "health_status"}) and a generous timeout_seconds. This blocks until that one event arrives (or the timeout elapses, returning an empty list) instead of re-polling a snapshot on a timer — there's no separate wait tool for this since the filtering this call already does covers it.

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)

system_closeA

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 system_reconnect when you want to immediately re-establish the connection rather than wait for the next tool call to trigger a lazy rebuild. With host omitted every pooled client is closed (unlike other tools, where omitting it means the default host). Closing clients does not affect running containers.

returns: bool - True once closed

system_reconnectA

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. Rebuilds the default host's client when host is omitted. It CANNOT retarget to a different daemon — to add or change a daemon, edit DOCKER_MCP_SERVER_HOSTS and restart. system_close closes pooled clients without rebuilding; host_list shows the configured endpoints.

returns: dict - the rebuilt host's version info (same shape as system_version), confirming connectivity

compose_upA

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, copied to the target host if no local plugin; 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; omit to use each service's own pull_policy 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}

compose_downA

Stop and remove containers, networks (and optionally volumes) for a compose project.

Inverse of compose_up. Images are kept; named volumes go only with volumes=True (destructive). Use compose_stop to stop without removing anything. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) 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}

compose_psA

List containers in a compose project, parsed from --format json.

Container-level view of one project (state, health, publishers); compose_list enumerates projects, and container_list covers non-compose containers. Does not raise on a non-zero CLI exit: services comes back empty — inspect raw.stderr.

args: project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) 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": }; on non-zero exit services is an empty list and the caller should inspect raw.stderr.

compose_logsA

Fetch a bounded slice of logs from a compose project (never follows).

Bounded and non-following by design, so it always returns promptly. For one container's logs use container_logs; for a swarm service use service_logs. Log text arrives on stdout. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) 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), or the literal "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}

compose_configA

Render the canonical compose configuration after merges, profiles, and variable substitution.

Use it to validate compose files and see exactly what the CLI will run before compose_up. Does not raise on a non-zero CLI exit: on a failed render config may be None — inspect raw.stderr.

args: project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) 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 - Render as YAML (default) or JSON returns: dict - {"config": str|dict|None, "raw": }; config is a parsed dict when format="json" and parsing succeeds, otherwise the rendered text from stdout.

compose_buildA

Build images for a compose project.

Builds the images declared by the project's build: sections without starting anything — compose_up(build=True) builds and starts in one step. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) 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}

compose_pullA

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 system_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 with the compose file (default: server cwd; copied to the target host if no local plugin) files - Explicit compose file paths (repeatable, -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}

compose_restartA

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 with the compose file (default: server cwd; copied to the target host if no local plugin) files - Explicit compose file paths (repeatable, -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}

compose_stopA

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; copied to the target host if no local plugin) 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}

compose_startA

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; copied to the target host if no local plugin) 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}

compose_runA

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. Unlike compose_exec, this starts a NEW container for the service rather than running inside the existing one.

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; copied to the target host if no local plugin) 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}

compose_execA

Run a command inside an already-running compose service container (see also container_exec).

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; copied to the target host if no local plugin) 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}

compose_imagesA

List the images used by a compose project's services, parsed from --format json.

Answers "what image and tag does each service container actually run?" — the containers must exist (compose_up/compose_create first). Use compose_ps for container state and image_list for daemon-wide images. Raises RuntimeError if the CLI call fails.

args: project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) 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)

compose_portA

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. For non-compose containers read container_inspect's NetworkSettings.Ports instead. Raises RuntimeError if the CLI call fails.

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; copied to the target host if no local plugin) 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).

compose_waitA

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. For a single container use container_wait; for swarm services use service_wait.

args: services - One or more services to wait on. At least one is required. project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) 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}

compose_topA

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. The per-container equivalent is container_top. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: services - Restrict to these services (default: all) project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) files - Explicit compose file paths (repeatable, -f) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

compose_cpA

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 container_archive_get. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result. With no local compose plugin and an ssh:// target, runs the real docker compose cp on that host instead and relays whichever side of the copy is local over the same SSH connection — every parameter above behaves the same either way, since the actual copy always runs through the real CLI. The one difference: a container->host copy is refused with FileExistsError if the local destination already exists, since only this host (not the remote one) knows that. unix:///tcp://+TLS hosts with no local plugin are not covered by this fallback (no shell to run the CLI on) and still raise RuntimeError — use container_archive_put (host to container) or container_archive_get_to_file (container to host) there instead; both talk to the daemon directly and need no local CLI (compose_ps gives you the container name).

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; copied to the target host if no local plugin) 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}

compose_killA

Send a signal to a compose project's containers (default SIGKILL).

Immediate, with no grace period — prefer compose_stop for a clean shutdown (stop signal, then kill after a timeout). Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

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; copied to the target host if no local plugin) files - Explicit compose file paths (repeatable, -f) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

compose_pauseA

Pause the containers of a compose project (freezes their processes in place).

Paused containers stop consuming CPU but keep memory, network endpoints, and state; resume with compose_unpause. To actually stop containers (each one's configured stop signal, freeing resources) use compose_stop; to stop and delete them use compose_down. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: services - Restrict to these services (default: all) project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) files - Explicit compose file paths (repeatable, -f) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

compose_unpauseA

Unpause the containers of a compose project (resumes paused processes).

Reverse of compose_pause: processes continue from where they were frozen (no restart). compose_start is the counterpart for stopped containers. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: services - Restrict to these services (default: all) project_dir - Dir with the compose file (default: server cwd; copied to the target host if no local plugin) files - Explicit compose file paths (repeatable, -f) project_name - Compose project name override returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

compose_listA

List compose projects known to the daemon (across all directories).

Project-level view (one entry per project); compose_ps lists the containers of a single project. Raises RuntimeError if the CLI call fails.

args: all - Include stopped projects returns: list - One dict per project (parsed from --format json)

config_createA

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 secret_create 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 config_remove.

args: name - Unique config name within the swarm data - Raw bytes content of the config file labels - Labels to set on the config templating - Templating driver config (e.g. {"Name": "golang"} for Go template syntax) returns: dict - The created config's attrs ({"ID", "Version", "CreatedAt", "Spec", ...})

config_inspectA

Get a swarm config's full inspect payload by id or name.

Requires a swarm manager. Unlike a secret, a config's payload IS readable after creation: Spec.Data in the result holds the base64-encoded contents. Use config_list to enumerate configs; use this to read one config's contents and metadata.

args: id_or_name - The config id or name returns: dict - The config's attrs (ID, CreatedAt, UpdatedAt, Spec{Name, Labels, Data base64})

config_listA

List swarm configs; requires a swarm manager.

Unlike secrets, config attrs include the actual config data (Spec.Data, base64-encoded) since configs are not treated as sensitive. Valid filter keys: id, name, names, label (key or key=value). Fetch a single config by id/name with config_inspect.

args: filters - Narrow the list; omit to return every config returns: list - One full config document ({"ID", "Spec", ...}) per config

config_removeA

Remove a swarm config.

Requires a swarm manager, and fails while any service still references the config — update or remove those services first. The last step of the rotation flow described in config_create.

args: id_or_name - The config id or name returns: bool - True after removal

container_runA

Run a container from an image (create and start in one call, like docker run).

Use container_create to prepare a container without starting it, or container_exec to run a command in a container that already exists. With detach=False the call blocks until the container exits and returns its output, so long-running images need detach=True. Created containers are stamped with provenance labels.

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 (call docs_lookup(section="containers") for the full accepted set) returns: dict | str - Container attrs when detach=True, otherwise stdout/stderr as a string

container_createA

Create a container from an image without starting it.

Use this when you need to configure a container (with extra_kwargs) before its first start, or want creation and start as separate observable steps. For the common case of create-then-start-immediately use container_run instead — it does both in one call. Start the created container with container_start. Common extra_kwargs keys: name (str), environment (list of "KEY=VAL" or dict), ports (dict, e.g. {"80/tcp": 8080}), volumes (dict, e.g. {"/host/path": {"bind": "/container/path", "mode": "rw"}}), labels (dict). For anything else docker-py's ContainerCollection.create accepts, call docs_lookup(section="containers") rather than guessing a key name.

args: image - Image to create the container from, e.g. "nginx:alpine" command - Override the image's default command; string or list of strings extra_kwargs - Additional docker-py ContainerCollection.create keyword arguments returns: dict - The created container's attrs (not yet running)

container_inspectA

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. To enumerate many containers use container_list instead (same payload per container by default; abridged with sparse=True). 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)

container_listA

List containers on the daemon (running only by default).

Pass all=True to include stopped containers. For a compose project compose_ps groups containers by service; for swarm services use service_ps (tasks may live on other nodes).

args: all - Show all containers, including stopped ones (default False: running only) 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 - One dict per container: full inspect payloads by default (each match is inspected, like container_inspect); sparse=True skips the per-container inspect calls and returns the daemon's abridged list entries instead

container_pruneA

Remove all stopped containers to reclaim disk space.

Only removes containers that are not running — running containers are never affected. Use container_list(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": }

container_startA

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 container_run 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 container_restart.

args: id_or_name - Container id (full or short) or name returns: dict - The container's full inspect payload after starting

container_stopA

Gracefully stop a running container (its configured stop signal, then SIGKILL after a timeout).

Prefer this over container_kill for a clean shutdown: the main process receives the container's stop signal (STOPSIGNAL, default SIGTERM) and has stop_timeout_seconds to exit before the daemon force-kills it. Use container_restart to stop and start again in one call, or container_pause to freeze processes without stopping. When the server runs containerized it refuses to stop its own container.

args: id_or_name - The container id or name stop_timeout_seconds - Seconds between the stop signal and SIGKILL (default 10) returns: dict - The container's attrs after the stop (exit code under State.ExitCode)

container_restartA

Restart a container: stop then start again in one call.

The container receives its configured stop signal (STOPSIGNAL, default SIGTERM), SIGKILL after stop_timeout_seconds, and is then started. Use container_stop/container_start to do the halves separately. When the server runs containerized it refuses to restart its own container.

args: id_or_name - The container id or name stop_timeout_seconds - Seconds between the stop signal and SIGKILL (default 10) returns: dict - The container's full inspect payload after the restart

container_killA

Send a signal to a running container (default SIGKILL — immediate, no graceful shutdown).

Use it to force-kill a container that ignores container_stop, or with signal to poke a process without stopping it (e.g. SIGHUP for a config reload). For a normal shutdown prefer container_stop, which sends the container's configured stop signal first. Fails with a conflict error if the container is not running. When the server runs containerized it refuses to signal its own container.

args: id_or_name - The container id or name signal - Signal name or number as a string (e.g. "SIGHUP", "9"); default SIGKILL returns: dict - The container's full inspect payload after the signal

container_pauseA

Suspend all processes in a container using the kernel freezer cgroup.

Unlike sending SIGSTOP, the freezer cgroup suspends processes without their being able to observe or intercept the suspension. A paused container keeps its resources (memory, open file descriptors) but consumes no CPU. Resume with container_unpausecontainer_exec fails against a paused container until it is unpaused.

args: id_or_name - The container id or name returns: dict - The container's full inspect payload after pause (State.Paused true)

container_unpauseA

Resume all processes in a paused container (the reverse of container_pause).

Only valid on a paused container — it fails if the container is merely stopped; use container_start for stopped containers. Processes continue from where they were frozen.

args: id_or_name - The container id or name returns: dict - The container's attrs after unpause (State.Paused becomes false)

container_removeA

Remove a container, deleting its writable layer.

The image is untouched (image_remove deletes images); named volumes are never removed — volumes=True only covers anonymous ones. A running container is refused unless force=True, which kills it first. When the server runs containerized it refuses to remove its own container.

args: id_or_name - The container id or name volumes - Also remove anonymous volumes (the CLI's --volumes); named volumes persist link - Remove the specified link force - Kill a running container before removing it (default False: running is an error) returns: bool - True after removal completes

container_logsA

Get the logs of a container: a one-shot snapshot by default, or a bounded live tail with follow=True.

Follow mode 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/timeout_seconds apply only in follow mode; until only in snapshot mode.

Snapshot mode is capped at 32 MiB and raises ValueError past it, so a noisy container can't exhaust the server's memory; service_logs caps the same way and lets the caller raise it. Prefer an integer tail, or since, over tail="all" on a long-running container: "all" is safe but will abort on the cap rather than returning a partial answer, and a large result can still exceed the agent's context.

Caveat for ssh:// daemons: docker-py can't cancel an SSH stream, so in follow mode the timeout_seconds watchdog can't interrupt a fully silent container — use the snapshot mode there if you need a hard time bound.

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 (default 200), or the literal "all" for everything since - Only return logs created after this unix timestamp until - Only return logs created before this unix timestamp (snapshot mode only) follow - Follow the live log stream instead of returning a snapshot limit_lines - Follow mode: max lines to collect before returning (default 200) timeout_seconds - Follow mode: max wall-clock seconds before returning what was collected (default 30) returns: str - Decoded log output (up to limit_lines lines in follow mode). Raises ValueError in snapshot mode if the logs exceed 32 MiB.

container_statsA

Get one point-in-time resource-usage snapshot for a container (non-streaming).

Returns the raw engine stats payload; CPU percent must be computed from the delta between cpu_stats and precpu_stats. For a pre-computed human-readable summary prefer the docker-stats://{id_or_name} resource; for a process listing use container_top.

args: id_or_name - The container id or name returns: dict - Engine stats payload (read, cpu_stats, precpu_stats, memory_stats, networks, pids_stats, ...)

container_topA

List the processes running inside a container (the daemon runs ps on the host).

Works on any running container without executing anything in it, so it needs no shell or ps binary in the image — unlike container_exec with ps. Use container_stats for resource usage rather than process lists. Fails if the container is not running.

args: id_or_name - The container id or name ps_args - Extra ps arguments (e.g. "aux"); default is the daemon's standard ps invocation returns: dict - {"Titles": [ps column names], "Processes": [[one row of values per process]]}

container_execA

Run a command inside a running container (for a compose service, prefer compose_exec).

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 - {"exit_code", "output"}; output is combined stdout+stderr, or a [stdout, stderr] pair with demux=True

container_commitA

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 image_build with a Dockerfile instead; publish the result with image_tag + image_push. 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 full inspect payload (Id is the new image id)

container_diffA

List filesystem changes a container has made relative to its image.

Use it to audit what a container wrote before container_commit or container_archive_get, or to debug unexpected writes. Only the writable container layer is compared — files in volumes and bind mounts never show up.

args: id_or_name - The container id or name returns: list - Dicts of {"Path", "Kind"}; Kind 0=modified, 1=added, 2=deleted

container_renameA

Rename a container in place; its id, state, and configuration are unchanged.

Use it to free up or claim a container name (names are unique per daemon) — e.g. before starting a replacement under the old name. Fails with a conflict error if the new name is already taken. Not related to image_tag, which names images.

args: id_or_name - The container id or name name - The new name; must not be in use by any other container returns: dict - The container's full inspect payload after the rename

container_updateA

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 (container_remove + container_run).

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 inspect payload after the update

container_waitA

Block until a container reaches a condition: stopped, "healthy", or its logs contain a pattern.

One contract for every mode: never raises on timeout — the result always carries met (condition reached) and timed_out. The stop conditions ("not-running"/"next-exit"/"removed") use the daemon's blocking wait and fill status_code/error (the container's exit info); "healthy" polls the container's HEALTHCHECK every poll_intervals and fills health/status; "log-match" polls recent logs every poll_intervals for pattern and fills matched_line. For a compose project use compose_wait; for swarm services use service_wait.

Health semantics: with no HEALTHCHECK defined, once the container is running the tool returns promptly with health: null and met: 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 met: false.

Log-match semantics: pattern is matched as a plain substring by default — safe against any input, including adversarial ones. Pass regex=True to match pattern as a regular expression (via re.search) instead; only do this with patterns you trust, since a regex with catastrophic backtracking run against attacker-influenced log content can exhaust CPU (ReDoS). Checks stdout and stderr, most recent lines first within each poll. If the container exits/dies before the pattern ever appears, returns promptly with met=false (not timed_out) — no further logs can arrive, so there's nothing to keep polling for.

args: id_or_name - The container id or name until - Condition to wait for: "not-running" (default), "next-exit", "removed", "healthy", or "log-match" (requires pattern) timeout_seconds - Max seconds to wait before returning with timed_out=true (default 600) poll_interval - "healthy"/"log-match" only: seconds between re-checks (default 2, > 0); capped by the time left so a large value can't push the total wait past the timeout pattern - "log-match" only: substring (or, with regex=True, a regular expression) to look for in the container's logs regex - "log-match" only: treat pattern as a regular expression instead of a plain substring returns: dict - {"container", "until", "met", "timed_out", "status_code", "error", "health", "status", "matched_line", "waited_seconds"}; stop modes fill status_code/error, "healthy" fills health ("starting"/"healthy"/"unhealthy", or null with no healthcheck) and status, "log-match" fills matched_line when met and status if the container exited without matching.

container_exportA

Export a container's filesystem as a tar archive: to a file on the server host, or in band.

The tar is a flat filesystem snapshot with no image metadata or layers — use image_save for an archive that image_load can restore, and container_archive_get for a single file or directory. With dest_path the archive streams straight to disk (no 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. Without dest_path the tar bytes are returned in band, capped at max_bytes (default 32 MiB) because MCP base64-encodes them — a fallback for when no writable host path exists (e.g. a containerized server without a bind mount).

args: id_or_name - The container id or name dest_path - Destination path on the server host; omit to return the bytes in band overwrite - Replace dest_path if it already exists (default False) max_bytes - In-band mode: abort with ValueError beyond this many bytes (default 32 MiB) returns: bytes | dict - the tar bytes (in band), or {"path": , "bytes_written": int}

container_archive_getA

Retrieve a file or directory from a container as a tar archive, returned in band.

For large paths prefer container_archive_get_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

container_archive_get_to_fileA

Retrieve a file or directory from a container as a tar archive written to a file on the server host.

File-writing variant of container_archive_get — prefer it for anything large, since in-band bytes are base64-encoded by MCP. For the whole filesystem use container_export. 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": , "bytes_written": int, "stat": dict}

container_archive_putA

Upload a tar archive to a path inside a container, from in-band bytes or a file on the server host.

Inverse of container_archive_get: the archive is extracted at path inside the container. Pass exactly one of data (tar bytes in band) or from_file (a path on the server host, streamed straight to the daemon — preferred for large archives, since in-band bytes are base64-encoded by MCP). from_file 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) data - Tar archive bytes; exactly one of data/from_file from_file - Path on the server host to the tar archive to upload; exactly one of data/from_file returns: bool - True if the upload succeeded

context_listA

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. Use context_inspect for one context's full config and context_use to switch. Raises RuntimeError if the CLI call fails.

returns: list - One dict per context with at least name, description, dockerEndpoint, and current

context_inspectA

Return the full configuration for a single Docker context.

Full endpoint/TLS detail for one context; context_list gives the one-line summary of all. Raises RuntimeError if the CLI call fails.

args: name - Context name (use the Name field from context_list) returns: dict - The parsed docker context inspect entry (keys include "Name" and "Endpoints" with the daemon URL)

context_createA

Create a new Docker CLI context pointing at a daemon endpoint.

Registers a named endpoint for the CLI; switch with context_use, enumerate with context_list. It does not retarget this server's docker-py client (pinned at startup). Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result. It does raise ValueError before running anything if docker_host or a TLS path contains a comma, which would inject extra keys (including skip-tls-verify) into the endpoint spec.

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"; no commas description - Optional human description shown in context ls tls_ca - Path on the local host to the CA cert (for TLS daemons); no commas tls_cert - Path on the local host to the client cert; no commas tls_key - Path on the local host to the client key; no commas skip_tls_verify - Disable TLS verification (insecure; for testing only). The only way to set it: it cannot be smuggled through docker_host returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

context_useA

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. Create contexts with context_create; list them with context_list.

args: name - Existing context name to set as default returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

context_removeA

Remove a Docker CLI context.

Deletes only the CLI's connection metadata — the daemon it pointed at is untouched. The current context needs force=True (or context_use another first). Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

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}

image_buildA

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 normally relative to path; omit to use the default Dockerfile.

dockerfile is not confined to the context, despite the usual relative form: docker-py detects an absolute path, or a relative one escaping via .., reads that file from the server host's filesystem and injects its contents into the build. So it can read any file the server user can, like the other host-filesystem parameters (dest_path, from_file), and unlike them it is easy to mistake for a context-relative name. buildx_build's --file resolves differently again (against the CLI's working directory) - see its docstring.

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"); an absolute path or one containing ".." reads that file from the server host instead of the context 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 set on 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 - Isolation technology, passed to the daemon as given; platform-dependent, so not validated here (Windows documents "default", "process", "hyperv") use_config_proxy - Forward proxy env vars from Docker client config to build returns: dict - The built image's full inspect payload (as docker inspect)

image_inspectA

Return the full inspect detail for a single local image.

Includes config (env, entrypoint, exposed ports), size, layer digests (RootFS.Layers), and all tags/digests referencing it (RepoTags/RepoDigests). For a quick overview of many images use image_list instead. For the per-layer build history (which command produced each layer) use image_history. Only inspects images already present locally — for a remote image's manifest without pulling it use image_registry_data or registry_manifest.

args: id_or_name - Image name (with optional tag/digest) or id returns: dict - Full image inspect attrs (equivalent to docker inspect on an image)

image_registry_dataA

Get registry data for an image without pulling it, via the daemon's distribution endpoint.

Uses the daemon (and its cached credentials) to resolve the remote descriptor and platform list. For direct registry access without a daemon use registry_manifest.

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 - Image reference auth_config - Optional registry authentication config returns: dict - {"Descriptor", "Platforms"} — the OCI descriptor and the platforms available for the reference

image_listA

List images in the daemon's local store.

Local only — for a registry's contents use registry_tags / hub_tags, and image_search to find images on Docker Hub. Dangling (untagged) build leftovers show with filters={"dangling": True}.

args: repository - Only show images of this repository all - Show intermediate image layers filters - Filter by attributes (label, dangling, before, since, etc.) returns: list - One summary dict per image ({"Id", "RepoTags", "RepoDigests", "Created", "Size", "Labels", ...}); use image_inspect for a full inspect payload

image_pullA

Pull an image from a registry to the daemon's local store.

Private repositories need credentials — system_login (or docker login on the host) first. Use image_load for tarballs, and registry_manifest / image_registry_data to inspect a remote image without pulling it.

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)

image_pushA

Push an image or repository to a registry.

The local image must already bear the target name — image_tag it with the registry-qualified repository[:tag] first; a bare name pushes to Docker Hub. Private registries need credentials (system_login, or docker login on the host).

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

image_removeA

Remove a local image by name or id.

Fails without force if the image is tagged by multiple names (untag first with image_tag) 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: id_or_name - 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

image_searchA

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_tags instead.

args: term - Search keyword, e.g. "nginx" or "python" limit - Maximum number of results to return (Docker Hub default is 25) returns: list - Result dicts: {"name", "description", "star_count", "is_official", "is_automated"}

image_pruneA

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 system_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": }

image_prune_buildsA

Delete the daemon's build cache to reclaim disk space.

Prunes the build cache — a separate Engine resource from the images image_prune removes, so run both to reclaim everything a build leaves behind. Prefer buildx_prune when the build ran on a non-default buildx builder (that builder keeps its own cache, invisible here) or when you need buildx's disk-ceiling flags; this tool needs no CLI plugin and works over any transport, including a daemon with no local docker binary. Inventory first with system_df (its BuildCache entry) or buildx_du. Destructive and immediate: later builds must re-run the steps whose cache was removed. Needs Docker API v1.31+; passing any of filters, keep_storage, or all needs v1.39+ and raises InvalidVersion on an older daemon — omit all three to prune with the daemon's own defaults.

args: filters - Narrow which cache records to remove, e.g. {"until": "24h"} (a duration or timestamp relative to the daemon's clock); also accepts id, parent, type, description, inuse, shared, private; omit to let the daemon prune unused cache keep_storage - Bytes of cache to keep, e.g. 5368709120 for 5 GiB; omit for no floor. The Engine renamed this reserved-space at API v1.48 and still honors the old name; the newer max-used-space/min-free-space ceilings are reachable only via buildx_prune all - Remove all types of build cache, not just the unused records returns: dict - {"CachesDeleted": [...], "SpaceReclaimed": }

image_loadA

Load an image from a tarball produced by image_save, from in-band bytes or a file on the server host.

Counterpart of image_save; when the image lives in a registry, image_pull is the normal route, and for a flat rootfs archive that is not a docker save bundle use image_import. Pass exactly one of data (tarball bytes in band) or from_file (a path on the server host, streamed straight to the daemon — preferred for anything but small images, since in-band bytes are base64-encoded by MCP). from_file is read by the server's user; ~ is expanded.

args: data - Tarball contents; exactly one of data/from_file from_file - Path to a tarball produced by docker save / image_save; exactly one of data/from_file returns: list - One full inspect payload per loaded image

image_importA

Create an image from a flat root-filesystem tarball, like docker import.

Imports a filesystem archive as a new single-layer image with no build history — not the same thing as image_load, which restores a docker save archive complete with its layers, tags and history, so prefer image_load for anything image_save produced. Use this for a rootfs that came from somewhere else: a container_export archive, a distro base tarball, a VM image dump. The result has an empty config — no CMD/ENTRYPOINT/ENV — unless you supply changes, so an imported image is usually not runnable until you set at least a command. Pass exactly one source (from_file, data, from_url or from_image); ValueError otherwise. from_url and from_image are fetched by the daemon, from_file/data are read here and uploaded; a from_file path that is not a readable file raises rather than being retried as a URL. Unlike the other image-creating tools this stamps no provenance labels: the Engine's import call accepts no labels field, and changes does not cover LABEL.

args: repository - Repository name to give the new image, e.g. "myorg/rootfs"; may include a tag (myorg/rootfs:v1), and defaults to :latest when it does not. Omit to import untagged, addressable only by the id in the returned progress (omit it entirely -- a blank string is a ValueError, not a shorthand for untagged). A digest reference is refused by the daemon. Required if tag is given tag - Tag to apply, e.g. "v1". Overrides a tag already in repository rather than being ignored, so passing repository="myorg/rootfs:v1" with tag="v2" yields :v2. Requires repository (ValueError without it — the daemon would otherwise silently drop the tag and import untagged). Blank is also a ValueError, not a shorthand for the default: the daemon would substitute latest without saying so from_file - Path to a rootfs tarball on the server host (~ expanded), read by the server's user; FileNotFoundError if it is not an existing regular file; exactly one source data - Rootfs tarball contents in band (base64-encoded by MCP, so prefer from_file for anything but small archives); exactly one source from_url - URL the daemon fetches the tarball from; exactly one source from_image - Name of an existing image to import from, like a Dockerfile FROM; exactly one source changes - Dockerfile instructions applied to the new image, e.g. ['CMD ["/bin/sh"]']; only CMD, ENTRYPOINT, ENV, EXPOSE, ONBUILD, USER, VOLUME and WORKDIR are supported. Parsed as real Dockerfile syntax, so shell form is wrapped exactly as a Dockerfile would wrap it (CMD /bin/sh is stored as ["/bin/sh","-c","/bin/sh"]) — use the exec form CMD ["/bin/sh"] to store a bare argv returns: str - The daemon's raw newline-delimited JSON progress records; the final record carries the new image id as its status

image_saveA

Save an image as a tar archive: to a file on the server host, or in band.

The archive keeps layers, tags, and metadata so image_load can restore it — different from container_export, which flattens one container's filesystem. With dest_path the archive streams straight to disk (no 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. Without dest_path the tar bytes are returned in band, capped at max_bytes (default 32 MiB) because MCP base64-encodes them — a fallback for when no writable host path exists (e.g. a containerized server without a bind mount).

args: id_or_name - Image name or id dest_path - Destination path on the server host; omit to return the bytes in band named - Whether to retain repository/tag names in the saved archive overwrite - Replace dest_path if it already exists (default False) max_bytes - In-band mode: abort with ValueError beyond this many bytes (default 32 MiB) returns: bytes | dict - the tarball bytes (in band), or {"path": , "bytes_written": int}

image_tagA

Tag an image into a repository (add a name to an existing local image).

The image id stays the same and no data is copied — a tag is an alias. Typical flow: tag with the registry-qualified name, then image_push. image_remove on a tag merely untags while other names remain.

args: id_or_name - The source image name or id repository - Target repository name (registry-qualified for pushing, e.g. "ghcr.io/o/r") tag - Optional tag for the new image (default "latest") force - Force the tag returns: bool - True if the image was tagged

image_historyA

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 "" 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 image_inspect instead.

args: id_or_name - Image name (with optional tag/digest) or id returns: list - Layer history entries, newest first

network_createA

Create a network.

The daemon default driver is bridge (single-host); use overlay for swarm-wide networks. Creating a network attaches nothing — connect containers afterwards with network_connect or at start via container_run(network=...). Created networks are stamped with provenance labels (find them later via network_list(managed_only=True)).

args: name - The name of the network driver - Driver name (daemon default bridge; overlay for swarm scope) options - Driver-specific options dict ipam - IPAM configuration as a dict (engine shape: {"Driver", "Config": [{"Subnet", "Gateway", ...}]}) check_duplicate - Reject creation if a duplicate name exists (deprecated: recent daemons always check) internal - Restrict external access labels - Labels to set on the network enable_ipv6 - Enable IPv6 networking attachable - Allow standalone containers to attach (swarm overlay networks) scope - Network scope; the driver picks a sensible default when omitted ingress - Make this an ingress network for swarm routing-mesh returns: dict - The created network's attrs (Id, Name, Driver, Scope, IPAM)

network_inspectA

Return the full inspect detail for a single network.

Includes the connected containers (Containers, keyed by container id, with each entry's assigned IP), IPAM config, and driver options. For a quick overview of many networks use network_list instead — its default (non-greedy) response omits the per-network Containers detail for speed.

args: id_or_name - The network id or name returns: dict - Full network inspect attrs (equivalent to docker network inspect)

network_listA

List networks.

Valid filter keys: driver (driver name), label (key or key=value), type ("custom" or "builtin"). names/ids are a separate shorthand for filtering by exact name/id, applied in addition to filters. Set greedy to fetch each network's attrs individually (adds the connected-containers detail that network_inspect returns, at the cost of one extra daemon call per network) — leave it False for a fast summary list.

args: names - Filter by exact network names ids - Filter by exact network ids filters - Additional server-side filters; see description for valid keys greedy - Fetch extended per-network details (including connected containers) 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 - One dict ({"Id", "Name", "Driver", "Scope", ...}) per network: summary attrs by default, full inspect attrs (adding "Containers") when greedy=True

network_pruneA

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). Use network_remove to delete one specific network instead.

args: filters - Narrow which networks to remove; omit to remove all unused custom networks returns: dict - {"NetworksDeleted": [...]}

network_removeA

Remove a single custom network by id or name.

Fails if any container is still attached (disconnect with network_disconnect or stop the containers first). Built-in networks (bridge, host, none) can never be removed and return an error regardless of attachment state. For bulk cleanup of every unused custom network at once use network_prune instead.

args: id_or_name - The network id or name returns: bool - True after removal

network_connectA

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 network_disconnect to undo.

args: id_or_name - 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

network_disconnectA

Disconnect a container from a network.

The container keeps running with its other network attachments; only this endpoint is removed (the reverse of network_connect). A network with connected containers cannot be deleted, so disconnect them before network_remove.

args: id_or_name - The network id or name container - The container id or name to disconnect force - Force the disconnect; use to clear a stale endpoint (e.g. from a deleted container) returns: bool - True after the container is disconnected

node_inspectA

Get a swarm node's full inspect payload by id or name.

Must run against a swarm manager. Shows role, availability, status, and manager reachability — use node_list to enumerate nodes first, or the docker://nodes resource for a fleet summary; service_ps(filters={"node": ...}) shows what a service runs on one node.

args: id_or_name - The node id or hostname (as shown by node_list) returns: dict - The node's attrs (Spec{Role, Availability}, Status, ManagerStatus for managers)

node_listA

List swarm nodes.

Must run against a swarm manager. The fleet view of membership, role, and state; drill into one node with node_inspect, or read the docker://nodes resource for a computed summary.

args: filters - Filter by attributes (id, name, membership, role) returns: list - One full node document per node (Spec, Status, ManagerStatus for managers)

node_updateA

Replace a node's spec (availability, name, role, labels).

Replacement, not a merge: spec becomes the node's entire spec, and omitted keys are cleared. Fetch the current spec via node_inspect (its Spec key), modify it, and resubmit the whole dict — e.g. sending just {"Availability": "drain"} would also wipe the node's role and labels.

args: id_or_name - The node id or name spec - The complete new node spec (see description — omitted keys are cleared) returns: bool - True after the update

node_removeA

Remove a node from the swarm.

A node should normally be drained (node_update with Availability "drain") and have left the swarm first, so its tasks reschedule cleanly. Removing an active/reachable node requires force=True.

args: id_or_name - The node id or name to remove force - Force removal of an active/reachable node returns: bool - True after the node is removed

node_waitA

Block until a swarm node's Status.State reaches a target value.

Never raises on timeout — the result always carries met and timed_out. Polls Status.State (one of "unknown"/"down"/"ready"/"disconnected") every poll_intervals. Common uses: until="ready" after a newly joined node, or until="down" while draining a node before removal. Does not track task placement — for "has this drained node's workload fully moved off", inspect the relevant services' tasks directly; no single cheap call spans every service in the swarm, so that check isn't built into this tool. service_wait covers service convergence; node_list shows every node's state at once.

args: id_or_name - The node id or name until - Target Status.State to wait for: "ready" (default), "down", "disconnected", "unknown" timeout_seconds - Max seconds to wait before returning with timed_out=true (default 300) poll_interval - Seconds between re-inspections (default 2, > 0); capped by the time left so a large value can't push the total wait past the timeout returns: dict - {"node", "until", "met", "timed_out", "state", "availability", "waited_seconds"}

plugin_createA

Build a plugin from a local plugin data directory and install it under name.

The counterpart to plugin_install, which pulls an already-published plugin from a registry: use this only for a plugin rootfs you built yourself, and plugin_install for anything on a registry. plugin_data_dir is read on the machine running this server (not on the daemon host), must already contain a config.json manifest and a rootfs directory, and is tarred client-side and posted to the daemon — in a container it must be a bind mount or the path resolves to nothing. The new plugin is created disabled: call plugin_configure for any settings it declares, then plugin_enable to activate it. Raises if the directory is missing or lacks config.json/rootfs, or if name is already installed (remove it first with plugin_remove). Unlike the other create tools, this stamps no provenance labels — the Engine API's plugin-create call accepts none.

args: name - Local name for the plugin, author/name:tag; the :latest tag is optional and is the default if omitted plugin_data_dir - Path on this server's filesystem to the plugin data directory (containing config.json and rootfs) gzip - Compress the uploaded directory with gzip (default False) returns: dict - The created plugin's attrs ({"Id", "Name", "Enabled", "Settings", "Config"})

plugin_inspectA

Return the full attrs for a single installed plugin.

Use this to check a plugin's Enabled state before calling plugin_enable / plugin_disable, or to read the config keys it exposes under Settings.Env before calling plugin_configure. For the set of all installed plugins use plugin_list.

args: name - Plugin name, e.g. "vieux/sshfs:latest" returns: dict - The plugin's attrs, including Enabled and Settings

plugin_installA

Install a plugin from Docker Hub.

remote is a Docker Hub reference in author/name:tag form, e.g. vieux/sshfs:latest. The daemon handles permission grants non-interactively — call plugin_privileges first to see what host access the plugin is asking for. After installation use plugin_inspect to confirm the plugin's enabled state, then call plugin_enable to activate it if needed, and optionally plugin_configure first if it requires settings. Use plugin_list to list all plugins, or plugin_remove to uninstall.

args: remote - Docker Hub plugin reference, e.g. "vieux/sshfs:latest" local_name - Alias to refer to the plugin locally; defaults to remote returns: dict - The installed plugin's attrs ({"Id", "Name", "Enabled", "Settings", "Config"})

plugin_privilegesA

Ask the registry which host privileges a not-yet-installed plugin demands.

The review step before plugin_install, which grants these privileges non-interactively (the daemon never prompts) — so this is the only chance to see what a plugin wants before it has it. Worth checking for anything not already trusted: plugins routinely request host mounts, devices, and elevated capabilities, and a granted privilege is host-level access, not container-scoped. Reads the remote plugin from its registry and installs nothing; for the privileges of a plugin already installed, read Config from plugin_inspect instead. Credentials come from system_login, or from ~/.docker/config.json if the host ran docker login. Raises if the reference cannot be resolved in the registry.

args: remote - Registry plugin reference, author/name:tag; the :latest tag is optional and is the default if omitted returns: list - One dict per requested privilege ({"Name", "Description", "Value"}), e.g. Name "mount" with Value ["/data"], or "capabilities" with Value ["CAP_SYS_ADMIN"]; empty if the plugin requests none

plugin_pushA

Push an installed plugin to its registry.

The write-side counterpart to plugin_install (which pulls) and the publish step after plugin_create builds a plugin locally: name must already be the registry-qualified name the plugin is installed under, since — unlike image_push — there is no plugin equivalent of image_tag to rename it first, so create it under the target name. The plugin does not need to be enabled. Credentials come from system_login, or from ~/.docker/config.json if the host ran docker login. Does NOT raise when the registry rejects the push: an authentication or quota failure arrives as a final progress record and is surfaced as the error key, so check that key rather than assuming success. Raises RuntimeError if the installed docker-py is too old to expose the internals below, and docker.errors.APIError if the plugin isn't installed.

Bypasses docker-py's Plugin.push()/APIClient.push_plugin(), which cannot work: both POST to /plugins/{name}/pull, a route the Engine does not define (push is /plugins/{name}/push), so they 404 against any daemon. Bug present since the method was written in 2017 and still in docker-py main; it survives because upstream has no test covering it. This calls the correct endpoint through docker-py's private request helpers, in the manner of system_logout's api._auth_configs reach-in, and fails loudly if those internals change shape.

Caveat for ssh:// daemons: docker-py can't cancel an SSH stream, so the timeout_seconds watchdog can't interrupt a push that stalls with the connection still open — the same limitation container_logs carries in follow mode. The call still returns normally once the registry answers or the stream ends.

args: name - Installed plugin name to push, [registry/]author/name:tag; :latest if the tag is omitted. A bare author/name pushes to Docker Hub timeout_seconds - Max wall-clock seconds to wait on the push stream before returning what was collected (default 300); raise it for a large plugin over a slow link returns: dict - {"name", "progress": [], "truncated": bool, "error": str or None} — error is non-None only when the registry reported a failure

plugin_listA

List installed engine plugins with their full attrs.

Covers managed engine plugins (volume/network/logging drivers installed via plugin_install) — not docker CLI plugins such as compose, buildx, or scout. Use it to find exact plugin names for plugin_inspect/plugin_enable/plugin_disable/plugin_remove; the Enabled key shows each plugin's state.

returns: list - One attrs dict per installed plugin (Id, Name, Enabled, Settings, Config)

plugin_configureA

Set runtime configuration options on an installed plugin.

Use plugin_inspect 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 plugin_disable first if it is currently active, then plugin_enable afterwards to apply the new settings.

args: name - Plugin name, e.g. "vieux/sshfs:latest" options - Key/value settings to apply, matching the plugin's declared env keys returns: bool - True after configuration

plugin_disableA

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 plugin_enable.

args: name - The plugin name force - Disable even if active containers are using the plugin (may disrupt them) returns: bool - True after the plugin is disabled

plugin_enableA

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 plugin_disable. If the plugin exposes configuration (check via plugin_inspect), call plugin_configure while it is still disabled before enabling it. timeout_seconds controls how long Docker waits for the plugin process to become healthy; 0 means wait indefinitely.

args: name - The plugin name to enable timeout_seconds - Seconds to wait for the plugin to become healthy (0 = no timeout) returns: bool - True after the plugin is enabled

plugin_removeA

Uninstall an engine plugin from the daemon.

Permanent removal — to deactivate but keep a plugin installed use plugin_disable instead. An enabled plugin must be disabled first unless force=True. Plugin names come from plugin_list.

args: name - The plugin name (e.g. "vieux/sshfs:latest") force - Remove even if the plugin is enabled (default False) returns: bool - True after removal

plugin_upgradeA

Upgrade an installed plugin to a newer version.

The plugin must be disabled first — call plugin_disable before this, then plugin_enable afterwards to bring it back up. remote lets you upgrade to a different reference (e.g. a newer tag) than the plugin's current name; omit it to re-pull the same reference. Existing settings and volumes created by the plugin persist across the upgrade.

args: name - The plugin name to upgrade remote - Reference to upgrade to, e.g. "vieux/sshfs:next" (default: same as name) returns: bool - True after the upgrade completes

registry_tagsA

List tags for a repository 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). Fetch one tag's manifest with registry_manifest; hub_tags adds Hub-specific tag metadata (sizes, push dates).

args: repository - Image/repository 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": , "registry": , "tags": [..], "truncated": bool}

registry_tag_waitA

Block until a specific tag appears in a repository (e.g. waiting for a CI push to land).

Never raises on timeout — the result always carries met and timed_out. Polls registry_tags every poll_intervals and checks whether tag is in its result. Works against Docker Hub too (registry_tags' own scope covers it), so there is no separate Hub variant. Unlike every other wait tool, this has no host argument — registry tools talk HTTPS directly to the registry, not a Docker daemon.

Caveat: registry_tags paginates up to 50 pages (or limit tags, whichever comes first); if tag would only appear beyond that window it is never found, even once it exists. Raise limit if you expect a very large tag list.

args: repository - Image/repository ref, e.g. "alpine", "ghcr.io/org/repo"; any :tag/@digest is stripped tag - The exact tag name to wait for 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 scan per poll (default 1000, >= 1); forwarded to registry_tags timeout_seconds - Max seconds to wait before returning with timed_out=true (default 600) poll_interval - Seconds between re-checks (default 5, > 0); capped by the time left so a large value can't push the total wait past the timeout returns: dict - {"repository", "tag", "met", "timed_out", "waited_seconds"}

registry_manifestA

Fetch a repository's manifest 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. Talks HTTPS directly — no daemon or CLI needed. Alternatives for the same question: buildx_imagetools_inspect (uses the docker CLI and its credential store) and image_registry_data (asks the daemon).

args: repository - Image/repository 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": }

registry_image_configA

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_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: repository - Image/repository 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": }; platform is the selected platform (None if single-platform)

hub_tagsA

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_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_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": , "tags": [{name, full_size, last_updated, digest, images}, ...], "truncated": bool}

hub_repo_infoA

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. Hub-only metadata (stars, pulls, description) — use registry_tags for tag lists on any OCI registry and hub_tags for Hub tag details.

args: repository - Hub repository, e.g. "library/alpine" or "myorg/myimage" returns: dict - The Hub /v2/repositories// response (description, star_count, pull_count, last_updated, is_private, etc.)

hub_rate_limitA

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 / image_pull 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"}

service_createA

Create a Swarm service; requires a swarm manager node.

Use this instead of container_run 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}}). For anything else docker-py's ServiceCollection.create accepts, call docs_lookup(section="services") rather than guessing a key name.

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 full document ({"ID", "Version", "Spec", ...})

service_inspectA

Get a swarm service by id or name.

Must run against a swarm manager. Returns the desired-state spec and rollout status — for the actually-running tasks use service_ps, or the service-tasks://{id_or_name} resource for a computed rollout summary.

args: id_or_name - The service id or name insert_defaults - Merge default values into the output returns: dict - The full service document ({"ID", "Version", "Spec", "Endpoint", ...}; "UpdateStatus" during a rolling update)

service_listA

List swarm services.

Must run against a swarm manager. One entry per service (the desired state); service_ps lists a service's tasks, and stack_services groups services by stack.

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 - One full service document ({"ID", "Spec", ...}) per service

service_updateA

Update a swarm service's configuration, or force a redeploy with no spec change.

Pass exactly one of updates (fields to change, same parameters as service_create) or force=True (the docker service update --force equivalent: bumps the ForceUpdate counter so the service's tasks redeploy with an unchanged spec — e.g. to reschedule after a node change or re-pull a mutable tag).

args: id_or_name - The service id or name updates - Fields to update on the service; exactly one of updates/force force - Redeploy the service without changing its spec; exactly one of updates/force returns: bool - True after the update

service_removeA

Stop and remove a swarm service.

Requires a swarm manager. Deletes the service definition and shuts down its tasks — no confirmation, no undo. To stop work but keep the definition, service_scale to 0 replicas.

args: id_or_name - The service id or name returns: bool - True after the service is removed

service_psA

List a swarm service's tasks (per-replica scheduling units), like docker service ps.

Shows where replicas run and why they fail: each task carries Status (State/Message/ContainerStatus), DesiredState, NodeID, and Slot. Prefer this over container_list for services (tasks may run on other nodes), stack_ps for a whole stack, and the service-tasks://{id_or_name} resource for a computed rollout summary. Requires a swarm manager.

args: id_or_name - The service id or name filters - Filter dict; keys: id, name, node, label, desired-state (running|shutdown|accepted) returns: list - Task dicts (ID, Slot, NodeID, Status, DesiredState, Spec)

service_logsA

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 is a bounded tail=200; tail="all" returns the whole buffer, which can be huge on long-running services and exceed the agent's context — prefer an integer, or since, to constrain output. Logs aggregate across all the service's tasks — container_logs reads a single container, and the service-logs://{id_or_name} resource is the resource-flavored equivalent of this tool.

args: id_or_name - 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 (default 200), or the literal "all" for everything max_bytes - Abort with ValueError if the buffered logs exceed this many bytes (default 32 MiB) returns: str - Decoded log output

service_scaleA

Set the desired replica count for a Replicated-mode swarm service.

Only applies to services in Replicated mode; a Global service runs one task per eligible node and has no replica count to set. The swarm scheduler places or removes tasks asynchronously to converge on the new count — this call returns once the update is accepted, not once every task is running. Check progress with service_ps or service_inspect. For any other spec change (image, env, resources) use service_update instead.

args: id_or_name - The service id or name replicas - The desired number of running task replicas returns: bool - True once the scale request is accepted

service_rollbackA

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 service_update / service_scale. 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 the low-level update_service API call.

args: id_or_name - The service id or name returns: dict - The daemon response (a dict with a "Warnings" key)

service_waitA

Block until a swarm service's tasks converge, or a rolling update finishes.

One contract for both modes: never raises on timeout — the result always carries met and timed_out. "running" polls task state via the same task-counting logic as service-tasks://{id_or_name} (not the unconfirmed daemon ServiceStatus field) until running tasks reach the desired count (Replicated mode) or every returned task is running (Global mode, which has no fixed target). "update-converged" polls UpdateStatus.State until it reaches a terminal value (completed or rollback_completed); if the service has never been updated (no UpdateStatus at all), returns promptly with met=false — there's nothing to converge to, same as container_wait's no-healthcheck case.

args: id_or_name - The service id or name until - Condition to wait for: "running" (default) or "update-converged" replicas - "running" mode only: override the desired replica count (e.g. right after a same-turn service_scale call, before polling reflects the new target) timeout_seconds - Max seconds to wait before returning with timed_out=true (default 600) poll_interval - Seconds between re-checks (default 2, > 0); capped by the time left so a large value can't push the total wait past the timeout returns: dict - {"service", "until", "met", "timed_out", "running_tasks", "desired_tasks", "failed_tasks", "update_state", "waited_seconds"}

docs_lookupA

Look up Docker SDK/CLI/registry reference documentation by section.

A tool-callable mirror of the docker-docs:// resources, for clients that can't read MCP resources (e.g. Claude Desktop, Cursor). Always registered regardless of DOCKER_MCP_SERVER_DISABLE — looking something up costs nothing and isn't tied to any single Docker feature area — but an individual section still refuses if the domain it documents is disabled, matching the equivalent docker-docs://{section} resource exactly.

Omit section to list every available section with its source URL (same as docker-docs://contents); pass a section name to fetch that page's content (same as docker-docs://{section}). Most useful before constructing an extra_kwargs-style passthrough dict for a tool like container_run/container_create/service_create (their docstrings only list common keys, not every key docker-py accepts), or before writing Compose/Dockerfile/buildx bake-file syntax, which no tool generates.

args: section - Section name (from a no-argument call's index); omit to list all sections instead returns: str - JSON section index (no section) or that section's raw HTML/Markdown content

tool_listA

List this server's registered tools as compact rows, filtered by domain, category or keyword.

A tool-callable mirror of docker-mcp://tool-catalog for clients that can't read MCP resources (e.g. Claude Desktop, Cursor), and the only way to ask what no per-tool description search can express: which tools are destructive, which accept a host, what this server actually registered. Use it to brief on an unfamiliar area (domain="buildx" returns one line per tool rather than ~13 full definitions), to check blast radius (category="destructive"), or to establish that nothing matches — matched: 0 is a definitive negative, which a client's fuzzy search cannot give. Covers this server's own surface; docs_lookup covers external Docker reference documentation. Rows are summaries, not definitions — fetch a tool's own definition for its parameters. Read-only, never raises on a query matching nothing, and always registered even when DOCKER_MCP_SERVER_DISABLE drops every domain. A tool dropped by a switch or a disabled domain is absent rather than flagged; hidden_by_configuration reports how many each domain hides.

args: domain - Exact domain name (see any result's domains key); omit for every domain category - Exact category; omit for all three keyword - Case-insensitive substring over tool names, summaries and parameter names returns: dict - {"matched": int, "tools": [{"name", "domain", "category", "summary"}], "domains": {domain: count}, "no_domain": int, "hidden_by_configuration": {domain: count}, "switches", "filters"}. Every domains key is a value domain accepts; no_domain counts the domain-less tools, whose rows carry domain: null and which no domain value selects.

scout_cvesA

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 that runs the CLI — this server's host, or the target ssh:// host itself when no local scout plugin is installed. Start with scout_quickview for a per-severity summary; scout_sbom inventories packages without vulnerability matching. Does not raise on a non-zero CLI exit (a missing scout plugin still raises) — inspect raw.stderr.

args: image - Image reference (a tag or a digest) only_fixed - Only report CVEs with a fixed version available only_severity - Filter to these severities (omit for all) ignore_base - Exclude CVEs introduced by the base image format - Parsed into result as JSON: "sarif" (default, the standard vulnerability-report schema), "spdx", "gitlab", "sbom". Returned verbatim as text: "packages" (Scout's own default, grouped by package), "markdown". There is no plain "json" for this subcommand platform - Platform of the image to analyze, e.g. "linux/amd64" returns: dict - {"format": , "result": , "raw": }

scout_quickviewA

Render a compact summary of an image's CVE posture.

The fastest triage step — counts per severity plus base-image status. Drill into individual findings with scout_cves, which unlike this tool can emit machine-readable JSON; get upgrade suggestions with scout_recommendations. Output is plain text only: docker scout quickview has no output-format option, so result is always the rendered text rather than a parsed document. Does not raise on a non-zero CLI exit (a missing scout plugin still raises) — inspect raw.stderr.

args: image - Image reference platform - Platform of the image to analyze, e.g. "linux/amd64" returns: dict - {"result": , "raw": }

scout_recommendationsA

Suggest base-image upgrades for an image.

Computed against Docker Scout's catalog; generally needs docker login on the host that runs the CLI (the target ssh:// host itself when no local scout plugin is installed) to return useful results for private or rarely-scanned base images. The natural follow-up to scout_cves when the fix is a newer base image. Output is plain text only: docker scout recommendations has no output-format option, so result is always the rendered text rather than a parsed document. Does not raise on a non-zero CLI exit (a missing scout plugin still raises) — inspect raw.stderr.

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 platform - Platform of the image to analyze returns: dict - {"result": , "raw": }

scout_compareA

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. Use it after a rebuild to check the new image against the old (scout_cves scans a single image). Does not raise on a non-zero CLI exit (a missing scout plugin still raises) — inspect raw.stderr. Raises ValueError if to names a local directory/archive while the call has to run on a remote ssh:// host (no local scout plugin): the file is not staged, so it would resolve against that host's filesystem instead.

args: image - The new / candidate image reference to - Compare against this image reference, directory, or archive (a local directory/archive only when the CLI runs on this host — see above) to_env - Compare against an image associated with this Scout environment to_latest - Compare against the latest scan of image only_severity - Filter to these severities (omit for all) ignore_unchanged - Exclude unchanged packages from the diff format - Output format; only "json" (the default) is parsed into result platform - Platform of the image to analyze returns: dict - {"format": , "result": , "raw": }

scout_sbomA

Generate a Software Bill of Materials (SBOM) for an image.

Package inventory only — scout_cves adds vulnerability matching on top. 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. Does not raise on a non-zero CLI exit (a missing scout plugin still raises) — inspect raw.stderr.

args: image - Image reference format - "spdx" (default, SPDX JSON), "cyclonedx" (CycloneDX JSON), "json" (Scout's native JSON), or "list" (plain-text package list) platform - Platform of the image to analyze returns: dict - {"format", "result", "raw": }. 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.

secret_createA

Create a swarm secret; requires a swarm manager.

Write-once: the payload can never be read back through the API (secret_inspect returns metadata only) and cannot be changed later — to rotate, create a new secret and update the consuming services, keeping your own copy of the value. For non-sensitive data that should stay readable, use config_create instead. Created secrets are stamped with provenance labels.

args: name - Name for the secret (unique within the swarm) data - The secret payload (max 500 KB; must be empty when driver is set) labels - Labels to set on the secret driver - Optional secret-driver config for values held in an external store returns: dict - The created secret's attrs (ID and Spec metadata; never the payload)

secret_inspectA

Get a swarm secret's metadata by id or name; requires a swarm manager.

The returned attrs never include the secret's actual data (Spec.Data is write-only — the daemon accepts it on secret_create but never returns it back, by design). Use this to check a secret's CreatedAt, Labels, or which driver created it, not to read its contents. To see which services reference it, inspect each service's spec via service_inspect (there is no server-side filter for "services using this secret").

args: id_or_name - The secret id or name returns: dict - The secret's attrs, excluding the actual secret data

secret_listA

List swarm secrets' metadata; requires a swarm manager.

Like secret_inspect, results never include secret data, only metadata (name, id, labels, timestamps). Valid filter keys: id, name, names, label (key or key=value).

args: filters - Narrow the list; omit to return every secret returns: list - A list of secret attrs dicts (data-free)

secret_removeA

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 service_list and inspect each service's spec via service_inspect to identify services that mount the secret before removing it (service filters do not support filtering by secret reference).

args: id_or_name - The secret id or name to remove returns: bool - True after removal

stack_deployA

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 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). The swarm analogue of compose_up; watch the rollout with stack_services / stack_ps. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: 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; omit for the CLI default ("always") 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; copied to the target host if no local docker CLI) timeout_seconds - Subprocess timeout (default 1800s) returns: dict - {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

stack_listA

List the stacks deployed to the swarm, parsed from --format '{{json .}}'.

Requires the target daemon to be a swarm manager. compose_list is the non-swarm equivalent; drill into one stack with stack_services. Raises RuntimeError if the CLI call fails.

returns: list - One dict per stack (name, services count, orchestrator)

stack_psA

List the tasks of a stack, parsed from --format '{{json .}}'.

Task-level view across every service in the stack (service_ps covers one service): where each task runs and why it failed. Requires a swarm manager. Raises RuntimeError if the CLI call fails.

args: name - The stack to list tasks for no_trunc - Do not truncate task IDs / errors in the output filters - Filter by attributes, e.g. {"desired-state": "running"}; a list value repeats the filter returns: list - One dict per task (id, name, node, image, desired/current state, error)

stack_servicesA

List the services of a stack, parsed from --format '{{json .}}'.

Service-level rollup (replicas ready per service); use stack_ps for individual tasks and service_inspect for one service's full spec. Requires a swarm manager. Raises RuntimeError if the CLI call fails.

args: name - The stack to list services for filters - Filter by attributes, e.g. {"name": "web"}; a list value repeats the filter returns: list - One dict per service (id, name, mode, replicas, image, ports)

stack_removeA

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) — the reverse of stack_deploy and the swarm analogue of compose_down. Defaults to detach=True so the call returns once removal is requested rather than waiting for teardown. Does not raise on a non-zero CLI exit — inspect returncode/stderr in the result.

args: 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}

swarm_initA

Initialize a new swarm, making this Engine its first manager node.

Fails if the Engine is already part of a swarm — call swarm_leave first to reset it. advertise_addr only needs setting when the host has multiple network interfaces or is behind NAT (otherwise it is auto-detected); it must be reachable by every other node that will join. To add more nodes afterwards, retrieve join tokens with swarm_join_tokens and call swarm_join on each one. Set autolock_managers=True to require the unlock key (swarm_unlock_key) on every manager restart — store that key securely immediately, since it is only shown once autolock is enabled.

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 single-node cluster from this node's current state (disaster recovery when a majority of managers is lost) 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 - Labels to set on the swarm autolock_managers - Require the unlock key after every manager restart log_driver - Default log driver configuration returns: str - The node id of the newly created swarm manager

swarm_joinA

Join this Engine to an existing swarm as a worker or manager.

Fails if the Engine is already part of a swarm. Whether this node joins as a worker or a manager is determined entirely by which token is passed — join_token must be one of the two tokens from swarm_join_tokens, called against any existing manager. advertise_addr only needs setting when this host has multiple network interfaces or is behind NAT (otherwise it is auto-detected from the interface used to reach remote_addrs); it must be reachable by every other node in the swarm.

args: remote_addrs - Address(es) of existing swarm managers to connect to join_token - The worker or manager join token (from swarm_join_tokens) — determines the role this node joins as listen_addr - Listen address for inter-manager communication advertise_addr - Externally reachable address advertised to other nodes data_path_addr - Address to use for data path traffic returns: bool - True after the engine joins the swarm

swarm_leaveA

Leave the current swarm.

The daemon's service tasks are rescheduled to the remaining nodes. A manager refuses to leave without force=True, since leaving can break raft quorum. The departed node lingers as "down" in node_list until a manager runs node_remove.

args: force - Force leave even if the node is a manager returns: bool - True after leaving the swarm

swarm_updateA

Update swarm-wide settings: the single home for join-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 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 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

swarm_inspectA

Inspect the swarm this daemon belongs to (id, spec, join-token config, CA info).

Works on a manager node only. Cluster-level configuration — for per-node state use node_list; for the tokens new nodes need, swarm_join_tokens.

returns: dict - The swarm's attrs, as returned by the daemon's swarm inspect endpoint

swarm_unlockA

Unlock a manager node that is locked after restart due to autolock being enabled.

When autolock is enabled (via swarm_init or swarm_update), 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 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 swarm_unlock_key) returns: bool - True after the swarm is unlocked

swarm_unlock_keyA

Return the swarm's current unlock key.

The key only serves a purpose when autolock is enabled (see swarm_init's / swarm_update's autolock_managers / rotate_manager_unlock_key). Must be called against an unlocked manager — a locked manager cannot serve API requests, including this one. Feed the result's key to swarm_unlock to unlock a manager after restart. Treat the key as a sensitive credential.

returns: dict - {"UnlockKey": }

swarm_join_tokensA

Return the swarm's worker and manager join tokens.

These are the tokens a new node passes to swarm_join — without one, swarm_join 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": , "Manager": }

swarm_task_listA

List tasks across the whole swarm, like docker service ps with no service to scope it.

The cluster-wide view of what is actually scheduled. service_ps covers one service and stack_ps one stack, so answering "what is failing anywhere" or "what is running on this node" through those means looping over every service; this is one call. Filter by node for a node's workload (the CLI's docker node ps), desired-state to separate what should be running from what is shutting down, or service for a single service -- for which service_ps is the simpler call. Each task carries its full Spec, including the ContainerSpec (image, command, env), so this returns much more per task than the service-tasks://{id_or_name} resource's computed rollout summary. Read-only. Requires a swarm manager: any other node raises docker.errors.APIError.

args: filters - Filter dict; keys: id, name, service, node, label, desired-state (running|shutdown|accepted); omit for every task in the cluster returns: list - One full task document per task (ID, ServiceID, NodeID, Slot, Spec, Status, DesiredState), the same shape service_ps returns

swarm_task_inspectA

Inspect a single swarm task, like docker inspect --type task.

For when you already hold a task reference -- from a swarm_task_list or service_ps row, a service event, or an error message -- and want just that task. swarm_task_list returns the same document for every task, so prefer it when scanning; this is the single-object fetch. To reach the container behind a running task, read Status.ContainerStatus.ContainerID and pass it to container_inspect / container_logs -- but note the container may be on another node, where those tools cannot see it, and service_logs aggregates across tasks instead. Read-only. Requires a swarm manager; raises docker.errors.APIError if the task does not exist, if a prefix matches more than one task, or if this node is not a manager.

args: id_or_name - The task id, an unambiguous id prefix, or the task's full name -- which is the container-name form <service>.<slot>.<taskid> (<service>.<nodeid>.<taskid> for a global service), NOT the shorter <service>.<slot> that docker service ps prints in its NAME column, which does not resolve. The daemon tries full id, then full name, then prefix, and rejects an ambiguous prefix rather than picking a match returns: dict - Full task inspect payload, as docker inspect --type task. Carries no name field of its own; compose one from ServiceID/Slot if you need it

volume_createA

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. List existing volumes with volume_list; reclaim unused ones with volume_prune. Created volumes are stamped with provenance labels.

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 ({"Name", "Driver", "Mountpoint", "Labels", ...})

volume_inspectA

Get a volume's full inspect payload by name.

Use it after volume_list to see a volume's on-disk location, driver, and labels — e.g. before a backup or volume_remove. Volumes are addressed purely by name; they have no separate id.

args: name - The volume name (volumes have no ids) returns: dict - The volume's attrs (Name, Driver, Mountpoint, CreatedAt, Labels, Options, Scope)

volume_listA

List volumes.

Volumes are addressed by name only — feed a Name to volume_inspect for detail or volume_remove / volume_prune to clean up. filters={"dangling": True} finds volumes that no container references.

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 - One volume document ({"Name", "Driver", "Mountpoint", ...}) per volume

volume_pruneA

Remove volumes not referenced by any container, running or stopped.

A volume used by even one stopped container is not "unused" and survives the prune — remove the container first (or use container_prune, then this) to reclaim its volumes. Valid filter keys: label (key or key=value), all ("true" as a string — without it only anonymous volumes are eligible, matching docker volume prune's default). Use volume_list first to see what currently exists.

args: filters - Narrow which unused volumes to remove; omit to remove all anonymous ones returns: dict - {"VolumesDeleted": [...], "SpaceReclaimed": }

volume_removeA

Remove a single volume by name.

Fails if any container, running or stopped, still references the volume — remove or recreate those containers first, or pass force=True to remove it anyway (the containers keep their reference but lose the underlying data). For bulk cleanup of volumes with no container references at all, use volume_prune instead.

args: name - Volume name to remove force - Remove even if a container still references the volume returns: bool - True after removal

Prompts

Interactive templates invoked by user choice

NameDescription
lookup_docker_docsRead the Docker SDK for Python documentation for a section before writing code that uses it.
verify_docker_methodVerify that a specific Docker SDK method exists before relying on it.
deploy_containerDeploy a containerized application end-to-end: image, network, volume, container.
troubleshoot_containerTroubleshoot a misbehaving container by gathering logs, state, and stats.
monitor_container_fleetSweep every running container for health and resource pressure (read-only monitoring).
triage_incidentTriage a host-wide incident from symptoms when you don't yet know which container is at fault.
migrate_containerReplace a running container with a new image while preserving its configuration.
clean_environmentReclaim disk space by pruning unused docker resources.
prune_managedTear down only the resources this MCP server created, leaving everything else untouched.
inspect_stackInspect every docker resource that shares a label.
plan_compose_stackPlan a multi-container application from an informal description.
deploy_compose_projectBring up a Docker Compose project and verify it's healthy.
troubleshoot_compose_projectDiagnose a misbehaving Docker Compose project.
audit_docker_contextsReview this server's configured hosts and Docker contexts, and the daemon it targets.
audit_swarm_healthAudit the health of a docker swarm: nodes, services, and task convergence.
find_latest_image_tagFind the latest tag for an image without pulling it.
plan_multiarch_buildPlan and run a multi-platform image build with buildx.
audit_image_cvesAudit an image's CVE posture with Docker Scout.
compare_image_versionsCompare two image versions and report the CVE delta.
recommend_base_imageRecommend a safer base image via Docker Scout.
inspect_multiarch_manifestInspect a multi-arch manifest list / OCI image index without pulling.
create_multiarch_manifestCreate a multi-arch manifest list from existing per-platform tags.
migrate_from_docker_manifestTranslate `docker manifest …` commands into buildx imagetools equivalents.
review_dockerfileReview a Dockerfile for security, correctness, and cache-efficiency issues.
audit_container_securityAudit running containers for risky runtime configuration (privilege, host access).
debug_container_networkingDiagnose why one container cannot reach another over the network.
investigate_disk_usageInvestigate what is consuming docker disk space before pruning.
backup_volumeBack up a named volume's contents to a tar file on the server host.
restore_volumeRestore a named volume's contents from a tar file on the server host.
deploy_swarm_stackDeploy a Compose file to a swarm as a stack and verify the rollout.

Resources

Contextual data attached and managed by the client

NameDescription
list_docs_sections List the available documentation sections. The response keeps the original `base_url` and `sections` (a list of section names) fields for backward compatibility with clients that parsed the pre-extension shape. Sections served from external URLs (compose, context, registry specs) appear in `sections` alongside the SDK ones; their absolute URLs live in `section_urls`. returns: str - JSON describing each section's source URL and how to read it
get_tool_catalog List every tool this server knows about with its domain, mutation category, and whether the active env switches actually registered it. Read this to see the blast radius of a tool before calling it (READ_ONLY / MUTATING / DESTRUCTIVE) and to confirm which whole domains the operator disabled via DOCKER_MCP_SERVER_DISABLE (or the read-only switches) — a tool absent from the live tool list but present here as `registered: false` was filtered out by configuration, not missing by mistake. returns: str - JSON with `switches`, per-domain counts, and a per-tool list
get_hosts_resource The Docker hosts configured via DOCKER_MCP_SERVER_HOSTS — the same data as the `host_list` tool: each host's name, resolved daemon URL, read_only / non_destructive / tls flags, and which one is the default used when a tool's `host` argument is omitted. The resolved default is observable here but is not itself a selectable label. returns: str - JSON list, one object per configured host
list_container_resources Index every container with the resource URIs for reading its logs and live stats. Lists all containers (running and stopped). Each entry carries a `logs` URI (readable in any state — useful for diagnosing why a container exited) and, for running containers only, a `stats` URI (a stopped container has no live cgroup to sample). Exited containers include their `exit_code` as a triage signal. returns: str - JSON object {"containers": [{id, name, image, status, exit_code?, logs, stats?}, ...]}
list_service_resources Index every swarm service with the resource URIs for reading its logs and task/rollout status. returns: str - JSON object {"services": [{id, name, image, mode, desired_replicas, logs, tasks}, ...]}
list_node_resources Index every swarm node with its state, availability, role, and (for managers) reachability. Index only — no per-node child resource. Watch this to notice a node flapping between ready/down, or an unexpected availability/role change, without re-querying `node_list`. returns: str - JSON object {"nodes": [{id, hostname, state, availability, role, manager_reachability}, ...]}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/L337-org/docker-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server