🦴不是MCP害了我,是这个阻塞害了我啊

大家好,我是EthanYuan,今天我来分享一下之前困扰了我很久都跑不通的一个技术:MCP。为什么跑不通呢?接下来先讲述一下什么是MCP,我最后再解释为什么我跑不通。

什么是MCP?

MCP(Model Context Protocol)模型上下文协议,是Anthropic在2024年11月发布的开放标准,核心目标是让大模型能够标准化地连接外部数据源和工具。

在MCP出现之前,想让大模型访问数据库、调用API、读取本地文件,都需要根据场景编写一套配置,维护成本极高,MCP的优化思路是:定制一套通用协议,所有实现这个协议的外部资源,大模型都可以直接调用,不用关心底层是哪种数据库,是云存储还是本地文件。

类比一下,就是在USB-C出现之前,各种数据线接口五花八门无法共用,而USB-C出来之后,一根线搞定所有设备,MCP就是AI领域的USB-C,使大模型和外部资源的连接变得灵活方便。

MCP的三大作用

  1. 轻松增强AI的能力
  2. 统一标准,降低理解和开发成本
  3. 打造生态,造福开发者。

MCP的两种通信协议

Stdio: 通过标准输入输出流实现和MCP服务器的通信,不走网络、延迟低、实现简单,适用于本地开发或使用,Client和Server都跑在同一台机器上,使用进程通信就行。

SSE: 基于 HTTP + Server-Sent Events 实现,客户端使用 HTTP POST 发请求,服务端将相应结果用SSE实时推送回客户端,适用于远程部署的环境,比如云端部署、分布式系统、需要实时推送的服务,一个SSE模式的服务端可以被多个客户端调用。

❓ 为什么之前有一段时间MCP会火,然后又降温得很快?

2024年底,Anthropic 推出MCP这一开放标准,声称要打造"AI时代的USB-C",承诺"一次开发全模型通用",在早期AI开发,程序员如果要让项目适配外部工具,就需要针对不同平台编写不同的配置文件,M × N 碎片化适配对开发者极为痛苦,MCP的出现直接解决行业痛点,且各互联网公司巨头,如OpenAI、Google等表示支持,甚至觉得MCP就是AI开发的基础设施。

后来在2025年这一"AI Agent 元年"时期,各大公司都在研究大模型,逐渐发现MCP有很多缺点:

  • 工程化硬伤: MCP存在性能与成本的缺点,一个是调用延迟高,对于简单工具调用,其延迟要增加3~5倍,在高频、实时业务场景存在极高的性能压力。其次,MCP是协议驱动的标准,如果要调用MCP,就需要把工具定义的数据作为上下文一次性加载到大模型中,这直接导致Token成本爆炸,且极其挤占模型上下文窗口,导致AI的理解成本上升。另外,在我们日常使用中,如果AI判断要调用MCP,通常不会只调用一次,这也是成本暴增的一大原因。
  • 安全风险: 2025年12月曾出现黑客插件通过MCP窃取密钥的事件,且大部分公开的MCP Server存在系统性安全风险。
  • 实用价值不足: 开发者发现,简单的工具调用仅需几行代码即可实现,而编写MCP Server违背了简化开发的原则

总结:

MCP底层也是基于工具调用来实现功能的

对于中小企业,无法支撑昂贵的成本,也没有极其复杂的业务场景需要频繁使用MCP;

对于大企业,它们会自己定制专属协议,开发者实际上还是要根据不同平台编写不同的配置文件调用外部资源。

所以,这就是MCP火了一段时间又迅速冷却的原因,实际上就是广大开发者和企业对于MCP的使用趋于理性化。

我的AI项目是如何使用MCP的

引入MCP客户端的依赖。

xml 复制代码
<!-- 添加Spring AI MCP starter依赖 -->
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
  <version>1.0.0-M6</version>
</dependency>

在mcp.so中,搜索amap找到高德地图官方MCP,查看调用示例,由此可知配置MCP服务需要编写JSON配置文件。

在项目中新建mcp-server.json文件,用于配置MCP服务,该配置文件能填写多个MCP配置。

💡Windows环境下,需要使用npx.cmd,否则会报错

MCP配置文件编写好之后,在服务类LoveApp中引入ToolCallbackProvider。将JSON配置文件中的MCP服务全部加载,然后新建调用MCP的对话方法,将加载的MCP提供给ChatClient即可。

scss 复制代码
@Resource
private ToolCallbackProvider toolCallbackProvider;
 
public String doChatWithMcp(String message, String chatId) {
        ChatResponse response = QAchatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .advisors(new MyLoggerAdvisor())
                // 调用 MCP
                .tools(toolCallbackProvider)
                .call()
                .chatResponse();
        String content = response.getResult().getOutput().getText();
        log.info("Response with MCP: {}", content);
        return content;
    }

生成单元测试,调用MCP对话方法,用户提问"寻找黄浦江观景餐厅并前往约会",结果如下:

MCP调用总结:

  1. MCP Client调用MCP,先引入MCP Client的依赖
  2. 前往MCP集成平台搜索MCP服务,得知配置MCP服务需要编写JSON配置
  3. 在服务类引入ToolCallbackProvider,自动加载JSON中已配置的所有MCP服务
  4. 将MCP服务注入到ChatClient中,大模型返回MCP调用结果

MCP Server开发-图片搜索

1)首先在项目根目录下新建模块yuluo-image-search-mcp-server,引入Hutool、Lombok、MCP Server依赖。

2)这里选择使用Pexels的图片搜索服务,先前往官网获取API Key,然后回到项目

3)编写配置文件,这里区分sse和stdio两种配置文件,然后在application.yml激活stdio配置

4)新建MCP服务类ImageSearchTool,开发图片搜索功能

stdio方式:已成功检测到自定义MCP图片搜索服务

返回结果

5)在MCP Server的启动类中,将MCP服务注册到ToolCallBackProvider中,才能被服务类识别

scss 复制代码
    @Bean
    public ToolCallbackProvider imageSearchTools(ImageSearchTool imageSearchTool){
        return MethodToolCallbackProvider.builder()
                .toolObjects(imageSearchTool)
                .build();
    }

💡经过测试,通过sse传输模式也可成功返回结果,运行时先保证MCP Server处于运行状态

💡MCP需要的API Key需要通过JSON配置中的"env"内获取,并且不提交到仓库中

MCP Server开发总结:

  • 添加Spring AI MCP依赖
  • 定义工具类并使用@Service注解标记为服务组件
  • 在工具方法上使用@Tool注解声明MCP工具功能
  • 使用@ToolParam注解定义工具参数及其描述
  • 在主应用类中通过@Bean注册ToolCallbackProvider
  • 配置application.yaml设置传输模式(stdio/sse)和端口

❓问题1: 本地基于 SSE 模式调用 MCP 频频失败,线上环境同样异常,但单元测试完全正常

解答:其实这是大模型调用MCP本身的超时问题,我在开发过程中,调用MCP报错往往是因为20s超时,大模型报错,原因就是整条调用链路都属于同步调用,不仅阻塞接口,而且硬拖到超时了才响应,成功率也低。实际上我也简单想到用CompletableFuture异步调用,但是这仅仅是释放了主线程,实际上就是把阻塞线程丢给异步线程池,本质上超时的问题没有解决,该报错还是报错。

想解决MCP超时的问题,只能是LLM+MCP都同时异步调用,企业的解决方案如下:

用户触发 LLM 工具调用后立即下发任务 ID 并响应前端,通过本地线程池 / 消息队列后台串行执行 LLM 流式推理 + MCP 工具回调全链路,全程不阻塞网关请求,前端轮询 / 长连接拉取最终结果,同时叠加 MCP 限时熔断、结果缓存与失败降级。


以上就是我对MCP学习的经历了,踩了坑最后还是没实现功能,但是了解到了MCP这么多坑也不亏,那么本篇就到这里,最后是我对MCP的一句话总结:

📒 MCP不是万能工具,而是特定场景的标准方案。

相关推荐
金銀銅鐵1 分钟前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
念何架构之路34 分钟前
go-grpc设计思想
开发语言·后端·golang
system_error_x1 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
步行cgn3 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
码事漫谈3 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780514 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123454 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒4 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记4 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk598784 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端