Essay

MCP 与 Skill:一个接能力,一个教方法

By XiaoLeiJun

MCP 与 Skill:一个接能力,一个教方法

如果把 Agent 比作一位刚入职的同事,MCP 和 Skill 分别解决两个完全不同的问题。

MCP 为他接通公司的代码仓库、数据库、工单系统和浏览器,让他有地方取数据,也有工具做事情;Skill 则把团队的规范、流程、模板和经验交给他,让他知道面对一类任务时,事情应该怎样做

一个给工具和通道,一个给方法和章法。

这句话几乎概括了两者最重要的区别。但如果继续追问,就会发现它们又有一些相似之处:MCP 的工具描述会进入模型上下文,Skill 的元信息和正文也会进入模型上下文;它们都依赖 Agent Harness 做发现、加载、权限控制与结果回传。

也正因为如此,两者才经常被混在一起。

这篇文章不再分别实现 MCP 和 Skill,而是把它们放到同一条 Agent Loop 里,看清它们各自站在哪一层、解决什么问题,以及为什么真正好用的 Agent 往往两者都需要。

它们为什么会出现

MCP 和 Skill 并不是同一时期、为同一个问题设计出来的。

2024 年 11 月 25 日,Anthropic 开源了 Model Context Protocol。当时要解决的痛点很直接:AI 应用想连接 Google Drive、GitHub、数据库或本地文件,每接一个系统都要重新做一套私有集成。MCP 希望为 AI 应用与数据、工具之间建立一套开放协议。

2025 年 10 月 16 日,Anthropic 正式介绍 Agent Skills,并在同年 12 月把它发布为开放标准。它瞄准的是另一个问题:通用 Agent 即使已经能读文件、跑脚本,仍然缺少组织内部的流程、专业领域的经验,以及稳定可复用的工作方法。

它们的出发点可以压缩成两句话:

MCP:外部系统很多,怎样用统一方式接进来?
Skill:任务方法很多,怎样只在需要时教给 Agent?

要真正理解这个区别,还得先回到最朴素的工具调用。

一切都从 Agent Loop 开始

《从一次 LLM 调用到 Agent Loop》里,我们已经实现过最小工具调用。它的主干并不复杂:

Harness 把工具描述交给模型
-> 模型返回 tool_name + arguments
-> Harness 校验并执行工具
-> Harness 把执行结果写回 messages
-> 模型根据结果继续判断

模型不会因为看见工具描述,就凭空获得操作文件或访问数据库的能力。它做的只是生成一份结构化的调用意图

比如,Harness 给模型的工具定义可能是:

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "查询指定城市的实时天气",
    "parameters": {
      "type": "object",
      "properties": {
        "city": { "type": "string" }
      },
      "required": ["city"]
    }
  }
}

模型读懂这份 schema 后,可能返回:

{
  "name": "get_weather",
  "arguments": {
    "city": "上海"
  }
}

真正查询天气的,是模型外面的 Harness 和工具实现。

这里常被概括成“把工具描述拼到提示词里”。这个说法抓住了本质,但还不够严谨。不同模型 API 可能把工具放在独立的 tools 字段中,服务端也可能用专门的 chat template 序列化它,而不是直接追加到 system prompt 文本末尾。

不过从模型推理的角度看,关键事实没有变化:工具的名称、描述和参数结构,最终都要成为本次模型输入的一部分。模型先看见能力的说明,才能决定要不要调用它。

MCP 和 Skill 都会在这里出现,但它们进入上下文的方式并不相同。

先用一张图看清核心区别

MCP 与 Skill 所在的两层

MCP 连接 Harness 与能力提供者,Skill 则在任务匹配时进入模型上下文,指导模型怎样使用已有能力。

MCP 位于能力接入层

它让 Harness 不必关心工具住在本地子进程、远程服务,还是某个团队维护的公共系统里。Harness 通过 MCP Client 与 Server 初始化连接、发现能力、发起调用,再把结果转换成模型能继续理解的消息。

Skill 位于方法指导层

它把一类任务的说明、流程、示例和资源组织成一个可发现的目录。Agent 先看见简短元信息,判断当前任务是否匹配;只有真正需要时,才把完整说明加载进上下文。

