最近在使用 OpenCode、Browser Control 等 AI Agent 工具时,经常会同时看到几个概念:
- Skill
- MCP
- MCP Server
- Tool
- Agent
刚开始接触的时候,很容易把 Skill 和 MCP 混为一谈。
例如安装 Browser Control 时,既需要安装 Skill,又需要配置 MCP:
Browser Control
├── Skill
├── MCP
├── Driver
└── Chrome Extension
那么问题来了:
Skill 和 MCP 到底有什么区别?为什么一个能力需要同时存在 Skill 和 MCP?
本文不从复杂的 MCP 协议规范讲起,而是自己做一个非常简单的“天气查询”例子,通过这个例子理解 Skill 和 MCP 的关系。
一、先给结论
如果只记住一句话,可以记住:
MCP 提供能力,Skill 告诉 AI 如何使用这个能力。
或者换一种更直观的说法:
MCP = 工具
Skill = 工具使用说明
Agent = 使用工具的人
例如我们做一个天气查询能力。
MCP 提供:
get_weather(city)
Skill 告诉 AI:
用户询问天气时,
应该调用 get_weather。
不要自己猜测天气。
获取结果以后再回答用户。
最终关系:
AI Agent
│
┌─────────┴─────────┐
│ │
▼ ▼
Skill MCP
│ │
告诉 AI 怎么用 提供实际工具
│ │
└─────────┬─────────┘
▼
外部系统
下面我们自己实现一遍。
二、先认识 MCP
MCP 的全称是:
Model Context Protocol
它可以理解成一个让 AI Agent 使用外部工具和数据的标准化协议。
例如我们有一个天气服务:
天气服务
│
├── 查询天气
├── 查询未来天气
└── 查询空气质量
如果直接给每一个 AI Agent 单独开发接口:
OpenCode → 天气 API
Claude → 天气 API
自己的 Agent → 天气 API
每个 Agent 都需要单独适配。
MCP 的目标之一就是提供一个统一的工具接口:
MCP
│
┌───────┼────────┐
▼ ▼ ▼
OpenCode Claude 自定义 Agent
│ │ │
└───────┼────────┘
▼
Weather MCP
│
▼
天气服务
所以 MCP 更关注:
“AI 有什么工具可以调用?”
三、创建一个最简单的 Weather MCP
下面做一个非常简化的 MCP Server。
创建目录:
mkdir ~/weather-demo
cd ~/weather-demo
创建:
weather-mcp.py
写入:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather-demo")
@mcp.tool()
def get_weather(city: str) -> str:
"""查询指定城市的天气。"""
data = {
"北京": "晴,25°C",
"上海": "多云,27°C",
"广州": "小雨,30°C",
}
return data.get(city, f"暂时没有 {city} 的天气数据")
if __name__ == "__main__":
mcp.run()
这里最重要的是:
@mcp.tool()
def get_weather(city: str) -> str:
这段代码向 MCP 暴露了一个 Tool:
get_weather(city)
因此 MCP Server 可以告诉 Agent:
我有一个工具:
名称:
get_weather
参数:
city: string
功能:
查询指定城市的天气
四、MCP 到底提供了什么?
假设 Agent 连接了这个 MCP Server。
它就能够发现:
Tools
└── get_weather
└── city: string
然后 Agent 可以调用:
get_weather("北京")
MCP Server 返回:
晴,25°C
整个过程:
AI Agent
│
│ get_weather("北京")
▼
Weather MCP
│
▼
get_weather()
│
▼
"晴,25°C"
│
▼
AI Agent
注意一个非常重要的问题:
MCP 并没有告诉 AI 什么时候应该调用 get_weather。
它只是提供了这个工具。
五、这时候 Skill 出场了
现在我们创建一个 Skill。
创建目录:
mkdir -p ~/.config/opencode/skills/weather
创建:
~/.config/opencode/skills/weather/SKILL.md
内容:
---
name: weather
description: 查询天气时使用 weather MCP
---
# Weather Skill
当用户询问天气时:
1. 使用 `weather-demo` MCP 的 `get_weather` 工具。
2. 不要自己猜测天气。
3. 获取工具结果后,告诉用户城市和天气。
4. 如果 MCP 没有该城市的数据,明确告诉用户暂时无法查询。
## 示例
用户:
北京今天多少度?
操作:
调用:
get_weather("北京")
然后根据工具返回的结果回答用户。
这就是一个 Skill。
注意:
Skill 里面没有:
Python
HTTP API
数据库
天气数据
MCP Tool 实现
它本质上是一份:
给 AI Agent 阅读的使用说明。
六、现在 Skill 和 MCP 就联系起来了
到这里,我们有两个东西:
Weather Skill
告诉 AI:
什么时候使用天气能力?
怎么使用?
有什么注意事项?
以及:
Weather MCP
提供:
get_weather(city)
它们的关系:
AI Agent
│
┌─────────┴─────────┐
│ │
▼ ▼
Weather Skill Weather MCP
│ │
│ │
“应该怎么用” “实际能做什么”
│ │
└─────────┬─────────┘
▼
get_weather()
这就是 Skill 和 MCP 最核心的关系。
七、用户发出一个请求
现在用户对 AI 说:
北京今天多少度?
AI Agent 首先需要理解用户的意图。
Skill 告诉它:
这是一个天气问题。
应该使用:
get_weather(city)
然后 MCP 告诉它:
我有:
get_weather(city)
于是 AI 调用:
get_weather("北京")
MCP 返回:
晴,25°C
最后 AI 回答:
北京今天晴,25°C。
完整流程:
用户
│
▼
“北京今天多少度?”
│
▼
AI Agent
│
┌──────────┴──────────┐
│ │
▼ ▼
Skill MCP
│ │
“这是天气问题, “我提供
应该调用天气工具” get_weather”
│ │
└──────────┬──────────┘
│
▼
get_weather("北京")
│
▼
MCP Server
│
▼
“晴,25°C”
│
▼
AI Agent
│
▼
“北京今天晴,25°C”
八、如果没有 Skill,会发生什么?
这是理解 Skill 作用的一个好方法。
假设我们只有 MCP:
AI Agent
│
▼
Weather MCP
│
└── get_weather()
AI 仍然能够发现:
get_weather(city)
所以它有能力查询天气。
但是它不知道项目作者希望它:
什么时候使用?
是否应该优先使用?
如何验证结果?
遇到错误怎么办?
应该怎么组织操作?
当然,强大的 LLM 很可能自己就能推断出来。
例如它看到:
get_weather(city)
大概率会理解:
“用户问天气的时候,我应该调用这个工具。”
但是这属于模型自己的推理,而不是明确的工作规范。
九、有了 Skill 以后
Skill 可以明确告诉 Agent:
天气问题
↓
必须调用 get_weather
↓
不要猜测
↓
拿到工具结果
↓
再回答用户
如果以后规则变复杂,例如:
用户问“今天北京天气”
↓
get_weather()
用户问“北京未来三天天气”
↓
get_forecast()
用户问“北京空气质量”
↓
get_air_quality()
用户问天气但没有城市
↓
先询问城市
那么 Skill 就非常有价值了。
MCP 负责提供:
get_weather()
get_forecast()
get_air_quality()
Skill 负责告诉 Agent:
什么情况下调用哪个工具。
十、所以 MCP 和 Skill 关注的问题不同
可以用下面这张表理解:
| 问题 | MCP | Skill |
|---|---|---|
| 有什么能力? | ✅ | ❌ |
| 提供 Tool | ✅ | ❌ |
| 定义 Tool 参数 | ✅ | ❌ |
| 实际执行代码 | ✅ | ❌ |
| 连接外部服务 | ✅ | ❌ |
| 告诉 AI 什么时候使用 | ❌ | ✅ |
| 告诉 AI 怎么使用 | ❌ | ✅ |
| 描述工作流程 | ❌ | ✅ |
| 提供最佳实践 | ❌ | ✅ |
| 约束 Agent 行为 | ❌ | ✅ |
因此:
MCP = Capability
Skill = Instructions
十一、Tool 又是什么?
这里还需要区分第三个概念:
Tool
例如:
@mcp.tool()
def get_weather(city: str):
这里的:
get_weather
就是一个 Tool。
所以关系可以进一步画成:
Skill
│
│ 告诉 Agent 如何使用
▼
Agent
│
│ 调用
▼
MCP
│
│ 暴露
▼
Tool
│
│ 执行
▼
外部系统
更加准确地说:
MCP 是工具与 Agent 之间的标准通信协议,Tool 是 MCP Server 暴露出来的具体能力,而 Skill 是指导 Agent 使用这些能力的说明。
十二、再联系 Browser Control
现在再回头看 Browser Control,就非常容易理解了。
之前我们安装 Browser Control 时同时接触到了:
browser-control
browser-control-mcp
Browser Control Skill
Chrome Extension
Relay
它们并不是重复的东西。
可以这样理解:
OpenCode
│
┌──────────┴──────────┐
│ │
▼ ▼
Browser Control Browser Control
Skill MCP
│ │
│ │
“如何操作浏览器” “提供浏览器工具”
│ │
└──────────┬──────────┘
▼
Browser Control
│
▼
Relay
│
▼
Chrome Extension
│
▼
Chrome
例如 MCP 提供:
browser_snapshot
browser_click
browser_type
browser_navigate
browser_tabs
而 Skill 可以告诉 AI:
操作网页时:
1. 先获取页面结构
2. 找到目标元素
3. 执行操作
4. 检查操作结果
5. 不要猜测页面元素
所以:
MCP:
“你可以点击按钮。”
Skill:
“遇到这种情况,你应该先找到按钮,再点击,
点击以后检查页面是否发生预期变化。”
两者结合起来,Agent 才不仅拥有浏览器能力,而且知道如何更可靠地使用这个能力。
十三、一个非常重要的认识:Skill 本身通常不能“执行”
这是很多初学者容易产生的误解。
例如 Skill 里面写:
调用 get_weather("北京")
它并不会真的执行:
get_weather()
因为 Skill 本身没有这个工具。
它只是告诉 Agent:
你应该这么做。
真正执行:
get_weather("北京")
的是 MCP Tool。
所以:
Skill
↓
告诉 Agent “调用 get_weather”
↓
Agent 决定调用
↓
MCP
↓
执行 Tool
十四、一个更形象的类比
可以把整个系统想象成一家餐厅。
MCP = 厨房
厨房里面有:
炒菜
煮面
做咖啡
做甜点
它真正具备生产能力。
Tool = 厨房里的具体设备/工位
例如:
炒菜 → 炒锅
咖啡 → 咖啡机
甜点 → 烤箱
这些是具体能力。
Skill = 厨师手册
告诉厨师:
做牛排:
先煎
再烤
最后静置
做咖啡:
根据客人的要求选择不同参数
它告诉你:
怎么组合和使用现有能力。
Agent = 厨师
用户说:
我要一杯咖啡。
厨师根据 Skill:
这是咖啡需求
↓
按照咖啡流程
↓
使用咖啡机
厨房提供实际能力。
所以:
用户
↓
Agent
↓
Skill:告诉怎么做
↓
MCP:提供工具
↓
Tool:实际执行
这个类比基本可以覆盖大多数 Agent + Skill + MCP 的使用场景。
十五、最终把四个概念放在一起
到这里可以建立一个完整的认知模型:
┌────────────────────────────────────┐
│ AI Agent │
│ │
│ LLM + Planning + Reasoning │
└───────────────┬────────────────────┘
│
┌───────┴────────┐
│ │
▼ ▼
Skill MCP
│ │
│ │
使用说明/流程 工具协议
│ │
│ ▼
│ Tools
│ │
│ ▼
│ 外部系统/API
│
└──────→ 指导 Agent 如何
使用这些能力
一句话总结:
LLM
负责思考
Agent
负责执行任务循环
Skill
负责告诉 Agent 怎么做
MCP
负责提供标准化工具接口
Tool
负责执行具体操作
外部系统
负责真正的数据和业务能力
十六、为什么现代 AI Agent 经常同时使用 Skill + MCP?
因为两者解决的是不同的问题。
假设没有 MCP:
Skill
↓
“请查询天气”
↓
但是没有天气工具
AI 知道应该做什么,却没有执行能力。
假设没有 Skill:
MCP
↓
get_weather()
↓
AI 可以调用
AI 有工具,但是复杂任务下需要自己推断最佳工作流程。
两者结合:
Skill
↓
告诉 Agent 如何完成任务
↓
MCP
↓
提供完成任务所需的工具
↓
Tool
↓
真正执行
这就是现代 Agent 架构中经常看到:
Agent
+ Skills
+ MCP
+ Tools
的原因。
十七、总结
如果你第一次接触 Skill 和 MCP,不需要一开始就研究 MCP 协议的所有细节。
先记住下面这四句话:
Skill 告诉 AI 怎么做。
MCP 告诉 AI 有什么工具可以用。
Tool 是具体可以执行的能力。
Agent/LLM 决定什么时候调用这些能力。
以本文的天气例子来说:
用户:
北京今天多少度?
↓
Skill:
这是天气问题,
应该使用天气工具。
↓
MCP:
我提供 get_weather(city)。
↓
Agent:
调用 get_weather("北京")。
↓
Tool:
返回“晴,25°C”。
↓
Agent:
告诉用户北京今天晴,25°C。
而到了 Browser Control:
Skill:
告诉 AI 如何可靠地操作浏览器
MCP:
提供浏览器操作工具
Tool:
click / type / navigate / snapshot ...
Browser Control:
真正执行浏览器控制
Chrome Extension:
连接现有 Chrome
这样再回头看 OpenCode 的 Browser Control,就不会再觉得:
“为什么一个 Browser Control 要同时安装 Skill 和 MCP?”
因为它们本来就是两个不同层次的东西:
一个负责“怎么用”,一个负责“提供能力”。