MCP authorization reference

MCP protected resource metadata (RFC 9728)

The exact protected resource metadata document, WWW-Authenticate challenge, and discovery path an MCP server needs so a client can find its authorization server without configuration.

Updated July 2026Implementation guiderfc 9728
Built for

Engineers making a remote MCP server discoverable to Claude, ChatGPT, IDE clients, and custom agents.

Decision supported

How an MCP client learns which authorization server protects your MCP endpoint, and what the server must return before the token exists.

The control gap

The MCP authorization specification delegates discovery to OAuth 2.0 Protected Resource Metadata, RFC 9728. A client that receives a 401 without a resource_metadata pointer cannot begin the flow, so the connection fails with a generic authentication error and no way for the user to fix it. The failure is usually not the token logic. It is a missing document and a missing header.

What good looks like

An unauthenticated request returns a 401 carrying a resource_metadata URL, that URL returns a document naming the canonical resource identifier and its authorization servers, and the client completes registration and consent without anyone editing a config file.

  • Serve the metadata at a path derived from the MCP endpoint, not at a single well-known path shared by every server you host.
  • Return the canonical resource identifier exactly as the client must later send it in the token request, including or excluding the trailing slash consistently.
  • Emit WWW-Authenticate on every 401 and on insufficient-scope 403 responses, with both the error code and the resource_metadata parameter.
  • List only the scopes the resource actually enforces, so a client does not request authority the server will never honour.

A production workflow

  1. The client calls the MCP endpoint with no credential and receives 401 plus a WWW-Authenticate header naming the metadata URL.
  2. The client fetches that metadata and reads the resource identifier, the authorization servers, the supported scopes, and the accepted bearer method.
  3. The client fetches the authorization server metadata, registers if it has no client identifier, and runs the authorization code flow with PKCE.
  4. The client retries the MCP request with the bearer token, and the server checks that the token audience matches the canonical resource before executing any tool.

Copy this

Endram serves this pair for every gateway. The metadata path carries the gateway slug so one deployment can host many independently authorized MCP endpoints.

GET /.well-known/oauth-protected-resource/mcp/<gateway-slug>

{
  "resource": "https://endram.com/mcp/<gateway-slug>",
  "authorization_servers": ["https://endram.com"],
  "scopes_supported": ["mcp:connect", "tools:read", "tools:call"],
  "bearer_methods_supported": ["header"],
  "resource_documentation": "https://endram.com/app/gateways"
}

# The 401 that sends a client there
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token",
  resource_metadata="https://endram.com/.well-known/oauth-protected-resource/mcp/<gateway-slug>"

# The 403 a client gets when the token is valid but too narrow
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope", scope="tools:call",
  resource_metadata="https://endram.com/.well-known/oauth-protected-resource/mcp/<gateway-slug>"

The insufficient_scope response matters more than it looks. Without it a client that holds a read-only token retries forever instead of asking the user to widen consent, and the failure surfaces to the operator as a hung tool call rather than a permission problem.

Evidence to require

  • The metadata document actually served for each endpoint, including its resource identifier and scope list.
  • The challenge header returned on the unauthenticated request, captured from a real client rather than from documentation.
  • Which authorization server issued the presented token and whether its audience matched the canonical resource.
  • Every rejected token, with the reason: wrong audience, expired, insufficient scope, or revoked consent.

Buyer checklist

  • Does each MCP endpoint have its own metadata document, or do several share one?
  • Is the resource identifier in the metadata byte-identical to the value the token request must carry?
  • Do 403 responses carry a scope challenge, or only 401s?
  • Does the server reject a valid token issued for a different resource on the same host?

Practical answers

Common implementation questions

Is RFC 9728 required by the MCP specification?

The MCP authorization specification builds on it. A remote MCP server that expects clients to discover authorization automatically needs to serve protected resource metadata and point at it from the 401 challenge.

Can one metadata document cover several MCP servers?

Only if they share one resource identifier and one scope set, which defeats per-server authorization. Endram serves a document per gateway so each endpoint has its own canonical resource and its own audience-bound tokens.

What should the server do with a token whose audience is a different resource?

Reject it. Accepting a token minted for another resource is the audience-confusion problem that resource indicators exist to prevent, and it turns any one compromised server into a path into the others.

Continue the evaluation

Related controls