codex - 💡(How to fix) Fix Splunk MCP not working with Codex CLI - handshaking with MCP server failed [1 participants]

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…
GitHub stats
openai/codex#20982Fetched 2026-05-05 05:55:00
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
labeled ×5

Error Message

⚠ MCP client for splunk-mcp-server 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

Root Cause

Root cause (suspected, based on log + spec + behavior of other clients):

Code Example

[mcp_servers.splunk-mcp-server]
url = "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp"
bearer_token_env_var = "SPLUNK_TOKEN"
startup_timeout_sec = 30
tool_timeout_sec = 60

---

MCP client for `splunk-mcp-server` 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

---

{
  "mcpServers": {
    "splunk-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://prd-p-8zn1c.splunkcloud.com:8089/services/mcp",
        "--header",
        "Authorization: Bearer <Your Token>"
      ]
    }
  }
}

---

"splunk-mcp-server": {
      "url": "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp",
      "headers": {
        "Authorization": "Bearer TOKEN"
      }
    }

---

[mcp_servers.splunk-mcp-server]
command = "npx"
args = [
  "-y",
  "mcp-remote",
  "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp",
  "--header",
  "Authorization: Bearer ${SPLUNK_TOKEN}",
]
env_vars = ["SPLUNK_TOKEN"]
startup_timeout_sec = 30
tool_timeout_sec = 60
RAW_BUFFERClick to expand / collapse

What version of Codex CLI is running?

codex-cli 0.128.0

What subscription do you have?

Business

Which model were you using?

gpt-5.5

What platform is your computer?

Darwin 25.2.0 arm64 arm

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

Warp

What issue are you seeing?

Human description: Hi all, we are trying to use Splunk MCP in codex CLI. I configured in the config.toml the following:

[mcp_servers.splunk-mcp-server]
url = "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp"
bearer_token_env_var = "SPLUNK_TOKEN"
startup_timeout_sec = 30
tool_timeout_sec = 60

When I start Codex CLI I get the following warning.

⚠ MCP client for `splunk-mcp-server` 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

When I configured Cursor to work with Splunk MCP it works fine (as it was configured like this per their documentation)

{
  "mcpServers": {
    "splunk-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://prd-p-8zn1c.splunkcloud.com:8089/services/mcp",
        "--header",
        "Authorization: Bearer <Your Token>"
      ]
    }
  }
}

And also when I configured it as

  "splunk-mcp-server": {
     "url": "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp",
     "headers": {
       "Authorization": "Bearer TOKEN"
     }
   }

it also worked fine.

However, in Codex when I configure it as I described above, I get the error mentioned.

When I configure codex cli with the following, it works

[mcp_servers.splunk-mcp-server]
command = "npx"
args = [
  "-y",
  "mcp-remote",
  "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp",
  "--header",
  "Authorization: Bearer ${SPLUNK_TOKEN}",
]
env_vars = ["SPLUNK_TOKEN"]
startup_timeout_sec = 30
tool_timeout_sec = 60

What steps can reproduce the bug?

  1. You will need splunk account with token and install the Splunk MCP server
  2. use the infromation from splunk (token and url) and configure the MCP in codex
  3. start codex
  4. try to use the MCP to get information from splunk

What is the expected behavior?

not error from codex on splunk MCP and the MCP is working as expected

Additional information

LLM Generated description:

codex-rmcp-client registers a Streamable-HTTP MCP server in ~/.codex/config.toml, the server appears under codex mcp list and codex mcp get <name>, but at runtime the model never sees the server's tools. How the failure is presented to the user differs by entrypoint:

Under codex exec — silent. No error in user-facing output. The only signal is in RUST_LOG=codex_rmcp_client=debug,rmcp=debug stderr:

INFO serve_inner: rmcp::service: Service initialized as client peer_info=Some(InitializeResult { protocol_version: ProtocolVersion("2025-06-18"), capabilities: ServerCapabilities { ... tools: Some(ToolsCapability { list_changed: Some(false) }) ... }, server_info: Implementation { name: "<server-name>", version: "x.y.z", ... } }) ERROR rmcp::transport::worker: worker quit with fatal: Deserialize error: EOF while parsing a value at line 1 column 0, when send initialized notification Under the interactive codex TUI — surfaced. Same ~/.codex/config.toml, same binary, displays a banner:

⚠ MCP client for splunk-mcp-server 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: splunk-mcp-server) So:

The server's response to initialize is well-formed JSON-RPC and parses fine. The crash is on the client's response to its own notifications/initialized POST. Once the worker quits, the server is removed from the active set. The TUI displays a banner; codex exec displays nothing. The TUI banner pins the crate path: the failing component is codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter, which wraps rmcp::transport::streamable_http_client::StreamableHttpClientWorker. That's where the empty-body deserialize is happening.

Root cause (suspected, based on log + spec + behavior of other clients):

After initialize succeeds, codex-rmcp-client sends the mandatory notifications/initialized JSON-RPC notification as an HTTP POST. The server replies with:

HTTP/1.1 200 OK Content-Type: application/json Content-Length: 0 (empty body) This is normal/expected for notifications. Per JSON-RPC 2.0, notifications have no id and elicit no response, so an empty 2xx is the natural ack. The MCP Streamable-HTTP transport recommends 202 Accepted, but 200 OK with Content-Length: 0 is what real-world MCP servers commonly return, and other lenient clients (see below) accept it.

