C.W.K.
Stream
Lesson 05 of 05 · published

The Compatibility Promise

~22 min · compatibility, rfc-2119, must-should-may, wire-format

Level 0Curious Reader
0 XP0/48 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Every serious protocol has, hidden in its plumbing, a compatibility promise. The promise says what kind of changes are allowed without breaking existing clients, and what kind of changes count as a breaking change that requires bumping the version. The shape of the promise is what lets ecosystems form around the protocol — it is what made HTTP, SQL, and MCP grow ecosystems in the first place.

The vocabulary comes from RFC 2119: MUST, SHOULD, and MAY. MUST is non-negotiable; if you do not do it, your implementation is non-conforming and will break. SHOULD is "you really ought to, and people will be unhappy if you don't, but it is not strictly fatal." MAY is "you can if you want, but no one is allowed to assume you did."

For protocols touching LLMs and agents, three patterns recur. First, fields tend to be added, not renamed: a new revision adds annotations next to content, but does not silently change what content means. Second, deprecation runs in long windows: a field is marked deprecated for at least one revision before it is removed, with the new field shipping in parallel so old clients still work. Third, capability negotiation moves the burden off versions: if both sides advertise what they support at handshake time, the protocol does not have to lock-step every detail to a global version number.

The compatibility promise is what you read when you ask "can I upgrade my server without breaking my clients?" If the answer is "look at the changelog and pray," you are not dealing with a real protocol; you are dealing with a moving target dressed up as one. Real protocols make the promise, write it down, and treat violations as bugs.

Code

RFC 2119 in the wild — a real MCP spec excerpt·markdown
A server **MUST** respond to `initialize` requests before processing any
other client requests. A client **SHOULD** advertise the protocol revision
it expects. A server **MAY** include extra capabilities not listed in the
client's request, but **MUST NOT** rely on the client using them.
Capability negotiation as version compatibility·json
// Client → Server (initialize)
{
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": { "sampling": {}, "roots": {} },
    "clientInfo": { "name": "claude-code", "version": "1.42.0" }
  }
}

// Server picks the highest revision *both* sides understand and only
// advertises capabilities the client also knows about. Lock-step
// upgrades become unnecessary.

External links

Exercise

Read the versioning section of any protocol you depend on (MCP, OpenAPI, HTTP, gRPC). Write down, in your own words, the rule that says when a change is breaking. Then look at one library you maintain and ask whether it follows that rule. Most do not.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.