当前位置: 首页 > news >正文

Spring AI MCP 实战:让大模型调用你的 Java 业务接口

Spring AI MCP 实战:让大模型调用你的 Java 业务接口

背景

最近在和公司 AI 团队对接,遇到了一个很实际的问题:AI 团队开发了一个 MCP 市场,需要把我们现有的 HTTP 业务接口注册上去,供大模型调用。

由此引发了一个思考:如果用 Java 语言来实现一个 MCP 客户端和服务端,应该怎么做?

今天分享一下基于 Spring AI 实现 MCP 客户端和服务端的完整实战经验。

什么是 MCP?

MCP(Model Context Protocol,模型上下文协议)是一个标准化的协议,用于 AI 模型与外部工具和资源交互。你可以把它理解为 AI 领域的 “USB 接口” —— 不管什么设备,只要支持 USB,就能插上去用。

MCP 协议的核心架构分为三层:

1. Client/Server 层

  • MCP Client:管理客户端连接、协议协商、能力发现、工具调用
  • MCP Server:暴露工具、资源,管理客户端连接

2. Session 层

  • 管理通信模式,维持连接状态

3. Transport 层

  • 处理消息传输和 JSON-RPC 序列化
  • 支持多种传输方式:STDIO、HTTP/SSE、Streamable-HTTP

Spring AI MCP 支持

Spring AI 提供了完整的 MCP 支持,通过 Boot Starter 可以快速搭建 MCP Server 和 MCP Client:

组件依赖说明
Serverspring-ai-starter-mcp-server-webfluxWebFlux 版本,支持 SSE、Streamable-HTTP、Stateless
Clientspring-ai-starter-mcp-client-webfluxWebFlux 版本,支持 SSE、Streamable-HTTP

实战:搭建 MCP Server

项目结构

java-ai-mcp-server/ ├── pom.xml └── src/main/ ├── java/com/why/ │ ├── McpServerApplication.java │ └── mcp/server/tool/WeatherService.java └── resources/ └── application.properties

Maven 依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>4.0.5</version></parent><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server-webflux</artifactId></dependency><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>2.0.0-M4</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

配置 application.properties

server.port=9000 # MCP Server 配置 spring.ai.mcp.server.annotation-scanner.enabled=true spring.ai.mcp.server.name=java-ai-mcp-server spring.ai.mcp.server.version=1.0.0 spring.ai.mcp.server.type=sync spring.ai.mcp.server.protocol=sse
  • annotation-scanner.enabled=true:开启注解扫描,自动发现@Tool注解的方法
  • protocol=sse:使用 SSE(Server-Sent Events)传输协议

定义 MCP 工具

只需在方法上加@Tool注解,Spring AI 会自动将其暴露为 MCP 工具:

@ServicepublicclassWeatherService{privatestaticfinalStringBASE_URL="https://restapi.amap.com/v3/weather/weatherInfo";privatefinalRestClientrestClient=RestClient.builder().baseUrl(BASE_URL).build();@Tool(description="获取某个城市的天气")publicStringgetWeather(StringcityCode){returnrestClient.get().uri(uriBuilder->uriBuilder.queryParam("key","你的高德API Key").queryParam("city",cityCode).build()).retrieve().body(String.class);}}

注册工具

@SpringBootApplicationpublicclassMcpServerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(McpServerApplication.class,args);}@BeanpublicToolCallbackProviderweatherTools(WeatherServiceweatherService){returnMethodToolCallbackProvider.builder().toolObjects(weatherService).build();}}

启动后,访问http://localhost:9000/mcp-server即可连接。

实战:搭建 MCP Client

项目结构

java-ai-mcp-client/ ├── pom.xml └── src/main/ ├── java/com/why/ │ ├── McpClientApplication.java │ └── controller/ChatClientController.java └── resources/ └── application.properties

Maven 依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client-webflux</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-minimax</artifactId></dependency>

配置 application.properties

server.port=9001 # MiniMax 配置 spring.ai.minimax.base-url=api.minimax.chat spring.ai.minimax.api-key=你的API Key spring.ai.minimax.chat.options.model=minimax-m2.7 # MCP Client 配置 spring.ai.mcp.client.enabled=true spring.ai.mcp.client.name=java-ai-mcp-client spring.ai.mcp.client.version=1.0.0 spring.ai.mcp.client.type=sync spring.ai.mcp.client.sse.connections.java-ai-mcp-server.url=http://localhost:9000/mcp-server

关键点:Client 的sse.connections.xxx.url必须与 Server 的spring.ai.mcp.server.name对应上。

使用 MCP 工具

通过SyncMcpToolCallbackProvider注入所有 MCP 工具:

