当前位置: 首页 > news >正文

【Bug已解决】Codex App: new task creation times out when configured MCP server is unreachable 解决方案

【Bug已解决】Codex App: new task creation times out when configured MCP server is unreachable 解决方案

原始报错线索:Codex App: new task creation times out when configured MCP server is unreachable(当用户配置的某个 MCP 服务器连不上时,创建新任务会一直超时,整个创建流程被拖死)。


一、现象长什么样

用户配了一个 MCP 服务器(可能是公司内网、可能暂时宕机)。然后:

  1. 点「新建任务」,界面转圈,几秒/几十秒后报「创建超时」;
  2. 创建任务本身根本不需要这个 MCP 服务器——它只是「锦上添花」的扩展能力;
  3. 但只要 MCP 不可达,创建就必超时;
  4. 把 MCP 配置删掉,创建立刻恢复正常。 根因是**「可选依赖」被当成了「必需依赖」,且没设超时隔离,主流程被一个无关紧要的服务拖死**。

二、背景:必需依赖 vs 可选依赖

任何创建流程都依赖一些东西:

  • 必需依赖:数据库、鉴权服务——它们挂了,创建确实该失败;
  • 可选依赖:MCP 服务器、插件后端、推荐服务——它们挂了,创建仍应成功,只是少了增强能力。 把可选依赖当成必需,是「创建被拖死」的根源。此外,即使依赖必需,也要有超时隔离:不能让一个慢依赖无限阻塞主流程。

三、为什么创建超时:根因

3.1 可选依赖同步阻塞主流程

创建任务时,代码里mcp.fetch_tools()是同步调用,没设超时,MCP 不可达就一直等 TCP 超时(常达数十秒)。

3.2 没区分必需 / 可选

MCP 挂了,代码把它当致命错误,整个创建 abort,而非「跳过增强、继续创建」。

3.3 重试放大超时

对不可达的 MCP 还做多次重试,每次都等满超时,总耗时叠加。

3.4 无健康度短路

没在创建前先快速探活 MCP,直接进重逻辑,浪费时间。

四、最小可运行复现(可选依赖阻塞主流程)

下面演示「MCP 不可达时同步等待」如何拖死创建:

import time, socket def fetch_mcp_tools_blocking(host, port): # 错误:无超时连接,不可达时等系统 TCP 超时(默认可长达几十秒) s = socket.create_connection((host, port)) # 阻塞直到超时 return s def create_task_bad(task): tools = fetch_mcp_tools_blocking("192.168.99.99", 9999) # 不可达 return {"task": task, "tools": tools} if __name__ == "__main__": t0 = time.time() try: create_task_bad({"name": "x"}) except Exception as e: print(f"创建失败({time.time()-t0:.1f}s): {e}") # 数十秒后才失败

不可达的 MCP 让创建卡几十秒才失败——核心功能被可选依赖拖垮。

五、解决方案一:所有外部依赖调用必须设超时

把无超时的阻塞调用改成「短超时 + 快速失败」:

import socket def fetch_mcp_tools(host, port, timeout=2.0): """带超时的依赖探测,不可达就快速失败。""" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(timeout) try: s.connect((host, port)) return ["tool_a", "tool_b"] # 示意 except (socket.timeout, OSError): return None # 不可达 finally: s.close() if __name__ == "__main__": import time t0 = time.time() tools = fetch_mcp_tools("192.168.99.99", 9999, timeout=2.0) print(f"探测耗时 {time.time()-t0:.1f}s, 工具={tools}") # 2s 内返回 None

2 秒超时,不可达立刻返回None,不再拖几十秒。

六、解决方案二:区分必需 / 可选,可选失败降级

创建主流程把 MCP 当可选:不可达就跳过增强,任务照常创建:

def create_task(task, mcp_endpoint=None): """创建任务:MCP 是可选的,不可达则降级创建。""" task_id = f"task-{int(time.time())}" enhancement = None if mcp_endpoint: tools = fetch_mcp_tools(*mcp_endpoint, timeout=2.0) if tools is None: # 可选依赖不可用 -> 降级,不阻塞创建 enhancement = "skipped:mcp_unreachable" else: enhancement = tools return {"task_id": task_id, "task": task, "enhancement": enhancement} if __name__ == "__main__": # MCP 不可达,但任务照样建出来 result = create_task({"name": "x"}, mcp_endpoint=("192.168.99.99", 9999)) print(result) # enhancement='skipped:mcp_unreachable',创建成功

可选依赖失败只影响「增强部分」,核心创建不受影响(解决 3.2)。

七、解决方案三:健康度短路 + 不重试不可达

创建前先快速探活,不可达直接跳过;且对「连接级不可达」不做重试(重试只用于「瞬时限流」):

def maybe_enhance(mcp_endpoint): """只对『可达』的 MCP 做增强;不可达立即放弃,不重试。""" if mcp_endpoint is None: return None # 探活:连接级失败不重试(重试对『主机不可达』无意义,只会叠加超时) tools = fetch_mcp_tools(*mcp_endpoint, timeout=1.5) if tools is None: return "skipped" # 不重试,直接降级 return tools def create_task_v2(task, mcp_endpoint=None): enhanced = maybe_enhance(mcp_endpoint) return {"task_id": f"task-{int(time.time())}", "enhanced": enhanced} if __name__ == "__main__": print(create_task_v2({"name": "x"}, ("192.168.99.99", 9999)))

