codex - 💡(How to fix) Fix Streamable HTTP MCP client fails to parse Penpot MCP responses

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

tool call error: tool call failed for penpot/execute_code

Caused by: Transport send error: Transport [rmcp::transport::worker::WorkerTransport<rmcp::transport::streamable_http_client::StreamableHttpClientWorker<codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter>>] error: Deserialize error: data did not match any variant of untagged enum JsonRpcMessage

Root Cause

Caused by: Transport send error: Transport [rmcp::transport::worker::WorkerTransport<rmcp::transport::streamable_http_client::StreamableHttpClientWorker<codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter>>] error: Deserialize error: data did not match any variant of untagged enum JsonRpcMessage

Code Example

[
  {
    "name": "penpot",
    "enabled": true,
    "transport": {
      "type": "streamable_http",
      "url": "http://localhost:4401/mcp",
      "bearer_token_env_var": null,
      "http_headers": null,
      "env_http_headers": null
    },
    "startup_timeout_sec": 10.0,
    "tool_timeout_sec": 120.0,
    "auth_status": "unsupported"
  }
]

---

@penpot/mcp 2.15.0

---

node dist/index.js
Modern Streamable HTTP endpoint: http://localhost:4401/mcp
WebSocket server URL: ws://localhost:4402

---

[::1]:4402  <->  [::1]:54736  chromium

---

name: penpot
   url: http://localhost:4401/mcp
   transport: streamable_http

---

return 1;

---

{
  "result": 1,
  "log": ""
}

---

tool call error: tool call failed for `penpot/execute_code`

Caused by:
    Transport send error: Transport [rmcp::transport::worker::WorkerTransport<rmcp::transport::streamable_http_client::StreamableHttpClientWorker<codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter>>] error: Deserialize error: data did not match any variant of untagged enum JsonRpcMessage

---

curl -i -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":201,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"codex-probe","version":"0.0.1"}}}' \
  http://localhost:4401/mcp

---

HTTP/1.1 200 OK
content-type: text/event-stream
mcp-session-id: f64e1bf9-1a1a-4e4c-818a-3cf04f643d61

event: message
data: {"result":{"protocolVersion":"2025-03-26","capabilities":{"tools":{"listChanged":true}},"serverInfo":{"name":"penpot","version":"1.0.0"},"instructions":"..."},"jsonrpc":"2.0","id":201}

---

curl -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'mcp-session-id: f64e1bf9-1a1a-4e4c-818a-3cf04f643d61' \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' \
  http://localhost:4401/mcp

curl -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'mcp-session-id: f64e1bf9-1a1a-4e4c-818a-3cf04f643d61' \
  -d '{"jsonrpc":"2.0","id":204,"method":"tools/call","params":{"name":"execute_code","arguments":{"code":"return 1;"}}}' \
  http://localhost:4401/mcp

---

event: message
data: {"result":{"content":[{"type":"text","text":"{\n  \"result\": 1,\n  \"log\": \"\"\n}"}]},"jsonrpc":"2.0","id":204}

---

Page: Page 1
Root: Root Frame
Root children: 0
Selection: 0
RAW_BUFFERClick to expand / collapse

What version of Codex is running?

codex-cli 0.134.0

Installed package metadata reports @openai/[email protected].

What platform is your computer?

Linux x86_64, running Codex CLI locally.

What issue are you seeing?

Codex can discover a local Penpot MCP server configured as streamable_http, but tool calls through Codex's registered MCP wrapper fail with a JSON-RPC deserialize error.

The same Penpot MCP server works when called directly over HTTP using the MCP Streamable HTTP endpoint, including executing code in the connected Penpot plugin. That makes this look like an interop/transport parsing issue in Codex's MCP client rather than a broken Penpot file/plugin setup.

MCP server config observed by Codex

[
  {
    "name": "penpot",
    "enabled": true,
    "transport": {
      "type": "streamable_http",
      "url": "http://localhost:4401/mcp",
      "bearer_token_env_var": null,
      "http_headers": null,
      "env_http_headers": null
    },
    "startup_timeout_sec": 10.0,
    "tool_timeout_sec": 120.0,
    "auth_status": "unsupported"
  }
]

