Codex Desktop authenticates OAuth MCP server but never imports tools into threads; auth_status stays unsupported

Open 💬 6 comments Opened Apr 28, 2026 by Matt-TravelStorys
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

Codex Desktop 0.125.0-alpha.3 is shown in local session metadata as the active CLI/app runtime.

What subscription do you have?

Unknown from the app logs on this machine.

What platform is your computer?

macOS (Darwin, Apple Silicon). The workspace is local.

What issue are you seeing?

Codex Desktop successfully adds and authenticates a streamable HTTP MCP server, but never surfaces that server's tools in any thread.

What works:

  • codex mcp add <server-name> --url <streamable-http-mcp-url>
  • codex mcp login <server-name>
  • OAuth completes successfully multiple times
  • codex mcp list --json shows the server is present and enabled
  • Manually calling tools/list with the same bearer token Codex obtained returns the expected tool list from the MCP server

What fails:

  • codex mcp list --json reports "auth_status": "unsupported"
  • Codex Desktop threads never receive any dynamic tool entries for the configured MCP server
  • Restarting Codex Desktop does not help
  • Removing the server, re-adding it, and re-authing from scratch does not help

This makes the server look configured and authenticated, but it is never actually imported into the thread tool registry.

Steps to reproduce

  1. Add a streamable HTTP MCP server that advertises OAuth:
  • codex mcp add <server-name> --url <streamable-http-mcp-url>
  1. Authenticate it:
  • codex mcp login <server-name>
  1. Complete the browser OAuth flow
  2. Start a new Codex Desktop thread or restart Codex Desktop
  3. Ask the thread whether the MCP server's tools are available

Expected behavior

After successful OAuth, Codex Desktop should import the MCP server's tools into new threads.

Actual behavior

The server remains visible in MCP config, but no tools from that MCP server are exposed in threads.

Evidence

codex mcp list --json returns:

[
  {
    "name": "<server-name>",
    "enabled": true,
    "disabled_reason": null,
    "transport": {
      "type": "streamable_http",
      "url": "<streamable-http-mcp-url>",
      "bearer_token_env_var": null,
      "http_headers": null,
      "env_http_headers": null
    },
    "startup_timeout_sec": null,
    "tool_timeout_sec": null,
    "auth_status": "unsupported"
  }
]

~/.codex/config.toml contains:

[mcp_servers.<server-name>]
url = "<streamable-http-mcp-url>"

Local thread state shows no dynamic tool entries for the configured MCP server at all. Recent threads only have built-in tools like:

  • automation_update
  • read_thread_terminal
  • load_workspace_dependencies
  • install_workspace_dependencies

In the local SQLite state DB (~/.codex/state_5.sqlite), the thread_dynamic_tools table never gets an entry for the configured MCP server in recent threads.

Also, the server itself appears healthy:

  • Unauthenticated tools/list returns 401 Unauthorized
  • The server advertises OAuth metadata correctly
  • Manual tools/list with the same Codex-issued bearer token succeeds and returns the expected MCP tool list

That suggests the server is not the problem; the issue appears to be in Codex Desktop/CLI auth classification or MCP tool import after login.

Additional notes

  • codex mcp login <server-name> succeeds repeatedly, but codex mcp list --json still reports "auth_status": "unsupported"
  • There is no legacy ~/.codex/.credentials.json on this machine
  • The visible ~/.codex/auth.json does not expose a named top-level credential entry for the configured MCP server

View original on GitHub ↗

6 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #18527
  • #19649
  • #19425

Powered by Codex Action

jm-fhc · 1 month ago

I am seeing what looks like the same MCP tool-injection failure on macOS / Codex Desktop.

Environment:

  • macOS 26.5 (25F71)
  • Codex CLI/runtime: codex-cli 0.136.0-alpha.2
  • Product surface: Codex Desktop

Configured streamable HTTP MCP servers:

  • jt-datax at https://ai.winyourdata.com/mcp
  • jobtread_native at https://api.jobtread.com/mcp

Observed behavior:

  • codex mcp list shows both servers enabled.
  • Both show Auth: Unsupported.
  • codex mcp get jobtread_native shows enabled: true, transport: streamable_http, and the expected URL.
  • The active thread is a user thread with local cwd /Users/joshmcculloch/Documents/Codex.
  • Current thread tool discovery does not expose either server's tools.
  • The local thread_dynamic_tools table has no JobTread MCP tools for the active thread.

This does not appear to be only a server-health/config issue: after OAuth, a fresh post-login thread previously exposed the DATAx JobTread tools and successfully completed a minimal read-only organization metadata call. Later, the long-running coordination thread could no longer see either the DATAx tools or the newly configured native JobTread tools.

Impact:

  • Long-running coordination / command-centre threads lose the ability to refresh JobTread current state.
  • Creating a fresh thread as a workaround defeats the purpose of a persistent coordination thread and loses context.
  • From inside the agent, this can be confused with "no relevant source data" unless the agent separately inspects MCP config and thread tool metadata.

Requests:

  • Add a diagnostic that distinguishes: MCP server configured, authenticated, initialized, tools discovered, tools injected into current thread, and tool call executable.
  • Clarify whether existing threads should refresh MCP tools after OAuth/config changes.
  • Fix or document why enabled streamable HTTP MCP servers can show Auth: Unsupported and fail to inject tools into threads.
JohnnyDevNull · 1 month ago

I have the same problem with the GitLab MCP Server authenticated with OAuth.
It's shows up connected in the mcp server overview in the desktop app, but not available in the Session.

When I do the login via console it works just one time but after that not accessible through any session or thread because of an json-parse error.

On one of my colleague's MacBook Pro this works perfectly fine with Claude Code Desktop, but not with Codex on my MacBook.

The first step works:

codex mcp add --url "https://gitlab.com/api/v4/mcp" GitLab

Added global MCP server 'GitLab'.
Detected OAuth support. Starting OAuth flow…
Authorize `GitLab` by opening this URL in your browser:
https://gitlab.com/oauth/authorize?response_type=code&client_id=[...]

Successfully logged in.

A mcp login then wants another OAuth again:

codex mcp login GitLab

Authorize `GitLab` by opening this URL in your browser:
https://gitlab.com/oauth/authorize?response_type=code&client_id=[...]

Successfully logged in to MCP server 'GitLab'.

The mcp list shows it as enabled after that:

codex mcp list

Name       Url                               Bearer Token Env Var  Status   Auth 
GitLab     https://gitlab.com/api/v4/mcp     -                     enabled  OAuth
atlassian  https://mcp.atlassian.com/v1/mcp  -                     enabled  OAuth

Now when i open the cli it shows an error:

⚠ MCP client for `GitLab` failed to start: MCP startup failed: handshaking with MCP server failed: Send message error Transport [rmcp::transport::worker::WorkerTransport<rmcp::transport::streamable_http_client::StreamableHttpClientWorker<rmcp::transport::auth::AuthClient<codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter>>>] error: Deserialize error: data did not match any variant of
  untagged enum JsonRpcMessage, when send initialize request

⚠ MCP startup incomplete (failed: GitLab)
````

Tools are not available:

/mcp

🔌 MCP Tools

• GitLab
• Auth: OAuth
• Tools: (none)


dnsmichi · 1 month ago

I've cloned this repo and asked Codex about this bug report issue, and feedback in https://gitlab.com/gitlab-org/gitlab/-/work_items/561564#note_3415658534 I cannot reproduce the problem in my environment (macOS Tahoe 26.5.1, Codex 0.131.0 - 0.136.0, GitLab.com 19.0 - 19.1. macOS Tahoe 26.5.1, Codex 0.131.0 - 0.136.0, GitLab.com 19.0 - 19.1.).

It seems that the streamable HTTP messages are directly parsed as JSON-RPC, swallowing other message formats like JSON formatted error messages from the server-side, which could help explain the current behavior in https://github.com/openai/codex/issues/20009#issuecomment-4611123594

Here's the full analysis summary with Codex help, and a suggested patch for debugging. I am a beginner with Codex 's code base, so this might not work immediately.

