Skip to content

Commit d591fbb

Browse files
committed
fix: Open DB connection on server startup not only on MCP client connection
1 parent 2d1b21e commit d591fbb

1 file changed

Lines changed: 28 additions & 2 deletions

File tree

server/main.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
from contextlib import asynccontextmanager
55
from typing import AsyncIterator
66

7+
import uvicorn
78
from mcp.server.fastmcp import FastMCP
9+
from starlette.applications import Starlette
810

911
from server.config import settings
1012
from server.embeddings.bm25 import BM25SparseProvider, close_sparse_embedding_provider
@@ -51,15 +53,29 @@ async def lifespan(_: FastMCP) -> AsyncIterator[None]:
5153
logger.info("semcode MCP server stopped.")
5254

5355

56+
# For streamable-http we drive the Starlette app's lifespan ourselves (see main),
57+
# so the per-MCP-session lifespan would re-init the store on every client connect.
5458
mcp = FastMCP(
5559
"semcode",
5660
instructions="Semantic code search across microservices codebases. Supports Go, Java, Python, and TypeScript/React.",
57-
lifespan=lifespan,
61+
lifespan=lifespan if settings.mcp_transport != "streamable-http" else None,
5862
host=settings.mcp_host,
5963
port=settings.mcp_port,
6064
)
6165

6266

67+
def _wrap_http_lifespan(app: Starlette) -> None:
68+
original = app.router.lifespan_context
69+
70+
@asynccontextmanager
71+
async def combined(scope_app: Starlette) -> AsyncIterator[None]:
72+
async with lifespan(mcp):
73+
async with original(scope_app):
74+
yield
75+
76+
app.router.lifespan_context = combined
77+
78+
6379
def main() -> None:
6480
from server.tools.search import register_search_tools
6581
from server.tools.index import register_index_tools
@@ -77,7 +93,17 @@ def main() -> None:
7793
register_system_prompts(mcp)
7894
register_http_routes(mcp)
7995

80-
mcp.run(transport=settings.mcp_transport)
96+
if settings.mcp_transport == "streamable-http":
97+
app = mcp.streamable_http_app()
98+
_wrap_http_lifespan(app)
99+
uvicorn.run(
100+
app,
101+
host=settings.mcp_host,
102+
port=settings.mcp_port,
103+
log_level=mcp.settings.log_level.lower(),
104+
)
105+
else:
106+
mcp.run(transport=settings.mcp_transport)
81107

82108

83109
if __name__ == "__main__":

0 commit comments

Comments
 (0)