
Why synchronous @mcp.tool definition is not supported for parallelism?
快速结论:该问题确认是 mcp.server.fastmcp 中的一个 Bug。在 v1.x 版本中,以同步函数形式定义的 @mcp.tool 会直接阻塞事件循环,而不是像 anyio.to_thread.run_sync 那样被委托到线程池运行。该问题已在 main 分支(v2)中修复,如果需要回迁到 v1.x 行,请在 Issue 中告知。
问题场景
用户在 mcp.server.fastmcp.utilities.func_metadata.FuncMetadata.call_fn_with_arg_validation 中定义了一个同步的 @mcp.tool 函数。该函数被调用时,整个运行循环被阻塞,而不是像预期那样被移出事件循环以支持并发。用户基于 FastAPI 的并发模型产生了疑问,期望同步工具也能被后台线程化处理。
报错原文
# 核心位置位于 FuncMetadata.call_fn_with_arg_validation
if fn_is_async:
return await fn(**arguments_parsed_dict)
else:
return fn(**arguments_parsed_dict) # 此处直接阻塞事件循环
原因分析
这是 mcp.server.fastmcp 的一个已知 Bug。当工具函数被定义为同步函数时,代码直接调用 fn(**arguments_parsed_dict),而没有使用 anyio.to_thread.run_sync 将同步函数放到线程池中运行。因此,同步工具会阻塞整个异步事件循环,导致无法并行处理其他请求或工具调用。
维护者确认:“It’s not ‘FastAPI concurrency model’”,“This is a bug.”
环境排查
- SDK 版本:确认使用的是 v1.x 行(如 v1.0.x, v1.1.x 等),问题仅存在于 v1.x 版本。
- Python 版本:建议使用 Python 3.10 或更高版本,以确保
anyio兼容。 - 依赖版本:检查
anyio是否已安装,建议版本 ≥ 4.0。
解决步骤
- 升级到 v2(推荐优先尝试):将
mcp包升级到或迁移到main分支对应的 v2 版本。v2 版本在 #1909 中修复了同步@mcp.tool的问题,通过anyio.to_thread.run_sync将同步函数路由到线程池,不再阻塞事件循环。同时 #2380 将相同修复扩展到同步的resource和prompt处理器。 - 如果无法升级(仍使用 v1.x):
- 手动修改
FuncMetadata.call_fn_with_arg_validation中的同步调用逻辑,将return fn(**arguments_parsed_dict)替换为return await anyio.to_thread.run_sync(fn, **arguments_parsed_dict)(需要导入anyio)。 - 或者在 Issue 中回复“I need this backported to v1.x”,告知维护者需要回迁修复。
- 手动修改
- 替代方案(临时规避):将同步
@mcp.tool函数改为异步函数,如async def my_tool(...),以避免阻塞事件循环。
验证方法
1. 确认修复前,运行包含同步 @mcp.tool 的 MCP 服务,观察客户端发送多个并行请求时,第二个请求是否被阻塞直到第一个完成(使用 curl 或 MCP 测试工具)。
2. 应用上述解决步骤后,再次发送并行请求,确认多个同步工具调用可以同时执行且不相互阻塞。
3. 在同步工具函数内添加 print(time.time()) 或日志,验证调用时间戳是否有明显的阻塞间隔。


![[Request] Add DOS Kernel MCP server to the MCP marketplace](https://www.chat-gpts.plus/wp-content/uploads/2026/06/15740-03e4d016-768x403.jpg)
![[Bug]: nightly vO.24.0-427-g577c96bf2 In the "paptor" feature of the knowledge graph, it is impossible to switch to "entire library" – it re](https://www.chat-gpts.plus/wp-content/uploads/2026/06/13999-d3493c41-768x403.jpg)