Skip to content

Windows Codex Desktop MCP tool wrapper reports Transport closed while same stdio server works directly #18486

Open

Description

@DrCord

What version of Codex is running?

Codex Desktop for Windows, observed process package version: OpenAI.Codex_26.415.1938.0_x64__2p2nqsd0c76g0.

What subscription do you have?

Plus

Which model were you using?

GPT-5 Codex desktop session.

What platform is your computer?

Windows, PowerShell shell. Unity Editor is running locally.

What issue are you seeing?

A configured MCP server for Unity is reachable and works when launched directly, but Codex Desktop's built-in MCP tool namespace fails immediately with Transport closed.

The failing Codex tool call is any mcp__unity__ call, for example:

unity_list_instances -> tool call error: tool call failed for `unity/unity_list_instances`
Caused by: Transport closed

This persists after restarting Codex multiple times and after restarting the Unity-side MCP server from within Unity. Claude is able to use the same MCP connection successfully on the same machine.

This may be related to, but appears narrower/different from, #7155. In this case the direct stdio MCP server is healthy and the latest failed Codex wrapper calls do not appear to reach the Unity MCP server log at all.

MCP server config

From ~/.codex/config.toml:

[mcp_servers.unity]
command = "node"
args = ["C:/Users/<user>/Projects/unity-mcp-server/src/index.js"]
env = { UNITY_HUB_PATH = "C:/Program Files/Unity Hub/Unity Hub.exe", UNITY_PORT_RANGE_START = "7890", UNITY_PORT_RANGE_END = "7899", UNITY_BRIDGE_TIMEOUT = "60000" }

[mcp_servers.unity.tools.unity_editor_ping]
approval_mode = "approve"

[mcp_servers.unity.tools.unity_editor_state]
approval_mode = "approve"

[mcp_servers.unity.tools.unity_list_instances]
approval_mode = "approve"

[mcp_servers.unity.tools.unity_select_instance]
approval_mode = "approve"

[mcp_servers.unity.tools.unity_agents_list]
approval_mode = "approve"

The server package is anklebreaker-unity-mcp; package.json says 2.28.1, while the MCP server reports serverInfo.version: 2.26.0.

Steps to reproduce

  1. On Windows, configure Codex Desktop with a local Node MCP server using newline-delimited JSON-RPC over stdio.
  2. Start Unity with the Unity MCP bridge listening in the range 7890-7899.
  3. In this repro, Unity is on port 7892.
  4. From Codex Desktop, call a configured MCP tool such as unity_list_instances or unity_editor_ping.
  5. Observe immediate Transport closed from the Codex MCP tool wrapper.
  6. Launch the exact same server command manually and send newline-delimited MCP JSON-RPC messages over stdio.
  7. Observe that direct MCP calls succeed.

Expected behavior

Codex should keep the MCP stdio transport open and return the tool result, matching the direct MCP client behavior and Claude's behavior on the same machine.

Actual behavior

Codex reports Transport closed immediately from the MCP tool wrapper. After the first failure, repeated mcp__unity__ calls continue to fail immediately.

Evidence collected

Raw Unity TCP port is open:

Test-NetConnection -ComputerName 127.0.0.1 -Port 7892
# TcpTestSucceeded: True

Unity MCP instance registration exists:

[
  {
    "port": 7892,
    "projectName": "CosmicCatastrophe",
    "projectPath": "C:/Users/<user>/Projects/cosmic-catastrophe/CosmicCatastrophe",
    "unityVersion": "6000.4.2f1",
    "platform": "WindowsEditor",
    "processId": 43084,
    "isClone": false,
    "cloneIndex": -1
  }
]

Direct MCP server launch and newline-delimited stdio handshake succeeds:

MCP_RESPONSE {"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{},"resources":{}},"serverInfo":{"name":"unity-mcp","version":"2.26.0"}, ...},"jsonrpc":"2.0","id":1}

Direct tools/call for unity_list_instances succeeds:

{
  "instances": [
    {
      "port": 7892,
      "projectName": "CosmicCatastrophe",
      "projectPath": "C:/Users/<user>/Projects/cosmic-catastrophe/CosmicCatastrophe",
      "unityVersion": "6000.4.2f1",
      "isClone": false,
      "cloneIndex": -1,
      "source": "portscan",
      "isSelected": false
    }
  ],
  "totalCount": 1,
  "selectedPort": null,
  "selectedProject": null
}

Direct tools/call for unity_editor_ping succeeds:

{
  "connected": true,
  "status": "ok",
  "unityVersion": "6000.4.2f1",
  "projectName": "CosmicCatastrophe",
  "projectPath": "C:/Users/<user>/Projects/cosmic-catastrophe/CosmicCatastrophe",
  "platform": "WindowsEditor",
  "isClone": false,
  "cloneIndex": -1,
  "processId": 43084
}

Unity MCP debug log shows prior successful Codex wrapper attempts reaching the server, but the latest failing calls after restart did not add log entries. That suggests the failure is happening before the configured Node MCP server receives the request.

Additional notes

When I tested the server manually, header-framed MCP messages started the server but did not get responses; newline-delimited JSON-RPC over stdio worked. If Codex Desktop's wrapper is using or falling back to a different stdio framing mode for this server, that could explain the symptom, but this is only an inference from the direct smoke tests.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    windows-osIssues related to Codex on Windows systems
    mcpIssues related to the use of model context protocol (MCP) servers
    tool-callsIssues related to tool calling
    on Apr 18, 2026
  2. github-actions commented on Apr 18, 2026

    @github-actions
    Contributor

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

    Powered by Codex Action

  3. removed
    tool-callsIssues related to tool calling
    appIssues related to the Codex desktop app
    on Apr 18, 2026
  4. DrCord commented on Apr 19, 2026

    @DrCord
    Author

    Not a duplicate of #16899 — these are distinct bugs.

    A bot flagged #16899 as a potential duplicate. After reviewing both issues, they are not the same:

    This issue (#18486) #16899
    Platform Windows / Codex Desktop Linux / WSL2, Codex CLI
    Failure pattern Transport closed immediately on every call — Unity MCP server logs confirm requests never arrive Works for an initial burst, then degrades mid-session
    Root cause hypothesis stdio framing mismatch: direct smoke tests showed header-framed MCP messages got no response while newline-delimited JSON-RPC succeeded; Codex Desktop's wrapper may be using a different framing mode Session-level MCP transport not being re-established after first close
    Workaround Bypass Codex wrapper and call Node MCP server directly via newline-delimited stdio Use fresh codex exec subprocesses

    #16899 is a session transport lifetime bug (connection degrades over time). This issue is a stdio framing or Codex Desktop wrapper bug that prevents the first call from ever reaching the server. The shared symptom (Transport closed) does not indicate the same root cause.

  5. DrCord commented on Apr 28, 2026

    @DrCord
    Author

    Update after more debugging: I was able to get native Codex Desktop MCP working with this Unity MCP server.

    The original framing hypothesis was incomplete. The decisive failure was that the Unity MCP server wrote a non-JSON status line to stdout during some tool calls, for example queue submission logging like:

    [MCP Bridge] Submitted editor/execute-code to queue, ticket: ...
    

    Direct smoke clients and some other MCP clients tolerated/ignored that line, but Codex Desktop appears to treat MCP stdio stdout as strict JSON-RPC. When unity_execute_code emitted that bridge status line before the JSON-RPC response, Codex closed the transport and surfaced Transport closed.

    Workaround/fix that restored native Codex MCP:

    1. Change the Unity MCP server so all diagnostic/status logging goes to stderr, not stdout. In this case, replacing console.debug(...) with console.error(...) for the bridge queue-submission and lazy-load log messages was enough.
    2. Pin the Codex MCP config to the real Node executable on Windows instead of relying on PATH resolution:
    [mcp_servers.unity]
    command = "C:/Program Files/nodejs/node.exe"
    args = ["C:/Users/Cord42/Projects/unity-mcp-server/src/index.js"]

    After restarting Codex Desktop, native MCP calls succeeded end to end:

    • unity_list_instances found the Unity instance.
    • unity_select_instance selected it.
    • unity_editor_ping returned connected: true.
    • unity_execute_code returned the active scene successfully instead of closing the transport.

    So at least one cause of this Transport closed failure mode is: MCP server writes non-JSON data to stdout, and Codex Desktop is stricter than clients that ignore such output. A useful Codex-side improvement would be better diagnostics for malformed/non-JSON stdout before closing the transport, but server authors should also ensure stdout is reserved exclusively for MCP JSON-RPC.

  6. Necmttn commented on Jun 22, 2026

    @Necmttn

    A Codex-side diagnostic before closing the transport would help a lot here. Suggested fields: MCP server name, command path, child pid, framing mode, stdout parser state, first non-JSON stdout line or byte offset, stderr tail, and close reason.

    That would turn Transport closed into an actionable server-author fix: stdout contained non-MCP bytes, Node path failed, process exited, or framing was wrong. Right now several distinct failures collapse into the same message.

    Generated with ax - https://github.com/Necmttn/ax

  7. Wheels00 commented on Jul 30, 2026

    @Wheels00

    Another reproducible macOS case: a resumed task retained a dead local-stdio MCP transport while direct and fresh-task checks passed.

    Environment:

    • Codex desktop 26.721.41059 (build 5848, bundle com.openai.codex)
    • macOS 26.0.1 (25A362)
    • Configured/enabled local stdio server: email_mcp
    • Server: email-mcp 1.27.0; MCP protocol 2025-11-25

    Timeline (UTC, 30 Jul 2026):

    • 00:42:59: resumed/current task called a harmless read-only tool. It immediately returned tool call error: tool call failed for email_mcp/email.list_account_statuses / Caused by: Transport closed.
    • 00:43:32: an isolated direct stdio probe passed configuration, launch (1 ms), initialize (306 ms), and tools/list (1 ms), discovering 21 tools.
    • 01:17:57: provider authentication refresh completed successfully through a new/direct MCP connection.
    • 01:20:58: the same resumed task called another Email MCP tool and again failed immediately with Transport closed.
    • 01:22:49: a genuinely fresh task completed a harmless Email MCP health call successfully (transport_health: ok). A repeat direct probe at 01:23 again passed initialize (395 ms), discovered 21 tools, and exited cleanly after stdin closed.

    Sanitized process snapshot (arguments and environment omitted):

    • One ChatGPT/Codex main process and one app-server root, both about 1 day 20 hours old.
    • MCP doctor matched 300 MCP-related rows: 276 direct roots plus 24 descendants, total RSS 1,576,624 KiB.
    • 271 direct MCP roots were children of the app-server, totaling 961,872 KiB RSS.
    • Seven other configured local servers each had 27 direct roots under that app-server, spanning many creation times.
    • Five unmatched candidates had PPID 1; two descendants were zombies.
    • The fresh task's email_mcp had one direct root plus one zombie helper child.

    This single snapshot shows substantial MCP-generation accumulation but does not by itself prove monotonic growth.

    Minimal reproduction:

    1. Resume an older Codex desktop task whose injected stdio MCP binding has died.
    2. Invoke a harmless read-only tool; observe immediate Transport closed.
    3. Run an isolated initialize plus tools/list probe against the same configured command; it succeeds.
    4. Refresh provider authentication through a fresh/direct connection; it succeeds, but the resumed task still returns Transport closed.
    5. Invoke the same server from a genuinely fresh task; it succeeds.

    Conclusion: stale task-bound host transport is confirmed in this case because the resumed task fails while the direct probe and fresh task pass. Authentication is not the fault boundary. The retained per-task MCP generations are plausible lifecycle-leak evidence, but growth would need before/after snapshots to confirm.

    Related macOS report: #15365.

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

    bugSomething isn't workingmcpIssues related to the use of model context protocol (MCP) serverswindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions