Detect MCP breaking changes before merge

Compare MCP tool schemas, descriptions and capabilities with a deterministic contract check in your pull request.

An MCP server exposes more than JSON Schema. Tools, resources, resource templates, prompts, capabilities and server instructions all form its contract. An agent uses descriptions and annotations to decide what to call, so a change can alter behavior even when an existing request still validates.

#Which changes can break an MCP caller?

ChangeWhy it mattersMCP Inspect severity
Remove a toolA caller can still request its old name.BREAKING
Make an optional input requiredPreviously valid calls can omit it.BREAKING
Narrow an input enumA caller can send a previously accepted value.BREAKING
Rewrite a tool description substantiallyAn agent may change its tool selection.POTENTIALLY_BREAKING
Change an annotation such as readOnlyHintThe host or agent may treat the tool differently.POTENTIALLY_BREAKING
Add a toolExisting tool contracts remain available.NON_BREAKING

These are examples, not an exhaustive checklist. The rule reference documents every emitted rule id and its migration hint. Input and output schemas have different compatibility directions. An unmodeled schema keyword is reported as breaking rather than silently ignored.

Description classification is a deterministic heuristic. It identifies changes worth reviewing; it does not predict a particular model’s behavior. Re-run your tool-selection evaluations when the meaning changes.

#Compare before and after

Run this in your MCP server repository before editing the contract:

mcp-inspect init --snapshot

This writes configuration and captures .mcp-inspect/surface.json. The inspector discovers the advertised contract over stdio or streamable HTTP without invoking tools. A baseline capture by itself is not a compatibility verdict.

After making your change and rebuilding the server, compare against that baseline:

mcp-inspect check --baseline-file .mcp-inspect/surface.json

The check captures the current surface without overwriting your baseline. By default a breaking change exits 1; a connection or capture failure exits 2. Set fail_on: POTENTIALLY_BREAKING in .mcp-inspect.yml if substantial prose and annotation changes should also block CI. Severity details.

For two existing captures, use mcp-inspect diff before.json after.json. The verdict needs no hosted account or LLM API key.

#Gate a pull request

Run mcp-inspect init --workflow and review the generated workflow, server build command and secrets. Commit the configuration and baseline to the base branch. The GitHub Action compares against that branch and updates one PR comment with findings and migration hints.

A first setup PR can report a skipped comparison. That is not a clean comparison; the Action’s compared=true output tells you whether analysis actually ran. Once an intentional change is reviewed, capture and commit the updated baseline with it. The PR still compares against the previous baseline in the base branch.

#What contract checks do not measure

A snapshot captures the surface a particular caller can discover. It does not execute handlers, test business logic or prove an agent completed its task. Keep integration tests and tool-selection evaluations alongside the contract check.

Optional telemetry adds observed tool and argument-path usage. It records no argument values. Observation windows and collection limits matter: absence of observed usage is not proof that removing a tool will affect nobody.

If you consume a third-party server, the hosted console can schedule captures under watched-server settings and alert when its contract changes. Local mcp-inspect watch instead rechecks your own server on source-file changes; these are separate workflows.