「深度拆解」Spring Boot如何用DeepSeek重构MCP通信层?从线程模型到分布式推理的架构进化

发布于:2025-06-06 ⋅ 阅读:(76) ⋅ 点赞:(0)

什么是MCP?
MCP(Model Context Protocol,模型上下文协议)是由Anthropic公司于2024年11月推出的开放标准协议,旨在为大型语言模型(LLM)与外部数据源、工具及系统提供统一的交互接口,被称为 “AI领域的USB-C接口”158。其核心目标是解决AI模型与外部世界交互的碎片化问题,推动AI从“被动应答”向“主动执行”跃迁。

  • 解决了什么问题?
    解决了AI大模型因数据孤岛限制无法发挥潜力的难题。举个例子,以前我们想要AI大模型使用我们的数据,要么自己复制粘贴,要么上传下载,其中都需要人参与,MCP就是AI大模型与数据资源中间的一座桥梁,通过MCP服务和MCP客户端,只要遵循这套协议,就能实现万物互联;

  • MCP核心架构
    MCP遵循CS架构(客户端-服务端),有三个核心概念: MCP HOST:发起请求的LLM应用程序,可以理解为用户请求入口; MCP Client:在应用程序内部,专门与MCP Server进行交互的工具,类似HttpClient的作用,提供调用本地MCP Server和远程MCP Server的能力; MCP Server:为MCP Client提供各类服务,比如文件操作,数据库操作等资源服务,可本地部署,也可远程部署;

  • MCP Client 从上述架构图中可以了解到,MCP Client充当了LLM大模型和MCP Server之间的桥梁,为LLM大模型很好的运用本地和远程数据资源提供了最基本的保障。 MCP Client的基本工作流程如下:
    • 当HOST项目初始化的时候,也会触发MCP Client初始化;
    • MCP Client首先会先与所有的MCP Server建立连接,并从MCP Server获取可以使用的工具列表(每个MCP Server都会告诉MCP Client自己具备的能力);
    • 当用户请求进来后,LLM大模型会根据用户的具体请求分析是否可以使用工具来解决用户的问题,并最终决定使用哪些工具来处理;
    • 如果需要使用工具,那么LLM大模型会通过MCP Client来调用MCP Server处理;
    • 最终调用工具的结果会经过LLM大模型处理后返回给用户;

  • MCP Server
    MCP Server主要提供三种类型的功能:
    • 资源(Resources):比如文件,数据库等,可以被客户端读取;
    • 工具(Tools):比如地图定位服务,实时公交查询等;
    • 提示(Prompts):比如如果需要 AI 定制化地返回某些格式化内容时,可以提供自定义的 prompts;

以上功能可以为AI应用提供丰富的上下文信息和操作能力,从而增强LLM大模型的实用性和灵活性。
目前已经出现了很多好玩的MCP Server,有兴趣的小伙伴可以访问官方MCP Server列表MCP.so阿里云MCP或者Awesome MCP Server

  • 通信机制
    MCP Client与MCP Server通信采用以下两种方式,并且都是使用JSON-RPC 2.0数据格式进行消息通信:
    • 本地通信:通过操作系统标准输入输出stdio传输,适用于MCP Client和MCP Server部署在同一台机器上进行通信;
    • 远程通信:使用SSE(Server-Sent Events)与Http结合,实现跨网络的数据传输,适用于需要访问远程资源或分布式部署的场景;

如何使用MCP
目前市面上有很多工具可以支持调用MCP Server,比如CursorCline等,大家有兴趣的可以去了解一下:


Spring Boot集成DeepSeek+MCP Client调用MCP Server

  • 前置工作
    安装nodejs环境:请安装nodejs 18+以上版本,并保证以下命令生效:
    node -v npm -v npx -v
    安装python环境:建议安装python-3 11或以上版本 ;
    说明:目前MCP Server基本都是使用Nodejs或者Python编写的,想要使用官方或者第三方的MCP Server需要保障本地有对应的运行环境;
    接下里开始创建SpringBoot项目
  • maven依赖
    pom.xml:
    <dependencies> <!-- 对外提供restful api --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 使用openai接入LLM大模型,咱们使用的deepseek兼容opanai接口,所以可以使用这个依赖,如果使用其他大模型可以更换这个依赖 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> <version>1.0.0-M6</version> </dependency> <!-- mcp客户端依赖,实现了与LLM大模型交互逻辑,且通过MCP协议调用MCP Server --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId> <version>1.0.0-M6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
  • 配置LLM大模型
    application.yml:
    spring: ai: openai: chat: options: model: "deepseek-chat" # 需要替换为自己的api-key api-key: "xxxxxxxxxxxxxxxxxxxxxxxx" base-url: "https://api.deepseek.com"
    上面的api-key需要去deepseek官网获取,创建api-key后需要充值,否则调用的时候会返回余额不足,影响使用效果;
  • 配置调用的MCP Server
    目前我在demo中接了两款MCP Server,且都在本地运行。
    • filesystem:用于管理文件系统,可以执行文件的增删查改等操作。
    • mysql:用于mysql数据库的数据查询和分析操作。

