MCP与A2A如何选?从JSON-RPC到Agent协议分层解析
做 Agent 开发的这段时间几乎每周都会被人问到一个问题MCP 和 A2A 到底什么关系我今天接工具该用哪个为什么 JSON-RPC 活了几十年大家还不消停又捣鼓出这么多新协议这个问题三句话说不清楚答案藏在每个协议的设计目标、抽象层级和它所属的生态里。我打算顺着线索把 JSON-RPC、MCP、A2A、ACP 逐个拆开说说它们各自解决了什么问题背后是什么思路以及在实际工程里应该怎么选。先说结论它们不是“一个替代另一个”的关系更像纵向分层。JSON-RPC 是公共信封MCP 管“模型接工具”A2A 管“智能体之间协作”ACP 还在尝试定义“语义层”。大多数团队应该先吃透前两个后两个按需关注。如果你正在做 Agent 项目或者想把现有业务改造成“可被模型调用”的服务这篇文章应该能戳中你的痛点。我尽量用工程语言讲少来虚的。1. 先回答最直接的问题为什么协议会这么多答案是它们解决的问题不一样。JSON-RPC 是一个通用远程过程调用协议它压根不知道 Agent 是什么也不管模型上下文只负责“让一个程序能调用另一个程序的函数”。而 MCP、A2A、ACP 都是为 AI Agent 场景专门设计的带着各自的假设和目标。站在 2025 年往回看协议爆发有几个很现实的原因大模型能力上了一个台阶之后“工具调用”成了刚需。可每个模型提供商的函数调用格式都不一样你接一个工具就得写一层胶水代码这显然不可持续需要中立接口。Agent 开始从单机走向多机、从单智能体走向多智能体。两个独立部署、用不同技术栈搭建的 Agent 要协作就需要一套跨运行时、跨厂商的“握手”方式。没有任何一方能同时定义模型与工具、模型与应用、Agent 与 Agent 的全部关系。大家都在生态里抢占有利位置协议就是生态入口。加一句更本质的协议本身也是护城河。一个开放规范如果被大家接受就会成为事实标准但在标准尘埃落定之前各方都有动机推出自己的方案这就造成了“协议百花齐放”的局面。这不是坏事反而是技术生态早期该有的样子。不过也别被乱象吓住——剥开外衣底层几乎都长一个样。往下看你就明白了。2. 先看共同底子JSON-RPC 为什么能活二十年2.1 JSON-RPC 2.0 到底规定了什么JSON-RPC 2.0 在规范里只定义了极少的对象核心就是请求、响应、通知。一个典型请求长这样{ jsonrpc: 2.0, method: subtract, params: [42, 23], id: 1 }请求对象有四个关键字段jsonrpc固定为2.0标识协议版本。method要调用的方法名字符串。params参数可以是数组也可以是对象。id请求标识用来把响应和请求对上。响应也分两种形态。成功返回时{ jsonrpc: 2.0, result: 19, id: 1 }失败返回时{ jsonrpc: 2.0, error: { code: -32601, message: Method not found }, id: 1 }还有一种特殊消息叫 Notification。它没有id接收方收到后不需要回响应。适合那种“你帮我干个事不用告诉我结果”的场景比如打日志、触发缓存刷新。错误码也有一套约定-32700是解析错误-32600是无效请求-32601是方法不存在-32602是参数无效-32603是内部错误-32000到-32099保留给服务端自定义。整个规范就是这么多内容。你不觉得它有点像一个“信封”吗它规定信封怎么写、怎么封装、怎么投递但信封里装的业务内容它一概不管。2.2 光有信封是不够的正因为 JSON-RPC 的边界感极好它才能活这么多年被各种系统拿去当传输底座。但它也有非常明显的边界调用前你必须事先知道方法名和参数结构没有发现机制。没有上下文概念。服务器不知道你是谁也不知道你之前调过什么。没有鉴权、幂等、重试、路由等高级语义这些都得自己搭。不定义业务字段的语义method字符串到底代表什么双方要提前约定。放到 Agent 场景里这些不足就变得要命了我需要让模型“知道现在有什么工具可用”而不是把工具文档硬塞进提示词里。我需要让工具执行结果作为上下文回传给模型而不只是简单返回一个值。我需要让多个 Agent 互相发现能力、协商分工、异步跟踪任务。我需要处理长任务中的多轮追问、中间状态和最终产物。这些都不是 JSON-RPC 能直接给的。于是大家开始在这个信封上叠语义。这正是后面每个协议的核心贡献不重新发明信封而是定义信封里的“业务语言”。3. MCP模型与工具之间的通用插座3.1 它解决的是“接线困境”在 MCP 出现之前想给大模型接外部工具体验相当原始。你想让模型查天气、查数据库、操作文件就得去对接每个模型供应商的 function calling 接口。有的用 JSON Schema 描述参数有的用自定义对象有的支持并行调用有的只支持串行。表面上大家都在做“工具调用”实际上实现细节千差万别。更难受的是你接入的工具越多胶水代码越臃肿。今天换一个模型提供商之前给工具写的适配层全得返工。MCP 的思路是把“工具接入”变成标准协议工具方按协议暴露能力客户端按协议消费能力两边都不必关心对方内部实现。就像电器不用每家一个插座统一三孔插头就能通电。它的关键角色有三个Host终端应用也就是你正在跑的程序比如聊天客户端、IDE 插件、自动化工作流。MCP ClientHost 内部的通信客户端负责和 MCP Server 对话。MCP Server暴露工具、数据、提示词的后端进程。传输层有三种主流选择stdio本地子进程通信、Streamable HTTP跨网络通信新版替代了老的 HTTPSSE。自己写内部工具时用 stdio 最省事部署到远端服务就必须走 HTTP。3.2 核心架构与调用链路MCP 定义了三个核心原语记住这三个就够了Tools可以被模型调用的函数返回结构化数据。Resources可以被读取的数据资源比如文件内容、配置项、数据库查询结果。Prompts可复用的提示词模板用于引导模型完成特定任务。一次完整调用链路大致如下客户端发起initialize请求和服务器交换能力信息。服务器返回支持的协议版本、capabilities 列表。客户端调用tools/list动态获取当前可用的工具列表及参数 Schema。用户向大模型提出需求模型根据上下文选择合适的工具。客户端发送tools/call带上工具名和参数。服务器执行工具返回执行结果。模型把结果纳入上下文组织最终回复。一个典型的tools/call消息长这样{ jsonrpc: 2.0, method: tools/call, params: { name: query_stock, arguments: { symbol: 600519 } }, id: 7 }动态发现机制是它比 JSON-RPC“先进”的地方。调用方不需要在写代码时就硬编码所有工具运行时问一下就能知道对方支持什么。工具数量增加、参数调整都不需要改客户端代码。3.3 老协议的新外壳MCP 与 JSON-RPC 的关系这里有个容易忽略的细节MCP 的消息格式本来就基于 JSON-RPC 2.0。它复用了 JSON-RPC 的报文结构、错误码、id 关联逻辑只是定义了一套自己的 method 命名空间和业务对象。换句话说MCP 干的事是“给 JSON-RPC 补齐语义层”。当协议演进到第二步时你往往会看到这种规律底层信封不动动的是信封里面的业务契约。这个规律在 A2A 身上也能看到。4. A2A从“人指挥模型”到“智能体相互协作”4.1 换个思考框架不是调用是任务MCP 解决的是“模型调用工具”。但现实中有另一种需求两个 Agent 互相协作。比如一个 Agent 负责收集行业资料另一个 Agent 专门做图表渲染。前者处理完资料后需要把结果交给后者。你能直接用 MCP 的做法把后者暴露成一个工具来调吗可以但不优雅。原因在于 Agent 协作和工具调用有本质区别。工具调用是短促、明确、一次性的你给我参数我给你结果。Agent 协作往往是长周期、多轮、带状态的过程——第一个 Agent 可能跑了几分钟才产出中间结果中途还要回头问你补充信息最后交付的不只是一个值而是一堆文件。A2A 的答案是“任务化”的交互模型把每一次协作建模为 Task。Task 有生命周期和状态迁移。允许异步处理客户端不用干等着。支持多轮消息交换中途可以请求输入。最终产出用 Artifact 表达可以是文件、结构化数据、代码。这个模型比“同步 RPC”更贴近 Agent 协作的真实节奏。4.2 Agent Card、Task、Message、ArtifactA2A 里有几个核心概念我按重要程度讲。第一个是 Agent Card。它相当于 Agent 的名片描述这个 Agent 能干什么、接受什么输入、返回什么输出、通信端点在哪、有哪些安全约束。客户端拿到 Agent Card才知道对方是不是自己需要的角色以及怎么发起协作。这解决了 JSON-RPC 没有“发现机制”的问题。第二个是 Task。一次协作就是创建了一个 Task。Task 有一个唯一 ID从创建到结束都靠这个 ID 追踪。一个 Task 的状态包括submitted任务已创建。workingAgent 正在处理。input-required需要用户或其他 Agent 补信息。completed任务完成产出 Artifact。failed失败可通过错误信息定位。canceled被取消。第三个是 Message。Agent 之间通过 Message 交换内容。Message 可以包含文本、文件引用、结构化对象并且和具体的 Task 绑定。流程上客户端给服务端发message服务端处理后返回新一轮的message你来我往直到任务结束。第四个是 Artifact。任务完成后的产物可以是文档、图片、代码仓库、数据集。Artifact 不只是一个返回值而是可以被双方继续引用的实体。有了这套模型两个 Agent 的协作就能跑起来客户端读取目标 Agent Card确认能力匹配。客户端创建 Task发给对方。服务端返回 Task ID进入submitted或working状态。客户端轮询或订阅状态变化。如果进入input-required客户端补充信息。任务完成客户端拿到 Artifact。异步处理是关键。Agent 的“思考”时间不可预期可能是几秒也可能是几分钟用同步调用会卡死上游。A2A 把状态机放在通信模型里就让长任务有了“出气口”。4.3 A2A 与 MCP 的分工我习惯这样理解二者的关系MCP 是 Agent 的“手”A2A 是 Agent 的“嘴”。Agent 内部要用 MCP 去调工具、读资源、执行动作Agent 对外要用 A2A 和其他 Agent 协商、交接、协作。二者可以叠用——一个 Agent 对外通过 A2A 接收任务对内通过 MCP 调用一堆工具完成任务。所以不要再纠结“MCP 能不能替代 A2A”了。如果你的场景是两个模块跑在同一进程包装成 MCP 也能凑合但跨进程、跨团队、跨组织需要能力发现和状态追踪的开放协作场景A2A 的模型明显更合适。而且A2A 的消息传输同样沿用 JSON-RPC 2.0 风格的信封。你看到没有底层信封居然又是它。5. ACP想把“语义”做成协议5.1 它想解决什么问题ACPAgent Communication Protocol是更靠后的一个新方向名字看着像协议大杂烩事实上它也确实在试图回答一个头疼问题Agent 之间到底怎样才算“互相理解”。MCP 补上了“工具发现”A2A 补上了“任务协作”但两者都还停留在“接口层”的互操作上。接口约定得再好也只解决了“能不能调通”的问题没解决“调通之后算法是不是真懂我意思”的问题。ACP 的切入点叫“语言优先”。它主张 Agent 之间交换的应该是标准化的语义消息而不是某家公司定义的函数接口。目标就是让两个用不同模型、不同框架、甚至不同语言实现的 Agent都能通过一套公共语义来理解对方的意图和指令。往深了说这有点像早年语义网领域讨论的那套东西——与其约定格式不如约定含义。5.2 为什么它短期内不会取代 A2A先说泼冷水的部分。ACP 目前更多处于概念验证和标准化草案阶段生产环境里你很难找到一套成熟的 SDK 和工具链。而 A2A 的 Task 模型更接近工程师已经熟悉的“任务队列 状态机”调试排错都有据可查。一个协议能不能普及从来不看理论完备性而看生态成熟度。框架支持、监控工具、中间件、代理网关、人才储备这些都比“语义设计得好不好”更卡脖子。但 ACP 不代表没有价值。它推动的是“语义协商”方向哪怕最终没有成为标准它的很多设计思路——比如意图注册、语义版本、Schema 协商——都可以反过来给现役协议做参考。做 Agent 架构的人值得关注它的走向但现阶段不建议把核心业务压在它上面。6. 四种协议横向对比看本质6.1 一张对比表维度JSON-RPCMCPA2AACP核心目标通用远程过程调用模型接入工具/数据Agent 到 Agent 协作Agent 语义级互操作通信对象进程/服务Host 与 MCP Server客户端 Agent 与服务 AgentAgent 与 Agent核心单元方法调用Tool / Resource / PromptTask / Message / Artifact意图 / 语义消息发现机制无capabilities tools/listAgent Card语义注册与协商异步支持无有限内置状态机设计目标之一传输方式不绑定stdio、Streamable HTTPHTTP 为主可扩展不固定成熟度极高较高生态增长快中上已有不少实践早期实验阶段适合场景内部服务间调用给 LLM 接工具多 Agent 协同跨厂商互操作研究表格看完你会有个直观感受这四种协议不是一条线上的四个版本而是不同层级、不同定位的产物。拿着 MCP 去硬套 Agent 协作场景会别扭拿 A2A 去给模型接一个简单的 SQL 工具也嫌重。6.2 协议演进背后的产业节奏从时间线看协议扎堆出现其实是产业成熟的信号第一阶段模型需要工具于是有了 MCP 这类“工具接入层”。第二阶段Agent 需要协作于是有了 A2A 这类“任务协作层”。第三阶段Agent 需要跨厂商、跨框架互认于是 ACP 这类“语义互操作层”开始冒头。这有点像当年 Web 服务演进先有 XML-RPC 解决机器间调用再往上有 SOAP 解决结构化业务协作最后 REST 用自己的简洁方式统一了大多数场景。Agent 协议的走向未必是“谁替代谁”更可能是分层共存网关负责在层次间转换。打个生活化的比方JSON-RPC 是“拿起电话就拨号”的规则只要通就行。MCP 是“统一了电器插头形状”什么电器都能插同一个插座。A2A 是“两家公司签外包合同”有进度、有交付、有问题反馈。ACP 是“试图发明一种通用商业语言”理论上谁都能跟谁聊。7. 工程选型我到底该用哪个7.1 按你的场景找答案我现场给不同情况开方子。场景一你想让 LLM 调用你的内部工具。绝大多数场景直接用 MCP。不管你是做一个聊天机器人查订单还是让模型读文件、搜数据库、执行脚本MCP 都是当下最省力的方案。它的 SDK 覆盖主流语言生态里现成 MCP Server 一堆接入成本在同级别协议里最低。场景二你要编排多个 Agent 协作。上 A2A。每个 Agent 发布自己的 Agent Card定义清楚任务状态机互相通过 Task 交换。跨进程、跨语言、跨团队都没问题。如果你只是单机单进程搞实验拿 MCP 也能顶但别指望 MCP 给你内置异步任务追踪。场景三你只是内部简单服务要互相调函数。别杀鸡用牛刀直接用 JSON-RPC 就行。它足够轻维护成本低也方便以后包一层 MCP 或 A2A 网关对外暴露。场景四你在做前瞻性研究或者想让一个 Agent 同时对接多种不同框架的其他 Agent。建议以 A2A 为基线跑通再适度参考 ACP 的语义协商思路做扩展。不要在起步阶段就押注一个还没成熟的标准。7.2 可以照抄的落地方式一个比较普适的工程做法是“协议网关”。在系统里放一层转发逻辑识别进入的请求属于哪种协议信封再分发给对应处理器。async def route_payload(payload: dict) - dict: if payload.get(jsonrpc) ! 2.0: raise ValueError(unsupported envelope) method payload.get(method, ) if method initialize or method.startswith(tools/) or method.startswith(resources/): return await handle_mcp(payload) if method.startswith(tasks/) or method.startswith(agent.): return await handle_a2a(payload) if method.startswith(semantic/) or method.startswith(intent.): return await handle_acp_experimental(payload) return await handle_plain_jsonrpc(payload)这个写法的核心思想是底层共用 JSON-RPC 信封高层按业务域分流。因为 MCP 和 A2A 的报文都是 JSON-RPC 风格网关层做协议互转的成本比想象中低。你可以先让内部系统之间用裸 JSON-RPC再在边界套一个 MCP 或 A2A 适配层。如果你团队资源有限我给个保守建议以 MCP 为默认接入标准把每个 Agent 的能力都暴露成 MCP Server宿主层调度多个 MCP Server 完成协作。这个模式生态最成熟、坑最少团队上手最快。等到跨组织协作成为必需品再引入 A2A 网关也不迟。7.3 踩坑记录有些坑我替你们踩过了列出来省点时间。协议版本漂移。MCP 早期用的是 HTTPSSE 传输后来新版本走向 Streamable HTTP。看到网上的老教程别急着抄先去官方仓库确认版本。我见过有人在生产环境用旧传输搞了半年升级协议时重构了半个客户端。忽略 capabilities 协商。MCP 握手阶段会交换能力清单有些实现图省事跳过协商结果客户端以为服务器支持 Prompt实际调用直接失败。该走的握手流程一步也别省。把 SSE 当长连接神器结果被代理掐断。企业内部网络环境复杂SSE 长连接经常被中间代理超时断开。用 SSE 订阅任务状态时一定要给客户端加自动重连并且考虑退避策略不然长任务跑到一半就失联。把 JSON-RPC 裸奔当成万能 API 设计。有人看 JSON-RPC 简单就把所有业务都塞进自定义 method不写 Schema 校验错误码乱用最后维护成本爆炸。记住它只是信封业务语义必须自己约束好或者直接上 MCP 这种带上语义的协议。还没讲完但核心意思已经清楚了。8. 写在最后协议不会收敛成一个我的判断很直白短期内不会有胜者通吃的局面。MCP 会逐渐成为“模型接工具”的事实标准因为它的位置最贴近实际需求A2A 会在企业级多智能体场景里落地因为跨团队协作总得有个规范ACP 会继续待在实验室和标准组织里发酵但它代表的“语义互操作”方向值得长期跟踪。最终形态大概率是分层共存。就像 Web 世界里HTTP、WebSocket、gRPC 各管一段没有谁消灭谁。Agent 协议也会是这样JSON-RPC 做公共信封MCP 做工具接入A2A 做智能体协作未来可能还有一个语义层浮出水面。网关和中间层负责互相翻译。如果给新入行的工程师一句建议我会说别执着于“哪个协议会赢”先想清楚“自己要解决什么抽象问题”。协议是抽象边界的产物只要有新的边界被切开就会出现新的协议。我自己的习惯是新项目一律先接 MCP遇到跨 Agent 协作再补 A2A嘴上吐槽着协议太多手里的活儿还得照干。希望这篇梳理能让你少踩几个坑。