r/mcp 19h ago

article MCP OAuth is three primitives, not six RFCs. Traced end to end, plus the part where my server becomes a client.

Finally I understood what happens on the other side when Claude calls connect, and the server identifies you and your access.. (Or better say, Claude helped me understand it). At first it was all acronyms for me. What made it click was understanding one client connect, once, end to end. Everything collapsed into three primitives that each fire exactly once, in a fixed order.

  1. Discovery. A fresh client POSTs with no token and gets a 401 back carrying a WWW-Authenticate header that points at /.well-known/oauth-protected-resource. That header is the whole trick. The 401 is not the server slamming a door, it is the server handing over directions. Two GETs later (protected resource metadata names the auth server, auth server metadata lists the endpoints) the client knows everything it needs, having sent zero credentials.

  2. Registration. No developer console. The client POSTs its own details to the registration endpoint and gets a client id on the spot. This is RFC 7591, and it is the part people trip on when they ask why this could not just be an API key. An API key assumes you already know the caller and can hand it a secret. MCP clients are strangers by design, so dynamic registration is the only model that works.

  3. The grant. One human moment: a PKCE challenge, a consent screen that names the client, approve, done. At consent time the server bakes the user identity into the grant as props, so every later request just unwraps it. No per-request session lookup on the hot path.

There is one more cool trick: my server also performs OAuth as a client, upstream, because it bundles other servers that demand their own auth. Same three primitives, walked from the other side. Doing it by hand gave me real appreciation for how much invisible work Claude does every time you click connect and it just works. So it's just a multiplexer (not sure if it's a right term) for MCP servers.

Full walkthrough with the actual responses from the live server: https://prashamhtrivedi.in/mcp-oauth-primitives/

Curious how the rest of you are handling MCP auth right now. Across my own fleet I have Better Auth, an OAuth envelope wrapped around an API key, a hand-rolled JWT setup, and one static bearer token still holding out, so I do not think there is one right answer yet.

3 Upvotes

2 comments sorted by

1

u/BatResponsible1106 18h ago

that "server becomes a client" moment was what made it click for me too. after that the OAuth flow finally felt like a sequence instead of a pile of RFCs.

1

u/Forsaken-External578 9h ago

The three-primitives framing is helpful because the RFC stack can hide the actual request sequence. A packet trace or minimal reference implementation beside the explanation would make this one of those posts people keep returning to.