侧边栏壁纸
  • 累计撰写 15 篇文章
  • 累计创建 16 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

MCP、skill、subagent 该放哪一层——放错了就是白配

 劉豐
2026-11-04 / 0 评论 / 0 点赞 / 6 阅读 / 3,459 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2026-11-04,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

我一度在客户端里挂了 5 个 MCP server、79 个工具。它们工作得很好,直到我算了一笔账:

每一条消息,光是工具说明书就要先花掉 23,352 个 token。

而且是每条消息都花。哪怕我这次只是让它改一个 CSS 变量。

后来把这些东西重新分了三层,同样的能力,前缀从 23,352 token 降到 4,553(−81%),一个典型请求从 93k 降到 74k。这篇讲的就是“什么该做成 MCP,什么该做成 skill,什么该派给 subagent”的判据。


三层的成本模型完全不同

这是所有决策的基础。三者的差别不是“功能强弱”,是你为它付钱的方式:

常驻成本 调用成本 本质
MCP 全部工具的 schema,每轮都付 几乎为零 实时结构化能力
skill 一行 description(几十 token) 读正文时付一次 能力 + 步骤 + 坑
subagent 零 一次完整派发 上下文隔离

一句话判据:

  • 需要连一个“活的”东西(本地应用、远端 API、实时数据)→ MCP
  • 是一套“怎么做”的知识(步骤、参数、验收标准、踩过的坑)→ skill
  • 需要独立上下文 / 独立角色 / 不污染主对话 → subagent

最容易放错的是第二种。因为 MCP 也能“把知识做成工具”,看起来更工程化,但它的成本模型是最贵的——工具越多,每一轮越贵,跟你用不用没关系。


先算账:23.4k 是谁贡献的

79 个工具的 JSON schema 一共 89,091 字符,折算 23,352 token。按 server 拆开:

server 工具数 字符 占比 折算 token
A 40 45,448 51.0% ≈11,900
B 24 26,271 29.5% ≈6,900
C 10 9,713 10.9% ≈2,550
D 3 6,988 7.8% ≈1,830
E 2 671 0.8% ≈180

这张表改变了我两个判断:

一、不是“挂得多”的问题,是“挂了几个巨无霸”。 A 和 B 两个 server 就占了 80%。剩下三个加起来才 4.5k,其中 E 两个工具不到 400 token——留着完全不心疼。

二、判断该不该改,看的是“常驻成本 × 闲置率”,不是“工具多不多”。

B 那 24 个工具是我做设计稿还原用的。问题在于:我的设计工具桌面端没打开的时候,它照样每轮收我 6.9k。 我一周认真做两次设计,剩下五天在为它付费。

这就是典型的“该改成 skill 的场景”。


案例:把一个 MCP 降级成 skill

判据先立三条

满足其中两条以上,就该考虑改:

  1. 工具描述总量 > 2k token(低于这个不值当折腾)
  2. 有可直连的 REST/HTTP 层,不是纯私有协议黑盒
  3. 使用频率低,但 schema 常驻(闲置率高的最亏)

B 三条全中:6.9k token、底层是一组 /api/xxx 的 REST 调用、一周用两次。

做法:薄封装,不要重写

两种落地方式,我选了第二种:

方案 做法 代价
纯文档 正文手抄所有 API 路径和参数,需要时 curl 上游改接口就静默失效,跨调用状态要自己传
薄封装 skill 正文只写 xxx <tool> '<json>',背后一个几十行脚本 spawn 官方客户端做 initialize → tools/call → 退出 每次多 0.5–1s 初始化

薄封装的关键是不碰协议:还是用官方客户端,只是把它从“常驻 server”改成“一次性进程”。上游升级,脚本不用改。

实测数字

项 结果
命中本地包缓存启动 0.76–1.24s
强制走 registry 拉取 12.0s
真实调用返回 版本、变量、字体列表全部正常
未知工具 报 Tool not found,边界清楚
常驻成本 6.9k → 43 token(一行 description)