@Slf4j@RestController@RequestMapping("minimax")publicclassChatClientController{@ResourceprivateMiniMaxChatModelminiMaxChatModel;@ResourceprivateSyncMcpToolCallbackProvidermcpToolCallbackProvider;@GetMapping(value="/stream/event",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicFlux<String>streamEvent(@RequestParam("question")Stringquestion){ChatClientchatClient=ChatClient.builder(miniMaxChatModel).build();// 获取所有 MCP 工具vartoolCallbacks=mcpToolCallbackProvider.getToolCallbacks();returnchatClient.prompt(question).toolCallbacks(toolCallbacks).stream().content();}}

踩坑记录

1. 协议必须匹配

Server 和 Client 的传输协议必须一致:

Server 配置Client 配置
protocol=ssesse.connections.xxx.url
protocol=streamablestreamable-http.connections.xxx.url

混用会导致400 Bad Request404 Not Found

2. 工具方法必须被 Spring 扫描到

@Tool注解的方法所在的类必须加@Service或其他 Spring 注解,Bean 名称要对应上。

3. Client 端工具回调要用 Provider

不要自己 newSyncMcpToolCallback,通过SyncMcpToolCallbackProvider.getToolCallbacks()获取已注册的工具,这是最稳定的方式。

总结

通过 Spring AI MCP,我们可以轻松地将 Java 业务接口暴露给 AI 模型调用。整个过程只需:

  1. 在方法上加@Tool注解
  2. 配置好 Server 和 Client 的连接
  3. 通过SyncMcpToolCallbackProvider将工具注入 ChatClient

这比手写 Tool Call 逻辑要简单得多,而且支持多种传输协议(SSE、Streamable-HTTP、STDIO),适合各种生产环境。

从这次对接中也能看出,MCP 协议的核心优势在于它的语言无关性—— 不管是 Go、Python 还是 Java,只要实现了 MCP 协议,就能接入 MCP 市场,供大模型调用。这对于企业级的 AI 能力复用来说,是一个很好的基础设施。


http://www.jsqmd.com/news/692850/

相关文章:

  • 从鉴权需求出发:为什么我放弃了Tinyproxy 1.8.3,选择了1.11.1?版本选择与配置实战
  • DeepSeek-Coder-V2实战指南:打破闭源模型壁垒的5大应用场景
  • 从混乱数据到清晰洞察:手把手教你用pheatmap做单细胞转录组数据可视化(Seurat/R兼容)
  • 别再纠结用ComBat还是removeBatchEffect了!一篇讲透它们在单细胞和bulk RNA-seq中的选择策略
  • 一次性搞懂 OSPF 特殊区域:Stub/Totally Stub/NSSA/Totally NSSA
  • 实战分享:我是如何让Windows 10驱动响应主板GPIO中断的(基于ACPI.sys与自定义ASL)
  • 2026年珠海靠谱的阳光房定制安装厂排名,这些品牌值得关注 - 工业推荐榜
  • 5G手机开机后,从“无信号”到“满格”到底经历了什么?—— 手把手拆解RRC连接建立全过程
  • 实战记录:我是如何用Nginx + frp,把家里NAS的Web服务套上自签名HTTPS并安全穿透出去的
  • 保姆级教程:用STM32的硬件SPI驱动ST7567 LCD,彻底告别ST7920的等待延时
  • 2026年性价比高的GEO推广系统推荐,低成本获客就选它 - mypinpai
  • 2026届毕业生推荐的降重复率方案实测分析
  • 2026年黑龙江、吉林、辽宁耐寒牡丹苗批发采购指南 - 年度推荐企业名录
  • 掌握Agentic RAG:让大模型更智能,轻松提升AI应用精度与效率(收藏版)
  • Unity WebGL项目部署到IIS服务器,这5个坑我帮你踩过了(附完整web.config配置)
  • Phi-4-mini-flash-reasoning镜像部署:7860端口映射与反向代理配置
  • 雄县邦讯商贸:东城酒店窗帘回收公司 - LYL仔仔
  • 别再傻傻分不清了!电工老师傅教你一眼看懂接触器和空开的区别与选型
  • OBS录课参数别再乱调了!这份‘黄金比例’设置清单,让你的视频又小又清晰
  • 【2026年最新600套毕设项目分享】在线课堂微信小程序(30160)
  • 2026年推荐6个专业简历模版平台:从国内到海外,覆盖全职业阶段
  • 如何在Windows资源管理器中优雅预览iPhone的HEIC照片缩略图
  • 半导体芯片行业展会全解析:从全产业链到细分赛道,如何选择? - 品牌2026
  • 3分钟掌握DLSS Swapper:免费游戏性能提升器的终极指南
  • C++26反射接入失败率高达67%?资深标准委员会成员亲授4类编译器差异适配方案(附Godbolt可验证示例)
  • K8s Pod 网络通信原理
  • 2026年|论文AI率太高怎么办?亲测5款降AI率工具,附效果对比 - 降AI实验室
  • 5步轻松解决Windows软件运行问题:VisualCppRedist AIO全面指南
  • 给新人的半导体ATE测试扫盲:DFT向量、MBIST、IDDQ到底在测什么?
  • springboot微信小程序的垃圾分类信息系统