Skip to content

test(server): hold every MCP answer to McpJson on the raw body - #99

Merged
youndie merged 1 commit into
mainfrom
test/mcp-wire-format
Oct 2, 2026
Merged

youndie merged 1 commit into
mainfrom
test/mcp-wire-format

Conversation

@youndie

@youndie youndie commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Why

katcher's ContentNegotiation (common()) pretty-prints and does not write defaults. On MCP SDK 0.15.0 the one thing the stateless transport sends through the application's ContentNegotiation is the answer to a POST in JSON mode, and under katcher's Json that answer loses protocolVersion from initialize and the whole result from ping. kore-mcp encodes the answer with McpJson before ContentNegotiation sees it — and the only test here watching that looked at protocolVersion alone.

What changes

  • McpWireFormatTest (commonTest): ten exchanges through the assembled module — initialize latest and older, ping, tools/list, tools/call without arguments, a call ending in a tool error, an unknown tool, an unknown method, a batch of two, an unparseable body. Each raw body must be exactly what McpJson writes for the message inside it.
  • Positive control in the same class: katcher's common(), katcher's five tools, the same requests, the transport installed by the bare SDK. It must come out different; the KDoc says what to do if it ever stops.
  • McpEndpointTest: the protocolVersion test is removed — the new test catches the missing field (see below); the negotiated value itself is kore-mcp's and is tested there.
  • README, MCP section: why the SDK's ContentNegotiation is already installed… warning at startup is expected and what holds it. CLAUDE.md: one sentence pointing at the test.

Verified

Locally, JVM and the macOS native target: :server:jvmTest and :server:nativeTest --tests 'io.github.youndie.katcher.mcp.*' green, ktlintCheck clean. Linux native is CI's build.

  • Mutation: installMcp switched from installKoreMcp to the bare SDK's mcpStatelessStreamableHttp → the new test fails with 9 of 10 exchanges different (all but the unparseable body, which the SDK writes itself); the removed protocolVersion test failed on the same mutation.
  • One-off probes (not committed), bare SDK with katcher's tools: under katcher's Json 9 of 10 differ; under McpJson none; under katcher's Json without prettyPrint three still do — initialize latest, ping and the batch carrying it, none of which McpJson can read back. So the comparison catches the dropped protocolVersion on its own, not only whitespace.
  • The warning is in the stand's startup log, as the README now says.

katcher's own Json pretty-prints and omits defaults: an MCP answer written
with it loses protocolVersion from initialize and the whole result from
ping. kore-mcp encodes the answers with McpJson before ContentNegotiation
sees them, and nothing here watched more than protocolVersion.

McpWireFormatTest drives ten exchanges through the assembled module and
compares each raw body with what McpJson writes for it. Its control sends
the same requests to the bare SDK under katcher's Json and must come out
different, so a green run cannot mean the comparison catches nothing.

The protocolVersion test in McpEndpointTest is covered and goes; the
negotiated value itself is kore-mcp's and tested there. The README says
why the SDK's startup warning is expected.
@youndie
youndie merged commit a533c5c into main Oct 2, 2026
3 checks passed
@youndie
youndie deleted the test/mcp-wire-format branch October 2, 2026 08:49
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.

1 participant