Defining schema drift
Tool-schema drift is what happens when the shape of a tool that an agent learned about, its name, description, required parameters, argument types, changes on the server side without any corresponding change on the client or agent side. The agent keeps calling the tool the way it always has. The server has moved on. Nothing crashes immediately; the agent just starts getting things subtly wrong.
This is different from a server going down or returning a JSON-RPC error. Drift is quieter than that: the connection works, the tool exists, the call often even succeeds. It just no longer means what the agent thinks it means.
How drift actually happens
In a normal software lifecycle, MCP servers get updated for reasons that have nothing to do with breaking anyone on purpose:
- A parameter that used to be optional becomes required.
- An enum of allowed values gains or loses an entry.
- A field's type narrows (a generic string becomes one restricted to a fixed pattern) or widens.
- A tool is renamed or removed as the underlying API evolves.
- A tool's description is rewritten to influence how models select it.
That last one is easy to underestimate. In MCP, the description isn't documentation for humans; the model reads it at inference time to decide whether and how to call the tool. Change the wording and you can change the model's tool-selection and argument-filling behavior even though the JSON Schema itself never moved. That makes description edits a real, if unconventional, category of schema drift.
Why it's silent
A few structural reasons make MCP drift harder to catch than a typical API breaking change:
- No enforced versioning. MCP tool definitions don't carry a semantic version the way a REST endpoint might carry a
/v2/path segment. A tool can change shape in place. - No contract tests by default. REST APIs are commonly covered by consumer-driven contract tests. Most MCP servers ship without any equivalent for their tool schemas.
- Tool lists get cached. Hosts often fetch
tools/listonce per session and don't re-check it until alist_changednotification fires, and not every server implementation sends that notification reliably. - The consumer is a model, not a type checker. A statically typed REST client fails loudly on an unexpected field. An LLM given a slightly wrong schema will often just guess, producing a plausible-looking call that fails validation, or worse, succeeds with the wrong arguments.
Put together: a server can drift on a Tuesday, and the first sign of it might be a user report three days later saying the agent seems less reliable, with no error anywhere in the logs.
A concrete failure scenario
Say a create_ticket tool required title and body. A server update makes assignee a required field, defaulting to nothing meaningful if omitted. The JSON Schema change is small and reasonable from the API's point of view. But every agent that learned the old schema keeps omitting assignee. Depending on how strictly the server validates, that either produces a hard validation error the agent has to interpret and recover from, or, worse, silently creates unassigned tickets, and nobody notices until someone asks why tickets aren't getting routed.
Detecting drift
The practical fix is treating a server's tools/list response as a versioned artifact, the same way you'd treat an OpenAPI spec:
- Snapshot it. Store the full tool list (names, descriptions, schemas) from each check.
- Diff it over time. Compare each new snapshot against the last known-good one, field by field.
- Classify changes by severity. A new optional tool is informational. A removed tool, a newly required parameter, or a narrowed type is breaking. A description change is worth flagging even though it's not a schema change in the strict sense.
- Alert on breaking changes, ideally with the actual diff attached, before an agent hits the change in production.
This is exactly the gap MCP Vitals is built to close: it runs the real MCP handshake against your servers on a schedule, hashes and diffs the tool schemas it gets back, and raises an alert with the specific field-level change when something drifts, rather than leaving you to find out from a confused user or a failed agent run.
Mitigating drift as a server operator
If you run MCP servers other people's agents depend on:
- Treat schema changes like API changes: changelog them, and where possible, avoid silently narrowing types or adding required fields to existing tools.
- Prefer adding a new tool over mutating an existing one's contract, when the change is significant.
- Keep tool descriptions stable once agents are relying on them; if you must edit wording, test that tool-selection behavior hasn't shifted.
- Publish and monitor a schema hash or version marker so downstream consumers can detect drift on their own.
Schema drift isn't a bug in MCP; it's a natural consequence of running any live system that other software depends on. The difference between a minor hiccup and a multi-day incident is usually just whether anyone was watching the shape of the contract, not only its uptime.