Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

Docker MCP Server

OCI · GHCR.IO/L337-ORG/DOCKER-MCP-SERVER · 3 COMPONENTS

Manage Docker (containers, images, Compose, Swarm, registries) via the Docker SDK and CLI.

+3 this week 39 Trust /100

Last scanned (15 hours ago)

Scores higher than 49% of OCI servers

Category Cloud Infrastructure

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security0
  • No malware scan is available for this kind of package: the supply-chain vendors we use do not cover it. This is a permanent gap in our coverage, not a finding about the package.Unverified
  • Known CVEs could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.Unverified
  • Install-script risk not yet assessed.Unverified
  • Dependency health could not be checked: this artifact ships no SBOM or dependency manifest, so there is no dependency list to read.Unverified
Provenance & Transparency35
Schema Quality & AI Usability74
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 36263 tokens (~230/item across 157 items; 154 tools + 3 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management22
  • Stability check failed: the tool surface changed between 2.2.7 and 2.2.8: 12 tool removals, 2 breaking changes, 1 additions. See how to fix → Fail
Tool Coverage71
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 0% of tool parameters carry a description.Fail
  • Structured output schemas are declared (23% of tools); any adoption earns full credit.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 17 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 156 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass

Unverified: 1 category

A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 22 Oct 26 0
    • Stability: 0.23 → unverified ▼ security
    • Tool safety: pass → unverified ▼ security
    • Stability: 0.23 → fail ▼ security
    • Capabilities: pass → unverified ▼ functional
    • Tool coverage: 100 → unverified ▼ functional
    • Schema quality: 100 → unverified ▼ functional
    • Schema quality: 40351 → 36263 ▲ functional
    • Package version: 2.2.7 → 2.2.8 functional
  • 19 Oct 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

  • 17 Oct 26 +2
    • Stability: unverified → 0.10 ▲ functional
  • 14 Oct 26 +29
    • Injection markers: unverified → pass ▲ security
    • First check of Judged manipulation: pass security
    • Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window). security
    • Tool coverage: unverified → 100 ▲ functional
    • Schema quality: unverified → 100 ▲ functional
    • MCP protocol: unverified → pass ▲ functional
    • First check of Destructive annotations: 100 functional
    • First check of Tool coverage: 0 functional
    • First check of Schema quality: fail functional
    • First check of Schema quality: good functional
    • First check of Tool coverage: 23 functional
    • First check of Schema quality: fail functional
  • 9 Oct 26 7

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 23 Oct 2026 · Analysed oci/ghcr.io/l337-org/docker-mcp-server@2.2.8

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem oci
Reason No attestation published

Background: How many MCP packages publish verified provenance →

MCP tools · 154 exposed · ~35,492 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
plugin_install ~374

