MCP 案例-Stdio传输模式
在该案例中,我们会创建MCP Server 和MCP Client 两个SpringBoot项目,MCP Server项目中会创建一个getWeather工具,该工具通过OpenWeather可以查询某个城市天气情况;MCP Client 项目中创建相应的Controller,根据配置通过STDIO 方式与MCP Server进行通信,实现调用天气工具。
Mcp Server开发


- 在项目中加入如下Maven依赖
java
```
<?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>

- 创建 WeatherService.java构建查询天气工具
在项目中创建service包,在该包中创建WeatherService.java类,构建查询天气工具:
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及相关依赖即可。
- 创建SpringBoot项目
SpringBoot项目命名为SpringAIMCPStdioClient,设置使用的JDK为17版本。


- 在项目中加入如下Maven依赖
html
<?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>



