MCP 的全称是 Model Context Protocol。它是由 Anthropic 公司推出的一项开放协议,旨在解决大语言模型应用中的一个核心问题:如何让 AI 模型安全、标准化地连接和使用外部工具、数据源和 API。
下面,我们基于SpringAI 去实现一个MCP使用案例。
MCP分为服务端和客户端。服务端提供agent能力,客户端调用服务接口能力在结合模型提供对外服务。
1. 前置条件
- deepseek 等线上模型或本地安装模型
- Springboot 3.5.9 +
- jdk 17 +
我以本地模型示【基于vllm搭建的qwen8b】,jdk21, Springboot 3.5.9,SpringAI 1.1.2版本演示代码。并且基于SSE传输设置MCP协议访问
2. 服务端代码
pom.xml 核心依赖。客户端与服务端依赖类似,唯一区别在于mcp-server和mcp-client
<!-- mcp 服务端 webflux SSE 传输-->
<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-model-openai</artifactId>
</dependency>
......
<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>
配置代码如下
/**
* mcp 工具,将该方法暴露给客户端
*
* @param toolService toolService
* @return ToolCallbackProvider
*/
@Bean
public ToolCallbackProvider toolCallbackProvider(ToolService toolService) {
return MethodToolCallbackProvider.builder()
.toolObjects(toolService)
.build();
}
该处代码用于将工具服务暴露出去,供客户端调用
@Bean
public ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory, ToolService toolService) {
return ChatClient.builder(chatModel)
.defaultSystem("你作为一名专业的AI助手,请根据用户提示信息回答问题。再根据用户信息,自定判断是否需要调用工具")
.defaultAdvisors(MessageChatMemoryAdvisor
.builder(chatMemory).build())
// 自定义工具类型
.defaultTools(toolService)
.build();
}
/**
* 聊天配置基于jdbc 存储于 MySQL 数据库中
*/
@Bean
public ChatMemory chatMemory(JdbcChatMemoryRepository repository) {
return MessageWindowChatMemory.builder()
.chatMemoryRepository(repository)
.maxMessages(200)
.build();
}
上述代码一方面配置自定义工具的使用,另一方面设置可以将聊天存进历史中。我这里是将历史信息存于MySQL数据库中。默认是存于内存中
@Slf4j
@Component
public class ToolService {
RestTemplate restTemplate = new RestTemplate();
@Tool(name = "getLocalOilPrice", description = "根据省份获取当地油价信息")
public String getLocalOilPrice(@ToolParam(description = "要查询的油价的省份名称") String province) {
log.info("调用获取当地油价工具,省份:{}", province);
String format = String.format("https://shanhe.kim/api/youjia/youjia.php?province=%s", province);
return restTemplate.getForObject(format, String.class);
}
}
这里定义自己的服务能力,根据自己实际业务来即可
application.yml如下
spring:
application:
name: sjjai
ai:
chat:
memory:
repository:
jdbc:
initialize-schema: always
# mysql mariadb
plateform: mysql
openai:
# https://api.deepseek.com
base-url: http://192.168.10.102:6006/
api-key: sk-aaacczxc
chat:
options:
model: qwen3-8b
datasource:
url: jdbc:mysql://192.168.47.130:3306/sjj-ai?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
connection-init-sql: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
logging:
file:
name: D:/code/sjjai/sjjai.log
server:
port: 8082
上述为服务端代码案例
客户端代码
pom依赖项
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- 引入MCP客户端 webflux SSE -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>
config配置项
/**
* 用户发现服务端mcp 服务(自动集成暴露的工具到client中)
*
* @return SyncMcpToolCallback
*/
@Bean
public SyncMcpToolCallbackProvider toolCallback(List<McpSyncClient> mcpClients) {
return new SyncMcpToolCallbackProvider(mcpClients);
}
@Bean
public ChatClient chatClient(ChatModel chatModel, SyncMcpToolCallbackProvider toolCallback) {
return ChatClient.builder(chatModel)
.defaultSystem("你是一个专业的助手")
.defaultToolCallbacks(toolCallback)
.build();
}
客户端测试代码
@RestController
@RequestMapping("/chat")
@RequiredArgsConstructor
public class ChatController {
final ChatClient chatClient;
@GetMapping(value = "question/{question}")
public Flux<String> chat(@PathVariable String question, HttpServletResponse response) {
response.setCharacterEncoding("utf-8");
return chatClient.prompt("请回答用户问题")
.system("你作为一名专业的AI助手,请根据用户提示信息回答问题。")
.user(question)
.stream()
.content();
}
}
客户端application.yml
spring:
ai:
openai:
# https://api.deepseek.com
base-url: http://192.168.10.102:6006
api-key: sk-6f14d95e96bf46c6aa67983e5b9138bf
chat:
options:
model: qwen3-8b
mcp:
client:
sse:
connections:
server1:
url: http://127.0.0.1:8082
application:
name: shujunjun-ai-test-client
server:
port: 8083
请注意,在服务端因为已经依赖了webflux + Netty 因此不能再使用tomcat,否则客户端在尝试使用sse连接服务端时,会报错404
启动项目后,访问 http://127.0.0.1:8083/chat/question/江苏油价

调用效果
客户端代码:https://gitee.com/JustNickNameWSH/springai-mcp-client
服务端代码:https://gitee.com/JustNickNameWSH/sjjai-server