|
|
""" |
|
|
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 |
|
|
|
|
|
|
|
|
PROJECT_ROOT = Path(__file__).parent.parent |
|
|
|
|
|
|
|
|
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", |
|
|
) |
|
|
|
|
|
|
|
|
app.add_middleware( |
|
|
CORSMiddleware, |
|
|
allow_origins=["*"], |
|
|
allow_credentials=True, |
|
|
allow_methods=["*"], |
|
|
allow_headers=["*"], |
|
|
) |
|
|
|
|
|
|
|
|
models_path = PROJECT_ROOT / "models" |
|
|
if models_path.exists(): |
|
|
app.mount("/static/models", StaticFiles(directory=str(models_path)), name="models") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@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") |
|
|
|
|
|
|
|
|
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"}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
import uvicorn |
|
|
uvicorn.run(app, host="0.0.0.0", port=8000) |
|
|
|