主要观点总结
文章介绍了如何在Java开发者中使用Spring AI Alibaba框架玩转MCP(Model Context Protocol)的详细流程,包括MCP基础、发布Spring应用为MCP Server、调用MCP Server、在Spring AI Alibaba OpenManus中使用MCP服务、存量应用如何转为MCP服务被智能体调用等。文章还提到了MCP的架构、Spring AI中的MCP支持,并给出了代码示例和源码地址。
关键观点总结
关键观点1: MCP基础与体验
文章介绍了MCP的基础知识、快速体验以及如何发布Spring应用为MCP Server。
关键观点2: 调用MCP Server
介绍了如何调用自己发布的Java MCP Server和市面上的通用MCP Server。
关键观点3: 在Spring AI Alibaba OpenManus中使用MCP
展示了如何在Spring AI Alibaba OpenManus中使用MCP服务,实现智能化。
关键观点4: 存量应用转为MCP服务
提到了存量应用如何转为MCP服务被智能体调用,并给出了后续解决方案。
关键观点5: Spring AI Alibaba中的MCP支持
说明了Spring AI Alibaba框架如何支持MCP,让Java开发者轻松集成MCP服务。
正文
在 Spring AI 中使用 Mcp Server
Spring AI MCP 为模型上下文协议提供 Java 和 Spring 框架集成。它使 Spring AI 应用程序能够通过标准化的接口与不同的数据源和工具进行交互,支持同步和异步通信模式。整体架构如下:
S
pr
ing
AI MCP 采用模块化架构,包括以下组件:
通过 Spring AI MCP,可以快速搭建 MCP 客户端和服务端程序。
2.2 使用 Spring AI MCP 快速搭建 MCP Server
Spring AI 提供了两种机制快速搭建 MCP Server,通过这两种方式开发者可以快速向 AI 应用开放自身的能力,这两种机制如下:
接下来逐一介绍一下这两种方式的实现,示例代码可以通过如下链接获取:
https://github.com/springaialibaba/spring-ai-alibaba-examples/tree/main/spring-ai-alibaba-mcp-example/starter-example/server
2.2.1 基于 stdio 的 MCP 服务端实现
基于 stdio 的 MCP 服务端通过标准输入输出流与客户端通信,适用于作为子进程被客户端启动和管理的场景。
添加依赖
首先,在项目中添加 Spring AI MCP Server Starter 依赖:
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-mcp-server-spring-boot-starterartifactId>
dependency>
配置 MCP 服务端
在
application.yml
中配置 MCP 服务端,这次要实现的是一个天气服务:
spring:
main:
web-application-type: none
banner-mode: off
ai:
mcp:
server:
stdio: true
name: my-weather-server
version: 0.0.1
实现 MCP 工具
使用
@Tool
注解标记方法,使其可以被 MCP 客户端发现和调用,通过
@ToolParameter
注解工具的具体参数:
@Service
publicclassOpenMeteoService {
privatefinal WebClient webClient;
publicOpenMeteoService(WebClient.Builder webClientBuilder){
this.webClient = webClientBuilder
.baseUrl("https://api.open-meteo.com/v1")
.build();
}
@Tool(description = "根据经纬度获取天气预报")
public String getWeatherForecastByLocation(
@ToolParameter(description = "纬度,例如:39.9042") String latitude,
@ToolParameter(description = "经度,例如:116.4074") String longitude) {
try {
String response = webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/forecast")
.queryParam("latitude", latitude)
.queryParam("longitude", longitude)
.queryParam("current", "temperature_2m,wind_speed_10m")
.queryParam("timezone", "auto")
.build())
.retrieve()
.bodyToMono(String.class)
.block();
return"当前位置(纬度:" + latitude + ",经度:" + longitude + ")的天气信息:\n" + response;
} catch (Exception e) {
return"获取天气信息失败:" + e.getMessage();
}
}
@Tool(description = "根据经纬度获取空气质量信息")
public String getAirQuality(
@ToolParameter(description = "纬度,例如:39.9042") String latitude,
@ToolParameter(description = "经度,例如:116.4074") String longitude) {
return"当前位置(纬度:" + latitude + ",经度:" + longitude + ")的空气质量:\n" +
"- PM2.5: 15 μg/m³ (优)\n" +
"- PM10: 28 μg/m³ (良)\n" +
"- 空气质量指数(AQI): 42 (优)\n" +
"- 主要污染物: 无";
}
}
这里使用了 OpenMeteo, OpenMeteo 是一个开源的天气 API,为非商业用途提供免费访问,无需 API 密钥。
注册 MCP 工具
在应用程序入口类中注册工具:
@SpringBootApplication
publicclassMcpServerApplication {
publicstaticvoidmain(String[] args){
SpringApplication.run(McpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider weatherTools(OpenMeteoService openMeteoService){
return MethodToolCallbackProvider.builder()
.toolObjects(openMeteoService)
.build();
}
}
运行服务端
在控制台中执行如下命令,编译并打包应用:
Terminal window
mvn clean package -DskipTests
2.2.2 基于 SSE 的 MCP 服务端实现
基于 SSE 的 MCP 服务端通过 HTTP 协议与客户端通信,适用于作为独立服务部署的场景,可以被多个客户端远程调用,具体做法与 stdio 非常类似。
添加依赖
首先,在您的项目中添加依赖:
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-mcp-server-webflux-spring-boot-starterartifactId>
dependency>
配置 MCP 服务端
在
application.yml
中配置 MCP 服务端:
server:
port: 8080
spring:
ai:
mcp:
server:
name: my-weather-server
version: 0.0.1
实现 MCP 工具
与基于 stdio 的实现完全相同:
@Service
publicclassOpenMeteoService {
privatefinal WebClient webClient;
publicOpenMeteoService(WebClient.Builder webClientBuilder){
this.webClient = webClientBuilder
.baseUrl("https://api.open-meteo.com/v1")
.build();
}
@Tool(description = "根据经纬度获取天气预报")
public String getWeatherForecastByLocation(
@ToolParameter(description = "纬度,例如:39.9042") String latitude,
@ToolParameter(description = "经度,例如:116.4074") String longitude) {
try {
String response = webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/forecast")
.queryParam("latitude", latitude)
.queryParam("longitude", longitude)
.queryParam("current", "temperature_2m,wind_speed_10m")
.queryParam("timezone", "auto")
.build())
.retrieve()
.bodyToMono(String.class)
.block();
return"当前位置(纬度:" + latitude + ",经度:" + longitude + ")的天气信息:\n" + response;
} catch (Exception e) {
return"获取天气信息失败:" + e.getMessage();
}
}
@Tool(description = "根据经纬度获取空气质量信息")
public String getAirQuality(
@ToolParameter(description = "纬度,例如:39.9042") String latitude,
@ToolParameter(description = "经度,例如:116.4074") String longitude) {
return"当前位置(纬度:" + latitude + ",经度:" + longitude + ")的空气质量:\n" +
"- PM2.5: 15 μg/m³ (优)\n" +
"- PM10: 28 μg/m³ (良)\n"