Skip to content

MCP startup should not block tool listing or thread startup #29321

Open

Description

@caokaizz

Summary

A configured MCP server that is still starting or unreachable can block core Codex workflows when the session builds the aggregated MCP tool list. This makes optional MCP extensions behave like startup-critical dependencies.

Root cause found locally

codex-mcp currently waits on pending MCP clients from McpConnectionManager::list_all_tools() through AsyncManagedClient::listed_tools(). When an MCP server is unreachable and has no startup tool cache, the first turn/tool-router construction can wait until MCP startup timeout instead of keeping chat usable.

Proposed fix

I have a local/fork branch that changes listed_tools() to skip clients that are still initializing and have no cached startup tools. Cached startup tools are still returned while initialization continues; once startup completes, tools are listed normally.

Branch:
https://github.com/caokaizz/codex/tree/codex/mcp-nonblocking-tool-list

Compare:
main...caokaizz:codex:codex/mcp-nonblocking-tool-list

Commit:
9502ad1 Avoid blocking tool listing on MCP startup

Validation run locally

  • just test -p codex-mcp list_all_tools_skips_pending_client_without_cached_tool_info_snapshot
  • just test -p codex-mcp (88 passed)
  • just fmt
  • just fix -p codex-mcp

Note

I attempted to open a PR from the fork branch, but GitHub returned: caokaizz does not have the correct permissions to execute CreatePullRequest.

Activity

  1. added
    bugSomething isn't working
    CLIIssues related to the Codex CLI
    mcpIssues related to the use of model context protocol (MCP) servers
    on Jun 21, 2026
  2. Necmttn commented on Jun 21, 2026

    @Necmttn

    MCP tool discovery should probably be a degraded capability inventory, not a hard pre-turn dependency.

    Each server row can carry last successful tool manifest, manifest hash, started_at, freshness, startup status, and timeout/error reason. The router can use cached tools when fresh enough, omit unknown servers for the current turn, and surface MCP server pending in diagnostics.


    Generated with ax.

  3. zyz23333 commented on Jun 21, 2026

    @zyz23333

    I hit what looks like the same issue today. Codex failed to start a new conversation, and removing one MCP server config made it work again.

    This was hard to diagnose from the user side because the failure happened during conversation startup, and it was not obvious that an optional MCP server was blocking core Codex functionality.

  4. tangweigang-jpg commented on Jun 21, 2026

    @tangweigang-jpg

    This failure mode is worth treating as a dependency-classification problem, not only a timeout problem.

    For startup, I would separate MCP servers into three states:

    1. required and blocking, where the session cannot safely proceed without the server;
    2. optional but cached, where the last known tool surface can be shown with a stale/revalidating marker;
    3. optional and unavailable, where the thread should start normally and expose a visible warning.

    The important edge case is the first turn. If an optional MCP server is slow or unreachable, the user still needs a usable chat and a clear diagnostic: which server blocked, how long it waited, whether cached tools were used, and whether the server will be retried in the background.

    For the proposed skip-pending behavior, I would also make the event observable in logs/UI. Otherwise users may see a model ignore a tool and misdiagnose it as a planning problem when the real cause was that the server was still initializing or had no startup cache.

    A useful acceptance test would be: configure one fast MCP server and one unreachable optional server, start a fresh session, and verify that core chat plus the fast server are usable before the unreachable server timeout expires. Then verify the unavailable server can become visible later without restarting the thread.

  5. Hello-Mugen commented on Jun 29, 2026

    @Hello-Mugen

    +1, Pls fix it

    This bug is stupid and wasting my token!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingmcpIssues related to the use of model context protocol (MCP) serversperformance

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions