Originally published on DevToolHub.
MCP server authentication stopped being optional a month ago. The Model Context Protocol's largest spec revision since launch finalized on schedule on July 28, 2026 and is now the current protocol version. It turns every remote MCP server into a formal OAuth 2.1 resource server. No more bring-your-own-token. No more skipping auth because your server only talks to internal agents.
That's not the only breaking change. Sessions are gone. The initialize handshake is gone. The Tasks feature moved out of core into an extension. Here's exactly what changed, what you need to fix, and what still has a 12-month grace period.
What Actually Changed in the MCP 2026-07-28 Spec
The release candidate locked on May 21, 2026, giving SDK maintainers a 10-week validation window, and the final spec published on July 28 as planned. Per the official spec blog, this is the biggest rewrite since MCP launched — the protocol moves from bidirectional and stateful to request/response and stateless — and it touches four areas at once:
-
Transport — protocol-level sessions and the
Mcp-Session-Idheader are gone from Streamable HTTP -
Lifecycle — the
initialize/initializedhandshake is gone entirely - Tasks — the async task feature graduated from experimental core into an official extension, with a different API
- Authorization — MCP servers are now OAuth 2.1 resource servers, full stop
None of this was a soft rollout. Servers on the 2026-07-28 revision won't necessarily work with older clients, and the reverse is also true. If you maintain a public or internal MCP server and haven't audited against the final spec yet, you're already a month behind the clients and SDKs that have.
MCP Server Authentication Becomes Mandatory OAuth 2.1
This is the change with the most real search volume behind it. That makes sense — it touches every server that accepts remote connections. Per the final authorization spec and WorkOS's breakdown, the spec now requires things your server didn't need before:
Protected Resource Metadata (RFC 9728). Your server must expose a .well-known/oauth-protected-resource endpoint. Or it can include resource_metadata in its WWW-Authenticate header instead. Either way, clients can discover your authorization server automatically:
WWW-Authenticate: Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource"
Resource Indicators (RFC 8707). Clients must now name the specific MCP server a token is meant for when they request it. This closes a real gap. Without a resource indicator, a token issued for one MCP server could get replayed against a different one. With it, the authorization server binds the token to a single audience.
Issuer verification (RFC 9207). Authorization servers should include the iss parameter, and clients must validate it whenever it's present — the final spec softened this from the release candidate's mandatory framing, and says a future revision is expected to make inclusion a hard requirement. Either way, if you migrate your MCP server to a different auth provider, existing clients need to re-register. There's no silent handoff.
On top of that, the spec deprecates Dynamic Client Registration (RFC 7591) in favor of Client ID Metadata Documents (CIMD). DCR keeps working for now, but CIMD is the preferred registration path going forward. Clients still registering through DCR must also declare an OpenID Connect application_type — something the old spec never asked for.
This lands three months after security researchers at OX Security disclosed a design flaw in the MCP SDK's STDIO transport that let arbitrary commands execute across more than 7,000 public servers. That RCE was a different transport and a different bug. This spec update doesn't patch it. What it does fix is a gap the STDIO issue never touched: a standard way for a server to confirm a token belongs to it, not to a callback meant for someone else. If you already run runtime security tooling like Falco on Kubernetes to catch anomalous process execution, treat this as the same category of gap, closed at a different layer.
Sessions and the Initialize Handshake Are Gone
If your server tracks state using Mcp-Session-Id, that header no longer exists on Streamable HTTP. Client info that used to travel through the initialize/initialized exchange now rides in _meta on every request instead. Look for fields like io.modelcontextprotocol/protocolVersion, /clientInfo, and /clientCapabilities.
Practically, this means:
- Replace any session-based state with a server-issued handle passed back as a regular tool argument
- Implement the new
server/discoverRPC endpoint for capability negotiation - Expect an
UnsupportedProtocolVersionErrorinstead of a failed handshake when a client's version doesn't match
This kills sticky-session routing requirements entirely. A stateless MCP server behind a plain load balancer becomes a normal deployment instead of a special case. You no longer need session affinity just to keep a client talking to the same backend instance.
Migrating the Tasks Extension
If your server uses Tasks for long-running operations, the spec replaces the experimental 2025-11-25 API. It removes tasks/list outright. You now drive the lifecycle with tasks/get, tasks/update, and tasks/cancel. Servers can hand back a task handle without a client opting in first.
The same revision introduces a core-protocol pattern (separate from the tasks extension) for anything that used to hold a connection open waiting on the client. Instead of a server-initiated callback, a call returns an InputRequiredResult carrying inputRequests and an opaque requestState. The client gathers what it needs and re-issues the original call with inputResponses and the echoed requestState. All the state lives in the payload instead of an open connection. That means any server instance can process the retry — the same stateless principle driving the session removal. One addition that landed between the release candidate and the final spec supports this: every result now carries a required resultType field, "complete" or "input_required", so clients can tell a finished call from one waiting on input without guessing from the payload's shape.
[IMAGE: articles/images/2026-07-25-mcp-server-authentication-spec-update-diagram.png | alt: "MCP client to authorization server to MCP server auth flow with resource indicators"]
What's Deprecated, Not Removed Yet
Three features get a 12-month minimum deprecation window instead of an immediate cut, under the new lifecycle policy (SEP-2596):
- Roots — replaced by tool parameters, resource URIs, or server-side config
- Sampling — replaced by direct integration with your LLM provider's API
-
Logging — replaced by
stderron stdio transports or OpenTelemetry for anything else
You don't have to touch these immediately. But treat the window as a countdown, not a reprieve. The spec's new governance model requires a conformance suite before any feature reaches "Final" status, and these three didn't make the cut.
One smaller change worth knowing: the error code for a missing resource changes too. It moves from the MCP-specific -32002 to the standard JSON-RPC -32602 (Invalid Params). If you have client code branching on the old code, that branch stops firing.
Checklist: Locking Down MCP Server Authentication Against the Final Spec
For most self-hosted or internal MCP servers, authorization hardening matters more than the transport changes. Work through this order:
- Confirm your server exposes
.well-known/oauth-protected-resourceor setsresource_metadataonWWW-Authenticate - Check that your authorization server issues tokens scoped with a resource indicator naming your specific MCP server
- Verify
issvalidation is happening on the client side, not just token signature checks - Audit any code that reads
Mcp-Session-Idor relies on theinitializehandshake — both need replacing before older clients start failing silently - If you use Tasks, migrate off
tasks/listand the2025-11-25polling model now, while you can still test against both old and new clients
If you're newer to the protocol itself, the site's Model Context Protocol guide covers the architecture this revision rewrites. And if you're building these servers as part of a broader Claude integration, Anthropic's own developer training track covers MCP alongside Agent Skills.
Frequently Asked Questions
Q: Do I have to rewrite my MCP server now that the spec is final?
A: If your server only talks to clients you control, you have flexibility to upgrade both sides together. If you run a public or third-party-facing MCP server, prioritize the OAuth 2.1 changes now — SDKs built against the final spec are already shipping, and older clients and new servers won't necessarily interoperate.
Q: Does the new spec fix the MCP STDIO RCE from April 2026?
A: No. That vulnerability was in the STDIO transport's command execution model. Anthropic characterized the underlying behavior as expected, not as a bug to patch. The July 28 update hardens OAuth-based authorization for remote transports — a related but separate concern.
Q: What happens if my client still sends Mcp-Session-Id to a 2026-07-28 server?
A: A server built against the new spec won't recognize it. Protocol-level sessions no longer exist on Streamable HTTP. You need to move that state into request payloads or _meta fields instead.
Q: Is Dynamic Client Registration completely removed?
A: No — the spec deprecates it in favor of Client ID Metadata Documents, but DCR support continues for backward compatibility. New integrations should register with CIMD.
Q: Did Roots, Sampling, and Logging stop working when the spec finalized?
A: No. The spec deprecates them with a minimum 12-month window before removal. Existing implementations keep functioning while you migrate to the replacements.
Quick Summary:
- The MCP 2026-07-28 spec, final and current since July 28, makes OAuth 2.1 mandatory for remote servers: Protected Resource Metadata (RFC 9728), Resource Indicators (RFC 8707), and RFC 9207 issuer verification (client-side validation required whenever
issis present) - Sessions (
Mcp-Session-Id) and theinitialize/initializedhandshake are removed from Streamable HTTP — client info now travels in_metaon every request - Tasks graduates from experimental core to an official extension;
tasks/listis removed in favor oftasks/getandtasks/update - Roots, Sampling, and Logging are deprecated with a 12-month minimum window, not removed outright
- Dynamic Client Registration is deprecated in favor of Client ID Metadata Documents, though DCR still works
Audit your MCP server's auth flow against the checklist above this week. The spec has been final for a month, SDKs targeting it are already in the wild, and every week of delay widens the gap between your server and the clients calling it.
Top comments (0)