这里有个必须注意的点:npx -y pkg@latest 每次 12 秒。 因为它每次都要去 registry 解析版本。要进 1 秒内,脚本必须主动去探测本地缓存路径,命中缓存启动。这一步不做,你会得到一个“省了 token 但每次卡 12 秒”的方案,然后放弃它。

整体结果:MCP 前缀 79 工具 / 23,352 token → 15 工具 / 4,553 token,每请求省 18.8k,典型请求 93k → 74k(−20%)。其中 6.9k 来自这次改造,11.9k 来自直接撤掉那个 40 工具的 server。


subagent 的坑更多,而且更隐蔽

subagent(子代理)的价值是上下文隔离:派一个任务出去,它自己跑完,只把结论带回来,中间那堆文件内容和报错不进你的主对话。

但它有三个坑,都跟“你以为能配,其实配不了”有关。

坑一:tools 和 model 会被吞掉

如果你是通过统一配置下发生成的 subagent,生成的 frontmatter 只保留四个字段:

name: xxx
description: xxx
skills: [...]
mcpServers: [...]

tools: 白名单和 model: 钉都会被丢弃。

后果很实际:你想做一个“只读、不许改文件”的审查 agent,靠 tools: [Read, Grep] 限制——不生效,它照样能写。 想钉一个便宜的模型跑机械任务——也不会生效。

绕法只有一个:把职责约束写进 prompt 正文,用自然语言明确“你不允许修改任何文件,只输出结论”。这比配置约束弱,但至少是真的。

坑二:能不能被选中,只看 description

主模型决定要不要派子代理,唯一依据是 description 文本。

所以写法很关键:Use when …;不用于 …。后半句比前半句重要——没有“不用于”,它会到处乱派。

坑三:派发策略别写进常驻提示词

我试过在全局提示词里写一段“默认派子代理 + 档位表”,想让它每次自动分诊。实测效果很差,而且它每轮都占着常驻位置。

后来改成:策略放 skill,触发条件放 description。

skill 是“要不要派、怎么派”的方法论,需要时才读;description 是“什么情况下想到我”,永远只有一行。这正好对上三层的成本模型。


还有一个维度 MCP 根本没有:项目

我原本想让某个 MCP “只在某个项目里出现”。查下来发现做不到:

  • 统一 hub 的模式是每个 agent 一个全局 URL,工具集按 URL 里的 agent 名过滤,天然拿不到项目信息。
  • 所以 MCP 的分配只有“给哪些 agent”,没有“给哪些项目”。

试过一个取巧办法:写个 wrapper,脚本里判断当前目录在不目标项目里,不在就退出。在 hub 模式下不成立——因为 stdio server 是 hub 守护进程拉起的,$PWD 是守护进程的目录,不是你的项目目录。

真正能用的只有两条:

  1. 把它的 agents 清空(全局下线)+ 项目根放项目级 MCP 配置
  2. 彻底不用 MCP,改成 skill(skill 是按需读的,天然可以项目相关)

第 2 条又指回同一个结论:能用 skill 表达的,不要用 MCP。

另外项目级 MCP 的支持面很窄,实测:Claude Code 有(项目根 .mcp.json)、Gemini CLI 有,codex、workbuddy、codebuddy 这些都没有,只有用户级配置——只能“全局有”或“全局没有”。


收尾:一句话判据

配之前先问自己四个问题:

  1. 这东西需要连一个活的系统吗?不需要 → skill。
  2. 它的工具描述超过 2k token 吗?超过 → 算一遍常驻成本。
  3. 我一周用几次?低频 → 优先改成 skill,把常驻成本降到一行。
  4. 它需要独立上下文吗?需要 → subagent,但记住 tools/model 配不了,只能写进正文。

分层的本质是一笔账:常驻成本 × 使用频率。 高频且必须有实时能力 → 付常驻钱,值。 低频但能力强 → 改成 skill,用时再付。 需要隔离 → 派出去,别让它污染主对话。

最贵的配置不是“挂得多”,是挂了一堆一周用一次、但每轮都在收费的东西。

0
博主关闭了所有页面的评论