MCP Auth, Explained: Every Method, Direct and Through a Proxy | Darek's Blog<br>Auth is the part of MCP everyone gets wrong first. I know because I build MCP gateways for a living, and the most common support question is some variant of “my client has a token, why won’t the server take it?” The answer is almost always the same: the token was minted for someone else.<br>This post is a field guide. (If MCP itself is new to you — what servers expose, how the protocol talks, how it evolved — start with the companion post, How MCP Works, and come back.) Part one covers how each auth method works when a client talks to an MCP server directly. Part two covers what changes when a proxy — an MCP gateway — sits in the middle, which is where most enterprise deployments end up and where most of the interesting failure modes live. Every method gets a sequence diagram showing who talks to whom and which token moves where.<br>Here is the canonical flow we will build up to, animated. Do not try to decode it yet — it is the destination, and every label on it gets explained below. It helps to meet the players first:<br>ActorWhat it doesMCP client The agent side — Claude, an IDE, any app calling MCP servers on your behalfMCP server Exposes tools and data; in OAuth terms a resource server — it consumes tokens, never creates themAuthorization server (AS) Mints (issues) tokens; may be your identity provider or something the server vendor runsGateway Optional proxy between clients and servers — the whole of Part 2And a key for reading every diagram in this post: a solid arrow is a request, a dashed arrow is the response, and the moving chip is the token — watch which server it travels to.<br>Animated flow: OAuth 2.1 authorization code with PKCE between MCP client, authorization server, and MCP serverMCP ClientAuthorization ServerMCP ServerMCP request (no token)401 + WWW-Authenticate (resource metadata URL)GET /.well-known/oauth-protected-resource (RFC 9728)/authorize + PKCE challenge (browser)authorization code/token: code + PKCE verifier + resourceaccess token (aud: MCP server)MCP request + Bearer token200 OKTOKENOAuth 2.1 authorization code flow with PKCE — the token is minted by the authorization server and only ever presented to the MCP server it was issued for. Discovery is abbreviated here; the sequence diagram in Part 1 shows all 12 steps.Why MCP auth is weird#<br>Three things make MCP auth harder than ordinary API auth.<br>The client acts on behalf of a human, through a model. When Claude calls your Jira MCP server, the thing holding the token is an agent, not the user. Every design decision downstream — consent screens, audience checks, scope granularity — flows from the question of how much that agent should be allowed to do with the user’s identity.<br>It is an N×M problem. Any MCP client is supposed to be able to talk to any MCP server without a human pre-registering the pair. Your OAuth setup at work assumes someone clicked around a developer console and copied a client ID. MCP explicitly does not: clients discover the authorization server at runtime and register (or identify themselves) on the fly.<br>The spec moved fast. Authorization landed in the 2025-03-26 revision, was overhauled in 2025-06-18 (the MCP server became a pure resource server), and extended again in 2025-11-25 (client ID metadata documents, discovery fallbacks, step-up authorization). A fourth revision is already locked as a release candidate for 2026-07-28, with a batch of authorization-hardening changes. Plenty of servers in the wild implement three different vintages of the spec. Knowing which vintage you are talking to is half the debugging.<br>One vocabulary note before the flows. Since 2025-06-18 the MCP server is an OAuth 2.1 resource server : it consumes tokens, it does not mint them. Minting is the job of an authorization server (AS), which may be your IdP (identity provider — the system that holds your organization’s logins and decides who you are: Okta, Entra ID, Google Workspace), a hosted service, or something the MCP server vendor runs. The client finds out which AS to talk to through discovery, not configuration. That separation is the single most load-bearing fact in this post.<br>And one note about the tokens themselves, because every diagram shows them. An access token here is usually a JWT — a small signed JSON blob carrying claims . Three claims do all the work in this post: sub (subject — who the token acts for), aud (audience — which server is allowed to accept it), and act (actor — who forwarded it on someone’s behalf). A scope is a named permission inside the token, like read:issues. And “audience binding” just means a token stamped aud: mcp.github.com is valid at that server and must be rejected everywhere else. Hold onto that one; it is the spine of everything below.<br>Part 1: Direct auth — client to MCP server#<br>OAuth 2.1 authorization code + PKCE#<br>This is the MCP auth method — what the spec means when it says...