# The 2026-07-28 MCP Spec: A Server Readiness Checklist

> Source: <https://dev.to/gustavo_gated/the-2026-07-28-mcp-spec-a-server-readiness-checklist-14nf>
> Published: 2026-06-19 15:15:56+00:00

The next Model Context Protocol specification, `2026-07-28`

, is the largest revision since the protocol launched. The release candidate locked on May 21, 2026, and the final spec publishes on July 28. It contains breaking changes to transport, authorization, and how tool schemas are handled.

A server that is correct against `2025-11-25`

today is not broken. Nothing here is a present-tense vulnerability. But several of these changes are security properties, not just compatibility ones — request routing integrity, cross-user cache scope, and schema-driven fetch behavior all move under this revision. This checklist walks the changes a server operator needs to handle before July 28, and calls out the security implication wherever there is one.

Everything below describes the release candidate. Treat specifics as subject to change until the July 28 final, and validate against the official spec before shipping.

This is the headline change. MCP becomes stateless at the protocol layer, and most of the migration work lives here.

The `initialize`

/`initialized`

handshake is removed (SEP-2575). Protocol version, client info, and client capabilities no longer get exchanged once at connection time — they travel in `_meta`

on every request. The same SEP adds `server/discover`

as the new discovery anchor: servers must implement it, and clients fetch server capabilities from it when they need them up front. Once the handshake is gone, a server that can't answer `server/discover`

can't be negotiated with.

The `Mcp-Session-Id`

header and the protocol-level session it carried are also removed (SEP-2567). Any request can now land on any server instance. The sticky routing and shared session stores that horizontal deployments relied on are no longer required at the protocol layer.

If a server needs state across calls, mint an explicit handle from a tool — a `basket_id`

, a `browser_id`

— and have the model pass it back as an ordinary argument. The state becomes a visible tool input rather than something hidden in transport metadata.

The Streamable HTTP transport now requires `Mcp-Method`

and `Mcp-Name`

headers (SEP-2243), so load balancers, gateways, and rate-limiters can route on the operation without reading the body. Requests also carry `MCP-Protocol-Version`

.

Servers must reject requests where the headers and the body disagree. This is a request-integrity check, not just a convenience: a mismatch between the routing header and the actual method in the body is exactly the kind of ambiguity that smuggling and confused-routing attacks exploit. Enforce the agreement; don't route on the header and execute the body.

`_meta`

`server/discover`

for capability negotiation`Mcp-Session-Id`

and stop requiring sticky sessions`Mcp-Method`

and `Mcp-Name`

, and reject header/body mismatchesA stateless protocol still needs a way for a server to ask the client for something mid-call. Two changes rebuild that flow without a persistent connection.

Server-initiated requests may now only be issued while the server is actively processing a client request (SEP-2260). Earlier versions recommended this; it is now required.

The security value is concrete. A user is never prompted out of nowhere, and every elicitation traces back to an action they or their agent started. An unsolicited server-initiated prompt is now a spec violation, which makes a whole class of social-engineering-via-prompt behavior detectable rather than ambiguous.

Instead of holding a Server-Sent Events stream open, the server returns an `InputRequiredResult`

carrying an opaque `requestState`

(SEP-2322). The client gathers answers and re-issues the original call with `inputResponses`

and the echoed `requestState`

, and any instance can pick the retry up.

Treat `requestState`

as untrusted on the way back in. It leaves the server, sits client-side, and returns. Integrity-protect it — sign or encrypt it — so a modified `requestState`

can't replay or escalate a half-finished operation. Don't deserialize it into trusted server state without verification.

`InputRequiredResult`

rather than holding an SSE stream open`requestState`

and verify it on retryThree smaller changes make the resulting traffic easier to operate — and two of them carry data across boundaries that deserve attention.

List and resource-read results now carry `ttlMs`

and `cacheScope`

, modeled on HTTP `Cache-Control`

(SEP-2549). Clients learn exactly how long a `tools/list`

response stays fresh and whether it is safe to share across users.

`cacheScope`

is where this becomes a security decision. If a server exposes a per-user or per-tenant tool surface but marks the result shareable, a client may serve one user's tool list to another. Set `cacheScope`

to match the actual sensitivity of what the response reveals, and default to the narrower scope when unsure.

W3C Trace Context propagation in `_meta`

is now documented, fixing the `traceparent`

, `tracestate`

, and `baggage`

key names (SEP-414). A trace can follow a call through the client SDK, the server, and whatever the server calls downstream, and show up as one span tree in an OpenTelemetry-compatible backend.

`baggage`

