MCP 和 A2A 有什么区别?一个连工具,一个连接 Agent
MCP 与 A2A 都是 Agent 协议,但解决的问题不同。本文用同一个退款业务对照工具调用与 Agent 委派,并拆解 Agent Card、Task、Artifact、传输和安全边界。

先给结论:
MCP 让一个 AI 应用以标准方式使用工具和数据;A2A 让一个 Agent 把目标委派给另一个 Agent,并跟踪它如何完成任务。
两者都可能运行在 HTTP 上,也都会交换结构化消息,但抽象层不同。MCP 暴露的是 refund_order 这样的具体能力;A2A 暴露的是“退款专员”这样的独立 Agent,它可以自行规划、追问、调用内部工具,并返回任务状态和交付物。
所以问题不是“哪一个会取代另一个”,而是:当前边界的另一端,是一个工具,还是一个有自主性的 Agent?
本文会用同一个退款业务做对照,并展示使用官方 SDK 实际构造和验证的两种结果。
一张表看懂核心差异
| 维度 | MCP | A2A |
|---|---|---|
| 全称 | Model Context Protocol | Agent2Agent Protocol |
| 主要关系 | AI 应用 ↔ 工具、资源、提示模板 | Client Agent ↔ Remote Agent |
| 对端暴露什么 | Tools、Resources、Prompts | Agent Card、Skills、Message、Task、Artifact |
| 对端内部是否透明 | 工具 Schema 和原语相对明确 | Remote Agent 通常被视为不透明系统 |
| 工作单位 | tools/call、resources/read 等协议操作 | Message 或有状态 Task |
| 适合时长 | 常见是一次具体读取或动作,也支持进度 | 原生面向即时到长时、异步、多轮任务 |
| 能力发现 | tools/list、resources/list、prompts/list | Agent Card 及其中的 Skills、接口和安全要求 |
| 结果 | 内容、结构化内容、资源 | Message、状态更新、Artifact |
| 常见传输 | stdio、Streamable HTTP | HTTP 上的 JSON-RPC、REST 或 gRPC 绑定;流式更新可用 SSE |
| 安全重点 | 工具权限、输入验证、本地进程、Prompt Injection | Agent 身份、认证授权、跨域委派、任务数据与回调 |
这张表是方向,不是绝对限制。MCP Tool 可以执行复杂动作,A2A Agent 也可能很简单。真正的区别是你向对端购买的是一个确定能力,还是一个结果导向的委派关系。

MCP 的心智模型:我知道要调用什么
在上一篇 MCP 入门实战 中,我们实际运行过:
initialize
→ tools/list
→ tools/call
→ tool result
Host 通过 MCP Client 发现 Server 暴露的工具,随后按工具 Schema 提交参数。例如:
{
"name": "refund_order",
"arguments": {
"order_id": "NB-2001",
"amount": 29.9
}
}
调用方已经知道要执行“退款”这个动作,也知道需要订单 ID 和金额。Server 的责任是校验、授权并执行这个具体能力。
MCP Server 不必是 Agent,也不必调用 LLM。它可以只是支付 API、数据库或文件系统的适配器。
A2A 的心智模型:我知道目标,但把过程交给你
A2A 的 Client Agent 可以发送:
调查退款案例 NB-2001。客户声称被重复扣款。
Remote Agent 暴露的是“退款案例调查”这项 Skill,而不是要求调用方按固定顺序操作每一个底层工具。它可能自行完成:
- 查询订单和支付流水;
- 核对退款政策;
- 检查风控标记;
- 发现信息不足后要求补充输入;
- 调用支付系统退款;
- 生成可审计的决定报告。
从 Client Agent 看,Remote Agent 是一个黑盒:你关心它承诺什么 Skill、如何认证、任务当前在哪个状态,以及最终交付什么 Artifact,不需要知道它内部使用哪个模型、框架或工具。
真实对照实验:同一个退款业务,两种建模
为避免只画概念图,我使用以下官方 Python SDK 实际运行或构造了两套对象:
- MCP Python SDK:
1.28.1 - A2A Python SDK:
1.1.1
测试使用虚构订单 NB-2001,没有连接生产数据或真实支付系统。

