codex mcp login fails against TLS 1.3-only OAuth providers on macOS

Open 💬 2 comments Opened Apr 21, 2026 by andreaslordos

What version of the Codex App are you using?

Codex CLI 0.121.0 installed via npm install -g @openai/codex, and reproduced with npx -y @openai/codex@latest / 0.122.0.

What subscription do you have?

ChatGPT Business

What platform is your computer?

Darwin 25.3.0 arm64 arm

What issue are you seeing?

codex mcp login <server> fails against an MCP OAuth provider behind a TLS-1.3-only HTTPS endpoint on macOS.

The command fails immediately with:

Error: No authorization support detected

When discovery is forced through a local HTTP metadata shim, it reaches dynamic client registration and then fails with:

Error: Registration failed: Dynamic registration failed: Registration failed: HTTP request error: error sending request for url (...)

Root cause

The MCP OAuth login path builds a raw reqwest client here:

codex-rs/rmcp-client/src/perform_oauth_login.rs

let http_client = apply_default_headers(ClientBuilder::new(), &default_headers).build()?;

On macOS this can select the native TLS backend. I captured the ClientHello from released Codex and it did not advertise TLS 1.3:

{
  "handshake_version": "3.3",
  "supported_versions": [],
  "cipher_suites": [
    "00ff", "c02c", "c02b", "c024", "c023", "c00a", "c009", "c008",
    "c030", "c02f", "c028", "c027", "c014", "c013", "c012", "009d",
    "009c", "003d", "003c", "0035", "002f", "000a"
  ]
}

Against a TLS-1.3-only Cloudflare edge, the underlying reqwest/native-tls error is:

reqwest::Error {
  kind: Request,
  url: "https://someurl/oidc/register",
  source: hyper_util::client::legacy::Error(
    Connect,
    Error { code: -9836, message: "bad protocol version" }
  )
}

Repro

MCP config:

[mcp_servers.name]
url = "https://someurl.ai/mcp"

The server discovery metadata is reachable:

curl -i https://someurl.ai/.well-known/oauth-authorization-server/mcp
curl -i https://someurl.ai/.well-known/oauth-authorization-server

TLS checks:

openssl s_client -connect someurl.longlake.ai:443 \
  -servername someurl.longlake.ai \
  -tls1_3

succeeds.

openssl s_client -connect someurl.longlake.ai:443 \
  -servername someurl.longlake.ai \
  -tls1_2

fails with:

tlsv1 alert protocol version

Then:

codex mcp login --scopes name:all name

fails with:

Error: No authorization support detected

Expected behavior

Codex should negotiate TLS 1.3 and proceed to OAuth dynamic client registration / authorization URL generation.

Tested fix

Changing the OAuth login client construction to force rustls fixes the issue:

let http_client = apply_default_headers(
    ClientBuilder::new().use_rustls_tls(),
    &default_headers,
)
.build()?;

With that local patch, Codex advertises TLS 1.3 in the ClientHello:

{
  "supported_versions": ["TLS 1.3", "TLS 1.2"],
  "cipher_suites": ["1302", "1301", "1303", "..."]
}

and codex mcp login --scopes name:all name gets past discovery/DCR and prints the OAuth authorization URL.

Suggested fix: force rustls for the MCP OAuth login reqwest client in codex-rs/rmcp-client/src/perform_oauth_login.rs. It would also help to surface the underlying TLS error instead of collapsing it into No authorization support detected.

View original on GitHub ↗

2 Comments

taiqihe · 3 months ago

I can confirm this appears to affect more than the codex mcp login OAuth path.

I reproduced the same underlying macOS native-tls / reqwest failure in the MCP Streamable HTTP request path used after an MCP server is already configured with a bearer token. In my case, raw curl requests through the same local HTTP proxy succeed, including both HTTP/1.1 and HTTP/2 and the exact MCP initialize JSON body, but Codex fails before the MCP server loads with:

http/request failed: error sending request for url (...)

One detail: the failing Codex request was routed through a local HTTP proxy via HTTP_PROXY / HTTPS_PROXY. The same proxy successfully handles raw curl HTTPS requests to the MCP server. A local HTTP forwarder workaround also succeeds, which suggests the MCP server and JSON-RPC payload are not the failing pieces.

Using a small reqwest probe, the underlying source is the same as this issue:

reqwest::Error {
  kind: Request,
  source: hyper_util::client::legacy::Error(
    Connect,
    Error { code: -9836, message: "bad protocol version" }
  )
}

Forcing Codex's rustls path makes the same request reach the server. So the affected surface is not only:

codex-rs/rmcp-client/src/perform_oauth_login.rs

but also the executor-owned HTTP client used by MCP Streamable HTTP requests:

codex-rs/exec-server/src/client/reqwest_http_client.rs

A local patch fixes the Streamable HTTP case for me by changing the reqwest::Client construction in codex-rs/exec-server/src/client/reqwest_http_client.rs to call ClientBuilder::use_rustls_tls() before building the client. In other words, forcing this MCP HTTP request path onto rustls avoids the macOS native TLS bad protocol version failure. It would also be useful to preserve the reqwest source chain in http/request failed errors, since the current MCP startup error hides the underlying cause.

cjangrist · 4 days ago

Same root cause, different code path: this also breaks the core Responses API streaming connection (codex_http_client), not just codex mcp login's OAuth client. Wrote up a full packet-level repro (TLS ClientHello analysis, Alert: fatal, protocol_version decode, env details) here: https://github.com/openai/codex/issues/6874#issuecomment-5386407455 — reproduces on both interactive TUI and headless codex exec, on the latest release (0.149.0).