Penpot MCP package:

@penpot/mcp 2.15.0

Penpot MCP server process:

node dist/index.js
Modern Streamable HTTP endpoint: http://localhost:4401/mcp
WebSocket server URL: ws://localhost:4402

The Penpot plugin WebSocket is connected:

[::1]:4402  <->  [::1]:54736  chromium

What steps can reproduce the bug?

  1. Start the local Penpot MCP server from @penpot/[email protected].

  2. Configure Codex with the streamable HTTP server:

    name: penpot
    url: http://localhost:4401/mcp
    transport: streamable_http
  3. In Penpot, load the MCP plugin from http://localhost:4400/manifest.json, open the plugin UI, and click "Connect to MCP server".

  4. Confirm the WebSocket to localhost:4402 is established.

  5. In Codex, call any registered Penpot MCP tool, for example penpot/high_level_overview or penpot/execute_code.

Expected behavior

Codex should parse the Penpot MCP Streamable HTTP response and return the tool result.

For example, execute_code with:

return 1;

should return:

{
  "result": 1,
  "log": ""
}

Actual behavior

Codex tool calls fail before returning the MCP tool result:

tool call error: tool call failed for `penpot/execute_code`

Caused by:
    Transport send error: Transport [rmcp::transport::worker::WorkerTransport<rmcp::transport::streamable_http_client::StreamableHttpClientWorker<codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter>>] error: Deserialize error: data did not match any variant of untagged enum JsonRpcMessage

The same deserialize error also happens for penpot/high_level_overview.

Direct MCP HTTP control succeeds

Calling the same server directly works.

Initialize:

curl -i -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":201,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"codex-probe","version":"0.0.1"}}}' \
  http://localhost:4401/mcp

Response:

HTTP/1.1 200 OK
content-type: text/event-stream
mcp-session-id: f64e1bf9-1a1a-4e4c-818a-3cf04f643d61

event: message
data: {"result":{"protocolVersion":"2025-03-26","capabilities":{"tools":{"listChanged":true}},"serverInfo":{"name":"penpot","version":"1.0.0"},"instructions":"..."},"jsonrpc":"2.0","id":201}

Then:

curl -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'mcp-session-id: f64e1bf9-1a1a-4e4c-818a-3cf04f643d61' \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' \
  http://localhost:4401/mcp

curl -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'mcp-session-id: f64e1bf9-1a1a-4e4c-818a-3cf04f643d61' \
  -d '{"jsonrpc":"2.0","id":204,"method":"tools/call","params":{"name":"execute_code","arguments":{"code":"return 1;"}}}' \
  http://localhost:4401/mcp

Response:

event: message
data: {"result":{"content":[{"type":"text","text":"{\n  \"result\": 1,\n  \"log\": \"\"\n}"}]},"jsonrpc":"2.0","id":204}

A direct execute_code probe also successfully inspected the open Penpot file:

Page: Page 1
Root: Root Frame
Root children: 0
Selection: 0

Why this seems distinct from related issues

This is related to MCP deserialize failures, but it does not appear to be a non-2xx HTTP response case like #20513: the direct response is HTTP/1.1 200 OK with content-type: text/event-stream.

It also differs from Codex Desktop app connector failures like #23606 because this is a user-configured local streamable_http MCP server in Codex CLI, and direct MCP calls to the same endpoint succeed.

Additional notes

There may still be a Penpot-side compatibility edge if the server is emitting Streamable HTTP/SSE in a form stricter clients reject. But since direct MCP HTTP calls work and Codex reports a deserialize error in codex_rmcp_client::http_client_adapter, I am filing this first on the Codex side.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Codex should parse the Penpot MCP Streamable HTTP response and return the tool result.

For example, execute_code with:

return 1;

should return:

{
  "result": 1,
  "log": ""
}

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix Streamable HTTP MCP client fails to parse Penpot MCP responses