Skip to content

feat: protocol version enum and per-version schema conformance for 2026-07-28 (T1, T2) - #238

Merged
kubinio123 merged 7 commits into
softwaremill:2026-07-28-protocol-supportfrom
sideeffffect:feat/protocol-2026-07-28
Sep 15, 2026
Merged

kubinio123 merged 7 commits into
softwaremill:2026-07-28-protocol-supportfrom
sideeffffect:feat/protocol-2026-07-28

Conversation

@sideeffffect

@sideeffffect sideeffffect commented Sep 5, 2026

Copy link
Copy Markdown

Targets the 2026-07-28-protocol-support branch. Groundwork for dual-era (legacy + modern) support, scoped to two tickets. The server-side handling and its datatypes are in the stacked follow-up #260.

Closes #239.
Closes #240.

Covers

  • #239 (T1 — version enum + ordering): V2026_07_28 added and made Latest; LatestLegacy = V2025_11_25; cases are ordered by release so code can branch with version >= V2026_07_28.
  • #240 (T2 — schema + per-version schema tests): schema/2026-07-28/schema.json bundled; SchemaConformance extracted as a shared trait parameterised by the schema resource path, with one concrete spec per version — Schema20251125ConformanceSpec and Schema20260728ConformanceSpec. The 2026-07-28 spec is seeded with datatypes shared across revisions and grows with the revision-specific defs in feat: dual-era datatypes and server handling for 2026-07-28 (T4, T8) #260.

Client default

Advancing Latest to 2026-07-28 would otherwise make every default client advertise 2026-07-28 and fail against legacy servers, so the client transports default to LatestLegacy. For the same reason the single legacy-initialize handler test sends an explicit 2025-11-25 — the handler itself is untouched.

Follow-up

Local gate green (scalafmt, compile, core/server/client unit suites). WIP.

🤖 Generated with Claude Code

sideeffffect and others added 3 commits September 5, 2026 10:34
Make chimp a dual-era server: alongside the legacy initialize handshake
(2025-11-25 and earlier), it now speaks the modern 2026-07-28 revision, where
each request carries its protocol version in _meta.

- ProtocolVersion.V2026_07_28 + a `supported` list; `Latest` still points at the
  latest legacy revision used by the initialize handshake.