is the field to watch. It propagates arbitrary key-value data downstream by design, which is useful and also a path for sensitive values to cross into systems that shouldn't see them. Decide deliberately what goes into `baggage`

, and strip or scrub it at trust boundaries rather than forwarding everything.

`ttlMs`

on list and resource-read results`cacheScope`

to match per-user or per-tenant sensitivity`baggage`

carries across boundariesSix SEPs align the authorization spec more closely with how OAuth 2.0 and OpenID Connect are deployed. These matter most to operators who run their own authorization server or broker auth in front of a server.

Authorization servers should supply the `iss`

parameter on authorization responses per RFC 9207 (SEP-2468). Clients are now expected to validate it, and in a future version they will reject responses that omit it. This is a low-cost mitigation for a mix-up attack that is more likely in MCP's single-client, many-server pattern — so begin supplying `iss`

now if you don't already.

The remaining changes are smaller but worth handling together: support the OpenID Connect `application_type`

during Dynamic Client Registration so desktop and CLI clients aren't defaulted to `"web"`

and rejected (SEP-837); bind registered credentials to the issuing authorization server's `issuer`

and re-register when a resource migrates (SEP-2352); document how to request refresh tokens from OIDC-style servers (SEP-2207); and follow the clarified scope-accumulation and `.well-known`

discovery rules (SEP-2350, SEP-2351).

`iss`

on authorization responses`application_type`

in Dynamic Client RegistrationTool `inputSchema`

and `outputSchema`

are lifted to full JSON Schema 2020-12 (SEP-2106). Input schemas keep the `type: "object"`

root but now allow composition (`oneOf`

, `anyOf`

, `allOf`

), conditionals, and references (`$ref`

, `$defs`

). Output schemas are unrestricted, and `structuredContent`

can be any JSON value rather than only an object.

Two constraints in this change are security constraints, and the spec states them as requirements. Implementations must not auto-dereference external `$ref`

URIs — a schema that points `$ref`

at an external URL is an SSRF and unbounded-fetch vector if you follow it. And implementations should bound schema depth and validation time, because a deeply nested or recursive schema is a denial-of-service input. If your server validates against client-supplied or third-party schemas, enforce both.

Separately, the error code for a missing resource changes from the MCP-custom `-32002`

to the JSON-RPC standard `-32602`

Invalid Params (SEP-2164). If any code matches on the literal `-32002`

, update it.

`$ref`

URIs`-32602`

for missing resources, and update any matching on `-32002`

Roots, Sampling, and Logging are deprecated under the new feature lifecycle policy (SEP-2577). These are annotation-only deprecations: they keep working in this release and in every spec version published within a year, and removal requires a separate SEP. There is no forced cutover on July 28 — but plan the replacements now.

The documented replacements are tool parameters, resource URIs, or server configuration in place of Roots; direct integration with an LLM provider API in place of Sampling; and `stderr`

(for stdio transports) or OpenTelemetry in place of Logging.

Extensions are now first-class (SEP-2133). They are identified by reverse-DNS IDs, negotiated through an `extensions`

map on client and server capabilities, and versioned independently of the specification.

Two official extensions ship with this release. Tasks graduates from an experimental core feature to an extension with a redesigned, stateless lifecycle: a server answers `tools/call`

with a task handle, and the client drives it with `tasks/get`

, `tasks/update`

, and `tasks/cancel`

. `tasks/list`

is removed (SEP-2663) because it can't be scoped safely without sessions. Anyone who built against the `2025-11-25`

experimental Tasks API needs to migrate.

MCP Apps (SEP-1865) lets servers ship interactive HTML interfaces that hosts render in a sandboxed iframe. Tools declare their UI templates ahead of time so hosts can prefetch, cache, and security-review them before anything runs, and every UI-initiated action goes through the same audit and consent path as a direct tool call.

`extensions`

capability mapThe ten-week window between the May 21 lock and the July 28 final exists for exactly this: validate the changes against real workloads before they become normative. Start a migration branch if you operate a remote MCP server, run your own authorization, or build against the experimental Tasks API. The transport rework is the largest piece; the auth and schema constraints are the ones with security teeth.

Most of these are checkable from outside the server — the routing-header enforcement, the cache scope on list responses, the `$ref`

handling, the `iss`

parameter. Gated inspects deployed MCP servers against these and the rest of [its check library](https://dev.to/docs/catalog), mapping each to the [conformance](https://dev.to/docs/catalog/conformance) and [security](https://dev.to/docs/catalog/security) families with a reproduction for every finding — including private and internal servers [reached from inside your network](https://dev.to/security). If a security team wants the posture of a server in writing before July 28, that's the kind of thing it produces.

— Gustavo, Gated
