将 DeepSeek 集成到 Spring Boot 项目实现通过 AI 对话方式操作后台数据
文章目录
- 项目简介
- 本项目分两大模块
- Gitee
- MCP 简介
- MCP 官网
- MCP Apifox 文档
- MCP 官方示例
- 环境要求
- 项目代码
- 核心实现代码
- MCP 服务端
- MCP 客户端
- DeepSeek API
- 腾讯云版 DeepSeek API(免费额度1000000token)
- 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 服务器可以连接到这些系统
MCP 官网
- https://modelcontextprotocol.io/introduction
MCP Apifox 文档
- https://app.apifox.com/project/5991953
MCP 官方示例
- https://github.com/modelcontextprotocol/servers
环境要求
- Java 环境 >= JDK17
- Spring Boot >= 3.x
项目代码
git clone https://gitee.com/wufengsheng/spring-mcp-server.git
注: Java 开发环境必须 >= JDK17,否则项目编译不过。
核心实现代码
- MCP 依赖 jar 包
org.springframework.ai spring-ai-bom 1.0.0-M7 pom import org.springframework.ai spring-ai-starter-mcp-server-webflux org.springframework.ai spring-ai-starter-mcp-client org.springframework.ai spring-ai-starter-model-openai ...
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 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 page = new Page(1, 10); List demoList = demoService.list(page, Wrappers.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 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
腾讯云版 DeepSeek API(免费额度1000000token)
- https://cloud.tencent.com/document/product/1772/115969
- https://console.cloud.tencent.com/lkeap/api
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
- 腾讯云版 DeepSeek API 配置
spring: ai: openai: api-key: sk-xxxxx base-url: https://api.lkeap.cloud.tencent.com/v1 chat: options: model: deepseek-v3 # 或deepseek-v3-0324、deepseek-r1 mcp: client: type: sync name: spring-mcp-client-ws sse: connections: server1: url: http://localhost:9800
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
- Nginx 配置 ws:// 或 wss://
- js 测试脚本
- 腾讯云版 DeepSeek API 配置
- 配置 API_KEY 与 DeepSeek 模型
- 申请 API_KEY:https://platform.deepseek.com/usage
- application.yml
- ChatService.java
- McpDemoService.java
- ToolCallbackProviderConfig.java
- MCP 依赖 jar 包
- https://github.com/modelcontextprotocol/servers
- https://app.apifox.com/project/5991953
- https://modelcontextprotocol.io/introduction
- https://gitee.com/wufengsheng/spring-mcp-server
-
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。