How MCP tool contracts change in the wild
mcpindex snapshots the public MCP registry's reachable remote servers and diffs every tool contract between snapshots. This report is the deduped, re-verified record of what changed: what kind of change, whether the server's declared version moved with it, and how often removal means replacement. A contract diff, not a safety verdict. Every number below is computed from the corpus, and every tool is a salted fingerprint - this page names no server.
Edition v1 · frozen 2026-07-19
DOI: 10.5281/zenodo.21449150These headline numbers are frozen as of 2026-07-19 and are the citable edition of this report. The live counters further down update with each crawl and are labeled separately, so a citation of this edition stays checkable against exactly these figures.
- Deduped safety-relevant incidents
- 2,503
- Landed with the declared version unchangedBasis: deduped safety incidents, first-occurrence delta.
- 62.4%
- Tools removed (deduped)
- 872
- Tools serving unstable contracts
- 76
- Coverage
- 23 snapshots across 40 days
Live since Edition v1
Everything below is auto-derived from the crawl corpus on every pipeline run - never hand-copied - and has accrued since the frozen edition above. Last derived 2026-07-22 (UTC).
What changed: 2,518 deduped incidents by kind
An incident is one (server, tool, change kind) triple, deduped across the whole window - the same tool changing the same way on five days counts once, with its occurrence span retained. Raw events observed: 63,471, of which 3,100 touched a safety-relevant contract field.
| Change kind | Incidents | Share |
|---|---|---|
| output-schema-changed (output shape changed) | 995 | 39.5% |
| tool-removed (tool removed) | 878 | 34.9% |
| removed-param (input removed) | 197 | 7.8% |
| annotation-flip-to-destructive (now marked destructive) | 123 | 4.9% |
| constraint-narrowed (input constraint tightened) | 119 | 4.7% |
| added-required-param (new required input) | 88 | 3.5% |
| type-changed (input type changed) | 67 | 2.7% |
| enum-values-removed (allowed values removed) | 28 | 1.1% |
| required-set-expanded (more inputs now required) | 23 | 0.9% |
Did the version move? The silent share, with its basis
For each incident we join the server's declared version across the pair of snapshots where the change first appeared. The silent share - the share of incidents that landed with the declared version unchanged - is 62.3%. Basis: deduped safety incidents, first-occurrence delta. That basis matters: the /ledger lede counts per-tool version behavior over every observed transition, a different (also labeled) basis, so the two numbers are reconcilable rather than interchangeable.
- Version unchanged across the change
- 1,569 · 62.3%
- Version changed with the change
- 949 · 37.7%
- No version declared at either snapshot
- 0 · 0%
"Version changed" means the declared version string differed across the pair - direction is never computed, so no claim about upgrades is made. A change arriving with an unchanged declared version is an observation about version behavior, not an accusation of intent.
Annotation flips: first labels vs changed guarantees
123 incidents flipped a tool to destructive. They split two ways: 68 were first-labelings - the old tool record carried no annotations block at all, so the flip is a server declaring safety hints for the first time, the ecosystem's labeling maturing - and 55 were guarantee changes, where an existing annotations block moved to destructive. First-labeling is the majority: most flips read as labels maturing, not guarantees changing. The segmentation below crosses each flip class with its version behavior.
| Flip class · version behavior | Incidents |
|---|---|
| first-labeling · version same | 63 |
| guarantee-change · version changed | 30 |
| guarantee-change · version same | 25 |
| first-labeling · version changed | 5 |
Removals: mostly replacement, rarely deletion
878 tools were removed (879 removal events - a tool can be removed, return, and be removed again). 740 (84.3%) were part of a toolset replacement - the same server shed five or more tools in one snapshot pair, typically an API redesign - while 138 were single-tool removals. The copy follows the data: replacement is the dominant reality; the rare single deletions are the events worth a second look. Removal entries are historical observations - a same-named tool may have since returned.
Unstable contracts, counted apart
78 tools serve unstable contracts (104 incidents, 5.8% of events): the contract changed on five or more distinct days, reverted to an earlier hash, or churned its hash while the schema stayed the same (dynamic metadata). Counting an oscillating contract as fresh drift every day would inflate the numbers, so the unstable class is excluded from the headline counts and reported here as its own finding. Excluding it, the deduped incident count is 2,414 and the share landing with the declared version unchanged rises to 63.3% (same basis as above) - the segmentation strengthens the headline rather than propping it up.
Coverage, stated honestly
This corpus is 25 snapshots across 42 days (2026-06-09 to 2026-07-21, 24 adjacent pairs), including a 21.1-day gap (2026-06-20 to 2026-07-11) when the crawler was down. It is not an unbroken daily series and we do not present it as one: incidents are deduped across the gap rather than papered over it, and changes that happened entirely inside the gap window were never observed.
Methodology
- Population: roughly 2,090 reachable remote servers of the indexed official registry. Indexed and crawled are different populations - a local-only or unreachable server never appears here, and absence from this report is not a clean bill of health.
- Merge per name: registry entries sharing one name are merged to a single record before diffing (winner: reachable, then most tools; other endpoints retained as alternates), so two deployments contending for one name can never mint phantom drift against each other.
- Flap guard: each snapshot pair is scoped to servers reachable in both snapshots before diffing, so a server flapping out of reachability never reads as mass tool removal.
- Dedup: incidents are one (server, tool, change kind) triple with first-seen / last-seen / occurrence count. Version behavior is joined per incident from the snapshot pair where it first appeared, anchored on content hashes.
- Unstable exclusion: five or more distinct change days, a hash revert, or a dynamic-metadata signature flags a tool unstable; the class is excluded from headline counts and reported separately above.
- Anonymization: tools and servers are salted fingerprints on every public surface of this dataset. This page names no server; per-server context lives on the named server pages with their own fairness labels.
The full pipeline, taxonomy, and disclosure history: /methodology.
Appendix · the census behind these numbers
Before publishing, we re-verified every event rather than sampling: a census of the 55,443-event corpus, recounted independently of the pipeline that produced it. The change-kind classifier came back with 0 misclassifications across the census, and no safety-relevant change was found missed.
The census also found our own day-one artifacts: reachability flaps on the first crawl day had minted phantom tool-removal events. We excluded them by regenerating every report from the retained snapshots with the current merge and flap-guard methodology - the ground-truth snapshots are archived, so every number here is re-derivable - and only then pinned the edition figures above.
Validation method, in short: independent recount of event totals per kind; hash-anchored adjacent-pair version joins checked for exactness against the pinned counts; and manual triage of every anomaly class (oscillating contracts, name collisions, flap artifacts) with each resolution disclosed in the methodology rather than silently absorbed - finding and excluding our own artifacts is the point of a census.
These numbers are observations after the fact.
The report tells you contracts change underneath agents; it cannot stop the next one. The gate pins every tool contract your agent uses on first sight and holds the call when a pinned contract changes - the check that keeps being true on Tuesday.
See your first HOLD in 2 minutes →
Background: silent contract drift · mcp.lock
For platform teams
mcpindex is a policy layer for MCP adoption. Pin every approved server's tool contracts at adoption time, so what your agents run is what you reviewed. The gate holds a call when a pinned contract changes underneath it - including changes that arrive with the declared version unchanged - until someone re-approves. The receipts page is the audit artifact: per-install evidence of what was held and why. All of it is a deterministic contract diff, never a safety verdict, and the methodology is public.
Evaluating MCP trust for a team? Email gb@mcpindex.ai - early design partners get input on the roadmap.
Page refreshed every 5 minutes · frozen edition numbers never change