MCP 工具描述与 Agent Skills:各自负责什么

MCP 工具描述是附在一个可调用函数上的一句话:它做什么、接收什么、会不会改动东西。 它会随客户端发给模型的每一个请求一起送出,和其他每个工具的描述并排在一起。技能 则是一个里面放着 SKILL.md 的文件夹,装的是一套流程——先做这个,再检查那个, 另外那件事要先问过——而它的正文只有在模型判定你的请求与它匹配之后才会加载。

区别就只有这一点,而且这是关于文本何时进入上下文的区别,不是关于文本写了什么。 描述是入场费:所有描述你都得付,每一轮都付,一直付下去。技能的指令在用不上之前 是免费的。所以,一段在工具描述里根本站不住脚的文字——三百个词讲怎么清理积压的 会议录音——放在技能里就完全合理。

本文谈的是怎么决定你的每条指令该放在哪一层。如果协议本身对您还是新东西,可以先 看什么是 MCP 服务器把词汇过一遍,再看 MCP 与插件、传统集成的区别,了解 MCP 相对于旧的连接方式站在什么位置。

工具描述能说什么,不能说什么

在 MCP 规范里,工具定义是一个小而固定的结构。它带有 name、可选的、给人看的 titledescription、描述参数的 inputSchema、可选的 outputSchema,以及 annotations——描述工具行为的可选属性,比如它是否只读。客户端用一次 tools/list 调用取回整份清单,摆到模型面前,这正是 MCP 工具被称为由模型控制 的原因:模型根据对话自己挑一个。

这个结构只有一件事做得好:告诉模型某一次调用做什么,好让它挑对。另外三件事,它 在结构上就做不好。

它写不了顺序。 工具定义里没有任何地方能说“先调用 list_channels,再调用 share_to_channel,因为频道必须存在,而且要由用户来选”。每条描述都是一座孤岛。

它装不了多少东西。 每条描述都会出现在每个对话的每个请求的上下文里,包括那些 永远不会碰到这个工具的对话。一台有十五个工具、每个工具配一段文字的服务器,在 用户还没敲下任何字之前,就已经花掉了上下文窗口中相当可观的一部分。

它写不进您的判断。 “拿不准该让谁看到时,给录音打标签而不是分享出去”是一条 策略,不是对某个函数的描述。同一个工具,两个不同的团队会想要两条不同的策略。

协议里确实有一个泄压阀:客户端连接时,服务器可以返回一个 instructions 字符串, 客户端可以把它加进系统提示词——排在工具清单前面。这里适合放一段简短的说明:这台 服务器是什么、它连着什么、有什么要当心。但有两点提醒。它仍然是按会话计费的文本, 所以要写短。而且规范说的是客户端可以使用它,而不是必须,因此到底会不会真的 呈现给模型,各家客户端并不一样。

技能补上了什么

技能是一个包含 SKILL.md 的目录:先是带 namedescription 的 YAML frontmatter,然后是 markdown 写的指令。旁边还可以捎带别的东西——放可执行代码的 scripts/、放详细文档的 references/、放模板的 assets/——而代理只有在指令 把它指过去时才会拉取这些内容。

这种加载方式叫作渐进式披露(progressive disclosure),规范把它分成三个阶段:

  1. 发现。 启动时,代理只加载每个可用技能的 namedescription——预算 约为每个技能 100 个 token。足够判断它什么时候可能相关,仅此而已。
  2. 激活。 当任务与描述匹配时,代理把 SKILL.md 的正文完整读进上下文。建议 把它控制在大约 5,000 个 token 以内,主文件控制在 500 行以内。
  3. 执行。 随附的脚本和参考文件,只有在指令真的去取用时才会加载。

所以装二十个技能的代价,是二十条简短的描述。而拥有二十条冗长工具描述的代价,是 每一轮都要付出二十条冗长的工具描述。正是这种不对称,让这一层有了存在的理由。

这个格式并不绑定某个客户端。Agent Skills 由 Anthropic 开发,作为开放标准发布在 agentskills.io 上;那里的客户端展示列出了数十个读取同一个文件夹的产品,包括 Claude Code、Claude、ChatGPT 和 Codex、Cursor、VS Code、GitHub Copilot、 Gemini CLI、Goose、Roo Code、Kiro、Junie、Amp、Factory、Tabnine、 Snowflake Cortex Code 和 Databricks Genie Code。查证于 2026 年 8 月 14 日。

