将 DeepSeek 集成到 Spring Boot 项目实现通过 AI 对话方式操作后台数据

news2025/4/21 17:55:47

文章目录

  • 项目简介
    • 本项目分两大模块
  • Gitee
  • MCP 简介
  • 环境要求
  • 项目代码
  • 核心实现代码
    • MCP 服务端
    • MCP 客户端
  • DeepSeek API
  • Docker
    • sse 连接
    • ws 连接(推荐)
    • http 连接
  • vue2-chat-window
  • Cherry Studio
    • 配置模型
    • 配置 MCP
    • 调用 MCP

项目简介

在本项目中,我们基于 Spring Boot 构建并通过 Docker 部署了 MCP 服务端与 MCP 客户端,通过 HTTP 协议 实现与现有系统的远程控制与集成。整个系统作为独立模块运行,服务端直接连接数据库,核心业务逻辑抽象于 tool 层中,具备良好的扩展性与解耦性。

为提升系统的实时交互能力,项目支持通过 Cherry Studio 使用 SSE(Server-Sent Events) 与 MCP 服务端保持长连接,实现消息的实时推送与指令响应。

此外,还新增了对 WebSocket 通信 的支持。相比于 HTTP 和 SSE,WebSocket 是一种 全双工、低延迟、连接持久 的通信协议,特别适用于高频次、强交互的控制场景。通过 WebSocket,客户端不仅可以实时获取状态更新,还可主动发送控制指令并立即获取响应,进一步增强了系统的交互性和用户体验。

本项目分两大模块

  • MCP 服务端:

    • 连接数据库
    • Tool 业务实现
  • MCP 客户端:

    • 连接 DeepSeek AI 模型
    • 连接 MCP 服务端加载 Tool 列表
    • 接收用户输入的提示词(问题)
    • DeepSeek 识别提示词(问题)意图
    • DeepSeek 在 Tool 列表中找到符合要求的 Tool 并调用 Tool
    • 接收 MCP 服务端 Tool 的业务处理结果
    • DeepSeek 分析结果并转换为 md 文档格式输出

Gitee

  • https://gitee.com/wufengsheng/spring-mcp-server

MCP 简介

MCP 是一种开放协议,用于标准化应用程序如何向 LLM 提供上下文。可以将 MCP 视为 AI 应用程序的 USB-C 端口。就像 USB-C 提供了一种将设备连接到各种外围设备和配件的标准化方式一样,MCP 提供了一种将 AI 模型连接到不同数据源和工具的标准化方式。
在这里插入图片描述

  • MCP 主机 (MCP Hosts):例如 Claude Desktop、IDE 或希望通过 MCP 访问数据的 AI 工具等程序
  • MCP 客户端 (MCP Clients):与服务器保持 1:1 连接的协议客户端
  • MCP 服务器 (MCP Servers):轻量级程序,每个程序通过标准化的模型上下文协议 (MCP) 公开特定的功能
  • 本地数据源 (Local Data Sources):您的计算机的文件、数据库和 MCP 服务器可以安全访问的服务
  • 远程服务 (Remote Services):可通过互联网访问的外部系统(例如,通过 API),MCP 服务器可以连接到这些系统

环境要求

  • Java 环境 >= JDK17
  • Spring Boot >= 3.x

在这里插入图片描述

项目代码

git clone https://gitee.com/wufengsheng/spring-mcp-server.git

注: Java 开发环境必须 >= JDK17,否则项目编译不过。

在这里插入图片描述

核心实现代码

  • MCP 依赖 jar 包
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-M7</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
	<!-- mcp 服务端引入 -->
	<dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
    </dependency>

	<!-- mcp 客户端引入 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-mcp-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
    ...
</dependencies>

MCP 服务端

  • ToolCallbackProviderConfig.java
import lombok.AllArgsConstructor;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

@Configuration
@AllArgsConstructor
public class ToolCallbackProviderConfig {

    private final ApplicationContext applicationContext;