连接不可达是「确定性失败」,重试只会叠加超时——直接降级最合理(解决 3.3)。

八、解决方案四:把依赖增强异步化

更彻底的做法:创建任务先返回(不含 MCP 增强),MCP 增强在后台补充:

import threading def create_task_async(task, mcp_endpoint=None): task_id = f"task-{int(time.time())}" # 主流程立即返回,MCP 增强后台做 def background_enhance(): if mcp_endpoint: tools = fetch_mcp_tools(*mcp_endpoint, timeout=2.0) # 拿到后写入任务元数据(示意) print(f"[{task_id}] 后台增强: {tools}") threading.Thread(target=background_enhance, daemon=True).start() return {"task_id": task_id, "status": "created"} if __name__ == "__main__": r = create_task_async({"name": "x"}, ("192.168.99.99", 9999)) print("任务已创建(不等 MCP):", r) # 立即返回

创建永远不被 MCP 阻塞——MCP 只是「后续补充」,彻底解耦。

九、排查清单

「依赖不可达时创建超时」,按下面排查:

  1. 依赖是必需还是可选?MCP 类增强应可选(第六节);
  2. 外部调用有超时吗?无超时阻塞是元凶;
  3. 可选失败是否降级?还是 abort 整个创建(第六节);
  4. 是否对『不可达』做无意义重试?连接级失败应直接降级(第七节);
  5. 能否异步化增强?创建先返回、增强后台补(第八节);
  6. 健康度能否短路?创建前先探活(第七节);
  7. 超时设置合理吗?2 秒级而非数十秒(第五节);
  8. 日志是否记录『MCP 跳过原因』

十、小结

「依赖的 MCP 不可达时新任务创建超时」的根因是可选依赖被当成必需依赖,且无超时隔离,主流程被一个无关服务阻塞至超时。通用修复:

  1. 必设超时:所有外部依赖调用短超时(2s 级),不可达快速失败;
  2. 区分必需/可选:可选依赖(MCP)不可达则降级创建,核心功能不受影响(第六节);
  3. 不重试不可达:连接级失败确定性,直接降级而非叠加超时(第七节);
  4. 异步解耦:创建先返回,增强后台补充,彻底不被阻塞。 一句话:创建资源的主流程,绝不能被『可选增强依赖』阻塞;外部调用一律短超时,可选失败一律降级,确定性不可达一律不重试。把核心路径和增强依赖解耦,应用才能在「配置了个暂时宕机的 MCP」时,依然秒级创建任务——这与第 129 篇连接韧性、第 130 篇后台压缩、第 117 篇 SSH 保活,共同体现「外部依赖必须超时隔离、可选降级」。

http://www.jsqmd.com/news/1214076/

相关文章:

  • Wpomniagent(WP 万灵智体)首个正式版发布
  • Diablo Edit2:终极游戏角色编辑器完整指南
  • Fastfetch终极指南:5分钟掌握系统信息监控神器
  • 2026安顺筑宅安房屋修缮|全域防水补漏一站式服务,根治雨季渗漏难题 - 筑宅安
  • OBS Studio多机位直播终极指南:5步打造专业级直播体验
  • 即梦AI人物生成翻车预警(面部畸变/手部错误/光影失真),8类典型故障诊断表
  • Atmosphère系统架构深度解析与模块化配置实战指南
  • 安卓逆向实战:从静态分析到动态调试的完整技术解析
  • Python TDD实战:红绿重构循环驱动高质量代码开发
  • 2026四平装饰高性价比品牌排行综合参考指南 - 奔跑123
  • 暗黑3自动化助手:告别重复操作,专注游戏策略
  • 揭秘GPT-4 Turbo vs Claude 3.5 vs Qwen2.5:谁真正扛得住200K tokens?实测RAG响应衰减率与语义连贯性(附Benchmark原始数据)
  • 终极指南:5分钟上手iFakeLocation - iOS虚拟定位神器
  • OpenCV imgproc模块深度解析:从C++图像处理基础到高级优化实战
  • 沈阳迪奥包包回收价格实测曝光:走访五家门店,谁报价没套路出价高? - 奢侈品回收评测
  • Guns项目API文档:Swagger集成与RESTful接口设计规范
  • 大连卖黄金踩坑亏哭!逸程回收全流程透明,靠谱商家没有任何暗地扣费 - 融媒生活
  • BlackHole音频驱动终极指南:5步实现macOS零延迟音频路由
  • 3种创新方案彻底解决Umi-OCR离线文字识别工具下载难题
  • C++实现高性能实习生招聘系统:架构设计与核心模块详解
  • BlenderGIS深度解析:三维地理数据可视化的架构设计与核心机制
  • 78645
  • 2026台州婚纱照口碑排行丨6家品牌测评 - 生活测评君
  • 从零构建C++高性能服务器:掌握epoll、线程池与Reactor/Proactor模式
  • 2026-07-17 GitHub 热点项目精选
  • 职场竞争本质是“资源稀缺下的排序游戏”:给核心项目、给决策权、给资源倾斜、给涨薪转正、给你犯错的空间
  • 安阳黄金回收,清奢、鑫清黄金珠宝,铂金钻戒回收。 - 清奢黄金上门回收
  • C++超市管理系统实战:从数据结构设计到Qt界面开发全解析
  • C++ string类模拟实现:深拷贝、内存管理与运算符重载实战
  • PyBoy:用Python玩转Game Boy模拟器与游戏AI开发