执行以下命令安装对应的MCP Server到机器上:
npm install mysql-mcp-server npm install @modelcontextprotocol/server-filesystem
application.yml相关配置如下:
spring: ai: mcp: client: stdio: connections: mysql: # Windows操作系统使用npx.cmd,Linux和MacOS使用npx command: "npx.cmd" args: # mcp server名称 - "mysql-mcp-server" env: # 数据库ip "MYSQL_HOST": "127.0.0.1" # 数据库服务端口 "MYSQL_PORT": "3306" # 数据库用户名 "MYSQL_USER": "xxxx" # 数据库密码 "MYSQL_PASSWORD": "xxxx" # 数据库名称 "MYSQL_DATABASE": "xxxx" filesystem: # Windows操作系统使用npx.cmd,Linux和MacOS使用npx command: "npx.cmd" args: - "-y" - "@modelcontextprotocol/server-filesystem" # 在此文件夹内进行文件操作,需根据具体需求调整目标文件夹 - "E:\\mcp_test"

  • Java Bean配置
    import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.mcp.SyncMcpToolCallbackProvider; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @ClassName McpClientConfiguration * @Description * @Author weizou.zou * @Date 2025/4/9 0:41 * @Version $ */ @Configuration public class McpClientConfiguration { /** * 注入ChatClient * @param chatModel * @param toolCallbackProvider 报红不用管,没有任何问题 * @return */ @Bean ChatClient chatClient(ChatModel chatModel, SyncMcpToolCallbackProvider toolCallbackProvider) { return ChatClient .builder(chatModel) .defaultTools(toolCallbackProvider.getToolCallbacks()) .build(); } }
  • McpClientController实现与用户交互
    import jakarta.annotation.Resource; import org.springframework.ai.chat.client.ChatClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/mcp") public class McpClientController { @Resource private ChatClient chatClient; @GetMapping("/ai") String generation(String userInput) { return this.chatClient.prompt() .user(userInput) .call() .content(); } }

至此我们的demo项目就搞定了,下面咱们来看看效果如何:
http://127.0.0.1:8081/api/mcp/ai?userInput=请帮我创建一个ai.txt,并在里面写入hello ai!


http://127.0.0.1:8081/api/mcp/ai?userInput=帮我查一下courier.user表中有多少条数据


遇到的问题

  • maven依赖难找
    虽然现在有很多文章聊MCP的,但是大多数都是科普文,即使是实战的,也很少有java或者spring相关的。另一个就是spring ai目前还没有release版本的mcp jar包,很多LLM实现上没有完全支持mcp,导致想要找到合适的maven比较困难。
  • 配置MCP Server报错
    一开始按照网上资料在application.yml中配置MCP Server,一启动项目就报错:


其实是因为Windows环境下npx命令需要有后缀cmd:npx.cmd,不能完全参照网上资料直接写npx。也就是说,调用命令需要根据操作系统环境进行调整。

  • 如何转换MCP Server配置为yml配置
    一般在网上找到的MCP Server配置如下,以百度地图MCP Server为例:
    { "mcpServers": { "baidu-maps": { "command": "python", "args": [ "-m", "mcp_server_baidu_maps" ], "env": { "BAIDU_MAPS_API_KEY": "<YOUR_API_KEY>" } } } }
    或者
    { "mcpServers": { "baidu-map": { "command": "npx", "args": [ "-y", "@baidumap/mcp-server-baidu-map" ], "env": { "BAIDU_MAP_API_KEY": "{您的AK}" } } } }
    如果是python环境的话,根据文档,需要先安装MCP Server
    pip install mcp-server-baidu-maps
    上面的两类配置最终转换为application.yml如下:
    Python版本
    spring: ai: mcp: client: stdio: connections: baidu-maps: command: "python.cmd" args: - "-m" - "mcp_server_baidu_maps" env: "BAIDU_MAPS_API_KEY": "<YOUR_API_KEY>"
    Nodejs版本
    spring: ai: mcp: client: stdio: connections: baidu-maps: command: "npx.cmd" args: - "-y" - "@baidumap/mcp-server-baidu-map" env: "BAIDU_MAP_API_KEY": "<YOUR_API_KEY>"

  • 多轮对话上下文丢失问题
    第一轮对话:请帮我生成查询user表总共有多少条的sql语句
    返回结果:select count(*) from user; 需要我帮你执行嘛?
    第二轮对话:是的,请帮我执行这条查询语句
    返回结果:请告诉我你需要执行哪条语句?
    上面的示例就是多轮对话上下文丢失的问题,这个问题的处理结果很快在deepseek官方文档找到了解决方案:


也就是说,如果需要保持上下文不丢失,那么需要把所有的历史问答全部发给deepseek大模型,这样将带来两个明显的问题:

    1. 过长的对话会导致token使用量上涨很快;
    2. 应用程序需要自己保存历史问答数据;

结语
未来,MCP 有望成为企业数字化转型的核心枢纽——从“数据搬运工”进化为“智能决策大脑”。期待这一技术组合持续迭代,为开发者带来更极致的体验,为行业树立高可用、高智能的集成范式标杆。


网站公告

今日签到

点亮在社区的每一天
去签到