openai / openai/codex

Codex Desktop receives MCP startup failures but silently omits plugin tools

Open
#42,079 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug mcp
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Codex Desktop receives MCP startup failure events but silently omits plugin tools

What version of the Codex App are you using?

26.825.51511 (build 7377), bundled codex-cli 0.151.0-alpha.7.2

What subscription do you have?

Authenticated ChatGPT subscription; the exact tier is not material to the reproduction.

What platform is your computer?

Darwin 27.0.0 arm64 arm

What issue are you seeing?

When an enabled local plugin's stdio MCP process exits before completing the initialize handshake, Codex Desktop silently omits that server and all of its tools from the task. The task UI does not show the launcher error, a failed-plugin state, or a recovery action.

In the reproduced case, the launcher wrote a stable diagnostic to stderr and exited. Local Codex logs then showed all of the following:

  • the launcher stderr diagnostic was captured;
  • mcpServer/startupStatus/updated notifications were emitted to connected app clients;
  • the tool catalog omitted the server because there was no exact ready client;
  • the task UI displayed none of this and the model received none of the plugin tools.

The current desktop bundle contains a handler that logs mcpServer/startupStatus/updated, including status, error, failureReason, threadId, and server name. The notification is therefore reaching the desktop boundary, but a generic failed plugin server does not become a durable, user-visible task warning.

This is distinct from a server that completes the handshake but whose tools are later filtered. The failure occurs before initialize, and Codex already has the failure information.

The reproduction does not depend on a specific private plugin: any minimal stdio MCP launcher that writes a diagnostic and exits before initialize should exercise the same boundary. No private plugin source, account data, or user content is required.

What steps can reproduce the bug?

  1. Install and enable a local plugin with a stdio MCP server.
  2. Make the plugin launcher print a stable error to stderr and exit non-zero before returning an MCP initialize response.
  3. Start a fresh Codex Desktop task in a project where the plugin is enabled.
  4. Observe the task UI and the model-visible tool list.
  5. Inspect Codex logs.

Actual result:

  • the plugin appears enabled;
  • its tools are absent;
  • the task UI shows no startup failure;
  • logs contain the launcher stderr diagnostic and outgoing mcpServer/startupStatus/updated events;
  • the tool catalog records that the server is omitted because no ready client exists.

What is the expected behavior?

Codex Desktop should retain and display a per-thread, per-server failed state whenever an enabled MCP server fails startup. The warning should include:

  • plugin and server name;
  • a bounded, sanitized error summary;
  • classified failure reason when available;
  • actions to retry startup and open diagnostics.

Tool omission should not be the only user-visible signal.

Additional information

The public app-server protocol already exposes the necessary notification:

  • McpServerStatusUpdatedNotification includes thread_id, name, status, error, and failure_reason;
  • the TUI already converts failed startup notifications into visible warnings;
  • app-server integration coverage already verifies a failed optional stdio server produces mcpServer/startupStatus/updated with an error.

Relevant existing reports include:

Suggested implementation direction

Desktop renderer:

  1. Subscribe to generic mcpServer/startupStatus/updated notifications for every server, not only special built-in servers.
  2. Keep a state map keyed by (hostId, threadId, serverName).
  3. On failed, render a deduplicated persistent warning in the affected task and invalidate the MCP status query.
  4. On ready, clear the warning or mark it recovered.
  5. Truncate and sanitize stderr-derived error text before display.

Public app-server follow-up suitable for a small PR:

  1. Extend McpServerStatus with optional startup_error and startup_failure_reason fields.
  2. Preserve the latest StartupOutcomeError in the read-only connection-status snapshot instead of collapsing it to the Failed enum alone.
  3. Return those fields from mcpServer/list so clients can reconstruct the failed state after a reload or a missed notification.
  4. Add an app-server integration test asserting that a broken optional stdio server is listed as failed with its bounded error text.

The renderer change is likely maintained outside the public openai/codex repository, but the persistent app-server status enhancement is independently PR-able and would make every client more robust.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the public app-server entry points for McpServerStatus, StartupOutcomeError, mcpServer/list, and the mcpServer/startupStatus/updated notification; inspect the existing integration coverage for failed optional stdio servers. Trace how the read-only connection-status snapshot represents startup failures. Done means failed servers retain bounded error details in mcpServer/list and the integration test verifies them after startup failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.