Spring AI实现MCP Server和Client #java
官方参考文档:模型上下文协议 (MCP) :: Spring AI 参考 - Spring 框架
下面实现一个简单实例:
MCP Server服务
主要步骤:将 Spring Boot 项目改造成一个 MCP Server,通过引入 Spring AI MCP Server 相关依赖,将业务能力以 MCP Tool / Resource 的形式标准化的暴露给大模型,并通过 SSE(Server-Sent Events) 与模型侧建立长连接通信。
引入依赖
<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-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>注解开发
在com.fang.mcp.tool包下面,定义了一个MyMathTool 的自定义计算类,使用McpTool注解将方法声明成可通过 MCP 协议暴露给大模型调用的工具(Tool):
@Component public class MathTools { @McpTool(name = "add", description = "计算两个数字的cp指数") public double add( @McpToolParam(description = "第一个数字", required = true) double a, @McpToolParam(description = "第二个数字", required = true) double b) { return 1314 *(a + b) / 520; } @McpTool(name = "fangCal", description = "计算小方数") public double fangCal( @McpToolParam(description = "被计算数字", required = true) double a) { return a * a - a + 520; } }配置文件
server: port: 8080 spring: application: name: mcp_server #启用一个 MCP Server,并通过 SSE协议,把本服务的能力暴露给 LLM 使用 ai: mcp: server: name: mcp_server version: 1.0.0 enabled: true protocol: SSE sse-endpoint: /api/v1/sse #SSE 长连接端点(通过这个地址建立 SSE 长连接) sse-message-endpoint: /api/v1/mcp #MCP 消息交互接口(MCP Client 通过 HTTP-POST 实际调用入口) capabilities: #能力是显式声明的,包括tool,resource,prompt,memory(像高德MCP仅支持tool) tool: true然后启动项目即可,可以用postMan先测试一下:可以看到以及能正常获取并使用工具的功能:

MCP Client
Web客户端 应用通过 Spring AI的OpenAI SDK 调用大模型,引入 MCP Client,通过 SSE 接入独立的 MCP Server,实现模型与工具、数据能力的解耦。
使用Spring Initializr构造一个web的项目骨架:依赖带上web、openAI和McpClient

大模型配置类
com.fang.mcp_client.config包下,创建 ChatClientConfig:
@Configuration public class ChatClientConfig { @Bean public ChatMemory chatMemory() { //默认使用的存储库就是InMemory(基于本地内存)无持久化,默认窗口大小是20 return MessageWindowChatMemory.builder() .build(); } @Bean public ChatClient chatClient(OpenAiChatModel model, ChatMemory chatMemory, ToolCallbackProvider mcpTools) { return ChatClient .builder(model) .defaultSystem("你是一个数学老师!") .defaultAdvisors( new SimpleLoggerAdvisor(), MessageChatMemoryAdvisor .builder(chatMemory) .build() ) .defaultToolCallbacks(mcpTools) //在这里引入MCP的工具 .build(); } }这样就定义了一个接入了外部MCP工具以及带有记忆功能的简单的大模型。
controller入口
@RequiredArgsConstructor @RestController @RequestMapping("/ai") public class AIController { private final ChatClient chatClient; //个人习惯用构造器注入 @RequestMapping(value = "/{chatMessage}",produces = "text/html;charset=utf-8") public String textChat(@PathVariable("chatMessage") String chatMessage){ return chatClient.prompt() .user(chatMessage) .advisors(a -> a.param(CONVERSATION_ID, 10086)) //传入ID,先随便给一个 .call() .content(); } }配置文件
server: port: 8081 spring: application: name: spring-car ai: openai: api-key: #填上自己在阿里云申请的Key base-url: https://dashscope.aliyuncs.com/compatible-mode chat: #对话模型 options: model: qwen-max-latest mcp: client: sse: connections: server1: url: http://localhost:8080 sse-endpoint: /api/v1/sse #还可以加上其他的MCP服务,比如高德的然后启动项目即可,在浏览器测试如下:可以看到大模型已经能按照我们之定义的规则进行计算。

SSE协议(补充)
SSE 的连接过程是一次普通get HTTP 请求建立长连接,服务器通过 text/event-stream 持续推送事件数据,连接保持期间无需客户端轮询,断开后支持自动重连,非常适合 MCP 中 Tool 执行的流式反馈场景。 适用于远程部署的 MCP 服务器,可以通过 HTTP 协议与 MCP 服务器进行通信。
对比:HTTP 是一次请求一次响应的无状态模型,每次反复发起请求增加网络开销,也不利于维护会话上下文。
前面服务端有配置:
sse-endpoint: /api/v1/sse #SSE 长连接端点(通过这个地址建立 SSE 长连接) sse-message-endpoint: /api/v1/mcp #MCP 消息交互接口(MCP Client 通过 HTTP-POST 实际调用入口)具体实现过程:(先向sse-endpoint发送HTTP的get请求建立长连接,返回session-ID,再向sse-message-endpoint发送pose请求带上请求体和ID,最后会在se-endpoint收到请求的回复)
可以参考:Lifecycle - Model Context Protocol,介绍MCP的生命周期