HelloAI
L4 第 13 篇 🐣 难度 🕒 11 分钟

Function Calling vs Tool Use vs MCP:三个相关概念怎么区分

工业界三个名字最让人晕——但它们是同一件事的三层抽象。一篇说清楚。

阿莱
2026/9/18

每次有人问”我要做 Agent,到底用 Function Calling 还是 MCP 还是 Tool Use?”—— 都说明这三个概念没人讲清楚过

这一篇讲清楚:它们是同一件事的三层抽象

一句话区分

名词是什么谁定义的在哪一层
Function CallingOpenAI 的 API 参数格式OpenAI(2023)模型 API
Tool UseAnthropic 的同类功能Anthropic(2023)模型 API
MCP跨厂商工具调用协议Anthropic(2024)应用 / 系统

它们都解决”让 LLM 调用外部工具”——但层次不同

视角一:API 层(FC / Tool Use)

直接通过 API 让 LLM 调用函数:

OpenAI Function Calling

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"]
        }
    }
}]

response = openai.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=tools
)

模型返回:

{
  "tool_calls": [{
    "function": {
      "name": "get_weather",
      "arguments": "{\"city\": \"Tokyo\"}"
    }
  }]
}

你的代码自己执行 get_weather("Tokyo"),结果再喂回去。

Anthropic Tool Use

tools = [{
    "name": "get_weather",
    "description": "Get current weather",
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
    }
}]

response = anthropic.messages.create(
    model="claude-3-5-sonnet",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=tools
)

几乎一模一样的概念,参数命名略有差异。

共同点

  • 都在 API 请求体里声明 tools
  • 模型返回”我要调用 X 函数,参数是 Y”
  • 你的代码负责实际执行
  • 模型不直接接触函数

唯一痛点

每家 LLM 厂商有自己的格式。换 OpenAI ↔ Anthropic ↔ Gemini ↔ DeepSeek 要重写工具声明。

视角二:协议层(MCP)

MCP(Model Context Protocol)回答了上面的痛点:

为什么每个工具都要为每个 LLM 重写一遍?

MCP 是一个协议,让工具”写一次,所有 LLM 都能用”。

MCP 的角色

之前:
  Cursor 想用 GitHub 工具 → Cursor 自己接 GitHub API
  Claude Desktop 想用 GitHub 工具 → Claude Desktop 自己接 GitHub API
  Cline 想用 GitHub 工具 → Cline 自己接 GitHub API
  → 重复实现 3 次

MCP 之后:
  有人写一个 mcp-server-github
  Cursor / Claude Desktop / Cline / Continue 都直接挂上
  → 一次实现,无数客户端用

MCP 长什么样

不是 API 调用,是进程间通信

你的应用(如 Claude Desktop)
   ↓ JSON-RPC over stdio / HTTP
MCP Server(如 github、filesystem、postgres)

真实工具(GitHub API、本地文件、数据库)

每个 MCP server 暴露它的工具:

# weather_mcp_server.py
from mcp.server import Server

server = Server("weather")

@server.list_tools()
async def list_tools():
    return [Tool(
        name="get_weather",
        description="Get current weather",
        inputSchema={...}
    )]

@server.call_tool()
async def call_tool(name, args):
    if name == "get_weather":
        return [TextContent(text=fetch_weather(args["city"]))]

启动后,任何支持 MCP 的客户端(Claude Desktop / Cursor / Cline / Continue / …)都能用它。

三者之间的关系

┌─────────────────────────────────────────┐
│  应用层:Cursor / Claude Desktop / Cline │
└────────────────┬────────────────────────┘

        ┌────────┴────────┐
        ↓                 ↓
   ┌─────────┐      ┌──────────┐
   │   MCP   │      │ 直接调用  │
   │ (协议)  │      │ 工具代码  │
   └────┬────┘      └────┬─────┘
        │                 │
        ↓                 ↓
    MCP Server      你的应用代码
        │                 │
        └────────┬────────┘

         ┌──────────────┐
         │  LLM API     │
         │ (Function    │
         │  Calling /   │  ← 这一层是 OpenAI / Anthropic 的格式
         │  Tool Use)   │
         └──────────────┘


            真实 LLM

