MCP 协议深度解析:AI Agent 时代的“USB-C 接口“,Java 开发者如何上车?
MCP 协议深度解析:AI Agent 时代的"USB-C 接口",Java 开发者如何上车?
全文约 12000 字,覆盖协议原理、架构剖析、Spring AI 实战、生产落地全流程。
不聊概念焦虑,只聊能跑通的代码和架构决策。
目录
- 引言:当 AI 遇到"信息孤岛"
- MCP 是什么?一个 USB-C 接口的类比
- MCP 核心架构:两层协议一张图
- 三大原语:Tools、Resources、Prompts
- 实战一:用 Spring AI 搭建你的第一个 MCP Server
- 实战二:MCP Client 消费远程 Server
- 传输层选型:Stdio vs Streamable HTTP 怎么选?
- MCP 的安全模型
- MCP vs Function Calling vs Agent API——一张表说清楚
- 2026 年 MCP 生态全景
- 从架构师视角看 MCP 的定位
- 避坑指南(来自实际踩坑)
- 总结与行动清单
一、引言:当 AI 遇到"信息孤岛"
1.1 一个每天都在发生的场景
想象这个场景:你正在用 Claude Code 或 ChatGPT 写代码,想让 AI 帮忙查一下生产数据库里某个用户的订单状态。于是你手动复制了一段 SQL,跑到数据库客户端执行,然后把结果粘贴回对话框。
这个动作,2026 年的开发者可能每天要重复几十次。
问题出在哪里?AI 的能力再强,也连不上你的系统。 它读不到你的数据库、查不了你的 API、操作不了你的文件系统。每一个数据源、每一个工具,都需要你手动"投喂"。
1.2 2025 年之前:Function Calling 的碎片化困境
在 MCP 出现之前,让 AI 调用外部工具的主流方式是各家大模型厂商提供的 Function Calling(工具调用):
- OpenAI 有
tools参数,你需要写 JSON Schema 描述每个函数 - Anthropic 有
tool_use,格式跟 OpenAI 不完全兼容 - 你需要把工具描述硬编码在每次请求里
- 每接入一个外部系统,都要写一堆适配胶水代码
结果就是:每个 AI 应用都在重复造轮子,整个生态像极了 USB 标准统一之前——每个设备有自己的接口和线缆。
1.3 MCP 的诞生:一个开放标准的出现
2024 年底,Anthropic 提出了 Model Context Protocol(MCP),一个开放协议,旨在标准化 AI 模型与外部工具、数据源、API 之间的交互方式。到 2026 年 7 月,MCP 已经迭代到 2026-07-28 协议版本,获得了整个行业的广泛支持:
- Claude Code / Claude Desktop 原生支持
- ChatGPT 全面接入 MCP
- VS Code Copilot 支持配置 MCP Server
- Cursor / MCPJam 等工具也已拥抱
从一个社区倡议变成了 AI Agent 基础设施层的核心协议。
二、MCP 是什么?一个 USB-C 接口的类比
2.1 一句话定义
MCP(Model Context Protocol)是一个开源的标准化协议,用于连接 AI 应用程序与外部系统。它定义了一套通用的通信规范,让 AI 模型能够发现和调用外部工具、读取数据源、使用预设提示模板。
用官方文档的原话说:
Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems.
2.2 USB-C 类比拆解
| USB-C | MCP |
|---|---|
| 统一了设备充电和数据传输接口 | 统一了 AI ↔ 外部系统的连接方式 |
| 一个充电器可以充手机、笔记本、平板 | 一个 MCP Server 可以被 Claude、ChatGPT、VS Code 共用 |
| 支持不同的协议(USB 2.0/3.0/Thunderbolt) | 支持不同的传输层(Stdio / Streamable HTTP) |
| 即插即用 | 通过 discovery 机制自动发现能力 |
2.3 用 MCP 能做什么?
- Agent 访问你的 Google Calendar 和 Notion,像一个真正的个人助理
- Claude Code 根据 Figma 设计稿生成完整的 Web 应用
- 企业聊天机器人连接多个内部数据库,用户用自然语言查数据
- AI 模型操作 Blender 做 3D 建模,然后直接 3D 打印
这些不是 Demo,而是 2026 年已经普遍落地的场景。
三、MCP 核心架构:两层协议一张图
3.1 三大参与者
MCP 遵循 客户端-服务器架构,涉及三个角色:
┌─────────────────────────────────────────────────┐
│ MCP Host │
│ (AI 应用: Claude Code / ChatGPT) │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ MCP Client 1 │ │ MCP Client 2 │ ... │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
└─────────┼──────────────────┼──────────────────────┘
│ │
┌─────▼──────┐ ┌─────▼──────┐
│ MCP │ │ MCP │
│ Server A │ │ Server B │
│ (数据库) │ │ (文件系统) │
└────────────┘ └────────────┘
- MCP Host:AI 应用程序,协调和管理多个 MCP Client(如 Claude Code、VS Code)
- MCP Client:与 MCP Server 建立点对点连接的组件
- MCP Server:对外提供工具、数据和提示的服务程序
Host 每连接一个 Server,就创建一个 Client 实例。本地 Stdio 传输通常一个 Client 对应一个 Server 进程;远程 Streamable HTTP 传输一个 Server 可以服务多个 Client。
3.2 两层协议
MCP 分为 数据层 和 传输层,概念上数据层在内,传输层在外:
┌──────────────────────────────────────┐
│ Data Layer │
│ (JSON-RPC 2.0 协议 · 原语 · 发现) │
├──────────────────────────────────────┤
│ Transport Layer │
│ (Stdio / Streamable HTTP / SSE) │
└──────────────────────────────────────┘
数据层(Data Layer)
基于 JSON-RPC 2.0 的消息协议,包含:
- 发现(Discovery):Client 通过
server/discover查询 Server 支持的协议版本和能力 - 工具操作:
tools/list发现工具列表,tools/call调用工具 - 资源操作:
resources/list、resources/read - 提示操作:
prompts/list、prompts/get - 通知(Notifications):实时变更通知(如工具列表变化)
传输层(Transport Layer)
两种传输机制(注意:传统 SSE 协议自 Spring AI 2.0 起已废弃,统一使用 Streamable HTTP):
| 传输方式 | 适用场景 | 特点 |
|---|---|---|
| Stdio | 本地进程间通信 | 零网络开销,适合开发调试和单机部署 |
| Streamable HTTP | 远程服务通信 | 支持 HTTP POST + SSE 流式返回,支持 OAuth 认证;SSE 的替代方案 |
3.3 协议版本 2026-07-28 的重要变化
2026 年最新协议版本相比早期版本有几个关键变化:
- Elicitation 取代 Sampling:Server 不再直接请求 LLM 采样,而是通过 Elicitation 向用户请求输入
- Notification 机制成熟:基于订阅(
subscriptions/listen)的实时变更通知 - Stateless 设计:每个请求携带
_meta字段包含协议版本和能力声明,Server 可以独立处理每个请求 - 三方登录标准化:OAuth 2.0 成为推荐的远程认证方式
3.4 一次完整的 MCP 交互流程
Client Server
│ │
│──── server/discover ────────→│ ← 发现:查询能力
│←── supportedVersions, caps ─│
│ │
│──── tools/list ─────────────→│ ← 工具发现
│←── [tool1, tool2, ...] ────│
│ │
│──── tools/call(tool1,args) →│ ← 工具调用
│←── result(content) ────────│
│ │
│──── subscriptions/listen ───→│ ← 订阅通知
│←── ack (subscriptionId) ───│
│ │
│←── notification(toolsChanged)│ ← 实时变更通知
│ │
这是 MCP 最核心的交互模式。理解这 5 步,就理解了 MCP 的 80%。
四、三大原语:Tools、Resources、Prompts
MCP 定义了三个核心原语(Primitives),它们是 Server 可以暴露给 Client 的能力类型:
4.1 Tools(工具)—— 最重要的原语
Tools 是 AI 模型可以调用的可执行函数,相当于给 AI 装上了"手"。
特点:
- AI 模型决定何时调用(不是开发者硬编码调用)
- 通过
tools/list发现,通过tools/call执行 - 入参使用 JSON Schema 定义,自动生成类型约束
典型场景:
- 数据库查询:
query_orders(userId) - API 调用:
get_weather(city) - 文件操作:
read_file(path)
// tools/list 响应示例
{
"tools": [
{
"name": "query_orders",
"description": "根据用户ID查询订单列表",
"inputSchema": {
"type": "object",
"properties": {
"userId": {
"type": "integer",
"description": "用户ID"
},
"status": {
"type": "string",
"enum": ["pending", "shipped", "completed"],
"description": "订单状态筛选"
}
},
"required": ["userId"]
}
}
]
}
4.2 Resources(资源)—— 提供给 AI 的数据
Resources 是有结构的数据源,让 AI 能"读到"系统中的信息。
特点:
- 通过 URI 标识和访问,如
file:///config/app.yml - 支持 URI 模板参数:
config://{key} - 可以订阅变更通知
典型场景:
- 项目配置文件
- 数据库 Schema
- 日志文件内容
4.3 Prompts(提示模板)—— 可复用的交互模板
Prompts 是预定义的提示模板,帮助结构化 AI 的交互方式。
特点:
- 包含参数化占位符
- 可以包含 few-shot 示例
- 被
prompts/list发现,通过prompts/get获取
4.4 三者对比
| 维度 | Tools | Resources | Prompts |
|---|---|---|---|
| 本质 | 函数执行 | 数据读取 | 模板填充 |
| AI 角色 | 主动调用 | 被动读取 | 结构化输入 |
| 操作 | tools/list + tools/call |
resources/list + resources/read |
prompts/list + prompts/get |
| 典型场景 | 查数据库、发邮件 | 读配置文件、访问日志 | 生成 SQL、格式化输出 |
| 返回 | 执行结果 | 数据内容 | 填充后的提示 |
五、实战一:用 Spring AI 搭建你的第一个 MCP Server
这是全篇最核心的实战内容。我们将用 Spring Boot + Spring AI 2.0 搭建一个 MCP Server,暴露一个查询订单的 Tool。代码全程可跑通。
5.1 技术选型
2026 年的 MCP Java 生态是这样的:
| 组件 | 选择 | 说明 |
|---|---|---|
| Spring Boot | 3.4+ | 基础框架 |
| Spring AI | 2.0+ | MCP 集成(Spring 官方维护) |
| MCP Java SDK | 2.0.0 | 底层协议实现 |
| 传输方式 | Stdio / Streamable HTTP | 根据部署场景选择 |
从 Spring AI 2.0 开始,MCP 的 Spring 集成从 MCP Java SDK 迁移到了 Spring AI 项目组下。使用
org.springframework.ai坐标。
5.2 项目初始化
方式一:Spring Initializr(推荐)
访问 start.spring.io,搜索并添加 “MCP Server” 依赖。
方式二:手动添加 Maven 依赖
Spring AI 2.0 提供两个 MCP Server Starter,根据你的传输模式选择:
<!-- ⭐ 方案 A:Stdio 模式(本地进程间通信,开发首选) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
<!-- ⭐ 方案 B:Streamable HTTP 模式(远程服务,生产首选) -->
<!-- 需要配合 spring-boot-starter-web 使用 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
⚠️ 特别注意:这两个 starter 对应不同的传输模式,不能混用。Stdio 模式用
spring-ai-starter-mcp-server,Streamable HTTP 用spring-ai-starter-mcp-server-webmvc。
完整示例(以 Stdio 模式为例):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
</parent>
<dependencyManagement>
<dependencies>
<!-- Spring AI BOM:统一管理版本 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>2.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Stdio 模式 MCP Server(版本由 BOM 管理) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
<!-- 数据库操作示例 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
5.3 编写 MCP Tool(核心代码)
Spring AI 2.0 提供了 @McpTool 注解,一行注解就能把普通 Spring Bean 方法暴露为 MCP Tool:
@Component
public class OrderTools {
private final OrderRepository orderRepository;
public OrderTools(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@McpTool(
name = "query_orders",
description = "根据用户ID和状态筛选查询订单列表"
)
public List<Order> queryOrders(
@McpToolParam(description = "用户ID", required = true) Long userId,
@McpToolParam(description = "订单状态:pending/shipped/completed", required = false) String status) {
if (status != null && !status.isEmpty()) {
return orderRepository.findByUserIdAndStatus(userId, status);
}
return orderRepository.findByUserId(userId);
}
@McpTool(
name = "get_order_detail",
description = "查询单个订单的详细信息"
)
public Order getOrderDetail(
@McpToolParam(description = "订单ID", required = true) Long orderId) {
return orderRepository.findById(orderId)
.orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderId));
}
@McpTool(
name = "get_order_stats",
description = "统计某个时间范围内的订单数据",
annotations = @McpTool.McpAnnotations(readOnlyHint = true, idempotentHint = true)
)
public OrderStats getOrderStats(
@McpToolParam(description = "开始日期 (yyyy-MM-dd)", required = true) String startDate,
@McpToolParam(description = "结束日期 (yyyy-MM-dd)", required = true) String endDate) {
LocalDate start = LocalDate.parse(startDate);
LocalDate end = LocalDate.parse(endDate);
return orderRepository.statByDateRange(start, end);
}
}
💡 关键点:
@McpTool注解的方法会被自动扫描并注册到 MCP Server。参数上的@McpToolParam会自动生成 JSON Schema。readOnlyHint = true告诉 AI 这是一个只读操作,不会修改数据。
5.4 实体和 Repository
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long userId;
private String orderNo;
private BigDecimal amount;
private String status; // pending, shipped, completed
private LocalDate createDate;
// getters & setters 省略
}
public interface OrderRepository extends JpaRepository<Order, Long> {
List<Order> findByUserId(Long userId);
List<Order> findByUserIdAndStatus(Long userId, String status);
@Query("SELECT new OrderStats(count(o), sum(o.amount)) " +
"FROM Order o WHERE o.createDate BETWEEN :start AND :end")
OrderStats statByDateRange(@Param("start") LocalDate start, @Param("end") LocalDate end);
}
5.5 配置文件
根据不同传输模式选择对应的配置:
Stdio 模式(配合 spring-ai-starter-mcp-server):
# application.yml
spring:
application:
name: mcp-order-server
ai:
mcp:
server:
stdio: true # 启用 Stdio 传输
name: order-service
version: 1.0.0
datasource:
url: jdbc:h2:mem:orderdb
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create-drop
show-sql: false
Streamable HTTP 模式(配合 spring-ai-starter-mcp-server-webmvc + spring-boot-starter-web):
# application.yml
spring:
application:
name: mcp-order-server
ai:
mcp:
server:
stdio: false
protocol: STREAMABLE # 使用 Streamable HTTP 协议
name: order-service
version: 1.0.0
datasource:
url: jdbc:h2:mem:orderdb
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create-drop
show-sql: false
server:
port: 8080
💡 选择建议:本地开发调试用 Stdio 模式(零依赖、零网络开销);需要远程访问或被多个 AI 客户端调用时用 Streamable HTTP 模式。
5.6 启动类
@SpringBootApplication
public class McpOrderServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpOrderServerApplication.class, args);
}
}
5.7 测试你的 MCP Server
测试方法一:MCP Inspector(推荐)
MCP Inspector 是官方提供的可视化调试工具:
npx @modelcontextprotocol/inspector \
--transport stdio \
--command "java -jar target/mcp-order-server.jar"
然后在浏览器中打开 Inspector 界面,你可以:
- 查看 Server 发现的能力列表
- 调用
tools/list查看所有工具 - 传入参数调用
query_orders查看返回结果 - 模拟 AI Agent 的完整交互流程
测试方法二:低层级 MCP Client
如果想用 Java SDK 直接测试:
@Component
public class McpServerTester implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
// 使用 MCP Java SDK 创建同步 Client 连接本地 Stdio Server
var stdioParams = ServerParameters.builder("java")
.args("-jar", "target/mcp-order-server.jar")
.build();
var transport = new StdioClientTransport(stdioParams, McpJsonDefaults.getMapper());
try (var client = McpClient.sync(transport)
.requestTimeout(Duration.ofSeconds(10))
.build()) {
// 初始化连接(协议版本协商 + 能力发现)
client.initialize();
// 发现工具
var tools = client.listTools();
System.out.println("发现 " + tools.tools().size() + " 个工具:");
tools.tools().forEach(t ->
System.out.println(" - " + t.name() + ": " + t.description()));
// 调用工具(使用 builder 模式)
var result = client.callTool(CallToolRequest.builder("query_orders")
.arguments(Map.of("userId", 1001))
.build());
System.out.println("查询结果: " + result);
}
}
}
5.8 验证 Server 启动
启动 Spring Boot 应用后,Stdio 模式的 Server 会通过标准输入/输出与 Client 通信;Streamable HTTP 模式的 Server 会在 http://localhost:8080/mcp 暴露端点。
你可以用 curl 简单验证 Streamable HTTP Server 是否在线:
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}'
六、实战二:MCP Client 消费远程 Server
在生产环境中,你的应用通常是 MCP Client——消费其他团队或第三方提供的 MCP Server。
6.1 添加依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
6.2 配置连接
连接远程 Streamable HTTP Server:
spring:
ai:
mcp:
client:
enabled: true
type: SYNC
request-timeout: 30s
streamable-http:
connections:
order-service:
url: http://localhost:8080
endpoint: /mcp
payment-service:
url: http://payment-service:8081
endpoint: /mcp
6.3 在代码中使用
@Service
public class OrderAssistantService {
private final SyncMcpToolCallbackProvider toolCallbackProvider;
private final ChatClient chatClient;
public OrderAssistantService(
SyncMcpToolCallbackProvider toolCallbackProvider,
ChatClient.Builder chatClientBuilder) {
this.toolCallbackProvider = toolCallbackProvider;
// 将 MCP Tools 注册为 AI 模型可用的工具
this.chatClient = chatClientBuilder
.defaultTools(toolCallbackProvider.getToolCallbacks())
.build();
}
public String ask(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
}
当用户说"帮我查一下用户 1001 的订单",Spring AI 会自动:
- 将自然语言匹配到
query_orders工具 - 提取参数
userId = 1001 - 通过 MCP Client 调用远程 Server
- 将结果返回给 LLM 生成回答
你可以同时连接多个 MCP Server,Spring AI 会自动合并所有工具。通过
toolFilter可以按 Server 名称筛选。
七、传输层选型:Stdio vs Streamable HTTP 怎么选?
7.1 对比表格
| 维度 | Stdio | Streamable HTTP |
|---|---|---|
| 通信方式 | 标准输入/输出管道 | HTTP POST + SSE |
| 网络开销 | 无(进程间) | 有(HTTP 往返) |
| 部署复杂度 | 低(本地进程) | 中(需 HTTP 服务) |
| 进程管理 | 需管理子进程生命周期 | 无状态,水平扩展 |
| 认证 | 不适用 | OAuth 2.0 / Bearer Token |
| 负载均衡 | 不支持 | 支持(标准 HTTP LB) |
| 适用环境 | 本地开发、单机部署 | 生产环境、微服务集群 |
| 并发连接 | 通常 1:1 | 1:N(一个 Server 服务多个 Client) |
7.2 选型建议
| 场景 | 推荐传输 | 理由 |
|---|---|---|
| 开发调试 | Stdio | 零配置,启动即用 |
| Claude Code 本地工具 | Stdio | 官方推荐模式 |
| 企业内部 AI 平台 | Streamable HTTP | 多消费者、需认证 |
| 对外暴露业务能力 | Streamable HTTP | 安全控制、运维监控 |
| 容器化部署 | Streamable HTTP | 标准 K8s 服务治理 |
7.3 混用策略
很多团队采用"开发用 Stdio,生产用 Streamable HTTP"的策略。注意这需要切换 starter 依赖,而非仅改配置:
开发环境(pom.xml + application-dev.yml):
<!-- pom.xml: Stdio 模式 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
# application-dev.yml
spring:
ai:
mcp:
server:
stdio: true
生产环境(pom.xml + application-prod.yml):
<!-- pom.xml: Streamable HTTP 模式 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
# application-prod.yml
spring:
ai:
mcp:
server:
stdio: false
protocol: STREAMABLE
server:
port: 8080
💡 最省心的做法:直接用 Stdio 做本地开发,生产部署时换 starter 和配置。两个 starter 不冲突,可以同时存在于依赖中,通过 profile 控制激活哪个配置。
八、MCP 的安全模型
8.1 传输安全
| 传输方式 | 安全机制 |
|---|---|
| Stdio | 本地进程隔离,依赖操作系统权限 |
| Streamable HTTP | OAuth 2.0 / Bearer Token / API Key |
对于远程 MCP Server,推荐使用 OAuth 2.0 获取凭证,然后通过 Bearer Token 认证每个请求:
spring:
ai:
mcp:
client:
streamable-http:
connections:
secure-service:
url: https://internal.company.com/mcp
headers:
Authorization: "Bearer ${MCP_AUTH_TOKEN}"
8.2 授权控制
Spring AI 2.0 的 MCP Server 支持通过 TransportContextExtractor 获取请求上下文(如 HTTP Header),然后在 Tool 内部做授权判断:
@Component
public class SecureOrderTools {
@McpTool(name = "query_orders", description = "查询订单(需要授权)")
public List<Order> queryOrders(
McpSyncRequestContext requestContext,
@McpToolParam(description = "用户ID") Long userId) {
// 从请求上下文中提取认证信息
McpTransportContext ctx = requestContext.transportContext();
String token = (String) ctx.get("authorization");
// 简单的 RBAC 校验
if (!hasPermission(token, "order:read")) {
throw new SecurityException("无订单查询权限");
}
return orderRepository.findByUserId(userId);
}
}
在 Server 端配置 TransportContextExtractor 来提取 HTTP 请求头中的认证信息:
@Bean
public WebMvcStreamableServerTransportProvider transportProvider() {
return WebMvcStreamableServerTransportProvider.builder()
.contextExtractor(serverRequest -> {
String auth = serverRequest.headers().firstHeader("Authorization");
return McpTransportContext.create(Map.of("authorization", auth));
})
.build();
}
8.3 最佳实践
- 最小权限原则:每个 MCP Server 只暴露必要的数据和操作
- 只读属性标记:利用
readOnlyHint = true让 AI 知道哪些工具不会修改数据 - 敏感数据隔离:涉及 PII 或商业敏感数据的工具需要额外的认证层
- 审计日志:所有工具调用记录日志,便于追踪和排查
九、MCP vs Function Calling vs Agent API——一张表说清楚
很多读者会问:MCP 和 OpenAI Function Calling 有什么区别?有了 MCP 还要写 Agent 吗?
9.1 核心区别
| 维度 | MCP | Function Calling | Agent API |
|---|---|---|---|
| 定位 | 开放协议标准 | 模型厂商 API 特性 | 厂商级 Agent 框架 |
| 厂商绑定 | 无(开放协议) | 强绑定(每个厂商不同) | 强绑定 |
| 工具注册 | 静态配置 + 动态发现 | 每次请求传 JSON Schema | 平台侧注册 |
| 传输方式 | Stdio / HTTP 可切换 | 仅 API 调用 | 仅平台 API |
| 服务端实现 | 任意语言(有 SDK) | 不需要(纯客户端) | 平台托管 |
| 跨模型兼容 | ✅ 完全兼容 | ❌ 不兼容 | ❌ 不兼容 |
| 社区生态 | MCP Registry(公开市场) | 无 | 厂商应用商店 |
| 适合谁用 | 工具/数据提供方 | AI 应用消费者 | 第三方开发者 |
9.2 什么时候用什么?
你的角色是...
├── 工具/服务提供方(暴露 API 给 AI 消费)
│ └── ✅ MCP Server(一次开发,所有 AI 平台可用)
├── AI 应用开发者(在自己的 App 里集成 AI)
│ ├── 只用单一模型 → Function Calling 够用
│ └── 多模型或开放生态 → ✅ MCP Client
└── AI 平台方(做大模型应用平台)
└── ✅ 同时支持 MCP 和自家 Agent API
9.3 MCP 不取代 Agent 框架
MCP 解决的是 工具与 AI 的连接标准化,不解决 Agent 的编排逻辑:
- MCP = 基础设施层(连接标准)
- Agent 框架 = 编排层(决策、规划、记忆)
- 两者互补,不是替代关系
你可以用 Spring AI 的 ChatClient + MCP Tools 构建 Agent,也可以用 LangChain4j + MCP,甚至手写 Agent 逻辑。
十、2026 年 MCP 生态全景
10.1 支持 MCP 的客户端(Host)
| 客户端 | 类型 | MCP 支持情况 |
|---|---|---|
| Claude Code | AI 编程助手 | 原生支持,经验最丰富 |
| Claude Desktop | AI 桌面应用 | 原生支持 |
| ChatGPT | AI 对话 | 全面支持 MCP Server 连接 |
| VS Code Copilot | IDE 插件 | 支持配置 MCP Server |
| Cursor | AI 编辑器 | 支持 MCP |
| MCPJam | MCP 专用客户端 | 全功能支持 |
| Visual Studio | IDE | 2026 年新增支持 |
10.2 官方 SDK 矩阵
截至 2026 年 7 月,MCP 官方 SDK 分为三个 Tier:
| Tier | SDK | 维护方 | 完备度 |
|---|---|---|---|
| Tier 1 | TypeScript, Python, C#, Go | 官方核心团队 | 全功能 |
| Tier 2 | Java, Rust | 社区合作 | 核心功能完备 |
| Tier 3 | Swift, Ruby, PHP, Kotlin | 社区维护 | 基础功能 |
Java SDK 虽然是 Tier 2,但由 Spring AI 团队(Christian Tzolov 等)主力维护,与 Spring Boot 深度集成,生产可用度非常高。Server 端 40/40 全量通过官方一致性测试,Client 端 9/10 通过。
10.3 MCP Registry
2026 年,MCP Registry 已经发展为一个公开的 MCP Server 市场,类似于 Docker Hub 之于容器:
- 发布你的 MCP Server 供他人消费
- 发现社区已有的工具(数据库连接器、云服务工具等)
- 版本管理和兼容性追踪
十一、从架构师视角看 MCP 的定位
作为 Java 后端架构师,如何看待 MCP 在系统中的位置?
11.1 MCP 在微服务架构中的角色
┌─────────────┐
│ AI Agent │
│ (Host) │
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌─────▼────┐ ┌────▼───┐ ┌─────▼────┐
│ MCP │ │ MCP │ │ MCP │
│ Client │ │ Client │ │ Client │
└────┬─────┘ └───┬────┘ └────┬─────┘
│ │ │
┌────▼───┐ ┌────▼───┐ ┌─────▼────┐
│ 订单 │ │ 支付 │ │ 用户 │
│ MCP │ │ MCP │ │ MCP │
│ Server │ │ Server │ │ Server │
└───┬────┘ └───┬────┘ └────┬─────┘
│ │ │
┌───▼────┐ ┌──▼────┐ ┌───▼─────┐
│ 订单 │ │ 支付 │ │ 用户 │
│ 微服务 │ │ 微服务│ │ 微服务 │
└────────┘ └───────┘ └─────────┘
关键设计思想:MCP Server 可以作为微服务的"AI 网关层",每个领域微服务暴露出专属的 MCP Server,AI Agent 通过 MCP Client 按需发现和调用。
11.2 演进路径
第一阶段:单体 MCP Server
├── 一个 Spring Boot 应用
├── 暴露当前系统所有 MCP Tool
└── 适合小团队快速验证
第二阶段:领域 MCP Server 集群
├── 每个领域一个独立的 MCP Server
├── 订单领域、支付领域、用户领域
├── 各自独立部署和扩展
└── 适合中大型团队
第三阶段:MCP Mesh
├── MCP Server 注册到 Registry
├── 服务网格级别的 MCP Gateway
├── 统一的认证、限流、监控
└── 适合企业级 AI 平台
11.3 架构决策清单
如果要在你的项目中引入 MCP,建议回答这几个问题:
- 哪些系统能力需要暴露给 AI?(不要全部暴露,从小做起)
- 谁可以调用这些能力?(权限模型)
- 用 Stdio 还是 Streamable HTTP?(开发 vs 生产)
- MCP Server 的部署密度?(一个服务一个 Server?还是合并?)
- 如何与现有的认证体系集成?(OAuth 2.0?内部 SSO?)
十二、避坑指南(来自实际踩坑)
坑 1:JSON-RPC 版本不匹配
MCP 每个请求都携带协议版本。如果 Client 和 Server 的协议版本不兼容,握手会失败。
解决:确保双方使用相同版本的 SDK。Java SDK 2.0.0 对应协议版本 2026-07-28。
坑 2:Tool 命名冲突
多个 MCP Server 暴露同名 Tool(如 query_orders),Client 端不知道调用哪个。
解决:使用 toolNamePrefix 为每个 Server 的工具名加前缀:
spring:
ai:
mcp:
client:
streamable-http:
connections:
order-service:
url: http://localhost:8080/mcp
tool-name-prefix: "order_" # 工具名变为 order_query_orders
payment-service:
url: http://localhost:8081/mcp
tool-name-prefix: "payment_"
坑 3:长耗时 Tool 的 Timeout
某些 Tool(如数据分析、报表生成)可能执行超过 30 秒,触发 Client 超时。
解决:
- 配置合理的
request-timeout - 对长任务使用异步模式,先返回 taskId,再轮询结果
- 考虑使用 MCP 的 Progress Tracking 机制
坑 4:Windows 上 Stdio 无法启动
Windows 上 npx、npm 等是 .cmd 批处理文件,不是原生可执行文件。Java 的 ProcessBuilder 无法直接执行。
解决:用 cmd.exe /c 包装:
{
"mcpServers": {
"filesystem": {
"command": "cmd.exe",
"args": ["/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "."]
}
}
}
坑 5:Stdio Server 进程管理
Stdio 模式下,Client 直接启动 Server 子进程。如果 Client 异常退出,子进程可能变成僵尸进程。
解决:实现 shutdown hook 优雅清理:
@PreDestroy
public void cleanup() {
// 关闭 MCP Client 时自动关闭关联的 Stdio 子进程
mcpClient.close();
}
Spring AI Client Starter 默认已经处理了生命周期管理,但自己手写 Client 时要注意。
坑 6:过度暴露
新手最容易犯的错误:把所有数据库表都暴露为 MCP Tool,包括敏感字段。
解决:
- 每个 Tool 只在返回值中包含必要的字段
@McpToolParam的description不要暴露实现细节- 敏感操作必须走额外的授权层
十三、总结与行动清单
13.1 核心结论
- MCP 是 2026 年 AI Agent 基础设施层的核心协议,类似于 HTTP 之于 Web、USB-C 之于外设
- 它不是替代 Function Calling,而是更上层的标准化——跨模型、跨平台、跨语言
- Java 生态已经准备就绪——Spring AI 2.0 + MCP Java SDK 2.0 提供了生产级支持
- 对于后端开发者,MCP 是"把自己系统的能力开放给 AI"的标准方式
13.2 三步上手指南
第 1 步:理解协议(30 分钟)
├── 阅读本文第四节的三大原语
├── 理解 discovery → list → call 的交互流程
└── 打开 MCP Inspector 看一个真实 Server 的响应
第 2 步:跑通 Demo(2 小时)
├── 用 Spring Initializr 创建项目
├── 写一个 @McpTool 注解的方法
├── 用 MCP Inspector 测试
└── 让 Claude Code / ChatGPT 连上来调用
第 3 步:接入生产(2 天)
├── 选择传输方式(推荐 Streamable HTTP)
├── 配置认证和授权
├── 部署到测试环境
└── 用实际业务场景验证
13.3 参考资料
| 资源 | 地址 |
|---|---|
| MCP 官方网站 | https://modelcontextprotocol.io |
| MCP Java SDK | https://github.com/modelcontextprotocol/java-sdk |
| Spring AI MCP 文档 | https://docs.spring.io/spring-ai/reference/api/mcp/mcp-overview.html |
| MCP 规范 | https://modelcontextprotocol.io/specification/latest |
| MCP Registry | https://registry.modelcontextprotocol.io |
| Spring Initializr | https://start.spring.io |
更多推荐


所有评论(0)