一篇文章告诉你MCP、MCP Tools、Function Calling的区别
Function Calling 是“打电话”这个动作,而 MCP 是“全球统一的电话号码簿和通信标准”。
先看定义
| 概念 | 本质 | 类比 |
|---|---|---|
| Function Calling(函数调用) | LLM 的一种内置能力,让模型能输出结构化的工具调用指令(JSON),由开发者执行具体逻辑。 | 你给员工发指令:“去查一下数据库,把结果告诉我。”(指令传递方式) |
| MCP(模型上下文协议) | 一个开放的协议标准,定义了 AI 应用与外部工具/数据源之间的通信接口和发现机制,实现“一次接入,处处可用”。 | 公司内部的统一服务总线:任何员工(AI)都能通过这套标准找到并使用任何部门(工具)的服务。 |
最核心的 5 个区别(面试必看)
| 维度 | Function Calling | MCP |
|---|---|---|
| 1. 层级 | 模型能力(Model Capability)——LLM 本身支持输出特定格式 | 协议标准(Protocol Standard)——定义 Client 和 Server 如何通信 |
| 2. 谁主导 | 由模型厂商(如 OpenAI、Anthropic)在模型层实现,开发者只是调用 | 由社区/基金会主导(如 Anthropic 发起),任何厂商都可以实现 |
| 3. 工具定义位置 | 硬编码在代码里:开发者用代码写死工具列表(tools 参数),每次调用都传入 | 动态发现:MCP Server 启动后,Client 自动拉取工具列表,无需事先硬编码 |
| 4. 标准化程度 | 厂商绑定:OpenAI 的 Function Calling 格式与 Claude 的 Tool Use 不同,切换模型需改代码 | 协议统一:所有 MCP 客户端和服务器遵循同一套协议(JSON-RPC),切换模型/工具无需重写 |
| 5. 适用场景 | 单次、简单、固定的工具调用(如查天气、算数) | 复杂、动态、可插拔的工具生态(如 IDE 插件市场、Agent 工具箱) |
代码层面的直观对比
Function Calling(常规用法)
# 每次调用都要把工具定义传进去,且格式依赖特定模型
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查天气",
"parameters": {"city": {"type": "string"}}
}
}
]
# 调用 OpenAI 时传入 tools
response = openai.chat.completions.create(
model="gpt-4",
messages=[...],
tools=tools # 硬编码在请求里
)
MCP(协议方式)
# 1. 启动 MCP Server(独立服务)
# 2. 客户端自动发现工具
from mcp import ClientSession, StdioServerParameters
# 连接到 MCP Server,自动获取工具列表
async with ClientSession(server_params) as session:
tools = await session.list_tools() # 动态发现!
# tools 包含所有可用工具,无需在代码里写死
# 调用工具
result = await session.call_tool("get_weather", {"city": "北京"})
关键差异:MCP 下,工具列表是运行时动态获取的,而 Function Calling 的工具列表是编译时硬编码的。
一个更好的理解:MCP 是 Function Calling 的“上层建筑”
在实际工程中,两者的关系通常是:
-
MCP Client 通过协议发现工具列表。
-
MCP Client 将工具列表映射成目标模型(如 OpenAI)的
functions或tools参数格式。 -
模型内部通过 Function Calling 能力输出调用指令。
-
MCP Client 再把指令翻译成 MCP 协议,去调用真正的 MCP Server。
所以:MCP 帮你统一了工具接入层,Function Calling 帮你实现了模型的推理决策层。
🆚 一图看懂区别
| 问题 | Function Calling 的回答 | MCP 的回答 |
|---|---|---|
| “我有 20 个工具,每次都要写进请求吗?” | ✅ 是的,每次都要传全部或动态拼装 | ❌ 不需要,Client 自动发现 |
| “换一个模型(比如 OpenAI → Claude)需要改代码吗?” | ✅ 格式不同,必须改 | ❌ 协议一致,Client 适配即可 |
| “工具逻辑更新了,要重新部署主应用吗?” | ✅ 需要(因为工具定义在代码里) | ❌ 不需要,只需重启 MCP Server |
| “支持多个 AI 应用共享同一套工具吗?” | ❌ 每个应用都要单独集成 | ✅ 可以,多个 Client 调用同一个 Server |
面试的时候怎么回答?
“Function Calling 是模型端的输出格式能力,而 MCP 是工具端的接入标准。MCP 通过协议统一了工具的发现和调用方式,让工具生态可以独立于模型和业务代码演进。实际落地时,我会用 MCP Server 封装所有工具,再由 MCP Client 将工具列表适配成模型能理解的 Function Calling 格式,从而同时享受模型的推理能力和协议的标准化。”
如果面试官继续追问“什么时候该用 MCP,什么时候直接用 Function Calling?”,你可以回答:
“如果工具数量少、固定、逻辑简单,直接 Function Calling 足够了。如果工具数量多、动态变化、且需要多个应用复用,或者要做工具市场、插件生态,那么 MCP 是更解耦、更可扩展的方案。”
MCP可以拆解成三层
| 层级 | 谁在干活 | 具体做了什么事 |
|---|---|---|
| 1. MCP Server | 工具提供方 | 只按 MCP 协议标准定义工具(不关心 OpenAI 或 Claude 长什么样)。 |
| 2. MCP Client | 适配层(核心) | 拉取 MCP Server 的工具列表;将 MCP 标准格式 转化成 各大模型厂商(OpenAI/Claude/Gemini)各自的 tools / functions 请求格式;模型返回调用指令后,再把指令转成 MCP 协议去调用真正的工具。 |
| 3. 大模型 | 推理方 | 收到适配好的 Function Calling 格式,正常输出工具调用指令,它完全不知道自己是在和 MCP 打交道。 |
举个直观的例子
假设你有一个 MCP Server,提供了 get_weather 工具。MCP Client 的内部适配逻辑大致如下:
# 1. MCP 标准格式(Server 返回的)
mcp_tool = {
"name": "get_weather",
"description": "查询天气",
"inputSchema": {
"type": "object",
"properties": {"city": {"type": "string"}}
}
}
# 2. MCP Client 内部做格式转换
# 如果目标模型是 OpenAI,转换成 OpenAI 的 tools 格式
openai_tool = {
"type": "function",
"function": {
"name": mcp_tool["name"],
"description": mcp_tool["description"],
"parameters": mcp_tool["inputSchema"]
}
}
# 如果目标模型是 Claude,转换成 Claude 的 tool_use 格式
claude_tool = {
"name": mcp_tool["name"],
"description": mcp_tool["description"],
"input_schema": mcp_tool["inputSchema"]
}
开发者只需要配置一句
model="openai"或model="claude",剩下的格式转换全由 MCP Client 完成。
面试时的精准表述
如果面试官问:“MCP 和 Function Calling 到底怎么配合?”
你可以回答:
“MCP 的核心作用之一是协议标准化。它把工具定义和调用逻辑从模型供应商的格式中解耦出来。开发者只需要按 MCP 标准写一次工具,MCP Client 会在运行时自动将这些工具列表转换成目标模型(如 OpenAI、Claude、Gemini)所要求的 Function Calling 参数格式。这样,工具可以复用,模型可以切换,而业务代码几乎无需改动,真正实现了工具层和模型层的分离。”
一句话总结
MCP 帮开发者屏蔽了不同模型厂商的 Function Calling 格式差异,用统一的协议完成了“工具定义 → 模型格式转换 → 工具调用”的全链路适配。
更多推荐

所有评论(0)