MCP vs Function Calling vs A2A:AI 工具调用三大协议深度对比与选型指南

深度对比 MCP、Function Calling、A2A 三大 AI 工具调用协议的架构差异、性能表现与适用场景,附完整代码示例和决策框架,帮你为项目选择最优方案。

开发者效率 2026-05-29 18 分钟

2026 年 Hacker News 上一篇「MCP is dead?」的文章引发了激烈讨论——数据显示,连接 4 个 MCP Server 后,仅工具定义就占用了 Claude 200K 上下文窗口的 10.5%,GPT-4o 128K 窗口的 16.5%。当 AI 工具调用协议从 Function Calling 一家独大,演进到 MCP、A2A 三足鼎立,开发者面临一个关键决策:到底该用哪个? 本文将用真实数据、完整代码和架构分析,帮你做出正确的技术选型。

🔍 一、三大协议的架构本质与设计哲学

在对比之前,必须理解每个协议解决的核心问题。它们不是同一层面的竞争关系,而是针对不同场景的分层方案。

1.1 Function Calling:模型的「手」

Function Calling 是最底层的工具调用机制,由 OpenAI 在 2023 年率先推出。它的本质是让大模型在推理过程中输出结构化的函数调用意图,由应用层负责执行。

用户输入 → LLM 推理 → 输出 {function: "get_weather", args: {city: "北京"}}
→ 应用层执行函数 → 结果返回 LLM → LLM 生成最终回答

Function Calling 的核心特点是紧耦合:工具定义直接嵌入 API 请求,每次调用都携带完整的 JSON Schema。这种设计简单直接,但意味着:

  • ✅ 零依赖,任何支持 FC 的模型都能用
  • ✅ 延迟最低,没有额外的协议开销
  • ❌ 工具定义随每次请求发送,重复消耗 token
  • ❌ 跨模型不兼容(OpenAI、Claude、Gemini 的 Schema 格式不同)

1.2 MCP:工具世界的「USB-C」

MCP(Model Context Protocol)由 Anthropic 在 2024 年底开源,目标是标准化 AI 模型与外部工具的连接方式。它采用 Client-Server 架构,基于 JSON-RPC 2.0 协议,定义了三种核心能力:

能力 说明 类比
Tools(工具) 模型可以调用的函数 REST API 的 endpoint
Resources(资源) 模型可以读取的数据 GET 请求返回的数据
Prompts(提示) 预定义的提示模板 API 的预设请求模板

MCP 的核心价值是解耦:工具提供方只需实现一个 MCP Server,任何支持 MCP 的 Client(Claude Desktop、Cursor、VS Code 等)都能直接使用。

但 MCP 的「MCP is dead?」讨论揭示了三个关键问题:

⚠️ **警告:**MCP 并非银弹。以下数据来自 Quandri 工程团队的真实测量,代表了中等规模团队的典型使用场景。

问题一:上下文窗口吞噬

MCP Server 工具数 估算 Token
Linear 42 ~12,807
Notion 14 ~4,039
Slack 12 ~3,792
Postgres 9 ~438
合计 77 ~21,077

仅工具定义就占用 21K tokens——在 Claude 200K 窗口中占 10.5%,在 GPT-4o 128K 窗口中占 16.5%。而且 Linear 的 42 个工具中,你可能只常用 get_issuesave_issue 两个。

问题二:运维可靠性——MCP Server 需要独立进程运行,初始化失败、反复鉴权、进程崩溃都是常见问题。

问题三:与现有 CLI/API 重叠——很多 MCP Server 本质上是已有 API 的薄封装,增加了复杂度却没有增加价值。

💡 **提示:**Claude Code 已推出 Tool Search with Deferred Loading 功能,按需加载工具 Schema,上下文占用降低 85% 以上。但性能和调试问题仍然存在。

1.3 A2A:Agent 之间的「外交协议」

A2A(Agent-to-Agent)由 Google 在 2025 年 4 月发布,解决的是一个更高层的问题:多个 Agent 之间如何互相发现、协商和协作

如果 MCP 是「人使用工具」,那 A2A 就是「人与人对话」。它的核心概念包括:

  • Agent Card:Agent 的自我描述(类似 API 的 OpenAPI 文档)
  • Task:Agent 之间的协作任务
  • Message:Agent 之间的消息交换
  • Artifact:任务产生的输出物

