-
Notifications
You must be signed in to change notification settings - Fork 806
feature: Support OAuth Protected Resource Metadata discovery via WWW-Authenticate header #688
Description
Problem Statement
When an MCP server is deployed at a sub-path (e.g., [https://gateway.example.com/mcp](https://gateway.example.com/mcp)), the current OAuth implementation fails to discover the Protected Resource Metadata (PRM) correctly.
The client constructs an origin-based URL:
https://gateway.example.com/.well-known/oauth-protected-resource
But the server can only serve PRM at:
https://gateway.example.com/mcp/.well-known/oauth-protected-resource
This is a common scenario when:
- MCP server is deployed behind a shared API gateway
- Multiple services share the same domain with different paths
- Cloud platforms or Kubernetes Ingress route traffic by path
- The service owner doesn't control the root path of the domain
Proposed Solution
Parse the resource_metadata parameter from the WWW-Authenticate header when receiving a 401 Unauthorized response, and use this URL for PRM discovery instead of constructing an origin-based URL.
Implementation approach:
- When receiving
401 Unauthorized, parseresource_metadatafromWWW-Authenticateheader - Store this URL in the
OAuthHandler - Use this URL (if present) in
getServerMetadata()before falling back to origin-based discovery - Maintain full backward compatibility - if no
resource_metadatais provided, current behavior is preserved
MCP Spec Reference
According to the MCP Authorization spec, when a server returns 401 Unauthorized, it should include:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource"The client should parse this header and use the provided URL for PRM discovery. See also RFC 9728 - OAuth 2.0 Protected Resource Metadata.
Example Usage
// No API changes required - the fix is internal to the OAuth discovery flow.
// After the fix, this would work correctly for sub-path deployments:
client, _ := client.NewOAuthStreamableHttpClient(
"https://gateway.example.com/mcp", // MCP server at sub-path
oauthConfig,
)
// Client receives 401 with:
// WWW-Authenticate: Bearer resource_metadata="https://gateway.example.com/mcp/.well-known/oauth-protected-resource"
//
// Client automatically uses the provided URL for PRM discovery Alternatives/Workarounds Considered
-
Manually set
AuthServerMetadataURL- Works but requires users to know the OIDC discovery URL upfront, bypassing the standard discovery flow. -
Deploy PRM at origin root - Not always possible when the service owner doesn't control the root path.
Notes
I have a local branch that implemented the fix/enhancement, and I'd be happy to contribute if it would be helpful - please let me know if opening a new PR would be appropriate. This is my first contribution to this project, so any guidance would be greatly appreciated!