# main.py # 将 Materials CIF MCP 与 System Tools MCP 一起挂载到 Starlette。 # 关键点: # - 在 lifespan 中启动每个 MCP 的 session_manager.run()(参考 SDK README 的 Starlette 挂载示例与 streamable_http_app 用法 [1]) # - 通过 Mount 指定各自的子路径(如 /system 与 /materials) import contextlib from starlette.applications import Starlette from starlette.routing import Mount from system_tools import create_system_mcp from materialproject_mcp import create_materials_mcp from softBV_remake import create_softbv_mcp from paper_search_mcp import create_paper_search_mcp from topological_analysis_models import create_topological_analysis_mcp # 创建 MCP 实例 system_mcp = create_system_mcp() materials_mcp = create_materials_mcp() softbv_mcp = create_softbv_mcp() paper_search_mcp = create_paper_search_mcp() topological_analysis_mcp = create_topological_analysis_mcp() # 在 Starlette 的 lifespan 中启动 MCP 的 session manager @contextlib.asynccontextmanager async def lifespan(app: Starlette): async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context(system_mcp.session_manager.run()) await stack.enter_async_context(materials_mcp.session_manager.run()) await stack.enter_async_context(softbv_mcp.session_manager.run()) await stack.enter_async_context(paper_search_mcp.session_manager.run()) await stack.enter_async_context(topological_analysis_mcp.session_manager.run()) yield # 服务器运行期间 # 退出时自动清理 # 挂载两个 MCP 的 Streamable HTTP App app = Starlette( lifespan=lifespan, routes=[ Mount("/system", app=system_mcp.streamable_http_app()), Mount("/materials", app=materials_mcp.streamable_http_app()), Mount("/softBV", app=softbv_mcp.streamable_http_app()), Mount("/papersearch",app=paper_search_mcp.streamable_http_app()), Mount("/topologicalAnalysis",app=topological_analysis_mcp.streamable_http_app()), ], ) # 启动命令(终端执行): # uvicorn main:app --host 0.0.0.0 --port 8000 # 访问: # http://localhost:8000/system # http://localhost:8000/materials # http://localhost:8000/softBV # http://localhost:8000/papersearch # http://localhost:8000/topologicalAnalysis # 如果需要浏览器客户端访问(CORS 暴露 Mcp-Session-Id),请参考 README 中的 CORS 配置示例 [1]