Fix uvicorn to run for all types of transport

The previous approach of running uvicorn.run(mcp_app) directly bypassed
MCP's internal session management, causing 400 Bad Request errors when
MCP Inspector tried to reuse sessions.

Solution:
- Use mcp.run() with middleware parameter instead of uvicorn.run()
- Build middleware list using starlette.middleware.Middleware wrapper
- Pass middleware list to mcp.run(transport, middleware=middleware_list)
- This preserves MCP's session handling while applying our middleware

Benefits:
- Proper MCP session continuity for streamable-http transport
- CORS middleware still applies correctly
- Authentication middleware works as expected
- Debug logging middleware available when LOG_LEVEL=DEBUG

This fixes the 400 Bad Request error on the second POST request.
This commit is contained in:
Claude 2025-11-30 01:33:39 +00:00
parent e4a8748af5
commit dd9e178e72
No known key found for this signature in database

View file

@ -8,7 +8,6 @@ with automatic API monitoring and dynamic schema adaptation.
import logging import logging
import sys import sys
import uvicorn
from mcp.server.fastmcp import FastMCP from mcp.server.fastmcp import FastMCP
from starlette.middleware.base import BaseHTTPMiddleware from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.cors import CORSMiddleware from starlette.middleware.cors import CORSMiddleware
@ -48,7 +47,32 @@ class RequestLoggingMiddleware(BaseHTTPMiddleware):
def main(): def main():
"""Main entry point for the server.""" """Main entry point for the server."""
# Create the MCP server instance # Prepare middleware list
from starlette.middleware import Middleware
middleware_list = []
# Add request logging middleware for debugging (first in chain)
if settings.LOG_LEVEL == "DEBUG":
middleware_list.append(Middleware(RequestLoggingMiddleware))
# Always add CORS middleware for browser compatibility
middleware_list.append(
Middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
)
# Add authentication middleware if enabled
if settings.MCP_AUTH_ENABLED:
logger.info("Setting up authentication middleware")
middleware_list.append(Middleware(AuthenticationMiddleware))
# Create the MCP server instance with middleware
mcp = FastMCP( mcp = FastMCP(
"GeoGuessr MCP", "GeoGuessr MCP",
instructions=""" instructions="""
@ -82,33 +106,6 @@ def main():
# Register all tools # Register all tools
register_all_tools(mcp) register_all_tools(mcp)
# Get the ASGI application
if settings.TRANSPORT == "streamable-http":
mcp_app = mcp.streamable_http_app()
elif settings.TRANSPORT == "sse":
mcp_app = mcp.sse_app()
else:
logger.error("Unsupported transport: %s", settings.TRANSPORT)
return
# Add request logging middleware for debugging (first, so it logs everything)
if settings.LOG_LEVEL == "DEBUG":
mcp_app.add_middleware(RequestLoggingMiddleware)
# Always add CORS middleware for browser compatibility
mcp_app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Setup authentication middleware if enabled
if settings.MCP_AUTH_ENABLED:
logger.info("Setting up authentication middleware")
mcp_app.add_middleware(AuthenticationMiddleware)
logger.info( logger.info(
f"Starting GeoGuessr MCP Server on {settings.HOST}:{settings.PORT} " f"Starting GeoGuessr MCP Server on {settings.HOST}:{settings.PORT} "
f"with {settings.TRANSPORT} transport" f"with {settings.TRANSPORT} transport"
@ -128,14 +125,8 @@ def main():
"Users will need to login or provide a cookie." "Users will need to login or provide a cookie."
) )
# Run the server with the modified app (with middleware) # Run the server with middleware support
uvicorn.run( mcp.run(transport=settings.TRANSPORT, middleware=middleware_list)
mcp_app,
host=settings.HOST,
port=settings.PORT,
log_level=settings.LOG_LEVEL.lower(),
access_log=True,
)
if __name__ == "__main__": if __name__ == "__main__":