必填的 frontmatter 刻意做得很薄。name 最多 64 个字符,只用小写字母、数字和 连字符,并且必须与父目录名一致。description 最多 1,024 个字符,应当同时写清楚 这个技能做什么以及什么时候用它——因为代理判断要不要打开这个文件,全部依据就是 这一串文字。可选字段有 licensecompatibilitymetadata,以及处于试验阶段 的 allowed-tools

description 这个字段值得比人们通常给的更多用心。“帮忙处理会议记录”永远不会 稳定地匹配上任何东西;“检视并归置最近的录音——打标签、给说话人命名、把属于团队 频道的分享过去;当用户要求整理、分拣或补上落下的内容时使用”就会。

第三层:每个会话都加载的文件

在按次调用的描述和按需加载的技能之间,还夹着一层,两者都不是:代理在会话开始时 就读取的文件,无论您问的是什么。

AGENTS.md 是最朴素的一种——标准 markdown,没有必填字段,沿目录树向上读取最近 的那份文件。它自己的站点称有超过 60,000 个开源项目在用,并列出了 OpenAI Codex、 Google Jules 和 Gemini CLI、Claude 的各类代理、GitHub Copilot 的编码代理、 Aider、VS Code、Cursor、Zed、Warp、Factory、goose、Roo Code、Devin 和 Junie 的 支持情况。查证于 2026 年 8 月 14 日。

Cursor 规则是同一个思路,外加一个开关。它们以 .mdc 文件的形式放在 .cursor/rules 里,由 frontmatter 的三个字段决定每一条何时被纳入: alwaysApply: true 让它进入每一个聊天会话;写了 description,代理就自己判断 是否相关;globs 会在打开匹配的文件时把它挂上;三者都不设置,那这条规则只有在 您用 @ 提到它时才会到场。Cursor 同样支持 AGENTS.md,现在也直接支持 Agent Skills——技能放在 .cursor/skills/.agents/skills/——并提供了一个迁移 工具,把符合条件的动态规则和斜杠命令转换成技能。查证于 2026 年 8 月 14 日。

把上面这两段再读一遍,规律就清楚了:格式已经趋同,加载方式没有。如今大家都 读 SKILL.md。但 alwaysApply 规则和 AGENTS.md 里的一段文字作用于会话,技能 作用于任务,格式再兼容也改变不了这一点。

由此得到的实用结论,是一条比格式细节更值钱的经验法则:

放在哪 那里适合放什么 代价是什么
工具的 description 一句话:这次调用做什么、改了什么 每个请求,一直如此
服务器的 instructions 关于整台服务器的简短说明 用到这台服务器的每个会话
AGENTS.md、总是生效的规则 对这个仓库里每项任务都成立的事实 这个项目里的每个会话
SKILL.md 流程、策略、实例演示、需要拿捏的判断 只在任务匹配时

凡是篇幅长的、有条件的、只在部分情况下成立的,都进技能。人们最常踩的坑,是把 一百五十行针对某个产品的流程写进全局的 AGENTS.md,于是整个下午在改一个毫不 相干的后端时,这些内容都一直躺在上下文里。

放到会议记录上是什么样子

Speak-Y 自带一台 MCP 服务器,它是个不错的例子,因为两层在这里明显各做各的事。

工具描述覆盖的是那些调用:搜索录音,读取转写、摘要或待办事项,列出频道和标签 ——在应用运行时,还可以给录音打标签、重命名说话人、改标题、重新转写,或者把它 归入某个团队频道。每个工具都带一条注解,说明它是读取还是改动,正是这一点让客户端 可以在执行改动类操作前先问一句,也让 --read-only 成为一个开关,而不是一串需要 记住的工具名。读取是在您本机的库上就地完成的;改动类命令要经过正在运行的应用, 并在那里留下记录,这一点在什么让 MCP 写入权限变得安全 里讲得更细。

技能覆盖的是这件事本身。当您从设置 → 集成安装这个集成时,Speak-Y 会在服务器 配置旁边写下一个整理用的技能:面对一堆录音该从哪儿下手,什么时候打标签才是正确 答案、什么时候该用频道,哪些操作要先确认再执行。这些内容描述装不下,服务器的 instructions 字符串也不该去装。

