为什么 MCP 突然重要了

如果你一直在跟 Spring AI,可能已经注意到了一个变化:从 Spring AI 2.0 GA 开始,MCP(Model Context Protocol)不再是社区孵化项目,而是被合并进了 Spring AI 核心。

这意味着什么?

你的 Spring Boot 应用现在可以同时扮演两个角色:

  1. MCP Client:连接外部 MCP Server(文件系统工具、数据库访问、第三方 API)
  2. MCP Server:把自己的业务逻辑暴露为 MCP 工具,供任何 MCP 兼容的 AI 客户端调用

以前你写一个 @Tool 方法,只有你自己的 ChatClient 能调用。现在写一个 @McpTool 方法,任何支持 MCP 的 AI 客户端都能调用——Claude Desktop、Cursor、Windsurf,或者另一个 Spring AI 应用的 MCP Client。

这不只是 API 变了,是架构选择变了。

@McpTool 和 @Tool 有什么区别

先搞清楚边界。

维度 @Tool(Spring AI 1.x / 2.0) @McpTool(Spring AI 2.0 MCP)
谁能调用 当前应用的 ChatClient 任何 MCP 兼容客户端
协议 进程内方法调用 HTTP / SSE / stdio 传输
注册方式 @Tool 注解,ChatClient 自动发现 @McpTool 注解,Spring Boot 自动配置 MCP 端点
适用场景 应用内 Agent 工具 跨应用、跨语言工具共享
性能 进程内调用,零网络开销 HTTP 请求,有网络开销
耦合度 工具和 Agent 在同一个进程 工具和 Agent 完全解耦

简单判断标准:

  • 如果你的 Agent 和工具在同一个应用里 → 用 @Tool,更简单更快
  • 如果你希望多个 Agent / 多个应用共享同一组工具 → 用 @McpTool,做成 MCP Server
  • 如果你希望把现有系统暴露给外部 AI 客户端(如 Claude Desktop)→ 用 @McpTool

50 行代码搭一个 MCP Server

Spring AI 2.0 的 MCP Server 开发体验已经非常好了。核心就三步。

第一步:加依赖

1
2
3
4
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

这一个 starter 包含了所有需要的东西:注解扫描、JSON Schema 生成、传输层配置、服务器生命周期管理。

第二步:配置

1
2
3
4
5
6
7
8
9
# MCP Server 身份
spring.ai.mcp.server.name=order-tools
spring.ai.mcp.server.version=1.0.0

# 传输协议:STREAMABLE(MCP 2025-03-26 规范推荐)
spring.ai.mcp.server.protocol=STREAMABLE

# MCP 端点路径,客户端连接 POST /mcp
spring.ai.mcp.server.streamable-http.mcp-endpoint=/mcp

第三步:写工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Component
public class OrderTools {

private final OrderRepository orderRepo;
private final InventoryService inventory;

public OrderTools(OrderRepository orderRepo, InventoryService inventory) {
this.orderRepo = orderRepo;
this.inventory = inventory;
}

@McpTool(
name = "get_order_status",
description = "查询订单状态。用户问订单进度、物流、配送时调用。"
)
public OrderStatus getOrderStatus(
@McpToolParam(description = "订单号,如 ORD-00123", required = true)
String orderId
) {
return orderRepo.findStatus(orderId);
}

@McpTool(
name = "check_inventory",
description = "查询商品库存数量。用户问是否有货、库存多少时调用。"
)
public int getStockCount(
@McpToolParam(description = "SKU 编码", required = true)
String skuCode
) {
return inventory.getStock(skuCode);
}

@McpTool(
name = "create_order",
description = "创建新订单。需要商品列表和收货地址。"
)
public Order createOrder(
@McpToolParam(description = "商品列表 JSON", required = true)
String itemsJson,
@McpToolParam(description = "收货地址", required = true)
String address
) {
return orderRepo.create(itemsJson, address);
}
}

就这样。 没有 Controller,没有路由配置,没有 JSON Schema 手写。Spring AI 启动时扫描所有 @McpTool 方法,自动生成 JSON Schema,注册到 /mcp 端点。

启动应用后,任何 MCP 客户端连到 http://localhost:8080/mcp 就能看到这三个工具并调用它们。

关键设计决策

1. description 是写给 AI 看的,不是写给人看的

1
2
3
4
5
6
7
// 错误:这是给人看的文档
@McpTool(description = "Order query interface")
public OrderStatus getOrderStatus(String orderId) { ... }

// 正确:这是给 AI 看的决策依据
@McpTool(description = "查询订单状态。用户问订单进度、物流、配送时调用。")
public OrderStatus getOrderStatus(String orderId) { ... }

AI 模型根据 description 决定什么时候调用这个工具。如果 description 写得含糊,模型要么不调用(该调不调),要么乱调(不该调也调)。

2. 传输协议选择

协议 适用场景 特点
Streamable HTTP 生产环境,远程调用 MCP 2025-03-26 规范推荐,支持长连接
SSE 向后兼容 已不推荐新项目使用
stdio 本地工具,如 Claude Desktop 插件 进程间通信,无网络开销

99% 的场景选 Streamable HTTP。 只有当你做本地桌面工具(如给 Claude Desktop 提供工具)时才用 stdio。

3. 进度报告:长耗时工具的必修课

最常见的问题:工具执行需要几秒甚至几十秒(如生成报表),AI 客户端等不及超时了。