    @Bean
    public ToolCallbackProvider methodToolCallbackProvider() {
        Map<String, McpTool> mcpBeanMap = applicationContext.getBeansOfType(McpTool.class);
        return MethodToolCallbackProvider.builder()
                .toolObjects(mcpBeanMap.values().toArray())
                .build();
    }

}
  • McpDemoService.java
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.server.core.McpTool;
import com.server.module.demo.domain.Demo;
import com.server.module.demo.service.IDemoService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@Service
@AllArgsConstructor
public class McpDemoService implements McpTool {

    private final IDemoService demoService;

    @Tool(description = "根据年龄查询 Demo 列表")
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public String queryDemoInfoByAge(@ToolParam(description = "年龄") Integer age) {
        Page<Demo> page = new Page<>(1, 10);
        List<Demo> demoList = demoService.list(page, Wrappers.<Demo>lambdaQuery().eq(Demo::getAge, age).orderByAsc(Demo::getName));
        return JSON.toJSONString(demoList);
    }

}

MCP 客户端

  • ChatService.java
import com.alibaba.fastjson2.JSON;
import io.modelcontextprotocol.client.McpSyncClient;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class ChatService {

    private final ChatClient chatClient;

    @Getter
    private final ToolCallback[] toolCallbacks;

    public ChatService(OpenAiChatModel openAiChatModel, List<McpSyncClient> mcpSyncClientList) {
        log.info("mcpSyncClientList={}", JSON.toJSONString(mcpSyncClientList));
        log.info("===============================================\n");
        for (McpSyncClient mcpSyncClient : mcpSyncClientList) {
            log.info("clientInfo={}", mcpSyncClient.getClientInfo());
            log.info("serverInfo={}", mcpSyncClient.getServerInfo());
        }
        log.info("===============================================\n");
        var mcpToolCallbackProvider = new SyncMcpToolCallbackProvider(mcpSyncClientList);
        toolCallbacks = mcpToolCallbackProvider.getToolCallbacks();
        log.info("toolCallbacks={}", JSON.toJSONString(toolCallbacks));
        log.info("===============================================\n");
        for (ToolCallback toolCallback : toolCallbacks) {
            log.info("toolCallback={}", JSON.toJSON(toolCallback.getToolDefinition()));
        }
        log.info("===============================================\n");
        this.chatClient = ChatClient.builder(openAiChatModel)
                .defaultTools(mcpToolCallbackProvider)
                .build();
    }

    public String askQuestion(String prompt) {
        return chatClient.prompt(prompt).call().content();
    }

}
  • application.yml
spring:
  ai:
    openai:
      api-key: sk-xxxxx
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-chat
    mcp:
      client:
        type: sync
        name: spring-mcp-client-ws
        sse:
          connections:
            server1:
              url: http://localhost:9800

DeepSeek API

  • 申请 API_KEY:https://platform.deepseek.com/usage

在这里插入图片描述

Docker

  • 打包 jar 包并复制到 docker/app/ 对应目录中
  • start.sh 脚本按顺序先启动 mcp-server 再启动 mcp-client-ws

在这里插入图片描述

  • 配置 API_KEY 与 DeepSeek 模型
cd docker/app/mcp-client-ws
vim application-prod.yml
spring:
  ai:
    openai:
      api-key: sk-xxxxx
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-chat
cd docker
docker-compose up -d mcp-server
docker logs -f mcp-server

sse 连接

http://127.0.0.1:9800/sse

ws 连接(推荐)

ws://127.0.0.1:9802/mcp/ws
  • js 测试脚本
cd node-ws-client
npm install
node client.js

在这里插入图片描述

  • Nginx 配置 ws:// 或 wss://