所以,MCP 回答的是:

这个能力在哪里,我怎样调用它?

Skill 回答的是:

面对这类任务,我应该遵循什么方法?

MCP:把远端能力翻译成本地工具

MCP 采用 Host、Client、Server 架构。模型通常不会直接连接 MCP Server,真正建立连接的是 Agent 应用里的 MCP Client。

Model
  <-> Agent Harness / MCP Host
        <-> MCP Client
              <-> MCP Server
                    <-> 文件、数据库、API、业务系统

按照 MCP 官方架构说明,Server 可以暴露三类核心能力:

  • Tools:可以执行的动作;
  • Resources:可以读取的上下文数据;
  • Prompts:可复用的交互模板。

在常见 Agent 场景中,Tools 最直观,也最容易进入主循环。一次典型接入会经过下面几步。

第一步:初始化与能力协商

Client 与 Server 建立连接后,先通过 initialize 交换协议版本、身份与支持的能力。

这一步解决的是协议双方能不能正确对话,还没有轮到模型。

第二步:发现工具

Client 调用 tools/list,Server 返回工具目录:

{
  "name": "get_weather",
  "description": "查询指定城市的实时天气",
  "inputSchema": {
    "type": "object",
    "properties": {
      "city": { "type": "string" }
    },
    "required": ["city"]
  }
}

是不是很眼熟?

除了字段命名和外层包装不同,它与模型 API 里的 function tool schema 几乎是同一种结构:都有工具名、描述和 JSON Schema 参数定义。

这正是 Host 中 MCP 适配层的关键工作之一:通过 Client 取得 Server 的工具目录,再转换成当前模型 Provider 能理解的工具定义,注册进 Harness 的 Tool Registry。

第三步:模型提出调用

Harness 把转换后的工具 schema 交给模型。模型只知道这里有一个 get_weather,却不需要知道它来自哪个 Server、使用 stdio 还是 HTTP,更不需要自己生成 JSON-RPC。

第四步:Client 转发调用

模型产生普通的 tool call 后,Harness 先做参数校验、权限判断和审批,然后才由 MCP Client 发出 tools/call

{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "city": "上海"
    }
  }
}

Server 执行真实逻辑,把结果返回给 Client;Harness 再把结果写回模型消息栈。

因此,从模型视角看,MCP 工具和本地工具几乎没有区别;从 Harness 视角看,它们却隔着一条明确的进程或网络边界。

可以把 MCP Client 连同它的上层适配器理解成一位翻译兼联络员。它们屏蔽了 Server 地址、传输方式、JSON-RPC 请求 ID、生命周期和分页等细节,让上层 Agent Loop 继续使用统一的工具调用方式。

但“屏蔽细节”不等于“消灭复杂度”。超时、断线、认证、名称冲突、动态工具列表、未知副作用和多租户隔离,仍然要由 Host 与 Client 认真处理。这也是本地 MCP远程 MCP需要分别讨论的原因。

Skill:把完整方法藏在需要它的那一刻

如果 MCP 给了 Agent 一双手,Skill 更像是放在手边的一本工作手册。

根据 Agent Skills 规范,一个 Skill 至少是一个包含 SKILL.md 的目录:

weekly-report/
  SKILL.md
  references/
    metric-definitions.md
  scripts/
    validate_report.py
  assets/
    report-template.md

其中 SKILL.md 由两部分组成:

---
name: weekly-report
description: 生成项目周报。用于汇总进展、风险、指标和下周计划。
---

# Weekly Report

1. 先确认报告周期和项目范围。
2. 从任务系统读取本周完成项与阻塞项。
3. 指标必须给出数据来源和统计口径。
4. 按“摘要、进展、风险、下周计划”的顺序输出。
5. 发布前运行 scripts/validate_report.py。

frontmatter 里的 namedescription 用于发现,正文用于执行

Skill 最关键的设计不是目录,而是渐进式披露:

第一层:启动时只加载 name + description
第二层:任务匹配后加载完整 SKILL.md
第三层:执行过程中按需读取 references、scripts 和 assets

