import os from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from starlette.middleware.sessions import SessionMiddleware from authlib.integrations.starlette_client import OAuth from math_server import mcp as math_mcp # ------------------------------- # Directories # ------------------------------- BASE_DIR = os.path.dirname(__file__) STATIC_DIR = os.path.join(BASE_DIR, "static") TEMPLATES_DIR = os.path.join(BASE_DIR, "templates") # ------------------------------- # App FastAPI # ------------------------------- app = FastAPI() # Session middleware nécessaire pour OAuth app.add_middleware(SessionMiddleware, secret_key=os.environ.get("SESSION_SECRET", "UN_SECRET_123")) # Static files app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static") templates = Jinja2Templates(directory=TEMPLATES_DIR) # ------------------------------- # Twitter OAuth configuration # ------------------------------- oauth = OAuth() oauth.register( name="twitter", client_id=os.environ.get("TWITTER_CLIENT_ID"), client_secret=os.environ.get("TWITTER_CLIENT_SECRET"), request_token_url=None, access_token_url="https://api.twitter.com/2/oauth2/token", authorize_url="https://twitter.com/i/oauth2/authorize", client_kwargs={"scope": "tweet.read users.read offline.access"}, ) # ------------------------------- # Endpoint racine # ------------------------------- @app.get("/", response_class=HTMLResponse) async def index(request: Request): space_host = os.environ.get("SPACE_HOST") if space_host and space_host.strip(): base_url = space_host.strip().rstrip("/") else: base_url = f"{request.url.scheme}://{request.url.netloc}" user = request.session.get("user") return templates.TemplateResponse("index.html", {"request": request, "base_url": base_url, "user": user}) # ------------------------------- # Twitter OAuth endpoints # ------------------------------- @app.get("/auth/twitter/login") async def login(request: Request): redirect_uri = request.url_for("auth_callback") return await oauth.twitter.authorize_redirect(request, redirect_uri) @app.get("/auth/twitter/callback") async def auth_callback(request: Request): token = await oauth.twitter.authorize_access_token(request) user_info = await oauth.twitter.parse_id_token(request, token) request.session["user"] = {"id": user_info.get("sub"), "username": user_info.get("name")} return RedirectResponse(url="/") @app.get("/auth/logout") async def logout(request: Request): request.session.pop("user", None) return RedirectResponse(url="/") # ------------------------------- # Endpoint MCP math # ------------------------------- app.mount("/math", math_mcp.http_app()) # juste le HTTP app, pas besoin de run() # ------------------------------- # Lancer le serveur # ------------------------------- PORT = int(os.environ.get("PORT", "10000")) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=PORT)