【中】SpringAI入门搭建MCP
https://www.bilibili.com/video/BV1WYjgzbEcA
MCP已经火了很久,最近公司也在考虑用MCP来完成一些业务功能,借此机会来学习一下SpingAI的MCP。这块的学习和以往的有很大不同,以往我们总是更注重实践,AI相对来说是个新事物,且不确定,所以它的理论要强于实践。
一、如何开发一个自己的Agent
有这么一个需求,为客户推荐套餐
,用户在对话框中说出自己的需求,然后系统自动帮用户购买套餐,用户拿到支付链接,付款即可。(传统的做法是分多个步骤,用户一步步来,先选择类型、再选择具体的套餐、最后输入用户信息,等等,会有很多页面的跳转交互)
构建一个Agent,首先需要一个大模型,充当人工大脑,来提取用户输入的信息,比如用户输入:你好,我今年三十岁了,最近感觉眼角的鱼尾纹越来越多了,我好焦虑啊。大模型就应该提取出:女性、三十岁、眼部医美等这些关键词。
大模型是通用的,大概率是无法定制一个完全适合需求的模型,所以我们要给大模型一个角色定义,这就是写提示词(prompt)。 新的问题又来了,大模型是固定参数训练的,它并没有公司的内部数据,这时候就需要把公司的数据提供给大模型,这就是知识库(RAG)。
套餐的数据是维护在系统里面的,套餐的数据时时刻刻在变化(比如新增了套餐),当然可以把套餐的数据导入到知识库里面去,可这会不会太麻烦了?以往在获取最新数据的时候都是去查接口。以往的接口是叫 RestFul接口,AI的接口就叫 MCP接口。只要提供几个MCP接口(查询套餐、查询就诊人信息、创建支付链接等)
总结一下需要做的事情
- 找一个大模型,使用提示词给它定义角色
- 提供公司内部知识库,让AI具备个性化知识
- 提供MCP接口,让AI可以查询并下单套餐
存在的一些问题
- 大模型的对话是只有一次的,简单来说你先给它发个你好,再问一句:我上面说了什么,其实它是不知道的,但为什么在使用各种模型的时候发现它其实是有记忆功能的呢?对接过大模型API的都知道,每次请求都会把之前的对话数据一并传递过去,这样才让大模型看起来是有记忆功能。
- 知识库的建立也并不是用我们之前的那种关系型数据库,用的是向量数据库。
- 对接各种模型API也是个麻烦事
基于以上问题,虽然可以手动撸一个Agent,但那会做很多无用的工作,一般都是借助第三方平台,比如Dify,这样我们就只需要聚焦具体的工作
- 提示词的编写
- 知识库的整理
- MCP接口的提供
二、开发一个天气查询的MCP
https://api.open-meteo.com/v1
提供了免费的查询天气的API,这本来是一个Rest的API,通过SpringAI框架,就可以把这个包装成一个MCP。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.5</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-autoconfigure</artifactId>
<version>1.0.0-M6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp</artifactId>
<version>1.0.0-M6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-spring-webflux</artifactId>
<version>0.8.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
server:
port: 8082 # 服务器端口配置
spring:
ai:
mcp:
server:
name: my-weather-server # MCP服务器名称
sse-endpoint: /sse
sse-message-endpoint: /mcp/messages
type: ASYNC
version: 0.0.1 # 服务器版本号
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ToolCallbackProvider weatherTools(OpenMeteoService openMeteoService) {
return MethodToolCallbackProvider.builder()
.toolObjects(openMeteoService)
.build();
}
}
OpenMeteoService
其实就是按照MCP的规范定义接口
@Service
public class OpenMeteoService {
private final WebClient webClient;
public OpenMeteoService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder
.baseUrl("https://api.open-meteo.com/v1")
.build();
}
@Tool(description = "根据经纬度获取天气预报")
public String getWeatherForecastByLocation(
@ToolParam(description = "纬度,例如:39.9042") String latitude,
@ToolParam(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(
@ToolParam(description = "纬度,例如:39.9042") String latitude,
@ToolParam(description = "经度,例如:116.4074") String longitude) {
// 模拟数据,实际应用中应调用真实API
return "当前位置(纬度:" + latitude + ",经度:" + longitude + ")的空气质量:\n" +
"- PM2.5: 15 μg/m³ (优)\n" +
"- PM10: 28 μg/m³ (良)\n" +
"- 空气质量指数(AQI): 42 (优)\n" +
"- 主要污染物: 无";
}
}
三、调试MCP
如果把MCP对比成Rest的话,接口写完就要调试了:
- 使用 modelcontextprotocol 提供的 Inspector,相当于用postMan去调用接口,输入参数直接调用
- 使用AI大模型去调用,目前很多工具都支持MCP了,可以使用VsCode的CLINE,或Dify,或直接用SpringAI写一个客户端
注:Cursor也可以去调用MCP,但目前的Cursor的客户端规则问题,导致无法调用这个
3-1、使用 Inspector
Inspector的官网地址:https://modelcontextprotocol.io/docs/tools/inspector
直接执行下面的命令就好了
npx @modelcontextprotocol/inspector node build/index.js
3-2、使用 VsCode的CLINE
这个相当于在正式环境中了,使用AI来调用MCP

打开对话窗口,输入 查询天气 116.39852,39.938838