- server/discover returns a DiscoverResult (supported versions, capabilities,
  serverInfo in _meta), so a modern/dual-era client no longer gets an error from
  a chimp server (addresses the softwaremill#235 review).
- A request declaring an unsupported protocol version in
  _meta[io.modelcontextprotocol/protocolVersion] is rejected with
  UnsupportedProtocolVersion (-32022) listing the supported versions.
- New protocol types (DiscoverResult, CacheScope, ProtocolMeta) are validated
  against the official 2026-07-28 JSON schema (Schema2026ConformanceSpec),
  following the existing schema-conformance convention; the 2025-11-25 types are
  left untouched.

WIP: modern client mode, HTTP transport-level validation (headers / 400
semantics), resultType on all results, and packaging extensions (e.g. Tasks) as
separate modules are follow-ups. Groundwork for softwaremill#163.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep the domain type while the wire stays integer milliseconds, via a
file-private millis codec. supportedVersions stays List[String] on purpose: the
field must carry version strings the receiver may not recognise (a newer peer),
which a closed ProtocolVersion enum would reject on decode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Parses the raw supportedVersions strings into Either[String, ProtocolVersion]:
Right for a known version, Left with the raw string for an unrecognised one, so
callers get the typed view without the wire field rejecting newer versions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sideeffffect sideeffffect changed the title WIP: feat: dual-era support for the 2026-07-28 protocol version feat: dual-era support for the 2026-07-28 protocol version Sep 7, 2026
@sideeffffect
sideeffffect marked this pull request as ready for review September 7, 2026 20:08
@sideeffffect

Copy link
Copy Markdown
Author

Hello @kubinio123 , what do this about adding support for dual-era like this?
I think this would unlock changes from the other two PRs (big thanks that you've already had a look at them too).

Assert that a classic initialize (and any request whose _meta omits the modern
protocol version) is served via the legacy handshake, not rejected with
UnsupportedProtocolVersion (-32022) — the official-SDK-client interop path that
surfaces first in practice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kubinio123

Copy link
Copy Markdown
Collaborator

@sideeffffect thanks for sending this in. I took some time to plan out the work for implementing the 2026-07-28 support in general and created several issues with with a common label https://github.com/softwaremill/chimp/issues?q=state%3Aopen%20label%3A%222026-07-28%20version%20support%22.

I would like to avoid any issues we might might have with stable implementation we have on main that's why I'd like to implement the 2026-07-28 support against a separate branch, 2026-07-28-protocol-support.

I created those issues so that it's easier for us to keep track of the progress and for contributors like you to participate.

For this PR, I think it pretty much implements #239 and #240, would you consider taking a look at those two?

@kubinio123

kubinio123 commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

@deemwario I know some SDK did this the hard way, but there are couple of them (like Rust) that support both versions, let's see how that plays out for chimp.

@sideeffffect
sideeffffect changed the base branch from master to 2026-07-28-protocol-support September 10, 2026 15:51
…softwaremill#240)

T1: make V2026_07_28 the Latest, add LatestLegacy (V2025_11_25) which the
initialize negotiation answers, and add release ordering so code can branch with
`version >= V2026_07_28`. The client and legacy handshake keep proposing the
latest legacy version.

T2: extract SchemaConformance as a shared trait parameterised by the schema
resource path, with one concrete spec per version (SchemaConformanceSpec for
2025-11-25, Schema2026ConformanceSpec for 2026-07-28).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sideeffffect sideeffffect changed the title feat: dual-era support for the 2026-07-28 protocol version WIP: feat: dual-era support for the 2026-07-28 protocol version Sep 10, 2026
The Pekko, Ox and ZIO streaming HTTP transports defaulted `protocolVersion`
to `ProtocolVersion.Latest` (2026-07-28), so their GET SSE stream carried
`MCP-Protocol-Version: 2026-07-28`. A legacy (2025-11-25-era) server rejects
that with HTTP 400 ("Unsupported protocol version"), which broke every HTTP
integration test in these modules.

Align them with the base `ClientHttpTransport`, which already defaults to
`ProtocolVersion.LatestLegacy`, and update the Pekko/ZIO HTTP integration
specs that explicitly passed `Latest` to the test server.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sideeffffect sideeffffect changed the title WIP: feat: dual-era support for the 2026-07-28 protocol version feat: dual-era support for the 2026-07-28 protocol version Sep 10, 2026
@sideeffffect

Copy link
Copy Markdown
Author

re-targeted to the new branch. Please let me know if you'd like to see further changes @kubinio123 🙏

@kubinio123 kubinio123 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really appreciate if we stick to the scope of T1 and T2, so we could skip the changes to handler and documentation at this point.

Comment thread core/src/main/scala/chimp/protocol/ProtocolVersion.scala Outdated
Comment thread core/src/main/scala/chimp/protocol/ProtocolVersion.scala Outdated
Comment thread core/src/main/scala/chimp/protocol/ProtocolVersion.scala Outdated
Comment thread core/src/test/scala/chimp/protocol/Schema2026ConformanceSpec.scala Outdated
Address softwaremill#238 review: keep this PR to
the protocol-version enum (T1, softwaremill#239) and the per-version schema conformance
(T2, softwaremill#240). Move the request metadata / result type / cache hints / error codes
/ discover datatypes (T4, softwaremill#242) and the server-side handling with its docs
(T8, softwaremill#246) into a stacked PR.

- ProtocolVersion: drop redundant comments, revert `negotiate` to its base form
  (negotiation reworks land in softwaremill#246), keep enum + Latest + LatestLegacy + ordering.
- Rename conformance specs to Schema20251125ConformanceSpec /
  Schema20260728ConformanceSpec; seed the 2026-07-28 spec with shared datatypes
  so the per-version harness runs and grows with the revision-specific defs.
- Remove Versioning.scala, DiscoverResultSpec, the -32022 error code, the
  server/discover handling and capabilities docs (they return in the stacked PR).
- Keep clients defaulting to LatestLegacy so advancing Latest to 2026-07-28 does
  not regress them against legacy servers; the legacy initialize test now sends
  an explicit protocol version for the same reason.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sideeffffect

sideeffffect commented Sep 14, 2026

Copy link
Copy Markdown
Author

Thanks — narrowed this PR to T1 + T2. Changes:

One thing I kept (happy to move it if you'd rather): the client transports now default to LatestLegacy. Advancing Latest to 2026-07-28 in T1 otherwise makes every default client advertise 2026-07-28 and fail against legacy servers. For the same reason the single legacy-initialize handler test now sends an explicit 2025-11-25, so the handler itself is untouched.

@sideeffffect sideeffffect changed the title feat: dual-era support for the 2026-07-28 protocol version feat: protocol version enum and per-version schema conformance for 2026-07-28 (T1, T2) Sep 14, 2026
@sideeffffect

Copy link
Copy Markdown
Author

Thanks for the review. Should be clean now. Please let me know if you still like to see more changes @kubinio123

@kubinio123

Copy link
Copy Markdown
Collaborator

Thanks @sideeffffect, merging this.

@kubinio123
kubinio123 merged commit 36e1f03 into softwaremill:2026-07-28-protocol-support Sep 15, 2026
4 checks passed
sideeffffect added a commit to sideeffffect/chimp that referenced this pull request Sep 16, 2026
Stacked on top of softwaremill#238 (T1 + T2).
Carries the parts moved out of that PR at review request:

T4 (softwaremill#242) - request metadata, result type, cache hints, error codes, discover types:
- Versioning.scala: ProtocolMeta, CacheScope, DiscoverResult (+ getSupportedVersions)
- JSONRPCErrorCodes.UnsupportedProtocolVersion (-32022)
- ProtocolVersion.supported / isModern
- DiscoverResultSpec + DiscoverResult / UnsupportedProtocolVersionError schema conformance

T8 (softwaremill#246) - serve 2026-07-28 requests next to legacy requests:
- McpHandler: server/discover, per-request modern-version validation, dual-era dispatch
- McpHandlerSpec: discover, -32022, modern and legacy-path coverage
- docs/server/capabilities.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sideeffffect
sideeffffect deleted the feat/protocol-2026-07-28 branch September 17, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants