快速结论:这个报错发生在 MCP Python SDK 2.x 中,当工具返回值是自引用(递归)Pydantic 模型时,工具列表 schema 缺少根级 type: "object",导致旧协议(2025-11-25)的 tools/list 校验失败。优先确认是否是递归返回类型并升级到包含修复的 SDK 版本。
适用环境:MCP Python SDK 2.x(main 分支,Issue 验证于 b2025ab8、0d921927、57394b0 等提交),CPython 3.12.13,使用内存 Client(MCPServer) 路径。
最快修复方案:暂无确认的一步修复方案(截至 Issue 关闭时,修复位于外部分支 Parker-Fawcett/fix/3337-recursive-tool-output-schema-object-root,尚未确认合入主分支)。可优先尝试检查是否使用了递归 BaseModel 或 TypedDict 作为工具返回类型,并关注 SDK 后续版本更新。
注意事项:Issue 中提出的修复方案(在 FuncMetadata.model_post_init 阶段将裸 $ref 包装为 {"type": "object", "allOf": [{"$ref": ...}], "$defs": ...})仅在本地分支验证,尚未合并,属于“可能有效的方案”而非官方确认。是否将单个工具的 schema 问题降级为仅影响该工具而不是整个列表失败,仍是未决的设计问题。
问题场景
用户在使用 MCP Python SDK 2.x 创建工具服务器(MCPServer)时,某个工具函数的返回类型为递归/自引用的 Pydantic 模型(如 class Node(BaseModel),且 children: list["Node"])。当客户端以旧协议模式(mode="legacy",对应 2025-11-25 协议版本)连接并调用 tools/list 时,整个工具列表操作失败,客户端收到错误,而不是只影响那个递归工具。
报错原文
ValidationError: 1 validation error for ListToolsResult
tools.0.outputSchema.type
Field required [type=missing, input_value={'$defs': {'Node': {...}}, '$ref': '#/$defs/Node'}, input_type=dict]
MCPError: Handler returned an invalid result
server logs "handler for 'tools/list' returned an invalid result"
原因分析
可能原因:当工具返回类型是递归/自引用的 Pydantic 模型时,Pydantic 发出的输出 schema 是 {"$defs": {...}, "$ref": "#/$defs/Node"},根位置没有 "type": "object"。这在 2026-07-28 协议版本下没问题,但 2025-11-25 协议版本要求 Tool.outputSchema 根级必须有 type: "object"。因此,在旧协议协商下序列化 tools/list 结果时校验失败,且失败影响的是整个列表,而不是单个工具。
Issue 中还指出,在 main 分支上,递归 BaseModel 返回类型受影响;PR #3331 将 TypedDict 返回原生交给 Pydantic,因此递归 TypedDict 也会出现同样问题(此前手工构建的镜像模型恰好内联了根类型)。
环境排查
- 确认 MCP Python SDK 版本为 2.x(
main分支,Issue 观测于b2025ab8、0d921927、57394b0等提交)。 - 确认 Python 版本(Issue 验证环境为 CPython 3.12.13)。
- 检查是否有工具函数的返回类型为递归
BaseModel(如children: list["Node"])或递归TypedDict。 - 确认客户端连接方式:是否使用
mode="legacy"(对应 2025-11-25 协议),以及是否可以通过内存Client(MCPServer)复现(Issue 中验证了该路径)。
解决步骤
- 先定位工具服务器中是否有递归/自引用的返回类型定义,例如:
class Node(BaseModel): name: str children: list["Node"] = [] - 检查使用的 MCP Python SDK 版本,并查看是否有已发布的修复版本(Issue 关闭于 2026-08-24,建议升级到该日期之后的最新版)。
- 如果无法升级,可优先尝试参考 Issue 中验证过的修复思路(尚未合并到主分支,仅供参考):在 schema 生成阶段(
FuncMetadata.model_post_init,即StrictJsonSchema推导处),当 Pydantic 发出根级是裸$ref且目标$defs条目是object类型时,发布为:{"type": "object", "allOf": [{"$ref": "#/$defs/Node"}], "$defs": {…}} - 注意:不要改变非递归、非对象类型的 schema(如
RootModel[list[...]]),只修复原本就损坏的递归对象场景。 - 如果不需要旧协议兼容,可以考虑强制客户端使用新协议(不加
mode="legacy"),但这不是根治方案。
验证方法
确认修复有效的方法是:在修复后,同时用 Client(mcp)(新协议)和 Client(mcp, mode="legacy")(旧协议)调用 tools/list,两者都应成功,且两种协议下返回的递归工具 structuredContent 一致。同时确认现代会话(2026-07-28)下非递归工具的 schema 与修复前完全一致,不受影响。建议补充回归测试:递归 BaseModel 返回的精确 schema 单元测试,以及两种协议下 tools/list 都成功的端到端测试。
参考来源
modelcontextprotocol/python-sdk #3337
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


![[bug]: Model Library](https://www.chat-gpts.plus/wp-content/uploads/2026/08/9468-2093c507-768x403.jpg)