codex exec silently auto-cancels MCP tool calls regardless of default_tools_approval_mode

Open 💬 5 comments Opened Jun 24, 2026 by alexandraabbas

When invoking codex exec (non-interactive), MCP tool calls are auto-cancelled with the message user cancelled MCP tool call, even when default_tools_approval_mode = "approve" is set in ~/.codex/config.toml for that MCP. Interactive codex honors the same config and runs the same MCP without issue.

This is surprising because (a) there is no "user" to cancel in non-interactive mode, and (b) the docs imply default_tools_approval_mode controls this exact case.

Reproduce

  1. Install a plugin with a bundled MCP server (or configure any user-side MCP). Example using an existing plugin:

``bash
codex plugin marketplace add meridianlabs-ai/inspect-skills
codex plugin add inspect-skills@meridian
``

  1. Add the enable block to ~/.codex/config.toml:

``toml
[plugins."inspect-skills".mcp_servers."py-repl"]
enabled = true
default_tools_approval_mode = "approve"
``

  1. Confirm the MCP is registered:

``bash
codex mcp list
# py-repl uvx ... enabled Unsupported
``

  1. Call it via codex exec:

``bash
codex exec --sandbox read-only "Use the py-repl MCP. Call execute_python with code='print(2+2)'."
``

Output:
``
mcp: py-repl/execute_python started
mcp: py-repl/execute_python (failed)
user cancelled MCP tool call
``

  1. Run the same prompt in interactive codex (no exec): the MCP call goes through and returns 4.

I verified all three accepted values of default_tools_approval_mode (auto, prompt, approve) — all produce the same user cancelled MCP tool call in codex exec. Dropping --sandbox read-only also doesn't help (the cancellation is not from the sandbox layer).

Expected

codex exec should honor default_tools_approval_mode = "approve" and auto-approve the call, or provide a narrower --auto-approve-mcp style flag for non-interactive use.

Current workaround

codex exec --dangerously-bypass-approvals-and-sandbox lets MCP calls through. But this also disables the sandbox, which is a much bigger blast radius than just auto-approving an explicitly-approved MCP. For automation use cases (CI, scripted runs), a smaller knob would be a much better fit.

Environment

  • Codex v0.139.0 (installed via brew)
  • macOS 26.3.1 (aarch64)
  • Plugin sourced from a local marketplace; same behavior expected with git-based marketplaces

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