fix: initialize MCP session_manager in lifespan and fix mount path
All checks were successful
ci/woodpecker/push/build Pipeline was successful

StreamableHTTPSessionManager requires its run() context manager to be
active before handling requests. Without it, every MCP call returned
RuntimeError: Task group is not initialized.

Also changed mount from /mcp to / (at end of route list) so the MCP
endpoint is accessible at /mcp rather than /mcp/mcp, matching the
sub-app's internal route structure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-02 19:11:48 -06:00
parent 6818da489e
commit 679fda8491

View File

@@ -77,6 +77,13 @@ async def stats() -> dict:
return s.model_dump(mode="json")
# Initialize the MCP sub-app early so session_manager is available for lifespan.
# streamable_http_app() creates a sub-app with a route at /mcp internally.
# Mounted at "/" (last in the route list), FastAPI routes take priority and
# requests to /mcp fall through to the sub-app — keeping the public URL at /mcp.
_mcp_app = mcp.streamable_http_app()
# ---------------------------------------------------------------------------
# FastAPI app
# ---------------------------------------------------------------------------
@@ -84,7 +91,8 @@ async def stats() -> dict:
async def lifespan(app: FastAPI):
logger.info("OpenBrain starting up")
await db.get_pool() # Warm the connection pool
yield
async with mcp.session_manager.run():
yield
await db.close_pool()
logger.info("OpenBrain shut down")
@@ -96,9 +104,6 @@ app = FastAPI(
lifespan=lifespan,
)
# Mount MCP server at /mcp (HTTP streamable transport)
app.mount("/mcp", mcp.streamable_http_app())
# ---------------------------------------------------------------------------
# REST endpoints (for direct API access and health checks)
@@ -126,3 +131,8 @@ async def api_recent(limit: int = 20, _: str = Depends(require_api_key)) -> list
@app.get("/v1/stats", response_model=Stats)
async def api_stats(_: str = Depends(require_api_key)) -> Stats:
return await brain.stats()
# Mount MCP sub-app at "/" last — FastAPI routes above take priority,
# /mcp falls through to the sub-app's internal /mcp route.
app.mount("/", _mcp_app)