Install a plugin from a registry, or with `dry_run=True` only show the host privileges it would get. The daemon grants every privilege a plugin requests without prompting, so for anything not already trusted call this with `dry_run=True` first: plugins routinely ask for host mounts, devices and elevated capabilities, and a granted privilege is host-level access, not container-scoped. A dry run reads the plugin from its registry and installs nothing; for 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`. After installing, `plugin_inspect` shows whether it is enabled; `plugin_configure` any settings it declares, then `plugin_enable` it. `plugin_list` lists every plugin and `plugin_remove` uninstalls. Args: remote: Registry plugin reference, `author/name:tag`, e.g. "vieux/sshfs:latest"; the `:latest` tag is optional and is the default if omitted local_name: Alias to refer to the plugin locally; defaults to remote dry_run: Return the privileges the plugin requests and install nothing Returns: dict: The installed plugin's full document ({"Id", "Name", "Enabled", "Settings", "Config"}); with `dry_run`, {"remote", "privileges"} where `privileges` holds one {"Name", "Description", "Value"} per requested privilege, e.g. Name "mount" with Value ["/data"], and is empty if the plugin requests none

NameTypeReqDescription
dry_runboolean––
local_namestring––
remotestringyes–

No output schema declared.

No examples provided.

plugin_list ~113

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 full document per installed plugin (Id, Name, Enabled, Settings, Config)

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

plugin_remove ~112

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 Returns: bool: True after removal

NameTypeReqDescription
forceboolean––
namestringyes–
NameTypeReqDescription
resultbooleanyes–

No examples provided.

plugin_upgrade ~281

Upgrade an installed plugin to a newer version, or with `dry_run=True` only show the privileges it would get. The daemon grants whatever privileges the new version requests without prompting, exactly as `plugin_install` does, so a dry run first shows them and changes nothing. Returns only once the upgrade has finished, and raises if the daemon reports a failure partway or it runs too long. 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: remote: Reference to upgrade to, e.g. "vieux/sshfs:next" (default: same as name) dry_run: Return the privileges the upgrade would grant and change nothing Returns: bool | dict: True after the upgrade completes; with `dry_run`, {"remote", "privileges"} where `privileges` holds one {"Name", "Description", "Value"} per requested privilege

NameTypeReqDescription
dry_runboolean––
namestringyes–
remotestring––
NameTypeReqDescription
result–yes–

No examples provided.

registry_image_config ~313

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. Fails where that resolves to no config descriptor, which means the reference is a manifest list rather than an image - `registry_manifest` reads those. Args: repository: Image/repository ref, e.g. "ghcr.io/org/repo"; `:tag`/`@digest` is stripped - pass via `reference` reference: Tag or digest platform: Platform to select from a multi-platform image, "os/arch[/variant]"; ignored for single-platform images username: Registry username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME) password: Registry password/token (overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD) Returns: dict: {"name", "registry", "reference", "platform", "config_digest", "config": <parsed>}; `platform` is the selected platform (None if single-platform)

NameTypeReqDescription
passwordstring––
platformstring––
referencestring––
repositorystringyes–
usernamestring––

No output schema declared.

No examples provided.

registry_manifest ~235

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 username: Registry username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME; no config.json) password: Registry password/token (overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD) Returns: dict: {"name", "registry", "reference", "media_type", "digest", "manifest": <JSON body>}

NameTypeReqDescription
passwordstring––
referencestring––
repositorystringyes–
usernamestring––

No output schema declared.

No examples provided.

registry_tags ~291

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: Registry username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME) password: Registry password/token (overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD) limit: Max tags to return (default 1000, >= 1); pagination capped at 50 pages Returns: dict: {"name": <repo>, "registry": <host>, "tags": [..], "truncated": bool}

NameTypeReqDescription
limitinteger––
passwordstring––
repositorystringyes–
usernamestring––

No output schema declared.

No examples provided.

scout_compare ~364

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). Needs `docker login`, as `scout_cves` does. Does not raise on a non-zero CLI exit - inspect `raw.stderr`. When the call has to run on a remote `ssh://` host, a local directory or archive in `to` is refused. 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: Which platform of a multi-platform image to analyse, e.g. "linux/arm64" Returns: dict: {"format": <format>, "result": <parsed-json-or-raw-text>, "raw": <CliResult dict>}

NameTypeReqDescription
formatstring––
ignore_unchangedboolean––
imagestringyes–
only_severityarray––
platformstring––
tostring––
to_envstring––
to_latestboolean––

No output schema declared.

No examples provided.

scout_cves ~347

List vulnerabilities (CVEs) in an image via Docker Scout. Needs `docker login` on the host that runs the CLI, even for a public image - this server's host, or the target `ssh://` host itself when no local scout plugin is installed; without it the CLI exits 1 asking to log in. 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 - 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": <format>, "result": <parsed-json-or-raw-text>, "raw": <CliResult dict>}

NameTypeReqDescription
formatstring––
ignore_baseboolean––
imagestringyes–
only_fixedboolean––
only_severityarray––
platformstring––

No output schema declared.

No examples provided.

