e2m2e.api.mcp.server#

MCP 服务:LLM 工具入口(ADR 0014)。

进程内库为主体 + CLI 薄包装 mcp-serve:create_server(facade) 函数 (进程内、可测试)+ e2m2e mcp-serve 子命令。一个 Facade 实例 = 一个 server。本模块是薄适配器:工具面、执行策略、帧契约的单一来源在执行核心 e2m2e.api.execution``(#601),这里只做 MCP 形状转换(信封 → ``CallToolResult)与 worker 子进程的异步泵。

依赖 [mcp] extra:本模块在缺 mcp 库时导入即失败,调用方(CLI)负责 给出安装提示。

Functions#

make_progress_reporter(→ Any)

把 MCP 请求上下文包成线程安全的进度回调(Facade 签名 (fraction, message))。

handle_list_tools(→ list[mcp.types.Tool])

列出工具(纯函数,便于测试)。

run_tool_in_worker(→ mcp.types.CallToolResult)

在 worker 子进程中执行长任务工具(#588 子进程隔离)。

handle_call_tool(→ mcp.types.CallToolResult)

调用工具并包信封(纯函数,便于测试)。

create_server(→ mcp.server.Server)

创建 MCP 服务器(绑定传入的 Facade)。

Module Contents#

e2m2e.api.mcp.server.make_progress_reporter(context: Any) → Any#

把 MCP 请求上下文包成线程安全的进度回调(Facade 签名 (fraction, message))。

客户端未在请求 meta 带 progressToken 时返回 None——零开销直通。 工具本体在 anyio worker 线程执行,而算法层回调可能从任意线程触发 (WSB 网格搜索的 Rust drainer 线程,见 spawn_progress_drainer), 因此投递走创建时捕获的 asyncio 事件循环(run_coroutine_threadsafe); e2m2e mcp-serve 经 anyio.run 默认 asyncio 后端,无运行中 asyncio 事件循环时同样返回 None。阻塞等待投递完成以施加背压并保持 通知顺序;投递失败静默吞掉——进度失败不得影响计算。

e2m2e.api.mcp.server.handle_list_tools(facade: e2m2e.api.facade.Facade) → list[mcp.types.Tool]#

列出工具(纯函数,便于测试)。

async e2m2e.api.mcp.server.run_tool_in_worker(facade: e2m2e.api.facade.Facade, tool_name: str, arguments: dict[str, Any], context: Any) → mcp.types.CallToolResult#

在 worker 子进程中执行长任务工具(#588 子进程隔离)。

请求经 stdin 一行 JSON 下发,进度/结果行经 stdout 回流(协议见 worker.py);注入的 Config 经 execution.worker_request_payload() 随请求下发(#601),子进程用它重建 Facade。等待全部走可取消的 await: MCP 请求取消(interrupt 模式取消 handler 作用域)与客户端断连(EOF 取消任务组)在此汇成同一处理——kill 子进程、shield 内收尸、重抛取消。 kill 只丢当前任务:catalog 落盘是一次性原子写(tmp + os.replace), 已入库记录不受影响。worker 异常退出(无结果行)译为 WORKER_CRASHED 结构化错误。

e2m2e.api.mcp.server.handle_call_tool(facade: e2m2e.api.facade.Facade, name: str, arguments: dict[str, Any], extra_kwargs: dict[str, Any] | None = None) → mcp.types.CallToolResult#

调用工具并包信封(纯函数,便于测试)。

执行委托执行核心(#601);extra_kwargs 是传输层注入的额外协作者 (如进度回调),核心按方法签名过滤,未接受的工具零影响。

e2m2e.api.mcp.server.create_server(facade: e2m2e.api.facade.Facade) → mcp.server.Server#

创建 MCP 服务器(绑定传入的 Facade)。

一个 Facade 实例 = 一个 server;工具清单在每次 tools/list 时由 Facade 纯派生,与 tool_inventory() 单一同源。注册走 add_request_handler (mcp 1.x/2.x 兼容:2.0 移除了装饰器 API)。

Args:

facade: Facade 实例。

Returns:

mcp.server.Server 对象(配合 mcp.server.stdio.stdio_server 运行)。