from pydantic import AnyHttpUrl from mcp.server.auth.provider import AccessToken, TokenVerifier from mcp.server.auth.settings import AuthSettings from mcp.server.fastmcp import FastMCP from fastapi import FastAPI from starlette.responses import JSONResponse, RedirectResponse import contextlib class SimpleTokenVerifier(TokenVerifier): """Simple token verifier for demonstration.""" async def verify_token(self, token: str) -> AccessToken | None: pass # This is where you would implement actual token validation # Create FastMCP instance as a Resource Server mcp = FastMCP( "Weather Service", # Token verifier for authentication token_verifier=SimpleTokenVerifier(), # Auth settings for RFC 9728 Protected Resource Metadata auth=AuthSettings( issuer_url=AnyHttpUrl("https://huggingface.co/.well-known/oauth-authorization-server"), # Authorization Server URL resource_server_url=AnyHttpUrl("https://freddyaboulton-fastmcp-oauth.hf.space/"), # This server's URL required_scopes=["user"], ), ) @mcp.tool() async def get_weather(city: str = "London") -> dict[str, str]: """Get weather data for a city""" return { "city": city, "temperature": "22", "condition": "Partly cloudy", "humidity": "65%", } @contextlib.asynccontextmanager async def lifespan(app: FastAPI): async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context(mcp.session_manager.run()) yield app = FastAPI(lifespan=lifespan) app.mount("/weather_mcp", mcp.streamable_http_app()) @app.get("/") async def _(): return JSONResponse({"message": "Welcome to the Weather Service!"}) @app.get("/.well-known/oauth-protected-resource") async def _(): return RedirectResponse("/weather_mcp/.well-known/oauth-protected-resource") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)