背景
MCP全称Model Context Protocol ,模型山下文协议,是一种标准化协议,使AI模型能够以结构化方式与外部工具和资源交互。MCP可以将各种大模型工具、或者能力以较为标准的方式暴露出来,方便其他组件完成对接,封装了很多以往需要实现的交互过程,也扩宽了大模型的能力边界。
当前MCP已经快速发展,大有成为事实标准的趋势。最新发布的SpringAI(2025-6)中已经实现了对MCP的封装组件,本文通过一个调用示例,实现基于SpringAI的MCP服务,并通过客户端访问,完成功能验证。
主要过程
首先,我们通过Spring的项目构建工具添加依赖,注意当前使用的SpringAI版本是1.0.0。之前有使用过1.0.0-M6,M7,部分依赖发生了比较大的变化,会产生很多复杂的问题。
其次,编写实际调用工具,再将其注册,方便MCP服务将其引入。
然后,增加相关配置,包括MCP配置、基础模型配置。国内可以使用比如Qwen,Deepseek, GLM等模型。本文中使用的是glm-4-plus。
最后,通过客户端增加本地MCP服务地址,进行调用,验证访问。
依赖
这里贴出了完整的POM依赖。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.4.7</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.my.csp.op</groupId> <artifactId>my-ai-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>my-ai-demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>21</java.version> <spring-ai.version>1.0.0</spring-ai.version> <lombok.version>1.18.30</lombok.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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-mcp-server-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-vector-store-milvus</artifactId> </dependency><!-- add start --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId> </dependency><!-- add end --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>${spring-ai.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- 剩余忽略 -->
主要代码逻辑
工具类定义
实现一个获取本地系统时间的方法。
import org.springframework.ai.tool.annotation.Tool;import org.springframework.stereotype.Service;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;@Servicepublic class CurrentTimeTool { @Tool(description = "精确获取当前系统时间") public String getCurrentTime() { return LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME); }}
注册工具
这个工具非常简单,用于获取当前服务端精确时间。
import org.springframework.ai.tool.ToolCallbackProvider;import org.springframework.ai.tool.method.MethodToolCallbackProvider;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class McpConfig { @Bean public ToolCallbackProvider toolCallbackProvider(CurrentTimeTool currentTimeTool) { return MethodToolCallbackProvider.builder().toolObjects(currentTimeTool).build(); }}
注意:有的文章提到要将ToolCallbackProvider注册给ChatClient,实际执行发现不需要,也可以让MCP服务注册。
增加模型交互端
import lombok.RequiredArgsConstructor;import org.springframework.ai.chat.client.ChatClient;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@RequiredArgsConstructor@Configurationpublic class ChatConfig { private final ChatClient.Builder builder; @Bean public ChatClient chatClient() { return builder .build(); }}
主要配置和注释
spring.application.name=csp-ai-demo#非常重要,和依赖共同影响,可能使得MCP服务无法正常启动spring.main.web-application-type=reactive#全面的日志,可以帮助查看MCP交互logging.level.root=debugserver.servlet.encoding.charset=UTF-8server.servlet.encoding.force=true#MCP主要配置,注意server.type也和webflux或者springMVC配置有关系spring.ai.mcp.server.type=asyncspring.ai.mcp.server.name=local-my-ai-opspring.ai.mcp.server.sse-endpoint=/ssespring.ai.mcp.server.sse-message-endpoint=/mcp/messagespring.ai.mcp.server.enabled=truespring.ai.mcp.server.version=1.0.0#这里使用的是智谱的glm-4-plus模型spring.ai.openai.base-url=https://open.bigmodel.cn/api/paasspring.ai.openai.api-key=your-keyspring.ai.openai.chat.options.model=glm-4-plusspring.ai.openai.embedding.metadata-mode=nonespring.ai.openai.chat.completions-path=/v4/chat/completionsspring.ai.openai.chat.options.temperature=0.0spring.ai.openai.chat.options.max-tokens=4096#由于增加了milvus向量库配置,需要增加miluvs地址。spring.ai.vectorstore.milvus.client.host=your-milvus-hostspring.ai.vectorstore.milvus.client.port=your-milvus-portspring.ai.vectorstore.milvus.database-name=your-milvus-database
执行结果
执行分别使用了1.14.1版本的Chatbox和1.4.5版本的cherry-studio,作为集成客户端,都支持配置MCP服务,相比自己开发客户端,要更加直观和方便。
Chatbox
配置链接
执行结果
Cherry-studio
配置和调用效果
注意事项
- 有时如果服务重启,而客户端没有重新配置,会出现session不存在的错误,在客户端表现为长时间无响应。可以通过客户端重新配置MCP服务实现。cherry-studio客户端比较常出现“虚假调用”的情况,返回调用了MCP的工具,但实际没有执行,可能是工具过于简单。但是相反Chatbox客户端没有出现这种情况。而使用的底层模型都是同样的glm-4-plus。