它的写法也顺着加载方式的偏好。一份详细的文件只存在一个地方,每个客户端拿到的, 是用它自己能读的格式写的一小段指路——给 Claude Code 的是 SKILL.md,给 Cursor 的是一条 .mdc 规则,给 Codex 的是 AGENTS.md 里一段带标记的内容,给 Gemini CLI 的是 GEMINI.md 里同样带标记的一段。那些按会话加载的客户端只拿到指路,恰恰因为 它们是按会话加载的:您在调试别人的后端时,一百五十行关于会议记录的文字不该常驻。 这些段落夹在标记之间,所以重新安装只会替换那一段,文件的其余部分原样不动。

MCP 服务器本身在所有套餐上都免费,包括 Free。一键安装和各客户端的手动配置,都 记在 AI 助手(MCP)里。

实际怎么判断

三个问题,按顺序问。

这条指令描述的是一次调用吗?那它就是工具描述,应该只有一两句话。如果您发现 自己在写第三句,那您已经找到了一个技能。

它对每个会话都成立,与任务无关吗?那它可以放进 AGENTS.md 或一条总是生效的 规则——但要老老实实检查“与任务无关”这半句。“这个仓库用 pnpm”合格。“这是我们的 会议分拣流程”不合格。

它描述的是一套带步骤、选择或例外的流程吗?技能。请认真推敲 namedescription,因为全部的路由都由这两串文字完成;篇幅长的内容放到 SKILL.md 旁边的 references/ 文件里,而不是塞进它本身。

往便宜的方向弄错,您得到的是臃肿的上下文,以及在每个不相干的问题上更低的命中率。 往昂贵的方向弄错——把流程硬塞进工具描述——模型会在每一轮都读到您的策略,却仍然 可能不照做,因为描述会被当成某个函数的文档来读,而不是必须服从的指令。

如果想具体看到这个差别,最快的检验方法,是为一件您真的在反复做的事写一个技能, 再和您以前一遍遍粘贴的提示词比一比。 向 AI 询问会议的提示词是个不错的 候选来源:那些您运行过两次以上的,就是该写进文件里的。

FAQ

MCP 工具描述和技能有什么区别?

工具描述是附在一个可调用函数上的一句话,由服务器作者编写,作为工具清单的一部分随每个请求发给模型。技能是一个包含 SKILL.md 的文件夹,里面写的是一套流程:若干步骤、若干工具、需要拿捏的判断。在模型判定任务与之匹配之前,进入上下文的只有它的名称和描述。描述回答的是“这次调用做什么”,技能回答的是“这件事该怎么做”。

如果我的 MCP 服务器工具描述已经写得不错,还需要技能吗?

一次调用就能完成的任务不需要。需要技能的情形是:一件事要按特定顺序用到多个工具;两个工具之间该选哪个,取决于描述承载不了的上下文;或者你希望同一套流程在不同会话里被一模一样地重复。好的描述让每一次调用正确,技能让一连串调用保持一致。

SKILL.md 是只属于 Claude 的格式吗?

不是。Agent Skills 由 Anthropic 开发,并作为开放标准发布在 agentskills.io 上,那里的客户端展示列出了数十个采用者,其中包括 Claude Code、ChatGPT 和 Codex、Cursor、VS Code、GitHub Copilot、Gemini CLI、Goose、Roo Code、Kiro、Junie 和 Factory。查证于 2026 年 8 月 14 日。

AGENTS.md 和技能有什么不同?

AGENTS.md 就是普通 markdown,没有必填字段,代理会从目录树上最近的位置读取它,并且无论你问的是什么,它都会为整个会话加载。技能的正文只有在代理把你的请求与它的描述对上之后才会加载。两者都有用,但凡是篇幅长的都该放进技能,因为 AGENTS.md 的内容会在每一个会话里占用上下文,包括那些和它毫无关系的会话。

SKILL.md 应该写多大?

Agent Skills 规范建议主文件 SKILL.md 控制在 500 行以内、大约 5,000 个 token 以内,把详细的参考资料移到单独的文件里,让代理只在需要时才加载。名称和描述的预算约为 100 个 token,因为每个会话都要为这部分付出代价。