Codex auto-mirrors Claude Code marketplaces, breaking MCP handshake for Claude-only plugins

Open 💬 0 comments Opened Apr 24, 2026 by Con-Benksl

What version of Codex CLI is running?

v0.124.0

What subscription do you have?

pro 5x

Which model were you using?

_No response_

What platform is your computer?

macOS

What terminal emulator and version are you using (if applicable)?

Terminal.app

What issue are you seeing?

## Problem

Codex CLI scans for .claude-plugin/marketplace.json files and
auto-imports any marketplace it finds into ~/.codex/.tmp/marketplaces/,
even when the marketplace is not declared in ~/.codex/config.toml.

When those marketplaces contain plugins designed only for Claude Code
(using ${CLAUDE_PLUGIN_ROOT} in .mcp.json — e.g., claude-mem),
Codex tries to launch their MCP servers at startup. Because Codex does
not substitute ${CLAUDE_PLUGIN_ROOT}, the command resolves to an
invalid path and the MCP handshake fails.

## Reproduction

  1. Install Claude Code and add a marketplace that ships a plugin with

${CLAUDE_PLUGIN_ROOT} in its .mcp.json (e.g. thedotmack/claude-mem).

  1. Install Codex CLI. Do not declare the marketplace in config.toml.
  2. Start Codex.
  3. Observe:

⚠ MCP client for mcp-search failed to start:
MCP startup failed: handshaking with MCP server failed:
connection closed: initialize response

The offending directories ~/.codex/plugins/cache/thedotmack/ and
~/.codex/.tmp/marketplaces/thedotmack/ appear even though the user
never added thedotmack to their Codex config.

## Workaround

Users currently have to either:

  • Delete the mirrored cache (will be re-created on next start), or
  • Add [plugins."<name>@<marketplace>"]\nenabled = false to config.toml

for every leaked plugin

Neither scales as the user installs more Claude Code plugins.

## Requested fix (any of)

  1. Add a config.toml flag to opt out of Claude-marketplace discovery:

```toml
[plugins]
auto_discover_claude_marketplaces = false

  1. Skip any plugin whose .mcp.json references ${CLAUDE_PLUGIN_ROOT}

(or any unresolved variable) instead of attempting the handshake.

  1. Only import marketplaces explicitly listed in config.toml.

Environment

  • Codex CLI: <your version — run codex --version>
  • OS: macOS 15.4.0 / Darwin 25.4.0 (arm64)
  • Claude Code installed: yes

What steps can reproduce the bug?

Summary

Codex CLI auto-mirrors Claude Code marketplaces into ~/.codex/.tmp/marketplaces/ even when the marketplace is not declared in ~/.codex/config.toml.
When those marketplaces contain Claude-Code-only plugins (whose .mcp.json references ${CLAUDE_PLUGIN_ROOT}), Codex tries to start their MCP servers at
launch, and the handshake always fails because Codex does not substitute that variable.

Steps to reproduce

  1. Install Claude Code and install a plugin that uses ${CLAUDE_PLUGIN_ROOT} in its .mcp.json — e.g. claude-mem from the thedotmack marketplace

(https://github.com/thedotmack/claude-mem).

  1. Install Codex CLI (@openai/codex v0.124.0). Do not add thedotmack to ~/.codex/config.toml.
  2. Launch Codex.
  3. Observe startup errors:

⚠ MCP client for mcp-search failed to start:
MCP startup failed: handshaking with MCP server failed:
connection closed: initialize response

  1. Check the filesystem:
  • ~/.codex/plugins/cache/thedotmack/claude-mem/12.3.9/ exists
  • ~/.codex/.tmp/marketplaces/thedotmack/ exists
  • Neither was ever declared in config.toml — they were mirrored from ~/.claude/plugins/marketplaces/thedotmack/.

Root cause (from strings inspection of the Codex binary)

The Rust module core-plugins/src/marketplace_upgrade.rs scans for .claude-plugin/marketplace.json files and registers them as Codex marketplaces. There is
no config flag to opt out.

---

What is the expected behavior?

Codex should only load marketplaces that the user has explicitly declared in ~/.codex/config.toml. Specifically, any of the following would fix the problem:

  1. Preferred: add an opt-out config flag:

```toml
[plugins]
auto_discover_claude_marketplaces = false

  1. Alternative: when Codex finds an MCP server whose command references an unresolved variable like ${CLAUDE_PLUGIN_ROOT}, skip it with a warning instead of

attempting a doomed handshake.

  1. Minimal: only import marketplaces that the user has explicitly added, and treat .claude-plugin/marketplace.json discovery as purely advisory.

Additional information

```markdown
Current workaround

Adding this to ~/.codex/config.toml for every leaked plugin:
```toml
[plugins."claude-mem@thedotmack"]
enabled = false
This doesn't scale — users who install more Claude Code plugins keep hitting new handshake failures.

Environment

  • Codex CLI: codex-cli 0.124.0
  • OS: macOS 15.4.0 / Darwin 25.4.0 (arm64)
  • Claude Code installed: yes
  • Affected plugin in my setup: claude-mem@thedotmack (12.3.9)

Related GitHub MCP issue (may or may not be the same root cause)

On the same setup, the built-in github@openai-curated plugin also fails to start, with:
⚠ GitHub MCP does not support OAuth. Log in by adding a personal access token...
This is a separate error but the user experience is the same — two startup warnings before any work begins.

---

View original on GitHub ↗