1、概述
前两篇我们讲了MCP Server的开发(MCP实践:MCP Server 开发保姆教程(附全部代码))和使用(),这篇文章我们介绍下如何自己开发MCP Client来调用自己开发的MCP Server。
2、MCP Client开发
MCP Server 调用有两种方式,一种是Stdio模式,另一种是SSE模式。Stdio相当于是依赖包加载到本地进行运行,SSE模式相当于远程服务调用,这篇文章我们介绍使用SSE方式进行调用。
2.1、依赖相关
开发MCP对环境有要求,Jdk要求17+,SpringBoot要求【3.4.0+】 MCP-Client开发有两个依赖包,底层的技术一个是依赖Webmvc,另一个是依赖Webflux。Webmvc是基于Servlet的阻塞式模型,Webflux是一个异步非阻塞式的 Web 框架,它能够充分利用多核 CPU 的硬件资源去处理大量的并发请求。 具体两个依赖如下(目前最新版本【1.0.0-M6】):
xml
<!-- stdio和webMvc是一个包-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- MCP client SSE 包-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
<!-- Spring ai 大模型的实现-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- AI基础依赖(感觉应该是SPI接口,定义接口标准)-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
2.2、代码开发
整体目录 代码开发比较简单,先看下整体目录,由于使用【spring-ai-openai-spring-boot-starter】包,因此许多组件在配置文件中配置完成后可以直接自动注入。

Controller

配置文件 配置文件比较简单,主要分为两部分
- 配置大模型,这里使用火山引擎的豆包大模型,也可以使用其他,只要符合标准OpenAi格式就行
- 配置MCP Server:这里要注意,开发的MCP Server 一定要是以SSE结尾的Endpoint,依赖里面进行强制拼接了(SSE),所以如果路由不正确的话会调不通(高德那个注释掉就是因为调不通)

下面是Client依赖包里面的源码(看网上说1.0的依赖已经修复,但是spring-mcp-client包还未更新到正式maven仓库)
3、功能验证
3.1、启动MCP Server

3.2、启动MCP Client
从MCP Client启动日志中看出订阅成功
从MCP Server启动日志中看出通信成功
3.3、调试
使用Postman进行调试

查看MCP Server发现已经被调用
MCP Server返回结果后,大模型对结果进行总结整理,输出如下
最终结果如下
4、总结
通过各个依赖组件发现,目前MCP相关发展还在初期,许多依赖不是特别完整。因此在开发过程中需要特别的注意配置及依赖版本等内容。如果遇到问题,我们可以进行源码调试,通过源码调试能让我们了解组件的原理。
5、源码
- 依赖
xml
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.young</groupId>
<artifactId>my-agi</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>mcp-client</artifactId>
<packaging>war</packaging>
<name>mcp-client Maven Webapp</name>
<url>http://maven.apache.org</url>
<build>
<finalName>mcp-client</finalName>
</build>
<properties>
<spring-ai.version>1.0.0-M6</spring-ai.version>
<java.version>17</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- stdio模式-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
<repository>
<id>central-portal-snapshots</id>
<name>Central Portal Snapshots</name>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>
- McpClientController
kotlin
package com.young.client.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* @author 刘子洋
* @date 2025年05月14日 下午5:13
* @description:mcp测试调用controller
*/
@RestController
@RequestMapping("/mcp")
public class McpClientController {
private static final Logger log = LoggerFactory.getLogger(McpClientController.class);
private final ChatClient chatClient;
@Autowired
public McpClientController(ChatClient.Builder mcpChatClientBuilder, ToolCallbackProvider tools) {
this.chatClient = mcpChatClientBuilder.defaultTools(tools).build();
}
@PostMapping("/ask")
public String ask(@RequestBody Map<String, String> question) {
String response = chatClient.prompt(question.get("question")).call().content();
log.info("response: {}", response);
return "question: " + question + " <hr>"
+ response
.replaceAll("\\*\\*(.*?)\\*\\*", "<strong>$1</strong>")
.replaceAll("\n", "<br/>");
}
@GetMapping("/askModel")
public String ask2(@RequestParam String question) {
return chatClient.prompt().user(question).call().content();
}
}
- 配置文件
yaml
spring:
application:
name: my-mcp-client
ai:
openai:
api-key: ********
base-url: https://ark.cn-beijing.volces.com/api
chat:
completions-path: /v3/chat/completions
options:
model: doubao-1-5-pro-256k-250115
mcp:
client:
sse:
connections:
server1:
url: http://localhost:8081
# server2:
# url: https://mcp.amap.com
# sse-endpoint: /sse?key=********
server:
port: 8082