一、那个让你想砸键盘的场景

凌晨两点,你刚把「智能客服」上线,老板在群里甩了一张截图:用户问「我的订单到哪了」,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 会自动做三件事:

  1. 从类型注解生成 JSON Schema;

  2. 注册 tools/listtools/call 两个 MCP 标准端点;

  3. 通过 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 CallingMCP 标准化接入
新增一个外部系统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 年工程化的正确姿势。


参考与备注

  1. MCP 官方协议规范:Specification - Model Context Protocol

  2. Anthropic 发布 MCP 的背景与演进(2024-11 初版、2026-07 无状态化重构):Anthropic 官方博客及协议变更日志。

  3. Function Calling 与 MCP 分层关系参考:The Prompt Bench, "MCP vs Function Calling: Different Layers, Not Rivals", 2026。

  4. FastMCP 开发框架:GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients · GitHub

  5. 生产环境 MCP 安全实践参考:QVeris AI Benchmark (2026-04) 及 Anthropic MCP 安全文档。

  6. 本文代码示例基于 Python 3.12 + FastMCP 编写,数据库路径、模型名称请按实际环境替换。

本文为原创技术实践总结,基于公开协议与个人项目落地经验整理。文中涉及的第三方服务与 SDK 接口规范,请以各官方最新文档为准。

更多推荐