What version of Codex CLI is running?
codex-cli 0.130.0
What platform is your computer?
Darwin 24.6.0 arm64
What issue are you seeing?
For Streamable HTTP MCP servers with saved OAuth credentials, Codex can hang before sending initialize when the OAuth metadata/bootstrap path is unreachable or hanging. startup_timeout_sec does not appear to apply to this pre-initialize OAuth path.
This is especially visible for VPN-only MCP servers:
- When the MCP is
auth_status: not_logged_in, Codex uses plain HTTP startup (initialize, tools/list) and fails fast if the VPN-only endpoint is unreachable.
- When the same MCP is
auth_status: o_auth because saved OAuth credentials exist, Codex performs OAuth bootstrap before initialize. If VPN is off, it can hang before the normal MCP startup timeout applies.
Repro
Use a Streamable HTTP MCP config with a low startup timeout:
mcp_oauth_credentials_store = "file"
[mcp_servers.local_timeout_config_test]
url = "http://127.0.0.1:<port>/mcp"
startup_timeout_sec = 3
Run a local test server that:
- Accepts OAuth metadata requests like
GET /.well-known/oauth-authorization-server/mcp but never responds, simulating a VPN-off / unreachable OAuth bootstrap path.
- Allows unauthenticated MCP startup requests on
/mcp (initialize, tools/list) if Codex reaches them.
Compare two cases:
- No saved MCP OAuth token for this server.
- A saved MCP OAuth token exists in the configured MCP credentials store for this server.
Observed behavior
No saved token:
GET /.well-known/oauth-authorization-server/mcp
GET /mcp/.well-known/oauth-authorization-server
GET /.well-known/oauth-authorization-server
POST /mcp initialize no Authorization
POST /mcp notifications/initialized no Authorization
POST /mcp tools/list no Authorization
DELETE /mcp no Authorization
Codex eventually reaches plain MCP startup.
Saved OAuth token:
GET /.well-known/oauth-authorization-server/mcp
Codex never sends initialize or tools/list. In my controlled test, the process was still stuck after 12 seconds even though startup_timeout_sec = 3.
Expected behavior
Either:
startup_timeout_sec should cover pre-initialize OAuth transport/bootstrap work, or
- the OAuth bootstrap path should have its own bounded timeout and return an actionable MCP startup error.
With startup_timeout_sec = 3, Codex should not remain stuck indefinitely before initialize.
Why this matters
A user who has previously run codex mcp login <server> can get worse startup behavior than a first-time/not-logged-in user. For VPN-only MCP servers, saved OAuth credentials cause Codex to enter a pre-initialize OAuth path that can hang when the VPN is off. The workaround is to run codex mcp logout <server> before starting Codex off VPN, which restores the plain startup/fail-fast path, but that is surprising and easy to miss.
Additional context
From reading the current open-source Codex code, the timeout seems to wrap the MCP handshake after the client/transport is created. In the saved-token case, Codex loads OAuth tokens and creates the OAuth-wrapped transport before the normal initialize/handshake timeout is applied. That appears to be the timeout boundary causing this behavior.
Related but not exact issues I found:
What version of Codex CLI is running?
codex-cli 0.130.0What platform is your computer?
Darwin 24.6.0 arm64What issue are you seeing?
For Streamable HTTP MCP servers with saved OAuth credentials, Codex can hang before sending
initializewhen the OAuth metadata/bootstrap path is unreachable or hanging.startup_timeout_secdoes not appear to apply to this pre-initialize OAuth path.This is especially visible for VPN-only MCP servers:
auth_status: not_logged_in, Codex uses plain HTTP startup (initialize,tools/list) and fails fast if the VPN-only endpoint is unreachable.auth_status: o_authbecause saved OAuth credentials exist, Codex performs OAuth bootstrap beforeinitialize. If VPN is off, it can hang before the normal MCP startup timeout applies.Repro
Use a Streamable HTTP MCP config with a low startup timeout:
Run a local test server that:
GET /.well-known/oauth-authorization-server/mcpbut never responds, simulating a VPN-off / unreachable OAuth bootstrap path./mcp(initialize,tools/list) if Codex reaches them.Compare two cases:
Observed behavior
No saved token:
Codex eventually reaches plain MCP startup.
Saved OAuth token:
Codex never sends
initializeortools/list. In my controlled test, the process was still stuck after 12 seconds even thoughstartup_timeout_sec = 3.Expected behavior
Either:
startup_timeout_secshould cover pre-initialize OAuth transport/bootstrap work, orWith
startup_timeout_sec = 3, Codex should not remain stuck indefinitely beforeinitialize.Why this matters
A user who has previously run
codex mcp login <server>can get worse startup behavior than a first-time/not-logged-in user. For VPN-only MCP servers, saved OAuth credentials cause Codex to enter a pre-initialize OAuth path that can hang when the VPN is off. The workaround is to runcodex mcp logout <server>before starting Codex off VPN, which restores the plain startup/fail-fast path, but that is surprising and easy to miss.Additional context
From reading the current open-source Codex code, the timeout seems to wrap the MCP handshake after the client/transport is created. In the saved-token case, Codex loads OAuth tokens and creates the OAuth-wrapped transport before the normal
initialize/handshake timeout is applied. That appears to be the timeout boundary causing this behavior.Related but not exact issues I found: