MCP breaking changes

A breaking change to an MCP server is any change that makes a request your agent already sends invalid, or removes something it already reads. Not that the server went down, and not that the JSON looks different, the test is whether working code stops working, and it is asked from the consumer's side, because the server has no idea what you send.

That definition matters because MCP has no version numbers. A REST API breaks at v2, an npm package breaks when you upgrade. A remote MCP server breaks whenever its authors deploy, and your agent picks up the new contract on its next handshake with nothing to review and nothing to pin against.

The three severities

Breaking: a tool, resource or prompt disappears or is renamed, a required input appears, an input field is removed, a type is narrowed, an enum value is dropped, or an output field your code reads is gone. Existing valid calls now fail, or quietly return less than they did.

Risky: nothing errors, but behaviour can move. A new optional input, a new enum value, a changed default, a new output field, or a description rewritten past a word-delta threshold. Descriptions are the one most tools miss, the text is what steers which tool a model picks and how it fills arguments, so rewriting it changes runtime behaviour without changing a single schema type.

Safe: cosmetic or strictly relaxing. A tool added, a required field made optional, a description tidied. Nothing that worked can stop working.

Why they are invisible

The failure mode is not an exception. A lenient server accepts your now-outdated request and returns 200 with the wrong shape; a strict one returns a validation error the model reads as a tool result and works around by trying something else. Either way your error tracker stays green, your uptime check stays green, and the only symptom is an agent that has quietly started doing the wrong thing.

There is also nobody to notify you. Servers publish no changelogs, and the ones that do publish them after the fact. Detection has to come from watching the contract itself, on a schedule, whether or not any traffic hit the changed tool.

Observed on the public monitor

What actually changes in MCP contracts

Every figure below is counted from the 269,213 individual contract changes Zevruna has recorded across 2,409 public MCP servers since 2026-08-12, one row per change rather than per deploy. It updates itself as the monitor observes more.

37%Breaking
24%Risky
39%Safe
17,903Contract revisions
ChangeSeverityTimes seenShare
Tool addedsafe61,82823%
Tool removedbreaking56,31821%
Output field addedrisky30,74911%
Resource addedsafe26,15910%
Resource removedbreaking23,7619%
Description rewrittensafe14,0995%
Input field addedrisky13,2645%
Description rewrittenrisky12,1865%
Input field removedbreaking5,5742%
Enum value addedrisky5,4182%
Enum value removedbreaking4,0842%
Output field removedbreaking3,5311%
Default changedrisky3,2981%
Input type changedbreaking2,1981%
Prompt addedsafe1,5961%
Output type changedbreaking1,2340%
Prompt removedbreaking1,1440%
Input field became optionalsafe9750%
Input field became requiredbreaking8260%
Enum narrowedbreaking4370%
Tool renamedbreaking2910%
output_property_renamedbreaking1780%
Input field renamedbreaking650%

Description rewrites appear twice: below the word-delta threshold they are cosmetic, above it they change which tool a model picks.

Questions

Is a new optional field really a breaking change?

No, and Zevruna does not classify it as one. It is risky: your calls keep working, but the model now sees an argument it did not see before and may start sending it. Worth knowing about, not worth failing a build over.

Why is a description change not cosmetic?

Because model-facing text is contract surface. The description decides which tool gets selected and how arguments are constructed, so a rewrite can change behaviour with no schema change at all. Zevruna computes a word-level delta and flags rewrites above a threshold as risky.

How do I find out my agent is affected?

Generate a manifest of what each agent actually sends and reads, then cross it with the classified diff. That is what turns "this server changed" into "these two agents break, at these call sites" — and it is why most changes should alert nobody.

Can I pin an MCP server the way I pin a dependency?

Not upstream, no. The schema has already shipped; a pin cannot hold the server back. What a pin does is fail your CI until your call sites match the new contract, so the break is caught at build time instead of in production.

Next step

Paste any MCP endpoint on the homepage, its contract report is free and needs no account.

Check a server freeRead the docs