Desktop thread can omit configured remote OAuth MCP server from mounted tools with no auth prompt or error
What version of the Codex App are you using (From “About Codex” dialog)?
0.122.0-alpha.1
What subscription do you have?
Pro
What platform is your computer?
macOS 15.7.4 (24G517), arm64
What issue are you seeing?
A configured and enabled remote OAuth MCP server can be present in local Codex config, reachable on the network, and still be completely absent from the mounted tool catalog for a new thread.
In my case, the server is Bridge Town:
[mcp_servers.bridge_town]
enabled = true
url = "https://api.bridgetown.builders/mcp"
and it is also present in the local factory MCP config.
However, in a fresh Codex desktop thread, Bridge Town is not exposed as a callable tool at all. There is also no OAuth prompt, no auth-needed error, and no tool-mount error surfaced in the thread.
So from the user side this looks like: “MCP is enabled, server is up, but Codex silently does not mount it into the thread.”
What steps can reproduce the bug?
- Configure a remote OAuth MCP server in local Codex config, for example:
[mcp_servers.bridge_town]
enabled = true
url = "https://api.bridgetown.builders/mcp"
- Start a fresh Codex desktop thread in a trusted workspace.
- Ask Codex to use that MCP in the thread.
- Observe that the MCP tool namespace is not available in the thread at all.
- Observe that there is no OAuth login prompt and no explicit auth error.
- Independently verify the endpoint is reachable and advertising OAuth protection:
curl -I https://api.bridgetown.builders/mcp
HTTP/2 401
www-authenticate: Bearer resource_metadata="https://api.bridgetown.builders/.well-known/oauth-protected-resource"
What is the expected behavior?
One of these should happen:
- Codex mounts the MCP tools into the thread and lets me authenticate.
- Codex surfaces a clear “auth required / login needed” state for that server.
- Codex surfaces a clear tool-mount failure / MCP initialization error.
What should not happen is silent omission of the configured MCP from the thread’s callable tools.
Actual behavior
The thread only gets the built-in tools and the configured MCP never appears as a callable tool namespace.
In the failing thread, the mounted dynamic tools were only:
automation_updateread_thread_terminalload_workspace_dependenciesinstall_workspace_dependencies
No Bridge Town or other MCP tool namespace was mounted.
Additional information
- The relevant thread id on my machine was
019da3b9-640f-7153-ba9c-2b34b0a1db91. - Local config definitely contains the enabled server.
- The Bridge Town endpoint was reachable and returned an OAuth-protected
401, so this does not look like a basic network outage. - The failure mode is specifically that the server is not exposed into the thread as tools, and the app gives no actionable reason.
This feels closely related to existing MCP exposure issues, but the important distinction here is:
- remote HTTP MCP
- OAuth-protected endpoint
- server reachable
- still not mounted into the thread tool catalog
- no auth handoff / prompt / explicit error
If this is expected behavior, Codex should at least surface that clearly in the thread or MCP status UI.
6 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional local evidence from the failing machine/thread, in case it helps triage:
list_mcp_resourcesbeing empty. I checked the local thread tool registry directly in Codex state.For failing thread
019da3b9-640f-7153-ba9c-2b34b0a1db91,thread_dynamic_toolscontained only:automation_updateread_thread_terminalload_workspace_dependenciesinstall_workspace_dependenciesThere was no Bridge Town namespace and no other MCP-derived tool namespace mounted into the thread.
019d53d2-de75-7542-8f47-c92b5cff9e4a019d86f6-69f9-7bf2-b21b-b29ef96c3f1d019d9f1b-8dc3-7623-adea-216e786819f0019da3b3-7332-7071-abb0-9b17d2225e42019da3b4-dabb-7a30-a129-978fcbe33746019da3b9-640f-7153-ba9c-2b34b0a1db91So this does not look like a one-off thread corruption.
~/.codex/config.tomlcontains:~/.factory/mcp.jsoncontains:HTTP/2 401www-authenticate: Bearer resource_metadata="https://api.bridgetown.builders/.well-known/oauth-protected-resource"That suggests the server is reachable and advertising the expected OAuth metadata, but Codex still never mounts it into the thread or offers an auth handoff.
This feels adjacent to:
MCP servers not detected in Codex VS Code extension (but working in Codex CLI))Desktop app does not expose local stdio MCP server until cwd is set explicitly)The difference here is that this is a remote HTTP MCP with OAuth rather than a local stdio server. The common symptom is silent non-exposure in the tool catalog.
Even if the intended behavior is “don’t mount until authenticated,” it would still be much better to surface that explicitly in the thread or MCP status UI rather than silently omitting the server.
I dug through the public codebase and there looks to be a real asymmetry between plugin MCP OAuth and ordinary configured remote MCP OAuth.
Likely path for this bug:
codex-rs/app-server/src/codex_message_processor/plugin_mcp_oauth.rsviastart_plugin_mcp_oauth_logins(...), which callsperform_oauth_login_silent(...)and emitsMcpServerOauthLoginCompleted.codex-rs/core/src/session/mcp.rs->codex-rs/codex-mcp/src/mcp_connection_manager.rs->codex-rs/rmcp-client/src/rmcp_client.rs.RmcpClient::create_pending_transport(...), a streamable HTTP MCP server only gets an OAuth-aware transport if there are already stored OAuth tokens (or an explicit bearer token/header). If there are no stored tokens, Codex builds a plain unauthenticatedStreamableHttptransport.StreamableHttpResponseClient::post_message(...), a401withWWW-AuthenticatebecomesStreamableHttpError::AuthRequired(...).mcp_connection_manager.rs, which currently formats the auth-required case as:The {server_name} MCP server is not logged in. Run \codex mcp login {server_name}\.So the probable product gap is:
codex_appsMCPs also do not have the startup snapshot fallback used forcodex_apps, so auth failure can leave them simply absent from the mounted tool list.That matches the Bridge Town behavior here exactly: reachable OAuth-protected MCP endpoint, no auth prompt in desktop, and no mounted tool namespace in-thread.
I have not yet proven the final UI wiring end-to-end, so I’d phrase this as a strong root-cause hypothesis rather than a confirmed single-line fix, but the code paths above seem like the right place to look first.
Probable fix directions:
codex_appsremote MCPs need a better startup/tool-visibility fallback when auth is pending or incomplete.Adding a more concrete diagnostic + patch sketch after reading a bit more of the OSS code/docs.
Diagnostic I’d add
StreamableHttpserver fails becauseStreamableHttpError::AuthRequired(...)bubbles up during handshake, emit a first-class “auth required / not logged in” reason all the way to app-server / UI instead of only formatting the generic startup error string inmcp_init_error_display(...).streamable_http)oauth_login_support(...)/discover_streamable_http_oauth(...))NotLoggedInvsOAuthvsBearerToken)thread_dynamic_tools.Why I think the fix should be in desktop/app-server wiring
mcpServer/oauth/login.McpServerOauthLoginParams = { name, scopes?, timeoutSecs? }McpServerOauthLoginResponse = { authorizationUrl }McpServerOauthLoginCompletedNotification = { name, success, error? }codex-rs/app-server/src/codex_message_processor/plugin_mcp_oauth.rs, which explains the asymmetry.Lowest-risk patch sketch
NotLoggedInand OAuth login is supported, have the desktop client/app-server path trigger the existingmcpServer/oauth/loginflow for that server instead of silently allowing tool exposure to collapse to zero.authorizationUrlin the frontend, then wait formcpServer/oauthLogin/completed.config/mcpServer/reloadand/or thread MCP refresh) so the server is re-mounted without requiring the user to manually restart / create guess-and-check threads.Alternative patch if you want the smallest UX-only change first
Regression test suggestion
codex-rs/app-server/tests/common/mcp_process.rsharness and a stubStreamableHttpMCP endpoint that:401+WWW-Authenticatebefore login,mcpServer/oauth/login(or equivalent auth-needed status), then after simulated completion + reload,mcpServerStatus/list/ mounted tools include the server.This feels like a good candidate for an invited PR if maintainers agree on whether the desired UX is auto-triggered login vs explicit “Connect MCP” UI first.
The behavior still persists and is maddening.
Adding a Windows reproduction that appears to match this issue.
Environment
Observed behavior
codex mcp listshows all three remote servers as enabled withAuth = OAuth.There may also be a separate post-restart empty or stale turn symptom consistent with #40915, but the reproducible issue here is the silent omission of authenticated remote OAuth MCP tools.
Expected behavior
Configured, enabled, authenticated remote MCP tools should be mounted in fresh tasks. If mounting fails, Codex should expose a per-server diagnostic explaining whether discovery, OAuth credential resolution, initialization, or tool-catalog attachment failed.
Could the maintainers add per-task MCP diagnostics that show why an enabled server was omitted from the callable tool catalog?