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:2.2.6 · 3 COMPONENTS · SCANNED SEP 21

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

+5 this week 41 Trust /100
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
  • Malware scan not yet available for this package.Unverified
  • Known CVEs could not be checked: this artifact ships no SBOM, so there is no dependency list to read. Publishing one would let us assess it.Unverified
  • Install-script risk not yet assessed.Unverified
  • Dependency health could not be checked: this artifact ships no SBOM, so there is no dependency list to read. Publishing one would let us assess it.Unverified
Provenance & Transparency35
Schema Quality & AI Usability75
  • 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 40054 tokens (~238/item across 168 items; 165 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 Management37
  • Stability observed for 11 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
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 167 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.

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.6. 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:2.2.6

# 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.6
// .cursor/mcp.json
{
  "mcpServers": {
    "l337-org-docker-mcp-server": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/l337-org/docker-mcp-server:2.2.6"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "l337-org-docker-mcp-server": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/l337-org/docker-mcp-server:2.2.6"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add l337-org-docker-mcp-server -- docker run --rm -i ghcr.io/l337-org/docker-mcp-server:2.2.6
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "l337-org-docker-mcp-server": {
      "type": "local",
      "command": [
        "docker",
        "run",
        "--rm",
        "-i",
        "ghcr.io/l337-org/docker-mcp-server:2.2.6"
      ],
      "enabled": true
    }
  }
}
# ~/.hermes/config.yaml
mcp_servers:
  l337-org-docker-mcp-server:
    command: "docker"
    args: ["run", "--rm", "-i", "ghcr.io/l337-org/docker-mcp-server:2.2.6"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "l337-org-docker-mcp-server": {
      "Transport": "stdio",
      "Command": "docker",
      "Arguments": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/l337-org/docker-mcp-server:2.2.6"
      ]
    }
  }
}
// mcp.json
{
  "mcpServers": {
    "l337-org-docker-mcp-server": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/l337-org/docker-mcp-server:2.2.6"
      ]
    }
  }
}
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.

  • 20 Sept 26 +1

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

  • 19 Sept 26 +4
    • Stability: unverified → 0.30 functional
  • 10 Sept 26 36

    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 21 Sept 2026 · Analysed oci/ghcr.io/l337-org/docker-mcp-server:2.2.6

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 · 165 exposed · ~39,062 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
node_wait ~309

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_interval`s. 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: until: Target Status.State to wait for: "ready" (default), "down", "disconnected", "unknown" timeout_seconds: Max seconds to wait before returning with timed_out=true 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"}

NameTypeReqDescription
id_or_namestringyes
poll_intervalnumber
timeout_secondsnumber
untilstring

No output schema declared.

No examples provided.

plugin_configure ~165

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

NameTypeReqDescription
namestringyes
optionsobjectyes
NameTypeReqDescription
resultbooleanyes

No examples provided.

plugin_create ~349

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 Returns: dict: The created plugin's full document ({"Id", "Name", "Enabled", "Settings", "Config"})

NameTypeReqDescription
gzipboolean
namestringyes
plugin_data_dirstringyes

No output schema declared.

No examples provided.

plugin_disable ~138

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: force: Disable even if active containers are using the plugin (may disrupt them) Returns: bool: True after the plugin is disabled

NameTypeReqDescription
forceboolean
namestringyes
NameTypeReqDescription
resultbooleanyes

No examples provided.

plugin_enable ~152

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

NameTypeReqDescription
namestringyes
timeout_secondsinteger
NameTypeReqDescription
resultbooleanyes

No examples provided.

plugin_inspect ~123

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

NameTypeReqDescription
namestringyes

No output schema declared.

No examples provided.

plugin_install ~217

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 full document ({"Id", "Name", "Enabled", "Settings", "Config"})

NameTypeReqDescription
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_privileges ~264

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

NameTypeReqDescription
remotestringyes

No output schema declared.

No examples provided.

plugin_push ~553

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 `CapabilityError` if the installed docker-py is too old to expose the internals below, and reports the daemon's own error 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…

NameTypeReqDescription
namestringyes
timeout_secondsnumber

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 ~160

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

NameTypeReqDescription
namestringyes
remotestring
NameTypeReqDescription
resultbooleanyes

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_tag_wait ~423

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_interval`s 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: Registry username (overrides DOCKER_MCP_SERVER_REGISTRY_USERNAME) password: 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 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"}

