MCP 2026-07-28: conforming `input_required` result on tools/call fails with "Unexpected response type", although the client declared `elicitation.url`
Summary
Codex declares elicitation: { url: {}, form: {} } in the per-request _meta.io.modelcontextprotocol/clientCapabilities envelope on the 2026-07-28 stateless lane — but when a server takes it at its word and answers a tools/call with a spec-conforming InputRequiredResult (MRTR, SEP-2322) carrying a url-mode elicitation/create, the tool call fails client-side with:
tool call error: tool call failed for `acme/send_message`
Caused by:
Unexpected response type
The elicitation is never surfaced to the user. In my case the input_required was a human-in-the-loop approval gate (a server-side policy requiring confirmation before a send-type action), so the practical effect was: the user never saw the approval prompt, and the agent treated the governed tool as broken and routed around it.
Environment
codex-mcp-client0.149.0-alpha.4.3 (0.147.0 behaves the same way)- Streamable HTTP, protocol
2026-07-28(stateless_metaenvelope), against a 2026-07-28-conforming MCP server - The client's envelope declared
elicitation: { url: {}, form: {} }— which is exactly what invites the server to send the url-mode ask (per MRTR server requirement #7, servers MUST NOT embed input requests the client didn't declare — so a client that did NOT declare it would have received the server's fallback carrier instead).
Wire flow
tools/call→ server-side policy requires human confirmation.- Server responds
200with (shape abbreviated):
{
"jsonrpc": "2.0",
"id": 10,
"result": {
"resultType": "input_required",
"inputRequests": {
"approval": {
"method": "elicitation/create",
"params": {
"mode": "url",
"url": "https://mcp.example.com/approve?token=…",
"message": "This action needs your approval. Review and approve it here, then it will continue."
}
}
}
}
}
- Codex errors with
Unexpected response typeinstead of presenting the URL consent flow and retrying the call.
Notably, this payload shape is essentially identical to the one your own MRTR test server emits (codex-rs/rmcp-client/src/bin/test_mcp_2026_stdio_server.rs — resultType: "input_required", inputRequests.approval.method = "elicitation/create"), and codex-rs/rmcp-client/tests/mcp_2026_mrtr.rs asserts it is handled. So the server response appears conformant by codex's own fixtures.
Where it breaks (as far as I can trace from source)
- The outer error string comes from
codex-rs/codex-mcp/src/connection_manager.rs("tool call failed for{server}/{tool}"), which calls the typedclient.call_tool(...)and converts viacall_tool_result_from_rmcp(result). - The inner
Unexpected response typeis rmcp'sServiceError::UnexpectedResponse(crates/rmcp/src/service.rs), raised by the strict typed-response match:ServerResult::CallToolResult(r) => Ok(r), _ => Err(ServiceError::UnexpectedResponse). Aninput_requiredresult is (correctly) not aCallToolResult, so the typed helper rejects it before any MRTR handling can run. - i.e. the MRTR-aware path in
codex-rs/rmcp-clientexists and is tested, but thecodex-mcpconnection-manager path used for these tool calls doesn't route through it — capability declaration and result handling are out of sync.
Why this matters more than the sibling decode issues
Related open issues hit the same UnexpectedResponse arm via decode strictness (#29002 — valid result decodes as CustomResult; #38979 — non-integer priority annotation). This one is different in kind: the client advertises elicitation.url per-request, which per spec invites servers to send url-mode input requests — and then hard-fails on the conforming response. Until the handling path catches up, declaring the capability makes behavior strictly worse than not declaring it.
A second-order safety effect worth flagging: when the human-approval elicitation errors out, the agent's natural recovery is to look for an equivalent tool that isn't behind the gate and try again — i.e. the failure mode actively steers agents around human-in-the-loop approvals.
Suggested fix directions
- Route
tools/callresults on thecodex-mcppath through the sameinput_required-aware handlingrmcp-clientalready has (or extendcall_tool_result_from_rmcpto accept the MRTR variant), or - until then, stop declaring
elicitation.urlin the_metacapabilities on paths that can't fulfill it, so conforming servers use their fallback carriers.
Happy to provide full wire captures or test against a fix.
1 Comment
Reproduced in both the desktop app and the CLI — identical error either way, which is consistent with the trace above: both surfaces route tool calls through the same
codex-mcpconnection-manager path.