系列篇章💥
目录
前言
在上一篇文章中,我们学习了如何使用 Spring AI 集成 Model Context Protocol (MCP),并通过 SQLite 数据库实现自然语言数据库交互。
本文将继续深入实践,介绍如何开发自己的MCP服务
,将 天气服务 封装为 LLM 可调用的工具,从而实现:
- 使用自然语言查询指定地区的天气预报
- 获取特定州的天气警报信息
- 构建图文并茂的天气报告
- 支持 SSE 和 STDIO 两种传输方式
我们将基于 spring-ai-mcp-weather-server
示例项目,演示完整的部署流程、核心代码解析以及实际应用场景,并提供可复用的服务端开发经验。
一、开发环境准备
(一)Java 版本要求
本项目采用Java 17进行编译和运行,请务必确保你的开发环境已成功安装JDK 17。你可以在命令行中输入以下命令进行检查:
java -version
输出应类似如下内容:
openjdk version "17.0.8" 2023-07-18
OpenJDK Runtime Environment (build 17.0.8+7)
OpenJDK 64-Bit Server VM (build 17.0.8+7, mixed mode, sharing)
(二)Maven 构建工具
确保你已安装 Maven 并配置好环境变量:
mvn -v
输出应类似如下内容:
Apache Maven 3.8.8 (4c87b05d9aedce574290d1acc98575ed5eb6cd39)
Maven home: D:\Program Files (x86)\apache-maven-3.8.8
Java version: 17.0.12, vendor: Oracle Corporation, runtime: D:\Program Files\jdk-17.0.12
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
(三)OpenAI API 密钥
你需要注册 OpenAI 官网 获取 API Key(国内可以直接使用中转地址),并设置为环境变量:
export OPENAI_API_KEY="your_openai_api_key"
export OPENAI_API_URL="https://api.openai.com/v1"
注意:出于安全考虑,不建议将密钥硬编码在代码中,推荐使用环境变量或配置中心进行管理。
(四)Node.js 和 npx 命令
MCP 客户端默认通过 npx
启动 Brave Search 服务,因此需要安装 Node.js 并配置 npm
和 npx
:
访问:https://nodejs.org 下载Node.js ,安装node 时注意勾选npm ;配置环境变量。
npx 是 npm 自带的工具,用于快速执行包中的命令。安装完成后,npx 也会自动可用。
检查版本信息:
node -v
npm -v
npx -v
配置 npm 全局模块路径(可选)
打开安装目录,新建两个文件夹:node_global 和 node_cache。
以管理员身份打开命令提示符,输入以下命令(将路径替换为你创建的文件夹路径):
npm config set prefix “你的路径\node_global”
npm config set cache “你的路径\node_cache”
(五)安装uvx 命令
MCP 客户端默认通过 uvx
启动 SQLite 服务,因此需要安装 Python 的 uv
包管理器:
pip install uv
验证是否安装成功:
uv --version
二、Maven 依赖配置
(一)MCP服务端依赖配置
你需要添加如下依赖以启用 MCP 服务端功能:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
</dependency>
该依赖提供了:
- 基于 HTTP 的传输(SSE)
- 自动配置的 MCP 端点
- 支持 STDIO 模式
- 包含
@Tool
注解支持与自动注册机制
(二)SpringAI相关依赖包版本管理
版本管理
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
部分通过引入spring-ai-bom,实现了对SpringAI相关依赖包版本的统一管理。这样,在项目中使用Spring AI相关依赖时,无需在每个依赖声明中单独指定版本号,只需遵循spring-ai-bom中定义的版本即可,极大地简化了依赖管理工作,同时确保了项目中依赖版本的一致性和稳定性。
三、Properties配置文件
server.port=8080
# spring.main.web-application-type=none
# 请注意:为了使STDIO传输正常工作,必须禁用横幅和控制台日志记录!
spring.main.banner-mode=off
# logging.pattern.console=
# spring.ai.mcp.server.stdio=false
# MCP服务名称、版本配置
spring.ai.mcp.server.name=my-mcp-weather-server
spring.ai.mcp.server.version=0.0.1
logging.file.name=./spring-ai-mcp-cookbook/spring-ai-mcp-weather-server/target/spring-ai-mcp-weather-server.log
四、MCP服务端代码解析:
(一)启动类:[Application.java]
使用 MethodToolCallbackProvider 构建器将 WeatherService 注册为一个工具对象,这样它就可以通过 Spring AI 的工具调用机制被调用。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService){
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
}
}
(二)服务工具类封装[WeatherService.java]
该类是核心业务逻辑所在,使用 @Tool
注解将方法注册为 LLM 可调用函数。
@Service
public class WeatherService {
private final RestClient restClient;
public WeatherService() {
this.restClient = RestClient.builder()
.baseUrl("https://api.weather.gov")
.defaultHeader("Accept", "application/geo+json")
.defaultHeader("User-Agent", "WeatherApiClient/1.0 (your@email.com)")
.build();
}
@Tool(description = "Get weather forecast for a specific latitude/longitude")
public String getWeatherForecastByLocation(double latitude, double longitude) {
var points = restClient.get()
.uri("/points/{latitude},{longitude}", latitude, longitude)
.retrieve()
.body(Points.class);
var forecast = restClient.get().uri(points.properties().forecast()).retrieve().body(Forecast.class);
return formatForecast(forecast);
}
@Tool(description = "Get weather alerts for a US state. Input is Two-letter US state code (e.g., CA, NY)")
public String getAlerts(String state) {
Alert alert = restClient.get().uri("/alerts/active/area/{state}", state).retrieve().body(Alert.class);
return formatAlert(alert);
}
}
✅ 核心能力说明:
方法 | 描述 |
---|---|
getWeatherForecastByLocation() | 根据经纬度获取天气预报 |
getAlerts() | 获取某个地方的天气警报信息 |
✅ 技术要点:
- 使用
RestClient
发起 HTTP 请求; - JSON 解析使用 Jackson 的
@JsonProperty
; - 工具方法使用
@Tool
注解注册; - 结果格式化返回自然语言描述。
五、工具注册与 MCP 服务启动
(一)工具注册机制
通过 MethodToolCallbackProvider
将 WeatherService
注册为可用工具:
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
}
Spring AI 会自动扫描所有带有 @Tool
注解的方法,并将其注册为 MCP 工具。
(二)启动 MCP 服务
你可以采用以下方式或者直接在idea启动运行,启动一个MCP服务:
java -jar target/spring-ai-mcp-weather-server-0.0.1-SNAPSHOT.jar
服务将在 http://localhost:8080
启动,支持 SSE 推送。
如果需要调整配置参数可参考:
java -Dspring.ai.mcp.server.stdio=true \
-Dspring.main.web-application-type=none \
-jar target/spring-ai-mcp-weather-server-0.0.1-SNAPSHOT.jar
六、MCP客户端:[spring-ai-mcp-weather-client]
(一)核心代码解析
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
/**
* 注入用户输入的提示内容。
* 通过 application.yml 配置文件中的 ai.user.input 属性设置。
*/
@Value("${ai.user.input}")
private String userInput;
/**
* 定义一个 CommandLineRunner Bean,用于在应用启动后执行预定义的提问逻辑。
*
* @param chatClientBuilder ChatClient 构建器,用于创建聊天客户端实例
* @param tools 工具回调提供者,用于注册和调用工具函数
* @param context Spring 应用上下文,用于管理 Bean 生命周期
* @return CommandLineRunner 返回一个可执行的命令行任务
*/
@Bean
public CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder, ToolCallbackProvider tools,
ConfigurableApplicationContext context) {
return args -> {
// 创建 ChatClient 实例,设置默认的工具回调
var chatClient = chatClientBuilder
.defaultToolCallbacks(tools)
.build();
// 输出当前的问题
System.out.println("\n>>> QUESTION: " + userInput);
// 发送问题给 AI 模型并获取回答
System.out.println("\n>>> ASSISTANT: " + chatClient.prompt(userInput).call().content());
// 关闭 Spring 应用上下文
context.close();
};
}
}
(二)客户端配置
# 设置应用程序的启动端口
server.port=8001
# 设置 Spring 应用程序的名称
spring.application.name=mcp
# 指定应用程序不启动 Web 容器(非 Web 应用)
spring.main.web-application-type=none
# 配置 OpenAI 的 API 密钥和基础 URL
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.base-url=${OPENAI_API_URL}
# MCP 客户端传输模式配置:
# 使用 stdio 传输模式(默认禁用,需要时取消注释)
# spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
# 使用 SSE (Server-Sent Events) 传输模式(启用并连接本地 MCP 天气服务)
spring.ai.mcp.client.sse.connections.my-mcp-weather-server.url=http://localhost:8080
# 日志级别设置为 WARN,减少不必要的调试信息输出
logging.level.io.modelcontextprotocol.client=WARN
logging.level.io.modelcontextprotocol.spec=WARN
# 用户输入的提示内容(用于 CommandLineRunner 示例)
ai.user.input=What tools are available?
# 启用 MCP 工具回调功能(确保客户端能正确注册工具)
spring.ai.mcp.client.toolcallback.enabled=true
(三)调用MCP服务(STDIO传输)
1. 创建 [mcp-servers-config.json]
{
"mcpServers": {
"my-mcp-weather-server": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dspring.main.web-application-type=none",
"-Dlogging.pattern.console=",
"-jar",
"/absolute/path/to/spring-ai-mcp-weather-server-0.0.1-SNAPSHOT.jar"
]
}
}
}
2. 使用 STDIO 传输启动客户端
在spring-ai-mcp-weather-client的properties中,使用 STDIO 传输启动客户端:
# MCP 客户端传输模式配置:
# 使用 stdio 传输模式(默认禁用,需要时取消注释)
spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
# 使用 SSE (Server-Sent Events) 传输模式(启用并连接本地 MCP 天气服务)
# spring.ai.mcp.client.sse.connections.my-mcp-weather-server.url=http://localhost:8080
3. 启动客户端程序:spring-ai-mcp-weather-client
使用命令:java -jar spring-ai-mcp-weather-client-0.0.1-SNAPSHOT.jar
启动客户端后,将看到以下输出:
(四)调用MCP服务(SSE传输)
1. 启动 spring-ai-mcp-weather-server
:
java -jar spring-ai-mcp-weather-server-0.0.1-SNAPSHOT.jar
该命令将在 8080 端口启动 MCP 服务器。
2. 使用 SSE 传输启动客户端
在spring-ai-mcp-weather-client的properties中,使用 SSE 传输启动客户端:
# MCP 客户端传输模式配置:
# 使用 stdio 传输模式(默认禁用,需要时取消注释)
# spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
# 使用 SSE (Server-Sent Events) 传输模式(启用并连接本地 MCP 天气服务)
spring.ai.mcp.client.sse.connections.my-mcp-weather-server.url=http://localhost:8080
3. 启动客户端程序:spring-ai-mcp-weather-client
使用命令:java -jar spring-ai-mcp-weather-client-0.0.1-SNAPSHOT.jar
启动客户端后,将看到以下输出:
(五)服务提问测试
调整问题参数,启动客户端:
java -Dai.user.input='纽约的天气怎么样?' -jar spring-ai-mcp-weather-client-0.0.1-SNAPSHOT.jar
控制台输出:
>>> QUESTION: '纽约的天气怎么样?'
>>> ASSISTANT: 纽约的天气预报如下:
**今晚:**
- 温度:62°F (约16°C)
- 风速:7 mph (约11 km/h) 东风
- 预报:有降雨的可能,天气多云,最低温度约62°F。降水概率为50%。
**星期一:**
- 温度:68°F (约20°C)
- 风速:8 mph (约13 km/h) 东风
- 预报:有轻微降雨的可能,天气多云,最高温度约68°F,下午气温会降至约66°F。降水概率为20%。
**星期一晚上:**
- 温度:64°F (约18°C)
- 风速:5到8 mph (约8到13 km/h) 东风
- 预报:有轻微降雨的可能,天气多云,最低温度约64°F。降水概率为20%。
**星期二:**
- 温度:69°F (约21°C)
- 风速:6到9 mph (约10到14 km/h) 东风
- 预报:早上8点前有轻微降雨的可能,然后可能有小雨,天气多云,最高温度约69°F。降水概率为20%。
**星期二晚上:**
- 温度:67°F (约19°C)
- 风速:6到9 mph (约10到14 km/h) 东南风
- 预报:可能有降雨,天气多云,最低温度约67°F。降水概率为60%。可能的新降水量在四分之一到半英寸之间。
**星期三:**
- 温度:81°F (约27°C)
- 风速:5到8 mph (约8到13 km/h) 南风
- 预报:上午11点前可能有降雨,然后可能有小雨和雷暴,天气部分晴朗,最高温度约81°F。降水概率为60%。可能的新降水量在十分之一到四分之一英寸之间。
**星期三晚上:**
- 温度:73°F (约23°C)
- 风速:8 mph (约13 km/h) 西南风
- 预报:晚上8点前可能有降雨和雷暴,天气部分多云,最低温度约73°F。降水概率为30%。
**星期四:**
- 温度:87°F (约31°C)
- 风速:7到15 mph (约11到24 km/h) 西南风
- 预报:下午2点后可能有降雨和雷暴,天气大部分晴朗,最高温度约87°F。降水概率为40%。
**星期四晚上:**
- 温度:72°F (约22°C)
- 风速:12到15 mph (约19到24 km/h) 西风
- 预报:凌晨2点前可能有降雨和雷暴,天气部分多云,最低温度约72°F。降水概率为40%。
**星期五:**
- 温度:80°F (约27°C)
- 风速:13 mph (约21 km/h) 西风
- 预报:天气晴朗,最高温度约80°F。
**星期五晚上:**
- 温度:67°F (约19°C)
- 风速:7到12 mph (约11到19 km/h) 西北风
- 预报:天气部分多云,最低温度约67°F。
**星期六:**
- 温度:81°F (约27°C)
- 风速:7到12 mph (约11到19 km/h) 西风
- 预报:天气晴朗,最高温度约81°F。
**星期六晚上:**
- 温度:72°F (约22°C)
- 风速:8到12 mph (约13到19 km/h) 西南风
- 预报:天气部分多云,最低温度约72°F。
**星期日:**
- 温度:84°F (约29°C)
- 风速:8到12 mph (约13到19 km/h) 西南风
- 预报:天气大部分晴朗,最高温度约84°F。
如果你需要更多信息,请告诉我!
通过控制台输出,我可以看到服务MCP服务调用成功,成功的返回了天气服务查询到的天气信息
七、结语
通过本文的实践,我们完成了 Spring AI 与 MCP 协议的集成,掌握了以下关键技能:
✅ 如何在 Spring Boot 中集成 MCP 服务端
✅ 如何将 RESTful 天气接口封装为 LLM 可调用工具
✅ 如何构建自然语言问答流程
✅ 如何调用 MCP 服务工具获取实时天气数据
✅ 完整部署与测试流程
这是 Spring AI 集成 MCP 协议的重要一步,后续我们将继续深入,介绍如何构建企业级 MCP 工具平台、支持多源搜索、动态工具注册等内容。
若您对本文介绍的技术内容感兴趣,希望进一步探索和实践,欢迎关注我,通过私信的方式与我联系,获取完整的项目代码
,开启您的 Spring AI 开发之旅。
🎯🔖更多专栏系列文章:AI大模型提示工程完全指南、AI大模型探索之路(零基础入门)、AI大模型预训练微调进阶、AI大模型开源精选实践、AI大模型RAG应用探索实践🔥🔥🔥 其他专栏可以查看博客主页📑
😎 作者介绍:资深程序老猿,从业10年+、互联网系统架构师,目前专注于AIGC的探索(CSDN博客之星|AIGC领域优质创作者)
📖专属社群:欢迎关注【小兵的AI视界】公众号或扫描下方👇二维码,回复‘入群’ 即刻上车,获取邀请链接。
💘领取三大专属福利:1️⃣免费赠送AI+编程📚500本,2️⃣AI技术教程副业资料1套,3️⃣DeepSeek资料教程1套🔥(限前500人)
如果文章内容对您有所触动,别忘了点赞、⭐关注,收藏!加入我们,一起携手同行AI的探索之旅,开启智能时代的大门!