---
title: "MCP 2026-07-28 conformance"
description: "Which parts of the MCP 2026-07-28 stateless core edi-mcp implements — discovery, cache hints, result types, schemas, _meta, MRTR — and which deprecated features it deliberately leaves out."
type: Reference
tags:
  - mcp
  - specification
  - conformance
generated:
  by: "claude/opus-5.5"
  at: "2026-10-19T00:00:00Z"
sources:
  - id: mcp-spec
    resource: "https://modelcontextprotocol.io/specification/2026-07-28"
    title: "Model Context Protocol specification, 2026-07-28"
    author: "team:modelcontextprotocol"
  - id: python-sdk
    resource: "https://github.com/modelcontextprotocol/python-sdk"
    title: "MCP Python SDK"
    author: "team:modelcontextprotocol"
status: stable
stale_after: "2027-07-28T00:00:00Z"
---

# MCP 2026-07-28 conformance

edi-mcp targets the **2026-07-28** revision of the Model Context Protocol, the
*stateless core*[^mcp-spec], on the Python `mcp` SDK 2.x (2.3.0 today) through its
low-level `Server` API[^python-sdk]. `server.py` is the only module coupled to the
SDK; the tool registry is SDK-agnostic.

## What the server does

| Requirement | edi-mcp |
| --- | --- |
| No `initialize` handshake, no sessions | Streamable HTTP runs with `stateless_http=True`: no `Mcp-Session-Id`, any instance answers any request. stdio also accepts the legacy handshake. |
| `server/discover` | Answered by the SDK with the supported versions, capabilities (tools, resources) and the server instructions. |
| Per-request `_meta` envelope | `io.modelcontextprotocol/clientCapabilities` decides whether a tool may ask a follow-up question (MRTR elicitation). |
| Cacheable results | `tools/list` 5 min, `resources/list` and `resources/templates/list` 1 h, `server/discover` 5 min, `resources/read` 24 h for static guides and 1 h for derived content; `cacheScope` is always `public` because nothing depends on the caller. |
| `resultType` | `complete` on every result; `input_required` only for an MRTR follow-up. |
| `structuredContent` and `outputSchema` | Every tool declares an `outputSchema`; results carry `structuredContent` and the same JSON as text. Failures set `isError` with `structuredContent.error` (see [error codes](../tools/utilities.md#error-codes)). |
| JSON Schema 2020-12 | Every `inputSchema` and `outputSchema` declares the dialect. Pydantic's generated `title` keys are dropped from both, and descriptions from output schemas (the [tool reference](../tools/reference.md) keeps them). |
| Tool annotations | All four hints (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) and a title on every tool. |
| Tool `_meta` | `io.edi-mcp/surface`, `io.edi-mcp/requiresKey`, `io.edi-mcp/endpoints`, and `io.edi-mcp/stdioOnly` on stdio-only tools. |
| Result `_meta` | The SDK's `io.modelcontextprotocol/serverInfo` plus `io.edi-mcp/upstream`: upstream request count, cache hits, the backend used and how the call authenticated (never the credential). |
| Deterministic `tools/list` | Sorted by name and fixed per deployment (transport and whether downloads are enabled); its serialized size has a conformance bound. |
| Header routing | `Mcp-Method` / `Mcp-Name` must match the body; protocol-version mismatches are `-32020` and unsupported versions `-32022` (see [Transports](transports.md)). |

## MRTR and requestState

The server supports multi round-trip requests: a tool can return an
`InputRequiredResult` with an elicitation form, and the client resumes by calling the
tool again with `inputResponses` and the `requestState` continuation. The
continuation is compact base64url JSON of at most 16 KiB, never contains a key, token
or authorization decision, and is rejected when malformed, issued for another tool, or
older than an hour. Elicitation is used only when the client declares support. No
released tool asks a question yet; the mechanism is covered by the conformance tests.

## Deliberately left out

edi-mcp uses none of the features the 2026-07-28 revision deprecates or that a
stateless server cannot honour: no legacy SSE transport, no sessions, no
`roots/list`, no `sampling/createMessage` and no `logging/setLevel`. A CI job greps
the source for them and fails if any appear.

## Measured size

With the eight tools registered today, `tools/list` is about 37 KB of compact JSON on
both transports. The conformance bound is 60,000 bytes and will be re-measured once
every planned tool has landed.

## Conformance tests

`tests/test_spec_conformance_2026_07_28.py` and `tests/transport/` run as their own
CI job: schema dialect and validity, annotations and `_meta`, sorted and stable
`tools/list` within its size bound, aliases accepted and unknown arguments rejected,
cache hints on lists and reads, `server/discover`, stateless requests in both eras,
result `_meta`, header routing, protocol-version errors, host allow-lists, resources
over HTTP, an MRTR round trip with a tampered continuation, a stateless session
manager, and a real stdio subprocess speaking both protocol eras.

[^mcp-spec]: Model Context Protocol specification, 2026-07-28. <https://modelcontextprotocol.io/specification/2026-07-28>
[^python-sdk]: MCP Python SDK. <https://github.com/modelcontextprotocol/python-sdk>
