MCP 不是 API,是大模型的手:Function Calling 之后,AI Agent 落地的正确姿势
一、那个让你想砸键盘的场景
凌晨两点,你刚把「智能客服」上线,老板在群里甩了一张截图:用户问「我的订单到哪了」,AI 回了三百字散文诗,半个字没提物流状态。你打开代码,发现为了接订单、物流、售后、知识库四个系统,你已经写了 17 个 adapter、8 套鉴权、3 种错误处理。更崩溃的是,业务方明天要加一个新系统,你预估又得改 6 个文件,联调 2 天。
这不是大模型不行,是你把它当成了一只「只会说话的鹦鹉」,却指望它自己伸手去柜子里拿东西。大模型没有手,Function Calling 只是它「说出想拿什么」的能力;真正把手伸进业务系统的,是一套标准化的连接层。2026 年,这套连接层已经有了事实标准——MCP(Model Context Protocol,模型上下文协议)。
二、Function Calling 已经够好了,问题在哪?
Function Calling 不是新技术。OpenAI 在 2023 年就推出了工具调用能力:你给模型一段 JSON Schema,模型在需要时返回一段结构化调用指令,程序再帮你执行。简单场景下,它的工作流很干净:
# 一个最简的 Function Calling 示例
tools = [{
"type": "function",
"function": {
"name": "query_order",
"description": "根据订单号查询物流状态",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "订单号"}
},
"required": ["order_id"]
}
}
}]
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "我的订单 20260817001 到哪了"}],
tools=tools
)
模型收到请求后,会输出类似这样的结构:
{
"tool": "query_order",
"arguments": {"order_id": "20260817001"}
}
看起来不错。但当业务系统从 1 个变成 10 个,Function Calling 的短板会逐个暴露:
| 痛点 | 裸写 Function Calling 时 | 接入 MCP 后 |
|---|---|---|
| 工具定义位置 | 硬编码在应用里,每换一个客户端要重写 | 写在 MCP Server 里,一次定义,到处复用 |
| 新增外部系统 | 改代码、加鉴权、写 adapter,3 天起步 | 配置一个 MCP Server,30 分钟联调 |
| 多模型兼容 | OpenAI / Anthropic / 文心 / DeepSeek 的 schema 格式各不同 | MCP Client 自动转换,模型无感知 |
| 动态发现 | 工具列表写死,上线后加工具必须发版 | 启动时 tools/list,运行时动态发现 |
| 错误处理 | 每个接口一种错误格式,模型看不懂 | MCP 层统一归一化,返回结构化错误 |
| 安全边界 | 应用直接拿 API Key 调外部系统 | 凭据留在 MCP Server,应用只发指令 |
一句话总结:Function Calling 解决的是「模型如何把意图表达成结构化调用」,MCP 解决的是「这个调用如何安全、标准、可复用地落到外部系统」。二者不是竞争关系,是上下层关系。
三、MCP 到底是什么:不是替代,是分层
很多人把 MCP 误解成「另一种 Function Calling」,这是错的。Function Calling 是模型原生能力,MCP 是工程协议。看下面这张图:

大模型"我要调这个工具"Function Calling 层:模型和程序之间的"语法"把自然语言意图 → 转成 {tool: "xxx", arguments: {...}} 结构化输出MCP 层:应用和外部系统之间的"管道"负责发现工具、路由调用、协议转换、鉴权、错误归一化模型能力工程协议OpenAI / Anthropic / Google 各有格式跨模型、跨客户端复用
打个比方:Function Calling 是大模型的「语言」,MCP 是连接大模型和现实世界的「手与神经系统」。手长什么样、怎么动,由 MCP Server 描述;模型只负责说「我要动这只手」。
再看一张架构对比图,左边是多数团队现在的处境,右边是 MCP 落地后的样子:

