本地MCP-开发步骤,需要MCP-Client和MCP-Server,以及MCP的优点
MCP是一个CS的架构,所以先从本地端的MCP实现
一、改pom
重点:
<!--注意事项(重要)
spring-ai-starter-mcp-server-webflux不能和<artifactId>spring-boot-starter-web</artifactId>依赖并存,
否则会使用tomcat启动,而不是netty启动,从而导致mcpserver启动失败,但程序运行是正常的,mcp客户端连接不上。 -->spring-boot-starter-web是Tomcat启动的
spring-boot-starter是netty启动的
为了不让spring-ai-starter-mcp-server-webflux和starter启动发生冲突,这里选择spring-boot-starter作为起步依赖
<!--注意事项(重要)
spring-ai-starter-mcp-server-webflux不能和<artifactId>spring-boot-starter-web</artifactId>依赖并存,
否则会使用tomcat启动,而不是netty启动,从而导致mcpserver启动失败,但程序运行是正常的,mcp客户端连接不上。
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--mcp-server-webflux-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
完整版本:
<?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>com.atguigu.study</groupId>
<artifactId>SpringAIAlibaba-atguiguV1</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>SAA-14LocalMcpServer</artifactId>
<dependencies>
<!--注意事项(重要)
spring-ai-starter-mcp-server-webflux不能和<artifactId>spring-boot-starter-web</artifactId>依赖并存,
否则会使用tomcat启动,而不是netty启动,从而导致mcpserver启动失败,但程序运行是正常的,mcp客户端连接不上。
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--mcp-server-webflux-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
二、YML
server.port=8014
# 设置全局编码格式
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8
spring.application.name=SAA-14LocalMcpServer
# ====mcp-server Config=============
#MCP Server的异步访问
spring.ai.mcp.server.type=async
#MCP Server的服务器的名字
spring.ai.mcp.server.name=customer-define-mcp-server
#MCP Server服务器的版本号
spring.ai.mcp.server.version=1.0.0
三、业务类---MCP-Server服务端实现
1.新建模块
SAA-14LocalMcpServer
2.天气预报WeatherService服务类
package com.atguigu.study.service;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @auther bs@126.com
* @create 2025-07-31 21:07
* @Description TODO
*/
@Service
public class WeatherService
{
@Tool(description = "根据城市名称获取天气预报")
public String getWeatherByCity(String city)
{
Map<String, String> map = Map.of(
"北京", "11111降雨频繁,其中今天和后天雨势较强,部分地区有暴雨并伴强对流天气,需注意",
"上海", "22222多云,15℃~27℃,南风3级,当前温度27℃。",
"深圳", "333333多云40天,阴16天,雨30天,晴3天"
);
return map.getOrDefault(city, "抱歉:未查询到对应城市!");
}
}
3.ToolCallbackProvider接口配置类
因为WeatherService已经被@Service进行了修饰,所以它可以自动装配到下面类
要把自己写的方法暴露出去供给外部的MCP Client调用,所以就要使用MethodToolCallbackProvider进行构建,toolObject表示要用一个工具类,要把工具类注入进去,这样WeatherService这个服务就基于MCP协议对外暴露了
package com.atguigu.study.config;
import com.atguigu.study.service.WeatherService;
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;
/**
* @auther zzyybs@126.com
* @create 2025-07-31 21:08
* @Description TODO
*/
@Configuration
public class McpServerConfig
{
/**
* 将工具方法暴露给外部 mcp client 调用
* @param weatherService
* @return
*/
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService)
{
return MethodToolCallbackProvider.builder()
.toolObjects(weatherService)
.build();
}
}
4.由于本次引入的是SpringBoot-starter,并没有web,所以后台启动的不是Tomcat,而是netty
Netty服务器是一个真正的高并发的服务器
Tomcat是对内启动,Netty是一个高并发的服务器并对外暴露
四、MCP-Client客户端实现
1.新建模块
8015端口访问8014端口
SAA-15LocalMcpClient
2.pom.xml
重点:
由于是客户端Client,所以此时就可以使用spring-boot-starter-web了,也就是Tomcat服务器
spring-ai-alibaba-starter-dashscope的依赖
spring-ai-starter-mcp-client是MCP客户端的依赖,spring-ai-starter-mcp-server-webflux是服务端的依赖(使用的是spring-boot-starter,因为要使用Netty)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring-ai-alibaba dashscope-->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- 2.mcp-clent 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<?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>com.atguigu.study</groupId>
<artifactId>SpringAIAlibaba-atguiguV1</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>SAA-15LocalMcpClient</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring-ai-alibaba dashscope-->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- 2.mcp-clent 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
3.YML
server.port=8015
# 设置全局编码格式
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8
spring.application.name=SAA-15LocalMcpClient
# ====SpringAIAlibaba Config=============
#阿里巴巴大模型
spring.ai.dashscope.api-key=${aliQwen-api}
# ====mcp-client Config=============
#MCP Client异步访问
spring.ai.mcp.client.type=async
#MCP Client的请求时间是60s
spring.ai.mcp.client.request-timeout=60s
#MCP Client是否要开启工具类调用返回,这里开启了
spring.ai.mcp.client.toolcallback.enabled=true
#MCP Client会提供MCP的协议去调用8014这个MCP Server
#如果有多个MCP Server,可以在下面多加几个
spring.ai.mcp.client.sse.connections.mcp-server1.url=http://localhost:8014
4.配置类
package com.atguigu.study.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @auther zzyybs@126.com
* @create 2025-07-31 20:47
* @Description TODO
*/
@Configuration
public class SaaLLMConfig
{
@Bean
public ChatClient chatClient(ChatModel chatModel, ToolCallbackProvider tools)
{
return ChatClient.builder(chatModel)
.defaultToolCallbacks(tools.getToolCallbacks()) //mcp协议,配置见yml文件
.build();
}
}
MCP协议是以服务的形式来进行工具的调用,相当于是ToolCalling的一种服务升级版本
5.Controller
package com.atguigu.study.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
/**
* @auther zzyybs@126.com
* @create 2025-07-31 21:14
* @Description TODO
*/
@RestController
public class McpClientController
{
@Resource
private ChatClient chatClient;//使用mcp支持
@Resource
private ChatModel chatModel;//没有纳入tool支持,普通调用
// http://localhost:8015/mcpclient/chat?msg=上海
@GetMapping("/mcpclient/chat")
public Flux<String> chat(@RequestParam(name = "msg",defaultValue = "北京") String msg)
{
System.out.println("使用了mcp");
return chatClient.prompt(msg).stream().content();
}
@RequestMapping("/mcpclient/chat2")
public Flux<String> chat2(@RequestParam(name = "msg",defaultValue = "北京") String msg)
{
System.out.println("未使用mcp");
return chatModel.stream(msg);
}
}
服务端的
客户端的,带着ToolCallbacks这个服务回调
五、测试
大模型会进行优化,把22222去掉了
说明访问到了MCP Server所暴露的天气预报的实时信息,由于调用配置的是阿里千问,大模型收到这个信息会进行优化和反馈
http://localhost:8015/mcpclient/chat2?msg=上海
六、优点
此时这种MCP的方式,无需每个微服务都带着Util工具类了(ToolCalling),功能全都让一个MCP服务器去实现
也就是只需要一个MCP Server去做这种通用的服务,后续如果需要这种通用的信息,只需要在客户端的配置文件直接访问这个地址的MCP Server,然后就可以拿到里面的数据
更多推荐
所有评论(0)