Skip to content

MCP tools/call fails with Unexpected response type when valid tool result decodes as CustomResult #29002

@ytsssun

Description

@ytsssun

What version of Codex CLI is running?

codex-cli 0.141.0

What subscription do you have?

ChatGPT Pro. This local repro is running Codex CLI with an Amazon Bedrock model provider.

Which model were you using?

gpt-5.5

What platform is your computer?

Linux 6.12.90-120.164.amzn2023.x86_64 x86_64 x86_64

What terminal emulator and version are you using (if applicable)?

zsh under zellij 0.44.2 over SSH. The noninteractive repro environment reports TERM=dumb.

Codex doctor report

Redacted summary from codex doctor --json:

{
  "overallStatus": "fail",
  "codexVersion": "0.141.0",
  "checks": {
    "config.load": {
      "status": "ok",
      "summary": "config loaded",
      "details": {
        "mcp servers": "3",
        "model": "openai.gpt-5.5",
        "model provider": "amazon-bedrock"
      }
    },
    "installation": {
      "status": "ok",
      "summary": "installation looks consistent"
    },
    "mcp.config": {
      "status": "ok",
      "summary": "MCP configuration is locally consistent",
      "details": {
        "configured servers": "3",
        "disabled servers": "0",
        "stdio servers": "3"
      }
    },
    "runtime.provenance": {
      "status": "ok",
      "summary": "running standalone on linux-x86_64",
      "details": {
        "platform": "linux-x86_64",
        "version": "0.141.0"
      }
    },
    "terminal.env": {
      "status": "fail",
      "summary": "TERM=dumb - colors and cursor control are disabled"
    },
    "updates.status": {
      "status": "warning",
      "summary": "update configuration is locally consistent"
    }
  }
}

What issue are you seeing?

Codex can initialize a stdio MCP server and discover tools, but every tools/call fails with:

Unexpected response type

This was observed with an internal stdio MCP server. The same MCP server and same tools work through another MCP client, which suggests the server response is valid MCP and this is a Codex client-side result handling issue. If this were a tool-level auth, permissions, or application error, the server would return a normal MCP tool result containing that error payload. Instead Codex fails below tool logic while decoding/dispatching the JSON-RPC result.

Tracing showed that rmcp successfully parsed the JSON-RPC response, but represented the tools/call result as ServerResult::CustomResult(...) rather than ServerResult::CallToolResult(...):

PeerMessage(Response(... result: CustomResult(... redacted valid tools/call payload ...)))
...
Unexpected response type

The redacted custom result payload has the expected MCP CallToolResult shape, including a content array of text content blocks. Codex currently accepts only ServerResult::CallToolResult in rmcp-client, so a valid tool-call payload can be rejected solely because rmcp decoded it through the extensibility/custom-result variant.

What steps can reproduce the bug?

  1. Configure Codex CLI 0.141.0 with a stdio MCP server that returns a normal tools/call JSON-RPC result shape but is decoded by rmcp as ServerResult::CustomResult.
  2. Call any tool exposed by that server.
  3. Observe that initialization and discovery succeed, but the tool call fails with Unexpected response type.

Observed repro details:

  • Transport: stdio MCP
  • Server details: redacted internal MCP server
  • initialize, tools/list, and other discovery paths succeed
  • tools/call fails identically across tools
  • Raw trace shows the response decoded as ServerResult::CustomResult(... redacted valid tools/call payload ...)

What is the expected behavior?

For a tools/call request, Codex should accept a ServerResult::CustomResult if and only if its payload cleanly deserializes as an MCP CallToolResult.

It should still reject unrelated custom result shapes for tools/call.

Additional information

I have a tested local fix that keeps this narrow:

  • Preserve the existing ServerResult::CallToolResult path.
  • Add a coercion path for ServerResult::CustomResult that attempts to deserialize the custom payload into CallToolResult.
  • Return UnexpectedResponse for non-tool custom shapes or any other response variant.
  • Add unit coverage for:
    • Custom result with a valid CallToolResult shape
    • Normal CallToolResult
    • Invalid custom result that should still be rejected

Patch branch is available here:

https://github.com/ytsssun/codex/tree/fix/mcp-call-tool-custom-result

Local commit:

4a010370335e0ce30100164c6dff616bd74639c2 Handle custom MCP tool call results

Verification run against the patch:

cargo test -p codex-rmcp-client coerce_call_tool_result -- --nocapture
# 3 passed

cargo test -p codex-rmcp-client --no-fail-fast
# all passed

I also validated the patched Codex CLI against the same raw internal MCP binary with no compatibility wrapper. The previously failing tool call returned a normal redacted JSON tool result successfully.

This is related to MCP parse/interop issues, but it appears distinct from #25451: this case is stdio tools/call, and the JSON-RPC frame is already decoded into an rmcp::model::ServerResult; Codex then rejects the CustomResult variant as an unexpected response type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingmcpIssues related to the use of model context protocol (MCP) serverstool-callsIssues related to tool calling

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions