Tips & Tricks · Parhum Khoshbakht

MCP Tool Search:我们如何延迟加载 12 万 token 的工具 schema

在任何工作开始之前,24 个 MCP 连接器就已经吃掉了我们大约 60% 的上下文窗口。打开 Tool Search 后,它降到了约 3K token。这是 /context 优化前后的输出,以及帮上忙的合并模式。

我们好几周都没注意到的隐藏成本

当您在 Claude Code 里安装一个 MCP(Model Context Protocol)服务器时,您会得到工具。很多工具。仅 GitHub MCP 服务器一家就提供 35 个 — 涵盖 issue、pull request、分支、评论、release、workflow run、deployment、安全告警等。

您默认还会得到的是:每个工具的完整 JSON schema 在会话开始时就被注入到上下文中。名称、描述、参数类型、枚举值、示例 — 全部,在您输入第一句提示之前。

我们在打造 Statnive 的过程中接入了 24 个 MCP 服务器。在我们的会话开始让人感觉憋屈之前,我们都没去想过这个成本。然后我们第一次跑了 /context

本文就是优化前后的对比、那个完成 85% 工作的开关,以及把剩余事情完成的另外三种模式。

/context 给我们看了什么

下面是任何优化之前 /context 输出的相关切片:

MCP 服务器工具消耗 token
GitHub35约 26,000
Slack11约 21,000
Jira约 20约 17,000
Playwright(浏览器自动化)21约 13,647
Context7(库文档)约 15约 8,000
其他 19 个连接器约 190约 50,000
MCP 总开销约 290约 135,000

那大约是整个 200K 上下文窗口的 67%,被花在我们这次会话也许根本不会用到的工具定义上。研究人员在别处记录的模式同样适用:MCP 工具的平均开销是每个工具约 500–710 token,而中等数量的连接器负载(24 个服务器)通常在任何工作开始前就消耗 48,000–120,000 token。最极端的有据可查的案例是 Docker 的 MCP 服务器:135 个工具,仅它一项就约 126,000 token。

我们只剩约 65K token 给真正的对话、系统提示、内置工具、我们的 CLAUDE.md、技能元数据,以及自动压缩缓冲区。这就是为什么一切都让人感觉憋屈。

Tool Search:那个完成 85% 工作的开关

Claude Code v2.1.7 交付了 MCP Tool Search。它不再在启动时注入每个工具的 schema,而是构建一个轻量的约 5K token 的索引,包含工具名和描述。任何具体工具的完整 schema 仅在 Claude 决定要调用时才加载。一旦加载,会在会话期间被缓存。

Anthropic 的内部测试显示从 134K 减少到约 5K token — 砍掉 85%。反直觉的是,MCP 评测的准确率反而上升:在同一基准上 Opus 4 从 49% 跳到 74%,大概是因为模型不再被它不需要的工具 schema 淹没。

当工具描述超过上下文窗口的大约 10%(约 20K token)时,Tool Search 会自动激活。在该阈值以下它保持关闭,假设您不需要它。我们远远高于这个阈值,因此它对我们始终是激活的。

启用后,我们的 /context 看起来截然不同:

来源之前之后
MCP 工具 schema约 135,000约 3,000(仅索引)
MCP 工具 schema(在使用了 4 个工具的会话中)约 135,000约 6,500(索引 + 4 个加载的 schema)
可用于工作的上下文约 65,000约 190,000

我们从不跳过的验证步骤:在会话开始时跑 /context,确认那一行说明工具 schema 已被延迟加载或 Tool Search 已激活。如果不是,您是在白白付费。

合并 CRUD 爆炸

Tool Search 是最大的单一杠杆,但如果单个工具的描述臃肿,或您的服务器暴露了几十个几乎完全相同的工具,它也帮不上忙。

我们使用一种在研究中称为 action-parameter consolidation(动作-参数合并) 的模式重构了我们的一个内部 MCP 服务器。原本用于 issue 管理的十工具 API:

create_issue, update_issue, delete_issue, list_issues, get_issue,
add_comment, update_comment, delete_comment, list_comments, get_comment

变成了一个工具:

manage_issues({ action: "create" | "update" | "delete" | "list" | "get",
                target: "issue" | "comment", ... })

一位开发者应用此模式的有据可查的成果:20 个工具从 14,214 token 降到 5,663 token减少 60%。模型仍能正确路由,因为 action 参数是枚举的,工具描述也列出每一个支持的操作。我们在自己的合并上看到类似结果:从约 9,800 token 降到 4,100。

即使有 Tool Search 延迟加载 schema,单个肥工具按需加载的成本也比十个瘦工具小得多,因为 schema 开销主要由重复的样板(类型定义、错误信封、分页模式)构成。

激进地修剪描述

同一枚硬币的另一面。工具描述里的营销腔花真金白银。

像这样的描述:

