MCP 与 Skill 的边界与成本
MCP 用于动态能力发现和跨客户端生态,稳定副作用用类型化服务工具;Skill 不是文档,安装它会改变未来任务的操作规程。
MCP 用于动态能力发现和跨客户端生态,稳定业务操作和副作用应该用类型化服务工具。Skill 不是文档——安装一个 Skill 会改变未来所有匹配任务的操作规程,它的风险等级接近引入一个依赖,而不是收藏一篇文章。
MCP 解决的是发现,不是调用
适用:跨进程或跨语言复用工具、接入第三方工具生态、多个 Agent Host 共用同一套能力、需要标准化的资源与提示发现。
该避免的场景同样清楚:同一进程里的普通函数、只服务一个项目的内部业务逻辑、低延迟核心路径、无法建立清晰授权边界的高风险操作。稳定业务操作和副作用用类型化服务工具;批量、可重跑、CI、编译、测试、迁移、健康检查用 CLI 和脚本。
判断标准只有一句:你要的是「运行时动态发现未知能力」,还是「可靠地执行一次已知操作」。前者是 MCP,后者不是。
MCP 的安全基线没有可选项
先看清责任在哪一侧:协议层从设计上就无法强制这些规则。规范自己写明,MCP 无法在协议层面执行安全原则,工具描述与标注应被视为不可信,除非来源可信;宿主必须在调用任何工具前取得明确同意 mcp-spec。换句话说,协议只负责把能力摆到台面上,「允不允许用、用到什么程度」这件事没有任何一层能替你兜底。
所以下面这些不是最佳实践,是宿主自己的责任:
HTTP MCP 走规范授权流程并做 token audience 校验;禁止 token passthrough,禁止把 token 放进 URL;全程 HTTPS;本地 MCP 安装要显示完整命令并拿到明确同意;每个 MCP Server 是独立信任域;按 Skill 或任务按需连接,不默认连接所有 Server。
「每个 Server 是独立信任域」最常被忽略。接了三个 MCP Server,等于把三段外部代码拉进你的信任边界,其中任何一个被攻破或行为异常,影响范围就是你给它的全部权限。本地安装那条同理——用户看到的是一行友好描述,实际执行的是一条完整命令。
MCP 的成本是常驻的
工具成本不只是执行,它包括 Schema 常驻 token、选择推理、参数构造、执行、结果注入,以及后续历史里反复携带。接满 Server 之后,光是 Schema 就能吃掉一大截窗口。
这个「一大截」有量级可查:仅仅 5 个 MCP Server 就可能引入数万 token 的工具定义,在 200K 窗口里还没开始对话就用掉近三成。Cursor 的缓解做法是把工具描述同步到本地文件夹,Agent 默认只看一份名称索引,需要时再查具体定义——A/B 测试显示,MCP 相关任务的总 token 消耗因此减少 46.9% ai-agent-book。
形态和数量是两个独立决策,别把它们混成一个。一条能力做成专用工具还是 Skill,决定的是每条常驻多少 token、参数怎么传、谁能改;一次把多少条摆在模型面前,是披露策略 ai-agent-book。两边的定价差得很远:接一个 MCP Server 是在运行时建连,它暴露的全部工具定义进入每一次会话的上下文;装一个 Skill 只是往磁盘拷一个文件夹,常驻的只有目录里的 name 和 description,便宜一到两个数量级。也正因为便宜,「全量常驻 Skill 目录」的可行边界比工具远得多——但那只放宽了披露这一侧,没有替你做出披露策略的选择。
所以必须为每个 Agent 设 Server 和工具白名单,统计每个 Schema 和结果的 token,把大结果存进 Artifact Store,绝不把所有已连接的 MCP 工具默认暴露给所有 Agent。反过来也成立:不能以成本为理由绕过权限、确认和审计要求。
Skill 是供应链,不是文档
供应链有四个阶段,各自需要独立的权限与审计:发现、安装、激活、执行。生产级 Skill 要有固定版本与 digest、明确的 owner、兼容矩阵、可执行脚本的审查签名、trigger eval 和回滚方案。
少任何一项,你都无法回答「线上这次行为变化是哪个 Skill 的哪个版本引起的」。
还有一层风险不在供应链而在语义:Skill 的本质是把外部内容当作指令加载的制度化形式。网页里的隐藏文本至少还要骗过一轮摘要,Skill 的内容是直接按指令生效的——第三方 Skill 里藏一条恶意指令,比藏在网页里有效得多。所以来源不明的 Skill 在安装前必须逐行读它的正文和脚本,像审查一段将要执行的代码那样审查它 ai-agent-book。
渐进式加载,以及什么值得做成 Skill
加载分三步:初始只加载名称和描述;任务匹配后加载完整 SKILL.md;需要时再读 references、scripts 和 assets。描述必须写清何时触发、何时不触发,并且要测误触发和漏触发。
写法上要把 description 当路由条件,不要当功能介绍——「何时该用我」比「我能做什么」重要得多。写成 "help with backend" 这类宽泛措辞,等于任何后端工作都能触发,路由必然失准;书里的建议是在描述里明确写出使用与不使用的边界,并附几条典型反例来压误触发 ai-agent-book。
规模是这套机制的硬约束:Skill 描述常驻 system prompt 的数量一多,即使前沿模型的质量也会开始退化,所以选择必须在加载之前发生,而不是把所有 Skill 平铺进去再让模型自己挑 langchain-stripe。
腾讯云用一个 Skill 撑起 C++ 到 tRPC-Go 的全量重构,是这套分层的完整样本:无注释的历史补丁、10 多个状态机分支散落在跨 4–5 个项目的调用链里,可以信的只有代码本身。他们把知识压成三层——Rule 限 100 行(编辑指定目录时自动注入规范)、SKILL.md 限 200 行(只写五阶段流程)、references 不限行数按阶段按需加载;把只有业务经验能定的取舍整理成选择题,每轮最多问 5 个,决定记进 clarifications.md 跨会话可还原;再加熔断阈值——同一错误连修 3 次不过就交人,测试自动修复循环最多 5 轮。结果是把依赖历史经验、动辄几天的重构变成可复现的流程 tencent-skill-refactor。
价值分层也由此清楚:通用公开技巧迟早被模型权重吸收,围绕它做的 Skill 贡献会退化到零。长期价值在 procedure、当前信息源、工具、策略、校验器、恢复路径和出处——需要持续更新、有组织归属或真实权限的 Skill 才是资产。
发布前按规范校验 frontmatter。Skill 规范只允许六个字段,多写的字段在有的工具里被静默忽略,在有的工具里直接报错——同一处错误在一个地方无声无息,在另一个地方大声失败,于是你以为生效的约束可能从来没生效。真实踩过的一处是写了 tools: Read, Write, Edit,那是给子 Agent 文件的字段不是 Skill 的,一个工具一声不响地跳过它,另一个工具的打包校验器直接拒绝 aase-egm。
Skill 正文:先讲为什么,再讲怎么做
正文的排布不是排版偏好,是给一个不知道全局的读者看的。一份 SKILL.md 读起来像给同事写的 runbook:开头一段说清这个 Skill 解决什么问题、产出什么,然后是硬规则、带勾选的步骤清单、每一步、反模式、最后是它在整个流程里的位置。
「这一步为什么存在」比「必须这样做」有用。模型知道理由,才能在步骤没覆盖到的情况下做对判断;只知道禁令,遇到清单外的情况就只能猜。反模式是多数 Skill 里最有价值的几行——它们是看过真实跑错之后写下来的,而步骤只能预防你预想到的错。
硬规则要放在最前面。长会话会被压缩,压缩之后只保留开头的一部分,靠后的内容等于没写。清单也有这个作用:一个能跑几天的会话,靠清单和状态文件知道自己在第几步。
references 和 assets 是两个不同的活。前者是给模型读来做判断的指导,后者是照抄进产出里的模板。分开放的原因不是整洁,是加载时机不同:指导在该读的时候读,模板在该用的时候用。还有一个容易忽略的约束——每个引用都要离 SKILL.md 只有一跳。模型顺着引用再点一层,很容易用扫的方式读完就漏掉关键部分。
严格程度跟着脆弱程度走
不是每句指令都该一样严。匹配的判据是这一步被软化之后会不会立刻出问题。
- 低自由度,原文照抄。 定调的那几句话、要复述的框架、要让模型对自己说的重置语。改写一点效果就变了——「你不太客气」和「把它撕碎」不是一回事。
- 中自由度,给模板。 产出物的骨架、台账的格式。字段名要对,内容可以按情况填。
- 高自由度,只给目标。 需要来回争论的那部分,比如访谈该问什么、哪里该追下去。这部分写不成步骤,写成步骤反而僵化。
一条指令写多严,问的是「软化它会不会立刻出问题」,不是「这条有多重要」。重要的判断常常可以只给目标,脆弱的口子必须一个字不改。
定调为什么值得一个字不改:模型被训练得乐于附和,你说「请批判性地审查」,它听到的还是客气版。用户在开场就把话说死——「我强烈感觉这段代码质量不行,请把它撕碎,告诉我它糟在哪」——改变的其实是这一轮里「有用」的定义:你已经声明自己期待坏消息,它再客气就是没完成任务。所以改写不是文风问题,是把承重墙换成装饰板。
该用脚本的地方,别用提示词
有些步骤不需要判断,需要每次结果都一样。这种就该是脚本。
理由有两个。脚本是执行的,不是读的——几百行的检查逻辑只有它的输出会进上下文,模型不为它付钱;提示词是每轮都要带着走的。脚本还每次都一样:让模型用 grep 找「连续十行没有注释」是做不到的,它每次都会即兴发挥,于是标注为「机械检查」的发现失去意义。
写给 Agent 的脚本和写给人的脚本有几个具体差别:不能有交互提问,Agent 答不了「确定吗」;--help 要能教会模型怎么用;退出码要有含义,让 Skill 能按码说下一步做什么;报错要说明下一步该运行什么,而不是「未找到」。
最后一条最要紧:脚本只测量,人来做决定。 检查门禁的脚本不应该自己去改门禁状态。测量的归脚本,裁决的归人——这个分工是整套方法里最能防住「模型为了跑完而放水」的一处。
Skill 的四层验证
- 对照实验:没有这个 Skill,模型也会做——那它的贡献是零
- 难度校准:太简单测不出差异,太难则两边都失败
- 轨迹追踪:Skill 在上下文里,但模型真的 follow 了吗
- 路径验证:结果正确,但有没有绕过关键校验步骤
后两层最容易被跳过,也最容易骗人。只看最终结果,会把「模型本来就做得对」记成「Skill 起作用了」。
