Expand description
What protocol revision a session says it is, read from the session itself.
A registry judges one revision. Point the validator at a recording of a
different one and every clause the two revisions disagree about becomes a
finding — confidently, with a verbatim spec quote, against an
implementation that violated nothing. A conforming 2026-07-28 stateless
session judged against 2025-11-25 fails LIFE-001 for not opening with
initialize, which 2026-07-28 removes (SEP-2575), and BASE-003 for
reusing request ids, which 2026-07-28 permits.
The trace is not silent about this. Every revision states its own version on the wire, and a recording carries it:
- the
initializeresult’sprotocolVersion— the negotiated revision, and the authority where there is one; - the
initializerequest’sprotocolVersion— what the client proposed, which is evidence even when no server answered; - a request’s
_metaio.modelcontextprotocol/protocolVersion— how2026-07-28carries it, per request, having no handshake; - the
MCP-Protocol-VersionHTTP header.
So the validator can tell the difference between this session broke the
rules and these are not the rules this session was playing by, and
Report::revision_mismatch says which.
The rule is deliberately quiet, in three ways.
A mismatch is reported only when the session declared at least one revision and none of them is the registry’s. A session that proposes one revision and negotiates another has touched both, so judging it against either is a question worth asking and draws no note.
A session that declares nothing at all — a message-level capture of a handshake that never happened — gets no note either: there is nothing to disagree with, and inventing a warning from an absence is the vacuous reasoning this validator refuses everywhere else.
And a version is only a declaration if the session actually ran under it.
Two filters enforce that. A request the other end answered with a JSON-RPC
error states nothing — it named a version and was told no — so a probe
asking for 1900-01-01 and drawing -32022, or a legacy initialize
drawing -32601 from a server that no longer has one, are sessions of no
revision at all rather than of the one they asked for; the clauses that
judge those refusals (TRAN-074, VERS-008) are the ones with something to
say. And only revisions this build ships a registry for count, because the
note exists to send a reader to a registry that exists: re-run with
--revision X is worthless advice when there is no X to run against.
Functions§
- declared_
revisions - Every protocol revision the session states about itself, ascending.
- mismatch
- The revisions a session declared, when it declared some and the registry’s
is not among them.
Nonemeans there is nothing to warn about. - mismatch_
any mismatchfor a run judging several revisions at once: the note fires only when none of them is one the session declared.