StreamableHttpClientAdapter (rmcp 0.15.0, wrapped by codex_rmcp_client::http_client_adapter) appears to unconditionally try to deserialize the HTTP response body as JSON. With Content-Length: 0, that fails with serde_json::Error: EOF while parsing a value at line 1 column 0. The transport worker treats this as fatal and exits — which is what the Transport channel closed, when send initialized notification line in the TUI banner is reporting downstream.

Cross-validation that the MCP server is fine:

The same MCP URL + bearer token works end-to-end with:

@modelcontextprotocol/sdk's StreamableHTTPClientTransport (the transport Cursor uses for native HTTP MCP). npx -y mcp-remote https://... --header "Authorization: Bearer ${TOKEN}" (the stdio bridge). Both lenient clients accept the empty-body 2xx ack to notifications/initialized and proceed to tools/list and tools/call normally. Only Codex's built-in rmcp-based transport crashes on it.

What steps can reproduce the bug? Any spec-compliant Streamable-HTTP MCP server that returns 200 OK with Content-Length: 0 (or any empty body) for a notifications/initialized POST will reproduce this. The server I originally hit was Splunk Cloud's MCP at /__raw/services/mcp, but the failure mode is independent of Splunk — it's just one server that exhibits the empty-body ack pattern.

  1. Confirm the server's behavior with curl (no Codex involved):

URL='https://<your-stack>.splunkcloud.com/en-US/splunkd/__raw/services/mcp' curl -k -sS -i -X POST "$URL"
-H "Authorization: Bearer ${SPLUNK_TOKEN}"
-H "Content-Type: application/json"
-H "Accept: application/json, text/event-stream"
-d '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' Expected response (this is the legal, "boring" case that breaks Codex):

HTTP/1.1 200 OK Content-Type: application/json Content-Length: 0 (The same empty-body 2xx pattern can be reproduced with any minimal stateless MCP server that you control — just have the notifications endpoint return 200 OK with no body, or 202 Accepted with no body.)

  1. Configure Codex to use it. In ~/.codex/config.toml:

[mcp_servers.repro] url = "https://<your-stack>.splunkcloud.com/en-US/splunkd/__raw/services/mcp" bearer_token_env_var = "SPLUNK_TOKEN" startup_timeout_sec = 30 3a. Run Codex non-interactively and watch it fail silently:

RUST_LOG=codex_rmcp_client=debug,rmcp=debug
codex exec --skip-git-repo-check --json --full-auto
'List the MCP servers you can see and their tools.' </dev/null Observe:

stderr contains: ERROR rmcp::transport::worker: worker quit with fatal: Deserialize error: EOF while parsing a value at line 1 column 0, when send initialized notification The configured MCP server is not in the list of MCP servers the model enumerates in its answer. There is no error in the user-facing output — the only signal is in RUST_LOG=debug stderr. 3b. Run the same config under the interactive TUI and observe the banner:

codex A banner appears at the top of the TUI:

⚠ MCP client for repro 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: repro) For comparison, the same url + same ${SPLUNK_TOKEN} works perfectly with npx -y mcp-remote "$URL" --header "Authorization: Bearer ${SPLUNK_TOKEN}" and with @modelcontextprotocol/sdk's StreamableHTTPClientTransport.

What is the expected behavior? An empty-body 200 OK (or 202 Accepted) response to a JSON-RPC notification (no id) should be treated as a successful ack, not as a JSON deserialization failure. Notifications, by definition, have no response body to parse. If the MCP transport handshake fails for any reason, the failure should be surfaced to the user regardless of entrypoint — currently the TUI shows a banner but codex exec is silent. The configured MCP server should be reachable from the model and its tools should appear in tools/list.

extent analysis

TL;DR

The issue can be fixed by modifying the Codex CLI configuration to use the command and args parameters instead of url for the Splunk MCP server.

Guidance

  • The error occurs because the StreamableHttpClientAdapter in codex_rmcp_client tries to deserialize the empty response body as JSON, which fails.
  • To fix this, use the command and args parameters in the Codex CLI configuration, as shown in the working example: [mcp_servers.splunk-mcp-server] command = "npx" args = [ "-y", "mcp-remote", "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp", "--header", "Authorization: Bearer ${SPLUNK_TOKEN}", ].
  • Verify that the MCP server is configured correctly and the SPLUNK_TOKEN environment variable is set.
  • Test the configuration using the codex exec command or the interactive TUI to ensure the MCP server is reachable and its tools are listed.

Example

[mcp_servers.splunk-mcp-server]
command = "npx"
args = [
  "-y",
  "mcp-remote",
  "https://prd-p-8zn1c.splunkcloud.com/en-US/splunkd/__raw/services/mcp",
  "--header",
  "Authorization: Bearer ${SPLUNK_TOKEN}",
]
env_vars = ["SPLUNK_TOKEN"]
startup_timeout_sec = 30
tool_timeout_sec = 60

Notes

  • The issue is specific to the codex_rmcp_client and its handling of empty response bodies.
  • The command and args parameters provide a workaround by using the mcp-remote command, which handles the MCP protocol correctly.

Recommendation

Apply the workaround by using

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING