第六章 MCP:把能力接入协议化
Skill 解决的是系统内部的复用:一类任务反复出现时,系统怎样把局部经验收束成稳定协议,不再每次从工具原语重新拼装。但方法可以复用,并不等于能力已经可以迁移。能力仍然可能散落在不同宿主、不同工具栈、不同运行环境里:一个 Agent 会用,另一个 Agent 不会用;这个宿主已经接好了权限,另一个宿主还要重接一遍;同一套资源在本地能跑,换个环境又要重新适配。系统开始撞上的,不再只是"怎样复用方法",而是"怎样复用能力接入本身"。
MCP 可以先被理解成一层"能力接入协议"。Host 或 Agent 通过 MCP client 连接一个 MCP server;server 向外声明自己提供哪些 tools、resources 和 prompts,每个入口需要什么参数、返回什么结构、依赖什么权限;Host 根据这些声明把远端能力纳入自己的工具运行时,再在需要时发起调用。它不是让模型更聪明,也不是替模型写任务步骤,而是把"某个能力怎样被发现、授权、调用、返回结果"这件事从宿主私有实现里抽出来。
一个具体例子会更清楚。假设公司里有一套发布平台,Agent 需要回答"服务 X 最近一次发布是否安全"。没有 MCP 时,Claude Code、Hermes、OpenClaw、IDE 插件和飞书机器人都要各自接一遍发布平台 API:各自处理 token,各自写服务发现,各自定义 get_release_status 的参数和返回格式,各自决定错误怎么暴露。接成 MCP server 后,发布平台只需要暴露一组协议入口:list_services、get_release_status、read_deploy_config、query_recent_errors。不同宿主连接同一个 server,拿到同一组工具描述,在自己的权限上下文里调用。能力仍然属于发布平台,任务组织仍然属于 Agent;MCP 负责把两者之间的接线方式标准化。
这些工具在协议里不是一段自然语言说明,而是一组可以被宿主读取的结构化描述。简化后,大致像这样:
json
{
"tools": [
{
"name": "list_services",
"description": "List services visible to the current user.",
"inputSchema": {
"type": "object",
"properties": {
"keyword": { "type": "string" }
}
}
},
{
"name": "get_release_status",
"description": "Get the latest release status for a service.",
"inputSchema": {
"type": "object",
"required": ["service_id"],
"properties": {
"service_id": { "type": "string" },
"env": { "type": "string", "enum": ["boe", "ppe", "prod"] }
}
}
},
{
"name": "query_recent_errors",
"description": "Query recent error logs for a service.",
"inputSchema": {
"type": "object",
"required": ["service_id", "since_minutes"],
"properties": {
"service_id": { "type": "string" },
"since_minutes": { "type": "integer" }
}
}
}
]
}
Host 读到这些描述后,才知道模型可以请求哪些动作、每个动作需要哪些参数、参数是否合法。一次调用也不是"模型直接访问发布平台",而是 Host 通过 MCP client 向 server 发起 tools/call,例如调用 get_release_status 时传入 {"service_id":"svc_123","env":"prod"},server 再用当前身份去查发布平台,并把结构化结果返回给 Host。这样一来,模型看到的是一个稳定工具,Host 管的是调用边界,server 管的是权限和真实系统连接。
Skill 放在前面,是因为它先解决任务路径怎样沉淀;MCP 接着出现,是因为稳定任务往往还要依赖外部能力。Skill 把"上线前怎么排查风险"写成步骤、门禁和恢复策略,MCP 则让"查发布状态、读配置、查错误日志"这些能力可以被多个宿主一致接入。Skill 让方法可以复用,MCP 让能力可以共享。
#mermaid-svg-xFk2kj2NauD8Ha76{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xFk2kj2NauD8Ha76 .error-icon{fill:#552222;}#mermaid-svg-xFk2kj2NauD8Ha76 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xFk2kj2NauD8Ha76 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xFk2kj2NauD8Ha76 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xFk2kj2NauD8Ha76 .marker.cross{stroke:#333333;}#mermaid-svg-xFk2kj2NauD8Ha76 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xFk2kj2NauD8Ha76 p{margin:0;}#mermaid-svg-xFk2kj2NauD8Ha76 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xFk2kj2NauD8Ha76 .cluster-label text{fill:#333;}#mermaid-svg-xFk2kj2NauD8Ha76 .cluster-label span{color:#333;}#mermaid-svg-xFk2kj2NauD8Ha76 .cluster-label span p{background-color:transparent;}#mermaid-svg-xFk2kj2NauD8Ha76 .label text,#mermaid-svg-xFk2kj2NauD8Ha76 span{fill:#333;color:#333;}#mermaid-svg-xFk2kj2NauD8Ha76 .node rect,#mermaid-svg-xFk2kj2NauD8Ha76 .node circle,#mermaid-svg-xFk2kj2NauD8Ha76 .node ellipse,#mermaid-svg-xFk2kj2NauD8Ha76 .node polygon,#mermaid-svg-xFk2kj2NauD8Ha76 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xFk2kj2NauD8Ha76 .rough-node .label text,#mermaid-svg-xFk2kj2NauD8Ha76 .node .label text,#mermaid-svg-xFk2kj2NauD8Ha76 .image-shape .label,#mermaid-svg-xFk2kj2NauD8Ha76 .icon-shape .label{text-anchor:middle;}#mermaid-svg-xFk2kj2NauD8Ha76 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xFk2kj2NauD8Ha76 .rough-node .label,#mermaid-svg-xFk2kj2NauD8Ha76 .node .label,#mermaid-svg-xFk2kj2NauD8Ha76 .image-shape .label,#mermaid-svg-xFk2kj2NauD8Ha76 .icon-shape .label{text-align:center;}#mermaid-svg-xFk2kj2NauD8Ha76 .node.clickable{cursor:pointer;}#mermaid-svg-xFk2kj2NauD8Ha76 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xFk2kj2NauD8Ha76 .arrowheadPath{fill:#333333;}#mermaid-svg-xFk2kj2NauD8Ha76 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xFk2kj2NauD8Ha76 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xFk2kj2NauD8Ha76 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xFk2kj2NauD8Ha76 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xFk2kj2NauD8Ha76 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xFk2kj2NauD8Ha76 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xFk2kj2NauD8Ha76 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xFk2kj2NauD8Ha76 .cluster text{fill:#333;}#mermaid-svg-xFk2kj2NauD8Ha76 .cluster span{color:#333;}#mermaid-svg-xFk2kj2NauD8Ha76 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xFk2kj2NauD8Ha76 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xFk2kj2NauD8Ha76 rect.text{fill:none;stroke-width:0;}#mermaid-svg-xFk2kj2NauD8Ha76 .icon-shape,#mermaid-svg-xFk2kj2NauD8Ha76 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xFk2kj2NauD8Ha76 .icon-shape p,#mermaid-svg-xFk2kj2NauD8Ha76 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xFk2kj2NauD8Ha76 .icon-shape .label rect,#mermaid-svg-xFk2kj2NauD8Ha76 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xFk2kj2NauD8Ha76 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xFk2kj2NauD8Ha76 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xFk2kj2NauD8Ha76 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} discover / call
Host / Agent
MCP Client
MCP Server
Tools
Resources
Prompts
External Systems
1. 它不是另一个 Skill,而是另一条轴
MCP 要解决的,不是系统会不会调用某个工具,而是能力接入能不能摆脱宿主私有实现。没有 MCP,系统照样能把工具接进来,只是接法往往锁在宿主内部:某个 CLI 有自己的插件协议,某个 IDE 有自己的扩展接口,某个 Agent 框架又有自己的注册方式。这样能跑,但能力面被宿主边界锁死。一个 Agent 接好了文件系统、浏览器、数据库和企业内部服务,换一个宿主后往往还得重接一遍。真正拖住系统的,不是"工具能不能调用",而是"接线方式能不能搬走"。
接线方式一旦被抽成协议,系统共享的就不再是一段提示词,也不是某个任务经验,而是一个可描述、可授权、可调用的能力入口:它暴露哪些方法,需要什么参数,返回什么结构,在什么权限下工作。权限治理也更容易落到同一层。工具如果只是宿主私下接进去的内部函数,授权、隔离和信任边界会散在实现细节里;当它被提升成协议接口,系统就能在同一层回答"谁提供这个能力、谁可以调用、以什么方式调用、能返回什么范围的数据"。MCP 不会自动解决权限问题,但它把权限问题放到了更适合统一治理的位置。
Skill 复用的是处理路径,回答"这类任务以后按什么结构推进";MCP 复用的是能力接入,回答"这类工具和资源以后怎样被不同系统一致使用"。假设系统要按既定风格改写文档。做成 Skill 时,系统关心什么时候触发改写、要保留哪些事实、哪些边界不能越过、输出前要不要检查新增观点。它是一条任务协议。可如果改写还需要访问样例库、组织内文档、风格规范、受权限控制的共享知识库,问题就变成这些资源怎样稳定接入,并被多个 Agent 共用。前一部分是 Skill,后一部分是 MCP。
这个边界在鉴权场景里尤其清楚。一个 Skill 可以规定"先发起 SSO challenge,再保存 credential 路径,随后继续访问内部资源",甚至可以把相关脚本和检查逻辑放在同一个目录里。但真正提供 SSO、维护 token、校验权限、限制资源可见范围的,不是 Skill 文本本身,而是它调用的 CLI、MCP server、浏览器环境、credential store 或 Gateway。Skill 组织的是任务路径,MCP 和类似协议组织的是能力接入。
能力接入协议化,并不等于任务语义已经被定义。一个 MCP server 可以暴露"查服务列表""读配置""查发布状态"这类底层工具,也可以暴露"上线前风险扫描"这种高层任务入口。差别不在协议本身,而在谁把底层动作组织成了稳定任务语义。真正占住入口的,往往不是暴露接口最多的一方,而是能把复杂动作收束成高层任务的一方。
Skill 与 MCP 不是并列关系,而是沿着同一个工程压力继续展开:内部先长出高层任务结构,随后这些结构又会依赖外部能力,接入方式就必须避免被单一宿主锁死。MCP 不是比 Skill 更高一层的概念,而是另一条正交的轴:Skill 让系统更会做事,MCP 让系统更容易接入外部能力。前者处理任务怎样被组织,后者处理能力怎样被接入和共享。
2. 为什么它今天又变得重要
Skill 往往更显眼,因为它直接改变一次任务怎样推进,用户很快能感受到差异。MCP 处理的是接入层、共享层、治理层的问题,只有当系统变复杂、宿主变多、能力来源变杂时,矛盾才会变得刺眼。它没那么显眼,并不代表不重要,反而说明它处理的是更底层的工程矛盾。
复制一个接口,并不等于复制一套能力。别人可以写出相似命令,也可以暴露相似 API,却很难同时复制权限模型、身份体系、服务发现、审计链路、内部数据源、错误处理经验、CI / IDE / Agent 集成和持续更新机制。Skill 可以把步骤编排进任务协议,MCP 可以把部分能力接入标准化;真正让入口可靠运转的,是协议背后的运行网络。
OpenHarness 没有把 MCP 当成独立于工具面的神秘机制,而是把每个 MCP tool 适配成普通宿主工具,命名也展开成 mcp__server__tool 这种形式。它做的是把外部协议能力接进宿主已有的工具运行时。mcp_tool.py#L14-L36 同时,OpenHarness 又把 MCP 放进运行时 readiness 检查,和 auth、skills、commands、tools 一起判断当前环境是 ready、warning 还是 blocked。工程上关心的不是"是否宣称支持 MCP",而是"这套外部能力接入此刻能不能可靠工作"。README.md#L157-L158 README.md#L290-L302
hermes-agent 没有读取一份 server 列表后一次性注册完事,而是给每个 MCP server 维护连接生命周期对象 MCPServerTask:ready、shutdown、reconnect 这些会话状态,_rpc_lock、_refresh_lock 这些并发保护,以及对 tools/list_changed 的动态刷新处理,都在这一层完成。mcp_tool.py#L856-L1028 注册工具时也不是"来什么挂什么",而是先经过 include/exclude 过滤、名字冲突保护、描述扫描,再把远端能力映射成本地 registry 里的 prefixed tool,同时补上 resources 和 prompts 这类 utility tools。mcp_tool.py#L2658-L2763 MCP 的实现层含义不是多一个名词,而是系统真的要维护 transport、auth、registry、lifecycle 和动态变更。
MCP 不只把外部能力接进来,也可以把宿主内部已有能力反向暴露出去。OpenClaw 的 plugin-tools-serve.ts 把插件系统里已经注册好的工具打包成独立 MCP server,让别的会话和宿主也能使用。plugin-tools-serve.ts#L1-L17 plugin-tools-serve.ts#L25-L45 到了 mcp-http.ts,它又不是简单暴露一堆工具,而是按 session、account、owner token 解析请求上下文,再给出当前请求真正可见的 scoped tools。mcp-http.ts#L54-L80 权限治理更自然,是因为能力边界先被协议化;多个 Agent 或宿主更容易共享同一批能力,是因为接入层已经被单独抽出。
不是所有"支持动态扩展"的系统都会自然长成 MCP。pi-mono 的主路径不是 MCP-first,而是 extension、package、skill、prompt 这些宿主内扩展机制。它的动态装载能力很强,工具、命令、provider、资源都可以在运行时继续接入;但这些接入默认仍站在宿主内部,权限模型也更接近"默认信任扩展作者",而不是先抽出一层独立协议边界再统一治理。扩展性解决的是"还能接更多能力",MCP 解决的是"这套能力接法能不能被搬走、共享和治理"。前者可以很强,却仍然没有跨到后者。
A2A 和 MCP 都属于协议化基础设施,但协议化的对象不同。MCP 面向工具、资源、server 和权限边界,解决 Agent 怎样稳定接入外部能力;A2A 面向 agent identity、会话路由、消息往返和协作策略,解决多个 Agent 怎样彼此协作。前者更接近"我怎样接世界",后者更接近"我怎样接另一个 Agent"。一个系统完全可以同时拥有 MCP 和 A2A,但它们是两条正交轴,不是一层包住另一层。
Skill 和 MCP 针对的是不同重复劳动。没有 Skill,系统重复拼装任务路径;没有 MCP,系统重复拼装能力接线。前者浪费认知组织成本,后者浪费能力接入成本。只解决前者,不解决后者,就会出现"方法可以复用,但能力难以迁移";只解决后者,不解决前者,就会出现"能力可以共享,但任务仍然每次临场组织"。pi-mono 这样的系统还提醒我们,现实里存在第三种状态:能力接入已经很动态,但仍停留在宿主内扩展阶段,尚未上升成跨宿主协议。成熟的 Agent 系统通常会同时面对这三层压力。
MCP 的收益和代价来自同一个事实:它把能力接入单独抽成了一层协议边界。收益在于,能力更容易跨宿主迁移,权限更容易集中治理,多个 Agent 更容易共享同一套外部工具和资源,不必把接入逻辑重复埋进每个系统内部;代价在于,系统多了一层新的抽象边界。抽象边界带来复用,也带来复杂度:接口要定义,权限要处理,不同宿主之间的信任要判断,协议本身还要演化和兼容。更重要的是,MCP 只负责把能力接进来,不会自动告诉系统什么时候用、怎样组合用、失败以后回到哪里。这些仍然属于 Skill、规划、验证闭环和更高层运行时治理。MCP 不是 Skill 的替代,而是让 Skill 不再被宿主私有的接入方式绑死。
MCP 的价值不在于又多了一个新名词,而在于它把能力接入从宿主私事提升成可共享、可治理、可迁移的协议边界。 系统内部可以先长出任务协议;当能力不该只属于单一系统,接入方式也必须被协议化。
能力接入被标准化之后,新的问题变得更清楚:能力已经能接进来,系统怎样持续组织行动、吸收反馈、纠正路径,而不是在一次次调用中原地打转?