docker-mcp-server 2.1.0__tar.gz → 2.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. docker_mcp_server-2.1.2/.claude/settings.json +15 -0
  2. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/PULL_REQUEST_TEMPLATE.md +1 -1
  3. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/copilot-instructions.md +3 -3
  4. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/workflows/canary.yaml +2 -2
  5. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/workflows/codeql.yaml +3 -3
  6. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/workflows/premerge.yaml +4 -4
  7. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/workflows/publish-homebrew.yaml +1 -1
  8. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/workflows/publish.yaml +21 -11
  9. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/CLAUDE.md +3 -3
  10. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/CONTRIBUTING.md +1 -1
  11. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/DOCKERHUB.md +7 -7
  12. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/PKG-INFO +21 -21
  13. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/PRIVACY.md +1 -1
  14. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/README.md +17 -17
  15. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/SECURITY.md +1 -1
  16. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/system.py +44 -4
  17. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/manifest.json +6 -6
  18. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/pyproject.toml +4 -4
  19. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/scripts/docker-mcp-server.rb.tpl +4 -4
  20. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/server.json +4 -4
  21. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_stack.py +14 -2
  22. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_system.py +72 -0
  23. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/uv.lock +1 -1
  24. docker_mcp_server-2.1.0/.claude/settings.json +0 -15
  25. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.claude/commands/docker-sdk.md +0 -0
  26. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.dockerignore +0 -0
  27. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/CODEOWNERS +0 -0
  28. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  29. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  30. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/actions/file-failure-issue/action.yaml +0 -0
  31. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/dependabot.yaml +0 -0
  32. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/release.yml +0 -0
  33. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.github/workflows/images.yaml +0 -0
  34. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.gitignore +0 -0
  35. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.mcpbignore +0 -0
  36. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/.python-version +0 -0
  37. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/CODE_OF_CONDUCT.md +0 -0
  38. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/Dockerfile +0 -0
  39. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/LICENSE +0 -0
  40. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/MIGRATION-2.0.md +0 -0
  41. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/assets/README.md +0 -0
  42. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/assets/icon.png +0 -0
  43. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/__init__.py +0 -0
  44. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/__main__.py +0 -0
  45. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/_env.py +0 -0
  46. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/_hosts.py +0 -0
  47. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/server.py +0 -0
  48. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/__init__.py +0 -0
  49. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/_cli.py +0 -0
  50. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/_labels.py +0 -0
  51. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/_ssh_proxy.py +0 -0
  52. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/_utils.py +0 -0
  53. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/buildx.py +0 -0
  54. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/compose.py +0 -0
  55. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/configs.py +0 -0
  56. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/containers.py +0 -0
  57. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/context.py +0 -0
  58. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/images.py +0 -0
  59. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/networks.py +0 -0
  60. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/nodes.py +0 -0
  61. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/plugins.py +0 -0
  62. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/prompts.py +0 -0
  63. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/registry.py +0 -0
  64. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/resources.py +0 -0
  65. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/scout.py +0 -0
  66. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/secrets.py +0 -0
  67. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/services.py +0 -0
  68. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/stack.py +0 -0
  69. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/swarm.py +0 -0
  70. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/docker_mcp/tools/volumes.py +0 -0
  71. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/glama.json +0 -0
  72. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/mcpb_run.py +0 -0
  73. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/scripts/build-mcpb.sh +0 -0
  74. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/__init__.py +0 -0
  75. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/conftest.py +0 -0
  76. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/__init__.py +0 -0
  77. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/conftest.py +0 -0
  78. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_buildx.py +0 -0
  79. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_cli.py +0 -0
  80. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_compose.py +0 -0
  81. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_containers.py +0 -0
  82. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_context.py +0 -0
  83. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_file_payloads.py +0 -0
  84. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_networks.py +0 -0
  85. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_nodes.py +0 -0
  86. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_registry.py +0 -0
  87. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_scout.py +0 -0
  88. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_services.py +0 -0
  89. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/integration/test_smoke.py +0 -0
  90. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_buildx.py +0 -0
  91. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_cli.py +0 -0
  92. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_compose.py +0 -0
  93. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_configs.py +0 -0
  94. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_containers.py +0 -0
  95. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_context.py +0 -0
  96. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_env.py +0 -0
  97. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_hosts.py +0 -0
  98. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_images.py +0 -0
  99. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_labels.py +0 -0
  100. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_main.py +0 -0
  101. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_naming.py +0 -0
  102. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_networks.py +0 -0
  103. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_nodes.py +0 -0
  104. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_plugins.py +0 -0
  105. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_prompts.py +0 -0
  106. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_pyproject_pins.py +0 -0
  107. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_registry.py +0 -0
  108. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_resources.py +0 -0
  109. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_scout.py +0 -0
  110. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_secrets.py +0 -0
  111. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_server.py +0 -0
  112. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_services.py +0 -0
  113. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_ssh_proxy.py +0 -0
  114. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_stack.py +0 -0
  115. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_swarm.py +0 -0
  116. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_utils.py +0 -0
  117. {docker_mcp_server-2.1.0 → docker_mcp_server-2.1.2}/tests/test_volumes.py +0 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Edit|Write|MultiEdit",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "python3 -c \"import json,sys,os; d=json.load(sys.stdin); fp=(d.get('tool_input') or {}).get('file_path',''); root=os.environ.get('CLAUDE_PROJECT_DIR') or os.getcwd(); print(json.dumps({'hookSpecificOutput':{'hookEventName':'PostToolUse','additionalContext':'You edited CLAUDE.md \\u2014 MIRROR RULE: make the equivalent change in .github/copilot-instructions.md (it drives GitHub Copilot review of every PR). Treat the change as incomplete until both files reflect it.'}})) if fp and os.path.normpath(os.path.join(root, fp)) == os.path.normpath(os.path.join(root, 'CLAUDE.md')) else None\""
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -9,6 +9,6 @@
9
9
  ## Checklist
10
10
 
11
11
  - [ ] `uv run pytest -v`, `uv run ruff check .`, `uv run ruff format --check .`, and `uv run pyright` all pass locally
