基于Spring Boot与MCP协议构建AI天气服务:从原理到实践
1. 项目概述:一个基于Spring Boot的天气服务MCP服务器
最近在折腾Cursor IDE的插件生态,发现Model Context Protocol(MCP)这个协议挺有意思的,它能让AI助手直接调用外部工具和服务。正好手头有个需求,想在做项目规划时,让AI能实时查询天气信息作为参考,比如判断某个地区的天气是否适合户外活动,或者评估天气对物流、活动安排的影响。于是,我决定动手实现一个MCP服务器,专门提供天气数据服务。
这个项目“Ahmed-Naseer-01/MCP-Server”就是一个现成的、开箱即用的解决方案。它是一个基于Spring Boot构建的天气服务,核心功能是通过MCP协议,将美国国家气象局(NWS)的API封装成AI助手可以调用的工具。简单来说,你把它跑起来,然后在Cursor IDE里配置好,你的AI助手(比如Claude)就能直接问你:“嘿,帮我查一下纽约明天的天气怎么样?”或者“加州现在有恶劣天气警报吗?”,并得到结构化的回答。
这个项目非常适合Java开发者,尤其是那些已经在用Spring Boot生态,并且对AI集成、智能IDE插件开发感兴趣的同行。它清晰地展示了如何将一个传统的REST API服务(这里是天气查询)适配到MCP协议下,为AI工作流提供实时数据支持。即使你暂时不用Cursor,理解其MCP服务器的实现方式,对理解未来AI与开发工具深度集成的趋势也大有裨益。接下来,我就结合这个项目,深入拆解一下MCP服务器的构建思路、核心实现细节,并分享一些在配置和调试过程中积累的实操心得。
2. 核心架构与MCP协议解析
2.1 为什么选择MCP与Spring Boot的组合
在开始动手之前,我们先聊聊技术选型。这个项目选择了Spring Boot作为基础框架,并用它来实现MCP服务器,这是一个非常务实且高效的选择。
首先,MCP(Model Context Protocol)本质上是一个标准化协议,它定义了AI模型(如大语言模型)与外部工具、数据源之间进行安全、结构化通信的规范。你可以把它想象成AI世界的“USB协议”——它为各式各样的“外设”(工具)提供了一个统一的插口(协议),让AI这个“主机”能够即插即用。对于开发者而言,实现一个MCP服务器,就是创建一个符合该协议规范的、能被AI模型调用的后端服务。
那么,为什么用Spring Boot呢?原因有三点。第一,快速启动。Spring Boot的“约定大于配置”理念和丰富的Starter依赖,能让我们在几分钟内就搭建起一个具备Web服务、依赖注入、配置管理等能力的基础项目骨架,把精力集中在业务逻辑(天气查询)和协议适配(MCP)上。第二,生态成熟。Spring生态拥有海量的库和良好的社区支持,无论是集成HTTP客户端去调用NWS API,还是处理JSON序列化、异常管理,都有现成、稳定的解决方案。第三,易于部署。Spring Boot应用可以打包成一个独立的JAR文件,通过简单的java -jar命令即可运行,这正好契合了MCP服务器通常以独立进程方式启动的需求。
这个项目的巧妙之处在于,它可能利用了spring-ai项目提供的MCP支持库。Spring AI是Spring官方为AI应用集成提供的一个项目,其中就包含了简化MCP服务器开发的模块。这比我们从零开始去解析MCP的Stdio(标准输入输出)通信、定义工具(Tool)的Schema要方便得多,相当于站在了巨人的肩膀上。
2.2 项目结构设计与依赖分析
一个典型的Spring Boot MCP服务器项目,其结构会非常清晰。虽然原项目README没有给出完整的目录树,但我们可以根据经验推断出其核心组成部分。
首先看依赖管理,pom.xml文件是关键。除了标准的spring-boot-starter-web(用于构建Web应用基础)和spring-boot-starter-test(测试)之外,核心依赖必然包含spring-ai-mcp或相关的MCP适配器starter。这个依赖会引入实现MCP服务器所需的所有底层库,包括处理JSON-RPC over stdio的通信模块、工具定义注解等。另一个关键依赖是用于调用外部天气API的HTTP客户端,可能是Spring自带的WebClient,也可能是RestTemplate,或者是更专业的如OpenFeign。为了解析NWS API返回的复杂JSON数据,像Jackson Databind这样的JSON处理库也是必不可少的。
项目的主要代码结构通常会如下组织:
- 主应用类(
WeatherMcpServerApplication.java): 包含标准的@SpringBootApplication注解和main方法,是应用的入口。 - 配置类(
McpServerConfig.java或WeatherServiceConfig.java): 这里会定义MCP服务器的Bean。如果使用Spring AI MCP,可能会有一个@Bean方法返回一个McpServer实例,并在这里注册具体的工具(Tool)。 - 服务层(
WeatherService.java): 这是业务逻辑的核心。它封装了调用美国国家气象局API的所有细节,包括构建请求URL、发送HTTP请求、解析响应数据、处理错误码和异常,并将原始的API数据转换为内部领域模型(DTO)。 - 工具层(
WeatherTools.java): 这一层是MCP协议适配层。它会定义AI可以调用的具体“工具”。每个工具通常对应一个Java方法,并使用特定的注解(如@Tool)进行标记。这些方法内部会调用上述的WeatherService。工具方法需要清晰地定义输入参数(如经纬度、州代码)和返回类型,这些信息会通过MCP协议暴露给AI。 - 数据传输对象(
WeatherForecast.java,Alert.java等): 一系列POJO类,用于在服务层、工具层之间传递结构化的天气和警报数据。它们的设计会尽量贴近NWS API的返回结构,同时做必要的简化和清理。 - 资源文件(
application.properties/application.yml): 存放配置项,例如NWS API的基础URL(虽然NWS API是公开免费的,无需密钥,但URL配置在此处更灵活)、服务器端口、日志级别等。
这种分层结构确保了关注点分离:服务层只关心如何获取天气数据,工具层只关心如何将数据能力暴露给MCP协议,而配置层则将它们组装起来。这样的设计使得代码易于测试、维护和扩展。
3. 核心功能实现细节拆解
3.1 天气数据获取与NWS API集成
这个项目的核心数据源是美国国家气象局(NWS)的API。这是一套完全免费、无需注册即可使用的公共服务,但它的数据结构和调用方式有其特点,需要仔细处理。
NWS API并非一个单一的端点,而是一组相互关联的RESTful接口。获取一个地点的天气预报,通常需要经过2到3次调用。这是一个典型的调用链:
- 根据经纬度获取网格点信息:首先,需要向
https://api.weather.gov/points/{latitude},{longitude}发送GET请求。这个接口不会直接返回天气,而是返回一个包含该坐标点所属气象局办公室(如OKX代表纽约)和网格坐标(如OKX/34,45)的JSON对象。这个网格坐标是后续所有请求的关键。 - 获取天气预报:使用上一步得到的网格坐标,向
https://api.weather.gov/gridpoints/{office}/{gridX},{gridY}/forecast发送请求。这个接口会返回未来7天分时段(白天、夜晚)的详细预报,包括温度、风速风向、天气状况描述、降水概率等。 - 获取天气警报(可选):警报信息通常按州或区域查询。可以向
https://api.weather.gov/alerts/active?area={STATE}发送请求,其中{STATE}是州的两个字母缩写(如CA、NY)。返回的数据包含警报的严重程度、标题、描述和有效时间。
在WeatherService的实现中,我们需要使用一个配置了超时和重试机制的HTTP客户端。因为NWS是公共服务,偶尔可能响应缓慢或暂时不可用。一个健壮的服务应该设置合理的连接超时(如5秒)和读取超时(如10秒),并考虑对非致命错误(如5xx服务器错误)进行有限次数的重试。
注意:NWS API要求在所有请求的
User-Agent头部中标识你的应用。这是一个强制性的礼貌性要求,如果缺失或使用默认值,请求会被拒绝。通常可以设置为你的应用名和联系方式,例如"MyWeatherApp (your-email@example.com)"。
解析API响应是另一个重点。NWS返回的JSON结构比较嵌套。例如,预报数据可能在properties.periods这个数组下,每个period对象里包含了temperature、windSpeed、shortForecast等字段。我们需要使用Jackson库的ObjectMapper,或者配合@JsonIgnoreProperties(ignoreUnknown = true)注解的DTO类,来安全地提取所需数据。务必处理字段可能缺失的情况,为DTO类的字段设置合理的默认值。
3.2 MCP工具的定义与暴露
这是项目最具特色的部分,即将天气查询能力包装成AI可调用的“工具”。如果使用Spring AI MCP,这个过程会大大简化。
首先,我们需要创建一个配置类,例如McpServerConfig,在其中定义一个@Bean方法来创建和配置MCP服务器。这个方法可能会接收一个List<Tool>作为参数,Spring AI MCP会自动扫描被@Tool注解标记的Bean,并将其收集到这个列表中。
然后,我们创建真正的工具类,例如WeatherTools。在这个类中,我们会定义具体的方法,并用@Tool注解进行标记。这个注解可以包含工具的name和description,这些信息对于AI理解工具的功能至关重要。
import org.springframework.ai.mcp.annotation.Tool; import org.springframework.stereotype.Component; @Component public class WeatherTools { private final WeatherService weatherService; // 构造器注入WeatherService public WeatherTools(WeatherService weatherService) { this.weatherService = weatherService; } @Tool(name = "get_weather_forecast", description = "获取指定经纬度位置的详细天气预报。") public WeatherForecast getForecast(@ToolParam(description = "纬度,例如 40.7128") double latitude, @ToolParam(description = "经度,例如 -74.0060") double longitude) { // 参数校验 if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) { throw new IllegalArgumentException("无效的经纬度坐标。"); } return weatherService.getForecast(latitude, longitude); } @Tool(name = "get_weather_alerts", description = "获取美国指定州的当前活跃天气警报。") public List<Alert> getAlerts(@ToolParam(description = "美国州的两个字母缩写,例如 CA, NY") String stateCode) { // 参数校验:简单的州代码格式检查 if (stateCode == null || !stateCode.matches("^[A-Z]{2}$")) { throw new IllegalArgumentException("州代码必须是两个大写字母。"); } return weatherService.getAlerts(stateCode); } }@ToolParam注解用于描述每个参数,这些描述会帮助AI更准确地理解如何提供参数。方法的返回类型WeatherForecast和List<Alert>也必须是结构清晰、可序列化为JSON的POJO类。Spring AI MCP框架会在底层处理所有协议通信的细节:它将标准输入(stdin)的JSON-RPC请求解析为对相应工具方法的调用,执行方法,再将返回的对象序列化为JSON-RPC响应,通过标准输出(stdout)写回。开发者只需要关注业务逻辑本身。
3.3 错误处理与健壮性设计
一个面向AI的服务,其错误处理必须格外友好和健壮。错误可能来自多个层面:
- 用户输入错误:如经纬度超出范围、州代码格式错误。这应该在工具方法的最开始进行校验,并立即抛出带有明确信息的异常(如
IllegalArgumentException)。 - 外部API错误:NWS API可能返回4xx(如位置不存在)、5xx错误,或者网络超时。在
WeatherService中,我们需要捕获这些异常,并将其转换为对用户(AI)更有意义的内部异常或错误消息。例如,将“404 Not Found”转换为“无法找到该坐标的天气信息,请确认坐标是否在美国境内。” - 业务逻辑错误:例如,解析NWS响应时发现数据格式不符合预期。
Spring AI MCP框架通常会提供一个全局异常处理机制,或者允许我们将工具方法抛出的异常转换为标准的JSON-RPC错误响应。我们需要确保错误响应的message字段是清晰、可读的,能够直接被AI理解并转述给最终用户。避免将堆栈跟踪或内部技术细节直接暴露出去。
此外,考虑到AI可能会连续、频繁地调用工具,在服务层面加入简单的限流或缓存机制也是提升健壮性的好方法。例如,可以对相同的经纬度查询结果缓存5-10分钟,以减少对NWS API的重复调用,提升响应速度。
4. 本地构建、配置与运行全流程
4.1 环境准备与项目构建
要运行这个项目,你的本地开发环境需要满足几个基本条件。首先是Java版本,项目要求Java 21或更高。我推荐使用SDKMAN!来管理多个Java版本,切换起来非常方便。如果你在macOS上,用brew install openjdk@21安装也很简单。安装后,记得在终端里用java -version确认一下。
构建工具是Maven,版本3.6以上。通常系统自带的或者从官网下载的都能用。项目里自带了mvnw(Maven Wrapper),这是个好东西,它能确保所有开发者使用完全一致的Maven版本进行构建,避免“在我机器上是好的”这类问题。所以,我们直接用它就好。
第一步是获取代码。打开终端,找一个合适的目录,执行克隆命令:
git clone https://github.com/Ahmed-Naseer-01/MCP-Server.git cd MCP-Server注意,根据原始README,克隆后需要进入的目录名是Weather-server,这可能意味着仓库根目录下有一个同名的子目录,或者README有笔误。如果cd MCP-Server后没看到pom.xml文件,就用ls命令查看一下,很可能会有一个Weather-server的文件夹,再cd进去即可。这是实操中会遇到的第一个小坑。
接下来设置Java环境变量。虽然系统可能已经设好了,但为了保险起见,可以按照README的提示设置(针对macOS):
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home在Linux或Windows的WSL上,路径会不同,例如可能是/usr/lib/jvm/java-21-openjdk。你可以用/usr/libexec/java_home -v 21(macOS)或update-alternatives --config java(Linux)来找到正确的路径。
最后,执行构建。使用项目自带的Wrapper,运行:
./mvnw clean package -DskipTests这个命令会清理旧构建、下载所有依赖、编译代码,并打包成一个可执行的JAR文件,-DskipTests参数跳过了测试以加快速度。打包成功后,你会在target/目录下找到名为Weather-server-0.0.1-SNAPSHOT.jar的文件(具体名字可能因项目配置略有不同)。记下这个JAR文件的完整路径,下一步配置会用到。
4.2 Cursor IDE的MCP服务器配置详解
这是让整个项目“活”起来的关键一步——将我们刚构建好的Spring Boot应用,注册为Cursor IDE的一个MCP服务器。Cursor的MCP配置统一放在一个JSON文件中。
首先,找到Cursor的配置目录。在macOS或Linux上,通常是用户主目录下的.cursor文件夹(~/.cursor)。在Windows上,可能是%USERPROFILE%\.cursor。如果这个文件夹不存在,就手动创建一个。
然后,在这个文件夹里,找到或创建mcp.json文件。根据README的指引,你也可以通过Cursor的设置界面进入:Settings -> MCP Tools,那里应该会有一个链接或按钮来打开或创建这个mcp.json文件。
接下来是核心的配置内容。你需要用文本编辑器打开mcp.json,并添加一个新的服务器配置。这里有一个非常重要的细节:配置的格式必须完全正确,尤其是路径。
{ "mcpServers": { "spring-ai-mcp-weather": { "command": "java", "args": [ "-Dspring.ai.mcp.server.stdio=true", "-jar", "/absolute/path/to/your/Weather-server/target/Weather-server-0.0.1-SNAPSHOT.jar" ] } } }让我详细解释一下每个部分:
"mcpServers": 这是一个对象,里面可以配置多个不同的MCP服务器。"spring-ai-mcp-weather": 这是你给这个天气服务器起的名字,可以自定义,但最好有辨识度。"command": "java": 这告诉Cursor,启动这个服务器需要执行java命令。"args": 这是传递给java命令的参数列表。"-Dspring.ai.mcp.server.stdio=true": 这是一个至关重要的系统属性。它告诉Spring AI MCP库,这个服务器将通过标准输入输出(stdio)与客户端(Cursor)通信,而不是HTTP或其他方式。缺少这个参数,服务器将无法以MCP模式启动。"-jar": 指定接下来要运行一个JAR包。- 最后一个参数是你本地JAR文件的绝对路径。你必须将
/path/to/your替换成真实的路径。例如,如果你的项目在/Users/yourname/Projects/MCP-Server/Weather-server,那么路径可能就是/Users/yourname/Projects/MCP-Server/Weather-server/target/Weather-server-0.0.1-SNAPSHOT.jar。
实操心得:路径与权限问题:
- 绝对路径:务必使用绝对路径。相对路径在Cursor的上下文中可能无法正确解析。
- 路径中的空格:如果路径中包含空格,在JSON中必须用反斜杠
\进行转义,或者将整个路径用双引号包起来作为单个参数(但这取决于JSON解析和命令执行的方式,最安全的方法是避免路径中有空格)。- 文件权限:确保JAR文件有可执行权限(在Unix系统上通常不是问题,因为
java -jar不依赖它本身的执行权限,但依赖读权限)。- Java可访问性:确保终端中
java命令可用的版本与JAVA_HOME设置一致。有时Cursor启动的环境可能与你的终端环境不同。一个检查方法是,在Cursor中打开内置终端,运行java -version看看是否是你期望的版本。
保存mcp.json文件后,需要重启Cursor IDE,以便它加载新的MCP配置。
4.3 服务器启动验证与功能测试
配置完成后,我们来验证服务器是否能正常工作。首先,我们需要手动启动一次服务器,以观察日志、排查问题。
打开一个终端,导航到你的项目目录,使用我们刚才在配置中写的一模一样的命令来启动JAR:
java -Dspring.ai.mcp.server.stdio=true -jar /absolute/path/to/your/Weather-server/target/Weather-server-0.0.1-SNAPSHOT.jar如果一切正常,你应该会看到Spring Boot那标志性的启动日志,最后一行通常是Started WeatherMcpServerApplication in X.XXX seconds (process running for X.XXX)。这表明你的Spring Boot应用已经以MCP服务器模式成功启动了。让它保持运行在这个终端窗口里。
接下来,测试MCP连接。由于这是一个Stdio服务器,我们需要模拟Cursor去连接它。一个简单的方法是使用nc(netcat) 或写一个小脚本,但更直接的方法是观察Cursor的行为。重启Cursor后,当你打开一个聊天窗口(与Claude等AI对话),理论上AI就应该能“看到”这个新工具了。
你可以尝试直接向AI提问:“查询一下纽约(经纬度大概40.7, -74.0)的天气。” 如果配置正确,AI应该会理解你的请求,并在后台调用get_weather_forecast工具。你可以在刚才运行服务器的终端里看到相应的日志输出,比如“Received request for tool: get_weather_forecast with params...”,以及调用NWS API的日志。如果AI返回了结构化的天气信息,那就大功告成了。
如果AI没有反应,或者报错说找不到工具,就需要排查:
- 检查Cursor日志:Cursor通常有开发者工具或日志输出。查看是否有加载
mcp.json成功的消息,或者连接服务器失败的错误信息。 - 检查服务器日志:查看你手动启动服务器的终端,是否有来自Cursor的连接请求?如果没有,说明Cursor根本没尝试连接,问题在配置;如果有连接但报错,问题在服务器端。
- 验证配置语法:确保
mcp.json是合法的JSON,没有缺少逗号或引号。 - 验证命令可执行:尝试在终端中,从Cursor的配置目录所在的环境(有时可能需要相同的用户环境)直接执行配置中的完整命令,看是否能启动服务器。
5. 进阶使用、问题排查与扩展思路
5.1 常见问题与排查技巧实录
在实际配置和运行过程中,你可能会遇到一些典型问题。下面我整理了一个速查表,涵盖了从配置到运行的常见坑点。
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| Cursor重启后,AI完全看不到新工具。 | 1.mcp.json文件路径错误或格式错误。2. Cursor未成功加载新配置。 | 1. 检查~/.cursor/mcp.json文件是否存在且内容正确。可使用在线JSON校验工具验证格式。2. 完全关闭Cursor(包括后台进程),再重新打开。查看Cursor的设置界面或日志确认MCP服务器列表。 |
| AI能看到工具,但调用时失败,返回“连接错误”或“服务器未响应”。 | 1. MCP服务器进程未启动。 2. mcp.json中的命令或路径错误。3. 端口冲突或权限问题(如果误配为网络模式)。 | 1. 在终端手动执行mcp.json中的完整命令,看服务器能否独立启动。2.重点检查 -Dspring.ai.mcp.server.stdio=true参数是否已添加。3. 检查JAR文件路径是否正确、是否存在。确保使用绝对路径。 |
| 服务器启动日志正常,但AI调用工具后,服务器终端报错(如ClassNotFound)。 | 项目依赖缺失或打包不完整。 | 1. 确保使用./mvnw clean package重新打包,不要跳过编译阶段。2. 检查是否使用了特殊的打包插件(如Spring Boot的 spring-boot-maven-plugin),它默认会打可执行JAR。 |
| 调用天气查询工具,返回“无效位置”或“无法获取数据”。 | 1. 输入的经纬度不在美国境内。 2. NWS API服务暂时不可用或返回错误。 3. 未设置合法的 User-Agent请求头。 | 1. 确认查询的坐标在美国本土、阿拉斯加、夏威夷或波多黎各等NWS覆盖区域。 2. 查看服务器日志中NWS API调用的详细错误信息。 3. 检查 WeatherService中HTTP客户端的配置,是否设置了合适的User-Agent。 |
服务器启动时报错:The following method did not exist或Bean creation error。 | Spring AI MCP或其他库的版本不兼容。 | 1. 检查pom.xml中spring-ai-mcp等依赖的版本,是否与Spring Boot主版本兼容。2. 尝试使用项目作者指定的、经过测试的依赖版本。查看项目源码或 pom.xml获取准确版本号。 |
| 工具调用成功,但AI返回的信息过于冗长或格式不佳。 | 工具方法返回的DTO对象结构过于复杂,或包含了AI不需要的字段。 | 1. 优化WeatherForecast等DTO类,只保留核心信息(如时间、温度、天气状况、风速)。2. 可以在工具方法内部对服务层返回的数据进行二次加工和简化,再返回给AI。 |
避坑技巧:日志级别调整。在开发调试阶段,将Spring Boot的日志级别调至
DEBUG或TRACE会非常有帮助。你可以在application.properties文件中添加logging.level.org.springframework.ai.mcp=DEBUG来查看MCP协议通信的细节,或者添加logging.level.com.yourpackage.WeatherService=DEBUG来查看详细的HTTP请求和响应。这能让你清晰地看到AI发送了什么请求,服务器又返回了什么。
5.2 项目局限性分析与应对策略
原README已经坦诚地列出了项目的几个主要限制,我们来深入分析一下这些限制意味着什么,以及可能的应对或扩展思路。
仅支持美国地理位置:这是由数据源NWS API决定的。NWS是美国联邦机构,其数据自然只覆盖美国及其领土。这对于美国本土的开发者或应用场景完全够用,但对于需要全球天气数据的项目,这就是一个根本性限制。
- 应对策略:如果需要全球覆盖,核心方案是更换数据源。你可以寻找其他提供全球天气数据的API,如OpenWeatherMap、WeatherAPI、AccuWeather等(它们通常有免费层级,但有限额)。这需要重写
WeatherService中调用API的部分,并处理新API的认证(API Key)、数据格式和费率限制。项目的架构优势在于,只要保持WeatherService的接口不变,更换底层数据源对上层的MCP工具层是透明的。
- 应对策略:如果需要全球覆盖,核心方案是更换数据源。你可以寻找其他提供全球天气数据的API,如OpenWeatherMap、WeatherAPI、AccuWeather等(它们通常有免费层级,但有限额)。这需要重写
警报仅限美国各州:同上,是数据源限制。NWS的警报接口是按州或区域代码查询的。
- 应对策略:如果使用全球数据源,通常也会有相应的天气警报接口,只是查询参数可能不再是州代码,而是国家、城市或经纬度范围。需要调整
getAlerts工具方法的参数和内部实现。
- 应对策略:如果使用全球数据源,通常也会有相应的天气警报接口,只是查询参数可能不再是州代码,而是国家、城市或经纬度范围。需要调整
温度单位仅为华氏度:NWS API默认返回华氏度。这对于习惯摄氏度的用户不友好。
- 应对策略:这是一个非常容易实现的增强点。你可以在
WeatherService或工具方法中,增加一个可选的单位参数。例如,将工具方法修改为getForecast(double lat, double lon, String unit),其中unit可以是"F"或"C"。在获取到原始数据后,如果用户请求摄氏度,就进行换算:C = (F - 32) * 5/9。这样既保留了原始数据精度,又提供了用户友好的选项。
- 应对策略:这是一个非常容易实现的增强点。你可以在
功能相对基础:目前只有预报和警报查询。
- 扩展思路:基于MCP协议的可扩展性,你可以轻松添加更多工具。例如:
get_current_weather: 获取实时天气,而非预报。get_air_quality: 集成空气质量指数(AQI)查询。get_weather_history: 查询历史天气数据(需要支持该功能的数据源)。get_location_by_city: 通过城市名搜索经纬度,作为其他工具的前置步骤。
- 扩展思路:基于MCP协议的可扩展性,你可以轻松添加更多工具。例如:
5.3 扩展与定制化开发指南
如果你不满足于只是一个天气查询服务器,想以此项目为模板,开发其他类型的MCP服务器,以下是清晰的扩展路径。
第一步:定义你的核心服务想清楚你要为AI提供什么能力?是股票查询、数据库操作、项目管理工具集成,还是内部系统接口?然后,像本项目的WeatherService一样,创建一个独立的服务类,封装所有与外部系统交互的复杂逻辑。这个类应该职责单一,易于测试。
第二步:设计MCP工具根据AI的使用场景,设计工具方法。思考AI会如何提问,以及你需要哪些参数。例如,一个股票查询工具可能需要symbol(股票代码)和interval(时间间隔)参数。使用@Tool注解清晰地定义它们。
第三步:处理认证与安全许多外部API需要认证(API Key, OAuth等)。切勿将密钥硬编码在代码中!应该使用Spring Boot的配置机制(@Value注解或@ConfigurationProperties),从环境变量或配置文件中读取敏感信息。例如,在application.yml中配置:
myapi: key: ${MY_API_KEY:}然后在代码中注入@Value("${myapi.key}")。启动时通过环境变量MY_API_KEY传入。
第四步:优化AI交互体验为了让AI更好地使用你的工具,工具方法和返回值的设计至关重要。
- 工具描述:
@Tool注解中的description要尽可能详细、自然,说明工具的功能、适用场景和参数含义。 - 参数描述:
@ToolParam的description要明确参数格式,例如“股票代码,例如 AAPL, GOOGL”。 - 返回值设计:返回的DTO对象应该结构扁平、字段名语义清晰。避免过深的嵌套和AI无法理解的内部编码。可以考虑重写
toString()方法或提供一个getSummary()方法,返回一段给AI阅读的自然语言摘要。
第五步:打包与分发当你完成开发后,可以将其打包,分享给团队其他成员。他们只需要有Java运行环境,以及一份正确的mcp.json配置,就能在他们的Cursor中使用你的工具了。你甚至可以将其部署到一台内部服务器上,让mcp.json中的command指向一个远程脚本或服务,实现团队共享。
这个基于Spring Boot和Spring AI MCP的模式,为我们提供了一个强大的样板。它清晰地分离了协议适配、业务逻辑和外部集成,使得为AI助手开发专用工具变得模块化和高效。无论你是想集成内部系统,还是连接公共API,这个框架都能提供一个坚实的起点。