Before:裸写 Function Calling大模型 LLM你的应用订单适配物流适配KB订单 API物流 API文档After:MCP 标准化接入大模型 LLM你的应用MCP Client订单 Server物流 ServerKB Server
MCP 的核心理念就一句话:写一次 Server,到处复用。Claude Code、Cursor、ChatGPT Desktop、Cherry Studio、你自己的 Agent,都能连同一个 MCP Server。业务系统换了 API 版本,只改 Server 不改 Agent。
四、一次完整的 MCP 调用长什么样?
别被协议吓到。一次 MCP 调用,本质上和 Function Calling 没差多少,只是中间多了两层:
用户提问
│
▼
[大模型 LLM] 判断需要调用工具
│
▼
[Function Calling] 输出 {tool: "query_order", arguments: {...}}
│
▼
[你的应用] 把调用请求交给 MCP Client
│
▼
[MCP Client] 根据 tool 名路由到对应 MCP Server
│
▼
[MCP Server] 执行真实业务逻辑(查数据库 / 调 API / 读文件)
│
▼
[外部系统] 返回结果
│
▲
结果沿原路返回,LLM 用自然语言组织最终回答
用图表示更直观:

用户提问大模型 LLM决定调用工具你的应用Function CallingMCP ClientMCP Server外部 API / 数据库结果逐层返回输出结构化 JSON模型不会直接调用 API
注意一个关键点:模型自始至终不直接认识 MCP。模型输出的是 Function Calling 结构,MCP Client 负责把这个结构翻译成对某个 MCP Server 的 JSON-RPC 调用。这意味着你可以把 GPT-4o、Claude、DeepSeek、通义千问接在同一个 MCP Server 上,它们各自用自己的 Function Calling 格式说话,MCP Client 做翻译。
五、实战:15 分钟搭一个能查数据库的 MCP Server
理论讲完,上一段能直接跑的代码。用 Python + FastMCP 写一个「查询业务数据库」的 MCP Server,工具就一个:query_revenue(按日期查营收)。
环境准备:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install mcp[cli] httpx uvicorn
server.py:
from mcp.server.fastmcp import FastMCP
import sqlite3
mcp = FastMCP("business-db-server")
@mcp.tool()
def query_revenue(date: str) -> str:
"""
查询指定日期的总营收。
参数:
date: 日期字符串,格式 YYYY-MM-DD
返回:
该日期总营收金额(元)
"""
conn = sqlite3.connect("/path/to/business.db")
cursor = conn.cursor()
cursor.execute(
"SELECT SUM(amount) FROM orders WHERE date = ?",
(date,)
)
row = cursor.fetchone()
conn.close()
total = row[0] if row and row[0] else 0
return f"{date} 的营收为 {total} 元"
if __name__ == "__main__":
mcp.run(transport="stdio")
就这么短。FastMCP 会自动做三件事:
-
从类型注解生成 JSON Schema;
-
注册
tools/list和tools/call两个 MCP 标准端点; -
通过 stdio 与你的 Agent 通信。
客户端配置(以 Cherry Studio / Claude Desktop 为例):
{
"mcpServers": {
"business-db": {
"command": "python",
"args": ["/absolute/path/to/server.py"]
}
}
}
保存后重启客户端,你的 Agent 就会多出一个叫 query_revenue 的工具。用户问「昨天营收多少」,模型自己会调用它,不需要你写任何调用代码。
六、生产落地的三个真坑
代码能跑只是开始。把 MCP 搬进生产环境,下面这三个坑我几乎每次都会遇到。
坑 1:MCP Server 的「描述」就是 prompt,写不好模型会乱调
MCP Server 里的 description 不是给人类看的注释,是原封不动塞进模型上下文的 prompt。如果你写:
@mcp.tool()
def query_revenue(date: str) -> str:
"""查询营收"""
模型根本搞不清 date 要什么格式,也分不清这个工具和你另一个 query_order 工具的区别。正确写法要包含:工具是干什么的、参数格式、返回什么、什么时候不该用。
@mcp.tool()
def query_revenue(date: str) -> str:
"""
查询指定日期的总营收。仅用于回答与营收相关的问题。
参数 date 必须是 YYYY-MM-DD 格式,例如 2026-08-17。
返回字符串形式的金额,单位元。
"""
这个 description 会占用模型上下文 token,写太啰嗦会拖慢响应、增加费用;写太简单模型会乱调用。需要反复测。
坑 2:把 MCP Server 当成「万能网关」,什么权限都开
见过有人一个 MCP Server 连了生产数据库,还给了写权限。Agent 一句话「把用户表删了」,Server 真的执行。MCP 协议本身不解决权限问题,权限是你自己设计的。
生产上建议的三条铁律:
-
只读优先:除非明确需要写操作,否则数据库账号只给 SELECT;
-
白名单工具:一个 Server 只暴露最小集合的工具,别把整个 API 都挂上去;
-
人在回路(Human-in-the-loop):写操作必须二次确认,别让它自动执行转账、删表、发邮件。
坑 3:以为 MCP 能解决所有延迟问题
MCP 加了一层网络跳转,stdio 本地还好,Streamable HTTP 远程 Server 通常会增加 200~500ms 延迟。如果.Agent 一次对话要串行调 5 个工具,延迟会叠加。优化手段有两个:
-
并行调用:没有依赖的工具让 LLM 一次性返回多个 tool_calls,同时执行;
-
本地优先:高频、低延迟的工具用 stdio 本地 Server,远程 Server 只放重逻辑。
七、Before / After:效果到底差多少?
回到开篇那个智能客服项目。接入 MCP 前后,维护成本和扩展性完全不是一个量级:
| 指标 | 裸写 Function Calling | MCP 标准化接入 |
|---|---|---|
| 新增一个外部系统 | 3 天(adapter + 鉴权 + 测试) | 30 分钟(写一个 Server) |
| 接入第二个客户端 | 重写工具定义 | 直接复用现有 Server |
| 工具描述维护 | 散落在应用代码里 | 集中在 Server 内 |
| 多模型切换 | 每模型改 schema | 由 MCP Client 自动适配 |
| 安全边界 | 应用直连外部 API | 凭据收敛在 Server |
| 故障定位 | 接口各自报错 | 错误格式统一 |
核心收益不是某一次开发变快,而是系统之间的耦合被切开了。业务系统怎么变,不影响 Agent;Agent 怎么变,不影响业务系统。
八、写在最后
2026 年的 AI 落地,早已过了「接个 API 就能 demo」的阶段。现在拼的是:同样的模型,谁能更安全、更稳定、更可维护地把它接到真实业务里。
Function Calling 是大模型的嘴和耳朵,让它能听懂和表达;MCP 是大模型的手和脚,让它能真正操作外部世界。二者缺一,Agent 都只能是玩具。
如果你现在正打算做一个「能查数据、能调系统、能干活」的 AI 应用,别再从零写 adapter 了。先写一个 MCP Server,把业务能力标准化地暴露出来,剩下的交给模型自己决定怎么调。这才是 2026 年工程化的正确姿势。
参考与备注
-
MCP 官方协议规范:Specification - Model Context Protocol
-
Anthropic 发布 MCP 的背景与演进(2024-11 初版、2026-07 无状态化重构):Anthropic 官方博客及协议变更日志。
-
Function Calling 与 MCP 分层关系参考:The Prompt Bench, "MCP vs Function Calling: Different Layers, Not Rivals", 2026。
-
生产环境 MCP 安全实践参考:QVeris AI Benchmark (2026-04) 及 Anthropic MCP 安全文档。
-
本文代码示例基于 Python 3.12 + FastMCP 编写,数据库路径、模型名称请按实际环境替换。
本文为原创技术实践总结,基于公开协议与个人项目落地经验整理。文中涉及的第三方服务与 SDK 接口规范,请以各官方最新文档为准。
更多推荐
所有评论(0)