diff --git a/docker-compose.yml b/docker-compose.yml index 6737184..7c90a37 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,12 @@ services: geoguessr-mcp: # Option 1: Build locally (for development) - # build: - # context: . - # dockerfile: Dockerfile + build: + context: . + dockerfile: Dockerfile # Option 2: Use pre-built image from Docker Hub (recommended) - image: nyxiumyuuki/geoguessr-mcp:latest + # image: nyxiumyuuki/geoguessr-mcp:latest container_name: geoguessr-mcp-server restart: unless-stopped diff --git a/src/geoguessr_mcp/main.py b/src/geoguessr_mcp/main.py index c6a1e6b..6d57c06 100644 --- a/src/geoguessr_mcp/main.py +++ b/src/geoguessr_mcp/main.py @@ -7,15 +7,12 @@ with automatic API monitoring and dynamic schema adaptation. import logging import sys -from typing import Any from mcp.server.fastmcp import FastMCP -from starlette.applications import Starlette -from starlette.middleware import Middleware +from starlette.middleware.cors import CORSMiddleware from .config import settings from .middleware import AuthenticationMiddleware -from .monitoring import endpoint_monitor from .tools import register_all_tools # Configure logging @@ -28,132 +25,60 @@ logging.basicConfig( logger = logging.getLogger(__name__) -# Create the MCP server instance -mcp = FastMCP( - "GeoGuessr Analyzer", - instructions=""" - MCP server for analyzing GeoGuessr game statistics and optimizing gameplay strategy. - - This server provides: - - Profile and statistics retrieval - - Game history and analysis - - Performance tracking and recommendations - - API monitoring with automatic schema adaptation - - The server automatically tracks API endpoint changes and adapts to response format - modifications. Use the monitoring tools to check API status and discover available data. - - Authentication: - - Use 'login(email, password)' to authenticate with your GeoGuessr account - - Or use 'set_ncfa_cookie(cookie)' with a cookie from your browser - - Or set GEOGUESSR_NCFA_COOKIE environment variable for automatic auth - - Key tools: - - get_performance_summary() - Comprehensive overview of your account - - analyze_recent_games(count) - Analyze your recent gameplay - - get_strategy_recommendations() - Get personalized improvement tips - - check_api_status() - Monitor API endpoint availability - - explore_endpoint(path) - Discover new API endpoints - """, - host=settings.HOST, - port=settings.PORT, -) - -# Register all tools -services = register_all_tools(mcp) - -# Setup authentication middleware if enabled -if settings.MCP_AUTH_ENABLED: - logger.info("Setting up authentication middleware") - - # Create a function to add middleware to the app - def add_middleware_to_app(app): - """Add authentication middleware to a Starlette app.""" - if app is not None: - try: - app.add_middleware(AuthenticationMiddleware) - logger.info("Authentication middleware successfully added") - return True - except Exception as e: - logger.error(f"Failed to add middleware: {e}") - return False - - # Try to add middleware immediately to any existing app - middleware_added = False - - # Try different possible locations where FastMCP might store the app - for attr_path in [ - "mcp._transport.app", - "mcp.sse.app", - "mcp.http_server.app", - "mcp._http_server.app", - "mcp._app", - "mcp._asgi_app", - ]: - try: - parts = attr_path.split(".") - obj = mcp - for part in parts[1:]: # Skip 'mcp' itself - obj = getattr(obj, part, None) - if obj is None: - break - - if obj is not None and add_middleware_to_app(obj): - middleware_added = True - break - except (AttributeError, TypeError): - continue - - if not middleware_added: - # If we couldn't add it immediately, wrap the run method - logger.info("Deferring middleware addition until server starts") - - _original_run = mcp.run - - def run_with_middleware_wrapper(*args, **kwargs): - """Wrapper to try adding middleware when run() is called.""" - # Try again when run is called - for attr_path in [ - "mcp._transport.app", - "mcp.sse.app", - "mcp.http_server.app", - "mcp._http_server.app", - "mcp._app", - "mcp._asgi_app", - ]: - try: - parts = attr_path.split(".") - obj = mcp - for part in parts[1:]: - obj = getattr(obj, part, None) - if obj is None: - break - - if obj is not None and add_middleware_to_app(obj): - break - except (AttributeError, TypeError): - continue - - return _original_run(*args, **kwargs) - - mcp.run = run_with_middleware_wrapper - - -async def start_background_tasks(): - """Start background monitoring tasks.""" - if settings.MONITORING_ENABLED: - logger.info("Starting API monitoring background task...") - await endpoint_monitor.start_periodic_monitoring() - - -async def stop_background_tasks(): - """Stop background monitoring tasks.""" - if endpoint_monitor._running: - await endpoint_monitor.stop_monitoring() - - def main(): """Main entry point for the server.""" + + # Create the MCP server instance + mcp = FastMCP( + "GeoGuessr Analyzer", + instructions=""" + MCP server for analyzing GeoGuessr game statistics and optimizing gameplay strategy. + + This server provides: + - Profile and statistics retrieval + - Game history and analysis + - Performance tracking and recommendations + - API monitoring with automatic schema adaptation + + The server automatically tracks API endpoint changes and adapts to response format + modifications. Use the monitoring tools to check API status and discover available data. + + Authentication: + - Use 'login(email, password)' to authenticate with your GeoGuessr account + - Or use 'set_ncfa_cookie(cookie)' with a cookie from your browser + - Or set GEOGUESSR_NCFA_COOKIE environment variable for automatic auth + + Key tools: + - get_performance_summary() - Comprehensive overview of your account + - analyze_recent_games(count) - Analyze your recent gameplay + - get_strategy_recommendations() - Get personalized improvement tips + - check_api_status() - Monitor API endpoint availability + - explore_endpoint(path) - Discover new API endpoints + """, + host=settings.HOST, + port=settings.PORT, + ) + + # Register all tools + register_all_tools(mcp) + + # Setup authentication middleware if enabled + if settings.MCP_AUTH_ENABLED: + logger.info("Setting up authentication middleware") + + # Récupérez l'application ASGI via streamable_http_app + mcp_app = mcp.streamable_http_app() + + # Ajoutez les middlewares + mcp_app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"] + ) + mcp_app.add_middleware(AuthenticationMiddleware) + logger.info( f"Starting GeoGuessr MCP Server on {settings.HOST}:{settings.PORT} " f"with {settings.TRANSPORT} transport" diff --git a/src/tests/unit/auth/test_multi_user_session.py b/src/tests/unit/auth/test_multi_user_session.py index 9d4808f..eea2ac6 100644 --- a/src/tests/unit/auth/test_multi_user_session.py +++ b/src/tests/unit/auth/test_multi_user_session.py @@ -61,7 +61,7 @@ class TestMultiUserSessionManager: assert session is None @pytest.mark.asyncio - async def test_login_user_creates_manager_if_not_exists(self, manager, mock_http_client): + async def test_login_user_creates_manager_if_not_exists(self, manager): """Test that login_user creates a manager if it doesn't exist.""" # This test requires mocking the HTTP client for GeoGuessr API # We'll mark it as a placeholder for now