location /mcp/ {
    proxy_pass http://192.168.0.160:9802/mcp/;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

http 连接

http://127.0.0.1:9801/mcp/mcpClient/listTools

在这里插入图片描述

http://127.0.0.1:9801/mcp/mcpClient/chat?prompt=查询章若楠用户信息

在这里插入图片描述

vue2-chat-window

  • 聊天窗口通过 ws:// 连接 mcp-client-ws 服务

在这里插入图片描述

cd vue2-chat-window
npm install
npm run serve
  • vue2 聊天界面

在这里插入图片描述

Cherry Studio

  • 下载地址:https://cherry-ai.com/

配置模型

在这里插入图片描述

在这里插入图片描述

配置 MCP

在这里插入图片描述
在这里插入图片描述

调用 MCP

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2339586.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《前端面试题之 Vue 篇(第三集)》

目录 1、 nvm的常用命令①.Node.js 版本与 npm 版本的对应关系②Vue2 与 Vue3 项目的 Node.js 版本分界线③版本管理实践建议 2、Vue2 项目搭建&#xff08;基于 vue-cli Webpack&#xff09;① 环境准备② 安装 Vue CLI&#xff08;脚手架&#xff09;③.创建项目&#xff08…

嵌入式C语言位操作的几种常见用法

作为一名老单片机工程师&#xff0c;我承认&#xff0c;当年刚入行的时候&#xff0c;最怕的就是看那些密密麻麻的寄存器定义&#xff0c;以及那些让人眼花缭乱的位操作。 尤其是遇到那种“明明改了寄存器&#xff0c;硬件就是不听话”的情况&#xff0c;简直想把示波器砸了&am…

基于Djiango实现中药材数据分析与可视化系统

中药材数据分析与可视化系统 项目截图 登录 注册 首页 药材Top20 药材价格 产地占比 历史价格 新闻资讯 后台管理 一、项目概述 中药材数据分析与可视化系统是一个基于Django框架开发的专业Web应用&#xff0c;致力于对各类中药材数据进行全面、系统的采集、分析和可视化展示…

stm32(gpio的四种输出)

其实GPIO这个片上外设的功能&#xff1a; 用于控制IO引脚。 CPU就如同大脑&#xff0c;而这些片上外设就如同四肢一样的关系 如图 —————————————————————————————— OK类比了以上 其实GPIO是有 八种工作模式的 这八种工作模式 因为GPIO是面向IO…

Zookeeper 可观测性最佳实践

Zookeeper 介绍 ZooKeeper 是一个开源的分布式协调服务&#xff0c;用于管理和协调分布式系统中的节点。它提供了一种高效、可靠的方式来解决分布式系统中的常见问题&#xff0c;如数据同步、配置管理、命名服务和集群管理等。本文介绍通过 DataKit 采集 Zookeeper 指标&#…

微信小程序三种裁剪动画有效果图

效果图 .wxml <image class"img inset {{status?action1:}}" src"{{src}}" /> <image class"img circle {{status?action2:}}" src"{{src}}" /> <image class"img polygon {{status?action3:}}" src&quo…

C语言笔记(鹏哥)上课板书+课件汇总(结构体)-----数据结构常用

结构体 目录&#xff1a; 1、结构体类型声明 2、结构体变量的创建和初始化 3、结构体成员访问操作符 4、结构体内存对齐*****&#xff08;重要指数五颗星&#xff09; 5、结构体传参 6、结构体实现位段 一、结构体类型声明 其实在指针中我们已经讲解了一些结构体内容了&…

git清理--解决.git文件过大问题

背景&#xff1a;为什么.git比我仓库中的文件大很多 为什么我的git中只有一个1KB的README&#xff0c;但是.git却又1G多&#xff1f;当我想把这个git库push到gitee时&#xff0c;还会报错&#xff1a; 根据报错信息&#xff0c;可看出失败的原因是&#xff1a;有文件的大小超过…

Jetson Orin NX 部署YOLOv12笔记

步骤一.创建虚拟环境 conda create -n yolov12 python3.8.20 注意&#xff1a;YOLOv12/YOLOv11/YOLOv10/YOLOv9/YOLOv8/YOLOv7a/YOLOv5 环境通用 步骤二.激活虚拟环境 conda activate yolov12 #激活环境 步骤三.查询Jetpack出厂版本 Jetson系列平台各型号支持的最高Jetp…

微服务2--服务治理与服务调用

前言 &#xff1a;本文主要阐述微服务架构中的服务治理&#xff0c;以及Nacos环境搭建、服务注册、服务调用&#xff0c;负载均衡以及Feign实现服务调用。 服务治理 服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动化注册与发现。 服务注册&#xff1a;在…

C语言之高校学生信息快速查询系统的实现

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之高校学生信息快速查询系统的实现 目录 任务陈述与分析 问题陈述问题分析 数据结构设…

Spring Boot 项目中发布流式接口支持实时数据向客户端推送

1、pom依赖添加 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>2、事例代码 package com.pojo.prj.controller;import com.pojo.common.core.utils.String…

【网络篇】从零写UDP客户端/服务器:回显程序源码解析

大家好呀 我是浪前 今天讲解的是网络篇的第四章&#xff1a;从零写UDP客户端/服务器&#xff1a;回显程序源码解析 从零写UDP客户端/服务器&#xff1a;回显程序源码解析 UDP 协议特性​核心类介绍​ UDP的socket应该如何使用&#xff1a;1: DatagramSocket2: DatagramPacket回…

MATLAB 控制系统设计与仿真 - 38

多变量系统控制器设计实例1 考虑如下给出的多变量系统模型&#xff1a; 考虑混合灵敏度问题&#xff0c;引入加权矩阵&#xff1a; 设计鲁棒控制器&#xff0c;并绘制闭环系统的阶跃响应曲线及开环系统的奇异值曲线。 MATLAB代码如下&#xff1a; clear all;clc; stf(s); g1…

[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案

[密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案 引言 国密算法&#xff08;SM2/SM3/SM4&#xff09;在金融、政务等领域广泛应用&#xff0c;但开发者在集成gmssl库实现SM2签名时&#xff0c;常遇到与第三方工具&#xff08;如OpenSSL、国密网关&#xff09;验证不…

【k8s系列1】一主两从结构的环境准备

环境准备 虚拟机软件准备及安装&#xff0c;这里就不详细展开了&#xff0c;可以看文章:【一、虚拟机vmware安装】 linux环境准备及下载&#xff0c;下载镜像centOS7.9&#xff0c;以前也有写过这个步骤的文章&#xff0c;可以看&#xff1a;【二、安装centOS】 开始进入正题…

【Rust 精进之路之第2篇-初体验】安装、配置与 Hello Cargo:踏出 Rust 开发第一步

系列&#xff1a; Rust 精进之路&#xff1a;构建可靠、高效软件的底层逻辑 **作者&#xff1a;**码觉客 发布日期&#xff1a; 2025-04-20 引言&#xff1a;磨刀不误砍柴工&#xff0c;装备先行&#xff01; 在上一篇文章中&#xff0c;我们一起探索了 Rust 诞生的缘由&…

腾讯旗下InstantCharacter框架正式开源 可高度个性化任何角色

目前基于学习的主题定制方法主要依赖于 U-Net 架构&#xff0c;但其泛化能力有限&#xff0c;图像质量也大打折扣。同时&#xff0c;基于优化的方法需要针对特定主题进行微调&#xff0c;这不可避免地会降低文本的可控性。为了应对这些挑战&#xff0c;我们提出了 “即时角色”…

详讲Linux下进程等待

3.进程等待 引言&#xff1a;什么是进程等待 想象有两个小伙伴&#xff0c;一个是 “大强”&#xff08;父进程 &#xff09;&#xff0c;一个是 “小强”&#xff08;子进程 &#xff09;。大强给小强安排了任务&#xff0c;比如去收集一些石头。 …

JBoss + WildFly 本地开发环境完全指南

JBoss WildFly 本地开发环境完全指南 本篇笔记主要实现在本地通过 docker 创建 JBoss 和 WildFly 服务器这一功能&#xff0c;基于红帽的禁制 EAP 版本的重新分发&#xff0c;所以我这里没办法放 JBoss EAP 的 zip 文件。WildFly 是免费开源的版本&#xff0c;可以在红帽官网找…