You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
OAuthClientProvider add prefix url for MCP Starlette Mounted endpoints to correctly route .well-known metadata discovery #1751
changed the title [-]OAuthClientProvider add prefix url for MCP Mounted endpoints to correctly route .well-known metadata discovery[/-][+]OAuthClientProvider add prefix url for MCP Starlette Mounted endpoints to correctly route .well-known metadata discovery[/+]on Dec 9, 2025
Thanks for the detailed issue! So the problem here is that Starlette's Mount() prefixes all routes including .well-known, which puts them in the wrong place per RFC 9728.
The spec says .well-known goes between host and path - so for https://example.com/hr-policy/hr-policy the metadata should be at /.well-known/oauth-protected-resource/hr-policy/hr-policy, not /hr-policy/.well-known/oauth-protected-resource. See RFC 9728 §3.1 for the well-known URI construction rules.
I tested this locally and confirmed:
When you mount at /hr-policy, routes like /.well-known/oauth-protected-resource become /hr-policy/.well-known/oauth-protected-resource
The client correctly looks at the RFC 9728 location (/.well-known/oauth-protected-resource/...) and gets 404
The workaround is to register the .well-known routes at root level instead of inside the mounted app:
frommcp.server.auth.routesimportcreate_protected_resource_routesroutes= [
# Root-level .well-known routes (before mounting)*create_protected_resource_routes(
resource_url="https://your-server.com/hr-policy/hr-policy",
authorization_servers=["https://your-auth-server/..."],
scopes_supported=["mcp:tools"],
),
# Then mount the appsMount("/hr-policy", app=hr_policy_mcp.streamable_http_app()),
]
Also note - your resource_server_url should be the full endpoint path (https://your-server.com/hr-policy/hr-policy), not just the base URL. The resource field in the metadata must match the actual resource per RFC 9728.
Closing #1762 since the client-side fix isn't spec-compliant. Let me know if the workaround works for you!
Thanks for the workaround, it is working, I'll look if I can override Mount to create create_protected_resource_routes based on authorization_servers state in the server object reference automatically, so no need to manually add those routes.
Activity
[-]OAuthClientProvider add prefix url for MCP Mounted endpoints to correctly route .well-known metadata discovery[/-][+]OAuthClientProvider add prefix url for MCP Starlette Mounted endpoints to correctly route .well-known metadata discovery[/+]maxisbey commentedon Dec 10, 2025
Thanks for the detailed issue! So the problem here is that Starlette's
Mount()prefixes all routes including.well-known, which puts them in the wrong place per RFC 9728.The spec says
.well-knowngoes between host and path - so forhttps://example.com/hr-policy/hr-policythe metadata should be at/.well-known/oauth-protected-resource/hr-policy/hr-policy, not/hr-policy/.well-known/oauth-protected-resource. See RFC 9728 §3.1 for the well-known URI construction rules.I tested this locally and confirmed:
/hr-policy, routes like/.well-known/oauth-protected-resourcebecome/hr-policy/.well-known/oauth-protected-resource/.well-known/oauth-protected-resource/...) and gets 404The workaround is to register the
.well-knownroutes at root level instead of inside the mounted app:Also note - your
resource_server_urlshould be the full endpoint path (https://your-server.com/hr-policy/hr-policy), not just the base URL. Theresourcefield in the metadata must match the actual resource per RFC 9728.Closing #1762 since the client-side fix isn't spec-compliant. Let me know if the workaround works for you!
AI Disclaimer
abneetwats24 commentedon Dec 12, 2025
Thanks for the workaround, it is working, I'll look if I can override Mount to create create_protected_resource_routes based on authorization_servers state in the server object reference automatically, so no need to manually add those routes.