Diese Notiz ist noch nicht übersetzt — die englische Version wird angezeigt.
MCP Server Authorization
The common reading is "MCP servers need OAuth", followed by bolting OAuth onto every server someone writes. The specification says something considerably more specific, and the specific version is easier to implement.
Everything below is from the Model Context Protocol specification, revision 2026-07-28. Quotes are verbatim, and the RFC 2119 keywords are the spec's own — the difference between MUST and SHOULD is doing real work here.
Authorization is optional
Straight from the spec:
"Authorization is OPTIONAL for MCP implementations."
A server behind a reverse proxy that already authenticates, or one bound to localhost and reachable only by processes on that machine, is entitled to implement none of this. That's not a loophole; it's the design.
The question to ask isn't "do I need auth?" but "what's my transport, and what's my trust boundary?"
Over stdio, don't
"Implementations using an STDIO transport SHOULD NOT follow this specification, and instead retrieve credentials from the environment."
Worth reading twice, because it's stronger than permission to skip the work — it's a recommendation against doing it.
The logic is that over stdio the trust boundary is the process boundary. The client launched the server as a subprocess. It already controls the server's environment, its lifetime, and its file descriptors. Layering a token exchange on top of that relationship doesn't add a boundary; it adds ceremony across a boundary that was never crossed. Credentials come from the environment, because whoever set the environment is already the trusted party.
Over HTTP, you're an OAuth 2.1 resource server
This is where the obligations become concrete. An HTTP-transport MCP server is a resource server, and it owes four things.
Publish protected resource metadata.
"MCP servers MUST implement OAuth 2.0 Protected Resource Metadata (RFC 9728)"
In practice: serve /.well-known/oauth-protected-resource, and include a resource_metadata pointer in the WWW-Authenticate header on a 401. That's how a client discovers which authorization server to go to without being told out of band.
Validate the audience.
"MCP servers MUST validate that access tokens were issued specifically for them as the intended audience"
A token that is merely valid is not sufficient. It has to have been minted for this server. A server that accepts any well-signed token from a familiar issuer becomes a confused deputy for every other resource that issuer serves.
Never pass the token through.
"The MCP server MUST NOT pass through the token it received from the MCP client"
Forwarding the caller's token to a downstream API is prohibited, not discouraged. If the server needs to call something on the user's behalf, it needs its own credential — which is the entire subject of Acting on a Human's Behalf.
Note how cleanly these last two fit together: if every resource server validates audience, and no server forwards tokens, then a token's audience always tells you truthfully where it was meant to go. Each rule is what makes the other one worth enforcing.
Include scope in the challenge. This one is a SHOULD, not a MUST — the WWW-Authenticate header should name the scope required, so a client can request the right thing on its second attempt rather than guessing.
Transport obligations
Independent of authorization, and easy to overlook because they aren't about tokens:
"Servers MUST validate the
Originheader on all incoming connections"
An invalid Origin gets a 403. This is what stops a web page the user happens to have open from driving a local MCP server through the browser — an attack that needs no credentials at all, because the browser helpfully supplies them.
Additionally: servers running locally SHOULD bind only to localhost rather than all interfaces, and there is to be exactly one endpoint path.
The actual shape of the decision
Reordered as a thing you can act on:
- stdio transport → no authorization layer. Credentials from the environment. The spec recommends against anything more.
- HTTP transport → OAuth 2.1 resource server: RFC 9728 metadata, strict audience validation, no passthrough,
scopein the challenge,Originvalidation, localhost binding when local.
Most of the confusion in this area comes from reading advice written for the second case and applying it to the first.
Where this actually stands
Budding. Sourced directly from one specification revision and quoted rather than paraphrased, so it's as reliable as that document — and it will age exactly as fast as the spec does. The revision is stamped at the top for that reason.
What this note doesn't cover: how any particular SDK implements the above, whether the client side holds up its end, or the dynamic client registration story. Those were not checked and aren't asserted.