Spring Ai 从Demo到搭建套壳项目(二)实现deepseek+MCP client让高德生成昆明游玩4天攻略

前言

上一章节说到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处理的步骤如下:

  1. 思考Thought:即,如果要回答这个问题,首先要做什么
  2. 行动Act:根据问题调用工具,并记录工具的结果 就是Tool calling的过程。 (tool calling后面讲)。
  3. 观察Obs:是否能做出最终回答,如果不能,则回到第一步,如果能做出最终答复,回答问题

[workflow]

LLM结合MCP实现对话的工作流程

这个步骤在官网叫Function calling

  1. 初始化客户端
  2. 启动时,就要去连接到各个你配置好的MCP服务器

你现在就是图中,最左边的client,通过一个像http层面的协议跟外部通信。 以cursor举例,就像这里配置各个mcp服务器

  1. 获取可用工具列表

就像cursor,他会问各个mcp服务器"你们提供什么能力",下面tool里的就是他们的能力。

  1. 接收用户输入,也就是对应上面图[workflow]的第一步

  2. 调用AI模型处理输入,ai model就会结合已有的工具,思考用哪些方法。如果用到方法了,就返回给客户端,告诉让客户端要调用mcp

  3. 执行必要的工具调用,这里就对应[workflow]的第三步,调用客户端 就像curosr会调用MCP。但cursor做得不是很好的地方,就是每次调用MCP都需要人为点一下按钮,不够自动化。

  1. 返回处理结果
  2. 循环继续或结束会话

数据传递的过程上就是

yaml 复制代码
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,我下一章节再讲。

pom.xml 复制代码
<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模型内容

applicat.yml 复制代码
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连接方式

我们以高德案例为例。

yaml 复制代码
##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连接方式

yaml 复制代码
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一样。

perl 复制代码
{
  "mcpServers": {
    "filesystem": {
      "command": "npx.cmd",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "C:/Users/kelvin/Desktop",
        "C:/Users/kelvin/Desktop"
      ]
    }
}

五、开始使用

该配置的已经配置好了,可以进行使用了

typescript 复制代码
@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有哪些能力。 他就回复我各个工具的能力。

markdown 复制代码
### 地图相关工具
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 改为

java 复制代码
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请加关注,联系我。

公------------地藏思维

相关推荐
why技术2 分钟前
Stack Overflow,轰然倒下!
前端·人工智能·后端
幽络源小助理5 分钟前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
猴哥源码7 分钟前
基于Java+springboot 的车险理赔信息管理系统
java·spring boot
超龄超能程序猿1 小时前
(三)PS识别:基于噪声分析PS识别的技术实现
图像处理·人工智能·计算机视觉
要努力啊啊啊1 小时前
YOLOv3-SPP Auto-Anchor 聚类调试指南!
人工智能·深度学习·yolo·目标检测·目标跟踪·数据挖掘
好开心啊没烦恼1 小时前
Python 数据分析:numpy,说人话,说说数组维度。听故事学知识点怎么这么容易?
开发语言·人工智能·python·数据挖掘·数据分析·numpy
生态遥感监测笔记1 小时前
GEE利用已有土地利用数据选取样本点并进行分类
人工智能·算法·机器学习·分类·数据挖掘
ai小鬼头1 小时前
AIStarter如何助力用户与创作者?Stable Diffusion一键管理教程!
后端·架构·github
简佐义的博客1 小时前
破解非模式物种GO/KEGG注释难题
开发语言·数据库·后端·oracle·golang
天天扭码1 小时前
从图片到语音:我是如何用两大模型API打造沉浸式英语学习工具的
前端·人工智能·github