Spring AI MCP案例
MCP 案例-Stdio传输模式
在该案例中,我们会创建MCP Server 和MCP Client 两个SpringBoot项目,MCP Server项目中会创建一个getWeather工具,该工具通过OpenWeather可以查询某个城市天气情况;MCP Client 项目中创建相应的Controller,根据配置通过STDIO 方式与MCP Server进行通信,实现调用天气工具。
Mcp Server开发
2) 在项目中加入如下Maven依赖
``` <?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>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.5.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>SpringAIMCPStdioServer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringAIMCPStdioServer</name> <description>SpringAIMCPStdioServer</description> <properties> <java.version>17</java.version> </properties> <!-- 导入 Spring AI BOM,用于统一管理 Spring AI 依赖的版本, 引用每个 Spring AI 模块时不用再写 <version>,只要依赖什么模块 Mavens 自动使用 BOM 推荐的版本 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.0.0-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 依赖的MCP 包 ,只支持 STDIO 传输--> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server</artifactId> </dependency> <!-- 依赖的json 包--> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20210307</version> </dependency> </dependencies> <!-- 打包插件 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>3.4.4</version> <configuration> <mainClass>com.example.springaimcpstdioserver.SpringAimcpStdioServerApplication</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <!-- 声明仓库, 用于获取 Spring AI 以及相关预发布版本--> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases> <enabled>false</enabled> </releases> </repository> <repository> <name>Central Portal Snapshots</name> <id>central-portal-snapshots</id> <url>https://central.sonatype.com/repository/maven-snapshots/</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> </project>4) 创建 WeatherService.java构建查询天气工具
在项目中创建service包,在该包中创建WeatherService.java类,构建查询天气工具:
package com.example.springaimcpstdioserver.service; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import org.json.JSONArray; import org.json.JSONObject; import org.springframework.ai.tool.annotation.Tool; import org.springframework.ai.tool.annotation.ToolParam; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 天气服务类,用于获取指定城市的天气信息 * @Service 标记为 Spring 服务层组件 */ @Service public class WeatherService { private static final Logger logger = LoggerFactory.getLogger(WeatherService.class); private static final String BASE_URL = "http://api.openweathermap.org/data/2.5/weather"; @Value("${OPEN_WEATHER_API_KEY}") private String OPEN_WEATHER_API_KEY; /** * 根据城市名称获取天气信息(使用 OpenWeatherMap) * @param city 城市名称,如 "Beijing" * @return 天气信息文本 */ @Tool(description = "获取指定城市的当前天气情况,格式化后的天气报告字符串。") public String getWeather(@ToolParam(description = "城市名称,必须是英文格式,比如 London 或 Beijing") String city) { logger.info("====== 调用了getWeather工具 ======"); try { String charset = "UTF-8"; String query = String.format( "q=%s&appid=%s&units=metric&lang=zh_cn", URLEncoder.encode(city, charset), URLEncoder.encode(OPEN_WEATHER_API_KEY, charset) ); URL url = new URL(BASE_URL + "?" + query); logger.info("====== 访问URL: ======"+url.toString()); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), charset)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); JSONObject data = new JSONObject(response.toString()); if (data.getInt("cod") == 404) { return "未找到该城市的天气信息。"; } JSONObject main = data.getJSONObject("main"); JSONArray weatherArray = data.getJSONArray("weather"); JSONObject weather = weatherArray.getJSONObject(0); JSONObject wind = data.getJSONObject("wind"); String weatherDescription = weather.optString("description", "无描述"); double temperature = main.optDouble("temp", Double.NaN); double feelsLike = main.optDouble("feels_like", Double.NaN); double tempMin = main.optDouble("temp_min", Double.NaN); double tempMax = main.optDouble("temp_max", Double.NaN); int pressure = main.optInt("pressure", 0); int humidity = main.optInt("humidity", 0); double windSpeed = wind.optDouble("speed", Double.NaN); return String.format(""" 城市: %s 天气描述: %s 当前温度: %.1f°C 体感温度: %.1f°C 最低温度: %.1f°C 最高温度: %.1f°C 气压: %d hPa 湿度: %d%% 风速: %.1f m/s """, data.optString("name", city), weatherDescription, temperature, feelsLike, tempMin, tempMax, pressure, humidity, windSpeed ); } catch (Exception e) { return "获取天气信息时出错: " + e.getMessage(); } } public static void main(String[] args) { //测试方法 WeatherService client = new WeatherService(); String beijing = client.getWeather("Beijing"); System.out.println(beijing); } }Mcp Client 开发
按照如下步骤创建MCP Client的SpringBoot项目。该MCP Client 项目中可以使用不同的LLM模型,只需要在对应配置文件中引入不同的模型对应的apikey及相关依赖即可。
1) 创建SpringBoot项目
SpringBoot项目命名为SpringAIMCPStdioClient,设置使用的JDK为17版本。
2) 在项目中加入如下Maven依赖
<?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>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.5.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>SpringAIMCPStdioClient</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringAIMCPStdioClient</name> <description>SpringAIMCPStdioClient</description> <properties> <java.version>17</java.version> </properties> <!-- 导入 Spring AI BOM,用于统一管理 Spring AI 依赖的版本, 引用每个 Spring AI 模块时不用再写 <version>,只要依赖什么模块 Mavens 自动使用 BOM 推荐的版本 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.0.0-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 基于 STDIO 传输客户端依赖 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-client</artifactId> </dependency> <!-- DeepSeek 模型依赖 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-deepseek</artifactId> </dependency> </dependencies> <!-- 声明仓库, 用于获取 Spring AI 以及相关预发布版本--> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases> <enabled>false</enabled> </releases> </repository> <repository> <name>Central Portal Snapshots</name> <id>central-portal-snapshots</id> <url>https://central.sonatype.com/repository/maven-snapshots/</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> </project>