""" GCP - Game Context Protocol Server FastAPI server for the 3D scene viewer HTTP endpoints. MCP tools are defined in mcp_server.py """ import os from pathlib import Path from fastapi import FastAPI, HTTPException from fastapi.responses import HTMLResponse, JSONResponse from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from backend.storage import storage # Get project root directory PROJECT_ROOT = Path(__file__).parent.parent # Create FastAPI app app = FastAPI( title="GCP - Game Context Protocol", description="3D scene building server. Use MCP tools via Claude/AI assistants, or view scenes via HTTP.", version="2.0.0", ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Mount static files for models models_path = PROJECT_ROOT / "models" if models_path.exists(): app.mount("/static/models", StaticFiles(directory=str(models_path)), name="models") # ============================================================================= # HTTP Endpoints (for viewer and health checks) # ============================================================================= @app.get("/health") async def health_check(): """Health check endpoint for startup verification.""" return { "status": "healthy", "service": "GCP - Game Context Protocol", "version": "2.0.0", } @app.get("/api") async def api_root(): """API root endpoint with API information.""" return { "name": "GCP - Game Context Protocol", "version": "2.0.0", "description": "MCP server for building 3D scenes with AI assistants", "endpoints": { "viewer": "/view/scene/{scene_id}", "scene_data": "/api/scenes/{scene_id}", "health": "/health", }, "mcp": "Connect via stdio transport using: python -m backend.mcp_server", } @app.get("/api/scenes/{scene_id}") async def get_scene_api(scene_id: str): """Get scene configuration and data as JSON.""" scene = storage.get(scene_id) if not scene: raise HTTPException(status_code=404, detail=f"Scene '{scene_id}' not found") return scene @app.get("/view/scene/{scene_id}") async def view_scene(scene_id: str): """Serve the Three.js viewer for a scene.""" scene = storage.get(scene_id) if not scene: raise HTTPException(status_code=404, detail=f"Scene '{scene_id}' not found") # Serve the game viewer HTML try: viewer_path = os.path.join(os.path.dirname(__file__), "..", "frontend", "game_viewer.html") with open(viewer_path, 'r') as f: html_content = f.read() return HTMLResponse(content=html_content) except FileNotFoundError: raise HTTPException(status_code=500, detail="Game viewer HTML not found") @app.get("/manifest.json") async def get_manifest(): """Serve PWA manifest to avoid 404 errors.""" try: manifest_path = os.path.join(os.path.dirname(__file__), "..", "frontend", "manifest.json") with open(manifest_path, 'r') as f: import json manifest_content = json.load(f) return JSONResponse(content=manifest_content) except FileNotFoundError: return JSONResponse(content={"name": "GCP", "short_name": "GCP"}) # ============================================================================= # Run server # ============================================================================= if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)