NameTypeReqDescription
limitinteger
passwordstring
poll_intervalnumber
repositorystringyes
tagstringyes
timeout_secondsnumber
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 ~374

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 or a timeout still raises) - inspect `raw.stderr`. Raises ToolInputError 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": <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 ~355

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 or a timeout 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": <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 ~190

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 or a timeout still raises) - 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 ~268

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 or a timeout still raises) - 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: Platform of the image to analyze 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 ~265

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 or a timeout still raises) - inspect `raw.stderr`. Args: 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": <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 ~125

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

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 ~135

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

NameTypeReqDescription
filtersobject
managed_onlyboolean

No output schema declared.

No examples provided.

service_logs ~308

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` (ToolInputError 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: use `swarm_task_logs` for one task, `container_logs` for one container, and the `service-logs://{id_or_name}` resource for the resource-flavored equivalent of this tool. Args: details: Show extra 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_namestringyes
max_bytesinteger
sinceinteger
stderrboolean
stdoutboolean
tail
timestampsboolean
NameTypeReqDescription
resultstringyes

No examples provided.

service_ps ~182

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: filters: Filter dict; keys: id, name, node, label, desired-state (running|shutdown|accepted) Returns: list: Task dicts (ID, Slot, NodeID, Status, DesiredState, Spec)

NameTypeReqDescription
filtersobject
id_or_namestringyes

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.

service_wait ~381

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

NameTypeReqDescription
id_or_namestringyes
poll_intervalnumber
replicasinteger
timeout_secondsnumber
untilstring

No output schema declared.

No examples provided.

stack_deploy ~388

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 (a missing `docker` binary or a timeout still raises) - 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}

NameTypeReqDescription
compose_filesarrayyes
cwdstring
detachboolean
namestringyes
pruneboolean
resolve_imagestring
timeout_secondsnumber
with_registry_authboolean

No output schema declared.

No examples provided.

stack_list ~87

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 RemoteFailureError if the CLI call fails. Returns: list: One dict per stack (name, services count, orchestrator)

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

stack_ps ~169

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

NameTypeReqDescription
filtersobject
namestringyes
no_truncboolean

No output schema declared.

No examples provided.

stack_remove ~224

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 (a missing `docker` binary or a timeout still raises) - 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}

NameTypeReqDescription
detachboolean
namesarrayyes
timeout_secondsnumber

No output schema declared.

No examples provided.

stack_services ~147

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

NameTypeReqDescription
filtersobject
namestringyes

No output schema declared.

No examples provided.

swarm_init ~428

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

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 ~268

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

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_task_inspect ~377

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; `swarm_task_logs` reads that one task's output wherever it landed. Read-only. Requires a swarm manager; reports the daemon's own error 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

NameTypeReqDescription
id_or_namestringyes

No output schema declared.

No examples provided.

swarm_task_list ~317

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, and `swarm_task_logs` reads what a failing one printed. 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: on any other node the daemon refuses, and its refusal is what comes back. 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

NameTypeReqDescription
filtersobject

No output schema declared.

No examples provided.

swarm_task_logs ~412

Get a bounded snapshot of one swarm task's logs (never follows). The per-replica counterpart to `service_logs`, which interleaves every task in the service: use this to read the replica that actually failed, found with `swarm_task_list` or `service_ps`. `container_logs` is no substitute on a multi-node swarm - the task's container lives on whichever node the scheduler placed it on, and this server talks to one daemon. As with `service_logs`, `follow` is not exposed (the stream is joined into one string before returning, so following would never finish) and collection is capped at `max_bytes`. The Engine offers no `until` bound here, unlike `container_logs`, so narrow with `since` or an integer `tail`. docker-py has no task collection and no `APIClient.task_logs`, so this drives its private request helpers against the published `GET /tasks/{id}/logs`, raising `CapabilityError` if those internals move. Drop the reach-in if docker-py grows a public method. Args: id_or_name: The task id, an unambiguous id prefix, or its full `<service>.<slot>.<taskid>` name; see `swarm_task_inspect` for how the daemon resolves these and which name forms do not work 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_namestringyes
max_bytesinteger
sinceinteger
stderrboolean
stdoutboolean
tail
timestampsboolean
NameTypeReqDescription
resultstringyes

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.

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

Is the Docker MCP Server server safe to use?

Docker MCP Server scores 41 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 165 tools: buildx_build, buildx_bake, buildx_imagetools_inspect, buildx_imagetools_create, buildx_list, and 160 more. Their descriptions and schemas cost roughly 39,062 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 21 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.