Implementing Semantic Versioning for MCP Tools: Managing Protocol Drift

Written by

in

# Implementing Semantic Versioning for MCP Tools: Managing Protocol Drift

![Implementing semantic versioning for MCP tools with OnlineCloud](https://www.onlinecloud.dev/assets/hero-profile-BlpwYfK_.png)

*By the engineering team at OnlineCloud — a US-based Agentic AI & MCP engineering studio*

—

## 1. Introduction: Why Breaking Changes in Tool Schemas Kill Production Agents

Every team that has shipped an agent to production learns the same lesson the worst way. Your MCP server has run for months; ticket deflection is up, your CFO is happy. Then someone “tidies up” a tool schema on a quiet Tuesday: `create_ticket(customer_email)` becomes `create_ticket(contact_id)`. A human API consumer reads the changelog and fixes their integration in an afternoon. Your agent keeps working — badly.

Here is what actually happens. The next customer inquiry arrives, and the model, still “knowing” the old surface from its prompts, training, and session context, calls with `customer_email`. The server rejects it. The model retries — models are stubborn about well-learned patterns — then burns tokens re-reading the schema and guesses at what `contact_id` means. It either fails the task or fabricates a value that validates but resolves to the wrong customer. The ticket is misrouted. PII lands in the wrong inbox. Nobody gets paged, because nothing *threw*; the agent just quietly delivered a worse outcome.

This is the asymmetry between human and machine consumers. A human integrates against a contract once and reads release notes on change. A production agent re-discovers your tool surface every session, but it arrives carrying priors from everything it has ever seen — including your schema from three months ago. When the tool boundary drifts from what the model expects, the failure is not a clean error code. It is degraded behavior inside an unattended loop: retries, hallucinated arguments, and confidence miscalibration that logs can barely trace.

We call this **protocol drift** — the gap between the surface your server advertises and the surface your agents believe they are calling. In fifteen-plus years shipping data systems at OnlineCloud — Oracle, MS SQL, Postgres, Snowflake, CRMs — we have never seen a system fail because a contract existed. We have seen systems fail because contracts changed without discipline. This post is the playbook for versioning MCP tool interfaces with semantic versioning, so schema evolution becomes routine instead of an outage in slow motion.

—

## 2. SemVer for AI: Defining Major/Minor/Patch for Tool Interfaces

Semantic versioning was designed for libraries, where the unit of compatibility is the function signature. In MCP, the unit is the **tool surface**: the `inputSchema` that defines every request an agent can validly send, and the `returns` — the output shape of a successful `tools/call`. Version the surface, and SemVer maps cleanly if you define the boundaries precisely.

**Patch (x.y.***z***) — nothing about valid requests or responses changes.** You clarified a tool’s `description`, fixed an error message, or added an `example` to a schema property. Any agent that worked before works identically after. One warning: description edits are invisible to type systems but fully visible to models, so treat them as *behavioral* patches and run them through the same eval gate as code.

**Minor (x.***y***.z) — backwards-compatible additions.** You added an *optional* input property with a sensible default, added an enum value that maps to an existing code path, added an output field old consumers will ignore, or shipped a brand-new tool. The discipline is ruthlessness about the word *optional*: adding a *required* property changes the set of valid requests, which makes it major. Output additions are minor only if consumers tolerate unknown fields; otherwise they are major too. Our standing rule: *new required field, new tool name.*

**Major (x.***y***.z) — previously-valid calls stop working or semantics change.** Removing or renaming a tool; changing a type, `pattern`, or `minimum`; tightening an `enum`; adding a required property; removing an output field; changing error or side-effect semantics. Major is not a value judgment; it is the statement that existing agents will break, and you are buying the right to break them deliberately.

Two properties of AI consumers make this trickier than human APIs. First, **the schema is not the only contract** — models also learn behavior from descriptions, examples, and listing order, so a technically-minor reword can be behaviorally major. Second, **models generalize**: tightening an enum from five values to three doesn’t just reject two strings — it changes the model’s willingness to attempt adjacent calls. When in doubt, call it major: an unannounced breaking change in an unattended loop costs an order of magnitude more than one extra version bump.

Finally, version at the right granularity. A server with forty tools does not need one monolith version; it needs a version per tool surface, aggregated into a published manifest (section 4).

—

## 3. Deprecation Patterns: Orchestrating Tool Upgrades Without Agent Downtime

Knowing a change is major solves nothing. The hard part is moving agents — some long-running, some third-party — off the old surface without a cutover weekend.

**Additive first.** MCP’s tool namespace is flat, so you cannot serve two `create_ticket` tools — but you can ship `create_ticket_v2` beside the original. That is additive, minor, and safe: both appear in `tools/list`, agents discover both, and nothing breaks because nothing changed.

**Dual-run.** While both versions live, run the same canonical task set against each and compare tool-call validity, completion, and repair-loop frequency before any production traffic shifts. This surfaces the real breakage — not schema violations (CI covers those) but *which* tool the model picks and how often it fumbles new argument shapes.

**Canary.** Shift production by the natural unit: new sessions and new agent instances, whose tool expectations crystallize early. Point 5–10% of new sessions at a profile that hides the deprecated tool, watch error rates and outcomes for two weeks, then expand. Rollback is a configuration flip.

**The deprecation lifecycle.** Codify four states, each visible in `tools/list`:

1. **Active** — current, fully supported.
2. **Deprecated** — works identically, but the description opens with `DEPRECATED — use create_ticket_v2`. The model gets positive pressure toward the new tool *and* a working fallback. Log every deprecated call with session and agent version — that is your migration telemetry.
3. **Sunset** — reachable only by explicit opt-in; returns a structured error naming the replacement. Few models keep fighting once the failure is loud and gives the answer.
4. **Removed** — the major lands; the tool disappears and your golden suite confirms nothing in the wild still calls it.

The cardinal rule: **never remove a tool that anything still calls.** Before the removal major, require a sustained window — at OnlineCloud, no fewer than four weeks — of zero deprecated-tool call volume across production and eval traffic. Sessions that cached the old surface can resurface weeks later. The deprecation window is not overhead; it is what makes major bumps boring.

—

## 4. Metadata: Using Annotations and Version-Scoped URIs in MCP

Versions only help if they are machine-readable where agents consume them. MCP gives you two native mechanisms — annotations and URIs — plus protocol signals, and disciplined teams use all three.

**Annotations.** Every tool carries an `annotations` object (`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) that shapes how hosts and models treat it — treat it as part of the versioned surface. Extend it with explicit version metadata, and mirror it in a canonical, parseable description block so a model reading the listing can act on it even if the host never surfaces the structured field:

“`json
{
“name”: “create_ticket_v2”,
“annotations”: { “title”: “Create ticket (v2)”, “readOnlyHint”: false },
“description”: “[version=2.1.0][deprecates=create_ticket][since=2026-08-01] Create a support ticket.”,
“inputSchema”: { “type”: “object”, “required”: [“contact_id”, “subject”, “severity”], “properties”: { “contact_id”: { “type”: “string” }, “subject”: { “type”: “string” }, “severity”: { “type”: “string”, “enum”: [“low”, “medium”, “high”] } } }
}
“`

**Version-scoped URIs.** MCP resources are addressed by URI, and the URI can be part of your contract. Serve each tool version’s JSON Schema at a stable address — `mcp://server/schema/create_ticket/v2` — so schemas become fetchable, cacheable, diffable artifacts that eval harnesses, audit tools, and golden-file suites consume from one source of truth. Keep alias URIs — `mcp://server/tools/create_ticket/latest` — for agents that want the current major, while cautious agents pin `@2`.

**Protocol signals.** MCP negotiates `protocolVersion` at the transport layer, and servers can emit `notifications/tools/list_changed` whenever the surface mutates mid-session, prompting hosts to re-fetch `tools/list`. Emit it after every deploy that changes the surface; one message eliminates an entire class of stale-listing drift.

Finally, publish a **version manifest resource** (`mcp://server/manifest`) listing every tool, its current version, all supported versions, and planned removals. This is what SREs query during incidents, what CI diffs against, and what audit logs join to when a regulator asks which version of `refund_order` touched a transaction. Version metadata is the join key between agent behavior and accountability.

—

## 5. Automated Testing: Golden-File Testing to Validate Agent Compatibility

SemVer promises are only as good as the tests that enforce them. The highest-leverage technique for tool surfaces is **golden-file testing**: checked-in, immutable snapshots that every change must be validated against.

**Schema goldens.** Store the canonical `tools/list` response — every tool’s full schema, annotations, and description — as a JSON golden per server version. CI regenerates the live listing and diffs it against the golden, so any surface change becomes a *reviewable diff* and the pipeline forces you to classify it as patch, minor, or major. Tightening an enum without a major bump becomes impossible to ship silently. Keep per-version directories (`goldens/v1/`, `goldens/v2/`) so you can always reproduce what a historical agent saw.

**Compatibility suites.** For every still-supported major, keep a corpus of **canonical valid requests** captured from real production transcripts — actual `tools/call` payloads, not hand-written examples. The test is brutally simple: every golden request for version N must still validate and succeed against the current server. This is the regression net against accidental majors — the day a “minor cleanup” breaks a v1 payload, CI fails, not production. Pair it with a **negative corpus** of payloads that must be rejected, so accidentally loosening a constraint also fails loudly.

**Behavioral goldens.** Validation proves compatibility, not that models *behave* the same. Record agent sessions over a fixed set of canonical tasks, run them against a shadow server, and diff the tool-call transcript against a golden transcript. If a description rephrase makes the model switch tools, the diff shows the behavioral shift and a human decides whether it is intended.

Two rules keep golden testing sustainable. First, **goldens change deliberately, never silently** — updating one requires a separate, labeled commit, never an auto-regeneration folded into an unrelated PR. Second, **releases train forward and test backward**: every deploy runs the full matrix — new-version schema goldens plus compatibility suites for every version you still promise to support. At OnlineCloud this matrix runs in under two minutes and has caught more would-be production incidents than every other layer combined. The suite does not prevent change; it forces change to be named, classified, and intentional — which is the entire point of versioning.

—

## 6. Roadmap: The 6–10 Week Guide to Version-Controlled AI Systems

You do not need a platform team for this. Here is the six-to-ten-week path we run with teams that need version-controlled agent surfaces — sequenced so every week leaves the system more defensible, with no big-bang rewrites.

**Weeks 1–2 — Baseline and inventory.** Enumerate every tool in every server; snapshot live `tools/list` responses into `goldens/v1/`; start capturing real call transcripts (you need production payloads, not examples) and build the compatibility and negative corpora from them. Write the versioning policy on one page: the major/minor/patch definitions and the deprecation states above. Exit criterion: CI diffs live schemas against goldens.

**Weeks 3–4 — Version machinery.** Add version metadata to every tool’s annotations and description; stand up version-scoped schema URIs and the manifest resource; wire `tools/list_changed` into deploys. Connect the golden diff to release so a surface change without a version classification cannot merge. Exit criterion: every surface change produces a reviewed golden diff and a version bump, end to end.

**Weeks 5–6 — First real deprecation.** Pick one tool that genuinely needs to change. Ship the additive successor, dual-run the eval comparison, then canary 5–10% of new sessions. Instrument deprecated-call volume, repair-loop frequency, and outcome metrics. Exit criterion: a documented before/after showing the new surface is at least as good, with deprecation announced and telemetry live.

**Weeks 7–8 — Hardening (take two to four weeks if your surface is large or agents are third-party).** Build the drift dashboard: validation-error rate, deprecated-call volume, repair-loop rate, and per-version call mix, with alerts on the first two. Write the incident runbook so “agent error rate spiked after a tool deploy” has a checklist, not a fire drill.

**Weeks 9–10 — Removal and scale.** Execute the first fully-planned major: remove the sunset tool after its zero-call window, ship the major, confirm the compatibility suite passes for all remaining versions. Then institutionalize — fold version review into the eval cadence and publish the manifest where SREs and auditors can find it. Exit criterion: one full deprecation lifecycle completed, and the next team can do it from the runbook alone.

The metrics that matter: **validation-error rate per tool** (drift surfacing), **deprecated-call volume** (migration progress), **repair-loop frequency** (agent suffering), and **time-to-resolution for tool-call failures** (maturity). When the first two trend down and the last two stay flat, you have version-controlled AI systems — not as governance theater, but as the boring, reliable substrate that lets agents change without breaking.

—

## 7. Conclusion: Versioning Is How Agents Stay Honest

Protocol drift is not a bug you fix once. It is a force that acts on every deploy, every description edit, every tightened enum — and it acts hardest on the agents that run unattended, where nobody watches when a schema quietly moves. Semantic versioning for MCP tools converts that silent drift into a visible, reviewable, scheduled event. The tool surface becomes a first-class artifact: versioned, annotated, URI-addressable, golden-tested, and deprecated on a timetable instead of by accident.

At OnlineCloud, we build MCP-native systems for teams that need agents doing real work against real systems — Oracle, MS SQL, Postgres, Snowflake, CRMs — with versioned tool surfaces, eval suites, and observability built in from the first commit. If your agents are drifting, or you are about to change a schema that production traffic depends on, talk to our architects. We will help you turn your tool boundary into a contract that evolves on your schedule — not on the day your logs light up.

**Ready to put version control on your MCP tool surface?** Contact the OnlineCloud architects today for a free initial consultation — [contact@onlinecloud.dev](mailto:contact@onlinecloud.dev) — or learn more at [https://www.onlinecloud.dev/](https://www.onlinecloud.dev/). US-based senior engineers, response within 24 hours.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *