CLI session loses stdio MCP connections after initial successful calls; fresh codex exec still works
Summary
In a long-lived Codex CLI session, stdio MCP servers can work initially and then permanently degrade to Transport closed for the rest of that session.
The key detail is that the servers themselves still appear healthy: repeated fresh codex exec subprocesses on the same machine continue to use the same MCP servers successfully while the original interactive session remains broken.
I reproduced this on 2026-04-06 with:
- Codex CLI
0.118.0 - Linux / WSL2:
Linux SimonRy9 6.6.87.2-microsoft-standard-WSL2 x86_64 - MCP servers:
vault_searchandrepo_search(both stdio Python servers)
Reproduction
- Start a fresh interactive Codex CLI session.
- Run a first burst of MCP calls in the session. In my case these all succeeded:
vault_search.vault_coveragerepo_search.repo_coveragevault_search.vault_search(query="Prompting")repo_search.repo_search(query="Prompting")
- Run a second burst of MCP calls in the same session.
- Observe that both MCP servers now fail with
Transport closed. - Try even simpler MCP operations like resource listing in the same session.
- Observe that those fail too.
- In parallel, run fresh
codex execsubprocesses that use the same MCP servers. - Observe that the fresh subprocesses continue to succeed repeatedly.
Expected
If the MCP servers are healthy, the existing interactive session should continue to use them successfully, or Codex should automatically reconnect / recover the MCP transport.
Actual
The interactive session enters a persistent broken state for MCP usage:
vault_search.vault_coverage->Transport closedrepo_search.repo_search(...)->Transport closedlist_mcp_resources(server="vault_search")->Transport closedlist_mcp_resources(server="repo_search")->Transport closed
At the same time, fresh codex exec subprocesses on the same machine still succeed with the same servers.
That suggests the problem is in the MCP client / session connection state of the long-lived interactive session, not in the MCP server process itself.
Why this seems like a Codex-side session bug
- Two different stdio MCP servers fail together in the same session.
- The failures persist for the remainder of that session.
- Fresh
codex execsubprocesses repeatedly succeed against the same servers. - No server config changes were made between the successful and failing calls.
Additional notes
- The same pattern reproduced again after restarting the Codex session: first MCP burst succeeded, second burst failed.
- This was not limited to one server or one MCP tool. It also affected
resources/list. - I also ran repeated fresh-process probes over time and they stayed green while the interactive session stayed broken.
Fresh-process control probe
I ran repeated fresh-process probes that call:
vault_coveragerepo_searchwith queryPrompting
All control probes succeeded while the interactive session remained broken.
Example aggregate result from the local probe log:
7/7successful fresh-process MCP runs- max duration about
25.449s - classifications: only
ok
Suggested investigation areas
- MCP transport lifecycle in long-lived interactive CLI sessions
- stdio MCP connection reuse across multiple tool bursts
- whether one failed/closed connection poisons other MCP client handles in the same session
- whether MCP resource-list calls and tool calls share a broken session-level connection pool
7 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Validated a local workaround on 2026-04-06.
Workaround:
mcp__vault_search__.../mcp__repo_search__...Local wrapper paths:
scripts/mcp-searchscripts/mcp_search_workaround.pyscripts/debug/mcp_workaround_probe.pyWhat this does:
Validation:
vault_search,repo_search,vault_coverage,repo_coverage12/12successful runs,0failures5.791sRelevant local log:
tmp/logs/mcp-workaround-probe.jsonlThis does not fix the Codex bug itself, but it does confirm that the underlying search implementations remain healthy and usable while the interactive session MCP transport is degraded to
Transport closed.I reviewed the suggested duplicates.
My take:
Transport closedstate in an already-working CLI session.I am leaving this issue open for now because the distinguishing details here are:
vault_searchandrepo_search) fail togetherTransport closedcodex execcontrol probes remain healthy on the same machineIf maintainers believe #15508 already fully covers the CLI/session-transport variant too, I am happy to close this as a duplicate of #15508.
I’m seeing a similar pattern here with
context-modeas the stdio MCP server.What I observed locally:
context-modeis configured as a stdio MCP server in my Codex configcontext-mode --versionreportsv1.0.75ctx_batch_executeMCP tool call failed with:tool call failed for context-mode/ctx_batch_executeCaused by: Transport closedThe main reason I’m adding this here is that it does not look like a pure initialize/handshake failure. In my case, the MCP had already worked earlier in the session, and then a later tool call failed with
Transport closed.That feels directionally similar to the failure mode described in this issue: a long-lived interactive session gets into a bad MCP transport state even though the problem is not just “server never started.”
I’m also looking at a potentially related
context-modeissue on their side:I’m not claiming root cause yet, only that I’m seeing the same client-visible symptom class from Codex:
Transport closedStill reproducible on 2026-04-22 with
codex-cli 0.122.0on Linux/WSL2.I hit the same failure mode again today with our stdio Python MCPs, especially
vault_search(and alsorepo_searchin the same session):Transport closedCurrent evidence from
~/.codex/log/codex-tui.logon 2026-04-22:read_mcp_resource {"server":"vault_search","uri":"config://info"}->Transport closedlist_mcp_resources {"server":"vault_search"}->Transport closedmcp__vault_search__vault_search {...}->Transport closedrepo_searchMCP calls failing withTransport closedFresh-process control probe on the same machine is still green:
codex execsubprocess today and asked it to callvault_search.vault_coverageexactly onceRESULT: OKSo
#16899does not appear to be fixed in0.122.0. This still looks like a Codex-side MCP transport/session lifecycle bug in long-lived interactive CLI sessions, not a bug in the MCP server implementation itself.A short-term mitigation might be to route affected FastMCP servers over local Streamable HTTP instead of stdio, but that is only a workaround. The actual product fix still seems to be needed on the Codex side: the CLI should either keep these MCP transports healthy across turns or automatically reconnect/recover instead of poisoning the rest of the session after the first break.
Please prioritize a real fix here. For MCP-heavy workflows, the current behavior makes the interactive CLI unreliable.
Follow-up with a working local mitigation / workaround.
I was able to stop the recurring MCP breakage for our local Python MCPs by moving them off
stdioand onto local Streamable HTTP endpoints.What worked here on 2026-04-22:
transport="streamable-http"instead ofstdio.--userin my case).command/argsin~/.codex/config.toml.Example config pattern:
Example service pattern:
Results on my side after switching to local Streamable HTTP:
vault_search: stable, verified with repeated live searches in fresh Codex sessionswindows-search: stable, verified with live searchesrepo_search: MCP transport is stable andrepo_coverageworks; I still see a separate search/index-recall issue on my current repo index, but that appears independent from the Codex MCP transport problemSo the original Codex bug still matters: long-lived
stdioMCP sessions were the thing poisoning the interactive CLI for us. But if someone is blocked right now and their server already supports FastMCP HTTP transport, switching the local MCP fromstdioto Streamable HTTP is a practical workaround.Follow-up after applying the workaround locally.
I was able to get all three local Python MCPs (
vault_search,repo_search,windows-search) working reliably in Codex by moving them fromstdioto local Streamable HTTP endpoints and running them as long-lived user services.What I changed:
--transport streamable-http --host 127.0.0.1 --port <port> --streamable-http-path /mcp--useron my machine)url = "http://127.0.0.1:<port>/mcp"instead ofcommand/argstool_timeout_secfor heavier MCPs and increasestartup_timeout_secforrepo_searchExample
config.tomlpattern:One extra bug I found while fixing
repo_search:repo_searchlook superficially healthy while every real search returned no hitsrepo_searchimplementation to detectmetadata exists but table missingand force a rebuild instead of incorrectly returningup_to_dateCurrent result on my side:
vault_search: working with real searcheswindows-search: working with real searchesrepo_search: working again with real docs/code searches after the rebuild fixSo the product bug still matters: Codex interactive sessions and local
stdioMCPs were not stable enough for this workflow. But for anyone blocked today, local Streamable HTTP MCP + a persistent local service is a viable workaround.