Spring AI MCP Server 实战:把现有系统暴露给 AI Agent
为什么 MCP 突然重要了
如果你一直在跟 Spring AI,可能已经注意到了一个变化:从 Spring AI 2.0 GA 开始,MCP(Model Context Protocol)不再是社区孵化项目,而是被合并进了 Spring AI 核心。
这意味着什么?
你的 Spring Boot 应用现在可以同时扮演两个角色:
- MCP Client:连接外部 MCP Server(文件系统工具、数据库访问、第三方 API)
- 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 | <dependency> |
这一个 starter 包含了所有需要的东西:注解扫描、JSON Schema 生成、传输层配置、服务器生命周期管理。
第二步:配置
1 | # MCP Server 身份 |
第三步:写工具
1 |
|
就这样。 没有 Controller,没有路由配置,没有 JSON Schema 手写。Spring AI 启动时扫描所有 @McpTool 方法,自动生成 JSON Schema,注册到 /mcp 端点。
启动应用后,任何 MCP 客户端连到 http://localhost:8080/mcp 就能看到这三个工具并调用它们。
关键设计决策
1. description 是写给 AI 看的,不是写给人看的
1 | // 错误:这是给人看的文档 |
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 |
|
客户端看到进度消息,知道工具在干活,不会超时。
4. 异步工具:不要阻塞调用方
如果你的工具会触发长时间任务(如训练模型、大批量数据导出),不要让调用方等着。返回一个任务 ID,让客户端轮询。
1 |
|
什么时候用 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 | ChatClient → MCP Client → MySQL MCP Server |
解耦,但复杂度上升。
建议:先用路线 A 验证场景,再在需要共享时迁移到路线 B。
2. Doris 做分析 + MCP = AI 原生 BI
Doris 4.0+ 支持向量搜索和全文搜索。如果把 Doris 暴露为 MCP Server,AI Agent 可以直接用自然语言查询和分析数据:
1 |
|
这就把 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,按需发现和加载,减轻主应用的工具索引负担。
参考链接
- Spring AI 2.0.0 GA Available Now
- Spring AI 2.0 + MCP: Building a Tool-Calling Agent in 50 Lines
- Spring AI 2.0 MCP Annotations: From Tool to Production
- Spring Boot 4 and Spring AI 2.0: The New Java AI Stack
- Spring AI vs Spring AI Alibaba:Java AI 开发的两个选择
- Spring AI 2.0 ToolSearch 实战:100 个工具只发 5 个
- Agent 安全治理:为什么 Agent 必须先”挣得”自主权
