Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
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"], | |
), | |
) | |
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%", | |
} | |
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()) | |
async def _(): | |
return JSONResponse({"message": "Welcome to the Weather Service!"}) | |
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) |