Function Calling 解决"模型层"问题,MCP 解决"协议层"问题,二者是上下层关系而非替代关系。
这一页串起 Agent 工具调用的底层基础设施——从 Plugin 演进到 Function Calling、再到 MCP 标准化,最后到当前最前沿的 Code Execution with MCP 范式。
Function Calling — 让 LLM "能动手做事"
LLM 本身只能"生成文本"——不能上网、不能访问数据库、不能发邮件。要做这些事必须给它"装上工具"。
这个机制叫 Function Calling(函数调用)——OpenAI 在 2023.6 首次发布 Function Calling API,现在已经是所有主流大模型(GPT-4o、Claude Sonnet 4.6、Gemini 1.5 Pro 等)的标配能力。
关键转折点:Function Calling 的成功率已经从 2023 年的 ~60% 提升到 2025 年的 95%+,这使得 Tool Use 从实验性功能变成了可靠的生产级能力。
Function Calling 的 4 个步骤
[1] 定义工具 开发者在发送给 LLM 的请求中,附带一份"工具说明书"
↓ 用 JSON Schema 格式描述每个工具的名称、功能、参数
[2] 模型选择工具 LLM 收到用户提问 + 工具清单后,做两件事:
↓ ① 理解用户意图
② 判断"需不需要调工具"以及"调哪个工具、传什么参数"
[3] 应用执行 系统(不是 LLM)拿到调用请求后,真正去执行
↓ 调用搜索引擎 API、查询数据库、发邮件等
LLM 本身不执行任何动作,它只是"决定要做什么"
执行完成后,系统把结果封装成文本,回传给 LLM
[4] 结果回传 LLM 结合工具结果 + 原始用户问题,生成最终回答
或者决定"还需要再调一个工具",进入新一轮循环
完整示例:北京明天天气
用户:"帮我查一下北京明天的天气"
[1] 工具清单:weather_query, web_search, calculator
[2] LLM 决定:调用 weather_query(city="北京", date="明天")
工具定义:
{
"name": "weather_query",
"description": "查询指定城市某天的天气。当用户询问天气、
气温、是否下雨时使用。",
"parameters": {
"city": { "type": "string", "description": "城市名" },
"date": { "type": "string", "description": "日期,如 今天/明天/2026-06-04" }
}
}
模型生成调用请求:
{
"tool": "weather_query",
"parameters": {
"city": "北京",
"date": "明天"
}
}
[3] 系统执行:调天气 API,得到 {"temp": "22°C", "condition": "晴"}
[4] LLM 生成:"北京明天天气晴朗,气温 22°C,适合出门。"
Plugin → Function Calling 的代际差
| 维度 | Plugin(已废弃) | Function Calling |
|---|---|---|
| 谁选择工具 | 用户手动安装和启用插件 | LLM 自己判断需要用哪个工具 |
| 工具数量 | 每次对话只能用 1-3 个插件 | 理论上可以同时用几十个工具 |
| 调用方式 | 每次对话只能用 1-3 个 | 原生 JSON Schema 定义,模型内置输出格式 |
| 用户体验 | 用户要先"装插件"——门槛高 | 用户无感知——模型自己决定调不调 |
范式跃迁:用户不需要知道"有什么工具可以用",模型自己知道。
MCP — Agent 的 USB-C
MCP(Model Context Protocol)是 Agent 调用外部工具的标准化协议。只要工具方按 MCP 标准暴露接口,任何 Agent 都能直接接入,不需要写适配代码。
Chat interface ┐ ┌ Data and file systems
Claude Desktop, │ │ PostgreSQL, SQLite, GDrive
LibreChat │ │
│ ← MCP → │
IDEs and code editors │ Standardized │ Development tools
Claude Code, Goose │ protocol │ Git, Sentry, etc.
│ │
Other AI applications │ │ Productivity tools
5ire, Superinterface ┘ ┘ Slack, Google Maps, etc.
AI applications Data sources and tools
MCP 三层架构
| 层 | 作用 |
|---|---|
| MCP Client | 通过 MCP 协议与 Servers 通信,并保持 1:1 连接 |
| MCP Servers | 上下文提供方,暴露外部数据源(Resources)、工具(Tools)、提示词(Prompts)等由 Client 进行调用 |
| 语言支持层 | TypeScript、Python、Java、Kotlin、C# |
MCP 工作时序(一次调用)
MCP Client MCP Server LLM
│ │ │
│ Request Resources │ │
│ /Prompts │ │
├───────────────────→│ │
│←───────────────────┤ │
│ Return Resources/Prompts │
│ │
│ Send Query + Available Tools List │
├────────────────────────────────────→│
│ │
│ alt: [LLM Needs Additional Info] │
│←────────────────────────────────────┤
│ Return Instruction: Use Specific Tool│
│ (e.g., Tool X) │
│ │ │
│ Invoke Tool (Tool X) │
├───────────────────→│ │
│←───────────────────┤ │
│ Return Tool Execution Result │
│ │
│ Resend Query + Tool Execution Result│
├────────────────────────────────────→│
│←────────────────────────────────────┤
│ Return Final Result │
│ │
│ alt: [LLM Has Sufficient Info] │
│←────────────────────────────────────┤
│ Return Final Result │
前后端区分
MCP 解耦了"做 Agent 的人"和"做工具的人"——
┌───────────────────────────────────────────────────────┐
│ AI Agent Application │
│ │
│ 🧑 AI Agent ┌──────────┐ ┌──────────┐ ┌───────┐│
│ Developer │ Prompt │ │ Agent │ │Prece- ││
│ │Engineering│ │ Loop │ │ption ││
│ └──────────┘ └──────────┘ └───────┘│
│ ┌──────────┐ ┌──────────┐ ┌───────┐│
│ │ Memory │ │MCP Client│ │Planning││
│ └──────────┘ └─────┬────┘ └───────┘│
└─────────────────────────────────────┬─┘────────────────┘
↓
Protocol: SSE / Stdio / HTTP / In-memory
↓
┌──────────────────────────────────────┬────────────────┐
│ 🧑 MCP Server │ │
│ Developer — dev/publish → ┌──┴────────────┐ │
│ │ MCP Server │ │
│ │ (npm/pypi/ │ │
│ │ binary) │ │
│ └───────────────┘ │
└────────────────────────────────────────────────────────┘
- AI Agent Developer 负责把 LLM + Memory + Planning + MCP Client 组装成应用
- MCP Server Developer 负责把工具/数据源按 MCP 标准暴露
- 二者通过 SSE / Stdio / HTTP / In-memory 协议通信
- 一个 MCP Server 写一次,所有支持 MCP 的 Agent 都能用——这就是生态层的标准化价值
FC 与 MCP 不是替代关系
Function Calling 和 MCP 不是替代关系,而是上下层关系:
| 层 | 解决的问题 |
|---|---|
| FC:模型层 | LLM 能输出结构化的工具调用请求 |
| MCP:协议层 | 定义了工具调用请求的统一格式和通信方式 |
FC 在上,MCP 在下,二者配合才完整。
类比:FC 是"模型能说出'我要点咖啡'",MCP 是"咖啡店和顾客之间用什么语言沟通的标准"。两者是不同层次的事,缺一不可。
Code Execution with MCP — 当前最前沿的范式升级
问题:当 Tool 很多、Token 很贵时怎么办?
一个编程 Agent 接入了 6-8 个 MCP Server,Token 消耗大致是这样:
| 组成部分 | Token 消耗 |
|---|---|
| System Prompt | ~1,000 Token |
| Tool 定义(30+ 工具,每个约 150-200 Token) | ~5,000-6,000 Token |
| 用户输入 + 历史对话 | ~2,000-4,000 Token |
| 中间结果 + 工作记忆 | ~3,000-5,000 Token |
| 总计 | ~11,000-16,000 Token |
解决方案:把 30 个 Tool 替换成一个 execute_code 工具,让 LLM 写 Python 代码按需导入 MCP Server。
传统方式 vs 新范式对比
传统方式 新范式(Claude Code 实践)
───────── ──────────
LLM context 里放着 30 个 Tool 的定义 LLM context 里只放一个 Tool:execute_code
(每个约 150-200 Token) (约 200 Token)
LLM 从 30 个里选一个调用 LLM 写一段 Python 代码来调用需要的 MCP Tool
Token 消耗巨大 代码执行环境按需加载 MCP Server 的定义
Token 消耗大幅降低
1. LLM Context(包含大量 Tool 定义) 1. LLM Context(只有一个 Tool)
Tool 1, Tool 2, Tool 3, ... Tool 30 Tool: execute_code
(150-200 Token 每个) (≈ 200 Token)
≈ 30 × 150-200 Token = 4,500-6,000 Token
2. LLM 生成 Python 代码调用 MCP Tool
2. LLM 选择并调用一个 Tool from mcp import MCPClient
client = MCPClient("filesystem")
3. Tool 执行 result = client.read_file("path/to/file.txt")
数据库 → 搜索 → 云服务 → 分析 → 邮件 → 文件系统 print(result)
3. 代码执行环境(按需加载 MCP Server)
代码执行环境 ←→ Filesystem / Database /
Search / Git MCP Server
对比维度
| 对比维度 | 传统方式(30 个 Tool) | 新范式(Claude Code) | 优势 |
|---|---|---|---|
| LLM Context 大小 | ≈ 4,500-6,000 Token | ≈ 200 Token | 降低 95%+ |
| Token 消耗 | 巨大(每次调用都要带上所有 Tool 定义) | 极小(只带一个 execute_code) | 大幅降低成本 |
| 扩展性 | 差(Tool 越多,context 越大) | 优秀(Tool 数量不影响 context 大小) | 无限扩展 |
| 灵活性 | 受限于预定义的 30 个 Tool | 通过代码可调用任意 MCP Tool | 极高灵活性 |
| 维护成本 | 高(每新增一个 Tool 都要更新 LLM context) | 低(新增 MCP Server,无需改 LLM context) | 易于维护 |
真实示例:GitHub Issue → Jira Task
传统方式:
Context 里放着 github_list_issues + github_read_issue +
jira_create_issue + 其他 27 个 Tool 的定义(~5000 Token)
LLM 推理:"我需要先从 GitHub 拉 Issue..."
调用:github_list_issues(repo="...")
拿到结果...
调用:github_read_issue(issue_id=42)
拿到结果...
调用:jira_create_issue(title="...", description="...")
Code Execution 方式(Claude Code 范式):
Context 里只放一个 Tool:execute_code 的定义(~200 Token)
LLM 写代码:
from mcp import github, jira
issue = github.get_issue(repo="org/repo", id=42)
jira.create_issue(
title=f"[Sync] {issue.title}",
description=issue.body,
labels=["synced-from-github"]
)
系统执行这段代码 → 代码里按需导入 MCP Server
Token 节省:从 ~5000 Token(30 个 Tool 定义,每个约 150-200 Token)降到 ~200 Token(execute_code 定义)+ ~300 Token(生成的代码)。
PM 视角:什么时候用哪种
- 少量工具(<10 个):直接 Function Calling,简单直接
- 中等工具(10-30 个)+ 跨产品复用:Function Calling + MCP,享受生态红利
- 大量工具(30+ 个)或者 Token 成本敏感:Code Execution with MCP,Token 降 95%+
相关页面
→ Agent五要素技术定义 → Agent工具与行动 → Agent vs Workflow → RAG(MCP 是工具调用层,与 RAG 的"外挂知识"是平行机制) → 模型选型方法论(FC 稳定性是模型选型的核心维度之一) → AIPM课程 Day10