前言
上一章节说到LLM(deepseek)可以对话,但是获取不到最新的数据。那如果想获取最新的数据怎么办?
那就要利用MCP协议的server,让LLM作为Client,知道某个MCP server提供哪些能力,然后结合这些能力来组织答案。
我觉得MCP是LLM里最实用的功能,你有没有想过,让LLM告诉你假期行程、理财实时数据并分析、券商实时数据?
这次将会使用spring ai结合MCP的方式来使用Chat对话。
一、什么是MCP?
MCP就是Model Context Protocol,相当于像HTTP的一个网络协议。用于服务和服务之间传输数据和通信。
就像大家的网页都通过http访问后端,那就是大家使用MCP协议,才可以跟LLM通信。
二、为什么要用MCP
场景:你问deepseek,弄一个广州三天两夜游行程,他需要知道未来几天的广州天气预报,广州几个几点的坐标,每个坐标之间距离,如何使用公交完成行程。但是这些实时或需要精确度问题,deepseek是不知道,他只知道广州的著名景点有哪些,因为这些在一年前的数据都能搜索出来。如何实现精确回答实时内容的问题呢,请看下文。
三、LLM怎么结合MCP
上述问题中,涉及多次访问外部拿数据,并依据结果给出最终回答的话,一般都是基于ReAct原理来做的。这里提到的ReAct就是所谓的智能体,英文文档里叫Agent
LLM处理的步骤如下:
- 思考Thought:即,如果要回答这个问题,首先要做什么
- 行动Act:根据问题调用工具,并记录工具的结果 就是Tool calling的过程。 (tool calling后面讲)。
- 观察Obs:是否能做出最终回答,如果不能,则回到第一步,如果能做出最终答复,回答问题
[workflow]
LLM结合MCP实现对话的工作流程
这个步骤在官网叫Function calling
- 初始化客户端
- 启动时,就要去连接到各个你配置好的MCP服务器
你现在就是图中,最左边的client,通过一个像http层面的协议跟外部通信。
以cursor举例,就像这里配置各个mcp服务器
- 获取可用工具列表
就像cursor,他会问各个mcp服务器“你们提供什么能力”,下面tool里的就是他们的能力。
-
接收用户输入,也就是对应上面图[workflow]的第一步
-
调用AI模型处理输入,ai model就会结合已有的工具,思考用哪些方法。如果用到方法了,就返回给客户端,告诉让客户端要调用mcp
-
执行必要的工具调用,这里就对应[workflow]的第三步,调用客户端
就像curosr会调用MCP。但cursor做得不是很好的地方,就是每次调用MCP都需要人为点一下按钮,不够自动化。
- 返回处理结果
- 循环继续或结束会话
数据传递的过程上就是
Request :
- messages:
- UserMessage:
- text: What is the square root of 475695037565?
- AiMessage:
- toolExecutionRequests:
- squareRoot(475695037565)
- ToolExecutionResultMessage:
- text: 689706.486532
Response :
- AiMessage:
- text: The square root of 475695037565 is 689706.486532.
四、现在就来用spring ai mcp client实现上面的需求
spring ai支持两种方式连接mcp server,一种是sse 事件流接口,一种是stdio标准io。
引入依赖
接着上一章,我是使用spring-ai-starter的框架,所以使用的是spring-ai-starter-model-deepseek,如果要看spring-ai-alibaba,我下一章节再讲。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
关键是这个spring-ai-starter-mcp-client要引入,代表能跟mcp server通信。
配置LLM模型内容
server:
port: 8081
spring:
application:
name: spring-ai-deepseek-chat-model-example
ai:
deepseek:
api-key: 你的key
base-url: "https://api.deepseek.com"
chat:
options:
model: deepseek-chat
embedding:
enabled: false
spring ai sse连接方式
我们以高德案例为例。
##spring: 接着上面的LLM配置填写
mcp:
client:
type: ASYNC
sse:
connections:
amap:
url: https://mcp.amap.com/sse
api-key: 你的key
这里就配置了高德MCP server,这里注意一个点,很多文章都已localhost:8080填在url上,就没有人演示如何使用公网的mcp server,连官网都没写好api-key要做为一个yml的key与url平级。搞得我之前一直把key填在url里,url: https://mcp.amap.com/sse?key=xxxx。 搞得我一直报403拒绝访问。
spring ai stdio连接方式
mcp:
client:
type: ASYNC
sse:
connections:
amap:
url: https://mcp.amap.com/sse
api-key: 你的key
stdio:
servers-configuration: classpath:/mcp-servers-config.json
你也可以同时配置stdio方式,因为市面上的MCP不一定只是sse方式连接。
有些会需要执行uv、python、npx命令的,所以需要stdio方式,还需要一个json文件配置,就像Cursor配置mcp一样。
{
"mcpServers": {
"filesystem": {
"command": "npx.cmd",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/kelvin/Desktop",
"C:/Users/kelvin/Desktop"
]
}
}
五、开始使用
该配置的已经配置好了,可以进行使用了
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
@Bean
public CommandLineRunner predefinedQuestions(
ChatClient.Builder chatClientBuilder,
ToolCallbackProvider tools,
ConfigurableApplicationContext context) {
return args -> {
// 构建ChatClient并注入MCP工具
ChatClient chatClient = chatClientBuilder
.defaultToolCallbacks(tools)
.build();
// 定义用户输入
String userInput = "有哪些工具可用";
// 打印问题
System.out.println("\n>>> QUESTION: " + userInput);
// 调用LLM并打印响应
System.out.println("\n>>> ASSISTANT: " +
chatClient.prompt(userInput).call().content());
// 关闭应用上下文
context.close();
};
}
}
问问有什么能力
可以先用这个userInput来访问有哪些工具,就像cursor一样,可以知道每个mcp server有哪些能力。
他就回复我各个工具的能力。
### 地图相关工具
1. **骑行路径规划**:规划骑行通勤方案。
2. **驾车路径规划**:规划驾车通勤方案。
3. **公交路径规划**:规划公共交通(火车、公交、地铁)通勤方案。
4. **步行路径规划**:规划步行通勤方案。
5. **距离测量**:测量两个经纬度坐标之间的距离(支持驾车、步行和直线距离)。
6. **地理编码**:将结构化地址转换为经纬度坐标。
7. **逆地理编码**:将经纬度坐标转换为行政区划地址信息。
8. **IP 定位**:根据 IP 地址定位位置。
9. **天气查询**:根据城市名称或 adcode 查询天气。
10. **POI 搜索**:
- **关键词搜索**:根据关键词搜索 POI。
- **周边搜索**:根据坐标和半径搜索 POI。
- **POI 详情查询**:查询 POI 的详细信息。
11. **地图展示**:
- **行程规划地图**:展示行程规划结果。
- **导航页面**:唤起导航页面。
- **打车页面**:唤起打车页面。
### GitHub 相关工具
1. **仓库管理**:
- 创建仓库。
- 搜索仓库。
- 获取仓库文件内容。
- 创建或更新文件。
- 推送多个文件。
- 创建分支。
- 列出提交记录。
2. **问题管理**:
- 创建、更新、列出问题。
- 添加问题评论。
3. **拉取请求管理**:
- 创建、合并拉取请求。
- 获取拉取请求详情。
- 列出拉取请求文件。
- 获取拉取请求状态。
4. **其他**:
- 搜索代码、用户、问题。
- 创建 Fork。
### 文件系统操作工具
1. **文件读写**:
- 读取单个或多个文件。
- 写入或编辑文件。
2. **目录操作**:
- 创建目录。
- 列出目录内容。
- 获取目录树。
- 移动或重命名文件。
3. **搜索与信息**:
- 搜索文件。
- 获取文件或目录的详细信息。
- 列出允许访问的目录。
如果需要了解某个工具的具体功能或使用方法,可以告诉我,我会为您提供详细说明!
下一步就是让他做事
把userInput 改为
String userInput = "##我五一计划去昆明游玩4天的旅行攻略。" +
"#帮制作旅行攻略,考虑出行时间和路线,以及天气状况路线规划。" +
"#制作网页地图自定义绘制旅游路线和位置。" +
"##网页使用简约美观页面风格,景区图片以卡片展示。" +
"#行程规划结果在高德地图app展示,并集成到h5页面中。" +
"##同一天行程景区之间我想打车前往。" +
"生成html格式的内容。让我人工保存到文件里。";
案例就如高德提到的样例一样: https://lbs.amap.com/api/mcp-server/application-case/travel-planning-case
回答得到
把html内容保存到电脑某个文件,改后缀叫html。打开,则看到高德示例的结果。有些不足的就是,deepseek拿到的图片可能是一年前的旧的连接,所以图片就打不开的了。
至此,你也可以利用deepseek和mcp client做些应用的功能了。
你也可以跟别人说,你跟高德合作过项目了。
六、开发MCP server
以后再来介绍mcp server。因为我觉得如果做一个项目,做应用层的话,可以利用已有的东西,快速做些实际效果,调用已存在的东西会比较快。
其次,没有什么场景需要我自己提供mcp server/http server,除非我是一个公众业务软件。
总结
做好了MCP功能,我们能实现Cusor这部分的功能了,所以说Cusor也是套壳项目,cursor不提供算法,提供基于LLM上层应用。
自己做了这个,哪里还需要20$一个月啊。距离完成自己的套壳项目,又进一步了。
下一章,讲spring-ai-alibaba
以后还会讲解ant-design-x做前端。
附
如果想知道还有哪些好用的MCP请加关注,联系我。
公————地藏思维
rver。因为我觉得如果做一个项目,做应用层的话,可以利用已有的东西,快速做些实际效果,调用已存在的东西会比较快。
其次,没有什么场景需要我自己提供mcp server/http server,除非我是一个公众业务软件。
总结
做好了MCP功能,我们能实现Cusor这部分的功能了,所以说Cusor也是套壳项目,cursor不提供算法,提供基于LLM上层应用。
自己做了这个,哪里还需要20$一个月啊。距离完成自己的套壳项目,又进一步了。
下一章,讲spring-ai-alibaba
以后还会讲解ant-design-x做前端。
附
如果想知道还有哪些好用的MCP请加关注,联系我。
公————地藏思维