Repository navigation
[Bug]: Codex turn sees partial MCP tool catalog during server startup #13437
Description
Activity
Confirmed. This is still the case on
mainand in the reportedv0.0.42build. No existing issue covers it.CodexSessionRuntime.sendTurntreatsconfig/mcpServer/reloadas “the tool catalog is ready,” then immediately callsturn/start:That RPC does not mean startup has finished. Its response is an empty
McpServerRefreshResponse, and the app-server only queuesOp::RefreshMcpServersbefore returning. Each server then reportsstarting/ready/failed/cancelledonmcpServer/startupStatus/updated. Nothing in this runtime waits on those notifications, and it never callsmcpServerStatus/list. The session is already markedreadywhen the thread opens.mcpServer/startupStatus/updatedis not mapped to a runtime event, so the thread gets no incomplete-inventory state.The reload runs on every turn where T3 attached
mcp_servers.t3-code, not only the first one. It refreshes every configured server on the thread, including user stdio servers. Your trace matches that window: servers enterstartingat 14:20:51.141 andturn/startedarrives 78ms later, before any of them areready.Codex then snapshots the model-facing tool binding with a 1s grace for optional servers (
OPTIONAL_MCP_STARTUP_GRACEincodex-rs/codex-mcp/src/connection_manager/tool_catalog.rs). A server still starting after that is omitted (omitting pending optional MCP server). Required servers andcodex_appsare waited on; ordinary configured servers are not. That lines up with a catalog that contains only the servers alreadyreadyat 14:21:04, while servers that reachedreadyat 14:21:10–12 stay out of that snapshot. A later turn can see them once startup has finished, which is why a follow-up registry lookup and tool call succeeded.list_mcp_resourcesis a separate Codex behavior: it lists resources, not callable tools (openai/codex#14242). It makes the model’s verbal inventory unreliable, but it does not explain tools that were alreadyreadyand still absent from the binding.A bounded wait before
turn/start— until each expected server leavesstarting, or a timeout elapses — would match what the Codex TUI does and would keep a hung or failed server from blocking the turn. Codex can emit a spuriouscancelledbeforereadyfor a server that was only started once (openai/codex#36682), so the waiter has to key on server name and let a laterreadywin.- addedacceptedfeature request acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 24, 2026 This still happens on V2
main, and a Codex setting already closes the gap without a T3 change.CodexAdapterV2sendsturn/starta few milliseconds afterthread/startreturns. Codex waitsmcp_optional_startup_grace_ms(default 1 s), then builds the first model request without any server that is still starting. It rebuilds the tool list for each later request in the turn, so a late server is missing only until it is ready.Workaround today: set
mcp_optional_startup_grace_msin the Codex home'sconfig.toml. With3000onmain, the first request waited 2.8 s and had every server. A value above the slowest server's start time should do the same for the 10–20 s servers in this report. I ran only3000.Measured on Linux with Codex 0.159.3, agent-run, one run per case. Windows and macOS were not measured.
- Warm
npx/uvxservers (filesystem, memory, sequential-thinking, Playwright, time, fetch) were ready 0.4–0.7 s afterturn/start. None was dropped. - With empty package caches they were ready after 1.4–2.7 s, and all six were left out of the first request.
- In the repo's recorded transcripts,
xcodebuildmcptakes 2.5–5.0 s to start (median 4.0 s, 29 recordings). In the 23 recordings where it starts with the thread, it is ready 3.8–5.5 s after the turn starts (median 4.6 s). - With grace
3000and one server that never answers, the first request waited 3.0 s and left out only that server. The second turn did not wait.
Do you want T3 to set a default, or leave this to the Codex setting?
- Docs only. Describe the setting in
docs/user/providers-codex.md. No default changes. - A finite grace in T3's thread config, for example 5 s. It covers cold
npxstarts and 18 of those 23 recordedxcodebuildmcpstarts, but not the 10–20 s servers in this report. A hung server would add about 4 s to the first turn of each Codex session (not run at 5 s). 0in T3's thread config. Codex then waits for each server up to itsstartup_timeout_sec, 30 s per startup phase by default. A server that never answered held the first turn about 30 s.
Options 2 and 3 would override the user's own
config.tomlvalue. That comes from the Codex source and was not run.I can send whichever you choose.
Written by Claude Fable 5.1 on behalf of @ScottN-PV.
- Warm
Area
apps/server — Codex provider
Version and environment
T3 Code desktop v0.0.42 on macOS; Codex with GPT-6 Luna. Several configured stdio MCP servers have different startup times.
Steps to reproduce
Expected behavior
The model can discover the configured MCP tools once their servers are ready, or receives a clear startup/incomplete-inventory state before answering. A tool inventory should not silently contain only the fastest servers.
Actual behavior
The model reported only the first two ready MCP servers and said it could not verify the rest. Other configured servers became ready before its answer, but their tools were absent from the catalog snapshot it used. In a separate Codex turn, a later tool-registry lookup found the missing tools and a call to one of them succeeded.
Relevant timing from a redacted provider trace
list_mcp_resourcesdoes not enumerate callable tools, which also makes the model's inventory unreliable. The timing issue is independent of those two failed servers: several successful servers reachedreadybefore the answer but after the model's lookup.In
apps/server/src/provider/Layers/CodexSessionRuntime.ts,sendTurncallsconfig/mcpServer/reloadand thenturn/start. The reload response arrives before themcpServer/startupStatus/updatednotifications reach terminal states. Please account for that asynchronous startup before the model treats a tool catalog as complete. A bounded wait or a live catalog refresh could preserve responsiveness when a server is slow or fails.Impact
Major degradation: Codex agents can skip working MCP tools or claim they are unavailable.
Workaround
A fresh tool-registry lookup after the server reaches
readycan find the tools, but the model does not reliably perform one on its own.