Validates this implementation against the official https://github.com/modelcontextprotocol/conformance[Model Context Protocol conformance suite], both the stateless 2026-07-28 protocol and the legacy 2025-11-25 one.

The conformance module boots a runnable server - http://localhost:8080/mcp - exposing a representative set of features the suite drives by name:

  • tools: plain text, erroring, content blocks (image, audio, embedded resource, several at once), one reporting notifications/progress, one exercising the implicit JSON-Schema 2020-12 input conversion (json_schema_2020_12_tool), one receiving its message through an Mcp-Param-* header (test_x_mcp_header), and the MRTR ones returning input_required (elicitation, sampling, roots, tampered and multi-round requestState);

  • a prompt (test_simple_prompt, test_prompt_with_arguments, ...), resources and resource templates, argument completion, and a long-running tool (long/running) returning an io.modelcontextprotocol/tasks handle the suite polls with tasks/get/tasks/update/tasks/cancel.

Beyond the spec methods it also exposes SEP-2575 diagnostic tools the suite drives by name:

Tool What it checks

test_missing_capability

requires the sampling client capability, a client which did not declare it gets the -32021 MissingRequiredClientCapabilityError with data.requiredCapabilities.

test_streaming_elicitation

echoes whether the client declared the streaming_elicitation capability.

test_logging_tool

a plain tool which sends no logging records.

test_trigger_tool_change

pushes notifications/tools/list_changed to the client.

test_trigger_prompt_change

pushes notifications/prompts/list_changed to the client.

On the stateless protocol the stream subscriptions/listen acknowledges its commitment with a notifications/subscriptions/acknowledged notification, and server/discover carries the server identity both top-level and in _meta.io.modelcontextprotocol/serverInfo.

Run the server

mvn package -pl conformance exec:exec

The conformance server is the one the suite is validated against: it exposes every tool the checks drive by name. The demo module (mvn package -pl demo exec:exec) is a smaller, human-friendly example of the same server stack - same route, both eras - but without the suite's diagnostic tools, so it is not a target for the suite.

The server listens on http://localhost:8080/mcp , serving both eras on the same route: a client sending the stateless per-request _meta.io.modelcontextprotocol/protocolVersion - served statelessly - and a client doing an initialize handshake.

Run the suite

Start the server in one terminal, then in another:

npx @modelcontextprotocol/conformance server \
  --url http://localhost:8080/mcp \
  --spec-version 2026-07-28 \
  --suite all \
  --verbose
NOTE

as of 2026-08-09 the latest MCP release (the stateless 2026-07-28 protocol) requires the alpha of the conformance runner, not the stable @modelcontextprotocol/conformance package - run npx @modelcontextprotocol/conformance@0.2.0-alpha.9 server --url http://localhost:8080/mcp --spec-version 2026-07-28 --suite all --verbose to validate the stateless protocol. Pin that version to keep the run reproducible; it is the one this project is validated against. Newer alphas exist (0.2.0-alpha.11 at the time of writing) - bump the pin only after a clean run, and keep it explicit.

The conformance runner is a stateless client, so it probes the server with server/discover and drives every method with the negotiated version. --spec-version selects the protocol revision the runner talks:

--spec-version What is validated

2026-07-28

the stateless protocol: required _meta, MRTR, tasks, extensions negotiation.

2025-11-25

the legacy handshake and session-backed protocol.

TIP

pass --suite all to run every suite (lifecycle, tools, prompts, resources, sampling, elicitation, roots, completion, logging, subscriptions) and --verbose to see each check. Use --suite tools for a single area.

What to look at on a failure

Most of the new feature surface is driven here, so a failure usually points at a specific area:

  • _meta/version: a failing server/discover, tools/* or prompts/* check on the stateless path means the 2026-07-28 envelope diverges - required namespaced _meta (see Transport ) - while a failing legacy initialize/session check means the 2025-11-25 handshake path diverges (see Configuration ).

  • dns-rebinding-protection: the server must accept a legacy initialize even when the runner adds an Mcp-Method header to a legacy request - the explicit MCP-Protocol-Version header (a legacy version) must win over the Mcp-Method heuristic, and Host/Origin loopback validation must answer 403 for a non-loopback host (see Transport ).

  • tools-call-with-progress: the suite sends the progress token as the bare _meta.progressToken key (the MCP way), not the io.modelcontextprotocol/progressToken one - a server that only reads the namespaced key echoes progressToken: "null" and the check reports No progress notifications received.

  • tools-call-with-logging, tools-call-sampling, tools-call-elicitation, elicitation-sep1034-defaults, elicitation-sep1330-enums: these drive tools by name (test_tool_with_logging, test_sampling, test_elicitation, ...). A -32602 Unknown tool '...' means the conformance server does not expose them; sampling/elicitation must also work server to client over the session SSE stream.

  • json-schema-2020-12: the input schemas must survive tools/list with the 2020-12 vocabulary ($defs, $ref, enum, const, if/then/else, additionalProperties) intact - see DescriptorService.

  • the conformance module pins fusion.mcp.requestStateSecret so the MRTR requestState integrity checks run as they would in production.