Minimal MCP server (stdio, zero dependencies) showing that Codex rejects a tool
result containing an MCP Apps resource_link content block with
Unexpected response type, while an otherwise identical text-only result works.
The server exposes two tools that differ only in their result:
| Tool | Result content | Codex |
|---|---|---|
plain_tool |
[text] |
works |
view_tool |
[text, resource_link(ui://…)] |
fails |
resource_link is the only variable.
Requires Node 18+. No install step.
node server.js
Register the server, then call each tool.
Config (~/.codex/config.toml):
[mcp_servers.apps_repro]
command = "node"
args = ["/absolute/path/to/server.js"]Then in a session:
- Call
plain_tool→ returnsplain result. - Call
view_tool→ fails with:
tool call failed for `apps_repro/view_tool`
Caused by:
Unexpected response type
- Expected:
view_toolis accepted; theresource_linkblock is handled or ignored. - Actual: the whole call fails with
Unexpected response type.
Unexpected response type is rmcp's ServiceError::UnexpectedResponse, raised
client-side when a ServerResult does not match CallToolResult. However, the
view_tool result is valid and rmcp 3.1.3 (the version Codex pins) deserializes
it without issue: a standalone rmcp 3.1.3 client, using both call_tool and the
manual send_request + match ServerResult::CallToolResult path, accepts it and
returns [text, resource_link]. So the defect appears to be in the layer that
consumes tool results, not in rmcp deserialization. The server advertises the
io.modelcontextprotocol/ui extension in initialize, and view_tool returns a
spec-valid resource_link.