feat: dual-era datatypes and server handling for 2026-07-28 (T4, T8) - #260
sideeffffect wants to merge 2 commits into
Conversation
|
The T1, T2 PR is merged now. I took a first look and I am missing updates to server conformance tests, will you look into that as well? Agent does a good job on them as long as he has access to it's sources, described in |
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>
60aef3f to
b574dd5
Compare
Wrap 2026-07-28 results with the modern envelope (resultType: complete, serverInfo in _meta; cacheable results also carry ttlMs and cacheScope) so the server passes the modern tools/list, tools/call, resources/*, prompts/*, completion and caching conformance scenarios. Wire the server conformance harness for 2026-07-28: a per-spec-version baseline (conformance-baseline-<version>.yml) selected by the sbt task, a conformance-baseline-2026-07-28.yml capturing the scenarios that still need later tickets (tasks/MRTR and input-required → T5 softwaremill#243; full stateless lifecycle and modern HTTP header validation), and a CI step running it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Done — rebased onto the merged T1/T2 base (the earlier conflict is gone) and added the server conformance updates. Server conformance for 2026-07-28:
Verified locally: 2026-07-28 server conformance passes (all remaining failures are the baselined ones); 2025-11-25 stays green (63 passed, 4 expected) — no regression. |
kubinio123
left a comment
There was a problem hiding this comment.
Some additional findings of the agents, I would look into 1.
1. -32022 goes out as HTTP 200, spec says it must be 400
server/McpHandler.scala:80 builds the error through jsonResponse(...), and
McpResponse.statusCode (lines 17-19) returns Ok for every JsonResponse.
The schema is explicit: "For HTTP, the response status code MUST be 400 Bad Request."
The damage is worse than a wrong status. The spec defines dual-era client fallback as
"inspect the body of a 400 Bad Request before falling back", so a 200 makes the
rejection invisible to a conforming client. The new test only reads the body, so it
passes either way.
Give JsonResponse a status field, or add an error case, and return BadRequest here.
2. An unknown initialize version is answered with 2026-07-28
ProtocolVersion.scala:18. negotiate still falls back to Latest. The PR fixed the
absent version default to LatestLegacy (McpHandler.scala:170) but left the
unknown version path pointing at the modern revision, which has no initialize at
all. A legacy client that sends 2025-03-26 is told to speak a handshake-less protocol
and has nowhere to go.
requested.flatMap(ProtocolVersion.from).filterNot(_.isModern).getOrElse(LatestLegacy)Smaller things
- Seven new // comments (Versioning.scala:8, McpHandler.scala:77,101,146,179,
build.sbt:241, McpHandlerSpec.scala:136). AGENTS.md rule 6 says none. Before this
PR the whole of core and server main had one. Scaladoc is fine, these aren't. - ProtocolVersion.supported (line 15) hand-lists the enum cases while from and
negotiate use values. Add a revision and server/discover starts lying.
values.toList.reverse fixes it. - resultType: String = "complete" (Versioning.scala:53) is a string sitting right
next to a properly modelled cacheScope enum. The schema defines a closed set. - modernResult (lines 150-152) hand-writes "complete", 0L and "private", which
bypasses the CacheScope encoder this same PR adds. Two sources of truth for one wire
format. - wrap(cacheable = true) reads as a contradiction, since it emits ttlMs: 0 and
private. - val ProtocolVersion: String inside ProtocolMeta shadows the ProtocolVersion enum
in the same package. - Hot path: _meta gets decoded into a full Map on every request to read one key.
Implementation(...).asJson.deepDropNullValues is rebuilt per modern response and is
redundant anyway, since line 25 already drops nulls globally. serverCapabilities and
the whole discover result are constant but recomputed. - getSupportedVersions scaladoc reads "Kept lazy of the wire so an unknown version
never fails decoding", which isn't grammatical. The name is Java-ish too. - build.sbt:242 only matches the space-separated --requirements v form, so
--requirements=v falls back to the default baseline without saying so.
server-conformance/README.md still documents conformance-baseline.yml alone, while
the new baseline file points readers back at that README.
| run: sbt -v compileDocs | ||
| - name: Unit tests | ||
| run: sbt -v test | ||
| - name: Client conformance tests |
There was a problem hiding this comment.
You can also rename the older steps so they include the version
| @@ -0,0 +1,60 @@ | |||
| package chimp.protocol | |||
There was a problem hiding this comment.
Comments in this file are redundant
Follow-up to #238 (T1 + T2, now merged). Targets
2026-07-28-protocol-support.Closes #242.
Closes #246.
T4 — #242: request metadata, result type, cache hints, error codes, discover types
Versioning.scala:ProtocolMeta,CacheScope,DiscoverResult(+getSupportedVersions)JSONRPCErrorCodes.UnsupportedProtocolVersion(-32022)ProtocolVersion.supported/isModernDiscoverResultSpec+DiscoverResult/UnsupportedProtocolVersionErrorschema conformanceT8 — #246: serve 2026-07-28 requests next to legacy requests
McpHandler:server/discover, per-request modern-version validation (-32022), dual-era dispatchresultType: completeandserverInfoin_meta; cacheable results (tools/list,resources/*,prompts/list, ...) also carryttlMs/cacheScopeMcpHandlerSpec: discover,-32022, modern and legacy-path coveragedocs/server/capabilities.mdServer conformance for 2026-07-28
serverConformance/conformance server --requirements 2026-07-28, with a per-spec-version baseline (conformance-baseline-<version>.yml) selected by the sbt taskconformance-baseline-2026-07-28.ymllists the scenarios that still need later tickets: tasks/MRTR + input-required (T5, #243), full stateless lifecycle, and modern HTTP-header validation🤖 Generated with Claude Code