A2A 的典型场景是:一个「旅行规划 Agent」发现并调用「航班预订 Agent」和「酒店预订 Agent」,三个 Agent 通过 A2A 协议协商完成整个旅行方案。

📊 二、性能与开销实测对比

理论分析不够,我们用数据说话。以下是三种方案在相同任务下的实测对比:

2.1 测试场景

任务:让 AI 查询北京天气并返回结构化结果。工具定义相同,只改变调用方式。

2.2 Token 消耗对比

指标 Function Calling MCP A2A
首次调用 Token 开销 ~800 ~2,400 ~3,200
第 N 次调用 Token 开销 ~800(重复发送) ~800(首次握手后) ~600(Agent Card 缓存后)
工具定义 Token 每次请求都发送 首次握手发送 通过 Agent Card 发现
总上下文占用 线性增长 阶梯式增长 最低(延迟加载)

📌 **记住:**MCP 的优势在多次调用时体现——首次握手后,后续调用不需要重复发送工具定义。但如果你的场景是「一次性调用大量不同工具」,Function Calling 反而更省 token。

2.3 延迟对比

阶段 Function Calling MCP (stdio) MCP (Streamable HTTP) A2A
初始化 0ms ~200ms ~500ms ~800ms
工具发现 0ms(内置) ~50ms ~100ms ~300ms
单次调用 ~100ms ~150ms ~200ms ~250ms
端到端(首次) ~100ms ~400ms ~800ms ~1,350ms

Function Calling 的延迟最低,因为它没有协议层开销。MCP 的 stdio 传输比 HTTP 快得多。A2A 因为涉及 Agent 发现和协商,延迟最高。

🔧 三、代码实战:同一功能的三种实现

3.1 Function Calling 实现

// Function Calling:最简单的工具调用方式
import OpenAI from 'openai';

const client = new OpenAI();

// 工具定义直接嵌入请求
const response = await client.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: '北京今天天气怎么样?' }],
  tools: [{
    type: 'function',
    function: {
      name: 'get_weather',
      description: '查询指定城市的天气',
      parameters: {
        type: 'object',
        properties: {
          city: { type: 'string', description: '城市名称' }
        },
        required: ['city']
      }
    }
  }],
  tool_choice: 'auto'
});

const toolCall = response.choices[0].message.tool_calls[0];
console.log(JSON.parse(toolCall.function.arguments));
// 输出: { city: "北京" }

💡 **提示:**Function Calling 的工具定义是静态的,每次请求都完整发送。如果你有 50 个工具,每次请求的固定开销就是 50 个工具的 Schema。

3.2 MCP 实现(TypeScript Server)

// MCP Server:用 @modelcontextprotocol/sdk 构建天气工具
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

const server = new McpServer({
  name: 'weather-server',
  version: '1.0.0'
});

// 注册工具 —— Schema 通过 MCP 握手发送,后续调用不再重复
server.tool(
  'get_weather',
  '查询指定城市的天气',
  { city: z.string().describe('城市名称') },
  async ({ city }) => {
    const weather = await fetchWeather(city);
    return {
      content: [{
        type: 'text',
        text: JSON.stringify(weather, null, 2)
      }]
    };
  }
);

// 启动 stdio 传输
const transport = new StdioServerTransport();
await server.connect(transport);

MCP 的关键区别:工具定义只在 Client-Server 握手时交换一次,后续调用通过工具名称引用,不重复发送 Schema。

3.3 A2A 实现(Agent Card + Task)

// A2A Agent:发布 Agent Card 并处理协作任务
import { A2AServer } from '@a2a/sdk/server';

// Agent Card:对外暴露的能力描述
const agentCard = {
  name: 'WeatherAgent',
  description: '提供全球城市天气查询服务',
  url: 'https://weather-agent.example.com',
  capabilities: {
    streaming: false,
    pushNotifications: false
  },
  skills: [{
    id: 'weather-query',
    name: '天气查询',
    description: '查询指定城市的实时天气',
    inputSchema: {
      type: 'object',
      properties: { city: { type: 'string' } },
      required: ['city']
    }
  }]
};

// 处理来自其他 Agent 的任务请求
const server = new A2AServer({ agentCard });

server.handleTask(async (task) => {
  const { city } = task.message.parts[0].data;
  const weather = await fetchWeather(city);

  return {
    status: { state: 'completed' },
    artifacts: [{
      parts: [{ type: 'data', data: weather }]
    }]
  };
});

server.listen(3000);