scout_quickview ~192

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`. Needs `docker login`, as `scout_cves` does. 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 - inspect `raw.stderr`. Args: platform: Platform of the image to analyze, e.g. "linux/amd64" Returns: dict: {"result": <rendered text>, "raw": <CliResult dict>}

NameTypeReqDescription
imagestringyes–
platformstring––

No output schema declared.

No examples provided.

scout_recommendations ~237

Suggest base-image upgrades for an image. Computed against Docker Scout's catalog; needs `docker login`, as `scout_cves` does. 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 - inspect `raw.stderr`. Args: 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: Which platform of a multi-platform image to analyse, e.g. "linux/arm64" Returns: dict: {"result": <rendered text>, "raw": <CliResult dict>}

NameTypeReqDescription
imagestringyes–
only_refreshboolean––
only_updateboolean––
platformstring––
tagstring––

No output schema declared.

No examples provided.

scout_sbom ~277

Generate a Software Bill of Materials (SBOM) for an image. Package inventory only - `scout_cves` adds vulnerability matching on top. The one Scout tool that works without `docker login`. 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 - inspect `raw.stderr`. Args: format: "spdx" (default, SPDX JSON), "cyclonedx" (CycloneDX JSON), "json" (Scout's native JSON), or "list" (plain-text package list) platform: Which platform of a multi-platform image to analyse, e.g. "linux/arm64" Returns: dict: {"format", "result", "raw": <CliResult dict>}. `result` is a parsed dict when `format` is "spdx"/"cyclonedx"/"json" and stdout parses cleanly; for "list" or a parse failure it's the raw text.

NameTypeReqDescription
formatstring––
imagestringyes–
platformstring––

No output schema declared.

No examples provided.

secret_create ~206

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: Secret-driver config for values held in an external store Returns: dict: The created secret's full document (ID and Spec metadata; never the payload)

NameTypeReqDescription
datastringyes–
driverobject––
labelsobject––
namestringyes–

No output schema declared.

No examples provided.

secret_inspect ~149

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"). Returns: dict: The secret's full document, excluding the actual secret data

NameTypeReqDescription
id_or_namestringyes–

No output schema declared.

No examples provided.

secret_list ~103

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: One full secret document per secret (data-free)

NameTypeReqDescription
filtersobject––

No output schema declared.

No examples provided.

secret_remove ~70

Remove a Swarm secret; requires a swarm manager. Fails while any service still references the secret, and the error names those services - move them to another secret with `service_update`, or remove them, first. Returns: bool: True after removal

NameTypeReqDescription
id_or_namestringyes–
NameTypeReqDescription
resultbooleanyes–

No examples provided.

service_create ~308

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", ...})

NameTypeReqDescription
command–––
extra_kwargsobject––
imagestringyes–

No output schema declared.

No examples provided.

service_inspect ~131

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: insert_defaults: Merge default values into the output Returns: dict: The full service document ({"ID", "Version", "Spec", "Endpoint", ...}; "UpdateStatus" during a rolling update)

NameTypeReqDescription
id_or_namestringyes–
insert_defaultsboolean––

No output schema declared.

No examples provided.

service_list ~289

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. Pass `status=True` for a whole-swarm health sweep: it adds each service's running-versus-desired task counts in the one call, where the alternative is a `service_ps` per service. It is a count, not a diagnosis - when a service comes back short, `service_ps` on that one name is what names the failing task and its error. Args: filters: Filter by attributes (id, name, label, mode) status: Add a `ServiceStatus` entry with the running, desired and completed task counts (needs daemon API v1.41+); omit when only the specs are wanted 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; with `status` each also carries "ServiceStatus" ({"RunningTasks", "DesiredTasks", "CompletedTasks"})

NameTypeReqDescription
filtersobject––
managed_onlyboolean––
statusboolean––

No output schema declared.

No examples provided.

service_logs ~423

Get a bounded snapshot of a swarm service's logs, or of one of its tasks (never follows). Pass `id_or_name` for every task of a service interleaved, or `task` for one replica - the one that actually failed, found with `service_ps` - just as `docker service logs` takes either. `container_logs` is no substitute on a multi-node swarm: a task's container lives on whichever node the scheduler chose, and this server talks to one daemon. `follow` is not exposed (the stream is joined into one string, so following would never finish). `tail` and `max_bytes` apply to what was asked for, so a quiet replica is not crowded out by noisy ones; `tail="all"` can exceed the agent's context, so prefer an integer or `since`. docker-py has no public call for a task's logs, so that path uses its private request helpers and raises if those internals move. Args: id_or_name: The service whose logs to read; give this or `task`, not both task: One task's id, an unambiguous id prefix, or its full `<service>.<slot>.<taskid>` name; give this or `id_or_name`, not both details: Include the extra attributes given to the log driver (`--details`) since: Show logs since this Unix timestamp tail: Number of lines from the end, or the literal "all" for everything max_bytes: Abort with ToolInputError if the buffered logs exceed this many bytes (default 32 MiB) Returns: str: Decoded log output

NameTypeReqDescription
detailsboolean––
id_or_namestring––
max_bytesinteger––
sinceinteger––
stderrboolean––
stdoutboolean––
tail–––
taskstring––
timestampsboolean––
NameTypeReqDescription
resultstringyes–

No examples provided.

service_ps ~373

List swarm tasks: one service's, or with no service every task in the swarm, like `docker service ps`. Omit `id_or_name` for the cluster-wide view - what is failing anywhere, or with the `node` filter one node's workload (the CLI's `docker node ps`) - in one call rather than one per service; `stack_ps` covers one stack. Find a single task with the `id` filter (full id or prefix) or `name` (the full `<service>.<slot>.<taskid>`, or `<service>.<slot>` for every task that slot has run). Both match by prefix, so an ambiguous prefix returns several tasks rather than an error, and `web.1` also matches `web.10`. Only container tasks come back unless `runtime` is filtered (e.g. `attachment`). Each task carries `Status` (State/Message/ContainerStatus), `DesiredState`, `NodeID`, `Slot` and its full `Spec`; `service_logs(task=...)` reads what one printed. Prefer this over `container_list` for services, whose tasks may run on other nodes. Read-only. Requires a swarm manager: on any other node the daemon refuses, and its refusal is what comes back. Args: id_or_name: The service whose tasks to list; omit for every task in the swarm filters: Filter dict; keys: id, name, service, node, label, desired-state (running|shutdown|accepted), runtime Returns: list: One full task document per task (ID, ServiceID, NodeID, Slot, Spec, Status, DesiredState)

NameTypeReqDescription
filtersobject––
id_or_namestring––

No output schema declared.

No examples provided.

service_remove ~76

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. Returns: bool: True after the service is removed

NameTypeReqDescription
id_or_namestringyes–
NameTypeReqDescription
resultbooleanyes–

No examples provided.

service_rollback ~144

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 ToolInputError 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. Returns: dict: The daemon response (a dict with a "Warnings" key)

NameTypeReqDescription
id_or_namestringyes–

No output schema declared.

No examples provided.

service_scale ~162

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: replicas: The desired number of running task replicas Returns: bool: True once the scale request is accepted

NameTypeReqDescription
id_or_namestringyes–
replicasintegeryes–
NameTypeReqDescription
resultbooleanyes–

No examples provided.

service_update ~170

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

NameTypeReqDescription
forceboolean––
id_or_namestringyes–
updatesobject––
NameTypeReqDescription
resultbooleanyes–

No examples provided.

stack_deploy ~331

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. Returns once the service specs are submitted, never waiting for the rollout: wait for it with `system_wait(kind="stack", target=name, until="converged")`, or see its state without waiting with `stack_services` / `stack_ps`. The swarm analogue of `compose_up`. Does not raise on a non-zero CLI exit - inspect `returncode`/`stderr`. 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") cwd: Working directory for resolving relative Compose paths (defaults to the server's cwd; copied to the target host if no local docker CLI) Returns: dict: {"returncode": int, "stdout": str, "stderr": str, "truncated": bool}

NameTypeReqDescription
compose_filesarrayyes–
cwdstring––
namestringyes–
pruneboolean––
resolve_imagestring––
timeout_secondsnumber––
with_registry_authboolean––

No output schema declared.

No examples provided.

stack_list ~82

List the stacks deployed to the swarm, with how many services each has. Requires a swarm manager. `compose_list` is the non-swarm equivalent; drill into one stack with `stack_services`, or wait for one with `system_wait(kind="stack")`. Returns: list: One {"name", "services"} per stack, sorted by name

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

stack_ps ~222

List the tasks of a stack: where each runs, its state, and why it failed. Task-level view across every service in the stack (`service_ps` covers one service). Includes the finished and failed tasks the swarm still keeps, so pass {"desired-state": "running"} for only the current ones. Requires a swarm manager. Args: name: The stack to list tasks for filters: Engine task filters, e.g. {"desired-state": "running"}; a list value matches any of them, except `label`, where every one must match and the stack's own label key is refused Returns: list: One {"id", "name", "service", "node", "image", "desired_state", "state", "error", "since"} per task, sorted by name; `node` is the hostname, `error` is null unless the task failed, and `since` is when it entered its state

NameTypeReqDescription
filtersobject––
namestringyes–

No output schema declared.

No examples provided.

stack_remove ~219

Remove one or more stacks from the swarm: their services, secrets, configs and networks. Destructive: this deletes every service in the named stack(s) - the reverse of `stack_deploy` and the swarm analogue of `compose_down`. Returns once removal is requested, never waiting for teardown: `system_wait(kind="stack", target=<name>, until="removed")` waits for it. A part that cannot be removed is reported under `failed` and the rest still go, as `docker stack rm` does. Args: names: One or more stack names to remove. At least one is required. Returns: list: One {"name", "found", "removed", "failed"} per stack; `found` is false when nothing carried the stack's label, `removed` maps "services"/"secrets"/"configs"/"networks" to the names removed, and `failed` lists {"kind", "name", "error"}

NameTypeReqDescription
namesarrayyes–

No output schema declared.

No examples provided.

stack_services ~236

List the services of a stack, with how many of their tasks are running against how many are wanted. Service-level rollup; use `stack_ps` for the individual tasks, `service_inspect` for one service's full spec, and `system_wait(kind="stack", until="converged")` to wait for the stack to settle. Requires a swarm manager. Args: name: The stack to list services for filters: Engine service filters, e.g. {"name": "web"}; a list value matches any of them, except `label`, where every one must match and the stack's own label key is refused Returns: list: One {"id", "name", "mode", "running_tasks", "desired_tasks", "image", "ports", "update_state"} per service, sorted by name; `ports` lists published ports as "published:target/protocol", and `update_state` is a rolling update's state, or null when there has been none

NameTypeReqDescription
filtersobject––
namestringyes–

No output schema declared.

No examples provided.

swarm_init ~489

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: name: Name for the swarm cluster itself, not for the node running init 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: Prefix length of each network carved from the default address pool, e.g. 24 data_path_addr: Address or interface for data-path (VXLAN) traffic, e.g. "192.168.1.1" or "eth0" data_path_port: UDP port for data-path traffic, 1024-49151 (the daemon's default is 4789) labels: Labels to set on the swarm autolock_managers: Require the unlock key after every manager restart log_driver: Default log driver for tasks, as {"Name": "json-file", "Options": {...}} Returns: str: The node id of the newly created swarm manager

NameTypeReqDescription
advertise_addrstring––
autolock_managersboolean––
data_path_addrstring––
data_path_portinteger––
default_addr_poolarray––
force_new_clusterboolean––
labelsobject––
listen_addrstring––
log_driverobject––
namestring––
subnet_sizeinteger––
NameTypeReqDescription
resultstringyes–

No examples provided.

swarm_inspect ~83

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

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

swarm_join ~289

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 or interface for data-path (VXLAN) traffic, e.g. "192.168.1.1" or "eth0" Returns: bool: True after the engine joins the swarm

NameTypeReqDescription
advertise_addrstring––
data_path_addrstring––
join_tokenstringyes–
listen_addrstring––
remote_addrsarrayyes–
NameTypeReqDescription
resultbooleanyes–

No examples provided.

swarm_join_tokens ~132

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": <worker join token>, "Manager": <manager join token>}

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

swarm_leave ~99

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

NameTypeReqDescription
forceboolean––
NameTypeReqDescription
resultbooleanyes–

No examples provided.

swarm_unlock ~180

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

NameTypeReqDescription
keystringyes–
NameTypeReqDescription
resultbooleanyes–

No examples provided.

swarm_unlock_key ~125

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": <the current unlock key>}

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

swarm_update ~417

Update swarm-wide settings: the single home for join-token rotation and cluster spec changes. 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`. Rotation and `updates` are independent and may be combined in one call; `swarm_init` sets these same fields when the swarm is first created, and `swarm_inspect` reads the current values back. The Engine replaces the whole cluster spec on every update, so this reads the current spec first and resubmits it, merging `updates` over it - omitting `updates` therefore changes nothing but the requested rotation. 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 updates: Engine SwarmSpec fields to change, merged over the current spec one top-level key at a time, so a named block is replaced whole rather than field by field: keys are "Name", "Labels", "Orchestration", "Raft", "Dispatcher", "CAConfig", "EncryptionConfig" and "TaskDefaults", e.g. {"EncryptionConfig": {"AutoLockManagers": True}} to turn manager autolock on. Read the current blocks from `swarm_inspect` Returns: bool: True after the update completes

NameTypeReqDescription
rotate_manager_tokenboolean––
rotate_manager_unlock_keyboolean––
rotate_worker_tokenboolean––
updatesobject––
NameTypeReqDescription
resultbooleanyes–

No examples provided.

system_close ~115

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

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultbooleanyes–

No examples provided.

system_df ~134

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

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

system_events ~376

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. To wait for a state rather than an event (a container exited or healthy, a service converged), use `system_wait`, which checks the state itself and so also sees one reached before the call. 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 timeout_seconds: Max wall-clock seconds before returning what was collected Returns: list: A list of decoded event dicts (length <= limit)

NameTypeReqDescription
filtersobject––
limitinteger––
sincestring––
timeout_secondsnumber––
untilstring––

No output schema declared.

No examples provided.

system_info ~86

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", ...}

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

system_login ~225

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: password: Registry password or token registry: URL to the registry (defaults to Docker Hub) reauth: Force re-authentication even if valid credentials exist dockercfg_path: A dockercfg file on the server host to use instead of `~/.docker/config.json` Returns: dict: The login response: {"Status"} always; "IdentityToken" only when the registry issues one

NameTypeReqDescription
dockercfg_pathstring––
passwordstringyes–
reauthboolean––
registrystring––
usernamestringyes–

No output schema declared.

