66from dotenv import load_dotenv
77from fastapi import FastAPI
88from fastapi .middleware .cors import CORSMiddleware
9+ from fastapi .responses import RedirectResponse
910from fastmcp import FastMCP
1011from fastmcp .server .openapi import RouteMap , MCPType
1112from uvicorn ._types import ASGI3Application , ASGIReceiveCallable , ASGISendCallable , Scope
@@ -115,13 +116,16 @@ def run():
115116 ),
116117 ]
117118
118- # Step 2: Convert to MCP and get http_app
119+ # Step 2: Convert to MCP and get both transport apps
119120 mcp = FastMCP .from_fastapi (
120121 app = temp_app ,
121122 name = "Neo4j Sandbox API MCP Server" ,
122123 route_maps = route_maps ,
123124 )
124- http_app = mcp .http_app ()
125+
126+ # Get both transport apps
127+ sse_app = mcp .sse_app () # For backward compatibility
128+ http_app = mcp .http_app () # Modern transport
125129
126130 # Step 3: Create combined lifespan
127131 @asynccontextmanager
@@ -145,11 +149,21 @@ async def combined_lifespan(app: FastAPI):
145149 app .add_middleware (ProxyHeadersMiddleware )
146150 app .add_middleware (SecurityHeadersMiddleware )
147151
148- # Step 5: Mount HTTP app at root
152+ # Step 5: Mount both transports for maximum compatibility
153+ # SSE app mounted at /sse creates routes at /sse/sse
154+ # To maintain backward compatibility, add a redirect from /sse to /sse/sse
155+ @app .get ("/sse" )
156+ async def sse_redirect ():
157+ """Redirect /sse to /sse/sse for backward compatibility"""
158+ return RedirectResponse (url = "/sse/sse" , status_code = 307 )
159+
160+ app .mount ("/sse" , sse_app )
161+ # HTTP at root (exposes /mcp endpoint) for modern clients
149162 app .mount ("" , http_app )
150163
151- logger .info ("MCP server available at:" )
152- logger .info (" - /mcp (HTTP transport)" )
164+ logger .info ("MCP server available at multiple transports:" )
165+ logger .info (" - /sse → /sse (SSE transport - backward compatible)" )
166+ logger .info (" - /mcp (HTTP transport - modern, recommended)" )
153167
154168 # Authentication Note:
155169 # - FastAPI routes use Depends(verify_auth) which handles both:
0 commit comments