From the Codex error: ``text AuthClient<codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter> ... Deserialize error: data did not match any variant of untagged enum JsonRpcMessage, when send initialize request ` Codex appears to have reached the OAuth-authenticated MCP transport. The failure happens during the streamable HTTP initialize request: Codex expects the response body to be a valid MCP JSON-RPC message, but the response is JSON that does not match JSON-RPC. A likely example would be a GitLab/Rails error payload such as: {"message":"404 Not Found"}or another non-MCP JSON error envelope. In that case Codex currently reports a JSON-RPC deserialization failure instead of the underlying HTTP/status/body. A useful next step is to capture Codex debug logs: mkdir -p /tmp/codex-mcp-debug RUST_LOG='codex_rmcp_client=trace,codex_mcp=trace,rmcp=trace,codex_core=debug' \ codex -c log_dir=/tmp/codex-mcp-debug Then reproduce the GitLab MCP startup failure and inspect: /tmp/codex-mcp-debug/codex-tui.log` However, Codex may still not log the exact response body before deserialization. If needed, the Codex side should add temporary logging around the HTTP JSON response handling to print status, content-type, and a sanitized body before parsing it as MCP JSON-RPC.
``rust • diff --git a/codex-rs/rmcp-client/src/http_client_adapter.rs b/codex-rs/rmcp-client/src/http_client_adapter.rs index 1234567890..abcdef1234 100644 --- a/codex-rs/rmcp-client/src/http_client_adapter.rs +++ b/codex-rs/rmcp-client/src/http_client_adapter.rs @@ -191,8 +191,22 @@ impl StreamableHttpClient for StreamableHttpClientAdapter { } Some(content_type) if content_type.starts_with(JSON_MIME_TYPE) => { let body = collect_body(&mut body_stream).await?; - let message: ServerJsonRpcMessage = - serde_json::from_slice(&body).map_err(StreamableHttpError::Deserialize)?; + let message: ServerJsonRpcMessage = match serde_json::from_slice(&body) { + Ok(message) => message, + Err(error) => { + tracing::warn!( + status = response.status, + content_type, + session_id = session_id.as_deref().unwrap_or("<none>"), + mcp_method = mcp_method.as_deref().unwrap_or("<none>"), + mcp_request_id = mcp_request_id.as_deref().unwrap_or("<none>"), + has_authorization_header, + body_preview = %body_preview(String::from_utf8_lossy(&body).to_string()), + "streamable HTTP JSON response did not deserialize as MCP JSON-RPC" + ); + return Err(StreamableHttpError::Deserialize(error)); + } + }; Ok(StreamableHttpPostResponse::Json(message, session_id)) } _ => { `` And re-run with debug logging again. This is probably not macOS-specific and not a SQLite/tool-import issue. It looks like GitLab MCP returns a non-JSON-RPC response during initialize, possibly due to 404/prerequisite/tier/Duo/ feature gating or another server-side error path after OAuth.
billypostleBBC · 1 month ago

Adding another reproduction, this time with Webflow's official remote OAuth MCP server.

Environment:

  • Codex Doctor: Codex Doctor v0.140.0-alpha.19 · macos-aarch64
  • Runtime from doctor: 0.140.0-alpha.19
  • Codex Desktop / app context
  • macOS: Mac OS 26.5.1 [64-bit]
  • Machine locale: en-GB
  • Server: webflow
  • Transport: streamable_http
  • URL: https://mcp.webflow.com/mcp

Configured MCP server:

[mcp_servers.webflow]
enabled = true
url = "https://mcp.webflow.com/mcp"

Observed behavior:

  1. codex mcp list shows Webflow as configured, enabled, and OAuth-backed:
Name     Url                          Bearer Token Env Var  Status   Auth
webflow  https://mcp.webflow.com/mcp  -                     enabled  OAuth
  1. codex mcp get webflow shows:
webflow
  enabled: true
  transport: streamable_http
  url: https://mcp.webflow.com/mcp
  bearer_token_env_var: -
  http_headers: -
  env_http_headers: -
  1. codex doctor --summary reports MCP configuration as healthy:
✓ mcp  4 server (2 stdio, 2 streamable_http) · 0 disabled
  1. I then reset auth locally:
codex mcp logout webflow
codex mcp login webflow

The login flow completed successfully:

Removed OAuth credentials for 'webflow'.
Successfully logged in to MCP server 'webflow'.
  1. After successful re-auth, codex mcp list still shows:
webflow  https://mcp.webflow.com/mcp  -  enabled  OAuth
  1. However, the current/new Codex desktop thread still has no callable Webflow tools. Inspecting local thread tool state:
select count(*)
from thread_dynamic_tools
where lower(coalesce(namespace,'') || ' ' || name || ' ' || description) like '%webflow%';

returns:

0

I also rendered a model-visible prompt input locally and searched it for Webflow/MCP tool references. It contains no Webflow tool namespace or Webflow tool instructions, despite the server being configured and re-authenticated.

Impact:

  • From the user's point of view, Webflow MCP is installed correctly and OAuth succeeds.
  • Codex confirms the server is enabled.
  • doctor confirms MCP config is healthy.
  • But new desktop threads cannot call Webflow at all because the tools are never exposed to the model/thread.

This looks like the same class of issue described here, but with Webflow's official MCP and a current mcp list output that reports Auth: OAuth rather than Auth: Unsupported.

Expected behavior:

  • After successful codex mcp login webflow, new Codex desktop threads should expose Webflow MCP tools.
  • If tool import fails, the desktop app/thread should show a specific MCP startup/import error instead of silently omitting the tool namespace.

Actual behavior:

  • Webflow remains enabled and OAuth-authenticated according to the CLI.
  • No Webflow tools are imported into the thread tool registry.
  • The model has no callable webflow/mcp__webflow__... namespace.
Necmttn · 29 days ago

This needs a thread-level MCP import state, separate from auth. For each server, show configured, auth complete, initialize ok, tools/list ok, schema accepted, injected into thread, and model-visible. Include last error at each stage. That would distinguish OAuth success from tool-registry failure without making users manually replay tools/list with the bearer token.

---

_Generated with ax._