`unsupported call: mcp__<server>__<tool>` for MCP tools when used with custom Responses API provider (Apps SDK + custom model)
Summary
When Codex is configured with a custom model provider that uses wire_api = "responses" (for example, MiniMax-M3 against api.minimaxi.com/v1, or llama.cpp with the Responses adapter), calls to MCP tools — including Apps SDK / UI widget MCP servers like Cowart — are rejected by Codex's tool dispatcher with the literal error:
error=unsupported call: mcp__<server>__<tool>
The MCP servers themselves are healthy and respond normally when invoked directly outside Codex. The failure happens before the MCP child process is reached. This blocks every MCP-driven plugin for non-OpenAI providers.
Environment
- Codex Desktop:
26.623.141536(Codex CLI0.142.5) - OS: macOS 26.5.1
- Model provider (custom):
```toml
model_provider = "custom"
model = "MiniMax-M3"
[model_providers.custom]
name = "minimax"
base_url = "https://api.minimaxi.com/v1"
wire_api = "responses"
requires_openai_auth = true
experimental_bearer_token = "<token>"
```
- MCP server used in the reproduction: Cowart
v0.1.11(Apps SDK / UI widget MCP,registerAppTool+_meta.ui.resourceUri+openai/outputTemplate = ui://widget/cowart/canvas.html).
Reproduction
- Install and enable the Cowart plugin in
~/.codex/config.toml:
``toml``
[plugins."cowart@personal"]
enabled = true
- Run the Cowart MCP probe outside Codex to confirm the server is healthy:
````
$ cd ~/.codex/plugins/cache/personal/cowart/0.1.11
$ node ./scripts/probe-mcp.mjs
OK: Cowart MCP tools and native widget resource are available.
- Start a Codex thread on
MiniMax-M3. Send: "Open the Cowart canvas for this project." - Model emits
function_callformcp__cowart_mcp__render_cowart_canvas_widget. Codex logs show:
````
dispatch_tool_call_with_code_mode_result{
otel.name = mcp__cowart_mcp__render_cowart_canvas_widget
tool_name = mcp__cowart_mcp__render_cowart_canvas_widget
call_id = "call_019f3a99811d726095284eed"
aborted = false
}:dispatch_tool_call_with_terminal_outcome:
error = unsupported call: mcp__cowart_mcp__render_cowart_canvas_widget
- The same error is produced for non-widget Cowart tools too (
get_cowart_canvas_state,save_cowart_canvas_state, etc.). Every call to anymcp__cowart_mcp__*tool fails identically.
Expected
- The widget tool should render the native Cowart canvas UI (
openai/outputTemplateresolution), and - Non-widget Cowart tools should execute against the MCP child process and return their
structuredContent.
Actual
- Every
mcp__cowart_mcp__*call is rejected at the Codex dispatcher withunsupported call: <tool>, regardless of whether the tool is an Apps SDK widget tool or a regular MCP tool. - Searching
~/.codex/logs_2.sqliteshows all 7 hits for this error string come from theMiniMax-M3provider; no occurrences undergpt-*models in the same time window.
Root cause (best guess, from Codex CLI binary strings)
The error is emitted by the dispatcher at core/src/tools/router.rs:185 (dispatch_tool_call_with_terminal_outcome). The function only knows how to route tool calls that match a known tool-kind arm; for everything else it falls through to unsupported call: <name>.
For Apps SDK widget MCP servers, Codex has a separate context type McpToolCallAppContext (with mcpAppResourceUri) and a corresponding dispatch path. When the model provider is OpenAI-native, the framework rewrites / re-emits Apps SDK tool calls into that path. With custom wire_api = "responses" providers, that rewrite is skipped — the model returns a plain function_call payload (e.g. call_id = "call_019f3a99..."), which the dispatcher does not recognize and rejects with unsupported call.
This explains why:
- Widget MCP tools (Cowart, Canva, Computer Use, …) all fail.
- Non-widget MCP tools on the same server also fail when registered by an Apps MCP server, because the whole server is treated as an Apps namespace.
- The probe script (
node scripts/probe-mcp.mjs) succeeds — the failure is purely on the Codex dispatch side, not on the MCP child process. - The error is provider-specific: switching back to the default OpenAI model in the same Codex build makes identical MCP calls succeed.
Related symptoms observed in ~/.codex/logs_2.sqlite under the same provider:
| tool_name | provider |
| ----------------------------------------------- | ---------- |
| mcp__cowart_mcp__render_cowart_canvas_widget | MiniMax-M3 |
| mcp__cowart_mcp__get_cowart_canvas_state | MiniMax-M3 |
| mcp__node_repl__js | MiniMax-M3 |
| mcp__codex_apps__github___search | MiniMax-M3 |
| multi_agent_v1__close_agent | MiniMax-M3 |
Suggested fix (in order of preference)
- In
core/src/tools/router.rs:185, fall through to the Apps SDK dispatch path whenever the MCP server exposes an Apps SDK resource (openai/outputTemplateon any of its tools) instead of returningunsupported call. - When a custom provider returns a
function_callfor a server whose tools are Apps SDK widget tools, wrap the call into theMcpToolCallAppContext/mcpAppResourceUrishape so the existing widget rendering pipeline can run. - As a longer-term fix, distinguish "Apps SDK MCP server" from "regular MCP server" at server-spawn time (not per-tool), so the dispatcher picks the right arm up front.
Workarounds
- Switch the thread model back to a default OpenAI model: Cowart renders correctly.
- Patch Cowart locally to register
render_cowart_canvas_widgetviamcpServer.registerTool(without_meta.ui.*) instead ofregisterAppTool. This loses the native widget UI but restores function-call dispatch.
Related
- openai/codex#30902 — same provider (
MinimaxM3), three different MCP servers all returningunsupported call. The reproduction in this issue is the same class of failure. - openai/codex#26977 — same error, llama.cpp provider, detailed RCA already in the report.
- openai/codex#22970 — same error class on Windows.
- openai/codex#21019 — Codex Desktop does not render MCP Apps inline UI resources; related but on the rendering side rather than dispatch.
- zhongerxin/Cowart#37 — Cowart UI does not render. Different failure mode (the tool returns successfully there, Codex just doesn't render the widget).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