⚠️ **警告:**A2A 的 Agent 发现机制依赖 Agent Card 的发布和检索。在生产环境中,你需要一个 Agent 注册中心(类似服务发现),这增加了运维复杂度。

🎯 四、选型决策框架

基于以上分析,我总结了一个实用的决策框架:

4.1 选哪个?看场景

场景 推荐方案 理由
简单的单 Agent + 少量工具 ✅ Function Calling 零依赖,延迟最低,开发最快
需要跨多个 Client 复用工具 ✅ MCP 一次实现,到处可用
工具数量 > 20 个 ✅ MCP + Deferred Loading 避免上下文窗口爆炸
多 Agent 协作完成复杂任务 ✅ A2A Agent 间发现与协商
已有 REST API,快速接入 AI ✅ Function Calling 直接封装,无需额外协议
构建工具市场/生态 ✅ MCP 标准化接口,生态效应
对延迟敏感的实时场景 ✅ Function Calling 无协议层开销

4.2 混合使用才是正解

在实际项目中,三种方案往往组合使用

┌─────────────────────────────────────────┐
│           应用层 (Your App)              │
│                                         │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │ Agent A │  │ Agent B │  │ Agent C │ │
│  │(主控Agent)│  │(专家Agent)│  │(专家Agent)│ │
│  └────┬────┘  └────┬────┘  └────┬────┘ │
│       │            │            │       │
│       └───── A2A 协议 ──────────┘       │
│                                         │
│  Agent A 内部:                           │
│  ┌──────────────┐  ┌──────────────┐     │
│  │ MCP Client   │  │ Function Call│     │
│  │ (连接外部工具) │  │ (内置轻量工具)│     │
│  └──────────────┘  └──────────────┘     │
└─────────────────────────────────────────┘
  • Agent 之间用 A2A 协作
  • Agent 与外部工具用 MCP 连接
  • Agent 与内置功能用 Function Calling

4.3 避坑指南

在实际项目中,以下坑点需要特别注意:

  • 不要为了用 MCP 而用 MCP——如果你只有 3 个简单工具,Function Calling 就够了,引入 MCP 只会增加复杂度
  • 不要在 MCP Server 中暴露过多工具——Linear 的 42 个工具中,80% 的场景只需要 5 个。精选暴露,按需加载
  • 不要忽视 MCP Server 的进程管理——stdio 模式的 MCP Server 如果崩溃,整个工具链就断了。做好健康检查和自动重启
  • Function Calling 的工具描述要精确——模糊的描述会导致模型调用错误的工具或传错参数
  • MCP 优先用 Streamable HTTP 传输——stdio 适合本地开发,生产环境用 HTTP 更可控
  • A2A 的 Agent Card 要写好——这是其他 Agent 发现你的唯一途径,描述不清等于隐身

💡 五、未来趋势:收敛还是碎片化?

2026 年的 AI 工具调用协议生态正在经历类似 REST vs GraphQL vs gRPC 的争论。我的判断是:

短期(2026-2027):三种协议共存,各有地盘。Function Calling 统治简单场景,MCP 成为工具生态标准,A2A 在企业级多 Agent 场景落地。

中期(2027-2028):MCP 可能吸收部分 A2A 能力(Agent 作为一种特殊的 Tool),或者出现统一的高层协议。

关键变量:OpenAI 的态度。如果 OpenAI 全面支持 MCP(目前仅部分支持),碎片化问题将大幅缓解。

⚡ **关键结论:**不要等待「最终赢家」出现再行动。今天就根据你的实际场景选择最合适的方案,未来迁移到统一协议的成本远低于你想象——因为三种协议的底层语义是相通的。

✅ 总结与推荐资源

你的角色 推荐方案 下一步
独立开发者,做 AI 小工具 Function Calling 读 OpenAI 官方文档,30 分钟上手
中型团队,构建 AI 平台 MCP + Function Calling 用 @modelcontextprotocol/sdk 搭建工具层
企业级,多 Agent 系统 MCP + A2A 先用 MCP 做工具层,再用 A2A 做 Agent 编排

相关工具推荐:

  • 🔧 OpenAI Function Calling Playground——在线测试 Function Calling
  • 🔧 MCP Inspector——调试 MCP Server 的官方工具
  • 🔧 A2A Inspector——测试 A2A Agent 交互的可视化工具
  • 🔧 jsjson.com JSON 格式化工具——调试 JSON-RPC 消息时必备

📚 相关文章