三种工具调用方式根本不在一个层级:Function Calling(函数调用)是模型输出结构化参数的能力,内置工具是平台送的现成货,MCP(Model Context Protocol,模型上下文协议)是把外部程序接进来的通信协议。选错的典型代价是延迟变高、上下文被撑爆,而不是「谁更先进」。
目录
-
- 三种方式站在不同的楼层
-
- 内置工具:平台给的现成货
-
- 本地 tools(工具):自己厨房现做
-
- MCP(模型上下文协议):给外部程序装的标准插座
-
- 选错方式的五类症状
-
- 一段能直接跑的本地 tool(工具)分发代码
-
- 面试高频追问三连
-
- 小结:先分层,再选型
1. 三种方式站在不同的楼层
面试官问「为什么不直接用本地 tools(工具),非要上 MCP(模型上下文协议)」,陷阱在于:这道题默认三者是竞品。它们不是竞品,是三层不同的东西。
- Function Calling(函数调用) :模型层能力。模型不执行任何代码,它只是吐出一段符合约定格式的 JSON(JavaScript 对象表示法),告诉你「我想调
get_weather,参数是{"city": "杭州"}」,真正的执行发生在你的应用里。 - 内置工具:平台层能力。搜索、代码解释器这类能力由平台或模型厂商自己实现,你只能开关,改不了实现。
- MCP(模型上下文协议):协议层能力。它规定的是「一个工具服务端怎么把能力描述给客户端、怎么接收调用、怎么回传结果」,跟模型本身没有绑定关系。
一句话记住:Function Calling(函数调用)管「模型怎么开口」,MCP(模型上下文协议)管「工具怎么接进来」。一个是嘴,一个是插座,不冲突,还经常一起用。
🤔 顺带吐槽:把这三个当成「本地版 vs 云端版」来背,就像把「说中文」和「用微信」当成两种语言,说出来面试官只能礼貌微笑。
2. 内置工具:平台给的现成货
内置工具是成本最低的一档。你不需要写代码,也不需要部署,勾一下就多一个能力。
它的边界也很清楚:
- 能改的少:参数、返回格式、超时策略基本由平台定,你只能整体接受或整体关掉。
- 黑盒:内部怎么检索、怎么截断、怎么计费,你看不到。
- 适合谁:验证想法、做 demo(演示)、跑通链路。原型阶段用它最省事。
但一旦业务需要「把公司内部知识库接进来」或者「调用我们自己的订单系统」,内置工具就无能为力了------它不可能认识你的私有系统。
3. 本地 tools(工具):自己厨房现做
本地 tools(工具)就是写在你自己服务进程里的函数,通过 Function Calling(函数调用)暴露给模型。模型输出 tool_call(工具调用)意图,你的代码解析后直接调本地函数。
它的优势非常实在:
- 快:函数调用就是同进程内的一次跳转,没有网络往返,延迟通常在毫秒级。
- 好调试:断点一打,栈一跟,问题在哪一目了然。
- 依赖少:拿个当前时间、做个四则运算、查一下本地缓存,这类工具写成 MCP(模型上下文协议)server(服务端)纯属给自己加戏。
它的天花板也很明确:
- 跟着应用走:换一个客户端,工具定义就得重写一遍。
- 同生共死:工具和应用在一个进程里,工具崩了应用一起遭殃。
- 权限混在一起:所有工具共享应用的凭证,出了问题很难界定是谁越权。
所以本地 tools(工具)适合 简单、高频、依赖少、不需要跨应用复用 的场景。这不是「低配版」,而是正确的工具。
4. MCP(模型上下文协议):给外部程序装的标准插座
MCP(模型上下文协议)解决的是另一类问题:工具根本不在你的进程里,它可能是一个独立部署的服务、一个第三方程序、一个别人的系统。
它把这件事标准化了:外部程序按协议描述自己的能力,客户端按协议发现和调用,中间不关心对面用什么语言写的。
什么时候值得上 MCP(模型上下文协议),判断条件其实只有三条:
- 依赖重、环境复杂:工具要装一堆运行时依赖,塞进主应用只会让依赖打架。
- 要独立部署、独立伸缩:工具自己想扩容、想灰度、想单独重启,不该拖着主应用一起。
- 要隔离权限和故障:外部工具崩了不能把主链路带崩,凭证也不该共享。
反过来说,MCP(模型上下文协议)不是免费午餐:多一层协议就多一次序列化、多一跳网络、多一份要维护的部署和鉴权。把高频小工具全搬上去,延迟和故障点都会跟着涨。
🍜 打个比方:本地 tools(工具)像自家厨房,想吃什么现做,快但只能喂自己;MCP(模型上下文协议)像外卖平台,谁都能点、商家可以独立经营,但你要等骑手,还要接受商家偶尔把汤洒了。
5. 选错方式的五类症状
| 症状(Symptom) | 原因(Cause) | 解法(Fix) |
|---|---|---|
| 一个查时间的工具也要走网络,延迟从毫秒涨到几十毫秒 | 把协议层用在了内部高频短路径上 | 简单、高频、依赖少的工具留在本地 Function Calling(函数调用) |
| 工具一多,prompt(提示词)被工具描述撑爆,token(词元)成本飙升 | MCP(模型上下文协议)会把成批的 tool schema(工具模式)塞进上下文 | 只暴露当前任务需要的工具,其余按需加载 |
| 某个外部服务挂了,整个 agent(智能体)跟着不可用 | 工具与应用同进程,没有故障边界 | 把不稳定依赖拆成独立 MCP(模型上下文协议)server(服务端) |
| 同一套工具要接三个客户端,改一次要改三份代码 | 每个应用各写一遍 Function Calling(函数调用) | 抽成 MCP(模型上下文协议)server(服务端)统一复用 |
| 出事后说不清是哪个工具越权 | 所有工具共享应用凭证 | MCP(模型上下文协议)server(服务端)单独持权、单独审计 |
这张表的用法是倒着看:先看自己有没有出现左边某一栏的症状,有症状才改架构,没症状就别动。为了「技术先进」而提前引入协议层,是典型的过度设计。
6. 一段能直接跑的本地 tool(工具)分发代码
不管走哪条路,本地这一侧的骨架都一样:注册工具、解析模型的调用意图、分发执行。下面这段只用标准库,复制就能跑。
python
import json # 解析模型吐出的 JSON 调用意图
from datetime import datetime, timedelta, timezone # 拼当前时间,演示无依赖小工具
from typing import Any, Callable # 类型标注,说明注册表存的是可调用对象
REGISTRY: dict[str, Callable[..., str]] = {} # 工具注册表:工具名 → 函数
def tool(name: str): # 装饰器工厂,用于注册工具
def register(fn: Callable[..., str]) -> Callable[..., str]: # 真正执行注册的内层函数
REGISTRY[name] = fn # 把函数按名字存进注册表
return fn # 原样返回函数,便于链式使用
return register # 返回装饰器
@tool("get_time") # 注册「查当前时间」工具
def get_time() -> str: # 无参数,返回格式化时间字符串
return datetime.now(timezone(timedelta(hours=8))).strftime("%Y-%m-%d %H:%M") # 东八区当前时间
@tool("add") # 注册「两数相加」工具
def add(a: float, b: float) -> str: # 接收两个数字参数
return str(a + b) # 计算结果转字符串回传
def dispatch(tool_call: str) -> str: # 分发器:处理模型给的调用意图
call: dict[str, Any] = json.loads(tool_call) # 反序列化成字典
fn = REGISTRY.get(call["name"]) # 按名字查注册表
if fn is None: # 工具不存在时兜底
return f"unknown tool: {call['name']}" # 返回明确错误,不静默失败
return fn(**call["arguments"]) # 用命名参数调用目标工具
print(dispatch('{"name": "add", "arguments": {"a": 2, "b": 3}}')) # 输出 5
print(dispatch('{"name": "get_time", "arguments": {}}')) # 输出当前时间
真实场景里,传给 dispatch 的那段 JSON 不是人手写的,而是模型返回的 tool_call(工具调用)。MCP(模型上下文协议)这一侧替换的只是「谁来发现工具、谁来传输调用」,dispatch 这种执行逻辑照样存在。
7. 面试高频追问三连
追问一:MCP(模型上下文协议)能替代 Function Calling(函数调用)吗?
不能。模型仍然要靠 Function Calling(函数调用)来决定调哪个工具、传什么参数,MCP(模型上下文协议)只负责把工具服务和客户端连起来。两者是上下游关系,不是替代关系。
追问二:为什么有的团队上了 MCP(模型上下文协议)又迁回 API(应用程序接口)直调?
因为上下文开销和维护成本被低估了。工具描述、返回结构、调用轨迹都会进上下文,工具一多就是持续的 token(词元)消耗;再加上每个 server(服务端)都要部署、鉴权、监控、处理故障,团队规模撑不住时,直调 API(应用程序接口)反而更划算。
追问三:怎么判断该不该上 MCP(模型上下文协议)?
看三个条件:工具是否需要独立部署、是否要被多个客户端复用、是否需要权限与故障隔离。三个都是「否」,就老实写本地 tools(工具);有一个是「是」,再考虑抽 MCP(模型上下文协议)server(服务端)。
8. 小结:先分层,再选型
回到那道面试题。「为什么不直接用本地 tools(工具)」这个问法本身就有问题------本地 tools(工具)不是落后者,它是最短路径。真正要回答的是:这个工具属于哪一层。
- 简单、高频、进程内能解决 → 本地 Function Calling(函数调用)。
- 想快速验证、不挑实现 → 内置工具。
- 跨应用复用、独立部署、权限与故障隔离 → MCP(模型上下文协议)。
先把层级分清,选型就变成填表题;分不清层级,才会在「本地还是外部」这种伪命题里绕圈。面试官真正想听的,不是名词解释,而是你能说清楚 每个选择背后的代价。
参考资料:
- MCP vs Function Calling: What's the Difference? (2026) -- Top MCPs
- MCP vs Function Calling -- Context Studios
- MCP in Agentic AI vs Function Calling -- DEV Community
- When to Use MCP -- OWASP MCP Top 10 Security Guidance
- MCP in Production: When It Works, When It Breaks -- Tensoria
- MCP、Function Calling、插件系统到底有什么区别?-- CSDN
最后更新时间:2026-10-24