Skip to content

RemoteAuthProvider OAuth Discovery Endpoint Points to Root Instead of MCP Endpoint #1348

@nick-youngblut

Description

@nick-youngblut

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

  1. 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()
  1. Deploy the server and test the OAuth discovery endpoint:
curl https://my-server.com/.well-known/oauth-protected-resource
  1. Observe that the resource field points to https://my-server.com/ instead of https://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:

  1. 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"]
            }
  1. 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

  1. Fix the resource_server_url parameter: Make RemoteAuthProvider respect the full URL path provided in resource_server_url, including /mcp/ or other paths.

  2. Add configuration option: Provide a separate parameter like mcp_endpoint_url to explicitly specify the MCP endpoint URL for OAuth discovery.

  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions