How to publish OAuth protected resource metadata
Follow these steps end-to-end. Use the local generator for the four artifacts; deploy them on your own resource origin.
1. Confirm prerequisites
You need deploy access on the resource origin (the host that serves your API or MCP endpoint) and a decision about which authorization server issuer URLs clients should use. This pack does not create tokens, clients, or AS metadata (RFC 8414).
2. Choose the resource identifier carefully
The resource identifier is an HTTPS URL with no fragment. Prefer no query string unless you truly need it. If the identifier includes a path (for example https://api.example.com/mcp), that path becomes part of the well-known location.
3. Fill the generator and rebuild
Open the generator. Enter the resource URL, one or more authorization server issuers, and optional scopes. Rebuild and inspect all four outputs before touching production.
4. Host JSON at the derived well-known path
For a resource with no path, publish at https://<host>/.well-known/oauth-protected-resource. For a resource with path /mcp, publish at https://<host>/.well-known/oauth-protected-resource/mcp — insert /.well-known/oauth-protected-resource between the host and the path after removing a trailing slash on the host component (RFC 9728 §3.1).
5. Keep resource byte-for-byte identical
The JSON field resource MUST match the resource identifier you used to derive the URL. Clients must reject metadata when these values differ. Do not add a trailing slash “for neatness” unless the identifier itself includes one.
6. Apply Pages _headers (or equivalent)
Copy the recipe from the tool into the root _headers of the Cloudflare Pages project that serves the resource host (or set an explicit Content-Type map on Nginx). Redeploy, then confirm the response is Content-Type: application/json. An HTML soft-404 with status 200 breaks discovery.
7. Return WWW-Authenticate on unauthenticated calls
When a client hits the resource without a token, respond with HTTP 401 and include:
WWW-Authenticate: Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource/mcp"
Point resource_metadata at the absolute well-known URL you just published. Clients fetch PRM, then discover the authorization server.
8. Curl self-check
From any machine:
curl -sSI "https://<host>/.well-known/oauth-protected-resource[/path]"
curl -sS "https://<host>/.well-known/oauth-protected-resource[/path]" | head
curl -sSI -o /dev/null -w "%{http_code}\n" -H "Authorization:" "https://<resource-url>"
Expect HTTP 200 and application/json on the well-known document, parseable JSON whose resource matches the identifier, and a 401 (or your chosen challenge) that includes resource_metadata when unauthenticated.