Skip to content

Support forcing transitive dependency versions in protocol-scheme builds #6209

Description

@danbarr

Problem

--build-with (#6116) constrains a transitive dependency that upstream leaves unbounded. That is its design: it maps to uv tool install --with '<spec>', an additive requirement the resolver must satisfy alongside what upstream declared.

It structurally cannot help when upstream pins or caps the vulnerable dependency, because no satisfiable version is left to ask for. fastmcp>=3.2.0 alongside upstream's fastmcp<3.0.0 is an unsatisfiable set, so the resolver errors instead of resolving our way. Beating a pin or a cap needs a force override, a different mechanism.

Real examples of the shape, from dockyard#668: @brightdata/mcp 2.9.5 hard-pins @modelcontextprotocol/sdk at 1.21.2 (fixes are >=1.24); mcp-clickhouse 0.3.0 caps fastmcp<3.0.0 (the CRITICAL fix is 3.2.0); mcp-neo4j-cypher 0.6.0 caps fastmcp<2.14 (all fixes excluded).

This is also why npx:// has no build-time dependency support at all. npm resolves each parent's range independently and nests a private copy, so there is no additive analogue of --with to add: installing @modelcontextprotocol/sdk@1.26.0 at the top level of the generated package.json leaves @brightdata/mcp's pinned 1.21.2 in node_modules/@brightdata/mcp/node_modules/. Overrides is npm's only lever, and it happens to cover both the pin and the cap case.

Sketch

A RuntimeConfig.BuildOverrides []string field with a --build-override flag on thv build and thv run, meaning "force this version wherever it appears in the tree". --build-with unchanged. Entries in each ecosystem's native syntax, matching the existing "interpreted per package ecosystem" convention:

  • npx: @modelcontextprotocol/sdk@1.26.0, split into name + range to become an overrides object in the package.json generated at npx.tmpl:56. npm honors overrides only from the root manifest and only if present before npm install, so that RUN echo ... > package.json line is the injection point, not the install line.
  • uvx: fastmcp>=3.2.0, written as lines of a requirements file passed to uv tool install --overrides <file> (verified present, and composable with the existing --with).
  • go: reject, as --build-with does today.

Validation needs a wider allowlist than buildWithPattern to cover npm syntax (@, /, ^, |) while still excluding anything that could escape a single-quoted shell word or a JSON string literal.

Status

Not scheduled, and there is no current consumer: dockyard is implementing native override support on its own side (dockyard#669), which supersedes its use of --build-with as well. Filing to record the finding so the next person hitting a pinned or capped transitive dep does not rediscover why --build-with will not fix it. Revisit if demand appears outside dockyard.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-triageIssue needs initial triage by a maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions