Function Calling 和 MCP 常被当作竞争关系,实际是两个层面的东西:前者是模型的原生能力(模型知道怎么"调用函数"),后者是生态的接入协议(函数从哪来、结果怎么回)。真正的选型题是:工具定义放在应用里,还是放到独立的服务进程里。

Function Calling:应用内一体化

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "schema": {...}
    }
}]
resp = llm.chat(messages, tools=tools)   # 工具定义随请求发送
result = execute(resp.tool_calls)         # 应用自己执行

优点:零额外进程、延迟最低(无进程间通信)、全部逻辑在一处、调试直接看请求体。 适用:工具数量少(<20)、团队单一、工具与应用强耦合的业务逻辑。

短板:工具定义散落在各应用代码里,重复实现;换模型供应商时各家的 schema 细节差异要逐一适配;没有统一的生命周期管理。

MCP:独立服务化

工具从应用代码里剥离成独立 Server,应用通过协议消费:

优点:一次实现处处接入(Claude、IDE、自研 Agent 共用同一个 Server);语言无关(Server 用 Python,Host 用 Rust);进程隔离带来安全边界;生态复用——现成的 GitHub/数据库/浏览器 Server 拿来就用。 成本:多一层进程与协议开销;需要管理 Server 的启动、健康、权限;调试链路变长。

选型决策表

场景 建议
单应用、少量私有业务工具 Function Calling,简单直接
工具需要被多个应用/团队复用 MCP
想直接用社区现成工具生态 MCP(GitHub/Slack/DB Server 现成)
极低延迟场景(流式对话中的工具) Function Calling(省一跳)
本地开发者工具(读文件、跑命令) MCP(stdio 传输,天然本地化)

混合才是常态

成熟的 Agent 系统通常两层并存:高频私有逻辑走 Function Calling 内联执行,通用能力(检索、代码执行、第三方 API)挂 MCP Server。模型不区分两者——它看到的都是"可调用的工具";差异只存在于应用的工程结构里。

一句话总结:Function Calling 决定模型能不能用工具,MCP 决定工具从哪里来。先有前者(能力),再长出后者(生态)——你的选型跟着工程结构走,而不是跟着新闻热度走。