关键洞察

  • MCP 不是 Function Calling 的替代 —— 它在更高层
  • MCP server 内部仍然可能通过 Function Calling 让 LLM 决定”调用哪个工具”。
  • 但你的应用代码不再直接写 Function Calling 的 JSON——它跟 MCP server 说话。

实战决策树

问:我要让 LLM 调用工具,怎么选?

├─ 我只服务一个 LLM 厂商,工具数量少(≤5)
│   → 用厂商原生 API(Function Calling / Tool Use)

├─ 我服务多个 LLM 厂商
│   → 用 LangChain / LlamaIndex 的抽象层(屏蔽差异)
│   → 或者直接用 MCP

├─ 我做的是消费级桌面应用,希望生态共享
│   → 用 MCP(这样别的应用也能用我做的工具)

└─ 我做的是企业内部 Agent 平台
    → MCP(解耦工具 / Agent 演化)

3 个常见误解

❌ “MCP 替代了 Function Calling”

正解:MCP 是协议,Function Calling 是 API 格式。两者同时存在。MCP server 内部很可能仍用 FC。

❌ “用 MCP 必须用 Claude”

正解:MCP 是开放协议,OpenAI / Google / Mistral 都在评估支持。MCP server 不绑定任何 LLM。

❌ “Function Calling 是给 OpenAI 用的,Tool Use 是给 Claude 用的,要选一个”

正解:你的应用同时支持两家,就两个 schema 都写。或用 LangChain / DSPy 等抽象层让你只写一次。

真实工业架构示例

一个 2026 年的真实 Agent 产品(如 Cursor):

[用户输入: "fix the bug in main.py"]

[Cursor 应用]
        ↓ ① 通过 MCP 连接的工具服务器列表
        │   - mcp-server-filesystem (读写文件)
        │   - mcp-server-git (git 操作)
        │   - mcp-server-shell (跑命令)
        ↓ ② 把所有工具的 schema 收集起来
[LLM API 调用]
        ↓ ③ 用 Anthropic Tool Use 格式(因为 Cursor 接了 Claude)
        │   tools=[{"name": "...", ...}, ...]
[LLM 决定用哪个工具]
        ↓ ④ 返回 tool_use 调用
[Cursor 翻译给对应的 MCP server]

[MCP server 执行]

[结果回流到 LLM]

[继续决定下一步]

MCP 在外面(管理工具生态),Function Calling / Tool Use 在里面(与 LLM 通信)。

💡 总结

Function Calling / Tool Use 是单个 LLM 厂商让你声明工具的格式—— 解决的是 “LLM 怎么告诉我要调什么函数”。

MCP 是协议—— 解决的是 “这个工具怎么被多个不同 LLM 客户端复用”。

两者是互补的,不是互斥。 实际系统里一起出现

下一篇推荐:L4-14 结构化输出L4-11 写自己的 MCP server

🚧 3 个常见坑

⚠️ 实战避坑

坑 1:把三个概念当同义词用 FC 是接口、Tool Use 是范式、MCP 是协议——讨论时混用导致团队对齐失败。

坑 2:以为 MCP = OpenAI Plugins 2.0 MCP 是协议(任意客户端 + 任意 server),Plugins 是 ChatGPT 内部架构——MCP 通用性高很多。

坑 3:不区分 single-step / multi-step 单次 function call 不是 Tool Use;多轮工具 + 反思 + 决定下一步才是。

🔗 被以下 1 篇文章引用
📬

读到这里说明你认真在学 🎯

订阅每周精选 —— 下一篇新文章 / 新可视化第一时间送到邮箱。

💬

讨论区

· 用 GitHub 账号登录评论
⚠️ Giscus 评论未配置 —— 在 src/components/Comments.astro 顶部填入 仓库 ID 和分类 ID(见组件注释里的配置步骤)。