我正在将所有 MCP 迁移至 Skills 模式,包括最后一个仍在使用的 Sentry MCP(译者注:Sentry 是主流的应用监控与错误追踪平台)。此前我已完全弃用 Playwright(译者注:微软开发的现代 Web 自动化测试与浏览器自动化框架),转而采用 Playwright Skill。
近一个月来,围绕“动态工具配置(dynamic tool loadouts)[1]”实现工具定义延迟加载的讨论颇为热烈。Anthropic 也在探索通过代码串联 MCP 调用的思路,这一点我也曾尝试过[2]。
我想分享自己在此过程中的最新思考,以及为何 Anthropic 提出的“延迟工具加载方案(deferred tool loading)”并未改变我对 MCP 的原有判断。希望这些见解能对他人有所启发。
01 什么是工具(Tool)?当 Agent 通过强化学习或其他方式接触到工具定义时,系统会鼓励它在适用场景下通过特定 token 输出工具调用。实际上,工具定义仅能出现在系统提示词(system prompt)中特定的工具定义 token 之间。历史经验表明,我们无法在对话中途动态引入新的工具定义。因此,唯一可行的方案是在对话启动时预先加载所有工具。
在智能体应用场景中,我们固然可以随时压缩对话状态或修改系统消息中的工具定义。但这样做的代价是丢失推理轨迹(reasoning traces)和缓存(cache)。以 Anthropic 为例,这将显著增加对话成本:相当于每次都要从头开始,不仅需支付完整 token 费用,还需承担缓存写入开销,而非直接读取缓存。
Anthropic 近期推出了一项创新功能——“延迟工具加载”(deferred tool loading)。我们仍需在系统提示词中提前声明工具,但这些工具不会在系统消息发出时立即注入,而是稍后加载。不过据我了解,这些工具定义在整个对话过程中必须是静态的——即对话开始时已确定所有可能存在的工具。 Anthropic 发现这些工具的方式完全依赖于正则表达式(regex)匹配。
02 与 Skills 的对比尽管支持延迟加载的 MCP 在理念上似乎更具优势,但在实际应用中,它需要在 LLM API 端进行大量工程化改造。相比之下,Skills 系统完全无需这些额外工作,且根据我的实践经验,其表现反而更为出色。
Skills 本质上是对现有功能及其说明文档路径的简要概述。这些信息会被主动注入到上下文之中。 因此,智能体能够在系统上下文(或上下文的其他位置)中明确知晓自身具备哪些能力,并获取到如何使用这些能力的“操作指引链接”。
关键在于,Skills 并不会将完整的工具定义加载到上下文中。 可用的工具集合保持不变:例如 bash 以及智能体已有的其他工具。Skills 所提供的,主要是关于如何更高效地运用这些工具的技巧与策略。
由于 Skills 主要传授的是如何更好地使用现有的命令行工具及类似实用程序,因此组合与协调这些工具的基本方式并未发生根本改变。而让 Claude 系列模型成为优秀工具调用者的强化学习机制,恰好能够有效应对这些新发现的工具使用方法。
03 MCP 能否转换为 Skills?这自然引出了一个关键问题:既然 Skills 效果如此出色,我能否将 MCP 完全移出上下文,转而按照 Anthropic 的建议,通过 CLI 来调用它?理论上可行,但实际效果并不理想。Peter Steinberger 开发的 mcporter[3] 便是其中一种实现方案。简而言之,该工具会读取 .mcp.json 配置文件,并将背后的 MCP 服务暴露为可供调用的命令行工具:
npx mcporter call 'linear.create_comment(issueId: "ENG-123", body: "Looks good!")'
从表面上看,这确实很像一个可供 LLM 调用的命令行工具。但核心问题在于,LLM 本身并不知晓有哪些工具可用——现在需要人工专门教导它。于是你可能会设想:为何不创建一些 Skills 来教会 LLM 使用这些 MCP 呢?但在我看来,这里存在一个根本性矛盾:MCP 服务器本身并无维持 API 稳定性的强烈意愿。它们越来越倾向于将工具定义压缩到极致,主要目的就是为了节省 token 用量。 这种做法虽然有其合理性,但却与 Skills 模式的设计初衷背道而驰。例如,Sentry MCP 服务器曾彻底将其查询语法切换为自然语言处理。这对智能体而言是一次重大改进,但我之前提供的使用建议反而成为了障碍,且未能及时发现问题所在。
这种情况与 Anthropic 的“延迟工具加载方案”非常相似:上下文中完全缺乏该工具的相关信息,我们必须手动创建说明摘要。我们过去对 MCP 工具采用的预加载方式,如今陷入了一个两难境地:描述内容既过于冗长,不适合预加载;又过于简略,无法真正指导智能体正确使用它们。 因此,至少基于我的实践经验,最终你仍然需要为通过 mcporter 或类似方式暴露的 MCP 工具,手动维护这些 Skills 摘要信息。
04 最省心的选择基于上述情况,我目前的结论是:我更倾向于采用最省心的方式,即让智能体以“技能”的形式自行编写所需工具。 这种做法耗时不多,最大的优势在于工具基本处于我的掌控之下。每当工具出现问题或需要新增功能时,我只需让智能体进行调整即可。以 Sentry MCP 为例——虽然我认为它可能是当前设计最出色的 MCP 工具之一,但我已经不再直接使用它了。一方面是因为一旦在上下文中预加载它,就会直接占用约 8k 的 token 容量;另一方面,我也始终无法通过 mcporter 使其稳定运行。现在,我让 Claude 为我维护一个对应的技能。诚然,这个技能可能存在不少缺陷,也需要持续更新,但由于是智能体自行维护的,整体效果反而更令人满意。
当然,这种情况很可能在未来发生变化。但就目前而言,手动维护技能库,并让智能体自行编写工具,已成为我的首选方案。我推测,基于 MCP 的动态工具加载终将成为主流,但要实现这一愿景,可能还需要协议层面的一系列改进,例如引入类似技能的摘要机制,以及为工具内置完善的使用指南。 同时我也认为,如果 MCP 能够具备更强的协议稳定性,将大有裨益。目前 MCP 服务器随意更改工具描述的做法,与那些已经固化的调用方式、README 文档以及技能文件中编写的外部工具说明很难保持兼容。
随时随地看视频