Streamable HTTP MCP fails before initialize for local Unity/FastMCP server; Codex only performs OAuth discovery GETs then reports missing-content-type

Open 💬 1 comment Opened Jun 8, 2026 by weypro

What version of the Codex App are you using (From “About Codex” dialog)?

26.602.40724

What subscription do you have?

plus

What platform is your computer?

_No response_

What issue are you seeing?

Summary

Codex fails to connect to a local Streamable HTTP MCP server from MCP for Unity / FastMCP.

The MCP server is healthy and works with direct MCP requests, including initialize, notifications/initialized, and tools/list. However, Codex never sends the expected POST /mcp initialize request. Instead, it only sends OAuth discovery GET requests, receives 404 responses, then reports:

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: Unexpected content type: Some("missing-content-type; body: "), when send initialize request

This looks related to #13920 and #14793, but this report includes a more specific packet-level observation: Codex does not reach the MCP initialize POST at all.

Environment

  • OS: Windows 10, Microsoft Windows NT 10.0.19045.0
  • Shell: PowerShell 7.6.0
  • Codex CLI: codex-cli 0.137.0-alpha.4
  • Codex Desktop app version: 26.602.40724
  • MCP server: mcpforunityserver==9.7.1
  • Unity: 6000.3.17f1
  • MCP transport: Streamable HTTP
  • MCP URL: http://127.0.0.1:8080/mcp

Codex MCP config

[mcp_servers.unityMCP]
url = "http://127.0.0.1:8080/mcp"

codex mcp get unityMCP reports:

unityMCP
  enabled: true
  transport: streamable_http
  url: http://127.0.0.1:8080/mcp
  bearer_token_env_var: -
  http_headers: -
  env_http_headers: -

Server health checks

The Unity MCP HTTP server is running and healthy.

GET http://127.0.0.1:8080/health returns:

{
  "status": "healthy",
  "version": "9.7.1",
  "message": "MCP for Unity server is running"
}

GET http://127.0.0.1:8080/api/instances returns a connected Unity instance:

{
  "success": true,
  "instances": [
    {
      "project": "dancetest",
      "unity_version": "6000.3.17f1"
    }
  ]
}

Direct MCP protocol validation succeeds

Using a direct HTTP/SSE MCP client sequence against http://127.0.0.1:8080/mcp succeeds:

  1. POST initialize
  2. receives 200 SSE response with serverInfo.name = "mcp-for-unity-server"
  3. receives mcp-session-id
  4. POST notifications/initialized
  5. POST tools/list
  6. receives a valid tools list including tools such as:
  • batch_execute
  • execute_code
  • find_gameobjects
  • manage_asset
  • manage_camera

So the server is reachable and can complete the normal MCP lifecycle outside Codex.

Codex behavior

When Codex starts a session, the local logs show it sees the configured MCP server and starts building the tool list.

For other MCP servers, the sequence completes:

waiting for MCP server tools while building tool list server_name=node_repl ...
listed MCP server tools while building tool list server_name=node_repl tool_count=3

waiting for MCP server tools while building tool list server_name=ida_pro_mcp ...
listed MCP server tools while building tool list server_name=ida_pro_mcp tool_count=65

For Unity MCP, Codex only logs:

waiting for MCP server tools while building tool list server_name=unityMCP has_cached_tool_info_snapshot=false startup_complete=true

There is no corresponding:

listed MCP server tools while building tool list server_name=unityMCP

The tools are therefore never exposed to the model.

Packet-level reproduction

I placed a local forwarding proxy in front of the Unity MCP endpoint:

  • Codex URL: http://127.0.0.1:18080/mcp
  • Proxy target: http://127.0.0.1:8080/mcp

Then I ran a clean Codex CLI invocation with only this MCP server configured:

codex exec `
  --ephemeral `
  --ignore-user-config `
  --skip-git-repo-check `
  --dangerously-bypass-approvals-and-sandbox `
  -C "G:\projects\dance-test" `
  -c 'model="gpt-5.5"' `
  -c 'mcp_servers.unityMCP={url="http://127.0.0.1:18080/mcp", startup_timeout_sec=5, tool_timeout_sec=10}' `
  --json `
  'Please only reply ok and do not call any tools.'

Codex returned the model response, but stderr contained:

ERROR rmcp::transport::worker: worker quit with fatal:
Transport channel closed, when UnexpectedContentType(Some("missing-content-type; body: "))

WARN codex_mcp::rmcp_client:
failed to initialize MCP client during shutdown:
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: Unexpected content type: Some("missing-content-type; body: "), when send initialize request

The proxy captured only these requests from Codex:

[
  {
    "method": "GET",
    "url": "/.well-known/oauth-authorization-server/mcp",
    "status": 404,
    "reqHeaders": {
      "mcp-protocol-version": "2024-11-05",
      "accept": "*/*"
    },
    "resHeaders": {
      "content-type": "text/plain; charset=utf-8"
    },
    "body": "Not Found"
  },
  {
    "method": "GET",
    "url": "/mcp/.well-known/oauth-authorization-server",
    "status": 404,
    "reqHeaders": {
      "mcp-protocol-version": "2024-11-05",
      "accept": "*/*"
    },
    "resHeaders": {
      "content-type": "text/plain; charset=utf-8"
    },
    "body": "Not Found"
  },
  {
    "method": "GET",
    "url": "/.well-known/oauth-authorization-server",
    "status": 404,
    "reqHeaders": {
      "mcp-protocol-version": "2024-11-05",
      "accept": "*/*"
    },
    "resHeaders": {
      "content-type": "text/plain; charset=utf-8"
    },
    "body": "Not Found"
  }
]

No POST /mcp initialize request was observed.

Expected behavior

For a local Streamable HTTP MCP server with no OAuth configured and no auth challenge from the MCP endpoint, Codex should proceed to the normal MCP lifecycle:

  1. POST /mcp with initialize
  2. receive SSE or JSON initialize response
  3. send notifications/initialized
  4. call tools/list
  5. expose the returned tools

OAuth discovery returning 404 should not prevent initialization for a non-OAuth local MCP server.

Actual behavior

Codex performs OAuth discovery GETs, receives 404, then fails the MCP startup before sending the actual initialize request.

As a result, the MCP server is configured and healthy, but no tools become available.

Related issues

  • #13920: similar local Streamable HTTP MCP failure where direct requests work but Codex fails
  • #14793: similar missing-content-type handshake failure
  • #24439: diagnostic gap for MCP startup/tool discovery failures

What steps can reproduce the bug?

see above

What is the expected behavior?

_No response_

Additional information

_No response_

View original on GitHub ↗

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