Repository navigation
The resource URL path is ignored when building the protected resource metadata URL #1052
Description
Activity
Hi @yurikunash thanks for opening this, I agree with you that we don't implement the more involved path discovery flow currently, and think we should add it like you've described.
One somewhat finicky nuance is the definition of "resource identifier" that I've had explained to me:
inserting a well-known URI string into the protected resource's resource identifier between the host component and the path and/or query components
The server can define the resource identifier to be different than the initial request path. For example, the request might be to
https://mcp.example.com/v1/mcp, but the resource identifier could behttps://mcp.example.com/v1orhttps://mcp.example.com/if that's how the server organizes things. The resource identifier is meant to be resource being protected, which might be broader than just the MCP endpoint.Since we're doing this all dynamically, we can only rely on what the server gives us to determine the resource identifier, and then fallback to defaults. The server can provide context in the
WWW-Authenticateheader. If it's not there though, we're stuck guessing. The way it is currently is implicitly always assuming it's the base URL, but we should instead check the request URL first, and then check the base URL. (We recently added this behavior for the AS metadata as well, so we can likely re-use some of that.)Reacted by yurikunashHi @pcarleton, thank you for your comments. I want to share my simple thoughts on that.
The FastMCP class exposes a settingsettings.auth.resource_server_url. So, why should we guess about the resource identifier and the path, instead of sticking to the value that the server developer has provided through that setting?
I hope you can either confirm or help find the gap.- addedauthIssues and PRs related to Authentication / OAuthIssues and PRs related to Authentication / OAuthready for workEnough information for someone to start working onEnough information for someone to start working onP3Nice to haves, rare edge casesNice to haves, rare edge casesquestionFurther information is requestedFurther information is requested
on Oct 3, 2025 Both halves of this are implemented and released:
- Server side: Improve OAuth protected resource metadata URL construction per RFC 9728 #1407 added
build_resource_metadata_url(), which inserts/.well-known/oauth-protected-resourcebetween the host and the resource path per RFC 9728 §3.1, and the metadata route is now registered at that path-based URL (theWWW-Authenticateresource_metadatahint uses it too). The URL is built directly from theresource_server_urlyou configure, so the server-provided resource identifier is used as-is rather than guessed. Released in v1.17.0. - Client side: Implement SEP-985: OAuth Protected Resource Metadata discovery fallback #1548 (SEP-985) made discovery try the
resource_metadataURL from theWWW-Authenticateheader first, then the path-based well-known URI, then fall back to the root-based one. Released in v1.21.0.
Both changes are also on
main(v2), and the current v1.x release (v1.27.2) carries them. Using the example from this issue: a server configured withresource_server_url=https://resource.example.com/resource1now serves metadata athttps://resource.example.com/.well-known/oauth-protected-resource/resource1.The remaining sharp edge — configurations where
resource_server_urlomits the transport path, making the metadataresourcefield mismatch what strict clients resolve — is tracked separately in #1264.Closing as resolved.
Reacted by yurikunash- Server side: Improve OAuth protected resource metadata URL construction per RFC 9728 #1407 added
Initial Checks
Description
The current MCP Server implementation appears to use a fixed URL pattern
[domain]/.well-known/oauth-protected-resourcefor the protected resource URL. After reviewing RFC9728, I believe this doesn't fully align with the specification's requirements.Expected behavior:
If the resource URL is
https://resource.example.com/resource1, the protected resource metadata URL to behttps://resource.example.com/.well-known/oauth-protected-resource/resource1Current behavior:
If the resource URL is
https://resource.example.com/resource1, the protected resource metadata URL to behttps://resource.example.com/.well-known/oauth-protected-resourceLink to the source code:
python-sdk/src/mcp/server/auth/routes.py
Line 219 in 7942184
RFC 9728
As the RFC correctly states:
which is difficult to achieve with the current implementation.
Example Code
Python & MCP Python SDK