feat: support "draft" as a first-class spec version target#255
feat: support "draft" as a first-class spec version target#255
Conversation
- Add LATEST_SPEC_VERSION and DATED_SPEC_VERSIONS constants so the next spec release is a one-line change in types.ts. - Accept "draft" as a valid protocolVersion in the initialize check and mock-server response. - --spec-version draft now selects latest-dated scenarios plus draft-tagged ones, so SEP authors can run the full suite against an SDK tracking the in-progress spec without retagging core scenarios. - Forward --spec-version to the client process via MCP_CONFORMANCE_SPEC_VERSION so SDK examples can pick the matching protocolVersion. Closes #253
commit: |
felixweinberger
left a comment
There was a problem hiding this comment.
LGTM, optional nit on consolidating a single constant instead of having 2 copies
| const VALID_VERSIONS = [ | ||
| '2025-06-18', | ||
| LATEST_SPEC_VERSION, | ||
| DRAFT_PROTOCOL_VERSION | ||
| ]; |
There was a problem hiding this comment.
could consider consolildating a VALID_VERSIONS constant in types.ts instead of having 2 copies here and in client.ts
| // could reuse the filter plumbing. It has no corresponding wire | ||
| // protocolVersion. Split it out of this type when moving to | ||
| // introducedIn/removedIn tagging. | ||
| if (version === 'extension') return undefined; |
There was a problem hiding this comment.
feels like something worth cleaning up, spec vs protocolVersion might get more confusing over time the longer we have both of these 🤔
There was a problem hiding this comment.
👍 we need a different way to refer to extensions, it doesn't super make sense to run "all extensions" as a selector. ties a bit into my comment on #114 about making it easier to selectively run scenarios via a config file
|
|
||
| // Mirrors LATEST_PROTOCOL_VERSION in the spec repo's schema/draft/schema.ts. | ||
| // Bump when that constant changes. | ||
| export const DRAFT_PROTOCOL_VERSION = 'DRAFT-2026-v1'; |
There was a problem hiding this comment.
I'm confused. What protocol version should we be using for conformance tests of draft features? This one or "draft"? If it is this one, then why the special casing of "draft" for the --spec-version parameter?
There was a problem hiding this comment.
fair question. I was thinking that draft would be a convenient alias, but looking at it again using the actual draft spec version will mean it's an easier string replace when we finalize the actual spec, and the alias just adds another indirection.
I've reworked it to be this one everywhere. so you can pass --spec-version DRAFT-2026-v1 and it will work. It will also work to pass --spec-version draft as a convenience, but tagging scenarios you need to use the explicit one now (not draft).
…OL_VERSIONS; split out 'extension' Addresses review feedback from @felixweinberger and @mikekistler: - SpecVersion is now always a wire protocolVersion string (DatedSpecVersion | typeof DRAFT_PROTOCOL_VERSION). The separate 'draft' tag literal is gone from the type system; 'draft' survives only as a CLI input alias in resolveSpecVersion. Removes the tag-vs-wire confusion and the specVersionToProtocolVersion mapping. - NEGOTIABLE_PROTOCOL_VERSIONS in types.ts is the single source for what the mock server accepts on initialize (was duplicated in checks/client.ts and scenarios/client/initialize.ts). - 'extension' moved out of SpecVersion into a separate ScenarioSpecTag type. --spec-version extension is no longer valid; extension scenarios remain reachable via --suite extensions. - Draft-tagged scenarios now use the DRAFT_PROTOCOL_VERSION constant so a draft revision bump is a one-line change in types.ts.
felixweinberger
left a comment
There was a problem hiding this comment.
Thanks for the changes!
mikekistler
left a comment
There was a problem hiding this comment.
Looks good! 👍
Just confirmed that I can layer my tests for SEP-2243 on top of this and successfully test the MCP C# reference implementation.
Closes #253.
Problem
SEP authors testing against the in-progress spec can't run the full suite: the
initializecheck rejects draftprotocolVersionstrings, and--spec-version draftonly selects the handful of explicitly draft-tagged scenarios (skippinginitializeand the rest of the core suite). Tagging core scenarios with'draft'is blocked by the spec-version isolation test.Raised by @mikekistler in #conformance-testing-wg while testing SEP-2243.
Design
SpecVersionis now always a wireprotocolVersionstring — the same value an SDK sends ininitializeand the value--spec-versionaccepts:DRAFT_PROTOCOL_VERSIONmirrorsLATEST_PROTOCOL_VERSIONin the spec repo'sschema/draft/schema.ts(which has cycledDRAFT-2025-v1→-v2→-v3→DRAFT-2026-v1). When the spec repo bumps it, this constant gets a matching bump and a conformance release — consumers updating to that release see the new value in the type, in--spec-versionvalidation, and in scenario tags simultaneously. Stale draft strings are rejected, which is a useful signal that the SDK and conformance package are out of sync.The CLI also accepts
--spec-version draftas a one-line alias that resolves toDRAFT_PROTOCOL_VERSION, purely for ergonomics; the literal'draft'does not appear in the type system.A
'2026-06-DRAFT'form was considered and rejected: the spec repo doesn't use it anywhere and the release date isn't known in advance.Changes
types.ts: addDATED_SPEC_VERSIONS,LATEST_SPEC_VERSION,DRAFT_PROTOCOL_VERSION, andNEGOTIABLE_PROTOCOL_VERSIONS.SpecVersion = DatedSpecVersion | typeof DRAFT_PROTOCOL_VERSION.'extension'moved to a separateScenarioSpecTagtype — it's a scenario category, not a point on the version timeline.checks/client.ts/scenarios/client/initialize.ts: both use the sharedNEGOTIABLE_PROTOCOL_VERSIONSconstant; the mock server accepts and echoesDRAFT_PROTOCOL_VERSION.scenarios/index.ts: newmatchesSpecVersion()helper. Selecting the draft version resolves to latest-dated ∪ draft-tagged, so SEP authors can run the full suite without retagging core scenarios.resolveSpecVersionadds the'draft'CLI alias.--spec-version extensionis no longer valid; extension scenarios are reachable via--suite extensions.runner/client.ts/index.ts: forward the resolved--spec-versionvalue to the client process asMCP_CONFORMANCE_PROTOCOL_VERSION. Example clients can use it directly as theirprotocolVersion; SDKs that hard-code their version can ignore it.offline-access,resource-mismatch,sep-2164-resource-not-found): now reference theDRAFT_PROTOCOL_VERSIONconstant, so a draft revision bump is a one-line change intypes.ts.tier-check: derives tier-scoring versions fromDATED_SPEC_VERSIONS; draft and extension remain non-scoring. A tier-check run at the draft version scores against latest ∪ draft (i.e., "would this SDK pass tier N if draft shipped today").DRAFT_PROTOCOL_VERSIONacceptance, negative tests for stale'DRAFT-2025-v1'and bare'draft'on the wire;'draft'CLI alias resolution; extension scenarios excluded from all--spec-versionselections.--spec-versionand the new env var.Testing
Typecheck and lint clean.
Follow-ups (not in this PR)
specVersions: [...]lists withintroducedIn/ optionalremovedIn. The superset model in this PR can't express a SEP that tightens or removes an existing requirement (e.g., SEP-986 narrowed valid tool-name format) — there's no subtraction arm.matchesSpecVersion()is the seam where range logic slots in.'2025-11-25'literals in server scenarios toLATEST_SPEC_VERSION.