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. 循环继续或结束会话

数据传递的过程上就是

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请加关注,联系我。

公————地藏思维

### DeepSeekMCP集成概述 DeepSeek作为一种先进的大型语言模型,在处理特定类型的复杂任务上表现出色,而MCP(Multi-Agent Collaboration Protocol)则提供了一种有效的机制来协调多个智能体之间的协作。当两者结合时,可以创建强大的自动化解决方案。 对于代码编写类的任务,倾向于采用DeepSeek作为底层支持引擎;而对于自然语言处理或者文案创作,则更偏向于使用Claude这样的预训练模型[^4]。这种灵活性使得开发者可以根据具体应用场景的需求灵活调整配置方案。 #### 集成指南 为了实现两者的无缝对接,通常会遵循以下几个原则: - **定义清晰的角色分工**:确保每个组件都有明确的功能定位。例如,通过TaskPlanner规划具体的子任务,并由ToolExecutor负责实际执行这些指令。 - **利用MCP协议促进交流**:借助该协议所提供的标准化接口,不同类型的代理之间能够高效沟通,共享必要的上下文信息。 - **实施严格的验证流程**:最后一步总是要经过ResultValidator的严格审查,以确认最终产出的质量达到预期标准。 ```python def integrate_deepseek_mcp(task): """ 将DeepSeek融入到MCP框架下的示例函数 参数: task (str): 待完成的工作描述 返回: dict: 经过验证后的结果报告 """ from deepseek import CodeGenerator, TextWriter # 导入所需的工具包 planner = TaskPlanner(task) if 'code' in planner.task_type.lower(): executor = CodeGenerator(planner.subtasks) # 对于编程相关任务启用CodeGenerator elif 'text' in planner.task_type.lower(): executor = TextWriter(planner.subtasks) # 文本生成场景下选择TextWriter else: raise ValueError('Unsupported task type') validator = ResultValidator(executor.execute()) # 获取并检验输出成果 return validator.get_final_report() ``` 此段代码展示了如何根据不同任务性质自动匹配合适的处理器实例,并且在整个过程中保持与其他参与方的良好互动关系。 #### 实际应用案例 一个典型的例子是在招聘环节中运用上述技术组合来进行候选人简历初筛工作。整个过程大致如下所示: 1. 接收HR部门提交的一批求职者资料; 2. 启动main_agent()启动程序,它内部包含了planner、executor和validator三个主要角色; 3. 根据职位要求设定筛选条件,比如技能标签匹配度计算等; 4. 输出一份详尽的人选推荐列表供进一步审核参考。 这种方法不仅提高了工作效率,还减少了人为因素带来的偏差可能性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值