Spring AI 2.0 提供了 McpSyncRequestContext,可以在工具执行过程中报告进度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@McpTool(name = "generate_report", description = "生成销售报表")
public Report generateReport(
@McpToolParam(description = "报表日期范围", required = true)
String dateRange,
McpSyncRequestContext context // Spring AI 自动注入
) {
context.logging("开始拉取数据...");
List<Data> data = dataService.fetch(dateRange);

context.logging("数据拉取完成,开始聚合...");
Report report = aggregateService.aggregate(data);

context.logging("报表生成完成");
return report;
}

客户端看到进度消息,知道工具在干活,不会超时。

4. 异步工具:不要阻塞调用方

如果你的工具会触发长时间任务(如训练模型、大批量数据导出),不要让调用方等着。返回一个任务 ID,让客户端轮询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@McpTool(name = "export_data", description = "导出数据为 CSV")
public TaskId exportData(
@McpToolParam(description = "导出条件", required = true)
String query
) {
String taskId = taskService.submit(query);
return new TaskId(taskId); // 立即返回,不等导出完成
}

@McpTool(name = "check_export_status", description = "查询导出任务状态")
public ExportStatus checkStatus(
@McpToolParam(description = "任务 ID", required = true)
String taskId
) {
return taskService.getStatus(taskId);
}

什么时候用 MCP Server,什么时候不用

该用 MCP Server 的场景

1. 多 Agent 共享工具

你有 3 个 Spring AI 应用:客服 Agent、运营 Agent、分析 Agent。它们都需要查询订单状态。

不用 MCP:每个应用各自实现 getOrderStatus → 3 份代码,3 个数据库连接。

用 MCP:写一个 order-tools MCP Server,3 个应用作为 MCP Client 连接 → 1 份代码,1 个数据库连接池。

2. 把现有系统暴露给 AI 客户端

你的公司有一套订单系统,想接入 Claude Desktop 让运营人员用自然语言查订单。不用改现有系统,新起一个 MCP Server 包装一层:

1
Claude Desktop → MCP Server (order-tools) → 现有订单系统 API

3. 跨语言工具共享

Python 团队用 LangChain,Java 团队用 Spring AI。工具做成 MCP Server,两个团队都能用。

不该用 MCP Server 的场景

1. 单应用内的简单工具调用

如果你的 Agent 和工具在同一个 Spring Boot 进程里,用 @Tool 就够了。MCP 的网络开销不值得。

2. 高频调用

MCP 通过 HTTP 传输,每次调用都有网络开销。如果 Agent 每秒调用工具 100 次(如批量处理),进程内 @Tool 更合适。

3. 工具返回大数据

MCP 通过 JSON 序列化传输结果。如果工具返回几 MB 的数据(如完整报表),HTTP 传输和序列化开销会很大。考虑让工具写入文件 / 对象存储,只返回 URL。

对正在学 Spring AI + MySQL + Doris + ES 的人意味着什么

1. MCP Server 是”系统对外 AI 接口”的标准答案

你现在的技术栈是:MySQL 做事务、Doris 做分析、ES 做搜索、MQ 做异步。这些系统都有现成的 API。

如果要让 AI Agent 访问这些系统,你有两条路:

路线 A:在 Spring AI 应用里用 @Tool

1
ChatClient → @Tool(查MySQL) + @Tool(查Doris) + @Tool(查ES)

简单,但工具和 Agent 耦合在一起,其他 Agent 用不了。

路线 B:每个系统做 MCP Server

1
2
3
ChatClient → MCP Client → MySQL MCP Server
→ Doris MCP Server
→ ES MCP Server

解耦,但复杂度上升。

建议:先用路线 A 验证场景,再在需要共享时迁移到路线 B。

2. Doris 做分析 + MCP = AI 原生 BI

Doris 4.0+ 支持向量搜索和全文搜索。如果把 Doris 暴露为 MCP Server,AI Agent 可以直接用自然语言查询和分析数据:

1
2
3
4
5
6
7
@McpTool(name = "query_analytics", description = "查询业务分析数据")
public QueryResult queryAnalytics(
@McpToolParam(description = "SQL 查询语句", required = true)
String sql
) {
return dorisJdbcTemplate.queryForList(sql);
}

这就把 Doris 从”人用的 BI 工具”变成了”AI Agent 用的数据接口”。当 AI Agent 可以自主查询和分析数据时,传统 BI 报表的需求会被重新定义。

3. 安全边界:不要让 AI 直接执行写操作

MCP Server 暴露的工具如果包含写操作(CREATE / UPDATE / DELETE),要特别小心。AI Agent 可能会误调用。

生产环境建议:

  • MCP Server 默认只暴露读操作
  • 写操作需要额外权限验证(如要求 Agent 提供 reason 字段)
  • 所有 MCP 调用记录审计日志

更新已有判断

Spring AI vs Spring AI Alibaba:Java AI 开发的两个选择 一文中,我的判断是 Spring AI 是”框架级”选择。MCP 支持合并进核心进一步验证了这个判断——**Spring AI 正在从”LLM 调用框架”演进为”AI 应用平台”**。

Spring AI 2.0 ToolSearch 实战 一文中讨论了工具过多的问题。MCP Server 模式可以和 ToolSearch 结合:把不常用的工具放到外部 MCP Server,按需发现和加载,减轻主应用的工具索引负担。

参考链接