全栈开发知识库

第十章 智能体通信协议(MCP / A2A / ANP)

一句话总结

智能体世界正在经历"从方言到普通话"的统一:MCP 统一了"智能体怎么用工具"(相当于给工具定了 USB 接口),A2A 统一了"智能体怎么和别的智能体对话",ANP 想让全网的智能体能互相发现和组网。这一章看懂三大协议各管哪段,并亲手写一个自己的 MCP 服务器。

本章你能学到什么

  • 为什么需要通信协议(M×N 集成灾难)
  • MCP 的核心概念、两种传输方式,以及怎么在智能体里用现成的 MCP 工具
  • A2A 和 ANP 各自的定位,三协议的分工地图
  • 从0到1手敲一个天气 MCP 服务器(用官方 SDK,任何支持 MCP 的客户端都能接)
  • 面试高频:MCP 和 Function Calling 的区别

一、为什么需要协议:M×N 灾难

设想没有协议的世界:市面上有 M 个智能体框架(LangChain、AutoGen、HelloAgents……)和 N 个工具服务(天气、数据库、日历……)。每个框架接每个工具都要写一份专属胶水代码,总共 M×N 份。工具升级一次,M 份胶水全要改——这就是"集成灾难"。

协议的思路是加一个中间标准:框架只要会"说协议"(M 份适配),工具只要会"听协议"(N 份适配),总量从 M×N 降到 M+N。这和 USB 统一充电口、HTTP 统一网页访问是同一个套路。每次行业出现 M×N 灾难,最后都靠一个开放协议收场——记住这个规律,以后看新技术不迷路。

三大协议的分工一张图:

┌─────────┐   A2A:智能体 ↔ 智能体   ┌─────────┐
│ 智能体 A │ ←──────────────────→ │ 智能体 B │
└────┬────┘                        └────┬────┘
     │ MCP:智能体 ↔ 工具/数据            │
     ▼                                  ▼
 [天气服务] [数据库] [文件系统]      [搜索服务] …
     ▲
     └── ANP:全网范围的智能体发现与组网(更宏大也更早期)

二、MCP:给工具世界定一个 USB 口

MCP(Model Context Protocol,模型上下文协议)由 Anthropic 2024 年底发布,目前是三者中生态最成熟的。核心角色:

  • MCP 服务器:工具的提供方。把"查天气""读数据库"包装成标准格式对外提供,并能回答"你有哪些工具?每个工具要什么参数?"
  • MCP 客户端:工具的使用方(智能体/IDE/聊天应用)。连上服务器 → 拿到工具清单 → 需要时按标准格式调用。

两种传输方式(面试常问):

传输方式 原理 适用场景
stdio(标准输入输出) 客户端把服务器作为子进程启动,通过管道通信 本地工具(读本地文件、开本地浏览器)
HTTP(含 SSE 流式) 服务器独立部署在网上,客户端远程调用 云端共享服务(团队公用的数据库查询)

MCP vs Function Calling 的区别(高频考点):Function Calling 是模型的能力(模型输出结构化的调用意图),MCP 是工具的分发标准(工具怎么被发现、描述、调用)。两者是上下游关系,不是竞争关系:智能体用 Function Calling 决定"我要调工具",通过 MCP 找到并真正执行工具。

在 HelloAgents 里用现成 MCP 工具非常简单(原书 10.2 节):MCPTool 连上任意 MCP 服务器,服务器的所有工具自动注册进智能体——docs/2 第 3 篇实测过用它两行代码接入社区的地图、搜索服务。MCP 社区生态(几千个现成服务器,从 GitHub 操作到 Slack 收发)是它最大的护城河,写工具前先去 smithery.ai 等市场搜一搜,很可能已经有人写好了。

三、A2A 与 ANP:智能体之间怎么打交道

A2A(Agent-to-Agent),Google 2025 年发布。解决的问题:你的智能体怎么调用别人家的智能体(而不是工具)?核心机制:

  • Agent Card(名片):每个 A2A 智能体挂出一份标准 JSON 名片——我叫什么、我会什么技能、在哪个地址找我;
  • 任务(Task)机制:调用方发任务 → 接收方异步执行 → 中途可以汇报进度、可以追问澄清 → 最终交付。对话式、长任务友好,这是它和"调工具"最大的不同:工具调用是"一问一答",智能体协作是"来回商量"。

ANP(Agent Network Protocol):更宏大的愿景——让全网智能体像网站一样可以被发现(类似 DNS/搜索引擎)、互相认证(去中心化身份 DID)、自由组网。目前处于早期,了解理念即可:如果说 MCP/A2A 在修"点对点的路",ANP 想修"整个路网"。

三句话记住分工:MCP 管"用工具",A2A 管"雇同行",ANP 管"找到彼此"。 真实系统三者叠着用:你的智能体通过 ANP 发现一个擅长财报分析的智能体 → 通过 A2A 委托它任务 → 它内部通过 MCP 调用数据库工具完成分析。


四、动手实战:从0到1手敲你的第一个 MCP 服务器

原书用 HelloAgents 内置的 MCPServer 类,我们用官方 Python SDK(FastMCP)来写——它是行业事实标准,你写出的服务器可以被 Claude Desktop、Cursor、任何支持 MCP 的客户端直接使用,技能可迁移性最强。

4.1 环境准备

pip install "mcp[cli]" requests

要求 Python ≥ 3.10。装完可以用 python -c "import mcp; print('ok')" 确认。

