Problem
Renovate version bumps for MCP servers fail the build-containers Grype gate (--fail-on high --only-fixed) when the bumped package pins or caps a transitive dependency to a vulnerable version, and we have no way to override that pin from within dockyard. Three open PRs are blocked on exactly this:
| PR |
Package |
Vulnerable transitive dep |
Why we can't fix it |
Worst |
| #469 |
@brightdata/mcp 2.9.5 |
@modelcontextprotocol/sdk hard-pinned 1.21.2 |
package pins exact version; fixes are ≥1.24 |
3× HIGH |
| #527 |
mcp-clickhouse 0.3.0 |
fastmcp capped <3.0.0 |
CRITICAL fix is fastmcp 3.2.0, excluded by cap |
CVE-2026-32871 (Critical) |
| #528 |
mcp-neo4j-cypher 0.6.0 |
fastmcp capped <2.14 |
all fixes (2.14.x / 3.2.0) excluded by cap |
Critical + 3 HIGH |
(Note #527 and #528 are also regressions vs. what main currently ships — see those PRs.)
Proposal
Add an optional dependency-override mechanism to the spec.yaml schema, plumbed into the generated Dockerfile:
spec:
package: "@brightdata/mcp"
version: "2.9.5"
overrides: # npx → npm "overrides"
"@modelcontextprotocol/sdk": "1.26.0"
spec:
package: "mcp-clickhouse"
version: "0.3.0"
constraints: # uvx → uv "--override" / constraints file
- "fastmcp>=3.2.0"
Implementation sketch
- Extend
MCPServerPackageSpec (cmd/dockhand/main.go:43) with Overrides map[string]string (npx) and/or Constraints []string (uvx).
generateDockerfile (cmd/dockhand/main.go:354) already receives the Dockerfile as a string from toolhive's BuildFromProtocolSchemeWithName(..., dryRun=true). Post-process that string to inject the override:
- npx: emit a
package.json containing an overrides block before the npm install --save <pkg> step (npm honors overrides only from package.json).
- uvx: add
--override <constraints-file> (or per-spec --override pkg>=ver) to the uv tool install step.
- Require every override entry to carry a short justification (mirroring
security.allowed_issues) so the why is auditable in-repo.
Verification (already done manually)
A throwaway test of each override was run against the exact build recipe + the same Grype gate:
Acceptance
🤖 Generated with Claude Code
Problem
Renovate version bumps for MCP servers fail the
build-containersGrype gate (--fail-on high --only-fixed) when the bumped package pins or caps a transitive dependency to a vulnerable version, and we have no way to override that pin from within dockyard. Three open PRs are blocked on exactly this:@brightdata/mcp2.9.5@modelcontextprotocol/sdkhard-pinned1.21.2mcp-clickhouse0.3.0fastmcpcapped<3.0.0fastmcp 3.2.0, excluded by capmcp-neo4j-cypher0.6.0fastmcpcapped<2.14(Note #527 and #528 are also regressions vs. what
maincurrently ships — see those PRs.)Proposal
Add an optional dependency-override mechanism to the
spec.yamlschema, plumbed into the generated Dockerfile:Implementation sketch
MCPServerPackageSpec(cmd/dockhand/main.go:43) withOverrides map[string]string(npx) and/orConstraints []string(uvx).generateDockerfile(cmd/dockhand/main.go:354) already receives the Dockerfile as a string from toolhive'sBuildFromProtocolSchemeWithName(..., dryRun=true). Post-process that string to inject the override:package.jsoncontaining anoverridesblock before thenpm install --save <pkg>step (npm honorsoverridesonly from package.json).--override <constraints-file>(or per-spec--override pkg>=ver) to theuv tool installstep.security.allowed_issues) so the why is auditable in-repo.Verification (already done manually)
A throwaway test of each override was run against the exact build recipe + the same Grype gate:
overrides {"@modelcontextprotocol/sdk":"1.26.0"}→ resolves to a single SDK 1.26.0, grype clean, gate passes, same-major so no API break.uv --override "fastmcp>=3.2.0"→ fastmcp 3.4.0,import mcp_clickhouseOK, grype clean (this just restores whatmain's 0.2.0 already ships).fastmcp>=3.2.0→ grype clean + imports, but crosses upstream's deliberate<2.14cap (major 2→3 jump) — needs functional testing of the neo4j tools before trusting.Acceptance
spec.overrides(npx) andspec.constraints(uvx) supported + documentedbuild-containerswith overrides applied🤖 Generated with Claude Code