如果 Agent 安装了 100 个 Skill,它不需要一开始就吞下 100 份完整说明。元信息先告诉模型“书架上有哪些手册”;当前任务需要写周报时,再把 weekly-report/SKILL.md 真正翻开。

这和 MCP 的工具发现看起来有点像:两者都先展示一份轻量目录,再在需要时进入下一层。但下一层发生的事情完全不同。

  • MCP 的下一层是向 Server 发起协议调用;
  • Skill 的下一层是把任务方法与相关资源加载进上下文。

Skill 可以附带脚本,却不意味着 Skill 自己就是一种远程调用协议。脚本最终仍由 Harness 的执行环境或现有工具运行,仍然要接受沙箱、权限和审批约束。

换句话说,SKILL.md 可以写“发布周报前运行校验脚本”,但真正启动脚本的,依旧是 bash、代码执行器或别的工具。

关于按需加载的完整实现,可以回看《Skill 与按需加载》

为什么它们看起来如此相似

现在可以回答草稿里那个很重要的判断:说到底,它们是不是都在做提示词组装?

从模型边界往里看,确实有相似之处:

MCP Tool
  -> name + description + inputSchema
  -> 进入模型可见的工具集合

Skill
  -> name + description
  -> 匹配后把 SKILL.md 正文放进上下文

模型无法调用一份自己从未见过的工具,也无法遵循一份自己从未读过的 Skill。Harness 都要先把必要信息放到当前输入中。

但如果因此得出“MCP 和 Skill 都只是提示词”,就把观察范围缩得太小了。

MCP 除了让模型看见 schema,还定义了连接生命周期、能力协商、发现、调用、结果、通知与传输。它要处理的是一次真实的跨边界通信。

Skill 除了让模型看见说明,还定义了一种组织和分发任务知识的开放格式。它要处理的是可复用方法如何被发现、加载和执行。

更准确的说法是:

两者都会参与上下文组装,但 MCP 的主体是协议与能力路由,Skill 的主体是知识包装与渐进加载。

放在一起对比

维度MCPSkill
核心问题怎样连接外部数据与能力怎样复用一类任务的方法与经验
主要形态Client/Server 协议与 SDKSKILL.md 加脚本、资料、模板等目录资源
模型最先看见什么Tool、Resource、Prompt 的描述namedescription
需要时发生什么Client 调用 Server 的协议方法Agent 加载正文与相关文件
是否直接产生外部副作用Tool 调用可能会Skill 本身通常不会,执行其中步骤的工具可能会
典型位置Harness 与外部能力之间Harness 管理的模型上下文中
是否适合远程能力是,尤其适合共享服务不是远程通信协议,但可以从平台分发或安装
权限由谁控制Host、Server 与业务系统共同控制Harness 的工具权限与执行环境控制
一句话类比接口、插座、物流通道手册、SOP、老师傅的经验

还有一个经常被忽略的区别:MCP Server 是一个活着的能力提供者,它可以读取最新数据、执行操作并返回结果;Skill 更多是一份可版本化的任务资源包,它保存方法,但不会自动让外部世界发生变化。

最有价值的场景,是两者一起使用

假设用户对 Agent 说:

汇总最近三个月的客户工单,写一份服务质量报告,并发布到团队知识库。

只接 MCP,Agent 可能已经能调用:

search_issues
get_issue_detail
query_sla_metrics
create_knowledge_page

它有数据,也有发布能力。但它未必知道:

  • “最近三个月”按自然月还是滚动 90 天统计;
  • 重复工单怎样去重;
  • SLA 应该使用首次响应还是最终解决时间;
  • 哪些客户信息必须脱敏;
  • 报告需要哪些章节;
  • 发布前是否必须让人确认。

这些内容很适合放进 service-quality-report Skill。

MCP 与 Skill 协作完成一项任务

Skill 决定工作方法,MCP 提供数据与动作,Harness 在中间管理上下文、权限和结果。