No examples provided.

system_logout ~210

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": [<registry keys removed>]}

NameTypeReqDescription
registrystring––

No output schema declared.

No examples provided.

system_ping ~84

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

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultbooleanyes–

No examples provided.

system_reconnect ~146

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

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

system_version ~82

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", ...}

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

system_wait ~603

Wait until a container/compose project exits or is healthy, a service/stack converges, a node/registry tag is ready. The one wait tool: action tools return once their work is started (bar `container_exec` and a timed `container_run`), and this waits for the result. For a status read without waiting use `container_inspect`, `service_ps` or `compose_ps`; to follow changes as they happen, `system_events`. Never raises on timeout. `met: false` without `timed_out` means the condition can no longer be met (the target stopped, has nothing to wait for, or is gone): `detail` says why. `kind`: `target` - `until` values: - container: id or name - not-running (exit code in `detail.status_code`), next-exit, removed, healthy (no HEALTHCHECK: not met), log-match (finds `pattern` in recent logs) - service: swarm manager only; id or name - running (all desired tasks, or `replicas`), update-converged - node: swarm manager only; id or hostname - ready, down, disconnected, unknown - stack: swarm manager only; stack name - converged (every service's tasks running, updates finished), removed - compose: project name from `compose_list` - running, healthy (no HEALTHCHECK: running is enough; a job others wait on may have exited 0), exited (exit codes in `detail`); `services` narrows it - registry_tag: "repository:tag" - present (polls the registry over HTTPS every 5 s by default; no daemon, no `host`) Args: poll_interval: Seconds between checks (default 2, unless the kind says otherwise), capped by the time left pattern: log-match: a plain substring, or with `regex=True` a regular expression (trusted patterns only: a hostile one run over attacker-influenced logs can exhaust CPU) username: registry_tag: overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME password: registry_tag: overrides DOCKER_MCP_SERVER_REGISTRY_PASSWORD limit: registry_tag: most tags read per poll; a tag beyond it is never found Returns: dict: {"kind", "target", "until", "met", "timed…

NameTypeReqDescription
kindstringyes–
limitinteger––
passwordstring––
patternstring––
poll_intervalnumber––
regexboolean––
replicasinteger––
servicesarray––
targetstringyes–
timeout_secondsnumber––
untilstringyes–
usernamestring––

No output schema declared.

No examples provided.

tool_list ~497

Find this server's tools by a few words, or list them by domain or category, as compact rows. The way to find a tool when your client's own search misses: pass the words for the job as `keyword` ("logs one task", "prune build cache") and every tool matching any of them comes back, those matching the most words first. Each word is matched as a substring of tool names, summaries and parameter names, with common endings trimmed ("failing" also finds "fail") and filler words ignored. `matched: 0` is a definite negative, which a client's fuzzy search cannot give. Also answers what no per-tool search can express: `domain="buildx"` briefs on an area in one line per tool, `category="destructive"` shows the blast radius. Covers this server's own surface; `docs_lookup` covers external Docker reference documentation. Rows are summaries, not definitions - load 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: One or more words, case-insensitive; a tool matching any word is returned Returns: dict: {"matched": int, "tools": [{"name", "domain", "category", "summary"}], "domains": {domain: count}, "no_domain": int, "hidden_by_configuration": {domain: count}, "configuration_warnings": [sentence], "switches", "filters"}, with `tools` best match first. 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. `configuration_warnings` explains a DOCKER_MCP_SERVER_DISABLE mistake, empty when the switch is sound. `filters.keywo…

NameTypeReqDescription
categorystring––
domainstring––
keywordstring––

No output schema declared.

No examples provided.

volume_create ~324

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 full document (keys include Name, Driver, Mountpoint, CreatedAt, Labels, Options, Scope)

NameTypeReqDescription
driverstring––
driver_optsobject––
labelsobject––
namestring––

No output schema declared.

No examples provided.

Install

How do I install the Docker MCP Server server?

Docker MCP Server runs locally as a container image, launched with docker run --rm -i ghcr.io/l337-org/docker-mcp-server:2.2.8. Ready-made configuration for Claude, Cursor, VS Code, Codex and 3 more is on this page, copied from each client's own documentation.

oci · ghcr.io/l337-org/docker-mcp-server

# add to Claude Code
claude mcp add l337-org-docker-mcp-server -- docker run --rm -i ghcr.io/l337-org/docker-mcp-server:2.2.8
Common questions

What is the Docker MCP Server server?

Docker MCP Server is listed in the public MCP registry as io.github.L337-org/docker-mcp-server. Manage Docker (containers, images, Compose, Swarm, registries) via the Docker SDK and CLI. This page covers its container image (ghcr.io/l337-org/docker-mcp-server).

Is the Docker MCP Server server safe to use?

Docker MCP Server scores 39 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the Docker MCP Server server expose?

Docker MCP Server exposes 154 tools: system_ping, system_version, system_info, system_df, host_list, and 149 more. Their descriptions and schemas cost roughly 35,492 tokens of context every time the server is loaded.

Is the Docker MCP Server server still maintained?

Docker MCP Server is still listed as active in the MCP registry. We last reached this channel on 23 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.