12
- - [ ] If this adds or changes a tool: the ["Checklist when adding a new tool module"](https://github.com/GavinLucas/docker-mcp/blob/main/CONTRIBUTING.md#checklist-when-adding-a-new-tool-module) in `CONTRIBUTING.md` has been followed (tests, prompts, resources, README, naming convention)
12
+ - [ ] If this adds or changes a tool: the ["Checklist when adding a new tool module"](https://github.com/L337-org/docker-mcp/blob/main/CONTRIBUTING.md#checklist-when-adding-a-new-tool-module) in `CONTRIBUTING.md` has been followed (tests, prompts, resources, README, naming convention)
13
13
  - [ ] If this changes project structure, conventions, env vars, or the tool/prompt/resource surface: both `CLAUDE.md` and `.github/copilot-instructions.md` are updated (see the mirror rule at the top of `CLAUDE.md`)
14
14
  - [ ] If this changes a dependency: `uv.lock` is updated (`uv lock`) and committed alongside `pyproject.toml`
@@ -4,7 +4,7 @@ This file provides guidance to GitHub Copilot when working with code in this rep
4
4
 
5
5
  ## Project
6
6
 
7
- `docker-mcp` is a Python MCP (Model Context Protocol) server that exposes the Docker SDK for Python — plus selected docker CLI features (Compose, Context, Buildx, Scout) and direct OCI-registry HTTPS access — as MCP tools. It requires Python >=3.14 and is managed with `uv`. It is published to PyPI as **`docker-mcp-server`** and as a container image to GHCR (`ghcr.io/gavinlucas/docker-mcp-server`), mirrored to Docker Hub (`gavinlucas/docker-mcp-server`) when the opt-in `DOCKERHUB_*` release secrets are configured (the import package stays `docker_mcp`, the repo stays `…/docker-mcp`); two console scripts — `docker-mcp` and `docker-mcp-server` — both target `docker_mcp:main`. A third distribution channel packages the server as a **Claude Desktop Extension (`.mcpb`)** attached to each GitHub Release (see "Desktop Extension (MCPB)" below). A fourth channel (**Homebrew tap**) exists in `gavinlucas/homebrew-tap` but is currently **paused** — see "Homebrew tap" below.
7
+ `docker-mcp` is a Python MCP (Model Context Protocol) server that exposes the Docker SDK for Python — plus selected docker CLI features (Compose, Context, Buildx, Scout) and direct OCI-registry HTTPS access — as MCP tools. It requires Python >=3.14 and is managed with `uv`. It is published to PyPI as **`docker-mcp-server`** and as a container image to GHCR (`ghcr.io/l337-org/docker-mcp-server`), mirrored to Docker Hub (`gavinlucas/docker-mcp-server`) when the opt-in `DOCKERHUB_*` release secrets are configured (the import package stays `docker_mcp`, the repo stays `…/docker-mcp`); two console scripts — `docker-mcp` and `docker-mcp-server` — both target `docker_mcp:main`. A third distribution channel packages the server as a **Claude Desktop Extension (`.mcpb`)** attached to each GitHub Release (see "Desktop Extension (MCPB)" below). A fourth channel (**Homebrew tap**) exists in `gavinlucas/homebrew-tap` but is currently **paused** — see "Homebrew tap" below.
8
8
 
9
9
  The `docker` dep uses the `[ssh]` extra (paramiko), so `DOCKER_HOST=ssh://…` works via a pure-Python transport (no system `ssh` binary; works in the container images). docker-py auto-selects paramiko for `ssh://`, so there's no transport code — only the `ssh://` branch in `system._connection_help`. CLI-backed tools (Compose, Buildx, Context, Scout) shell out to `docker`, which would otherwise need the system `ssh` client — instead, `_cli.py:run_docker` detects `DOCKER_HOST=ssh://…` and routes the subprocess through a per-call local TCP proxy (`docker_mcp/tools/_ssh_proxy.py`) that opens its own paramiko connection and runs `docker system dial-stdio` over it, so the CLI authenticates the same way the docker-py-backed tools do, with no system `ssh` binary involved (except a `ProxyCommand` in `~/.ssh/config` for bastion/jump-host setups, which paramiko runs as an external command — commonly `ssh -W %h:%p ...` — for both tool families alike).
10
10
 
@@ -97,11 +97,11 @@ The infrastructure exists (`scripts/docker-mcp-server.rb.tpl`, `.github/workflow
97
97
 
98
98
  ### MCP Registry (`server.json`)
99
99
 
100
- A discovery listing in the official MCP Registry (`registry.modelcontextprotocol.io`), which stores only metadata pointing at the existing artifacts. `server.json` (repo root, name `io.github.GavinLucas/docker-mcp-server`) declares three package types — `pypi`, `oci` (GHCR image), `mcpb` (release `.mcpb`). The `registry` job in `.github/workflows/publish.yaml` stamps the tag version + the published `.mcpb`'s `fileSha256` into `server.json`, authenticates via GitHub OIDC (`id-token: write`, no secret), and runs `mcp-publisher publish`. Ownership is verified per package against `server.json`'s `name`, so three markers must equal it: the `<!-- mcp-name: … -->` comment in `README.md` (PyPI), the `io.modelcontextprotocol.server.name` image label in the `images` job (OCI), and the `.mcpb` URL + hash (MCPB). Keep them in sync with `server.json`'s `name`.
100
+ A discovery listing in the official MCP Registry (`registry.modelcontextprotocol.io`), which stores only metadata pointing at the existing artifacts. `server.json` (repo root, name `io.github.L337-org/docker-mcp-server`) declares three package types — `pypi`, `oci` (GHCR image), `mcpb` (release `.mcpb`). The `registry` job in `.github/workflows/publish.yaml` stamps the tag version + the published `.mcpb`'s `fileSha256` into `server.json`, authenticates via GitHub OIDC (`id-token: write`, no secret), and runs `mcp-publisher publish`. Ownership is verified per package against `server.json`'s `name`, so three markers must equal it: the `<!-- mcp-name: … -->` comment in `README.md` (PyPI), the `io.modelcontextprotocol.server.name` image label in the `images` job (OCI), and the `.mcpb` URL + hash (MCPB). Keep them in sync with `server.json`'s `name`.
101
101
 
102
102
  ### Release pipeline (`.github/workflows/publish.yaml`)
103
103
 
104
- All publishing runs through one workflow on each **published GitHub Release**: `preflight` → `pypi` ∥ `images`(→`dockerhub-description`) ∥ `mcpb` → `registry` → `verify`, plus a `notify` job on failure. `preflight` resolves the tag once (every job checks out **the tag ref**) and fails fast if the tag disagrees with the committed `pyproject.toml` / `manifest.json` / `uv.lock` self-entry versions — preventing a split-brain release where PyPI ships the pyproject version and everything else ships the tag version. `verify` confirms all channels serve the version (PyPI JSON API, both GHCR tags, `.mcpb` asset + checksum, registry listing). `notify` files a deduplicated `ci-failure` + `wf:release` issue via `.github/actions/file-failure-issue` (one open issue per failure stream; a scheduled Claude responder routine polls `ci-failure` issues). Re-runs go through `workflow_dispatch` with the tag and are idempotent end-to-end (`skip-existing` on PyPI, re-pushed image tags, `--clobber` on the `.mcpb`, duplicate-tolerant registry publish). **PyPI Trusted Publishing pins the workflow *filename* (`publish.yaml`)** — when reviewing a PR that renames or splits this workflow, flag that the PyPI trusted publisher must be updated first. `.github/release.yml` (GitHub's release-*notes* config — a different file) groups generated notes; `publish-homebrew.yaml` (paused, dispatch-only) stays separate. When reviewing changes to the pipeline's job graph, ownership markers, or re-run semantics, check this section stays accurate.
104
+ All publishing runs through one workflow on each **published GitHub Release**: `preflight` → `pypi` ∥ `images`(→`dockerhub-description`) ∥ `mcpb` → `registry` → `verify`, plus a `notify` job on failure. `preflight` resolves the tag once (every job checks out **the tag ref**) and fails fast if the tag disagrees with the committed `pyproject.toml` / `manifest.json` / `uv.lock` self-entry versions — preventing a split-brain release where PyPI ships the pyproject version and everything else ships the tag version. It also refuses to run when `github.repository_owner` isn't `L337-org`, so a release published from a fork (or mis-timed around a repo transfer) fails before anything ships rather than half-publishing. `verify` confirms all channels serve the version (PyPI JSON API, both GHCR tags, `.mcpb` asset + checksum, registry listing). `notify` files a deduplicated `ci-failure` + `wf:release` issue via `.github/actions/file-failure-issue` (one open issue per failure stream; a scheduled Claude responder routine polls `ci-failure` issues). Re-runs go through `workflow_dispatch` with the tag and are idempotent end-to-end (`skip-existing` on PyPI, re-pushed image tags, `--clobber` on the `.mcpb`, duplicate-tolerant registry publish). **PyPI Trusted Publishing pins the workflow *filename* (`publish.yaml`)** — when reviewing a PR that renames or splits this workflow, flag that the PyPI trusted publisher must be updated first. `.github/release.yml` (GitHub's release-*notes* config — a different file) groups generated notes; `publish-homebrew.yaml` (paused, dispatch-only) stays separate. When reviewing changes to the pipeline's job graph, ownership markers, or re-run semantics, check this section stays accurate.
105
105
 
106
106
  ## Conventions
107
107
 
@@ -41,7 +41,7 @@ jobs:
41
41
  uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
42
42
 
43
43
  - name: Set up uv
44
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
44
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
45
45
  with:
46
46
  # Pinned (matching the Dockerfile's uv image tag) so this step never needs the
47
47
  # live "resolve latest" fetch to raw.githubusercontent.com — that network call
@@ -102,7 +102,7 @@ jobs:
102
102
  os: [macos-latest, macos-15-intel, windows-latest]
103
103
  steps:
104
104
  - name: Set up uv
105
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
105
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
106
106
  with:
107
107
  # This job deliberately has no checkout — it tests the *published* package, not the
108
108
  # repo — so disable the repo-keyed cache and the empty-workdir warning it triggers.
@@ -31,12 +31,12 @@ jobs:
31
31
  uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
32
32
 
33
33
  - name: Initialize CodeQL
34
- uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
34
+ uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4
35
35
  with:
36
36
  languages: ${{ matrix.language }}
37
37
 
38
38
  - name: Autobuild
39
- uses: github/codeql-action/autobuild@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
39
+ uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4
40
40
 
41
41
  - name: Perform CodeQL Analysis
42
- uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
42
+ uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4
@@ -33,7 +33,7 @@ jobs:
33
33
  python-version: "3.14"
34
34
 
35
35
  - name: Set up uv
36
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
36
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
37
37
 
38
38
  - name: Install dependencies
39
39
  # --locked fails if uv.lock disagrees with pyproject.toml instead of silently
@@ -62,7 +62,7 @@ jobs:
62
62
  python-version: "3.14"
63
63
 
64
64
  - name: Set up uv
65
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
65
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
66
66
 
67
67
  - name: Install dependencies
68
68
  # --locked fails if uv.lock disagrees with pyproject.toml instead of silently
@@ -91,7 +91,7 @@ jobs:
91
91
  python-version: "3.14"
92
92
 
93
93
  - name: Set up uv
94
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
94
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
95
95
 
96
96
  - name: Install dependencies
97
97
  # --locked fails if uv.lock disagrees with pyproject.toml instead of silently
@@ -158,7 +158,7 @@ jobs:
158
158
  python-version: "3.14"
159
159
 
160
160
  - name: Set up uv
161
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
161
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
162
162
 
163
163
  - name: Install dependencies
164
164
  # --locked fails if uv.lock disagrees with pyproject.toml instead of silently
@@ -64,7 +64,7 @@ jobs:
64
64
  run: git fetch --depth=1 origin main && git checkout origin/main -- scripts/docker-mcp-server.rb.tpl
65
65
 
66
66
  - name: Install uv
67
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
67
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
68
68
 
69
69
  - name: Resolve version, Python target, and macOS floor
70
70
  run: |
@@ -15,7 +15,7 @@ name: Release
15
15
  # channel actually converged so a partial release is loud instead of silent.
16
16
  #
17
17
  # PyPI Trusted Publishing pins the WORKFLOW FILENAME: the trusted publisher on PyPI must list
18
- # `publish.yaml` (owner GavinLucas, repo docker-mcp). If the pypi job fails with an OIDC
18
+ # `publish.yaml` (owner L337-org, repo docker-mcp). If the pypi job fails with an OIDC
19
19
  # `invalid-publisher` error, that registration is missing — add it on PyPI, then re-run.
20
20
  #
21
21
  # Partial-failure semantics: no rollback is attempted (PyPI files are immutable anyway). The
@@ -55,6 +55,16 @@ jobs:
55
55
  tag: ${{ steps.resolve.outputs.tag }}
56
56
  version: ${{ steps.resolve.outputs.version }}
57
57
  steps:
58
+ - name: Assert canonical repository owner
59
+ # The GHCR path, MCP Registry name, and PyPI trusted publisher are all pinned to the
60
+ # L337-org identity. Publishing from anywhere else (a fork, or the window between the
61
+ # identity sweep landing and the repo transfer) would half-publish — PyPI first, then
62
+ # fail on GHCR/registry. Fail fast before anything ships; every other job needs preflight.
63
+ if: github.repository_owner != 'L337-org'
64
+ run: |
65
+ echo "::error::This pipeline publishes the L337-org identity but is running in ${GITHUB_REPOSITORY}. Refusing to publish."
66
+ exit 1
67
+
58
68
  - name: Resolve tag and version
59
69
  id: resolve
60
70
  env:
@@ -142,7 +152,7 @@ jobs:
142
152
  python-version: "3.14"
143
153
 
144
154
  - name: Install uv
145
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
155
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
146
156
 
147
157
  - name: Build sdist and wheel
148
158
  run: uv build
@@ -160,7 +170,7 @@ jobs:
160
170
  # Publishes the container images:
161
171
  # full -> docker-mcp-server:latest + :<version>
162
172
  # no-scout -> docker-mcp-server:no-scout + :<version>-no-scout
163
- # Images go to GHCR (ghcr.io/gavinlucas/docker-mcp-server) always, and are mirrored to Docker
173
+ # Images go to GHCR (ghcr.io/l337-org/docker-mcp-server) always, and are mirrored to Docker
164
174
  # Hub (docker.io/gavinlucas/docker-mcp-server) when the DOCKERHUB_USER / DOCKERHUB_TOKEN repo
165
175
  # secrets are set. The Hub mirror is opt-in: with the secrets unset the Hub login/tags steps
166
176
  # are skipped and only GHCR is pushed, so a release never fails for lack of Hub credentials.
@@ -202,7 +212,7 @@ jobs:
202
212
  VERSION: ${{ needs.preflight.outputs.version }}
203
213
  run: |
204
214
  # GHCR always; mirror to Docker Hub only when the credentials are present (see header).
205
- registries="ghcr.io/gavinlucas/docker-mcp-server"
215
+ registries="ghcr.io/l337-org/docker-mcp-server"
206
216
  if [ -n "$DOCKERHUB_USER" ] && [ -n "$DOCKERHUB_TOKEN" ]; then
207
217
  registries="$registries docker.io/gavinlucas/docker-mcp-server"
208
218
  fi
@@ -254,9 +264,9 @@ jobs:
254
264
  # match `name` in server.json so the registry can verify we own this image (see the
255
265
  # registry job below). image.version is the v-stripped version, matching the image tags.
256
266
  labels: |
257
- org.opencontainers.image.source=https://github.com/GavinLucas/docker-mcp
267
+ org.opencontainers.image.source=https://github.com/L337-org/docker-mcp
258
268
  org.opencontainers.image.version=${{ needs.preflight.outputs.version }}
259
- io.modelcontextprotocol.server.name=io.github.GavinLucas/docker-mcp-server
269
+ io.modelcontextprotocol.server.name=io.github.L337-org/docker-mcp-server
260
270
  build-args: |
261
271
  INSTALL_CLI=${{ matrix.install_cli }}
262
272
  INSTALL_SCOUT=${{ matrix.install_scout }}
@@ -341,7 +351,7 @@ jobs:
341
351
  # Publishes server.json to the official MCP Registry (registry.modelcontextprotocol.io). The
342
352
  # registry stores only metadata — it points at the artifacts the sibling jobs above publish —
343
353
  # and verifies we own each listed package via a marker that must equal server.json's `name`
344
- # (io.github.GavinLucas/docker-mcp-server):
354
+ # (io.github.L337-org/docker-mcp-server):
345
355
  # - pypi -> the `<!-- mcp-name: ... -->` comment in README.md (PyPI long-description)
346
356
  # - oci -> the io.modelcontextprotocol.server.name image label (set in the images job)
347
357
  # - mcpb -> the .mcpb release-asset URL (must contain "mcp") + a matching fileSha256
@@ -393,9 +403,9 @@ jobs:
393
403
  .version = $v
394
404
  | (.packages[] | select(.registryType == "pypi") | .version) = $v
395
405
  | (.packages[] | select(.registryType == "oci") | .identifier)
396
- = "ghcr.io/gavinlucas/docker-mcp-server:\($v)"
406
+ = "ghcr.io/l337-org/docker-mcp-server:\($v)"
397
407
  | (.packages[] | select(.registryType == "mcpb") | .identifier)
398
- = "https://github.com/GavinLucas/docker-mcp/releases/download/\($tag)/docker-mcp-server-\($v).mcpb"
408
+ = "https://github.com/L337-org/docker-mcp/releases/download/\($tag)/docker-mcp-server-\($v).mcpb"
399
409
  | (.packages[] | select(.registryType == "mcpb") | .fileSha256) = $sha
400
410
  ' server.json > server.tmp && mv server.tmp server.json
401
411
  echo "--- server.json ---"; cat server.json
@@ -481,7 +491,7 @@ jobs:
481
491
  for tag in "${VERSION}" "${VERSION}-no-scout"; do
482
492
  ok=""
483
493
  for i in $(seq 1 5); do
484
- if docker buildx imagetools inspect "ghcr.io/gavinlucas/docker-mcp-server:${tag}" >/dev/null 2>&1; then
494
+ if docker buildx imagetools inspect "ghcr.io/l337-org/docker-mcp-server:${tag}" >/dev/null 2>&1; then
485
495
  echo "GHCR OK: :${tag}"; ok=1; break
486
496
  fi
487
497
  echo "::notice::GHCR tag :${tag} not readable yet (attempt $i/5); waiting 15s"
@@ -512,7 +522,7 @@ jobs:
512
522
  - name: Verify the MCP Registry lists the version
513
523
  run: |
514
524
  set -euo pipefail
515
- url="https://registry.modelcontextprotocol.io/v0/servers?search=io.github.GavinLucas/docker-mcp-server"
525
+ url="https://registry.modelcontextprotocol.io/v0/servers?search=io.github.L337-org/docker-mcp-server"
516
526
  for i in $(seq 1 5); do
517
527
  if curl -fsS "$url" | jq -e --arg v "$VERSION" \
518
528
  '.servers[] | select(.server.version == $v)' >/dev/null; then
@@ -11,7 +11,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
11
11
 
12
12
  ## Project
13
13
 
14
- `docker-mcp` is a Python MCP server (requires Python >=3.14) managed with `uv` that exposes the Docker SDK for Python as MCP tools. The entry point is the `docker_mcp` package, run with `python -m docker_mcp` or via the installed console script. It is **published to PyPI as `docker-mcp-server`** (the `docker-mcp` name was already taken) and as a container image to GHCR (`ghcr.io/gavinlucas/docker-mcp-server`), mirrored to Docker Hub (`gavinlucas/docker-mcp-server`) when the opt-in `DOCKERHUB_*` release secrets are configured; the import package stays `docker_mcp` and the repo stays `…/docker-mcp`. Two console scripts are installed — `docker-mcp` and `docker-mcp-server` — both targeting `docker_mcp:main`. A third channel packages the server as a **Claude Desktop Extension (`.mcpb`)** attached to each GitHub Release — see "Desktop Extension (MCPB bundle)" below. A fourth channel (**Homebrew tap**) exists in `gavinlucas/homebrew-tap` but is currently **paused** — see "Homebrew tap" below.
14
+ `docker-mcp` is a Python MCP server (requires Python >=3.14) managed with `uv` that exposes the Docker SDK for Python as MCP tools. The entry point is the `docker_mcp` package, run with `python -m docker_mcp` or via the installed console script. It is **published to PyPI as `docker-mcp-server`** (the `docker-mcp` name was already taken) and as a container image to GHCR (`ghcr.io/l337-org/docker-mcp-server`), mirrored to Docker Hub (`gavinlucas/docker-mcp-server`) when the opt-in `DOCKERHUB_*` release secrets are configured; the import package stays `docker_mcp` and the repo stays `…/docker-mcp`. Two console scripts are installed — `docker-mcp` and `docker-mcp-server` — both targeting `docker_mcp:main`. A third channel packages the server as a **Claude Desktop Extension (`.mcpb`)** attached to each GitHub Release — see "Desktop Extension (MCPB bundle)" below. A fourth channel (**Homebrew tap**) exists in `gavinlucas/homebrew-tap` but is currently **paused** — see "Homebrew tap" below.
15
15
 
16
16
  The `docker` dependency is pulled with its `[ssh]` extra (paramiko), so `DOCKER_HOST=ssh://…` works through a pure-Python transport — no system `ssh` binary, identical on the host and in the container images. docker-py auto-selects paramiko for `ssh://` when present, so there is no transport code to maintain (just the `ssh://` branch in `system._connection_help`). CLI-backed tools (Compose, Buildx, Context, Scout) shell out to `docker`, which would otherwise use the *system* `ssh` — instead, `_cli.py:run_docker` detects `DOCKER_HOST=ssh://…` and routes the subprocess through a per-call local TCP proxy (`docker_mcp/tools/_ssh_proxy.py`) that opens its own paramiko connection (mirroring docker-py's `SSHHTTPAdapter` defaults) and runs `docker system dial-stdio` over it, so the CLI authenticates identically to the docker-py-backed tools with no system `ssh` binary involved (the one exception being a `ProxyCommand` in `~/.ssh/config` for bastion/jump-host setups, which paramiko runs as an external command — commonly `ssh -W %h:%p ...` — same as it would for the docker-py-backed tools).
17
17
 
@@ -163,11 +163,11 @@ The infrastructure exists (`scripts/docker-mcp-server.rb.tpl`, `.github/workflow
163
163
 
164
164
  ### MCP Registry (`server.json`)
165
165
 
166
- A discovery listing in the official MCP Registry (`registry.modelcontextprotocol.io`), which stores only **metadata** pointing at the artifacts the other channels already publish — so it's not a fourth artifact, just an index entry covering all of them. `server.json` (repo root, server name `io.github.GavinLucas/docker-mcp-server`) declares three package types in one entry: `pypi` (`docker-mcp-server`), `oci` (the GHCR image), and `mcpb` (the release `.mcpb`). The `registry` job in `.github/workflows/publish.yaml` stamps the tag version and the published `.mcpb`'s `fileSha256` into `server.json`, authenticates via **GitHub OIDC** (`id-token: write`, no stored secret), and runs `mcp-publisher publish`. The registry verifies we own each listed package by matching a marker against `server.json`'s `name`, so three markers must stay equal to it: the `<!-- mcp-name: … -->` comment in `README.md` (PyPI long-description), the `io.modelcontextprotocol.server.name` image label in the `images` job (OCI), and the `.mcpb` URL (must contain "mcp") + its hash (MCPB). The job runs `needs: [pypi, images, mcpb]`, so all three markers are live before it starts — its short retries only absorb registry-side read lag. **If `server.json`'s name/markers or the package set change, update this section.**
166
+ A discovery listing in the official MCP Registry (`registry.modelcontextprotocol.io`), which stores only **metadata** pointing at the artifacts the other channels already publish — so it's not a fourth artifact, just an index entry covering all of them. `server.json` (repo root, server name `io.github.L337-org/docker-mcp-server`) declares three package types in one entry: `pypi` (`docker-mcp-server`), `oci` (the GHCR image), and `mcpb` (the release `.mcpb`). The `registry` job in `.github/workflows/publish.yaml` stamps the tag version and the published `.mcpb`'s `fileSha256` into `server.json`, authenticates via **GitHub OIDC** (`id-token: write`, no stored secret), and runs `mcp-publisher publish`. The registry verifies we own each listed package by matching a marker against `server.json`'s `name`, so three markers must stay equal to it: the `<!-- mcp-name: … -->` comment in `README.md` (PyPI long-description), the `io.modelcontextprotocol.server.name` image label in the `images` job (OCI), and the `.mcpb` URL (must contain "mcp") + its hash (MCPB). The job runs `needs: [pypi, images, mcpb]`, so all three markers are live before it starts — its short retries only absorb registry-side read lag. **If `server.json`'s name/markers or the package set change, update this section.**
167
167
 
168
168
  ### Release pipeline (`.github/workflows/publish.yaml`)
169
169
 
170
- All publishing runs through one workflow on each **published GitHub Release** (nothing publishes without that human step): `preflight` → `pypi` ∥ `images`(→`dockerhub-description`) ∥ `mcpb` → `registry` → `verify`, with a `notify` job on failure. `preflight` resolves the tag once for every job (each checks out **the tag ref**, not the event SHA) and fails fast if the tag disagrees with the committed `pyproject.toml` / `manifest.json` / `uv.lock` self-entry versions — preventing a split-brain release (PyPI ships the pyproject version; every other channel ships the tag version). `verify` confirms all four channels actually serve the version (PyPI JSON API, both GHCR tags, the `.mcpb` asset + checksum, the registry listing) so a partial release is loud. `notify` files (or comments on) a deduplicated issue labeled `ci-failure` + `wf:release` via the composite action `.github/actions/file-failure-issue` — one open issue per failure stream; a scheduled Claude responder routine polls `ci-failure` issues. Re-run a failed release via `workflow_dispatch` with the tag: every job is idempotent (`skip-existing` on PyPI, re-pushed image tags, `--clobber` on the `.mcpb`, duplicate-tolerant registry publish). **PyPI Trusted Publishing pins the workflow *filename*** — the trusted publisher on PyPI must name `publish.yaml`; if the `pypi` job fails OIDC, that registration is missing. Version-bump checklist for a release: edit `pyproject.toml` + `manifest.json`, run `uv lock`, merge, then publish a GitHub Release whose tag matches (`.github/release.yml` — GitHub's release-*notes* config, a different file — groups the generated notes, Dependabot PRs under "Dependencies"). `publish-homebrew.yaml` (paused, dispatch-only) stays separate. **When the pipeline's job graph, markers, or re-run semantics change, update this section.**
170
+ All publishing runs through one workflow on each **published GitHub Release** (nothing publishes without that human step): `preflight` → `pypi` ∥ `images`(→`dockerhub-description`) ∥ `mcpb` → `registry` → `verify`, with a `notify` job on failure. `preflight` resolves the tag once for every job (each checks out **the tag ref**, not the event SHA) and fails fast if the tag disagrees with the committed `pyproject.toml` / `manifest.json` / `uv.lock` self-entry versions — preventing a split-brain release (PyPI ships the pyproject version; every other channel ships the tag version). It also refuses to run when `github.repository_owner` isn't `L337-org`, so a release published from a fork (or mis-timed around a repo transfer) fails before anything ships rather than half-publishing. `verify` confirms all four channels actually serve the version (PyPI JSON API, both GHCR tags, the `.mcpb` asset + checksum, the registry listing) so a partial release is loud. `notify` files (or comments on) a deduplicated issue labeled `ci-failure` + `wf:release` via the composite action `.github/actions/file-failure-issue` — one open issue per failure stream; a scheduled Claude responder routine polls `ci-failure` issues. Re-run a failed release via `workflow_dispatch` with the tag: every job is idempotent (`skip-existing` on PyPI, re-pushed image tags, `--clobber` on the `.mcpb`, duplicate-tolerant registry publish). **PyPI Trusted Publishing pins the workflow *filename*** — the trusted publisher on PyPI must name `publish.yaml`; if the `pypi` job fails OIDC, that registration is missing. Version-bump checklist for a release: edit `pyproject.toml` + `manifest.json`, run `uv lock`, merge, then publish a GitHub Release whose tag matches (`.github/release.yml` — GitHub's release-*notes* config, a different file — groups the generated notes, Dependabot PRs under "Dependencies"). `publish-homebrew.yaml` (paused, dispatch-only) stays separate. **When the pipeline's job graph, markers, or re-run semantics change, update this section.**
171
171
 
172
172
  ## Conventions
173
173
 
@@ -185,4 +185,4 @@ It reads the version from `pyproject.toml`, creates `dist/` if needed, writes a
185
185
 
186
186
  ## Reporting issues
187
187
 
188
- Bug reports and feature requests have templates that you can choose when you [`create an issue`](https://github.com/GavinLucas/docker-mcp/issues/new/choose). Please select the correct issue type and follow the template.
188
+ Bug reports and feature requests have templates that you can choose when you [`create an issue`](https://github.com/L337-org/docker-mcp/issues/new/choose). Please select the correct issue type and follow the template.
@@ -4,11 +4,11 @@ More than just a fully featured [MCP](https://modelcontextprotocol.io) server th
4
4
 
5
5
  It can manage multiple Docker daemons, e.g. both your local dev environment and also a remote production environment over TCP, TLS or SSH in a single session. It can also be configured to mark some daemons as read-only, so that you can monitor them without the risk of making accidental changes. It also exposes things like logs and stats as resources so that you can easily monitor and triage your environments with a few prompts.
6
6
 
7
- The server runs entirely on your machine and sends no telemetry. You are entirely in control — see the [Privacy Policy](https://github.com/GavinLucas/docker-mcp#privacy-policy).
7
+ The server runs entirely on your machine and sends no telemetry. You are entirely in control — see the [Privacy Policy](https://github.com/L337-org/docker-mcp#privacy-policy).
8
8
 
9
- This image is the container distribution of the project. **Full documentation, configuration, and source are on GitHub: <https://github.com/GavinLucas/docker-mcp>.**
9
+ This image is the container distribution of the project. **Full documentation, configuration, and source are on GitHub: <https://github.com/L337-org/docker-mcp>.**
10
10
 
11
- > The same images are published to GHCR as [`ghcr.io/gavinlucas/docker-mcp-server`](https://github.com/GavinLucas/docker-mcp/pkgs/container/docker-mcp-server) — identical content, so use whichever registry you prefer.
11
+ > The same images are published to GHCR as [`ghcr.io/l337-org/docker-mcp-server`](https://github.com/L337-org/docker-mcp/pkgs/container/docker-mcp-server) — identical content, so use whichever registry you prefer.
12
12
 
13
13
  ## Quick start
14
14
 
@@ -72,14 +72,14 @@ Set these in the client's `env` block. Three switches restrict which tools are r
72
72
 
73
73
  `DOCKER_HOST` / `DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH` retarget the daemon (e.g. `-e DOCKER_HOST=tcp://remote-host:2375`).
74
74
 
75
- See the [full configuration reference](https://github.com/GavinLucas/docker-mcp#configuration) for the complete list and examples.
75
+ See the [full configuration reference](https://github.com/L337-org/docker-mcp#configuration) for the complete list and examples.
76
76
 
77
77
  ## Security
78
78
 
79
- Connecting this server to an AI agent grants it the same access as a local Docker CLI session against the configured daemon — the daemon's socket is effectively root-equivalent on its host. Prefer pointing it at a daemon dedicated to workloads the agent may touch (a dev VM, a remote sandbox, Docker Desktop, a rootless install) rather than your production socket. See the [Security considerations](https://github.com/GavinLucas/docker-mcp#security-considerations) on GitHub before enabling the server.
79
+ Connecting this server to an AI agent grants it the same access as a local Docker CLI session against the configured daemon — the daemon's socket is effectively root-equivalent on its host. Prefer pointing it at a daemon dedicated to workloads the agent may touch (a dev VM, a remote sandbox, Docker Desktop, a rootless install) rather than your production socket. See the [Security considerations](https://github.com/L337-org/docker-mcp#security-considerations) on GitHub before enabling the server.
80
80
 
81
81
  ## Links
82
82
 
83
- - **Source, full docs & issues:** <https://github.com/GavinLucas/docker-mcp>
84
- - **Also on PyPI** (run without a container): `uvx docker-mcp-server` — see the [README](https://github.com/GavinLucas/docker-mcp#using-the-server).
83
+ - **Source, full docs & issues:** <https://github.com/L337-org/docker-mcp>
84
+ - **Also on PyPI** (run without a container): `uvx docker-mcp-server` — see the [README](https://github.com/L337-org/docker-mcp#using-the-server).
85
85
  - **License & contributing:** see the GitHub repository.
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docker-mcp-server
3
- Version: 2.1.0
3
+ Version: 2.1.2
4
4
  Summary: MCP server for managing Docker resources via the Docker SDK for Python
5
- Project-URL: Homepage, https://github.com/GavinLucas/docker-mcp
6
- Project-URL: Repository, https://github.com/GavinLucas/docker-mcp
7
- Project-URL: Issues, https://github.com/GavinLucas/docker-mcp/issues
5
+ Project-URL: Homepage, https://github.com/L337-org/docker-mcp
6
+ Project-URL: Repository, https://github.com/L337-org/docker-mcp
7
+ Project-URL: Issues, https://github.com/L337-org/docker-mcp/issues
8
8
  Author: Gavin Lucas
9
9
  License-Expression: MIT
10
10
  License-File: LICENSE
@@ -26,13 +26,13 @@ Requires-Dist: mcp>=1.27.1
26
26
  Requires-Dist: requests>=2.26.0
27
27
  Description-Content-Type: text/markdown
28
28
 
29
- <img src="https://raw.githubusercontent.com/GavinLucas/docker-mcp/main/assets/icon.png" align="left" width="72" height="72" alt="">
29
+ <img src="https://raw.githubusercontent.com/L337-org/docker-mcp/main/assets/icon.png" align="left" width="72" height="72" alt="">
30
30
 
31
31
  # docker-mcp-server
32
32
 
33
33
  [![docker-mcp MCP server](https://glama.ai/mcp/servers/GavinLucas/docker-mcp/badges/score.svg)](https://glama.ai/mcp/servers/GavinLucas/docker-mcp)
34
34
 
35
- <!-- mcp-name: io.github.GavinLucas/docker-mcp-server -->
35
+ <!-- mcp-name: io.github.L337-org/docker-mcp-server -->
36
36
 
37
37
  More than just a fully featured [MCP](https://modelcontextprotocol.io) server that lets AI agents manage Docker — containers, images, networks, volumes, swarm services, secrets, configs, nodes, plugins, etc., it helps you create workflows to easily manage your Docker environments.
38
38
 
@@ -79,7 +79,7 @@ To pin a specific version, append `==<version>` to the package name (e.g. `docke
79
79
  "command": "uvx",
80
80
  "args": [
81
81
  "--from",
82
- "git+https://github.com/GavinLucas/docker-mcp.git",
82
+ "git+https://github.com/L337-org/docker-mcp.git",
83
83
  "docker-mcp-server"
84
84
  ],
85
85
  "env": {}
@@ -93,7 +93,7 @@ To pin a specific revision, append `@<tag-or-commit>` to the git URL.
93
93
  ### Install as a Desktop Extension (.mcpb)
94
94
 
95
95
  For [Claude Desktop](https://claude.com/download), a one-click bundle is attached to each
96
- [GitHub Release](https://github.com/GavinLucas/docker-mcp/releases) as
96
+ [GitHub Release](https://github.com/L337-org/docker-mcp/releases) as
97
97
  `docker-mcp-server-<version>.mcpb` (with a matching `.sha256`). Download it and drag it into
98
98
  **Settings → Extensions**, or use **Settings → Extensions → Advanced settings → Install extension…**
99
99
  and pick the file. The install dialog surfaces a **Docker host(s)** field and the read-only /
@@ -110,7 +110,7 @@ Docker context; set one endpoint (`ssh://user@host`) for a remote daemon, or lis
110
110
  Running the server as a container removes the Python / uv / git prerequisites entirely — the only
111
111
  thing the host needs is Docker, which you already have. Prebuilt multi-arch images (linux/amd64 +
112
112
  linux/arm64) are published on each release to **Docker Hub** (`gavinlucas/docker-mcp-server`) and
113
- **GHCR** (`ghcr.io/gavinlucas/docker-mcp-server`) — the two are identical. Point your MCP client at
113
+ **GHCR** (`ghcr.io/l337-org/docker-mcp-server`) — the two are identical. Point your MCP client at
114
114
  `docker run`:
115
115
 
116
116
  ```json
@@ -131,14 +131,14 @@ linux/arm64) are published on each release to **Docker Hub** (`gavinlucas/docker
131
131
 
132
132
  `-i` is required (the server speaks MCP over stdio); `--rm` cleans up when the client disconnects. To
133
133
  pin a version, replace `:latest` with a release tag (e.g. `:1.5.1`). To pull from GHCR instead, use
134
- `ghcr.io/gavinlucas/docker-mcp-server:latest`.
134
+ `ghcr.io/l337-org/docker-mcp-server:latest`.
135
135
 
136
- > **Image renamed.** As of 1.5.0 the image is published to `ghcr.io/gavinlucas/docker-mcp-server`
137
- > (matching the PyPI name). The old `ghcr.io/gavinlucas/docker-mcp` image is frozen at 1.4.0 and no
138
- > longer updated — point new pulls at `…/docker-mcp-server`.
136
+ > **Image renamed.** As of 1.5.0 the image is published as `docker-mcp-server` (matching the PyPI
137
+ > name). The old `ghcr.io/gavinlucas/docker-mcp` image is frozen at 1.4.0 and no longer updated —
138
+ > point new pulls at `ghcr.io/l337-org/docker-mcp-server`.
139
139
 
140
140
  **Image variants.** Two variants are published to both registries (`gavinlucas/docker-mcp-server` on
141
- Docker Hub and `ghcr.io/gavinlucas/docker-mcp-server` on GHCR), both built from one `Dockerfile`. The
141
+ Docker Hub and `ghcr.io/l337-org/docker-mcp-server` on GHCR), both built from one `Dockerfile`. The
142
142
  CLI-backed domains (Compose, Stack, Buildx, Scout, Context) shell out to the `docker` CLI and its
143
143
  plugins.
144
144
 
@@ -361,7 +361,7 @@ All of these go in the `env` block of the server entry in your MCP client config
361
361
  "command": "uvx",
362
362
  "args": [
363
363
  "--from",
364
- "git+https://github.com/GavinLucas/docker-mcp.git",
364
+ "git+https://github.com/L337-org/docker-mcp.git",
365
365
  "docker-mcp-server"
366
366
  ],
367
367
  "env": {
@@ -379,7 +379,7 @@ Swap `DOCKER_MCP_SERVER_READONLY` for `DOCKER_MCP_SERVER_NO_DESTRUCTIVE` to allo
379
379
  ```bash
380
380
  claude mcp add docker-mcp-server-readonly \
381
381
  --env DOCKER_MCP_SERVER_READONLY=1 \
382
- -- uvx --from git+https://github.com/GavinLucas/docker-mcp.git docker-mcp-server
382
+ -- uvx --from git+https://github.com/L337-org/docker-mcp.git docker-mcp-server
383
383
  ```
384
384
 
385
385
  ## Security considerations
@@ -407,10 +407,10 @@ Connecting this server to an AI agent grants it the same level of access as a lo
407
407
  | Channel | Link |
408
408
  |---------|------|
409
409
  | PyPI | [docker-mcp-server](https://pypi.org/project/docker-mcp-server/) |
410
- | GHCR (container) | [ghcr.io/gavinlucas/docker-mcp-server](https://github.com/GavinLucas/docker-mcp/pkgs/container/docker-mcp-server) |
410
+ | GHCR (container) | [ghcr.io/l337-org/docker-mcp-server](https://github.com/L337-org/docker-mcp/pkgs/container/docker-mcp-server) |
411
411
  | Docker Hub (container) | [gavinlucas/docker-mcp-server](https://hub.docker.com/r/gavinlucas/docker-mcp-server) |
412
- | Desktop Extension (.mcpb) | [GitHub Releases](https://github.com/GavinLucas/docker-mcp/releases) |
413
- | Official MCP Registry | [io.github.GavinLucas/docker-mcp-server](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.GavinLucas%2Fdocker-mcp-server/versions) |
412
+ | Desktop Extension (.mcpb) | [GitHub Releases](https://github.com/L337-org/docker-mcp/releases) |
413
+ | Official MCP Registry | [io.github.L337-org/docker-mcp-server](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.L337-org%2Fdocker-mcp-server/versions) |
414
414
  | Glama | [docker-mcp-server](https://glama.ai/mcp/servers/GavinLucas/docker-mcp) |
415
415
  | mcp.so | [docker-mcp-server](https://mcp.so/server/docker-mcp-server/GavinLucas) |
416
416
  | awesome-mcp-servers | [punkpeye/awesome-mcp-servers](https://github.com/punkpeye/awesome-mcp-servers#cloud-platforms) |
@@ -419,8 +419,8 @@ Connecting this server to an AI agent grants it the same level of access as a lo
419
419
 
420
420
  docker-mcp-server collects no data, sends no telemetry, and has no author-operated backend. It runs
421
421
  locally and talks only to the Docker daemon and container registries **you** point it at, as part of
422
- the operations you request. The full statement is in [PRIVACY.md](https://github.com/GavinLucas/docker-mcp/blob/main/PRIVACY.md).
422
+ the operations you request. The full statement is in [PRIVACY.md](https://github.com/L337-org/docker-mcp/blob/main/PRIVACY.md).
423
423
 
424
424
  ## Contributing
425
425
 
426
- Contributions are welcome. The project values a tight mapping between the Docker SDK's public surface and the MCP tools we expose. See [CONTRIBUTING.md](https://github.com/GavinLucas/docker-mcp/blob/main/CONTRIBUTING.md) for the project layout, tool conventions, the checklist for adding a new tool module, and local development setup.
426
+ Contributions are welcome. The project values a tight mapping between the Docker SDK's public surface and the MCP tools we expose. See [CONTRIBUTING.md](https://github.com/L337-org/docker-mcp/blob/main/CONTRIBUTING.md) for the project layout, tool conventions, the checklist for adding a new tool module, and local development setup.
@@ -24,4 +24,4 @@ results surfaced to the model. This policy covers only the behaviour of docker-m
24
24
  ## Contact
25
25
 
26
26
  Questions about this policy: open an issue at
27
- <https://github.com/GavinLucas/docker-mcp/issues>.
27
+ <https://github.com/L337-org/docker-mcp/issues>.
@@ -1,10 +1,10 @@
1
- <img src="https://raw.githubusercontent.com/GavinLucas/docker-mcp/main/assets/icon.png" align="left" width="72" height="72" alt="">
1
+ <img src="https://raw.githubusercontent.com/L337-org/docker-mcp/main/assets/icon.png" align="left" width="72" height="72" alt="">
2
2
 
3
3
  # docker-mcp-server
4
4
 
5
5
  [![docker-mcp MCP server](https://glama.ai/mcp/servers/GavinLucas/docker-mcp/badges/score.svg)](https://glama.ai/mcp/servers/GavinLucas/docker-mcp)
6
6
 
7
- <!-- mcp-name: io.github.GavinLucas/docker-mcp-server -->
7
+ <!-- mcp-name: io.github.L337-org/docker-mcp-server -->
8
8
 
9
9
  More than just a fully featured [MCP](https://modelcontextprotocol.io) server that lets AI agents manage Docker — containers, images, networks, volumes, swarm services, secrets, configs, nodes, plugins, etc., it helps you create workflows to easily manage your Docker environments.
10
10
 
@@ -51,7 +51,7 @@ To pin a specific version, append `==<version>` to the package name (e.g. `docke
51
51
  "command": "uvx",
52
52
  "args": [
53
53
  "--from",
54
- "git+https://github.com/GavinLucas/docker-mcp.git",
54
+ "git+https://github.com/L337-org/docker-mcp.git",
55
55
  "docker-mcp-server"
56
56
  ],
57
57
  "env": {}
@@ -65,7 +65,7 @@ To pin a specific revision, append `@<tag-or-commit>` to the git URL.
65
65
  ### Install as a Desktop Extension (.mcpb)
66
66
 
67
67
  For [Claude Desktop](https://claude.com/download), a one-click bundle is attached to each
68
- [GitHub Release](https://github.com/GavinLucas/docker-mcp/releases) as
68
+ [GitHub Release](https://github.com/L337-org/docker-mcp/releases) as
69
69
  `docker-mcp-server-<version>.mcpb` (with a matching `.sha256`). Download it and drag it into
70
70
  **Settings → Extensions**, or use **Settings → Extensions → Advanced settings → Install extension…**
71
71
  and pick the file. The install dialog surfaces a **Docker host(s)** field and the read-only /
@@ -82,7 +82,7 @@ Docker context; set one endpoint (`ssh://user@host`) for a remote daemon, or lis
82
82
  Running the server as a container removes the Python / uv / git prerequisites entirely — the only
83
83
  thing the host needs is Docker, which you already have. Prebuilt multi-arch images (linux/amd64 +
84
84
  linux/arm64) are published on each release to **Docker Hub** (`gavinlucas/docker-mcp-server`) and
85
- **GHCR** (`ghcr.io/gavinlucas/docker-mcp-server`) — the two are identical. Point your MCP client at
85
+ **GHCR** (`ghcr.io/l337-org/docker-mcp-server`) — the two are identical. Point your MCP client at
86
86
  `docker run`:
87
87
 
88
88
  ```json
@@ -103,14 +103,14 @@ linux/arm64) are published on each release to **Docker Hub** (`gavinlucas/docker
103
103
 
104
104
  `-i` is required (the server speaks MCP over stdio); `--rm` cleans up when the client disconnects. To
105
105
  pin a version, replace `:latest` with a release tag (e.g. `:1.5.1`). To pull from GHCR instead, use
106
- `ghcr.io/gavinlucas/docker-mcp-server:latest`.
106
+ `ghcr.io/l337-org/docker-mcp-server:latest`.
107
107
 
108
- > **Image renamed.** As of 1.5.0 the image is published to `ghcr.io/gavinlucas/docker-mcp-server`
109
- > (matching the PyPI name). The old `ghcr.io/gavinlucas/docker-mcp` image is frozen at 1.4.0 and no
110
- > longer updated — point new pulls at `…/docker-mcp-server`.
108
+ > **Image renamed.** As of 1.5.0 the image is published as `docker-mcp-server` (matching the PyPI
109
+ > name). The old `ghcr.io/gavinlucas/docker-mcp` image is frozen at 1.4.0 and no longer updated —
110
+ > point new pulls at `ghcr.io/l337-org/docker-mcp-server`.
111
111
 
112
112
  **Image variants.** Two variants are published to both registries (`gavinlucas/docker-mcp-server` on
113
- Docker Hub and `ghcr.io/gavinlucas/docker-mcp-server` on GHCR), both built from one `Dockerfile`. The
113
+ Docker Hub and `ghcr.io/l337-org/docker-mcp-server` on GHCR), both built from one `Dockerfile`. The
114
114
  CLI-backed domains (Compose, Stack, Buildx, Scout, Context) shell out to the `docker` CLI and its
115
115
  plugins.
116
116
 
@@ -333,7 +333,7 @@ All of these go in the `env` block of the server entry in your MCP client config
333
333
  "command": "uvx",
334
334
  "args": [
335
335
  "--from",
336
- "git+https://github.com/GavinLucas/docker-mcp.git",
336
+ "git+https://github.com/L337-org/docker-mcp.git",
337
337
  "docker-mcp-server"
338
338
  ],
339
339
  "env": {
@@ -351,7 +351,7 @@ Swap `DOCKER_MCP_SERVER_READONLY` for `DOCKER_MCP_SERVER_NO_DESTRUCTIVE` to allo
351
351
  ```bash
352
352
  claude mcp add docker-mcp-server-readonly \
353
353
  --env DOCKER_MCP_SERVER_READONLY=1 \
354
- -- uvx --from git+https://github.com/GavinLucas/docker-mcp.git docker-mcp-server
354
+ -- uvx --from git+https://github.com/L337-org/docker-mcp.git docker-mcp-server
355
355
  ```
356
356
 
357
357
  ## Security considerations
@@ -379,10 +379,10 @@ Connecting this server to an AI agent grants it the same level of access as a lo
379
379
  | Channel | Link |
380
380
  |---------|------|
381
381
  | PyPI | [docker-mcp-server](https://pypi.org/project/docker-mcp-server/) |
382
- | GHCR (container) | [ghcr.io/gavinlucas/docker-mcp-server](https://github.com/GavinLucas/docker-mcp/pkgs/container/docker-mcp-server) |
382
+ | GHCR (container) | [ghcr.io/l337-org/docker-mcp-server](https://github.com/L337-org/docker-mcp/pkgs/container/docker-mcp-server) |
383
383
  | Docker Hub (container) | [gavinlucas/docker-mcp-server](https://hub.docker.com/r/gavinlucas/docker-mcp-server) |
384
- | Desktop Extension (.mcpb) | [GitHub Releases](https://github.com/GavinLucas/docker-mcp/releases) |
385
- | Official MCP Registry | [io.github.GavinLucas/docker-mcp-server](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.GavinLucas%2Fdocker-mcp-server/versions) |
384
+ | Desktop Extension (.mcpb) | [GitHub Releases](https://github.com/L337-org/docker-mcp/releases) |
385
+ | Official MCP Registry | [io.github.L337-org/docker-mcp-server](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.L337-org%2Fdocker-mcp-server/versions) |
386
386
  | Glama | [docker-mcp-server](https://glama.ai/mcp/servers/GavinLucas/docker-mcp) |
387
387
  | mcp.so | [docker-mcp-server](https://mcp.so/server/docker-mcp-server/GavinLucas) |
388
388
  | awesome-mcp-servers | [punkpeye/awesome-mcp-servers](https://github.com/punkpeye/awesome-mcp-servers#cloud-platforms) |
@@ -391,8 +391,8 @@ Connecting this server to an AI agent grants it the same level of access as a lo
391
391
 
392
392
  docker-mcp-server collects no data, sends no telemetry, and has no author-operated backend. It runs
393
393
  locally and talks only to the Docker daemon and container registries **you** point it at, as part of
394
- the operations you request. The full statement is in [PRIVACY.md](https://github.com/GavinLucas/docker-mcp/blob/main/PRIVACY.md).
394
+ the operations you request. The full statement is in [PRIVACY.md](https://github.com/L337-org/docker-mcp/blob/main/PRIVACY.md).
395
395
 
396
396
  ## Contributing
397
397
 
398
- Contributions are welcome. The project values a tight mapping between the Docker SDK's public surface and the MCP tools we expose. See [CONTRIBUTING.md](https://github.com/GavinLucas/docker-mcp/blob/main/CONTRIBUTING.md) for the project layout, tool conventions, the checklist for adding a new tool module, and local development setup.
398
+ Contributions are welcome. The project values a tight mapping between the Docker SDK's public surface and the MCP tools we expose. See [CONTRIBUTING.md](https://github.com/L337-org/docker-mcp/blob/main/CONTRIBUTING.md) for the project layout, tool conventions, the checklist for adding a new tool module, and local development setup.
@@ -4,7 +4,7 @@
4
4
 
5
5
  If you believe you have found a security issue in `docker-mcp`, please open a
6
6
  private vulnerability report via GitHub's
7
- [security advisory flow](https://github.com/GavinLucas/docker-mcp/security/advisories/new)
7
+ [security advisory flow](https://github.com/L337-org/docker-mcp/security/advisories/new)
8
8
  rather than filing a public issue. That keeps the discussion private until a
9
9
  fix is available.
10
10