方案 A:把退款建模为 MCP Tool
最小 MCP Server:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("payment-tools")
@mcp.tool()
def refund_order(order_id: str, amount: float) -> dict:
"""Issue a deterministic refund after application-level authorization."""
return {
"refund_id": "RF-2001",
"order_id": order_id,
"amount": amount,
"status": "succeeded",
}
if __name__ == "__main__":
mcp.run(transport="stdio")
实际通过 stdio 初始化后,tools/list 找到:
{
"sdk": "1.28.1",
"discovery": ["refund_order"]
}
实际调用结果的核心内容为:
{
"refund_id": "RF-2001",
"order_id": "NB-2001",
"amount": 29.9,
"status": "succeeded"
}
这个建模适合边界明确的动作。调用方决定“现在退款 29.9”,工具负责执行。注意,JSON Schema 只能验证形状;谁有权退款、最高金额、是否重复提交,仍必须由业务代码检查。
方案 B:把退款建模为 A2A Agent
A2A 首先通过 Agent Card 描述 Remote Agent。本文用官方 SDK 构造并序列化的核心信息如下:
{
"name": "Refund Specialist",
"description": "Investigates refund cases and returns a decision report.",
"supported_interfaces": [
{
"url": "https://refund.example/a2a",
"protocol_binding": "JSONRPC",
"protocol_version": "1.0"
}
],
"capabilities": {
"streaming": true,
"push_notifications": true
},
"skills": [
{
"id": "refund-case",
"name": "Refund case investigation",
"tags": ["refund", "billing"]
}
]
}
这里的 URL 是不可访问的示例地址,不是线上服务。Agent Card 像数字名片,告诉 Client:
- Agent 是谁、提供哪些 Skills;
- 支持哪些协议接口和版本;
- 输入输出媒体类型;
- 是否支持流式和推送通知;
- 需要什么安全方案。
Client Agent 发送一条 Message:
{
"message_id": "msg-102",
"context_id": "ctx-102",
"role": "ROLE_USER",
"parts": [
{
"text": "Investigate refund case NB-2001. Customer reports duplicate charge."
}
]
}
Remote Agent 可以立即返回普通 Message;如果工作需要状态和后续交互,则创建 Task。本文实际构造的初始状态为:
{
"id": "task-102",
"context_id": "ctx-102",
"status": {
"state": "TASK_STATE_SUBMITTED"
}
}
完成后,同一 Task 进入 TASK_STATE_COMPLETED,并带回 Artifact:
{
"id": "task-102",
"status": {
"state": "TASK_STATE_COMPLETED"
},
"artifacts": [
{
"artifact_id": "artifact-102",
"name": "refund-decision.json",
"parts": [
{
"data": {
"decision": "approve",
"amount": 29.9,
"reason": "duplicate_charge"
}
}
]
}
]
}
这不是完整网络 Server 的演示,而是使用官方 a2a-sdk 1.1.1 创建并序列化 Agent Card、Message、Task 和 Artifact 的可执行建模探针。它验证了两种协议的交付单位确实不同:MCP 返回工具结果;A2A 管理委派任务及交付物。
A2A 为什么需要 Task
Agent 工作常常不是一次函数调用:
- 可能要几分钟或几小时;
- 可能需要用户补充材料;
- 可能等待授权;
- 可能持续产生中间结果;
- Client 可能暂时断开连接。
A2A Task 因而有明确生命周期。当前规范中的状态包括:
submitted → working → completed
↘ failed
↘ canceled
↘ rejected
↘ input-required
↘ auth-required
其中 input-required 和 auth-required 是可中断状态:Remote Agent 不是简单报错,而是告诉 Client 需要什么才能继续。
contextId 用于把相关 Message 和多个 Task 归入同一上下文;taskId 标识具体工作单元。后续请求可以引用它们继续多轮协作。
MCP 也有进度、通知机制;2025-11-25 规范还加入了实验性的 Tasks,用于包装延迟执行和状态追踪。但 MCP 的核心仍是 Client–Server 能力交互,而 Tasks 尚不是所有 Client 和 SDK 都稳定支持的通用能力。A2A 则从一开始就把跨 Agent 的有状态委派、人工介入和异步交付作为核心数据模型。
能力发现:Tool Schema 与 Agent Card 不一样
MCP 发现具体操作
tools/list 返回:
- 工具名;
- 描述;
inputSchema;- 可选
outputSchema和注解。
调用方得到的是一份函数式契约。
A2A 发现合作对象
Agent Card 描述:
- 身份、版本和 Provider;
- 支持的协议接口;
- Capabilities;
- 认证和安全要求;
- 输入输出媒体类型;
- Skills、示例和标签。
公开 Agent Card 可以放在 Well-Known URI,也可以通过注册表或私有配置发现。不要把“找到 Agent Card”误写成“已经信任这个 Agent”:生产环境仍需验证来源、签名、域名和授权策略。
Message、Task 和 Artifact 分别是什么
| A2A 对象 | 用途 | 退款例子 |
|---|---|---|
| Message | Agent 之间的一轮沟通 | “调查重复扣款”或“请补充付款凭证” |
| Part | Message/Artifact 的内容容器 | 文本、文件引用、二进制或结构化数据 |
| Task | 有 ID 和状态的工作单元 | 退款调查案例 |
| Artifact | Task 产生的具体交付物 | 决定报告、退款凭证、JSON 结论 |
不是每条 Message 都必须变成 Task。即时、自包含的回答可以直接返回 Message;需要跟踪、异步或多轮处理时,Task 才有价值。
传输层也不能混为一谈
MCP
标准传输是:
- stdio;
- Streamable HTTP。
它们承载 MCP 的 JSON-RPC 生命周期与原语。
A2A
A2A 1.0 规范定义协议操作,并允许通过声明的接口绑定访问。当前官方生态包括:
- JSON-RPC over HTTP;
- REST;
- gRPC。
长任务可以:
- 同步请求后轮询 Task;
- 使用 SSE 流接收状态和 Artifact 更新;
- 在断开场景使用 Push Notification 配置。
因此“它们都用 JSON-RPC”不足以证明两者相同。HTTP 和 JSON-RPC 只是运送方式,真正不同的是消息语义和协作边界。
安全模型:A2A 不是把 Tool 权限放大一层
MCP 侧重点
- Tool 参数和副作用确认;
- Server 本地进程权限;
- 路径、租户和业务授权;
- Tool/Resource 内容中的 Prompt Injection;
- 远程 Server 的认证、Origin 和会话安全。
A2A 侧重点
- Agent Card 是否来自可信主体;
- Client Agent 代表哪个用户或服务;
- Remote Agent 能看到哪些任务数据;
- 跨组织委派是否被允许;
- 长任务、Artifact 和历史如何隔离租户;
- SSE 或 Push Notification 回调如何认证、防重放和防 SSRF;
- Agent 是否有权继续调用下游 Agent 或高风险工具。
一个常见错误是:Client Agent 有权查订单,就默认 Remote Agent 也有同样权限。委派目标不等于委派全部身份和凭据。 应为每次调用签发最小范围、可审计、可撤销的权限,而不是透传上游 Token。
MCP 和 A2A 如何组合

