最近在给团队做 AI Agent 技术分享时,发现大家经常把三个名词混在一起聊:Tool Calling、Skills、MCP。有人以为 Skills 就是 MCP 的另一种叫法,有人把 Tool Calling 当成 MCP 的一个功能,还有人觉得只要接入了 MCP 就天然支持了 Tool Calling。
这些理解不能说完全错,但都没说到根上。如果概念边界不清晰,做架构选型和方案设计时就容易踩坑。这篇文章会把这三个概念拆开来讲,先说它们各自解决什么问题,再用对比表格梳理区别,最后给出一套最小可运行的示例代码,帮助你快速建立整体认知。
无论你是刚开始接触 AI Agent 开发的新手,还是已经在业务中落地过 Function Calling 的工程师,这篇文章都值得收藏备用。
1. 背景与核心概念
1.1 Tool Calling:让模型具备调用外部工具的“能力”
先看一个最简单的场景。你问大模型:“北京现在气温多少度?”
如果没有联网能力和工具调用能力,模型只能凭训练数据回答一个大致范围,甚至直接告诉你“我无法获取实时数据”。但如果你在请求中额外提供两个工具函数:一个负责查询天气,一个负责查询城市编码。模型会先输出一个结构化调用指令,比如:
{ "name": "get_weather", "arguments": "{\"city\": \"beijing\"}" }你的程序收到这个指令后,去真实天气 API 查询数据,再把结果返回给模型,模型基于真实数据生成最终回答。
这就是 Tool Calling,本质上是大模型的一种“行为决策能力”。模型本身不会去执行真实 API 调用,它只是根据用户输入和工具描述,决定“接下来应该调用哪个工具、传入什么参数”。实际执行逻辑由你的代码完成,结果再回传给模型继续生成。
专业一点的叫法是 Function Calling 或 Tool Use。OpenAI 早期称之为 Function Calling,后来演进为 Tool Calling,Anthropic 也有类似的 Tool Use 机制。不同平台实现细节略有差异,但核心思想一致:把模型从“只会生成文本”扩展为“可以发起外部动作”。
1.2 Skills:把复杂能力打包成可复用的“技能”
Skills 的概念在 Claude 生态(如 Claude Code、Claude Desktop)中非常流行。它本质上是一组预定义好的指令、规则和示例,打包成一个可复用的文件夹或单一 Markdown 文件。当模型在对话或编码任务中触发对应的技能时,会自动加载这套指令,从而按照你期望的方式完成任务。
举个例子。你希望 AI 在帮你写代码时,必须遵循公司的 Git 提交规范。如果把规范写在每一次 Prompt 里,既冗长又容易遗漏。这时可以创建一个名为git-commit-skill的 Skills 文件,内容大致是:
--- name: git-commit-skill description: 用于生成符合团队规范的 Git 提交信息。 --- 当用户要求生成 Git 提交信息时,请严格遵守以下规则: 1. 提交类型使用固定前缀:feat / fix / docs / style / refactor / test / chore。 2. 首行不超过 50 个字符。 3. 正文必须说明修改动机,不能只写“更新代码”。 4. 如果涉及破坏性变更,必须以 BREAKING CHANGE 开头单独成段。当模型识别到用户正在处理 Git 提交相关任务时,会主动加载并遵循这个技能文件里的约束,不需要你每次重复强调。
所以,Skills 的重点在于“封装经验和规则”。它有点像给 AI 写的“岗位 SOP”,把一套固定的工作方法沉淀下来,让 AI 在特定场景中稳定输出符合预期的结果。
1.3 MCP:统一工具接入的“协议标准”
MCP 全称是 Model Context Protocol,模型上下文协议。它由 Anthropic 在 2024 年底提出,目的是解决一个很实际的问题:每接入一个外部数据源或工具,开发者都要为不同模型平台写一套定制化集成代码。今天对接公司的内部数据库写一套,明天对接 Figma 又要写一套,重复劳动严重。
MCP 的思路是借鉴 USB 接口的设计:设备厂商按照 USB 标准生产设备,电脑系统按照 USB 标准识别设备,两者之间不需要互相知道对方的具体实现。MCP 把“AI 应用”(Host)和“外部工具/数据源”(MCP Server)解耦,定义一个标准化的通信协议。统一之后,同一个 MCP Server 可以在 Claude Desktop、Claude Code、Cursor 甚至自研 Agent 应用中复用。
一个典型的 MCP Server 会暴露三类能力:
| 能力类型 | 作用 | 类比 |
|---|---|---|
| Tools | 可执行的函数,比如查询数据库、发 HTTP 请求 | 接口函数 |
| Resources | 可读取的数据资源,比如文件内容、数据库记录 | 静态数据 |
| Prompts | 预定义的可复用提示词模板 | 脚本模板 |
可以看到,MCP 的范畴比单纯的工具调用更大,它试图成为整个 AI Agent 生态的“标准化接入层”。
1.4 为什么这三个概念容易混淆
容易混淆的根本原因是:它们出现在同一个技术链条上,但处于不同层次。
- Tool Calling 是一种能力,回答的是“模型能不能调用工具”。
- Skills 是一种内容封装,回答的是“怎么让模型按特定规范完成任务”。
- MCP 是一种协议标准,回答的是“工具和模型之间用什么方式互通”。
打个比方:Tool Calling 相当于“人会使用螺丝刀”,Skills 相当于“一套标准化的修车流程手册”,MCP 相当于“全世界统一的螺丝刀接口规格”。三者职责不同,但实际使用中往往同时出现。
2. 三者本质区别与关系详解
2.1 核心定位对比
先把三者的核心定位放在一起看:
| 维度 | Tool Calling | Skills | MCP |
|---|---|---|---|
| 本质 | 模型能力 | 内容/指令封装 | 通信协议 |
| 解决什么问题 | 模型如何决定调用外部函数 | 模型如何按固定规范完成任务 | 工具/数据源如何标准化接入 |
| 实现层面 | 模型推理层 | Prompt/上下文策略层 | 应用架构层 |
| 典型载体 | API 参数中的 tools 字段 | Markdown 文件或 JSON 目录 | MCP Server 进程 |
| 是否依赖具体平台 | 不依赖,各大模型基本支持 | 多为 Claude 系生态 | 跨平台、跨模型 |
| 开发者工作量 | 写函数定义和调用逻辑 | 写领域规则和示例 | 写 Server 和 Client 适配层 |
2.2 三者的实现层次差异
从实现方式来看,三者完全不同。
Tool Calling 是模型平台内置的能力。你在请求里传入工具 Schema,模型在生成过程中自行决定是否调用以及如何调用。这个“决策”是模型推理的一部分,开发者无法直接干预模型内部的决策逻辑,只能通过工具描述写得是否清晰来间接影响。
Skills 是 Prompt 层面的增强。本质上它是把一段高质量的指令文本提前准备好,在恰当的时机注入上下文。它不需要模型额外支持什么特殊 API,只要模型具备足够长的上下文理解能力即可。这也是为什么 Skills 文件可以做成 Markdown 这种纯文本形式——因为它最终就是作为指令文本被模型读取。
MCP 是进程间的标准化通信。它需要客户端(MCP Client)和服务端(MCP Server)同时遵循协议规范。工具的真实执行逻辑在 MCP Server 中,Client 通过 JSON-RPC 格式的消息和服务端交互。两者通过标准输入输出或远程 HTTP 进行通信,实现进程解耦。
2.3 三者如何协同工作
这里用一个实际场景串联起来:你开发了一个 AI 编程助手,用户要求“帮我把项目里的 TODO 列表同步到飞书文档”。
- MCP 负责打通“飞书文档”这个外部系统。你写好一个飞书 MCP Server,暴露一个
create_doc的 Tool。 - Tool Calling 负责让模型“看懂”应该调用
create_doc。模型阅读用户请求,匹配到飞书文档相关的工具描述,输出一行调用指令。 - Skills 负责约束“怎么调用才符合规范”。比如你预定义了一个
feishu-doc-skill,规定标题格式、权限设置、内容排版要求,模型在调用工具前会先参考这套规则。
换句话说,MCP 把工具接入标准化,Tool Calling 让模型具备调用能力,Skills 让调用过程更可控、更贴近业务要求。它们不是替代关系,而是互补关系。
3. 环境准备与最小示例
3.1 环境准备
为了演示方便,本文使用 Python 3.10+ 作为示例环境,并假设你已经安装了openai、anthropic两个 Python SDK。版本不需要完全一致,但建议尽量使用较新版本,以免缺少部分 API 参数。
pip install openai anthropic同时,你可以准备一个虚拟环境,避免依赖冲突:
python -m venv .venv source .venv/bin/activate # Windows 下执行 .venv\Scripts\activate由于不同模型的 API Key 获取方式不同,本文不会实际调用远程模型,而是以代码结构和配置示例为主,重点说明三者各自的实现形态。如果你需要真实运行,替换为自己的 API Key 即可。
3.2 Tool Calling 最小示例
下面这段代码演示了 OpenAI 风格下的 Tool Calling 实现。核心是:在请求中声明一个工具get_weather,模型在收到用户消息后,如果判断需要查询天气,会返回工具调用指令,而不是直接返回文本。
# 文件路径:examples/tool_calling_demo.py from openai import OpenAI client = OpenAI(api_key="YOUR_API_KEY") tools = [ { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的当前天气", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称,如北京、上海" } }, "required": ["city"] } } } ] messages = [ {"role": "user", "content": "北京现在热不热?"} ] response = client.chat.completions.create( model="gpt-4o-mini", messages=messages, tools=tools, ) # 打印模型给出的工具调用指令 print(response.choices[0].message.tool_calls)预期输出中会有一个tool_calls列表,里面包含函数名get_weather和参数{"city": "北京"}。你拿到这个结果后,可以执行真实的天气查询函数,再把结果以role="tool"的消息回传给模型,让模型完成最终回答。
这里的关键是:模型只负责“决定要调用哪个工具”,不负责“真的执行工具”。执行逻辑,如请求天气 API、解析响应、做数据转换,全部在你的代码中完成。
3.3 Skills 示例
Skills 的载体通常是文件夹或 Markdown 文件。以 Claude Code 的 Skills 为例,一个标准技能目录结构如下:
skills/ └── git-commit-skill/ ├── SKILL.md └── examples/ └── good_commit.mdSKILL.md是核心文件,带有 YAML 格式的 frontmatter,用于描述技能名称和触发条件:
--- name: git-commit-skill description: 当用户需要生成 Git 提交信息时使用此技能。 --- # Git Commit 技能 该技能用于生成符合团队规范的 Git 提交信息。 ## 规则 1. 提交类型必须使用 feat、fix、docs、style、refactor、test、chore 前缀。 2. 首行不超过 50 个字符。 3. 正文必须描述修改动机和影响范围。 4. 如有破坏性变更,必须使用 BREAKING CHANGE 开头。 ## 示例 用户输入:我修复了登录页面的按钮点击无响应问题 输出:fix: 修复登录页按钮点击无响应问题当模型根据用户请求判断“这属于 Git 提交信息生成任务”时,它会自动加载这个技能文件,按里面的规则组织回答。这个过程中没有额外的 API 请求,也没有进程间通信,纯粹是通过注入更高质量的上下文指令来约束模型输出。
3.4 MCP 配置示例
MCP 的完整实现涉及 Server 和 Client 两端。这里以一个最小的服务端配置示例,展示 MCP Server 在 Claude Desktop 中的注册方式。配置文件位于claude_desktop_config.json:
{ "mcpServers": { "weather-server": { "command": "python", "args": ["path/to/weather_server.py"], "env": { "WEATHER_API_KEY": "your_api_key_here" } } } }上面的配置告诉 Claude Desktop:启动一个名为weather-server的 MCP Server,通过 Python 脚本运行,并注入环境变量。
如果使用 MCP 官方 Python SDK 搭建一个最简单的 Server,核心代码大致如下:
# 文件路径:examples/weather_server.py from mcp.server import Server from mcp.server.stdio import stdio_server app = Server("weather-server") @app.list_tools() async def list_tools(): return [ { "name": "get_weather", "description": "查询指定城市的当前天气", "inputSchema": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } ] @app.call_tool() async def call_tool(name: str, arguments: dict): if name == "get_weather": city = arguments["city"] # 这里可以替换为真实的天气 API 调用 return {"city": city, "temperature": "26℃", "condition": "晴"} raise ValueError(f"未知工具: {name}") async def main(): async with stdio_server() as (read_stream, write_stream): await app.run(read_stream, write_stream, app.create_initialization_options()) if __name__ == "__main__": import asyncio asyncio.run(main())这段代码实现了一个标准的 MCP Server:list_tools向客户端声明可用的工具列表,call_tool处理真实的工具调用逻辑。客户端(如 Claude Desktop、自研 Agent)通过标准输入输出流与 Server 通信,实现进程间的能力复用。
4. 实际场景选择指南
4.1 什么时候只需要 Tool Calling
如果你的业务逻辑相对简单,外部依赖较少,只需要调用两三个固定 API,那么直接用 Tool Calling 就够了。
典型场景包括:
- 让 AI 根据用户问题决定调用计算器、翻译接口或短链接生成接口。
- 在已有业务系统中增加一个“AI 助手”,只需要查询订单状态、用户信息等少量接口。
- 快速原型验证阶段,不想引入额外协议层。
用 Tool Calling 的优势是简单直接。你不需要搭建额外服务,只需要在请求参数里写好工具 Schema。缺点是每个接入方都要写一套定制化代码,复用性差。
4.2 什么时候应该用 Skills
当你发现同一个领域的 AI 任务反复出现,且每次都需要强调同样的规则时,就该考虑用 Skills。
典型场景包括:
- 团队内部要求 AI 生成代码时必须遵守固定的代码风格和提交规范。
- 需要让 AI 按固定格式输出测试报告、周报、复盘文档。
- 面向特定岗位,比如前端、测试、运维,沉淀专属的 AI 工作流。
Skills 的价值在于“一次编写,处处生效”。它把经验沉淀为可复用的资产。尤其适合团队协作,因为技能文件可以进入 Git 仓库,接受版本管理和评审。
4.3 什么时候必须引入 MCP
MCP 的引入成本相对更高,但收益也更明显。当你的应用需要对接多种外部系统,或者希望同一个接入能力被多个 AI 应用复用时,MCP 是更合适的方案。
典型场景包括:
- 需要同时对接数据库、文件系统、第三方 SaaS 平台等多个数据源。
- 同一套工具能力需要被 Claude Desktop、Claude Code、Cursor、自研应用等多端复用。
- 希望团队内部沉淀一套标准化的“工具接入层”,不同业务线共用。
- 涉及复杂的长生命周期连接,比如数据库连接、浏览器自动化会话、设计稿读取等。
4.4 综合选型矩阵
| 场景特征 | 推荐方案 | 理由 |
|---|---|---|
| 接口少、逻辑简单、快速验证 | Tool Calling | 成本最低,开发速度快 |
| 需要固定输出规范、积累团队经验 | Skills | 以内容驱动模型行为,收敛效果好 |
| 多工具、多端复用、系统间解耦 | MCP | 标准化接入,避免重复开发 |
| 三者混合、复杂 Agent 应用 | 三者结合 | MCP 接入工具,Tool Calling 驱动调用,Skills 规范过程 |
5. 常见问题与排查思路
5.1 常见问题排查表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 模型输出了工具名,但没有参数 | 工具 Schema 中缺少required字段,或者描述不够明确 | 为必填参数添加required;在参数描述中给出示例值 |
| 模型一直不调用工具 | 工具描述与用户问题的关联度不够强 | 优化工具描述的措辞,显式说明“当用户询问 XXX 时使用此工具” |
| Skills 没有生效 | 技能文件命名不符合规范,或触发条件描述不清晰 | 检查 frontmatter 中name和description;确保技能目录结构正确 |
| MCP Server 启动失败 | Python 依赖缺失或路径配置错误 | 使用python -m mcp.server手动启动调试,检查环境变量和依赖 |
| MCP 工具能注册但调用报错 | 参数格式与 Server 端预期不一致 | 在 Server 端添加参数校验和日志输出,对比客户端传入的参数结构 |
| 同一个工具在 Codex 中注册不上 | 客户端对 MCP Server 的启动方式或参数类型有限制 | 查看客户端日志确认具体报错;尝试用本地 stdio 模式和远程模式分别验证 |
5.2 排查思路示例
以“模型一直不调用工具”为例,推荐按以下顺序排查:
- 打开调试日志,确认模型返回的完整响应中是否包含
tool_calls字段。 - 检查工具描述是否清晰。很多时候,模型不调用是因为描述里没有说明“什么时候该用”。
- 尝试把工具数量减少到一个,排除多个工具间的选择干扰。
- 检查上下文长度。如果用户问题前后信息量过大,模型可能丢失工具信息。
- 如果使用 OpenAI 系模型,可以尝试在工具定义中增加
"strict": true来约束 JSON Schema 严格模式,减少参数匹配失败的概率。
MCP 相关的问题则要优先看日志。MCP 是进程间通信,任何一端发生异常都会导致整体失败。建议在 Server 的关键路径添加日志输出,确认是否收到客户端的初始化请求、工具列表请求和调用请求。
6. 最佳实践与工程建议
6.1 工具命名与描述规范化
无论采用哪种方案,工具命名和描述都值得认真打磨。工具名使用小写字母和下划线,如get_weather,避免使用空格和特殊字符。描述中明确说明“在什么情况下使用”,必要时给出示例参数,让模型更容易理解调用边界。
一个反例和一个正例对比:
反例:查询天气 正例:当用户询问某个城市的当前气温、天气状况或出行建议时,查询该城市的实时天气数据。参数 city 为城市中文名,例如“北京”“上海”。6.2 配置隔离与环境管理
Skills 文件建议纳入版本管理,按团队或项目维度拆分。不要把所有规则写进一个巨型文件,应该按领域拆分,比如frontend-skill、backend-skill、test-skill,让模型按需加载。
MCP Server 的配置信息,如 API Key、数据库连接串,应该通过环境变量注入,不能硬编码在配置文件中。不同环境(开发、测试、生产)使用不同的配置文件,避免把生产环境的密钥带到本地。
6.3 安全边界与最小权限原则
工具调用和 MCP 接入都意味着模型获得了触发外部动作的能力。权限控制是必须考虑的问题。
建议遵循最小权限原则:给模型暴露的工具,只授予完成任务所需的最小权限。比如,查询订单状态的工具不应该具备删除订单的能力。如果 MCP Server 需要访问数据库,建议使用只读账号,并限制可访问的表和字段范围。
对于涉及用户数据、支付、删除类操作的调用,应该在调用链路上增加人工确认环节,不能完全由模型自动决定。
6.4 异常处理与可观测性
无论使用 Tool Calling 还是 MCP,建议在工具执行层统一封装错误处理逻辑:
- 工具执行失败时,返回结构化错误信息,而不要抛出原始异常给模型。
- 记录完整的调用流水,包括用户输入、模型决策、工具参数、执行结果、耗时。
- 对耗时较高的工具调用做超时控制,防止模型长时间等待外部服务响应。
- 为关键工具调用增加日志级别区分,便于线上问题回溯。
6.5 性能优化建议
MCP 的进程间通信有一定开销,如果是本地 stdio 模式,单次调用的延迟增加并不明显。但如果是远程 HTTP 模式,网络延迟会成为瓶颈。在设计 MCP Server 时,尽量把频繁调用的逻辑做成无状态接口,方便水平扩展。
Tool Calling 的性能优化重点在减少不必要的工具调用。通过更精确的工具描述和更严格的参数约束,可以让模型一次就调用正确的工具,避免多轮试探带来的 Token 浪费和延迟。
7. 总结与学习路线
本文梳理了 Tool Calling、Skills、MCP 三者的核心概念和区别。简单回顾一下重点:
- Tool Calling 是模型决策层的“能力开关”,负责决定是否调用工具以及传什么参数。
- Skills 是内容层的“知识沉淀”,用预定义指令约束模型输出质量。
- MCP 是架构层的“协议标准”,解决工具接入的标准化和跨应用复用问题。
三者不是竞争关系,而是层层叠加的配合关系。MCP 负责接入,Tool Calling 负责决策,Skills 负责规范。
如果你想继续深入学习,建议按以下路线推进:
- 先熟练掌握一种模型的 Tool Calling 用法,理解工具 Schema 如何影响模型决策。
- 接着研究 Skills 的编写规范,把你日常工作流沉淀成可复用的技能文件。
- 最后学习 MCP 协议,尝试用官方 SDK 搭建一个自己的 MCP Server,接入 Claude Desktop 或自研应用。
- 等基础概念清晰之后,再接触 LangChain、LlamaIndex 这类 Agent 框架,你会发现框架里的很多抽象,本质上就是在封装 Tool Calling、Skills、MCP 的这些基础能力。
如果在实际项目中遇到这三个概念混用、选择困难的问题,建议回到业务场景本身:你当前最需要解决的是“模型不会调用工具”“输出不稳定”还是“工具接入太重复”?定位清楚问题,再选对应的技术方案,就不会被概念绕晕了。
如果这篇文章对你有帮助,欢迎收藏备用,后续会继续更新 Agent 工程化的实战内容。