智能体协议选型指南:MCP、A2A、ANP 核心区别与落地实践
简介这份PPT资料面向大模型与人工智能方向的开发者、架构师及技术决策者系统梳理智能体通信协作领域的三大主流协议——MCP、A2A与ANP。内容从未来智能体互联网对协议的需求切入逐一剖析MCP的Root、Sampling、Prompt、Resource、Tools等核心概念与初始化、操作、关闭三大流程A2A基于任务的企业内部智能体协作模式以及ANP面向数十亿智能体构建开放协作网络的愿景并对比三者的差异、优缺点与未来角色。资源包为1个pptx文件约5.23MB结构清晰、图文并茂适合用于技术分享、方案选型或团队内部培训。目前已有219人学习下载。通过这份资料读者可快速建立对智能体协议体系的整体认知理解数据孤岛、互联互通与标准化三大挑战的应对思路为后续架构设计与技术选型提供参考。1. 三份 PPT 拆开看MCP、A2A、ANP 到底谁管哪一段上周帮一个做企业知识库的团队做架构评审他们已经在用 MCP 把内部检索、数据库、工单系统接进了大模型跑得挺顺。结果老板突然提了个需求让销售侧的智能体直接去调用供应链侧的智能体跨部门自动对账。团队第一反应是「再写个 MCP Server 不就行了」结果卡了两周——因为 MCP 压根不是干这个的。这就是我拿到《深入对比智能体协议MCP、A2A、ANP.pptx》这份资源时的真实背景。它把三个最容易混淆的智能体协议放在同一张对比表里讲清楚了MCP 解决的是「智能体怎么调用工具和数据」A2A 解决的是「智能体之间怎么互相调用」ANP 解决的是「智能体怎么在网络里被发现、被信任、被组合」。如果你正在做 Agent 落地分不清这三者的边界选型阶段就会埋雷。这份 PPT 适合已经上手过至少一个 Agent 框架、需要做协议选型或架构对齐的工程师也适合想快速建立全局认知的技术负责人。2. MCP 协议拆解从工具描述到一次完整调用链2.1 MCP 的设计动机与核心抽象MCP 全称 Model Context Protocol它要解决的核心痛点是大模型应用每次接一个新工具数据库、文件系统、API都要写一套定制化的适配代码。工具多了以后代码里全是胶水逻辑换一个模型或换一个框架就得重写。MCP 的做法是把「工具」抽象成标准化的 Server把「调用方」抽象成 Client中间用 JSON-RPC 2.0 通信。这样工具提供方只需要实现一次 MCP Server任何支持 MCP 的 Client 都能直接接入。PPT 里把 MCP 的核心抽象拆成四层Resources资源类似文件或数据记录、Tools可执行函数、Prompts预置提示模板、Sampling让 Server 反向请求 Client 的模型能力。实际落地中最常用的是 Tools 和 ResourcesPrompts 和 Sampling 用得少但有特定场景。理解这四层的关键在于Resources 是「读」的语义Tools 是「做」的语义两者在权限控制上要分开处理。2.2 手写一个最小 MCP Server下面用 Python 写一个最小可用的 MCP Server暴露一个查询订单状态的工具。这段代码可以直接跑依赖只有mcp包。# minimal_mcp_server.py # 依赖: pip install mcp import asyncio from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app Server(order-service) # 模拟订单数据 ORDERS { ORD-1001: {status: shipped, eta: 2025-06-20}, ORD-1002: {status: pending, eta: None}, } app.list_tools() async def list_tools() - list[Tool]: 声明本 Server 提供哪些工具Client 启动时会拉取这个列表 return [ Tool( namequery_order, description根据订单号查询订单状态和预计到达时间, inputSchema{ type: object, properties: { order_id: { type: string, description: 订单号格式 ORD-XXXX } }, required: [order_id] } ) ] app.call_tool() async def call_tool(name: str, arguments: dict) - list[TextContent]: 实际执行工具调用返回结果给 Client if name ! query_order: raise ValueError(f未知工具: {name}) order_id arguments.get(order_id, ) order ORDERS.get(order_id) if not order: return [TextContent(typetext, textf订单 {order_id} 不存在)] return [TextContent( typetext, textf订单 {order_id}: 状态{order[status]}, 预计到达{order[eta] or 待定} )] async def main(): # 通过 stdio 传输层启动Client 以子进程方式拉起本 Server async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) if __name__ __main__: asyncio.run(main())逻辑说明list_tools返回工具清单和 JSON Schema 格式的参数定义Client 拿到后会把工具描述注入模型的上下文模型决定是否调用。call_tool是实际执行入口参数由模型生成、Client 转发。传输层用 stdio 是最简单的本地调试方式生产环境常见做法是换成 SSE 或 Streamable HTTP。参数说明inputSchema必须符合 JSON Schema 规范required字段决定模型是否必须提供该参数。TextContent的type目前支持text和image返回图片时传 base64。注意description写得好不好直接影响模型调用准确率——这是血泪经验描述含糊的工具模型经常不调用或传错参数。2.3 用 Client 验证调用链写完 Server 后用官方提供的 Client 做一次端到端验证# 安装 MCP Inspector可视化调试工具 npx modelcontextprotocol/inspector python minimal_mcp_server.py启动后浏览器打开 Inspector 界面能看到工具列表、手动触发调用、查看原始 JSON-RPC 消息。这一步很关键——很多「模型不调用工具」的问题其实是 Server 返回的 Schema 有问题用 Inspector 能快速定位是 Server 端还是 Client 端的问题。如果要在代码里集成Client 侧大致是这样# mcp_client_demo.py from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def run(): params StdioServerParameters( commandpython, args[minimal_mcp_server.py] ) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() # 拉取工具列表 tools await session.list_tools() print(可用工具:, [t.name for t in tools.tools]) # 直接调用工具 result await session.call_tool( query_order, {order_id: ORD-1001} ) print(调用结果:, result.content[0].text) import asyncio asyncio.run(run())这段代码展示了 MCP 调用的完整生命周期建立传输连接 → 初始化会话 → 拉取工具列表 → 调用工具 → 拿到结果。实际接入大模型时中间多一步「把工具列表转成模型能理解的 function calling 格式」但底层走的还是这套流程。3. A2A 协议拆解智能体之间的任务委派怎么落地3.1 A2A 与 MCP 的本质区别A2A 全称 Agent-to-Agent Protocol它和 MCP 最容易混淆但定位完全不同。MCP 是「智能体 → 工具」的纵向调用A2A 是「智能体 → 智能体」的横向协作。PPT 里用了一个很准确的类比MCP 像是给电脑装驱动A2A 像是两台电脑之间组网。具体来说A2A 要解决的是一个智能体如何发现另一个智能体的能力、如何把任务委派过去、如何追踪任务状态、如何处理长任务和流式返回。它的核心抽象是 Agent Card能力声明、Task任务对象、Message消息和 Artifact产出物。Agent Card 是一个 JSON 文件通常放在/.well-known/agent.json路径下描述这个智能体的名称、能力、支持的输入输出格式和认证方式。3.2 定义一个 Agent CardAgent Card 是 A2A 的入口没有它别的智能体就找不到你。下面是一个典型的 Agent Card{ name: supply-chain-agent, description: 供应链对账智能体支持订单核对和差异分析, url: https://supply.example.com/a2a, version: 1.0.0, capabilities: { streaming: true, pushNotifications: false }, skills: [ { id: reconcile-orders, name: 订单对账, description: 接收销售侧订单列表与供应链记录比对返回差异明细, inputModes: [application/json], outputModes: [application/json] } ], authentication: { schemes: [Bearer] } }逻辑说明capabilities.streaming表示该智能体支持流式返回中间状态长任务场景必须开。skills数组列出具体能力每个 skill 有独立的 id 和输入输出格式声明。authentication声明认证方式A2A 本身不定义认证协议只声明要求具体走 OAuth2 还是 API Key 由实现方决定。参数说明url是 A2A 服务的端点Client 会向这个地址发 JSON-RPC 请求。inputModes和outputModes用 MIME 类型标注常见的是application/json和text/plain。如果智能体要接收文件加application/pdf之类的类型。3.3 发起一次 A2A 任务委派A2A 的调用流程比 MCP 多一层任务管理。下面用 Python 演示如何向一个 A2A 智能体发起任务# a2a_client_demo.py # 依赖: pip install httpx import httpx import uuid AGENT_URL https://supply.example.com/a2a async def send_task(): task_id str(uuid.uuid4()) payload { jsonrpc: 2.0, id: task_id, method: tasks/send, params: { id: task_id, message: { role: user, parts: [ { type: text, text: 请对账以下订单ORD-1001, ORD-1002, ORD-1003 } ] } } } async with httpx.AsyncClient() as client: resp await client.post( AGENT_URL, jsonpayload, headers{Authorization: Bearer token}, timeout60.0 ) result resp.json() # 任务可能直接完成也可能返回 working 状态 print(任务状态:, result[result][status][state]) return result[result][id] async def poll_task(task_id: str): 长任务需要轮询状态直到 completed 或 failed payload { jsonrpc: 2.0, id: str(uuid.uuid4()), method: tasks/get, params: {id: task_id} } async with httpx.AsyncClient() as client: resp await client.post(AGENT_URL, jsonpayload) return resp.json()[result] import asyncio task_id asyncio.run(send_task()) print(任务已提交:, task_id)逻辑说明A2A 用 JSON-RPC 2.0 作为基础协议tasks/send提交任务tasks/get查询状态。任务状态机包括submitted、working、input-required、completed、failed、canceled。input-required是个关键状态——智能体执行到一半需要补充信息时会暂停并返回这个状态Client 需要再发一条消息补充输入。参数说明message.parts是消息内容数组支持 text、file、data 三种类型。timeout要设够跨智能体调用往往比本地工具调用慢。如果 Agent Card 里声明了streaming: true可以用tasks/sendSubscribe方法建立 SSE 连接实时接收状态更新避免轮询。3.4 A2A 的适用边界A2A 不是万能的。PPT 里明确列了几个不适合用 A2A 的场景单智能体内部调用工具用 MCP、纯数据管道用消息队列、需要严格事务保证的同步调用用 gRPC。A2A 最适合的是「多个智能体分属不同团队或不同系统需要松耦合协作」的场景。比如销售智能体和供应链智能体分属两个部门各自迭代通过 A2A 协议对接谁也不用改谁的代码。4. ANP 协议拆解智能体网络里的发现与信任4.1 ANP 要解决的是什么问题ANP 全称 Agent Network Protocol它比 MCP 和 A2A 更上层。MCP 解决工具接入A2A 解决点对点协作ANP 解决的是「当网络里有成百上千个智能体时怎么发现谁、怎么信任谁、怎么组合成更大的能力」。PPT 里把 ANP 的核心归纳为三个机制去中心化身份DID、能力发现基于语义描述、信任传递基于可验证凭证。这个定位决定了 ANP 的落地门槛比前两者高。MCP 和 A2A 可以单点接入ANP 需要整个网络层面的基础设施。但如果你的场景是「构建一个开放的智能体市场」或「跨组织的智能体协作网络」ANP 是绕不开的。4.2 DID 与可验证凭证的落地方式ANP 用 DID 标识每个智能体用可验证凭证VC表达信任关系。下面是一个简化的 DID 文档示例{ context: https://www.w3.org/ns/did/v1, id: did:example:supply-chain-agent-001, verificationMethod: [ { id: did:example:supply-chain-agent-001#key-1, type: Ed25519VerificationKey2020, controller: did:example:supply-chain-agent-001, publicKeyMultibase: z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK } ], service: [ { id: did:example:supply-chain-agent-001#a2a, type: A2AService, serviceEndpoint: https://supply.example.com/a2a } ] }逻辑说明verificationMethod声明公钥其他智能体用这个公钥验证该智能体签名的消息。service声明服务端点这里指向 A2A 端点说明 ANP 和 A2A 是互补关系——ANP 负责发现和信任A2A 负责实际通信。参数说明publicKeyMultibase是 Multibase 编码的公钥z前缀表示 base58btc 编码。type字段决定签名算法Ed25519 是目前主流选择性能好且密钥短。实际部署时 DID 文档通常托管在区块链或分布式存储上但也可以先用 HTTPS 托管做原型验证。4.3 能力发现与语义匹配ANP 的能力发现基于语义描述不是简单的关键词匹配。每个智能体在 DID 文档或独立的服务描述里声明自己的能力其他智能体用语义相似度找到最合适的协作者。常见做法是用向量数据库存能力描述查询时做相似度检索。# capability_discovery.py # 依赖: pip install sentence-transformers numpy from sentence_transformers import SentenceTransformer import numpy as np model SentenceTransformer(all-MiniLM-L6-v2) # 模拟网络中的智能体能力描述 agents [ {did: did:example:agent-001, capability: 订单对账和差异分析}, {did: did:example:agent-002, capability: 库存查询和补货建议}, {did: did:example:agent-003, capability: 物流轨迹追踪和异常预警}, {did: did:example:agent-004, capability: 财务报表生成和合规检查}, ] # 预计算能力向量 capability_texts [a[capability] for a in agents] capability_vectors model.encode(capability_texts, normalize_embeddingsTrue) def find_agent(query: str, top_k: int 2): 根据自然语言查询找到最匹配的智能体 query_vec model.encode([query], normalize_embeddingsTrue) scores np.dot(capability_vectors, query_vec.T).flatten() ranked np.argsort(scores)[::-1][:top_k] return [ {did: agents[i][did], score: float(scores[i])} for i in ranked ] # 测试找一个能做对账的智能体 results find_agent(我需要核对销售订单和供应链记录) for r in results: print(f{r[did]} 相似度{r[score]:.4f})逻辑说明用 Sentence Transformer 把能力描述和查询都编码成向量做余弦相似度匹配。normalize_embeddingsTrue让向量归一化点积直接等于余弦相似度。实际生产环境会把向量存进 FAISS 或 Milvus支持百万级智能体的毫秒级检索。参数说明all-MiniLM-L6-v2是轻量模型384 维向量适合原型验证。生产环境可以换更大的模型提升语义匹配精度但要注意推理延迟。top_k控制返回候选数量通常取 3 到 5太少容易漏太多增加后续验证成本。5. 避坑与常见问题协议选型和落地中的真实翻车记录5.1 用 MCP 做智能体间通信结果任务状态全丢了现象团队用 MCP 的 Tools 机制让智能体 A 调用智能体 B简单场景能跑通但一旦 B 执行超过 30 秒A 就超时了而且拿不到 B 的中间状态。原因MCP 的 Tools 调用是同步语义设计上就是「调用-返回」的短交互模式。它没有任务状态机不支持长任务和流式中间状态。A2A 才有working、input-required这些状态。解决智能体间通信一律走 A2AMCP 只用于智能体调用无状态工具。如果暂时不想引入 A2A至少把长任务拆成「提交任务返回 task_id」「轮询状态」两步但这本质是在 MCP 上重新实现 A2A 的任务管理不如直接用 A2A。5.2 Agent Card 路径写错发现机制直接失效现象A2A 智能体部署好了但其他智能体死活发现不了它日志里全是 404。原因A2A 规范约定 Agent Card 放在/.well-known/agent.json但有些框架默认路径是/.well-known/agent-card.json或/agent.json。不同实现之间路径不统一导致发现失败。解决部署后用curl https://your-domain/.well-known/agent.json验证路径可访问。如果框架默认路径不同在反向代理层加一条 rewrite 规则统一到标准路径。这个坑很隐蔽因为本地测试时如果 Client 和 Server 用同一个框架路径一致就不会暴露问题。5.3 MCP Server 的工具描述太模糊模型调用率极低现象MCP Server 接入了 10 个工具但模型实际只调用了其中 2 个其他工具明明该用却不用。原因工具的description写得太笼统比如「查询数据」「处理请求」这种。模型在选择工具时依赖描述做语义匹配描述不具体就无法准确判断该用哪个。解决每个工具的 description 要写清楚「做什么、输入什么、输出什么、什么场景用」。比如把「查询数据」改成「根据订单号查询订单状态输入 ORD-XXXX 格式订单号返回状态和预计到达时间」。另外inputSchema里每个参数的 description 也要写模型生成参数时同样依赖这些描述。5.4 ANP 的 DID 解析在离线环境不可用现象在内网环境部署 ANP 智能体网络DID 解析全部失败智能体之间无法互相发现。原因DID 解析通常依赖外部解析器或区块链节点内网环境访问不了。有些实现虽然支持本地缓存但首次解析仍然需要外部访问。解决内网场景用did:web方法替代did:example把 DID 文档托管在内网 HTTPS 服务上解析走标准 HTTP 请求。或者部署本地 DID 解析缓存服务预热常用 DID 文档。选型阶段就要确认 DID 方法是否支持离线解析别等部署了才发现。5.5 三个协议混用时认证体系冲突现象MCP Server 用 API Key 认证A2A 智能体用 OAuth2ANP 用 DID 签名三套认证体系混在一起调用链上认证信息传丢了。原因三个协议各自定义认证声明方式但没有规定互相之间怎么传递认证上下文。MCP 的 API Key 不会自动转成 A2A 的 Bearer TokenANP 的 DID 签名也无法直接用于 MCP 的认证。解决在网关层做认证转换统一用一套内部认证体系比如 JWT各协议端点的认证在网关终止内部调用携带统一的 JWT。这样每个协议对外保持自己的认证声明对内统一。别试图让三个协议直接互认认证信息那是自找麻烦。6. 协议选型的决策框架与验证清单选型这件事PPT 里给了一张对比表但表格只能看个大概真正做决策需要落到具体场景。我一般会按下面这个流程走一遍。第一步明确交互类型。如果是「智能体调用工具/数据源」选 MCP。如果是「智能体调用智能体」选 A2A。如果是「在开放网络中发布和发现智能体」选 ANP。三者不是互斥关系一个系统里可以同时用用 ANP 做发现用 A2A 做协作用 MCP 做工具接入。第二步确认任务时长和状态需求。短任务秒级返回MCP 够用。长任务分钟级以上、需要中间状态必须用 A2A。这一步判断错了后面全是坑。第三步评估网络规模。点对点协作几个到几十个智能体A2A 足够。开放网络上百个以上、需要动态发现才需要 ANP。别为了「看起来先进」上 ANP它的基础设施成本不低。第四步验证认证体系兼容性。把三个协议的认证方式列出来看是否有冲突。有冲突就在网关层统一别在协议层硬解。下面这张表是我自己用的验证清单每次选型后逐项过一遍验证项MCPA2AANP工具/能力描述是否完整检查 inputSchema 和 description检查 Agent Card 的 skills检查能力向量覆盖度长任务支持不支持需自行封装原生支持状态机依赖底层 A2A发现机制手动配置 Server 地址Agent Card 路径可访问DID 解析可用认证方式API Key / OAuthBearer / OAuth2DID 签名 VC流式返回部分支持支持 SSE依赖底层 A2A离线可用性本地 stdio 可用内网 HTTP 可用需确认 DID 方法最后说一个我自己的习惯每次做完协议选型我会写一个最小验证 Demo把三个协议各跑通一次调用链确认端到端没问题再进入正式开发。这个 Demo 不用复杂MCP 跑通一个工具调用A2A 跑通一次任务委派ANP 跑通一次 DID 解析和能力发现就行。花半天时间能省掉后面两周的返工。从那以后我每次做架构评审都强制走一遍这个验证流程希望帮到你。本文还有配套的精品资源点击获取