MCP Streamable HTTP handshake fails with n8n MCP server after initialize

Open 💬 1 comment Opened May 9, 2026 by quent1nQ

Summary

Codex CLI fails to start a Streamable HTTP MCP server backed by n8n's official instance-level MCP endpoint. The remote endpoint is reachable and returns the expected MCP server info/tools when queried directly, but Codex startup fails during the post-initialize notifications/initialized step with Transport channel closed.

This looks related to prior Streamable HTTP/RMCP handshake edge cases, but still reproduces with the current Codex CLI release in this n8n MCP combination.

Environment

  • Codex CLI: codex-cli 0.130.0
  • oh-my-codex wrapper: oh-my-codex v0.16.2
  • Platform: macOS / darwin arm64
  • Node.js: v24.1.0
  • Remote MCP server: n8n official instance-level MCP endpoint
  • Remote MCP serverInfo from initialize: name: "n8n MCP Server", version: "1.1.0"
  • Transport: Streamable HTTP

Codex MCP config shape

[mcp_servers.n8n_mcp]
url = "https://<n8n-host>/mcp-server/http"
http_headers = { "authorization" = "Bearer <redacted>" }

codex mcp get n8n_mcp reports:

n8n_mcp
  enabled: true
  transport: streamable_http
  url: https://<n8n-host>/mcp-server/http
  bearer_token_env_var: -
  http_headers: authorization=*****

Failure during Codex/OMX startup

⚠ MCP client for `n8n_mcp` failed to start: MCP startup failed: handshaking with MCP server failed: Send message error Transport
  [rmcp::transport::worker::WorkerTransport<rmcp::transport::streamable_http_client::StreamableHttpClientWorker<codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter>>]
  error: Transport channel closed, when send initialized notification

⚠ MCP startup incomplete (failed: n8n_mcp)

What works outside Codex

Using the same URL/token, a direct JSON-RPC initialize request succeeds and returns SSE:

HTTP/2 200
content-type: text/event-stream

serverInfo: { name: "n8n MCP Server", version: "1.1.0" }
capabilities: { tools: { listChanged: true }, resources: { listChanged: true } }

A direct tools/list request to the same endpoint/token returns 25 tools, including write/build tools:

search_workflows
execute_workflow
get_execution
get_workflow_details
publish_workflow
unpublish_workflow
prepare_test_pin_data
test_workflow
search_data_tables
create_data_table
rename_data_table
add_data_table_column
delete_data_table_column
rename_data_table_column
add_data_table_rows
search_nodes
get_node_types
get_suggested_nodes
validate_workflow
create_workflow_from_code
search_projects
search_folders
archive_workflow
update_workflow
get_sdk_reference

A basic direct notifications/initialized POST also receives HTTP/2 202 from the endpoint when sent manually with curl, but Codex/RMCP still fails at this startup phase. That suggests the issue may depend on the exact request shape/session/header handling used by the Streamable HTTP client during handshake.

Additional observation

Testing mcp-remote as a stdio proxy against the same endpoint also fails during the initialized notification stage:

Connection error: StreamableHTTPError: Streamable HTTP error: Error POSTing to endpoint:
...
code: 400

So this may be a broader client/server interoperability edge case around Streamable HTTP initialization rather than a simple auth or endpoint configuration problem.

Expected behavior

Codex should successfully complete MCP startup and expose the n8n MCP tools, including create_workflow_from_code, update_workflow, validate_workflow, and publish_workflow.

Actual behavior

Codex fails MCP startup after initialize, when sending the initialized notification, and the server is not registered for use inside Codex.

Notes

  • The token and actual host are intentionally redacted.
  • The same endpoint/token can be used directly to initialize and list tools, so auth and server availability appear valid.
  • Related-looking prior issue: #5208 / PR #5542, but this reproduces on codex-cli 0.130.0 with n8n MCP Server 1.1.0.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