evalstate/fastmcp-hf-oauth-test
0
1import os2 3from fastmcp import FastMCP4from fastmcp.server.auth.providers.huggingface import HuggingFaceProvider5from fastmcp.utilities.auth import parse_scopes6 7 8def scopes_from_space() -> list[str]:9 scopes = parse_scopes(os.environ.get("OAUTH_SCOPES")) or []10 merged = list(dict.fromkeys(["openid", "profile", *scopes]))11 return merged12 13 14base_url = f"https://{os.environ['SPACE_HOST']}"15 16mcp = FastMCP(17 name="FastMCP Hugging Face OAuth Test",18 auth=HuggingFaceProvider(19 client_id=os.environ["OAUTH_CLIENT_ID"],20 client_secret=os.environ["OAUTH_CLIENT_SECRET"],21 base_url=base_url,22 jwt_signing_key=os.environ["JWT_SIGNING_KEY"],23 required_scopes=scopes_from_space(),24 ),25)26 27 28@mcp.tool29async def whoami() -> dict:30 """Return the authenticated Hugging Face user's token claims."""31 from fastmcp.server.dependencies import get_access_token32 33 token = get_access_token()34 return {35 "client_id": token.client_id,36 "scopes": token.scopes,37 "claims": {38 "sub": token.claims.get("sub"),39 "preferred_username": token.claims.get("preferred_username"),40 "name": token.claims.get("name"),41 "email": token.claims.get("email"),42 "email_verified": token.claims.get("email_verified"),43 "profile": token.claims.get("profile"),44 "picture": token.claims.get("picture"),45 "organizations": token.claims.get("organizations"),46 },47 }48 49 50@mcp.tool51async def echo(message: str) -> str:52 """Echo a message after OAuth succeeds."""53 return message54 55 56if __name__ == "__main__":57 mcp.run(58 transport="http",59 host="0.0.0.0",60 port=int(os.environ.get("PORT", "7860")),61 path="/mcp",62 )63 