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 能力复用来说,是一个很好的基础设施。