Skip to content

CI: run the MCP interface diff only for servers a PR changes, and add it for every server #5428

Closed

Description

@cliffhall

Problem

The everything MCP interface diff (.github/workflows/everything-mcp-diff.yml, scripts/interface-diff.mjs, #4860) runs, and posts its sticky "everything: MCP interface diff" comment, on PRs that do not touch the everything server at all.

The workflow already has a paths filter, but besides src/everything/** it lists the root package.json, package-lock.json and tsconfig.json. Almost every TypeScript PR changes the root lockfile, so the filter rarely excludes anything. Two examples from today:

Also, only everything gets an interface diff. The other six servers have none, so a tool, prompt, resource or capability change in them gets no reviewer-facing report.

Expected behavior

  1. Each server's interface diff runs only when that PR changes that server. "Changes that server" means src/<server>/**, plus a change to the dependency tree the server actually resolves. A root lockfile edit counts only when it changes a package <server> resolves, not just because the file changed. The diff tooling itself (scripts/interface-diff.mjs, its helpers and the workflow) still triggers every server's diff.
  2. Every server gets an interface diff. That covers the four TypeScript servers (everything, filesystem, memory, sequentialthinking) and the three Python servers (fetch, git, time), each with its own sticky PR comment (one marker per server) and its own report artifact.

Notes for the implementation

  • paths is per workflow, not per server, and it cannot express "the lockfile changed in a way that affects server X". A changes job that computes the affected servers and fans out through a matrix will probably work better than seven copies of the workflow. The same job could also handle the lockfile check, for example by comparing npm ls --workspace src/<server> --all between base and head, or by checking whether uv.lock changed for the Python servers.
  • scripts/interface-diff.mjs is hard-wired to everything. It needs a --server <name> argument, and for the Python servers it has to build or run the base with uv (uv run --frozen mcp-server-<name> from the exported base tree) rather than node dist/…. Some servers need arguments to boot (for example, filesystem needs an allowed directory, and git may need a repository), so each server needs its own start command.
  • local:gate: the interface-diff stage runs on every gate today. It should follow the same rule and diff only the servers changed since the merge-base with origin/v2/main. scripts/lib/workflow-gate.test.mjs requires CI and the gate to run the same npm script, so both should share the server-selection logic.
  • Keep the existing security split (untrusted build in a read-only diff job, comment posted by a separate job that runs no PR code), the release and workflow_dispatch triggers, and the fork-PR fallback to the job summary and artifact.
  • Update docs/quality-gate.md, the AGENTS.md tree entry and the gate description that name the everything-only diff.

Related: #4860 (where the diff was adopted), #5173 (version PRs), and #5218 (an outside proposal for per-server contract diffs).

Activity

  1. added this to the v2.4.0 milestone on Nov 4, 2026
  2. added
    choreMaintenance: deps, build tooling, CI, cleanup — no user-facing behavior change
    on Nov 4, 2026
  3. self-assigned this
    on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

choreMaintenance: deps, build tooling, CI, cleanup — no user-facing behavior changev2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions