MCP 工具不显示?先排查 Schema 兼容性
文章整理 Claude Code、Cursor 等客户端拒绝工具 Schema 或不展示工具的相关报告,提供手动检查和脚本排查方法。内容区分已核实、用户报告与未确认信息,并提醒修复已知问题不代表所有客户端都会接受。
完整中文译文
MCP server 能启动,客户端也显示已连接,工具却不出现,甚至直到调用时才报 schema 无效。问题可能藏在根类型、JSON Schema 方言、描述长度或整个工具列表的体积里。
原文汇总了 Claude Code、Cursor 等客户端的相关报告,并区分了规范要求、已查到的原始 issue 和未经核实的用户说法。它最有用的结论是:服务启动、工具发现和实际调用,是三道需要分别验证的关卡。
先检查根类型,再排查复杂结构
最容易检查的一项,是每个 inputSchema 根部有没有 "type": "object"。
作者查到的案例发布在 Claude Code 仓库,但实际报错来自 Kilo CLI 1.0.23。出问题的 schema 在根部使用了 anyOf,没有声明根类型;客户端指向 ["tools",20,"inputSchema","type"],提示 Invalid input: expected "object"。
下面这份工具定义展示了同类问题:参数 q 有类型,包住参数的根对象却没有类型。
{
"tools": [
{
"name": "search",
"description": "Does one thing.",
"inputSchema": {
"properties": {
"q": {
"type": "string",
"description": "A text value."
}
}
}
}
]
}
要检查的是 inputSchema 这一层,不能因为 q 已经声明为字符串,就认为整份 schema 的类型信息齐全了。作者建议在根部补上 "type": "object"。无参数工具则可使用 { "type": "object" },或增加 "additionalProperties": false。
不过,这个案例不能推出「根部禁止 anyOf」。报错针对的是缺失的根类型,作者没有找到禁止根部组合关键字的官方说明。2026-07-28 版规范还放宽了限制,允许 inputSchema 和 outputSchema 使用任意 JSON Schema 2020-12 关键字。
规范措辞也要分清:作者读到的是 inputSchema 必须为有效且非 null 的 JSON Schema 对象,没有在正文找到「根部类型必须为 object」这句原话。规范中的无参数示例使用了 object,但示例和强制条款不能混为一谈。
因此,补根类型是有案例支持的排查动作;把 oneOf、anyOf 一律删掉,则缺少依据。作者建议必要时将分支放到属性内部,但也提醒:Oracle 的报告中,oneOf 已在 properties 内,某个客户端仍然失败。移动位置不是通用解法。
为什么改了 $schema,仍然可能报错
JSON Schema 方言,可以理解成校验规则使用的语言版本。$schema 声明了版本,具体关键字也必须遵循对应语义。
2025-11-25 版 MCP 规范规定,inputSchema 和 outputSchema 未填写 $schema 时,默认使用 2020-12。实现必须支持至少 2020-12;可以显式指定其他方言,但实现遇到不支持的方言必须报错。draft-07 是规范展示过的显式声明示例,却不代表所有客户端都支持它。2026-07-28 版仍默认使用 2020-12。
作者查到的 TypeScript SDK issue 745,就与生成器默认值有关:SDK 使用的 zod-to-json-schema 3.24.5 默认生成 draft-07,客户端却要求 2020-12。相关 diff 修改了 $schema URL。
另一个更容易误判的案例是 Claude Code issue 88882。作者在 2026-10-14 查看时,它仍处于开放状态:带 draft-07 声明的 outputSchema 被拒绝,错误明确表示默认校验器只支持 2020-12;但 tools/list 可以成功,失败发生在调用阶段。同一报告中,只有 draft-07 inputSchema、没有 outputSchema 的工具可以工作。
报告者认为问题在 Claude Code 2.1.220 到 2.1.229 之间发生回归,作者没有独立确认,也没有看到厂商回复。
处理时应同时检查输入和输出 schema。若不需要 draft-07,可删除其声明,让规范默认值生效,或改为 https://json-schema.org/draft/2020-12/schema。但随后还要检查关键字:draft-07 用 items 数组表达的元组,在 2020-12 中使用 prefixItems。
修改版本声明之后,还得检查 schema 的实际写法。
至于 Anthropic API 的 tools.N.custom.input_schema 报错,作者查到两份报告都要求匹配 2020-12,但没有确认具体触发结构。Oracle SQLcl 报告者怀疑 oneOf 的位置,同一工具在 Claude Desktop 可以工作;Pydantic Logfire MCP 的讨论没有点明原因。不能看到这条错误,就直接归咎于某个关键字。
工具消失,也可能是描述或列表太大
描述长度和整个列表体积,是两类不同问题。
关于 Claude Code 的 2048 限制,作者只读到了两份 issue 镜像,没有核实原始 GitHub 页面。报告称,工具描述以及 initialize 返回的 server instructions 会被截断到 2048 个 UTF-16 代码单元,也就是 JavaScript String.length 的计数方式,不是字节数。
报告还称,instructions 被截断时会有调试日志,工具描述被截断则没有日志。另一份报告将限制关联到 2.1.84,描述约 9,336 字符时,60 个函数只剩 15 个可见,并出现 ... [truncated]。
两份报告分别在 2026-05-06、2026-09-09 以「not planned」关闭;后续记录标记 v2.1.234 已解决某事,但作者无法确定具体修复范围。MCP 规范本身没有规定描述上限,因此不能把 2048 当作所有客户端的统一标准。
Cursor 的列表体积限制,证据更直接。论坛工作人员确认存在内部 payload 限制,超出后整个工具列表会被静默丢弃,表现为已连接、0 个工具。
案例中的 Stitch MCP 列表约 287 KB,大量体积来自重复的 outputSchema 和大型枚举。用户通过代理移除 outputSchema 后,列表缩到约 41 KB,工具随即出现。287 KB 失败、约 41 KB 成功,只是两个观察值,不能据此推算准确上限。
作者还给出一个免费 Python 脚本,只检查根类型 SL001、数组缺少 items 的 SL004、工具重名 SL007。下面的输出说明它如何定位根类型问题:
$ python3 mcp_schema_lint.py fixtures/bad/SL001-missing-type.json
mcp-schema-lint 1.0.0: fixtures/bad/SL001-missing-type.json
tools: 1, payload: 144 bytes
ERROR SL001 search/inputSchema: inputSchema has no type; set "type": "object"
1 error(s), 0 warning(s)
exit=1
需要看的是最后的 exit=1:存在错误时退出码为 1,否则为 0。数组缺少 items 只产生警告,因为作者没有找到客户端因此失败的报告。脚本也不覆盖方言、2048 截断或列表体积问题;检查通过只能说明这三条规则没有发现问题。
我的判断
这篇文章可取的地方,是没有把零散 issue 包装成 MCP 的通用禁令。尤其是区分「看过原始报告」和「亲自复现」:作者确认读到了案例,不代表作者对所有客户端做过实验。
对团队来说,这是一份排查清单,尚不足以作为兼容性矩阵。它没有给出统一测试环境,也没有对照数据证明移动 anyOf、缩短描述等改法在多少客户端上有效。部分建议属于工程经验,仍需在目标客户端验证。
我会优先修复根类型缺失、生成器方言配置等明确问题,再考虑简化结构。直接移除全部 outputSchema 虽然在 Cursor 案例中见效,却同时拿掉了输出约束;更合适的顺序是先找重复定义、大型枚举和冗长文本,再判断是否需要删减 schema。
原文还披露由 AI agents 阅读来源并起草。这个信息不直接决定结论是否可信,但结合镜像来源和未复现项,更应保留它已经标出的证据边界。
能拿来做什么
- 在 Node 或 TypeScript MCP 项目中,保存实际
tools/list返回的 JSON,检查根类型、重复工具名和生成器方言配置。不要只检查代码里的 Zod 定义,转换后的产物才是客户端实际收到的内容。 - 将验证拆成启动、发现和调用三个步骤,并记录客户端版本。特别是使用
outputSchema时,工具能被列出来之后,还要执行一次真实调用。 - 用 JavaScript
description.length检查描述长度,将关键用途、参数限制和调用条件放在前面。同时测量整个工具列表的 JSON 体积,优先压缩重复 schema、大型枚举和重复说明。 - 把脚本检查作为提交前的快速筛查,并保留目标客户端验证。对于数组缺少
items这样的警告,先判断是否符合工具设计,不要将它当作已经证实的兼容性故障。