前言
上一章节说到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.486532Response :- 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: 8081spring: 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: mcp.amap.com/sse?key=xxx… 搞得我一直报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" ] }}
五、开始使用
该配置的已经配置好了,可以进行使用了
@SpringBootApplicationpublic 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格式的内容。让我人工保存到文件里。";
案例就如高德提到的样例一样: lbs.amap.com/api/mcp-ser…
回答得到
把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请加关注,联系我。
公————地藏思维