#688·mcp-go

feature: Support OAuth Protected Resource Metadata discovery via WWW-Authenticate header

Author: qhzhuCreated Jan 2, 2026Updated Apr 18, 2026

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:

  1. When receiving 401 Unauthorized, parse resource_metadata from WWW-Authenticate header
  2. Store this URL in the OAuthHandler
  3. Use this URL (if present) in getServerMetadata() before falling back to origin-based discovery
  4. Maintain full backward compatibility - if no resource_metadata is provided, current behavior is preserved

MCP Spec Reference

According to the MCP Authorization spec, when a server returns 401 Unauthorized, it should include:

http
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

go
// 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

  1. Manually set AuthServerMetadataURL - Works but requires users to know the OIDC discovery URL upfront, bypassing the standard discovery flow.
  2. 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!