MCP HTTP/SSE (Rube/Composio) fails to start with 'request timed out' on macOS (Codex 0.29.0)

Resolved 💬 2 comments Opened Sep 5, 2025 by danialhasan Closed Sep 9, 2025
💡 Likely answer: A maintainer (Bit-urd, contributor) responded on this thread — see the highlighted reply below.

Title: MCP HTTP/SSE servers (Rube/Composio) fail to start with "request timed out" in Codex CLI on macOS

Summary

  • Attempting to use the Rube (Composio) MCP hub via its MCP URL https://rube.app/mcp with Codex CLI.
  • Direct transport = "http" + url = … in ~/.codex/config.toml is rejected (schema expects stdio command).
  • Implemented stdio→HTTP/SSE proxy (first Deno, then Node 20) to bridge Codex to Rube. Codex still reports timeouts when starting the MCP client.
  • Even after providing the signed token from Rube (Authorization or X-API-Key), Codex shows: MCP client for 'rube' failed to start: request timed out.

Steps to Reproduce
1) Add an MCP entry (stdio) that launches a small proxy which forwards to https://rube.app/mcp over Streamable HTTP with SSE fallback.

[mcp_servers.rube]
command = "/Users/danialhasan/.nvm/versions/node/v20.19.0/bin/node"
args = [
  "/Users/danialhasan/Desktop/dev.nosync/scripts/rube-proxy-node/index.mjs"
]
# Token redacted; header can be Authorization or X-API-Key depending on provider docs
env = { RUBE_URL = "https://rube.app/mcp", RUBE_TOKEN = "<redacted>", RUBE_AUTH_HEADER = "Authorization" }

2) Restart Codex CLI and open a session.
3) Observe error in TUI: 🖐 Failed to create MCP connection manager: request timed out (and/or MCP client for 'rube' failed to start: request timed out).
4) Proxy stderr with invalid token shows 401 from SSE; with token provided, Codex still times out at startup.

Expected

  • Codex should support HTTP/Streamable HTTP/SSE MCP servers natively (e.g., transport = "http" with url and headers), or at least not time out when a stdio proxy is used.
  • On auth/network errors from the remote MCP server, surface the HTTP status/message instead of a generic startup timeout.

Actual

  • Codex fails to initialize the MCP connection with a generic timeout.
  • No actionable error details are surfaced in the TUI; proxy logs show SSE/HTTP behavior but Codex reports only a timeout.

Environment

  • macOS 15.2 (arm64)
  • Codex CLI 0.29.0
  • Node.js v20.19.0 for stdio proxy (also tried Deno 2.4.4)
  • Deno and Node proxies both attempted; Node 20 used to avoid older Node fetch/stream incompatibilities

Additional Notes / Attempts

  • Direct TOML with transport = "http" + url was rejected by Codex config parser (requires [mcp_servers.<name>] with command).
  • Deno-based stdio proxy worked functionally but still resulted in request timed out from Codex.
  • Node-based proxy (using @modelcontextprotocol/sdk 1.17.5) connects in background; still see Codex timeout on client start with valid token and header.

Related Issues

  • #2129 Feature Request: Native SSE transport support for MCP servers
  • #2320 SSE based MCP servers are non-configurable
  • #2550 feat: enable Streamable HTTP MCP servers & lazy loading of tools
  • #2555 Windows 11: MCP server (Context7) fails with “request timed out”
  • #3182 feat(mcp): per-server timeout and capture server stdout/stderr
  • #2346 Make MCP Request timeout configurable

Request

  • Add native support for HTTP/Streamable HTTP/SSE MCP servers in ~/.codex/config.toml (e.g., transport = "http", url, and headers).
  • Improve error propagation so Codex surfaces HTTP status (401/403/405) and response body from remote MCP servers on startup.
  • Document recommended auth header handling for HTTP MCP (Authorization vs X-API-Key) with examples.
  • Consider a per-server configurable connect timeout and retry policy.

Happy to provide a minimal proxy repo or more logs if helpful.

View original on GitHub ↗

2 Comments

Bit-urd contributor · 11 months ago

@bolinfest This was my case in the PR you merged [https://github.com/openai/codex/pull/3243] , and your change works
perfectly — it resolves the my issue case in a clean way. Thanks for the review!

We need this defensive Err(e) branch because McpClient::new_stdio_client()
covers business logic errors as (server_name, Err(error)), but task-level
failures (panic/cancellation) surface as JoinError. Without handling JoinError,
a single faulty MCP server could crash the entire connection manager and block
other servers from initializing.
Here’s a concrete example I ran into while debugging list_all_tools():

while let Some(join_res) = join_set.join_next().await {
    match &join_res {
        Ok((server_name, _)) => {
            debug!("Join result OK for server: {}", server_name);
        }
        Err(e) => {
            error!("JoinError detected - task panic/cancelled: {e:#}");
            error!(
                "JoinError details - is_cancelled: {}, is_panic: {}",
                e.is_cancelled(),
                e.is_panic()
            );
            // Without defensive handling, this would crash
        }
    }

    let (server_name, list_result) = join_res?;
    // Original code crashes here on JoinError
}

my debug log:

2025-09-08T17:24:57.022282Z DEBUG Successfully got join result for server: mcp-obsidian
2025-09-08T17:24:57.022286Z DEBUG Server 'mcp-obsidian' returned 12 tools
2025-09-08T17:24:57.022291Z DEBUG Successfully processed list_tools result for server: mcp-obsidian
2025-09-08T17:25:07.020117Z ERROR Failed to list tools for server 'shrimp-task-manager': request timed out
2025-09-08T17:25:07.020403Z DEBUG Processing join result from task
2025-09-08T17:25:07.020430Z DEBUG Join result OK for server: shrimp-task-manager
2025-09-08T17:25:07.020456Z DEBUG Successfully got join result for server: shrimp-task-manager
2025-09-08T17:25:07.020475Z ERROR list_tools failed for server 'shrimp-task-manager': request timed out
2025-09-08T17:25:07.020494Z ERROR About to propagate list_tools error - this will cause the function to return early
2025-09-08T17:25:07.021038Z ERROR Failed to create MCP connection manager: request timed out
bolinfest collaborator · 11 months ago

https://github.com/openai/codex/releases/tag/rust-v0.31.0 now supports startup_timeout_ms, so please use that!