-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Description
Issue Description
When using RemoteAuthProvider
with FastMCP, the OAuth protected resource metadata endpoint (/.well-known/oauth-protected-resource
) always returns the base server URL as the resource
field, rather than the actual MCP endpoint URL (/mcp/
). This causes OAuth clients (like Claude Desktop) to attempt authentication and subsequent MCP requests to the wrong endpoint, resulting in 404 errors.
Expected Behavior
The OAuth discovery endpoint should return the MCP endpoint URL in the resource
field so that OAuth clients know where to send authenticated MCP requests.
Expected Response:
{
"resource": "https://my-server.com/mcp/",
"authorization_servers": ["https://accounts.google.com"],
"scopes_supported": [],
"bearer_methods_supported": ["header"]
}
Actual Behavior
The OAuth discovery endpoint always returns the base server URL, regardless of the resource_server_url
parameter.
Actual Response:
{
"resource": "https://my-server.com/",
"authorization_servers": ["https://accounts.google.com"],
"scopes_supported": [],
"bearer_methods_supported": ["header"]
}
Reproduction Steps
- Create a FastMCP server with
RemoteAuthProvider
:
from fastmcp import FastMCP
from fastmcp.server.auth import RemoteAuthProvider
from fastmcp.server.auth.providers.jwt import JWTVerifier
from pydantic import AnyHttpUrl
import os
# Configure token verification
token_verifier = JWTVerifier(
jwks_uri="https://www.googleapis.com/oauth2/v3/certs",
issuer="https://accounts.google.com",
audience="your-google-client-id"
)
# Create RemoteAuthProvider with full MCP endpoint URL
auth = RemoteAuthProvider(
token_verifier=token_verifier,
authorization_servers=[AnyHttpUrl("https://accounts.google.com")],
resource_server_url="https://my-server.com/mcp/" # Note: includes /mcp/ path
)
mcp = FastMCP(name="Test Server", auth=auth)
@mcp.tool
def test_tool() -> str:
return "Hello"
if __name__ == "__main__":
mcp.run()
- Deploy the server and test the OAuth discovery endpoint:
curl https://my-server.com/.well-known/oauth-protected-resource
- Observe that the
resource
field points tohttps://my-server.com/
instead ofhttps://my-server.com/mcp/
Environment
- FastMCP Version: 2.11.1
- Python Version: 3.11
- Deployment: Google Cloud Run (HTTP transport)
- OAuth Provider: Google OAuth
Impact
This prevents OAuth-enabled MCP servers from working with OAuth clients like Claude Desktop, as the clients receive incorrect endpoint information during discovery and subsequently make requests to the wrong URL.
Workaround Attempts
I tried several approaches to override the OAuth discovery endpoint, but none were successful:
- Custom subclass with
customize_auth_routes
:
class CustomRemoteAuthProvider(RemoteAuthProvider):
def customize_auth_routes(self, app):
super().customize_auth_routes(app)
@app.get("/.well-known/oauth-protected-resource")
async def custom_protected_resource_metadata():
return {
"resource": "https://my-server.com/mcp/",
"authorization_servers": ["https://accounts.google.com"],
"scopes_supported": [],
"bearer_methods_supported": ["header"]
}
- Direct FastAPI route override:
@mcp.http_app().get("/.well-known/oauth-protected-resource") # This fails
async def custom_oauth_protected_resource():
return {"resource": "https://my-server.com/mcp/", ...}
Both approaches either failed to execute or were ignored by the existing route.
Proposed Solutions
-
Fix the
resource_server_url
parameter: MakeRemoteAuthProvider
respect the full URL path provided inresource_server_url
, including/mcp/
or other paths. -
Add configuration option: Provide a separate parameter like
mcp_endpoint_url
to explicitly specify the MCP endpoint URL for OAuth discovery. -
Provide override method: Add a documented way to override the OAuth discovery endpoints, such as a working
customize_auth_routes
method or similar.
Additional Context
According to the [MCP OAuth specification](https://spec.modelcontextprotocol.io/specification/server/authentication/#oauth-20-authentication), the resource
field in the protected resource metadata should point to the actual protected resource (the MCP endpoint), not just the server's base URL.
The server logs show that FastMCP correctly serves the MCP endpoint at /mcp/
, but the OAuth discovery points clients to /
, causing a mismatch:
INFO: Starting MCP server on http://0.0.0.0:8080/mcp/
...
WARNING: GET / HTTP/1.1" 404 Not Found # OAuth client trying wrong endpoint
INFO: GET /.well-known/oauth-protected-resource HTTP/1.1" 200 OK # Discovery works
Example Code
See above
Version Information
FastMCP version: 2.11.1.dev4+ec52e74
MCP version: 1.12.3
Python version: 3.10.17
Platform: macOS-15.5-arm64-arm-64bit
FastMCP root path: /Users/nickyoungblut/dev/python/arc-example-mcp/.venv/lib/python3.10/site-packages
Additional Context
No response