Codex mcp-server can hang indefinitely when command approval requires elicitation but MCP client cannot answer
What version of Codex CLI is running?
codex-cli 0.101.0
What subscription do you have?
ChatGPT Pro (Individual)
Which model were you using?
gpt-5.3-codex
What platform is your computer?
Linux 6.8.0-90-generic x86_64 x86_64 (Ubuntu 24.04)
What terminal emulator and version are you using (if applicable)?
_No response_
What issue are you seeing?
When using codex mcp-server from an MCP client (Claude Code v2.1.34) that does not respond to elicitation/create (or
does not surface approval UI), tool calls can block indefinitely if a command requires approval.
This is reproducible when approval-policy and sandbox are omitted and an unsafe command is
selected (example: pipeline with sort).
Observed behavior:
- No final tool response is returned.
- The turn remains stuck until manual cancellation.
- In multi-tool scenarios, one blocked approval can delay/hold completion of other finished tool
calls.
What steps can reproduce the bug?
- Start MCP server:
codex mcp-server
- Call MCP tool
codexwithout explicitly settingapproval-policy/sandbox. - Prompt it to run:
echo -e 'banana\napple\ncherry' | sort
- Wait for tool response.
Reproducible result:
- Request hangs (no response for long time / indefinitely).
Control:
- Same prompt with
approval-policy: "never"andsandbox: "danger-full-access"returns
immediately.
What is the expected behavior?
codex mcp-server should fail fast instead of hanging when approval cannot be completed via MCP
client.
Expected options:
- Detect missing elicitation support during initialize and reject approval-requiring execution with a
clear error.
- Or apply a timeout to approval elicitation and return a structured error.
- Or provide explicit documented behavior/fallback for non-elicitation clients.
Additional information
Relevant source references:
- No client capability gating on initialize path:
codex-rs/mcp-server/src/message_processor.rs:183 - Elicitation request callback has no timeout:
codex-rs/mcp-server/src/outgoing_message.rs:42 - Approval wait in core path is await-based (can block until decision): `codex-rs/core/src/
codex.rs:2168`
- Unsafe classification depends on command allowlist (
sortis not in allowlist): `codex-rs/shell-
command/src/command_safety/is_safe_command.rs:56`
- In-flight tool futures are ordered; head-of-line blocking can delay later completions: `codex-rs/
core/src/codex.rs:5237`
2 Comments
I investigated the source code and traced the full approval flow in the MCP server. Here's my root-cause analysis:
The hang point
When the MCP server needs command approval, it sends an
elicitation/createrequest to the client and spawns a task that awaits the response on aoneshot::Receiver:exec_approval.rs:118The same pattern exists in
patch_approval.rs:108.If the MCP client doesn't support elicitation (or simply never responds), this
awaitblocks forever — the tool call never completes and the session appears frozen.Three contributing issues
1. No timeout on the receiver
There is no
tokio::time::timeout()wrapping thereceiver.await. The core already has a cancellation-aware pattern incodex_delegate.rsviaawait_approval_with_cancel()usingtokio::select!, but the MCP server doesn't use anything similar.2. Client capabilities are never checked
In
message_processor.rs:183-206,handle_initialize()receivesparams.client_infobut never capturesparams.client_capabilities. The server has no way to know whether the client supports elicitation before sending the request.3. Inconsistent error handling between exec and patch approval
When the oneshot channel errors (e.g., client disconnects), the two handlers behave differently:
patch_approval.rs:111-123— submitsReviewDecision::Deniedto the core (correct fallback)exec_approval.rs:121-124— logs the error and silently returns without submitting any decision, leaving the core waiting foreverPossible fix approaches
receiver.awaitwithtokio::time::timeout()and default toDeniedon expiry (quick fix)handle_initialize()and deny immediately if the client doesn't support it (prevents the hang entirely)Err, submitOp::ExecApproval { decision: ReviewDecision::Denied }likepatch_approvalalready doesNote: We've announced that the mcp-server is deprecated and will be removed in a future release. We recommend using the app server interface instead. We won't be prioritizing any bug fixes in the mcp-server, so I'm going to close this issue.