AI智能体——MCP实战
1、程序中使用 MCP
1.1、安装依赖
<!-- https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-mcp-client-spring-boot-starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
1.2、编写配置
其次申请一个key。

之后在 resources 目录下新建 mcp-servers.json 配置,定义需要用到的 MCP 服务:
{
"mcpServers": {
"amap-maps": {
"command": "npx",
"args": [
"-y",
"@amap/amap-maps-mcp-server"
],
"env": {
"AMAP_MAPS_API_KEY": "自己的API Key"
}
}
}
}
特别注意:在 Windows 环境下,命令配置需要添加 .cmd 后缀(如 npx.cmd),否则会报找不到命令的错误。
因为调用MCP 服务的本质是在启动项目的过程中,单独开一个子进程,运行 npx @amap/amap-maps-mcp-server 命令,来启动 MCP 服务。当关闭程序时,子进程也关闭,所以我们需要提供 window 上能运行的命令。
1.3、编写 MCP 客户端配置
修改 Spring 配置文件,编写 MCP 客户端配置。由于是本地运行 MCP 服务,所以使用 stdio 模式,并且要指定 MCP 服务配置文件的位置。
spring:
ai:
mcp:
client:
stdio:
servers-configuration: classpath:mcp-servers.json
1.4、修改 LoveApp 的代码,
新增一个利用 MCP 完成对话的方法。通过自动注入的 ToolCallbackProvider 获取到配置中定义的 MCP 服务提供的 所有工具,并提供给 ChatClient。代码如下:
@Resource
private ToolCallbackProvider toolCallbackProvider;
public String doChatWithMcp(String message, String chatId) {
ChatResponse response = chatClient
.prompt()
.user(message)
.advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
// 开启日志,便于观察效果
.advisors(new MyLoggerAdvisor())
.tools(toolCallbackProvider)
.call()
.chatResponse();
String content = response.getResult().getOutput().getText();
log.info("content: {}", content);
return content;
}
private ToolCallbackProvider toolCallbackProvider; Spring AI在启动的时候,会自动读取 mcp-servers.json 配置文件,从中找到所有的工具,自动注入到工具提供者类(ToolCallbackProvider)上
MCP 调用的本质就是类似工具调用,并不是让 AI 服务器主动去调用 MCP 服务,而是告诉 AI “MCP 服务提供了哪些工具”,如果 AI 想要使用这些工具完成任务,就会告诉我们的后端程序,后端程序在执行工具后将结果返回给 AI,最后由 AI 总结并回复。
1.5、测试运行
@Test
void doChatWithMcp() {
String chatId = UUID.randomUUID().toString();
// 测试地图 MCP
String message = "我的另一半居住在西安雁塔区,请帮我找到 5 公里内合适的约会地点";
String answer = loveApp.doChatWithMcp(message, chatId);
}
debug 查看

MCP底层 可以理解为 工具调用,Spring AI 没有单独针对 MCP 开发一套机制,而是把 MCP 转化为 工具,把 MCP 中的 工具 提取出来,从而复用 tools 能力。
结果显示👇

2、MCP 服务端开发
可参照官网进行开发。
2.1、先在 Pexels 网站生成 API Key:

2.2、新建 module
在项目根目录下新建 module,名称为 yuAn-image-search-mcp-server:

2.3、引入依赖
引入必要的依赖,包括 Lombok、hutool 工具库和 Spring AI MCP 服务端依赖。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
2.4、编写两套配置服务文件
在 resources 目录下编写两套服务端配置文件,分别实现 stdio 和 SSE 模式的传输。
1、配置文件 application-stdio.yml
spring:
ai:
mcp:
server:
name: yuAn-image-search-mcp-server
version: 0.0.1
type: SYNC
# stdio
stdio: true
# stdio
main:
web-application-type: none
banner-mode: off
2、配置文件application-sse.yml
spring:
ai:
mcp:
server:
name: yuAn-image-search-mcp-server
version: 0.0.1
type: SYNC
# sse
stdio: false
3、编写主配置文件 application.yml,可以灵活指定激活哪套配置
spring:
application:
name: yuAn-image-search-mcp-server
profiles:
active: stdio
server:
port: 8127
2.5、服务类开发
编写图片搜索服务类,在 tools 包下新建 ImageSearchTool,使用 @Tool 注解标注方法,作为 MCP 服务提供的工具。
@Service
public class ImageSearchTool {
// 替换为你的 Pexels API 密钥(需从官网申请)
private static final String API_KEY = "2.1节申请的 API Key";
// Pexels 常规搜索接口(请以文档为准)
private static final String API_URL = "https://api.pexels.com/v1/search";
@Tool(description = "search image from web")
public String searchImage(@ToolParam(description = "Search query keyword") String query) {
try {
return String.join(",", searchMediumImages(query));
} catch (Exception e) {
return "Error search image: " + e.getMessage();
}
}
/**
* 搜索中等尺寸的图片列表
*
* @param query
* @return
*/
public List<String> searchMediumImages(String query) {
// 设置请求头(包含API密钥)
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", API_KEY);
// 设置请求参数(仅包含query,可根据文档补充page、per_page等参数)
Map<String, Object> params = new HashMap<>();
params.put("query", query);
// 发送 GET 请求
String response = HttpUtil.createGet(API_URL)
.addHeaders(headers)
.form(params)
.execute()
.body();
// 解析响应JSON(假设响应结构包含"photos"数组,每个元素包含"medium"字段)
return JSONUtil.parseObj(response)
.getJSONArray("photos")
.stream()
.map(photoObj -> (JSONObject) photoObj)
.map(photoObj -> photoObj.getJSONObject("src"))
.map(photo -> photo.getStr("medium"))
.filter(StrUtil::isNotBlank)
.collect(Collectors.toList());
}
}
编写这种代码要多看 pexels官网 给的例子,借助官网和大模型生成。
2.6、测试
debug 模式下结果如下

我们随便打开一个网址,在网页中输入,显示如下:

MCP服务开发成功!!!
2.6、在主类注册工具
在主类中通过定义 ToolCallbackProvider Bean 来注册工具
@SpringBootApplication
public class YuAnImageSearchMcpServerApplication {
public static void main(String[] args) {
SpringApplication.run(YuAnImageSearchMcpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider imageSearchTools(ImageSearchTool imageSearchTool){
return MethodToolCallbackProvider.builder()
.toolObjects(imageSearchTool)
.build();
}
}
3、客户端开发
3.1、先引入必要的 MCP 客户端依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
3.2、测试stdio 传输方式
先测试 stdio 传输方式。在 mcp-servers.json 配置文件中新增 MCP Server 的配置,通过 java 命令执行我们刚刚打包好的 jar 包。
{
"mcpServers": {
"amap-maps": {
"command": "npx.cmd",
"args": [
"-y",
"@amap/amap-maps-mcp-server"
],
"env": {
"AMAP_MAPS_API_KEY": "你自己申请的 API"
}
},
"yuAn-image-search-mcp-server": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dspring.main.web-application-type=none",
"-Dlogging.pattern.console=",
"-jar",
"yuAn-image-search-mcp-server/target/yuAn-image-search-mcp-server-0.0.1-SNAPSHOT.jar"
],
"env": {}
}
}
}
3.3、测试运行。
编写单元测试代码:
@Test
void doChatWithMcp() {
// 测试图片搜索 MCP
String message = "帮我搜索一些哄另一半开心的图片";
String answer = loveApp.doChatWithMcp(message, chatId);
Assertions.assertNotNull(answer);
}
结果返回

我们点击看一下

(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)(⊙﹏⊙)
还行吧
更多推荐

所有评论(0)