版本说明:本文代码基于 mcp SDK 2.x(2026年主流版本)。如果你装到的是老的 1.x 版本,只需把导入行改成 from mcp.server.fastmcp import FastMCP 并把 MCPServer("weather-server") 换成 FastMCP("weather-server"),其余代码完全一样——2.x 就是把 FastMCP 转正改名成了 MCPServer。

4.2 手敲 weather_server.py(约45行)

"""天气查询 MCP 服务器:任何 MCP 客户端都能连"""

import requests
from mcp.server.mcpserver import MCPServer

mcp = MCPServer("weather-server")

CITY_MAP = {
    "北京": "Beijing", "上海": "Shanghai", "广州": "Guangzhou",
    "深圳": "Shenzhen", "杭州": "Hangzhou", "成都": "Chengdu",
}


@mcp.tool()
def get_weather(city: str) -> str:
    """查询城市当前天气。参数 city 为中文城市名,如 北京"""
    en = CITY_MAP.get(city, city)
    try:
        r = requests.get(f"https://wttr.in/{en}?format=j1", timeout=10).json()
        cur = r["current_condition"][0]
        return (
            f"{city}当前天气:{cur['weatherDesc'][0]['value']},"
            f"气温{cur['temp_C']}°C,体感{cur['FeelsLikeC']}°C,湿度{cur['humidity']}%"
        )
    except Exception as e:
        return f"天气查询失败:{e}"


@mcp.tool()
def list_supported_cities() -> str:
    """列出内置了中文名映射的城市"""
    return "、".join(CITY_MAP)


if __name__ == "__main__":
    mcp.run(transport="stdio")  # 以 stdio 方式运行:等客户端把我拉起来

注意两个设计点:①函数的文档字符串(docstring)就是工具说明书——客户端和 LLM 靠它理解工具怎么用,写得越清楚,LLM 调用越准;②@mcp.tool() 装饰器自动把函数签名转成 MCP 标准的参数描述,你完全不用手写 JSON Schema。

4.3 手敲 test_client.py(约35行)

服务器是 stdio 模式,不能直接 python weather_server.py 看效果(它会安静地等标准输入)。写一个客户端把它拉起来测试:

"""MCP 客户端:拉起服务器,列出工具并调用"""

import asyncio

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client


async def main():
    params = StdioServerParameters(command="python", args=["weather_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("服务器提供的工具:")
            for t in tools.tools:
                print(f"  - {t.name}: {t.description}")

            result = await session.call_tool("get_weather", {"city": "北京"})
            print("\n调用 get_weather('北京') 的结果:")
            print(result.content[0].text)


if __name__ == "__main__":
    asyncio.run(main())
python test_client.py

验收标准(Checkpoint):先打印出两个工具的名字和说明(说明文字正是你写的 docstring!),然后打印北京的真实天气。恭喜——你已经写出了一个符合行业标准的 MCP 服务器,这一刻你和 smithery 市场上几千个服务器的作者用的是同一套技术。

4.4 接进真实客户端(选做但强烈建议)

在 Cursor / Claude Desktop 的 MCP 配置里加上:

{
  "mcpServers": {
    "my-weather": {
      "command": "python",
      "args": ["/绝对路径/weather_server.py"]
    }
  }
}

重启后直接问"北京天气怎么样",AI 会自动调用你写的服务器。想给 HelloAgents 智能体用,则用 MCPTool 指向同一个脚本(写法见原书 10.2.4)。一份代码,处处能接——这就是协议的力量。

再升级(选做):参考原书 10.5.2,补一份 pyproject.toml、Dockerfile 和 smithery.yaml,就能把服务器发布到 Smithery 市场让全世界用。发布过一个 MCP 服务器,简历上是实打实的亮点。


面试视角:本章高频四连问

  1. "MCP 解决了什么问题?"——答 M×N 集成灾难 → M+N;类比 USB/HTTP。加分:提两种传输方式(stdio 本地/HTTP 远程)各自的适用场景。
  2. "MCP 和 Function Calling 什么关系?"——上下游而非竞争:Function Calling 是模型表达"调用意图"的能力,MCP 是工具被"发现和执行"的标准。一个管说,一个管接线。
  3. "A2A 和 MCP 的区别?"——对象不同:MCP 连接"智能体↔工具"(一问一答),A2A 连接"智能体↔智能体"(任务式、异步、可来回澄清)。举例:调天气 API 用 MCP,委托另一个财报分析智能体用 A2A。
  4. "自己写 MCP 服务器要注意什么?"——docstring 即接口文档(LLM 靠它决定怎么调)、参数校验和超时兜底(工具永远可能失败)、安全(不暴露危险操作,或加确认机制——参考 docs/2 第 10 篇的提示注入防线)。

划重点

  1. 协议的价值一句话:把 M×N 的集成灾难降为 M+N。
  2. 分工地图:MCP 用工具,A2A 雇同行,ANP 找到彼此;三者叠加使用,不互相取代。
  3. MCP 两种传输:stdio 管本地,HTTP 管远程;生态(几千个现成服务器)是它最大的资产,先搜后写。
  4. 写 MCP 服务器的两个关键:docstring 写清楚(那是给 LLM 看的说明书)、失败要兜底(工具永远可能挂)。
  5. 手敲的天气服务器务必跑通并接进一个真实客户端——"我发布过自己的 MCP 服务器"是面试里含金量很高的一句话。

下一章预告:目前为止我们都在"用"现成的模型。第十一章进入训练领域——Agentic RL:用强化学习把一个普通模型练成更会用工具、更会推理的智能体模型。

本页由 Markdown 自动渲染 · 共 628 篇笔记