实地笔记 · 2026-07-13
作者:Sujay · 以下每一个数字均可从提交的运行数据复现
Agent不会读取你的服务器代码。它们通过三个字符串来选择工具:工具的名称、描述以及参数模式。这就是全部的接口。如果两个描述存在重叠,Agent就靠猜。如果某个描述没有写明"这也会创建父目录",那么Agent就会调用它四次。这些错误中的每一个都会让人觉得你的服务器不可靠。
我构建了Toolmetry来回答一个简单的问题:如果你只修改描述,其他什么都不变,Agent的表现能提升多少?
方法
- 为每个服务器编写10–18个逼真的场景(一个提示词 + 一个设计良好的服务器应触发的工具 + 预期的参数)。
- 每个场景在真实Agent循环中针对在线服务器运行5次;记录每一次实际工具调用。
- 对三项指标评分:命中率(正确的工具?)、参数正确性以及额外调用(是否用不必要的调用填充了任务?)。"严格成功" = 三项同时达标。
- 将失败案例 + 当前描述输入给一个LLM重写器。在内存中应用重写后的描述——服务器本身不会被修改。
- 重新测量。仅在可测量出改进时才保留重写内容。丢弃退步的情况。
Agent:gpt-oss-120b(故意选了个中等水平的Agent——下文会解释原因)。重写器:Kimi K2。本文所有内容的API总花费:约4美元。
结果
| 服务器 | 严格成功率 | 变化 |
|---|---|---|
| official sqlite server | 34.0% → 100% | +66.0 |
| official memory server | 61.8% → 96.4% | +34.5 |
| official git server | 75.0% → 96.7% | +21.7 |
| official filesystem server | 74.4% → 84.4% | +10.0 |
出现了三种不同的失败原型,而描述重写全部解决了这三种情况:
1. 错误工具混淆(记忆服务器)。
知识图谱记忆服务器具有 create_entities、add_observations、search_nodes、open_nodes 等功能——而基线代理在 20% 的情况下会混淆它们。重写器添加了明确的“当……时请改用 X”交叉引用。命中率从 80% 提升至 100%。
2. 习惯性额外调用(SQLite、Git)。
SQLite 代理在三分之二的查询之前都会调用 list_tables + describe_table——即便是“有多少用户?”这样的问题。只需一句话(“不要仅仅为了在查询前检查表是否存在而调用此工具”)就将额外调用率从 66% 降为零。严格成功率:34% → 100%。
3. 废弃别名陷阱(文件系统)。
文件系统服务器自带一个已废弃的 read_file,但其描述仍看起来像主要工具。代理们总是掉进这个陷阱。解决方法:将“已废弃”作为第一个词,并指明替代工具。
让我感到意外的部分
我改用 Claude Haiku 4.5 作为代理运行了同样的优化。它的基线(84.4%)大致相当于中等模型优化后的分数——而优化仅使其提升了 +2.2 个百分点。
更好的代理可以绕过你糟糕的描述。而较弱的代理做不到。 这意味着描述质量恰好是对人们用于高吞吐量工作的代理——那些廉价、快速的代理——征收的税。如果你的 MCP 服务器“在廉价模型下不稳定”,这可能就是原因,而这只需不到一美元即可修复。
另一个诚实的发现:LLM 重写结果方差很大。 对同一基线的两次独立重写尝试分别得到了 +10.0 和 −2.2 分。你无法一次性搞定——你必须测量,而且必须愿意丢弃一次重写。(Toolmetry 的循环会自动完成这一操作;在本次运行期间,它两次丢弃了回归结果。)
无需分叉即可交付
重写后的描述保存在一个 JSON 文件中。toolmetry proxy 包装任意 MCP 服务器,并即时重写其 tools/list 响应:
npx mcp-toolmetry proxy --overrides best.json -- uvx mcp-server-sqlite --db-path ./my.db
将 MCP 客户端指向这个代理而非原始服务器。无需分叉,无需修补,一行命令即可撤销。
注意事项——因为没有注意事项的数据就是营销
- 每个场景N=5次测试,将比率量化为20点步长;请信任聚合结果,而非单个场景的增量差异。
- 场景编码了基准真值;存在争议的
expected_tool会产生有争议的度量指标。所有51个场景都在仓库中——请自行评判。 - 增量是智能体特定的(参见Haiku的结果)。请使用你实际服务的智能体层级进行测量。
- 某些失败是工具设计问题,任何描述都无法修复。按场景生成的报告会明确指出这些问题。