Before a client ever shows you a consent screen, it has to answer a question MCP itself doesn’t hard-code: where does this server’s OAuth actually live? A remote MCP server’s URL isn’t an authorization server — it’s just an endpoint for tool calls. The discovery step is how a client goes from “this server replied 401” to “here’s the login page,” and it runs entirely on two small metadata documents, fetched before any scope or consent screen enters the picture.

How the handshake actually runs

The sequence is specified, not left to each client to improvise:

  • An unauthenticated request first. The client calls the MCP server with no token. A server that requires auth replies with an HTTP 401 and a WWW-Authenticate header — the same mechanism browsers have used for basic auth for decades, repurposed here to carry a URL instead of a realm name.
  • Protected Resource Metadata (RFC 9728). That header points to a document, conventionally served at /.well-known/oauth-protected-resource, that identifies the MCP server as an OAuth-protected resource and lists which authorization server (or servers) can issue tokens for it.
  • Authorization Server Metadata (RFC 8414). Once the client knows which authorization server to talk to, it fetches a second document from that server — typically /.well-known/oauth-authorization-server — describing its actual endpoints: where to send a user to log in, where to exchange a code for a token, and whether it supports registering a new client on the fly.
  • Dynamic client registration, if offered. If the authorization server supports it, the client registers itself automatically and gets back a client ID with no human involved. This is the step that fails for the vendors we’ve covered whose OAuth only admits pre-approved clients — see why some servers reject a client here even though discovery itself succeeded.
  • The authorization code flow, with PKCE. Only now does the familiar part happen: a browser redirect, a login, a consent screen, and a code exchanged for a token scoped to that one resource.

Every step before the consent screen is metadata-fetching, not permission-granting. A client can complete all of it against a server that turns out to be badly run, or outright hostile, and discovery itself won’t have told it so.

Why MCP needed this instead of per-server config

Before this pattern existed, connecting a new OAuth-protected server meant a human finding the vendor’s developer docs, registering an app by hand, and pasting a client ID and secret into a config file — the exact manual step that made adding servers one at a time slow in the first place. Standardized discovery means a client only needs to know one thing to start: the server’s URL. Everything else — where to authenticate, how to register, what flow to run — comes back from the two metadata documents instead of a README. That’s also why an MCP server’s OAuth can “just work” in one client and need a bearer token pasted in by hand in another: discovery is only as good as whether both the server and the client actually implement it, and some vendors still fall back to older patterns outside this flow.

What discovery doesn’t tell you

It’s worth being precise about what two metadata documents and a redirect actually prove, because it isn’t much:

  • It doesn’t verify who the authorization server belongs to. Protected Resource Metadata tells a client which authorization server to trust for this resource — it doesn’t independently confirm that server is run by the vendor whose name is on the MCP server. That’s the same gap we cover in telling a real MCP server from a fake one: a convincing name and a working discovery flow are not the same thing as provenance.
  • It says nothing about what the resulting token can actually do. Discovery gets you to a token. What that token is scoped to, and how far it reaches past what you intended to grant, is the separate question OAuth scopes answers — and discovery succeeding tells you nothing about whether the scopes on offer are reasonable.
  • It’s not mutual. The flow authenticates the user to the authorization server. It doesn’t give the user strong assurance that the authorization server itself is legitimate beyond “this is the URL the resource server’s metadata pointed at.” If that first metadata document were ever served from a compromised or spoofed endpoint, the rest of the flow would run exactly as designed against the wrong authorization server.

If you’re building a server

Serving both metadata documents correctly is most of the work, and it’s the part generic OAuth libraries often don’t hand you for free, since Protected Resource Metadata is newer and MCP-specific in how it’s used. If you’d rather not implement the discovery documents, the 401 handling, and dynamic client registration yourself, that’s exactly the shortcut we described in adding OAuth to your own MCP server: put a gateway in front that already speaks this handshake, and your server only has to trust one caller instead of implementing the full flow for every client that might connect.

Where gate fits: a gateway sits through exactly this handshake once, on your behalf, so Claude, Cursor, and every other client authenticate against the gateway instead of each running its own discovery flow against every server you connect. gate’s free MCP security scanner is a separate check worth running alongside this — discovery tells a client how to get a token, not whether the server on the other end deserves one.

The bottom line

MCP OAuth discovery is two metadata fetches — Protected Resource Metadata to find the authorization server, Authorization Server Metadata to find its endpoints — that let a client go from a server URL to a working login with no manual app registration. It replaces copy-pasted client IDs with a standard lookup, and it’s why some servers connect in one click while others still ask for a token pasted by hand. What it doesn’t replace is judgment about the server itself: see gate’s MCP security guide for the checks discovery was never meant to cover.