Last month, researchers at Token Security dropped a vulnerability report that should have made every MCP server operator lose sleep. The Azure MCP server — Microsoft's own, the official one — had no authentication on its HTTP/SSE transport. None. An attacker with network access could instruct the LLM to invoke Azure CLI commands, download a malicious script into ~/.bashrc via blob storage, and steal Entra ID credentials. Full tenant takeover from a tool call. Microsoft's fix was to rip out the SSE transport entirely and bolt on Entra ID's On-Behalf-Of flow after the fact.

The uncomfortable part isn't that it happened. It's that the architecture made it inevitable.

The Token Passthrough Anti-Pattern

Here's how most MCP deployments worked through 2025 and into early 2026: your agent gets a token from an authorization server. It calls MCP Server A. Then it calls MCP Server B. Same token. Maybe Server B is a third-party integration someone on your team installed from a registry last Tuesday. Maybe it's something that showed up in your server discovery results and looked legit.

Server B now holds a token that was never meant for it. If that token has broad scopes — and early MCP tokens almost always did, because nobody was thinking about per-server scoping — Server B can do anything Server A could. Read your files. Query your database. Call downstream APIs on your behalf.

This is token mis-redemption. It's not a novel attack; OAuth people have been warning about it for years. But MCP made it trivially easy because the protocol had no mechanism to say "this token is only valid at this server." Tokens floated between servers like house keys passed around at a party where you don't know half the guests.

The new spec finally calls this out explicitly: token passthrough is forbidden. The language is unambiguous — MCP servers must not accept tokens that weren't explicitly issued for them. But a prohibition without enforcement is just a suggestion, which is where RFC 8707 comes in.

What Resource Indicators Actually Do

RFC 8707 is a short spec with a simple idea. When your client requests a token, it includes a resource parameter that declares the intended recipient:

POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOj3gBR...
&resource=https://mcp-server-a.example.com

The authorization server stamps the token with an aud (audience) claim matching that resource. When MCP Server A receives the token, it checks: does the audience match my own URL? If yes, proceed. If not, reject. When MCP Server B receives that same token, the audience doesn't match, and the request fails.

That's it. One parameter, one claim, one validation check. The kind of thing that should have been there from day one.

Three Changes That Actually Matter

The 2026-03-15 MCP specification revision does more than just recommend resource indicators. It restructures the entire auth model.

MCP servers are now OAuth 2.1 resource servers. This isn't a semantic distinction. It means every MCP server must advertise its authorization server location through protected resource metadata. Clients discover where to authenticate by querying the server itself, not by hardcoding auth endpoints or trusting some external configuration. The server tells you who vouches for it.

Resource indicators are mandatory, not optional. The previous spec mentioned them as a recommendation. The March revision makes them a compliance requirement. Clients that don't include the resource parameter in both authorization requests and token requests are non-conformant. Servers that don't validate the aud claim are non-conformant. There's no "we'll get to it later" escape hatch.

Incremental scope consent replaces blanket permissions. Instead of requesting every permission upfront — read files, execute code, access databases, all in one token — clients now request the minimum scope needed for each operation. Your agent needs to read a file? It gets a token scoped to file reads on that specific server. It needs to write later? New consent flow, new token. This is least-privilege applied at the protocol level, not just as a best-practice recommendation in some security guide nobody reads.

What This Means If You Run MCP Servers

If you operate an MCP server in production, here's the short list:

Validate the aud claim on every incoming token against your server's canonical URL. If it doesn't match, return 401. No exceptions, no fallback to "well, the token is valid in general." A valid token for the wrong server is an invalid token for your server.

Implement token introspection if you're using opaque tokens. You need a way to verify audience and scope claims without relying solely on JWT parsing — especially in environments where tokens pass through proxies or gateways that might strip or rewrite headers.

Support dynamic client registration. The spec now allows MCP clients to self-register rather than requiring manual provisioning. This reduces the friction that pushed teams toward the "just use one token for everything" shortcut in the first place.

Kill any token passthrough in your middleware. If your agent orchestration layer is forwarding tokens between tool calls without re-scoping them, you are running the exact pattern that MCPwned exploited. Audit your request chain. Every hop should get its own appropriately-scoped token.

The Fourteen Percent

Clutch Security's latest survey puts adoption of resource indicators at 86% among enterprise MCP servers. That sounds good until you think about what the remaining 14% represents. These are production servers handling real data, running real tools, connected to real infrastructure — and they're accepting tokens without checking who the token was actually issued for.

Fourteen percent of enterprise MCP servers are running the same configuration class that let an unauthenticated attacker achieve full Azure tenant takeover. The fix is one parameter in the token request and one validation check on the server. It has been in the spec since March.

If you're in that 14%, you don't have a roadmap problem. You have a Tuesday morning problem.