streamable-http MCP transport ignored, falls back to SSE

Resolved 💬 3 comments Opened Mar 10, 2026 by bhuvii-nuvai Closed Apr 19, 2026

Bug Description

When configuring an MCP server with "type": "streamable-http" in ~/.claude/mcp.json, Claude Code ignores the transport type and always uses the legacy SSE transport instead.

Steps to Reproduce

  1. Configure an MCP server in ~/.claude/mcp.json:
{
  "mcpServers": {
    "my-server": {
      "type": "streamable-http",
      "url": "https://example.com/api/mcp",
      "headers": {
        "Authorization": "Bearer <token>"
      }
    }
  }
}
  1. The server correctly implements the streamable-http protocol (POST-based JSON-RPC with optional SSE responses)
  2. Start Claude Code — the server fails to connect

Expected Behavior

Claude Code should use the streamable-http transport (POST requests) as specified in the config.

Actual Behavior

Claude Code uses the legacy SSE transport (GET request) regardless of the "type": "streamable-http" setting. From the MCP logs:

{"debug":"SSE transport initialized, awaiting connection",...}
{"debug":"SSE Connection failed after 1172ms: {...\"error\":\"SSE error: Non-200 status code (405)\",...}"}
{"error":"Connection failed: SSE error: Non-200 status code (405)"}

The server correctly returns 405 for GET (it only supports POST for streamable-http), but Claude Code treats this as a fatal connection failure instead of using the POST-based transport.

Verification

The server works correctly when called with proper streamable-http semantics:

curl -X POST https://example.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer <token>" \
  -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
# Returns 200 with valid MCP initialize response

Additional Context

  • Also logs misleading "Token expired without refresh token" messages for servers using static bearer tokens (not OAuth)
  • The "type" field in ~/.claude/mcp.json appears to have no effect on transport selection
  • Reproducible across all projects (tested in multiple working directories)

Environment

  • Claude Code version: 2.1.71
  • OS: Linux (Ubuntu)
  • MCP server: Vercel-deployed streamable-http server using @modelcontextprotocol/sdk

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