Skip to content

Commit 73fe685

Browse files
committed
fix: docker server pinning end-to-end + migrate 5 npm servers to mcp/* images
Two latent bugs in the docker install branch surfaced when the github_mcp digest finally got captured today: (1) load_pinned_servers read docker_digest but the yaml uses image_digest, so docker fields were never loaded into PinnedServer; (2) stdio_params_for built `docker run -i <bare-sha256>`, which is not a valid image reference. Renamed to image_digest, added docker_image field, and stdio_params_for now builds `<image>@<digest>`. Migrated 5 servers (git/fetch/sequentialthinking/time/sqlite) from @modelcontextprotocol/server-* on npm — all 404 as of 2026-05-26 — to official mcp/* Docker images, digest-pinned. environment.lock now captures 6 docker digests; pool/descriptions.json bootstrapped with 7 server entries (5 newly-docker'd + filesystem_mcp + memory_mcp). 253/253 tests pass (247 prior + 6 new docker-branch tests).
1 parent a857612 commit 73fe685

8 files changed

Lines changed: 1230 additions & 54 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ All notable changes to tool-crowding are documented here. Format follows [Keep a
44

55
## [Unreleased]
66

7+
### Fixed — docker MCP server pinning end-to-end: yaml field-name mismatch + invalid `docker run` reference (2026-05-26)
8+
9+
- `servers_pinned.yaml` used `docker_image` and `image_digest` for `github_mcp`, but `tcrun/servers.py::load_pinned_servers` read `docker_digest` — so the docker fields had never actually been loaded into `PinnedServer`. `verify_pins(...)` would have raised `ServerPinMismatch("docker install requires docker_digest pin")` for any pinned docker server because `pin.docker_digest` was always `None`. Latent since the docker branch landed; surfaced only when `github_mcp`'s digest finally got pulled (Docker daemon HTTP 500 had blocked the capture since 2026-05-23).
10+
- `stdio_params_for(pin)`'s docker branch built `docker run --rm -i <bare-sha256>` from `pin.docker_digest or "latest"`. A bare digest is not addressable by `docker run` — the canonical form is `<image>@sha256:<hex>`. Even after fixing the field-name bug, every docker spawn would have failed.
11+
- Fix: `PinnedServer.docker_digest` renamed to `image_digest`; new `docker_image` field. `load_pinned_servers` reads both. `verify_pins` requires both for `install: docker`. `stdio_params_for` builds `f"{pin.docker_image}@{pin.image_digest}"`; raises `ServerInstallError` if either is missing (defense-in-depth — `verify_pins` is the contract gate, but the snapshot path doesn't run it).
12+
- `tcrun/snapshot.py::_pin_identity` renamed `pin.docker_digest``pin.image_digest` to match.
13+
- 6 new tests in `tests/test_servers.py`: `verify_pins` rejects partial docker pin (image-only, digest-only); accepts both-present; `load_pinned_servers` reads `docker_image` + `image_digest` from yaml; `stdio_params_for` builds the digest-pinned reference; raises on missing fields.
14+
15+
### Changed — 5 npm-distributed MCP servers migrated to official `mcp/*` Docker images (2026-05-26)
16+
17+
- `npx -y @modelcontextprotocol/server-{git,fetch,sequentialthinking,time,sqlite}` is 404 on npm as of 2026-05-26 (audited against the npm registry directly). All 5 packages have official Docker images at `mcp/*` on Docker Hub (modelcontextprotocol-owned). Migrated `tcrun/servers_pinned.yaml` to `install: docker` for each, pinned by image digest. `github_mcp` digest also captured (was TBD since 2026-05-23 Docker daemon outage). See `DevVault/tool-crowding/server-pool-audit-2026-05-26.md` for the upstream-npm failure evidence + migration rationale.
18+
- `environment.lock` regenerated: `docker_images` count 0 → 6.
19+
- `pool/descriptions.json` bootstrapped via `tcrun snapshot-descriptions --all`: 7 servers populated (5 newly-docker'd: git_mcp/fetch_mcp/sequential_thinking_mcp/time_mcp/sqlite_mcp; plus filesystem_mcp + memory_mcp on npx). Remaining failures are pre-existing and unblocked by this work: `github_mcp` (needs `GITHUB_PERSONAL_ACCESS_TOKEN` for MCP handshake), `aider_mcp`/`oci` (need `server-pool/` clones), `postgres_mcp`/`brave_search_mcp`/`slack_mcp` (`stdio_params_for` has no `install: tarball` branch yet), `linear_mcp`/`notion_mcp` (`package: TBD`, OAuth-deferred post-pilot).
20+
721
### Fixed — pin `typer<0.26` to keep `CliRunner.isolated_filesystem` available (2026-05-26)
822

923
- Typer 0.26.0 (released 2026-05-26) replaced its `CliRunner` with a fresh `typer._click.testing.CliRunner` that no longer inherits from `click.testing.CliRunner`, so `isolated_filesystem()` is no longer a method. CI installed typer 0.26.0 transitively (pyproject had `typer>=0.12` with no upper bound) and 5 tests in `tests/test_cli.py` failed with `AttributeError: 'CliRunner' object has no attribute 'isolated_filesystem'`. Added an upper bound `typer>=0.12,<0.26` to unblock CI. Follow-up migration tracked in [#1](https://github.com/DevanshuNEU/tool-crowding/issues/1) (replace `runner.isolated_filesystem()` with pytest's `tmp_path` + `monkeypatch.chdir`).

harness/environment.lock

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
{
22
"docker_images": {
3-
"ghcr.io/github/github-mcp-server": "sha256:fc0318a670520247ae6d58930c7c54a2f82cc7652dc7809044abff77db467a7a"
3+
"ghcr.io/github/github-mcp-server": "sha256:e3816a476a977cfb836e7d221510011436c654d11861db66ecfd826601aba6a4",
4+
"mcp/fetch": "sha256:d9907377c03da91e49cf02c3dd6f0f83d1e0183e1222850f92595089f2c9a59d",
5+
"mcp/git": "sha256:ad6af958e79466a14b895891e772fdda28fdc12c06fff4a70637b66773303a2c",
6+
"mcp/sequentialthinking": "sha256:cd3174b2ecf37738654cf7671fb1b719a225c40a78274817da00c4241f465e5f",
7+
"mcp/sqlite": "sha256:efbc05ccace18df122f26b674bd1730c76ece716551df2b3961d519909c34696",
8+
"mcp/time": "sha256:9c46a918633fb474bf8035e3ee90ebac6bcf2b18ccb00679ac4c179cba0ebfcf"
49
},
5-
"harness_git_sha": "bff91cfa8421a49a6a5d1563e967b380ce119916",
10+
"harness_git_sha": "a857612f5de896ca19169085924e2c24f6e39f26",
611
"os": "macOS-15.0.1-arm64-arm-64bit-Mach-O",
712
"pip_freeze": [
8-
"-e git+ssh://git@github.com/DevanshuNEU/tool-crowding.git@bff91cfa8421a49a6a5d1563e967b380ce119916#egg=tool_crowding&subdirectory=harness",
13+
"-e git+ssh://git@github.com/DevanshuNEU/tool-crowding.git@a857612f5de896ca19169085924e2c24f6e39f26#egg=tool_crowding&subdirectory=harness",
914
"PyJWT==2.13.0",
1015
"PyYAML==6.0.3",
1116
"Pygments==2.20.0",

0 commit comments

Comments
 (0)