---
title: "MCP 2026-07-28 conformance"
description: "How neon-mcp implements the MCP 2026-07-28 stateless core: discovery, cache hints, result metadata, MRTR, header routing and the conformance tests."
type: Reference
tags:
  - mcp
  - protocol
  - conformance
generated:
  by: "claude/opus-5"
  at: "2026-09-10T00:00:00Z"
sources:
  - id: mcp-changelog
    resource: "https://blog.modelcontextprotocol.io/posts/2026-07-28/"
    title: "MCP 2026-07-28 release notes"
    author: "team:modelcontextprotocol"
  - 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

neon-mcp targets the **2026-07-28** revision of the Model Context Protocol, the
*stateless core*[^mcp-changelog], on the Python `mcp` SDK 2.x (2.2.0 at release) through
its low-level `Server` API[^python-sdk]. The SDK serves both eras on stdio, so clients
on earlier revisions (2024-11-05 … 2025-11-25) still work.

## What the server does

| Requirement | neon-mcp |
| --- | --- |
| No `initialize` handshake, no sessions | Streamable HTTP runs with `stateless_http=True`: no `Mcp-Session-Id`, any instance answers any request |
| `server/discover` | answered by the SDK with supported versions, capabilities (tools, resources, prompts) and the server instructions |
| Per-request `_meta` envelope | `io.modelcontextprotocol/clientCapabilities` decides whether MRTR elicitation may be used |
| Cacheable list results | `tools/list` 5 min, `resources/list` and `resources/templates/list` 1 h, `prompts/list` 24 h, `server/discover` 5 min, `resources/read` 1 h (24 h for static guides); `cacheScope` is always `public` because nothing depends on the caller |
| `resultType` | `complete` on every result; `input_required` only from `neon_get_sample` |
| Result `_meta` | the SDK's `io.modelcontextprotocol/serverInfo` plus `io.neon-mcp/upstream` (NEON requests, cache hits, rate-limit headroom, identity) |
| JSON Schema 2020-12 | every `inputSchema` and `outputSchema` declares the dialect; outputs match `structuredContent` |
| Tool annotations and `_meta` | all four hints on every tool; `io.neon-mcp/surface`, `requiresToken`, `endpoints`, `stdioOnly` |
| Header routing | `Mcp-Method` / `Mcp-Name` must match the body (400, `-32020`); an unsupported version is `-32022` |
| Deprecated features | none: no roots, sampling, `logging/setLevel`, SSE transport or sessions (a CI job greps for them) |

## MRTR and requestState

Only `neon_get_sample` asks the user a question, and only when the client declares
elicitation support: a sample tag that belongs to several classes produces an
`InputRequiredResult` with a form listing the candidates. The continuation
(`requestState`) is base64url JSON of at most 16 KiB holding the question and
candidates; it never contains a token, a path or an authorization decision, it expires
after an hour, and the answer is re-validated against a fresh lookup on resume. It is
unsigned by design: tampering can only change the caller's own question.

## Measured sizes

With all 20 tools (stdio), `tools/list` is **107,734 bytes** of compact JSON: input
schemas 25,347 B, output schemas 67,661 B, descriptions 6,581 characters. HTTP lists 19
tools in 102,342 B. Pydantic's generated `title` keys are dropped from both schemas and
descriptions from output schemas (the [tool reference](../tools/reference.md) keeps
them). The conformance bound is 135,000 B (measured × 1.25).

## SDK behaviour worth knowing

* A request whose `MCP-Protocol-Version` header names an **older** revision
  (e.g. `2025-11-25`) is served in the legacy era even if its body carries a 2026-07-28
  envelope; a modern header with a different envelope version is rejected with `-32020`.
* `resources/read` and `prompts/get` require `Mcp-Name` (the URI or prompt name).

## Conformance tests

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

[^mcp-changelog]: MCP 2026-07-28 release notes. <https://blog.modelcontextprotocol.io/posts/2026-07-28/>
[^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>
