Codex CLI 跑着跑着 MCP 服务器断了, 看上去像是被 logout 吞了 session。这篇从 stdio 长会话断连、provider 切换丢 MCP、ChatGPT auth 卡 codex_apps、mcp logout 副作用四个根因, 拆解可复现路径和修复矩阵, 一次把 session 救回来。
TL;DR: 你看到的”logout 吞 session”是什么
你在 Codex CLI 里跑了一会儿 MCP 工具, 突然第二轮调用全炸成 Transport closed, 或者一登出 / 切个 provider, 整个会话连同 MCP 服务器列表一起”被吞了”。看上去像 codex logout / codex mcp logout 这一个命令的锅, 实际是 4 个根因叠在一起:
- stdio MCP 在长会话里默默断连, 首轮成功、第二轮
Transport closed(issue #16899, v0.118.0 已确认) - 切到 custom provider 后 MCP 资源整体消失,
codex mcp list还能看到但 session 内调不到 (issue #19363) - 长会话 ChatGPT-auth 卡在启动期
codex_apps, 实际是 Cloudflare 返回 403 HTML 而不是 JSON (issue #19284) codex mcp logout <name>只擦 OAuth 凭据, 不主动重连, 接下来本轮所有指向该 server 的工具调用都会失败
所以”logout 吞 session”是个复合症状, 不是单一命令的 bug。这篇拆 4 个根因, 给一套可复现脚本 + 一份从快到慢的排查清单 + 修复矩阵。
如果你只想要救命方案, 直接跳到末尾 一键修复矩阵。
先把 “logout” 这个词在 Codex 里拆清楚
Codex CLI 里 logout 不是一个动作, 是三个动作, 作用对象完全不一样, 互相不能替代:
| 命令 | 作用对象 | 副作用 | 是否会”吞 session” |
|---|---|---|---|
codex logout |
顶级 auth (ChatGPT / API key) | 清 ~/.codex/auth.json 里的 access_token + refresh_token |
会让本进程后续调用全 401 |
codex mcp logout <name> |
某个 streamable HTTP MCP server 的 OAuth 凭据 | 清这个 server 的 OAuth token | 仅影响该 server, 但 session 不主动重连 |
codex mcp remove <name> |
~/.codex/config.toml 里的 MCP server 配置 |
写盘删配置, 下次启动不再加载 | 当前 session 仍能用, 但状态不一致 |
官方文档明确写了: OAuth 操作 (login, logout) 只对 streamable HTTP MCP servers 生效, 且仅当 server 本身支持 OAuth。stdio MCP servers 没有”登出”概念, 它们靠 env 注入 API key 或本地进程权限, codex mcp logout 对它们是空操作。
这一层先理清楚, 后面排查才不会瞎抓。Codex 配置体系本身的全貌可以参考 Codex CLI 完整入门: 安装、工作流、故障排查与 Claude Code 协同, 里面把 ~/.codex/ 目录结构画了一遍。
三个关键文件路径
~/.codex/config.toml— 全局配置, MCP server 列表写在[mcp_servers.<name>]段~/.codex/auth.json— token 存储, 含access_token/refresh_token/expires_at三个字段 (不走 keyring 时)~/.codex/sessions/— 单次会话的 transcript 文件, 是事后排查的第一现场
项目级也可以放 .codex/config.toml, 但只有把项目加进 trusted projects 才生效。这点很多人配完不生效是因为没标 trust。
根因一: stdio MCP 在长会话里默默断连
这是最常见、也最被误诊为”logout 副作用”的一种。
症状:
– 启动 codex 进入交互模式, 前两三轮跑 stdio MCP 工具都 OK
– 第 N 轮 (一般是叠了几次 retry 或一次大 burst) 之后, 同一个 session 里所有 stdio MCP 调用同时炸 Transport closed
– 退出重进 / 起新的 codex exec 子进程, 同样的 MCP server 又能正常用
根因侧写 (GitHub issue #16899 在 v0.118.0 复现):
– 不是 server 死了, 是 CLI 这边的 transport lifecycle 管理在长会话里出问题
– 怀疑是 connection pool 在某次 tool burst 之后被 poison 掉, 后续 reuse 时拿到的是已关闭的 pipe
– 表现上是”两个完全独立的 stdio MCP server 同时死掉”, 这强烈暗示问题在 CLI 侧而不是某个 server
为什么会被当成 logout 锅:
长会话里你大概率前面跑过 codex mcp login 或者切过 auth, 再叠一次 Transport closed, 直观感觉就是”我刚才登出了什么东西吧?” 实际上 stdio MCP 跟你的 OAuth 状态完全无关。
类似的”看起来像 auth 问题、实际是底层连接 / 进程问题”的坑, 在 Codex 历史里反复出现, 之前那个 OpenAI Codex 日志写入异常损耗 SSD 也是一个典型 — 用户先骂 OpenAI 风控, 最后查出来是日志写法。
根因二: 切到 custom provider 后 MCP 资源整体”消失”
症状 (issue #19363):
– codex mcp list / codex mcp get 都能看到 Context7 等 MCP server, status 是 enabled
– 用 OpenAI native provider 时 in-session 调用 OK
– 一旦切到 custom provider over Responses API, session 里这些 MCP 资源就调不到
根因侧写:
– Auth 状态显示是 Not logged in, 但功能性可用性问题跟 auth 无关
– 触发条件是 provider 切换本身, 不是 token 状态
– 推测 custom provider 的配置没有正确把 MCP server 初始化逻辑串进 session 启动流程
为什么会被当成 logout 锅:
你可能为了切 provider 跑了 codex logout, 然后 codex login 进 custom provider, 切完发现 MCP 全没了 — 顺序上 logout 在前, 锅就背上了。实际上跟 logout 一点关系没有, 它是 provider switch 路径的 bug。
如果你切 provider 是为了走第三方降智 API, 顺带看一下 OpenAI 限制第三方 API 推理能力?开发者发现推理 Token 遭压低 和 GitHub 开源 Codex 测试脚本, 验证 OpenAI 第三方客户端降智疑云, 现在多方在用脚本量化这件事, 跑之前心里有个底。
根因三: 长会话 ChatGPT-auth 卡在 codex_apps
症状 (issue #19284 / #20167):
– 启动 Codex CLI, 状态栏卡在 Starting MCP servers (2/3): codex_apps 几分钟不动
– 新开一个 shell 重新跑 codex, 启动飞快
– 同一个长跑了几天的 ChatGPT 登录 session 反复出现这个症状
根因侧写:
– 本地日志 (~/.codex/sessions/) 里能看到 apps/connectors discovery 请求拿回的不是 JSON, 而是 403 + Cloudflare 挑战 HTML 页面
– 这是 ChatGPT 那边对长会话 / 老 session 做的某种风控分级, 不是 Codex 本身的 bug, 但 Codex 的处理是”无限等”
– v0.136.0 (2026-06-01) 仍未修复 reconnect 类问题
为什么会被当成 logout 锅:
你看到 codex 卡死, 第一反应是 Ctrl-C 然后 codex logout && codex login 重启 — 这一刀确实能救活, 因为它把老的 ChatGPT session token refresh 了, 顺带 reset 了 Cloudflare 那边的判定。然后你就会得出”logout 治好了 session”的结论, 实际上是治好了 session-age-dependent 的 CF 风控。
ChatGPT 那边对账号 / session 的”风控分级”还有一些其他表现, 跨服务通用的, 类似情况看看 OpenAI 风控升级: 使用泰国个人邀请码及代理工具的账号遭删号, 那里讲了另一类被风控触发的代价。
根因四: codex mcp logout 真的会”吞 session”吗
直接回答: 不会吞整个 session, 但会让本轮所有指向该 server 的工具调用失败, 且不主动重连。
精确行为:
– codex mcp logout <name> 只删 ~/.codex/auth.json (或 keyring) 里属于这个 server 的 OAuth bundle (access_token / refresh_token / expires_at)
– session 自身的 transcript、message 历史、其他 MCP server 状态、stdio 子进程都不会被清
– 但: 当前 session 已经握着的那个 server 连接不会被主动 close 也不会主动重 auth, 后续模型如果还想调它的工具, 会拿一个无 token 的请求出去, 然后 401
– Codex 此时不会自动跳 OAuth 重 login, 你必须手动 codex mcp login <name> 然后通常需要重启 session 才能让 MCP 客户端拿到新 token
为什么会被当成”吞 session”:
– 因为 MCP server 调用失败之后, 模型链路上很多用户 prompt 都依赖 MCP 工具, 实际效果就是”AI 不会说人话了, 只回答说工具不可用”
– 用户体感上跟 session 失忆 / 被吞没区别
issue #4828 早期就有人吐这个体验, 后来 #26760 显示启动期 bearer-token auth 失败时 Codex 才学会建议跑 codex mcp login, 但 session 内的自动重 auth 至今没有。
如果你的诉求是给 Claude 系类 AI 工具加 MCP, 体感更顺的可以看 利用 MCP 协议, 开源项目让 ChatGPT 获得本地代码读写能力 和 Codex-Shim 更新: 支持 OpenAI-SDK 兼容, 强化 API Key 安全与 MCP 协议集成, 这俩走的是另一条路, 把 OAuth 这层风险降下来。
一套可复现的复现路径
把上面 4 个根因捏成一个最小复现脚本 (Linux/WSL2, Codex CLI 0.118.0+):
# 1. 准备两个 stdio MCP server (用本地 python 即可)
codex mcp add vault_search --env PYTHONUNBUFFERED=1 -- python3 ~/mcp_servers/vault_search.py
codex mcp add repo_search --env PYTHONUNBUFFERED=1 -- python3 ~/mcp_servers/repo_search.py
# 2. 启动交互 session, 前两轮调一下 MCP 工具
codex
# > "用 vault_search 找一下 X"
# > "用 repo_search 找一下 Y"
# 此时两个 server 都 OK
# 3. 触发"长会话" — 连续 10+ 轮带工具调用, 或一次大 burst
# > "重复执行 vault_search 找 A 找 B 找 C 找 D..." (一条 prompt 里塞多个工具调用)
# 4. 等下一轮再调 → 大概率 Transport closed
叠加根因三 (重现 CF 403):
– 把 session 挂上一晚上, 第二天早上启动新对话, 看 ~/.codex/sessions/<latest>.log, 大概率能抓到 403 HTML 响应
叠加根因二 (custom provider):
– 在 ~/.codex/config.toml 里加一个 custom provider (走 Responses API), codex login 切到它, 然后 codex mcp list 看 server 显示正常, in-session 调用却拿不到 — 复现率较高
单纯触发根因四:
codex mcp add notion-mcp --url https://mcp.notion.com/sse # streamable HTTP
codex mcp login notion-mcp # 走 OAuth
codex # 启动 session
# > "用 notion 把这页存到 X" ← 成功
# 另开 shell 跑:
codex mcp logout notion-mcp
# 回到 session > "再用 notion 把这页存到 Y" ← 401, 但 session 没被吞
排查清单 (从快到慢, 1 分钟到 10 分钟)
按这个顺序走, 70% 的”logout 吞 session”都能在前三步定位:
步 1: 看 codex mcp list 和 status
codex mcp list
# 输出每个 server 的 Status / Auth / Transport
- Status 是
enabled但 in-session 调不到 → 大概率 根因二 (provider switch) - Status 是
enabled, Auth 是Not logged in但 server 是 streamable HTTP → 根因四, 跑codex mcp login <name>再重启 session - Status 是
disabled→ 上一次手动codex mcp remove之后没重新 add
步 2: 看 ~/.codex/sessions/ 最近一个 log
ls -lt ~/.codex/sessions/ | head -5
tail -200 ~/.codex/sessions/<latest>.log | grep -E "Transport|403|Cloudflare|MCP"
- 抓到
Transport closed且多个 server 同时炸 → 根因一, 重启进程 - 抓到
403+CloudflareHTML → 根因三,codex logout && codex login - 抓到
401单个 server → 根因四,codex mcp login <name>+ 重启
详细的 log 字段含义 / 调试技巧, Codex 知识库那边有专门一篇 (Daniel Vaughan 维护), 用 codex --log-level debug 可以看到 transport handshake 的详细过程。
步 3: 验证是不是只挂当前 session
# 另开一个 shell
codex exec "用 vault_search 找 hello"
- 这步还能用 → 强证根因一, 不是 server / auth / 网络问题, 就是当前 session 的 transport 死了, 重启即可
- 这步也炸 → 不是 session 问题, 是 server 或 auth 或网络层
步 4: 看 ~/.codex/auth.json
cat ~/.codex/auth.json | python3 -m json.tool
- 看
expires_at, 已过期 → refresh token 出问题, 跑codex logout && codex login - 不存在 / 空 → 你确实 logout 了
- 看 MCP server 的 OAuth bundle 段是否还在 (有 mcp 子段)
步 5: 看 ~/.codex/config.toml
cat ~/.codex/config.toml
[mcp_servers.xxx]段缺失 →codex mcp remove干过- 段在但跟你期望不一样 → 手动编辑过没意识到
一键修复矩阵 (按根因分支)
按上面排查定位到根因后, 对症下药:
修根因一 (stdio 长会话断连)
# 直接退出当前 codex 进程, 起新 session
exit
codex
- 不需要动 auth, 不需要动 config
- 想长期规避: 把重活拆给
codex exec子进程, 主交互 session 只做轻量任务 - 等官方修, 关注 issue #16899
修根因二 (provider switch 丢 MCP)
# 临时方案: 切回 native provider
# 在 ~/.codex/config.toml 里把 default_provider 改回 openai
# 然后重启 codex
- 长期方案: 等 issue #19363 修复
- 如果非走 custom provider 不可: 用
codex exec一次性命令包住每个 MCP 调用, 别在长 session 里来回切
修根因三 (ChatGPT auth 卡 codex_apps)
codex logout
rm -f ~/.codex/auth.json
unset OPENAI_API_KEY
codex login
- 这套是官方文档明确给的 refresh auth 路径
- 跑完一定要新开 shell, 别在老 shell 里 retry (老进程拿的是老 token)
- 如果你的账号一直触发 CF 403, 看 开发者反馈 Codex 额度消耗异常快, Claude Pro 成替代主力, 不少人是在这种风控反复触发后转 Claude 的
修根因四 (mcp logout 副作用)
codex mcp login <server-name> # 重新 OAuth
# 然后必须重启 session
exit
codex
- 仅
codex mcp login不重启 session 是没用的, 当前 session 握的是 stale token - 如果你不想重启, 退而求其次用
codex exec子进程把那一次工具调用单独跑掉
避坑指南: 不让这事重演
总结成几条工程实践, 哥写文章时也尽量自检:
1. 不要在交互 session 里来回 codex logout / codex mcp logout
logout 是个高副作用动作, 该用的时机是”我要换账号 / 我要彻底重置”, 不是”我随手试试”。每一次 logout 在交互 session 里都至少要 + 一次 restart, 否则 session 处于”模型记忆还在但工具全废”的诡异状态。
2. 把 stdio MCP 跑在 codex exec 而不是交互 session
codex exec <prompt> 启一个新进程跑完即退, 不存在 connection pool poison 问题。重活 / 批量 / 需要稳定性的工作流, 都走 exec, 把交互 session 当成”轻量讨论 + 推 exec”的指挥台。
类似把 AI 工具串成长流水线的整体思路, 看 企业级 AI 编程实战: Codex 全流程解析与 MCP、Skills 深度应用, 那里有把 Codex + MCP + Skills 串成生产管线的章节。
3. 用 streamable HTTP MCP server 时, 启动期跑一次 codex mcp get <name>
确认 Auth 字段是 Logged in 再进 session, 别等模型调到那个 server 才发现 401。这一步成本几乎为 0, 能省下后面整轮重 session 的时间。
4. 给 ~/.codex/sessions/ 做定期清理
session log 是排查第一现场, 但堆多了会拖慢启动 (尤其上面提到的 codex_apps 启动期问题, 在老 session log 多时更易触发)。每周清一次, 或者按 Codex 知识库那一套日志调试方案做轮转。配合磁盘清理的全套, 还得防 Codex macOS code_sign_clone 占几十 GB 磁盘 那种悄悄涨的临时目录。
5. Mac / Intel 用户额外踩一遍 Node + Rosetta 路径
codex 是 Node 包, Intel Mac 上没装对 Node 或没走 Rosetta, 启动期更容易触发奇怪的 MCP 子进程问题。装机阶段就照 Codex CLI Intel Mac 安装指南: 版本、Node 与 Rosetta 走一遍, 后期排查能省一层。
6. 把 MCP server 列表写成可版本控制的脚本
把所有 codex mcp add ... 写成一个 setup_mcp.sh, 跟着项目走。手抖 codex mcp remove 之后能一键恢复, 也避免不同机器配置漂移。
7. 自己写的 stdio MCP server 加 heartbeat
如果你是 MCP server 作者: 在 server 内部加一个 1-2 分钟的 stdout heartbeat (按 MCP spec notification), 配合客户端 transport 的 keep-alive 检测, 能让客户端更早发现连接死了去主动重连, 而不是悄悄 poison 连接池。
8. MCP 桌面 Agent 选型也考虑稳定性
如果你的 use case 是本地文档 / CAD 这种重的, MCP 客户端不止 Codex 一家, 横比一下 寻找支持 MCP 协议的桌面 AI Agent: 现有工具在本地文档处理上存在短板 里提到的几款, 现在 stdio MCP 长会话稳定性是普遍痛点, Codex 不是最差的也不是最好的。
相关阅读
- Codex CLI 完整入门: 安装、工作流、故障排查与 Claude Code 协同 — Codex CLI 通识 + 完整故障排查目录
- 企业级 AI 编程实战: Codex 全流程解析与 MCP、Skills 深度应用 — Codex + MCP + Skills 在生产管线里的串法
- 大模型选型指南 2026: Claude/GPT/Gemini/Grok/DeepSeek 怎么选 — 写代码场景下 Codex (GPT 系) vs Claude Code 的选型决策
- 增强版 AI 浏览器自动化工具开源: 支持 MCP 协议与多 Agent 实例共享 — MCP 多 agent 实例共享的另一种实现路径
- 开发者公开 All in AI 半年实战日记: 从踩坑复盘到工具导航 — 同样是 Codex / Claude / MCP 这套技术栈的踩坑实录
FAQ
Q1: 我看 codex mcp list 显示 Auth: Not logged in, 但我没主动 logout 过, 怎么回事?
A: 两种可能。一是你重装过 Codex / 换过机器, OAuth bundle 没跨机器同步; 二是 OAuth refresh token 过期 (默认 90 天左右), Codex 在 expires_at 之后会把 Auth 字段降级显示。无论哪种, 跑 codex mcp login <name> 再重启 session 即可。
Q2: codex logout 之后我的 MCP server 配置会不会丢?
A: 不会。codex logout 只清 ~/.codex/auth.json 里的 ChatGPT/API 顶层 token, 不动 ~/.codex/config.toml。MCP server 配置完整保留, 但你 login 回来之后, 那些走 OAuth 的 streamable HTTP server 需要单独再 codex mcp login <name>。
Q3: Transport closed 在 stdio MCP 上反复出现, 重启也只是临时缓解, 有根治方案吗?
A: 截至 v0.136.0 (2026-06-01) 没有官方根治。短期缓解是”重活走 codex exec 子进程, 交互 session 只做轻量任务”。中期可以给 stdio MCP server 自己加 heartbeat, 让客户端早点感知断连。issue #16899 是跟进窗口。
Q4: 我切到第三方 API provider (走某 OpenAI 兼容服务) 之后 MCP 调不到, 是 provider 的 bug 还是 Codex 的 bug?
A: 大概率是 Codex 这边的 provider switch 路径在 MCP server 初始化上漏了一手 (issue #19363), 跟第三方 provider 没关系。临时方案是切回 OpenAI native provider; 必须走 custom 的话, 把每次 MCP 调用拆成 codex exec 一次性命令包住。
Q5: Codex 启动期一直卡 Starting MCP servers (2/3): codex_apps 怎么办?
A: 这是 ChatGPT-auth 长会话被 Cloudflare 风控 (返回 403 HTML), Codex 处理逻辑是无限等。修复路径: codex logout && rm -f ~/.codex/auth.json && unset OPENAI_API_KEY && codex login, 然后新开 shell 重启 codex。如果反复触发, 考虑账号 / 网络环境层面的风控因素。
Q6: 我能不能完全禁用 OAuth, 只用 API key + stdio MCP, 避免所有这些坑?
A: 可以。在 ~/.codex/config.toml 里把 provider 配成 API key 模式 (走 OPENAI_API_KEY env), 然后只 codex mcp add stdio 类 server (本地命令 + env 注入 API key)。这种配置下根因二 / 三 / 四基本规避, 只剩根因一 (stdio 长会话断连)。但代价是放弃了 ChatGPT 订阅额度走的便宜入口。
结语
“MCP 搞砸了 codex, 服务器 codex logout 吞 session” 这个标题本身就是一个症状语言, 不是根因语言。看上去像一个 bug, 实际上是 4 个 bug 叠在一起被用户体感汇成一种”session 不见了”的感受。Codex 在 MCP 这块还在快速迭代, v0.118 → v0.136 之间这几个 issue 都是 open 状态, 短期最有效的工程实践不是等修, 是把重活拆给 codex exec 子进程, 把交互 session 当指挥台。