真实系统经常同时使用两者:
用户
↓
客服 Agent
│
├── A2A → 退款专员 Agent
│ ├── MCP → 订单数据库
│ ├── MCP → 支付工具
│ └── MCP → 风控查询
│
└── A2A → 物流 Agent
└── MCP → 物流 API
A2A 负责“把退款调查交给退款专员”;退款专员内部再通过 MCP 调用订单、支付和风控工具。
模型 API 是第三条独立边界:每个 Agent 可能调用 OpenAI、Claude、Gemini 或其他模型。MCP 和 A2A 都不负责统一模型价格、Token 计费或 Provider 故障切换。若多个 Agent 需要稳定的统一模型入口,才由 Nbility 这类 AI API 网关处理。
决策规则:什么时候用哪一个
用 MCP,如果你需要
- 读取数据库、文件或 API;
- 调用参数明确的动作;
- 让多个 Host 复用同一工具;
- 保持工具执行与模型 Provider 解耦;
- 对每个操作做细粒度授权。
用 A2A,如果你需要
- 把目标委派给独立 Agent;
- 不暴露 Remote Agent 的内部实现;
- 跟踪长任务和多轮上下文;
- 交换状态、文件或结构化交付物;
- 跨团队、跨系统或跨组织协作。
两者都不要,如果
- 普通函数调用已经足够;
- 只有一个进程和一个固定工作流;
- 团队还没有身份、授权和审计能力;
- 只是为了追热点而增加协议层。
五个常见误解
1. “A2A 是 MCP 2.0”
不是。A2A 解决 Agent 之间的委派,MCP 解决应用与工具/上下文的连接,官方也把它们描述为互补协议。
2. “接入 A2A 后不再需要 MCP”
Remote Agent 仍要访问数据库、文件和业务 API,这些内部连接依然适合 MCP。
3. “MCP Server 就是一个 Agent”
不一定。确定性的数据库适配器就是有效 MCP Server。只有当对端以目标为中心自主规划并承担任务生命周期时,才更接近 A2A Agent。
4. “每次 A2A 调用都创建 Task”
不是。简单即时交互可以返回无状态 Message;需要跟踪的工作才创建 Task。
5. “Agent Card 是可信证书”
不是。它是能力和连接元数据。发现之后仍需身份验证、授权、来源校验和风险决策。
版本说明
本文核对时:
- A2A 官方文档显示规范
v1.0.1; - 实验安装的官方 Python SDK 为
1.1.1; - MCP 实验使用官方 Python SDK
1.28.1。
协议和 SDK 都在快速演进。不要把示例中的版本、接口 URL 或枚举当永久常量;生产集成应固定依赖版本,读取 Agent Card/能力声明,并为升级建立兼容测试。
总结
判断 MCP 还是 A2A,可以问三个问题:
- 我是在调用一个明确工具,还是委派一个目标?
- 我需要一个立即结果,还是需要跟踪任务、状态和交付物?
- 我需要知道对端如何执行,还是只关心它承诺的 Skill 和结果?
前者通常是 MCP,后者通常是 A2A。复杂 Agent 系统往往两者并用:A2A 横向连接 Agent,MCP 纵向连接每个 Agent 的工具和数据。
而模型 API 网关位于另一个平面,为这些 Agent 提供统一模型访问、用量统计和渠道可靠性。把三层分开,架构才不会因为“都是 AI 协议”而混成一团。


