Protocol types for 2026-07-28: superset monolith, committed per-version packages, and wire-method maps#2849
Draft
maxisbey wants to merge 1 commit into
Draft
Protocol types for 2026-07-28: superset monolith, committed per-version packages, and wire-method maps#2849maxisbey wants to merge 1 commit into
maxisbey wants to merge 1 commit into
Conversation
9 tasks
…on packages, and wire-method maps One public type set (mcp.types) covering every protocol revision through 2026-07-28, two committed per-version model packages that act as the schema-exact validating layer, and plain (method, version) maps with two-step parse functions replacing the previous serializer boundary. Version gating is data: key absence is the gate. Outbound serialization is the model dump, with the new 2026-07-28 result fields as ordinary serialized defaults.
6e1bfac to
9a38b0d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This revision replaces the previous candidate body. The candidate pairing with #2850 is over: the declarative fact-row registry is dropped, and the wire boundary module this PR previously carried (
mcp.types.wire) is gone with it. What remains is deliberately simpler — types, data, and two-step parse functions, with no protocol behavior hiding in a serializer.What this is
mcp.typesstays the single public type set (the "monolith"): one class per protocol construct, a superset of every released revision plus the upcoming 2026-07-28 revision. Existing names and shapes are unchanged (pinned bytests/types/test_public_surface.py); new constructs are additive.mcp.types.v2025_11_25andmcp.types.v2026_07_28, each a complete model package readable beside its pinned schema. The released schemas (2024-11-05 through 2025-11-25) only ever added fields, so thev2025_11_25package serves all of them; the 2026-07-28 package carries the upcoming revision's stricter shapes. These packages are now the validating layer: schema-exact validation happens through the package serving the negotiated version, not through a separate boundary module.mcp.types.methods: plain maps keyed(method, version)and valued with the per-version model types — what servers receive, what clients receive, and the response type for the request you sent — plus version-free monolith maps and six two-step parse functions (validate against the surface row, then construct the monolith type user code sees). Absence of a key is the version gate. The maps are plain data: importingmcp.typesdoes not import them, and no validators are built at import time.resultType: "complete"on the nine result classes that carry it, theinput_requiredtag onInputRequiredResult, andttlMs: 0/cacheScope: "private"on the six cacheable results.EmptyResultstill dumps{}. Outbound emission is the model's own dump everywhere — no version parameter, no field injection, no stripping.Motivation and Context
Every session negotiates its own protocol version, and 2026-07-28 changes wire shapes materially: a required
resultTypeon results, required reserved_metaentries on client requests,server/discoverand embedded input requests replacing the server→client request channel, and resource subscriptions. One public type set can carry all of that only if version knowledge lives somewhere. In this revision it lives in data — the committed packages and the(method, version)maps — instead of in serializer code.What changed since the previous revision of this PR
mcp.types.wireis deleted.serialize_for/parse_as, the version-keyed injections, and the strict-check-on-emit machinery are gone. The fields the old boundary injected on 2026-07-28 sessions are now plain serialized defaults on the monolith models, present at every version (deployed peers ignore unknown result fields).tests/spec_oracles/, the parity suite, and the generator script are gone. The committed surface packages are themselves the validating layer, exercised directly by the parse functions and the new map tests rather than compared against generated mirrors.mcp.types.methods, one entry per(method, version)pair, with key absence as the gate — no compression, no dispatch logic in the data.resultTypevalue no longer fails validation; it flows through as data on the open-tagged field._spec_names.pyis gone; the deliberate SDK↔schema naming divergences are documented where they occur.Behavior notes
docs/migration.md.SUPPORTED_PROTOCOL_VERSIONSis unchanged — 2026-07-28 is modeled, not yet negotiable.resultTypevalues parse. Previously the wire boundary rejected them; now they are preserved on the open-tagged field and the payload validates normally.How Has This Been Tested?
strict-no-coverclean; pyright strict and ruff clean.tests/types/test_methods.pypins the complete method matrix per version (set equality against the known-version list, value pins for both response maps including union arm order, cross-map invariants, immutability), replays fixtures for all 208 per-version map rows through the six parse functions, and pins the gate and rejection shapes (unknown method/version, missing reserved_metaentries, requiredresultTypeat 2026-07-28,paramsomission, lazy adapter caching).tests/types/test_wire_frames.pypins the emitted bytes of representative JSON-RPC frames (request, notification, results including the new serialized defaults and theEmptyResultcarve-out, error) with full-object inline snapshots.EmptyResult, leaving) dumps, 3 are error-classification changes (tag rejection removed; reserved-_metarequiredness now enforced by the 2026-07-28 package's schema), and 3 are fixtures that pin the deleted outbound injection/stripping behavior itself and need re-authoring for the new contract.Conformance status
The conformance suite has scenarios matching the 2026-07-28 behaviors modeled here — caching fields on cacheable results (SEP-2549), input-required results (SEP-2322), request metadata — and this repo's conformance workflow runs the suite on CI. Those scenarios are gated to spec version 2026-07-28, which this PR does not make negotiable, so they exercise these types end-to-end only once the session-wiring follow-up lands.
Breaking Changes
Serialized result payloads gain the default fields described above; documented with migration guidance in
docs/migration.md. Everything else is additive: existingmcp.typesnames and shapes are unchanged.Types of changes
Checklist
Reading order
src/mcp/types/_types.py— the monolith: one class per construct, every revision's fields, the new serialized defaults.src/mcp/types/v2025_11_25/__init__.py— the released-revisions package, read beside the pinned 2025-11-25 schema (src/mcp/types/_wire_base.pyholds its base classes).src/mcp/types/v2026_07_28/__init__.py— the upcoming-revision package; skim for the 2026-07-28 delta.src/mcp/types/methods.py— the maps and the six parse functions; the module docstring spells out the integration contract.tests/types/test_methods.py— the method matrix, value pins, invariants, and parse/rejection behavior.docs/migration.md— the serialized-defaults change and how to adapt exact-payload assertions.