Classic OAuth assumes you know your clients in advance: you register an app in a
dashboard, get a client_id and client_secret, and ship them
inside your application. MCP breaks both assumptions. The client is someone's Claude
Desktop or Cursor install — you will never pre-register it — and it runs on a desktop
where a baked-in secret is not a secret. OAuth 2.1 plus three extension RFCs is how the
MCP spec resolves this.
Every OAuth setup splits into two jobs. The Authorization Server (AS){' '} authenticates users and issues tokens. The Resource Server (RS) — your MCP server — accepts requests only when they carry a valid token. They can be the same deployment or separate services; the protocol only cares that the RS can verify what the AS signs, typically via a published JWKS (the AS's public keys).
The authorization-code flow hands the client a one-time code via a browser redirect, and the client exchanges that code for a token. The classic attack is stealing the code in-flight and exchanging it yourself. PKCE closes this: the client invents a random secret (the verifier), sends only its hash (the challenge) when the flow starts, and must present the original verifier at exchange time. A thief who intercepted the code never saw the verifier, so the code is useless to them.
In OAuth 2.1, PKCE is mandatory for every client — the old exemption for "confidential" server-side clients is gone. If your AS treats PKCE as optional, it is not OAuth 2.1.
When a user adds your MCP server to Claude Desktop, the client calls your AS's
registration endpoint at runtime — "here is my name and redirect URI" — and receives a
fresh client_id on the spot. No dashboard, no support ticket, no shared
credentials between users. DCR is what makes "paste a URL, connect,
done" possible: without it, every user of every MCP client would need you to manually
provision app credentials.
A user might connect their client to ten different MCP servers. Without{' '}
Resource Indicators, a token minted for server A could be replayed
against server B — any server you talk to could impersonate you elsewhere. RFC 8707 has
the client name the exact server (the resource) when requesting the token,
and the AS bakes that audience into the token. Your MCP server then rejects any token
whose audience is not itself. One token, one server, no cross-server replay.
WWW-Authenticate header pointing at the
protected-resource metadata — this is how the client discovers your AS.
resource.
plain PKCE instead of requiring S256.None of this is exotic, but it is a genuine authorization-server implementation — days of work plus ongoing spec-tracking, and mistakes are security bugs rather than build failures. If you want to own it, the{' '} hosting guide {' '} walks through the deployment options. If you'd rather not: every server generated on BuildMyMCPServer ships behind an OAuth 2.1 AS with PKCE, DCR and Resource Indicators already wired — the flow above is what our{' '} OAuth docs {' '} implement, and the free tier{' '} includes it.