
Codex MCP 连接失败先别急着改配置Codex 接 MCP 服务时最常见的现象是客户端里显示连接失败、工具列表为空、调用工具时卡住或者日志里只有一句MCP server exited。这类问题不要一上来就怀疑 Codex本质上通常是 MCP 服务没有正常启动、命令路径不对、环境变量没带进去或者 stdio/端口通信方式配置错了。我的排查顺序一般是先确认 MCP 配置是否能被客户端读到再单独启动 MCP 服务接着查环境变量和网络请求最后看 Codex 或 MCP 服务的详细日志。按这个顺序走基本能定位到具体环节。1. 先检查 MCP 配置是否写对不同客户端的 MCP 配置文件位置不完全一样但结构大同小异。以常见的 stdio 方式为例配置通常长这样### token云桥中转 0029.org ### { mcpServers: { my-tools: { command: node, args: [ /Users/dev/mcp-server/dist/index.js ], env: { API_KEY: your_api_key } } } }这里最容易出错的是command和args。如果你写的是相对路径例如./dist/index.js在终端里能跑不代表 Codex 启动时也能跑。因为 Codex 启动 MCP 服务时的工作目录可能不是你的项目目录。建议把关键路径全部改成绝对路径{ command: /opt/homebrew/bin/node, args: [ /Users/dev/workspace/my-mcp/dist/index.js ] }Windows 下也一样不要只写node或python先确认真实路径where node where pythonmacOS / Linux 可以这样查which node which python32. 单独启动 MCP 服务看它到底能不能跑不要只在 Codex 里点连接。先把配置里的命令拿出来在终端中直接执行。/opt/homebrew/bin/node /Users/dev/workspace/my-mcp/dist/index.js如果是 Python MCP 服务/usr/bin/python3 /Users/dev/workspace/my-mcp/server.py正常的 stdio MCP 服务启动后可能不会输出太多内容甚至看起来像“卡住”。这不一定是错误因为它在等待客户端通过标准输入输出通信。但如果直接报错例如模块找不到、权限不足、端口占用、环境变量缺失就说明 Codex 连接失败只是表象。常见错误包括Cannot find module依赖没安装或者启动路径不对。permission denied脚本没有执行权限或目录权限不够。command not foundCodex 所在环境找不到 node、python、uv、npx 等命令。missing API key环境变量没有传入 MCP 进程。Node 项目先确认依赖cd /Users/dev/workspace/my-mcp npm install npm run buildPython 项目先确认虚拟环境和依赖cd /Users/dev/workspace/my-mcp python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt3. 环境变量不要只配在终端里很多人把 API Key 写在~/.zshrc或~/.bashrc里然后在终端测试没问题但 Codex 里就是连接失败。原因是图形客户端或插件进程不一定读取你的 shell 配置文件。稳妥做法是在 MCP 配置里显式写env{ mcpServers: { search-mcp: { command: /opt/homebrew/bin/node, args: [ /Users/dev/mcp/search/dist/index.js ], env: { OPENAI_API_KEY: sk-xxxx, OPENAI_BASE_URL: https://api.example.com/v1 } } } }如果你的 MCP 服务需要访问外部模型接口建议顺手把BASE_URL、代理地址、区域配置都写清楚。实际项目里我更倾向于用稳定的中转接口统一管理 Key 和额度比如 token 云桥 AI 中转站 0029.org尤其是团队里多人共用 MCP 工具时避免每台机器都散落一堆不同来源的 Key。这里注意按你的服务代码支持的变量名来写不要随便猜。4. 区分 stdio 连接和端口连接MCP 常见有两种连接方式一种是 stdio客户端负责启动 MCP 进程通过标准输入输出通信另一种是服务先启动在某个端口客户端再通过 HTTP、SSE 或 WebSocket 连接。stdio 模式stdio 模式下MCP 服务不要把普通调试日志写到 stdout。因为 stdout 是协议通道乱写日志可能导致 Codex 解析失败。日志最好写到 stderr 或文件。console.error(mcp server started);不要这样写大量调试内容console.log(debug message);如果服务一启动就输出 banner、进度条、彩色日志也可能污染协议输出。遇到这种情况先关掉无关输出。端口模式如果 MCP 服务是端口连接先确认端口真的在监听lsof -i :3000 curl http://127.0.0.1:3000/healthWindows 可以用netstat -ano | findstr 3000如果服务监听的是127.0.0.1同机访问没问题如果 Codex 跑在容器、远程环境或 WSL 里就可能访问不到。容器场景要特别注意localhost指向的是容器内部不是宿主机。5. 外部接口访问失败也会表现为 MCP 失败有些 MCP 服务启动成功了但初始化时会请求外部接口比如模型 API、搜索 API、数据库或公司内网服务。只要这些请求失败Codex 侧也可能显示 MCP 连接失败或工具不可用。先在同一个环境里测试网络curl -I https://api.example.com/v1/models如果需要代理确认代理变量是否传给 MCP 进程{ env: { HTTP_PROXY: http://127.0.0.1:7890, HTTPS_PROXY: http://127.0.0.1:7890 } }还要检查公司网络、防火墙、DNS。DNS 问题可以先试nslookup api.example.com ping api.example.com有些接口不允许ping所以ping不通不一定代表 HTTP 不通最终还是以curl为准。6. 打开日志别只看界面提示界面上的“连接失败”信息通常太粗。需要看 Codex 客户端日志和 MCP 服务自身日志。MCP 服务建议加一个简单的日志文件至少记录启动参数、关键环境变量是否存在、外部接口请求结果。import fs from fs; function log(msg) { fs.appendFileSync( /tmp/my-mcp.log, new Date().toISOString() msg \n ); } log(server starting); log(API_KEY exists: Boolean(process.env.API_KEY));注意不要把完整 API Key 写进日志只记录是否存在、长度或前后几位即可。排障结束后也建议清理临时日志避免凭据泄露。7. 重新加载配置和清理旧进程改完 MCP 配置后很多客户端不会自动重启 MCP 进程。最好完整重启 Codex或者手动杀掉旧的 MCP 进程。ps aux | grep mcp kill -9 pid端口模式下如果旧进程占着端口新配置怎么改都不会生效lsof -i :3000 kill -9 pid总结Codex MCP 连接失败优先按“配置路径、单独启动、环境变量、stdio/端口、外部网络、日志”这个顺序排查。大多数问题不是协议本身复杂而是 MCP 服务启动环境和你在终端里的环境不一致。把命令改成绝对路径把必要变量写进配置再用日志确认服务实际运行状态定位会快很多。