“Search the web using Tavily Search API. Best for factual queries requiring reliable sources and citations from authoritative web content. Handles complex topics with academic depth and provides comprehensive results with relevance scoring…”

87 token。同样的路由信号写成:

“Search using Tavily. Best for factual/academic topics with citations.”

12 token。在 290 个工具上,每条描述平均省 50 token 就是约 14,500 token。

我们使用的规则:描述应当帮助 Claude 决定是否调用这个工具,而不是营销这个工具。砍掉一切不会改变路由决策的内容。

我们什么时候让某个工具保持立即加载

少数工具我们希望立即加载,因为它们几乎在每个会话都会触发:

  • Read、Write、Edit、Grep、Glob、Bash — 内置而非 MCP,但原则相同:高调用频率证明值得始终加载。
  • 我们每次会话都会用到几次的两个 MCP 服务器 — 我们内部的发布工具和文档抓取服务器。它们的 schema 加在一起约 3,500 token;每会话按需加载 6+ 次的重新拉取延迟成本会高于立即加载省下的部分。

Tool Search 支持按服务器的「立即加载白名单」,正是为了这种情况。要精准使用 — 每一个立即加载的工具都是永久开销。

给输出设上限,否则它会反过来限住您

MCP 环境变量 MAX_MCP_OUTPUT_TOKENS 默认是 每个工具响应 25,000 token。对一个 200K 窗口、每轮一次工具调用来说够慷慨。当您有 24 个连接器、一轮里多个调用扇出时,这就是把上下文塞满原始 API 响应的稳妥方式。

我们把上限设为 4,000,并要求输出最重的几个服务器支持服务器端分页和「先返回摘要」的响应形态。一次 GitHub list-issues 调用现在返回前 20 条,并附带一个 has_more: true 标记和续接 token,而不是把 200 条 issue 全砸进上下文。模型需要时可以再要;通常它不需要。

对于复杂的多工具工作流,Programmatic Tool Calling(Claude 在沙盒环境中编写编排代码运行,仅最终结果进入上下文)在 Anthropic 关于研究密集型任务的内部测试中显示出约 37% 的 token 减少。我们将其用于一个工作流 — 一个调用 6 个文档服务器的问答 agent — 节省效果保持得很好。

偶尔使用的工具:CLI > MCP

反直觉但真实:对于很少使用的工具,shell 命令比 MCP 服务器更便宜。ghawsgcloudsentry-cliwp — 它们通过 Bash 工具执行,没有持久的上下文开销。Bash 工具描述(已加载)就是您要付的全部上下文。CLI 二进制的帮助文本仅在 Claude 读取它时才加载。

我们移除了三个很少使用的 MCP 服务器,并用 CLI 替代。仅这一项就省下了约 12,000 token 的基线开销。

盈亏平衡点大致是:这个工具是否在一次典型会话里被触发超过一次? 是 → MCP。否 → CLI。

我们没有优化的部分

  • MAX_MCP_OUTPUT_TOKENS 是按调用,而不是按会话。 一个表现不佳的服务器仍可能跨多轮淹没上下文。我们目前没有按会话的上限 — 这是 Claude Code 的功能请求,不是我们能本地修复的事情。
  • Tool Search 是开或关。 我们没法像给技能分层那样给 MCP 服务器分层。我们 24 个全部统一走 Tool Search。对一个我们几乎每个会话都用的服务器来说,立即加载其实更高效 — 但我们无法在不全局禁用 Tool Search 的情况下,单独让那一个服务器的 schema 立即加载。
  • 我们没有在自己的工作负载上仔细衡量路由准确度。 Anthropic 在 Opus 4 上 49% → 74% 的数字让人鼓舞,我们在实践中也没看到路由失败,但我们没有一套基准来证明在 Statnive 特定任务上延迟加载的效果与立即加载相当。

您今天就能照做的实操步骤

  1. 在一个全新的会话中跑 /context。看看实际加载了什么。
  2. 如果 MCP 工具 schema 超过约 20K token(窗口的 10%),Tool Search 应该已自动激活。从 /context 输出中验证。
  3. 审查您最重的三个连接器。Pareto 曲线很残酷 — 通常 3 个服务器消耗 60%+ 的 MCP 开销。
  4. 对您能掌控的任何 MCP 服务器进行 CRUD 爆炸合并。
  5. 为任何描述读起来像营销文案的工具修剪描述。
  6. 把偶尔使用的工具从 MCP 移到 CLI。
  7. MAX_MCP_OUTPUT_TOKENS 上限设到合理的每调用值(我们用 4,000)。

如果您想看更全的图景 — 这件事如何与 CLAUDE.md 优化技能分层一起带来乘法节省 — 请从这一系列的旗舰文章开始。

试试 Statnive

由一支关心每一个 token 去向的团队交付的隐私优先 WordPress 分析。从 WordPress.org 免费安装 Statnive — 您的数据留在您的服务器上。

免费获取 Statnive