AI Agent 的 TCP/IP 时刻:MCP 协议深度解析
为什么说 MCP 是 Agent 时代的 USB-C?7 月 28 日最大架构重构改了什么?Java 开发者怎么上手?一文讲透。
一、一个问题:你的 Agent 想调工具,到底有多难?
假设你正在开发一个售前商机管理 Agent,它需要:
- 查 CRM 系统里的客户信息
- 调地图 API 计算距离
- 从知识库检索产品资料
- 发消息通知销售跟进
没有 MCP 之前,每接一个工具,你得写一套适配代码:鉴权、序列化、错误处理、超时重试......4 个工具 4 套逻辑,10 个工具 10 套。更要命的是,换了 Agent 框架,这套全得重写。
这就是 N×M 问题:N 个 Agent 乘以 M 个工具,每对组合都是一次硬编码。
MCP 要做的事很简单------把 N×M 降维成 N+M。Agent 只需实现一个 MCP Client,工具只需实现一个 MCP Server,彼此通过标准协议对话。
就像 USB-C 一样:不管你是什么设备,插上就能用。
二、MCP 核心架构:三层 + 三原语
2.1 三层架构
scss
┌──────────────────────────────────────────┐
│ Host (宿主应用) │
│ Claude Desktop / IDE / Agent Runtime │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │MCP Client│ │MCP Client│ │ LLM │ │
│ │ (A) │ │ (B) │ │ │ │
│ └────┬─────┘ └────┬─────┘ └────────┘ │
└───────┼──────────────┼──────────────────┘
│ │
标准协议 标准协议
│ │
┌───────▼──────┐ ┌────▼───────────┐
│ MCP Server │ │ MCP Server │
│ (CRM 工具) │ │ (地图服务) │
└──────────────┘ └────────────────┘
- Host:运行 AI 应用的宿主,比如 Claude Desktop、VS Code、你的 Agent Runtime
- MCP Client:Host 内部的协议客户端,负责与 Server 建立连接、发现能力、转发调用
- MCP Server:封装具体工具/数据源的轻量服务,通过标准协议暴露能力
关键点:Client 和 Server 是 1:1 关系。一个 Host 可以有多个 Client,每个 Client 连一个 Server。
2.2 三原语:Tools / Resources / Prompts
MCP 把所有业务能力归纳为三类原语(Primitive):
| 原语 | 作用 | 类比 | 典型场景 |
|---|---|---|---|
| Tools | 让模型执行动作 | 函数调用 | 查订单、发通知、调 API |
| Resources | 让模型读取数据 | 文件/数据库读取 | 知识库检索、配置读取 |
| Prompts | 预设提示词模板 | 快捷指令 | "帮我分析这个客户"的标准提示词 |
三原语的设计哲学:Tools 写世界,Resources 读世界,Prompts 教模型怎么用。
三、协议底层:JSON-RPC 2.0
MCP 选择 JSON-RPC 2.0 作为消息格式,原因很直接:
- 极轻量,任何语言零门槛解析
- 严格区分 Request-Response 和 Notification
- 内置错误码体系,不用自己发明
一次典型的工具调用流程:
json
// Client → Server: 调用工具
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "query_customer",
"arguments": {
"customer_id": "C-001"
}
}
}
// Server → Client: 返回结果
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "客户名称:XX科技,商机阶段:方案验证,预计金额:120万"
}
]
}
}
四、7 月 28 日最大重构:从有状态到无状态
2026 年 7 月 28 日,MCP 发布了诞生以来最大规模的架构重构。核心变化:取消协议层 Session,改为每次请求携带完整处理信息。
4.1 旧版(2025-11-25)怎么工作的
less
Client Server
│ │
│── initialize ────────────────→│ ← 握手
│←─ Mcp-Session-Id: abc123 ────│ ← 返回会话ID
│ │
│── tools/list (Session:abc) ─→│ ← 后续请求必须带Session
│←─ [tool1, tool2, ...] ───────│
│ │
│── tools/call (Session:abc) ─→│ ← 同一Session粘滞路由
│←─ result ────────────────────│
问题来了:
| 问题 | 具体表现 |
|---|---|
| Pod 重启 = 会话丢失 | K8s 滚动更新,所有进行中的任务断线 |
| 必须粘滞路由 | 负载均衡器要记住哪个请求去哪个实例 |
| 扩容无效 | 加了 10 个副本,流量还黏在原来那个上 |
| 共享状态存储 | 多实例需要 Redis/DB 共享 Session,增加延迟 |
4.2 新版(2026-07-28)怎么工作的
less
Client Server (任意实例)
│ │
│── tools/call ────────────────→│ ← 无握手,直接发
│ Header: Mcp-Protocol-Version│ ← 版本随请求走
│ Body._meta: client info │ ← 客户端身份随请求走
│←─ result ────────────────────│ ← 任何实例都能处理
│ │
│── resources/read ───────────→│ ← 新请求,任意实例
│ Header: Mcp-Method: ... │ ← 方法名走Header
│←─ result ────────────────────│
核心变化对照表:
| 关注点 | 旧版 (2025-11-25) | 新版 (2026-07-28) |
|---|---|---|
| 启动 | initialize → initialized 握手 |
不再有初始化握手 |
| 协议状态 | 建立一次 Session | 每个请求自包含 |
| Client 上下文 | 初始化时交换 | 进入请求 _meta |
| 路由 | 按 Session ID 粘滞 | 任意实例均可处理 |
| Server 能力 | 初始化响应返回 | 按需调 server/discover |
| 请求路由提示 | Gateway 检查 JSON-RPC Body | Mcp-Method + Mcp-Name Header |
4.3 这不是性能优化,是产业分工的划界
用一句更直白的话说:
旧版像去银行必须先开一个房间,办事期间房间一直占着,柜员换班就得从头再来。 新版是每次办业务自带全套证件,任何一个窗口都能接单,人多了就多开窗口。
MCP 工程负责人 Mazin Gilbert 说得很直接:"有状态 Session 是企业从试点走向数万 Agent 规模部署的首要障碍。"
但注意:协议无状态 ≠ 应用无状态。你的业务仍然需要状态------购物车、任务进度、用户授权------只是这些状态不再由协议层管理,而是由你自己显式管理。
json
// 应用状态通过 Handle 传递,不是 Session
{
"tool": "add_item",
"arguments": {
"basket_id": "opaque-handle-from-create-basket",
"sku": "SKU-42"
}
}
五、MCP vs A2A:别搞混了
同一天,A2A 协议庆祝一周年。两者经常被拿来对比,但它们根本不在同一层:
arduino
┌──────────────────────────────────────────┐
│ A2A (Agent-to-Agent) │
│ Agent 之间怎么发现、委派、协作 │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Agent A │─── Task ─→│ Agent B │ │
│ │ (采购主管)│ │(价格分析) │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ ┌────▼─────┐ ┌────▼─────┐ │
│ │MCP Client│ │MCP Client│ │
│ └────┬─────┘ └────┬─────┘ │
└───────┼──────────────────────┼───────────┘
│ MCP 协议 │
┌───────▼──────┐ ┌────────▼─────┐
│ MCP Server │ │ MCP Server │
│ (CRM 系统) │ │ (价格数据库) │
└──────────────┘ └──────────────┘
| 维度 | MCP | A2A |
|---|---|---|
| 解决什么 | Agent ↔ 工具/数据 | Agent ↔ Agent |
| 通信单元 | JSON-RPC 请求/响应 | Task + Artifact |
| 发现机制 | server/discover |
Agent Card |
| 适用场景 | 单 Agent 调工具 | 多 Agent 协作 |
| 关系 | 单个 Agent 的"手" | Agent 之间的"嘴" |
简单记:MCP 给 Agent 配工具,A2A 让 Agent 找同事。两者是上下层关系,不是竞争。
六、Java 开发者上手:Spring AI + MCP
6.1 搭建一个 MCP Server
依赖:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
配置:
yaml
spring:
application:
name: crm-mcp-server
ai:
mcp:
server:
name: crm-mcp-server
version: 1.0.0
instructions: CRM系统工具集,支持客户查询、商机管理
定义工具:
java
@Service
public class CrmTools {
@Tool(description = "根据客户ID查询客户详情")
public CustomerInfo queryCustomer(
@ToolParam(description = "客户ID") String customerId) {
// 实际调用 CRM API 或数据库
return crmService.getCustomer(customerId);
}
@Tool(description = "查询指定销售名下的商机列表")
public List<Opportunity> listOpportunities(
@ToolParam(description = "销售姓名") String salesName) {
return crmService.getOpportunitiesBySales(salesName);
}
}
启动后,这个 Server 就通过 HTTP 暴露了标准 MCP 接口,任何 MCP Client 都能发现和调用。
6.2 在 Agent 中使用 MCP Client
依赖:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
配置连接:
yaml
spring:
ai:
mcp:
client:
servers:
crm:
url: http://localhost:8081/mcp
map:
url: http://localhost:8082/mcp
在 Agent 中调用:
java
@RestController
public class AgentController {
private final ChatClient chatClient;
public AgentController(ChatClient.Builder builder,
List<McpSyncClient> mcpClients) {
// MCP Client 自动发现工具,注入到 ChatClient
this.chatClient = builder
.defaultTools(mcpClients.toArray())
.build();
}
@GetMapping("/ask")
public String ask(@RequestParam String question) {
return chatClient.prompt()
.user(question)
.call()
.content();
}
}
用户问"帮我查 C-001 客户的商机情况",Agent 自动发现 CRM Server 的 queryCustomer 和 listOpportunities 工具,编排调用,返回结果。
6.3 新版无状态适配要点
如果你的 MCP Server 要适配 2026-07-28 新规范:
- 删除 initialize/initialized 握手逻辑,不再维护 Session
- 协议版本走 Header :
Mcp-Protocol-Version: 2026-07-28 - Client 信息走请求
_meta字段,不再依赖初始化交换 - Server 能力通过
server/discover按需获取,不再在初始化响应返回 - 应用状态通过显式 Handle 管理 (如
basket_id、job_id),不再依赖 Session - 幂等性由应用层保证:无状态下重试变频繁,下单/转账等工具必须做去重
七、迁移避坑清单
| 坑 | 怎么避 |
|---|---|
| 直接删 Redis | 先建状态归属清单,证明里面只有 Session 数据 |
| 协议无状态 = 不需要存储 | 应用状态仍然需要,只是换了管理方 |
| 不做幂等 | 下单类工具必须加去重键 + 幂等窗口 |
| 信任 Client Metadata | 每次请求都要鉴权校验,不信任 Client 自报的身份 |
| 永久缓存 Server 能力 | server/discover 结果要有过期时间 |
| 不做跨实例测试 | Round-robin 不够,必须强制请求落到不同实例验证 |
| 一步到位切新版本 | 先做双版本分流层,逐步切流 |
八、生态现状:10 万+ Server,4 亿次月下载
几个关键数据:
- 全球 10 万+ 注册 MCP Server 在运行
- SDK 月度下载量突破 4 亿次
- GitHub MCP Server 已提前适配新规范
- 阿里云、腾讯云、百度云 MCP 广场已同步接入
- Anthropic 已将协议捐赠给 Linux 基金会
企业落地方面,Gartner 预计到 2026 年底,40% 的企业应用将集成任务专用 Agent------而 MCP 就是这些 Agent 连接工具的标准接口。
九、总结:MCP 对 Java 开发者意味着什么
- Agent 不再是玩具:MCP 让 Agent 从"能聊天"变成"能干活",工具接入从硬编码变成标准化协议
- Java 生态全面跟进:Spring AI 已经提供 MCP Client/Server Starter,Java 开发者可以零门槛接入
- 无状态是规模化的前提:7 月 28 日重构不是可选升级,是生产环境的必选项------想在 K8s 上跑 MCP,这是前提
- 协议层做减法,应用层做加法:状态管理、幂等性、鉴权这些责任回归应用层,反而是 Java 开发者最擅长的领域
MCP 不是另一个 API 框架,它是 Agent 连接世界的标准接口。就像 HTTP 定义了 Web 的通信方式,MCP 正在定义 Agent 的通信方式。
相关阅读: