两个问题
MCP 的架构优势在第 01 篇已经讲清楚了:工具标准化复用。工程师在实际选型时会追问两个更具体的问题:
- MCP 的进程通信开销有多大,会影响用户体验吗?
- 代码量上,MCP 什么时候比 Function Calling 更划算?
下面用真实基准测试数据回答。
基准测试设计
测试对象:同一个"搜索 Issues"功能
- 方案 A(Function Calling):工具定义和执行逻辑写在 Agent 代码里,直接 Python 函数调用
- 方案 B(MCP):工具在独立 Server 进程中,通过 stdio 子进程通信
每种方案各跑 20 次调用(5 次热身不计),记录 P50/P90/均值。
延迟测量结果
sql
Method Mean P50 P90 Min
──────────────────────────── ──────── ──────── ──────── ────────
Direct function call 0.01ms 0.01ms 0.01ms 0.005ms
MCP stdio call 2.09ms 2.05ms 2.37ms 2.00ms
MCP overhead per call: +2.08ms (283x slower than direct)
MCP server startup (one-time): 570ms
Calls to amortize startup cost: ~274
283x 听起来很吓人。换个角度看:每次 LLM 推理需要 5-30 秒,工具调用只是其中一环。在这个时间尺度上,2ms 的协议开销完全不可感知。
2ms 开销什么时候才有影响:
markdown
Agent 任务:LLM 推理 15s + 工具调用 2ms → 开销占比 0.01%
→ 忽略不计
实时聊天机器人:目标响应 < 200ms,工具调用在关键路径上
→ 需要评估
高频自动化:每秒调用 100 次工具 → 2ms × 100 = 200ms 额外延迟/秒
→ 需要评估
MCP Server 是子进程,每次会话启动时初始化一次,之后所有工具调用共用这个进程。调用超过 274 次(570ms / 2.08ms),总延迟与 Function Calling 持平。普通 Agent 任务的工具调用次数远超 274,启动成本很快摊销。
代码规模测量结果
vbscript
Function Calling(工具定义 + handler + Agent 循环):43 行
MCP Server(独立进程,含完整 Server): 32 行
MCP Agent 代码(无工具代码): 0 行
单项目差异不大(43 vs 32 行),随项目数量增长差距拉开:
ini
共享同一工具的项目数 Function Calling 总行数 MCP 总行数 MCP 节省
──────────────────────────────────────────────────────────────────────
N=1 43 32 11 行
N=2 86 32 54 行
N=3 129 32 97 行
N=5 215 32 183 行
Function Calling 的代码量线性增长,每个 Agent 独立维护工具代码。MCP Server 只写一次,代码量不随项目数量变化。
为什么 283x 不是选型的主要依据
原始倍数容易误导决策。工具调用的实际成本由三部分组成:
javascript
总延迟 = LLM 推理时间 + 工具执行时间 + 协议开销
典型场景:
LLM 推理: 8,000ms
工具执行(Jira): 200ms
MCP 协议开销: 2ms
─────────────────────────
总计: 8,202ms
Function Calling:8,200ms(无协议开销)
MCP: 8,202ms(+2ms)
差异:0.024%
协议开销在 LLM 推理面前几乎不存在。选 MCP 还是 Function Calling,延迟不是决定因素。
决策框架
核心问题:这个工具会被多少个项目使用?
vbscript
使用项目数 = 1,且:
工具逻辑 < 30 行
Agent 快速原型,不确定是否长期用
→ Function Calling
使用项目数 >= 2,或:
工具需要状态管理(连接池、认证 Session)
非工程师需要能安装配置这个工具(Claude Desktop 生态)
团队想统一维护工具标准
→ MCP Server
不适合 MCP 的场景:
每次调用 < 10ms 的实时性要求(API 网关、实时推荐)
工具与 Agent 逻辑高度耦合,分离没有意义
Agent 生命周期极短(< 100 次工具调用)且对启动时间敏感
一张图总结选型逻辑:
vbscript
工具复用次数(N个项目 × M次调用)
│
├── 单项目、低频 ────────────→ Function Calling(代码简单)
│
├── 多项目共享 ─────────────→ MCP Server(复用收益明显)
│
├── 需要状态 ───────────────→ MCP Server(进程管理状态)
│
└── 实时性 < 10ms ──────────→ Function Calling(无协议开销)
两种写法并排对比
同一个"搜索 Issues"功能,完整实现代码:
Function Calling(43 行,工具逻辑在 Agent 里):
python
# 工具定义
SEARCH_TOOL = {
"name": "search_issues",
"description": "Search Jira issues by keyword",
"input_schema": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
}
}
# 工具实现
def search_issues(query: str) -> str:
results = [i for i in ISSUES if query.lower() in i["summary"].lower()]
return "\n".join(f"[{i['key']}] {i['summary']}" for i in results)
# Agent 循环(每个 Agent 都要写这段)
def run_agent(user_input: str):
client = anthropic.Anthropic()
messages = [{"role": "user", "content": user_input}]
while True:
response = client.messages.create(model="claude-sonnet-4-6",
tools=[SEARCH_TOOL], messages=messages)
if response.stop_reason != "tool_use":
return response.content[0].text
tc = next(b for b in response.content if b.type == "tool_use")
result = search_issues(tc.input["query"])
messages.extend([...]) # 添加工具结果
MCP Server(32 行 Server,Agent 代码 0 行工具代码):
python
# jira_server.py(一次性写,所有 Agent 复用)
server = Server("jira-tools")
@server.list_tools()
async def list_tools():
return [Tool(name="search_issues", description="Search issues",
inputSchema={"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]})]
@server.call_tool()
async def call_tool(name, arguments):
query = arguments["query"].lower()
results = [i for i in ISSUES if query in i["summary"].lower()]
text = "\n".join(f"[{i['key']}] {i['summary']}" for i in results)
return [TextContent(type="text", text=text)]
async def main():
async with stdio_server() as (r, w):
await server.run(r, w, server.create_initialization_options())
asyncio.run(main())
# Agent 配置(在 settings.json 里加一行,Agent 代码里不需要任何工具代码)
总结
三条结论来自真实数字:
- 2ms 开销在 Agent 场景里可以忽略:LLM 推理是 8000ms,协议开销是 2ms,占比 0.024%。"283x 更慢"是技术上正确但实践上误导的描述
- 570ms 启动成本需要预热设计:如果 Agent 需要快速响应第一个工具调用,在会话开始时提前初始化 MCP Server(懒加载 vs 预加载的工程选择)
- 代码复用是选 MCP 的核心原因:单项目差异有限(43 vs 32 行),3 个项目共用时 FC 需要 129 行而 MCP 保持 32 行------工具越多、项目越多,差距越大
参考资料
- 本系列完整 Demo 代码:mcp-06-comparison
欢迎访问 PrimeSkills ------ 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。
更多实用知识和有趣产品,欢迎访问我的个人主页