1. 从一次真实的困惑说起
很多人在 Claude 生态里第一次接触“外部能力扩展”时都会懵:
- 一会儿有人让你去写一个MCP Server;
- 一会儿又有人让你建一个叫Skill的文件夹,里面塞一个
SKILL.md。
两者看起来都能“让 AI 更强”,于是很容易被混为一谈。实际上,它们解决的问题完全不同:
- MCP(Model Context Protocol)是一门协议——它规定了模型和外部世界之间怎么“打电话”;
- Skills(Agent Skills)是一个能力包——它是一份写给模型的“说明书 + 工具箱”,告诉模型某类任务该怎么干。
一个更形象的类比:
- MCP 像USB-C 接口标准:只要设备遵循这个标准,就能插上任何外设;
- Skills 像一份工作手册/SOP 文件夹:里面写着步骤、注意事项,还附带几个可以直接运行的脚本。
下面我们先给结论,再从协议层、代码层和工程层逐一拆开,最后给出可运行的代码实战,以及两者如何配合使用。
2. 一句话结论与核心对比
MCP 解决的是“能不能调用外部能力”,Skills 解决的是“该怎么用这些能力把事办成”。
MCP 让模型长出新能力,Skills 让模型带着正确的使用方法。
核心对比表如下:
| 维度 | MCP | Skills(Agent Skills) |
|---|---|---|
| 本质 | 开放协议 / 接口标准 | 文件夹形式的能力包(指令 + 脚本) |
| 发布时间 | 2024 年 11 月 | 2025 年 10 月 |
| 解决的问题 | 模型如何调用外部工具 / 数据 | 模型如何按流程完成某类任务 |
| 运行时形态 | 常驻的独立 Server 进程 | 静态文件,按需加载进上下文 |
| 通信方式 | JSON-RPC 2.0(stdio / HTTP) | 上下文注入(Markdown / 脚本文件) |
| 提供的东西 | tools / resources / prompts | 过程性知识(SOP)、脚本、模板 |
| 跨生态程度 | 开放标准,跨模型、跨应用 | 主要服务于 Claude 生态,文件夹即插即用 |
| 类比 | USB-C 接口标准 | 说明书 + 工具箱 |
一句话记住它们的关系:MCP 是“连接方式”,Skills 是“做事方法”,二者经常配合使用。
3. MCP:一门真正的通信协议
MCP 的全称是 Model Context Protocol,2024 年 11 月由 Anthropic 开源,随后迅速成为事实上的开放标准,OpenAI、Google、Microsoft、阿里、字节等平台纷纷支持。
它的核心价值在于:以前每接入一个新工具,模型供应商都要写一套专用适配器;有了 MCP 之后,只需要按统一协议暴露能力即可“一次编写,处处接入”。
3.1 三层架构
MCP 定义了清晰的参与者:
- Host:宿主应用,比如 Claude Desktop、IDE 插件、你自己的 AI 应用;
- Client:运行在 Host 内部,负责与 Server 建立一对一的连接;
- Server:真正提供能力的一方,暴露工具、数据等资源。
3.2 三大核心原语
一个 MCP Server 可以提供三类能力:
tools —— 可执行的函数,模型可以“调用”它 resources —— 可读取的数据,模型可以“查阅”它 prompts —— 可复用的提示模板其中tools是最常用的一种,等价于 Server 向模型暴露出一个个可以被动态调用的新函数。
3.3 传输与消息格式
MCP 底层使用JSON-RPC 2.0通信,最常见的传输方式有两种:
stdio —— 本地子进程,简单可靠,适合本机工具 Streamable HTTP —— 远程服务器,适合部署成网络服务模型和 Server 之间交换的其实是标准 JSON 消息。一次“列出工具并调用天气查询”的完整对话大致是这样(按时间先后,注释仅作说明,实际消息不含注释):
// 1. 客户端初始化 {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"demo","version":"1.0"}}} // 2. 客户端询问:你有哪些工具? {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} // 3. 客户端调用 get_weather 工具 {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_weather","arguments":{"city":"北京"}}}可以看到,MCP 非常“协议化”:它定义的是消息格式、方法和传输规则,而不关心模型需要完成什么业务。
4. 代码实战一:手写一个 MCP Server
下面用 Python 官方 SDK 手写一个天气查询服务:暴露两个工具(tool)和一个资源(resource),再用客户端接上它。
4.1 安装依赖
pipinstall"mcp[cli]"4.2 服务端:weather_server.py
服务端使用官方 SDK 提供的FastMCP,通过装饰器即可把一个普通 Python 函数变成可供模型调用的工具。
# weather_server.pyfromdatetimeimportdatetimefrommcp.server.fastmcpimportFastMCP mcp=FastMCP("weather-demo")# 模拟一个天气数据库CITIES={"北京":{"weather":"晴","temp":22,"humidity":"40%"},"上海":{"weather":"多云","temp":26,"humidity":"65%"},"广州":{"weather":"阵雨","temp":30,"humidity":"80%"},}@mcp.tool()defget_weather(city:str)->str:"""查询指定城市的实时天气。city 支持:北京、上海、广州。"""ifcitynotinCITIES:returnf"暂不支持{city},当前支持:{', '.join(CITIES)}"info=CITIES[city]returnf"{city}天气:{info['weather']},气温{info['temp']}°C,湿度{info['humidity']}"@mcp.tool()defget_time()->str:"""获取当前服务器时间。"""returndatetime.now().strftime("%Y-%m-%d %H:%M:%S")@mcp.resource("weather://cities")deflist_cities()->str:"""返回支持查询的城市列表。"""return"\n".join(CITIES)if__name__=="__main__":mcp.run(transport="stdio")要点:函数的docstring 就是工具描述,模型会根据它来决定何时调用、如何传参。
4.3 客户端:weather_client.py
客户端以子进程方式拉起 Server,走 stdio 通道完成初始化、枚举工具、调用工具、读取资源。
# weather_client.pyimportasynciofrommcpimportClientSession,StdioServerParametersfrommcp.client.stdioimportstdio_clientasyncdefmain():server=StdioServerParameters(command="python",args=["weather_server.py"])asyncwithstdio_client(server)as(read,write):asyncwithClientSession(read,write)assession:# 1. 初始化握手awaitsession.initialize()# 2. 列出 Server 暴露的所有工具tools=awaitsession.list_tools()print("已发现工具:",[t.namefortintools.tools])# 3. 调用 get_weather 工具result=awaitsession.call_tool("get_weather",arguments={"city":"北京"})texts=[c.textforcinresult.contentifhasattr(c,"text")]print("天气查询结果:",texts[0])# 4. 读取一个资源res=awaitsession.read_resource("weather://cities")print("资源内容:",[c.textforcinres.contentsifhasattr(c,"text")])if__name__=="__main__":asyncio.run(main())运行结果大致如下:
已发现工具: ['get_weather', 'get_time'] 天气查询结果: 北京天气:晴,气温 22°C,湿度 40% 资源内容: ['北京\n上海\n广州']到这里,MCP 的本质已经很清楚了:它是一套协议,Server 把能力暴露成标准化的“工具”和“资源”,模型通过 JSON-RPC 去调用。
5. Skills:一份带给模型的操作手册
Skills(官方叫 Agent Skills)是 2025 年 10 月由 Anthropic 推出并开源的能力组织形式。它不是一个运行中的服务,而是一个文件夹。
一个 Skill 的典型结构如下:
term-report-skill/ # 技能目录 ├── SKILL.md # 技能说明书(核心) ├── scripts/ │ └── fetch_report.py # 可执行的辅助脚本 └── references/ └── report_template.md # 参考资料 / 模板(可选)核心是SKILL.md。它由两部分组成:
YAML frontmatter(元数据) —— 用 name + description 描述“这是什么、何时用” Markdown 正文(指令) —— 告诉模型“该怎么做”:步骤、注意事项、工具组合方式5.1 渐进式披露:Skills 的省 Token 机制
Skills 采用渐进式披露(progressive disclosure)策略:
- 只有 frontmatter 里的
name和description会一直保留在模型上下文中; - 当模型判断“当前任务需要某个技能”时,才把
SKILL.md正文加载进来; - 执行阶段需要跑脚本时,才真正去读取并运行
scripts/下的文件。
这样可以以极低的上下文成本,挂载几十个甚至上百个技能。
5.2 和 MCP 的本质差异
注意一个关键区别:Skill 里的脚本由模型决定“何时调用”,脚本本身并不是注册给模型的工具。Skills 给模型的是“过程性知识”——先做什么、后做什么、遇到什么情况怎么处理;而 MCP 给模型的是“声明性能力”——多了一个可以调用的函数或一个可以读的数据源。
6. 代码实战二:手写一个 Skill
我们写一个“术语调研报告”技能:当用户要求调研某个技术术语时,模型按 SKILL.md 的步骤执行,并借助附带脚本生成报告骨架。
6.1 SKILL.md
--- name: term-report description: 生成一份结构化的术语调研报告。当用户需要调研某技术术语、概念并输出报告时使用。 --- # 术语调研报告 ## 触发条件 - 用户说“调研 xxx”“出一份 xxx 的报告”“总结 xxx 的最新进展”。 ## 执行步骤 1. 明确调研对象和输出格式,默认输出 Markdown。 2. 使用可用的联网搜索能力,收集至少 3 个来源的信息。 3. 运行 `scripts/fetch_report.py`,把调研术语作为参数传给脚本,生成报告骨架。 4. 按 `references/report_template.md` 的组织方式填充正文。 5. 核对事实、标注来源,输出最终报告。 ## 输出要求 - 必须包含:定义、核心概念、典型用例、与相关概念的区别。 - 引用来源时保留原始链接。6.2 辅助脚本:scripts/fetch_report.py
#!/usr/bin/env python3"""把零散信息整理成一份标准报告骨架。"""importsysfromdatetimeimportdatedefbuild_skeleton(term:str)->str:returnf"""#{term}调研报告 > 生成日期:{date.today().isoformat()}## 1. 定义 (待补充) ## 2. 核心概念 (待补充) ## 3. 典型用例 (待补充) ## 4. 相关概念对比 (待补充) ## 5. 参考资料 (待补充) """if__name__=="__main__":term=sys.argv[1]iflen(sys.argv)>1else"未命名术语"print(build_skeleton(term))6.3 安装并触发技能
在支持 Skills 的客户端(以 Claude Code 为例)中,把文件夹复制到个人技能目录即可:
# 创建个人技能目录mkdir-p~/.claude/skills# 安装技能cp-rterm-report-skill ~/.claude/skills/term-report之后在对话里直接说需求,模型会根据description自动匹配并加载这个技能:
用户:调研一下 Agent Skills,出一份报告模型会识别出“调研 + 出报告”这一意图,加载term-report技能,并按照 SKILL.md 的步骤执行——包括调用fetch_report.py生成骨架。
可以看到:Skills 管的是“流程和方法”,脚本只是这个方法的一部分;它并不需要维持一个常驻 Server,也不需要实现 JSON-RPC 协议。
7. 核心区别逐条拆解
结合上面两个实战,我们把区别归为五条:
7.1 本质不同:协议 vs 内容包
MCP 是协议文件,规定了消息格式、方法和传输方式;Skills 是内容包,核心是写给模型的指令文本。前者是“标准”,后者是“素材”。
7.2 运行时不同:常驻进程 vs 按需加载
MCP Server 是一个真实运行的进程,模型需要实时连接它;Skills 只是躺在磁盘上的文件,需要时被读进上下文。
7.3 提供的东西不同:新能力 vs 新方法
MCP 的tools让模型多了一个可调用的函数;Skills 的SKILL.md让模型多了一套“怎么做”的知识。一个增加能力集合,一个增加知识集合。
7.4 通信方式不同:JSON-RPC vs 上下文注入
MCP 的每次交互都是结构化的 JSON 消息,有请求、响应、错误码;Skills 的生效方式是普通文本注入上下文,由模型自行理解和执行。
7.5 生态定位不同:跨模型标准 vs Claude 原生包
MCP 是开放协议,已被多家模型厂商和大量工具平台采纳;Skills 目前主要围绕 Claude 生态(Claude Desktop、Claude Code、Claude API),但文件夹式的设计让它天然轻量、易分发。
8. 代码实战三:让 Skills 编排 MCP
两者并不对立,真正生产级方案常常是:用 MCP 提供底层原子能力,用 Skills 定义业务编排流程。
下面设计一个“竞品分析”场景:
- 通过 MCP 挂载网页抓取和搜索工具(
web_fetch、web_search); - 用一个 Skill 规定完整的分析流程,指明“第几步该调用哪个 MCP 工具”。
整体关系如下:
对应的SKILL.md可以这样写:
--- name: competitor-analysis description: 对指定竞品进行结构化分析并产出对比报告。依赖 web-fetch MCP 服务器。 --- # 竞品分析 ## 前置条件 - 当前环境已挂载 web-fetch MCP 服务器,提供 `web_fetch` 与 `web_search` 两个工具。 ## 执行步骤 1. 使用 MCP 工具 `web_fetch` 依次抓取各竞品官网首页。 2. 使用 `web_search` 查询各竞品近期的融资、产品更新动态。 3. 把收集到的信息填入 `references/compare_template.md` 的对比表。 4. 运行 `scripts/score.py`,对价格、易用性、生态等进行加权评分。 5. 输出 Markdown 报告,并附上全部数据来源链接。 ## 输出要求 - 对比维度不得少于:定位、核心功能、定价、优劣势。 - 引用数据必须标明来源与抓取时间。在这个例子里:
- MCP负责“能不能抓网页、能不能搜信息”;
- Skill负责“先抓什么、再搜什么、如何评分、最终输出什么”。
这就是它们最典型的配合方式:能力由 MCP 提供,流程由 Skills 沉淀。
9. 什么时候用谁:一张决策清单
| 你的需求 | 选择 | 原因 |
|---|---|---|
| 接入数据库、浏览器、Git、外部 API 等系统 | MCP | 需要实时连接与标准协议 |
| 让模型掌握一套固定流程 / 领域 SOP | Skills | 指令 + 脚本,按需加载,成本低 |
| 需要给模型增加一个“原本没有的函数” | MCP | Server 通过 tools 暴露新能力 |
| 模型已有工具,但需要知道“怎么组合着用” | Skills | 提供过程性知识 |
| 追求跨模型、跨平台的通用能力 | MCP | 开放协议,生态最广 |
| 只在 Claude 生态内快速沉淀、分享经验 | Skills | 一个文件夹即可分发 |
实操中还有几个实用的组合原则:
1. 原子能力用 MCP 沉淀成稳定接口; 2. 业务流程用 Skills 沉淀成可复用 SOP; 3. 尖括号包住的是“怎么做”,JSON-RPC 包住的是“调什么”。10. 总结
回到最初的问题:Skills 和 MCP 到底什么区别?
- MCP 是一门协议:它规定了模型如何通过标准化的 JSON-RPC 消息,去调用外部工具、读取外部资源。它让模