一次完整运行可能是:

  1. Agent 从 Skill Catalog 发现 service-quality-report
  2. Harness 加载完整 SKILL.md
  3. 模型按照 Skill 的统计口径,通过 MCP 工具查询工单和 SLA;
  4. Harness 在每次调用前完成参数校验、权限检查与审计;
  5. 模型按 Skill 模板生成报告,并执行脱敏检查;
  6. 涉及发布副作用时,Harness 请求用户确认;
  7. 确认后,再通过 MCP 工具写入知识库。

这里谁也替代不了谁。

没有 MCP,Skill 只能告诉 Agent 应该查什么,却没有稳定通道取到工单;没有 Skill,MCP 只给了 Agent 一排按钮,却没有告诉它以什么口径、顺序和标准完成报告。

几个容易踩的坑

把所有操作说明都写进 Tool description

Tool description 应该说明工具做什么、何时使用、参数有什么约束,但不适合塞入一整套业务流程。

如果 query_sales 的描述里同时写着周报结构、指标口径、品牌语气和审批规则,它会越来越长,也无法被其他任务自然复用。工具契约留在 MCP,跨工具的任务方法放进 Skill,边界会更清楚。

把 Skill 当成权限配置

Skill 可以写“禁止读取生产密钥”,但这只是给模型的行为指导,不是强制安全边界。

真正的限制必须落在文件沙箱、工具 allowlist、MCP Server 授权、审批策略和审计系统里。模型即使忽略了 Skill,也不应该越过这些边界。

以为 MCP Server 暴露的工具都应该交给模型

tools/list 回答的是“Server 有什么”,不是“当前任务允许什么”。

更稳妥的流程是:

Server Tool Catalog
-> 部署级 allowlist
-> 当前用户权限
-> 当前任务真正需要的工具快照
-> 模型

能力越多,越不能把整个目录不加筛选地塞给模型。

把 Skill 当成模型训练

加载 Skill 不会改变模型参数。它只是把一份经过组织的说明和资源放进当前运行上下文。

所以 Skill 的效果取决于描述是否容易匹配、正文是否清晰、例子是否具体,以及 Harness 是否真的提供了完成步骤所需的工具与环境。

因为 MCP 也有 Prompts,就认为它等于 Skill

MCP Prompts 是 Server 暴露的可复用提示模板;Skill 则是面向 Agent 的任务资源包,可以包含多阶段说明、脚本、参考资料和资产,并强调渐进式加载。

二者存在交集,却不是同一个抽象。一个 MCP Server 可以提供 Prompt,一个 Skill 也可以指导 Agent 使用某个 MCP Server,它们不需要争夺同一个位置。

到底该选哪一个

遇到需求时,可以先问两个问题。

第一,Agent 是缺一双手,还是缺一套方法?

  • 需要连接数据库、代码仓库、CRM、浏览器或内部 API:优先考虑 MCP 或普通 Tool;
  • 需要复用审查流程、分析框架、输出模板、团队规范:优先考虑 Skill;
  • 既要访问外部系统,又要按固定流程完成任务:两者一起用。

第二,这件事是否值得被标准化?

一次性的简单要求,直接写在用户提示里就够了;稳定重复、需要团队复用的做法,才值得沉淀成 Skill。一个只在本进程里使用的小函数,也未必需要包装成 MCP Server;当能力需要跨进程、跨语言、跨产品或由独立团队维护时,MCP 的价值才真正显现。

可以用一张最短的决策表收尾:

缺数据或动作        -> Tool / MCP
缺流程或专业方法    -> Skill
只是一次临时要求    -> Prompt
既缺能力又缺方法    -> MCP + Skill

小结

MCP 与 Skill 都在扩展 Agent,但扩展的不是同一个部位。

MCP 把能力提供者接到 Harness 上,让模型可以通过统一工具接口触达外部世界;Skill 把经验组织成可发现、可按需加载的任务包,让模型在真正需要时获得一套方法。

它们最终都会影响模型上下文,却不能被简化成同一种“提示词技巧”:

MCP 解决“能力怎样进来”
Skill 解决“能力应该怎样使用”
Harness 负责让两者安全地一起工作

如果只记住一句话,那就是:MCP 让 Agent 做得到,Skill 让 Agent 做得对。