Skip to content

[BUG] HTTP/SSE MCP Transport Ignores Authentication Headers #7290

@martintburgess

Description

@martintburgess

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Claude Code v1.0.108 ignores authentication headers in HTTP and SSE MCP server configurations and always attempts OAuth2 Dynamic Client Registration instead. This affects both X-API-Key and Authorization: Bearer header formats.

Key Issues:

  1. Headers Ignored: Authentication headers in .mcp.json are completely ignored
  2. OAuth Forced: Claude Code always attempts OAuth discovery regardless of header configuration
  3. Multiple Transports Affected: Both http and sse transport types exhibit this behavior

This appears to be a regression or incomplete fix of Issue #2831, which was supposedly resolved in v1.0.40.

What Should Happen?

Claude Code should respect the authentication headers specified in the .mcp.json configuration and send them with MCP requests instead of attempting OAuth2 Dynamic Client Registration.

Expected behavior:

  1. HTTP transport with headers should send the specified headers with requests
  2. SSE transport with headers should send the specified headers with connections
  3. No OAuth discovery requests should be made when headers are explicitly configured
  4. Server should receive requests with the configured authentication headers

Error Messages/Logs

### Claude Code Error Message:

Error: HTTP 404: Invalid OAuth error response: [
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "undefined", 
    "path": [
      "error"
    ],
    "message": "Required"
  }
]. Raw body: {"detail":"Not Found"}


### Server Logs - HTTP Transport:

GET /.well-known/oauth-protected-resource HTTP/1.1 404 Not Found
GET /.well-known/oauth-authorization-server HTTP/1.1 404 Not Found
GET /.well-known/openid-configuration HTTP/1.1 404 Not Found
POST /register HTTP/1.1 404 Not Found
POST / HTTP/1.1 404 Not Found


### Server Logs - SSE Transport (Note malformed paths):

GET /.well-known/oauth-protected-resource/sse HTTP/1.1 404 Not Found
GET /.well-known/oauth-authorization-server/sse HTTP/1.1 404 Not Found
GET /.well-known/openid-configuration/sse HTTP/1.1 404 Not Found
GET /sse/.well-known/openid-configuration HTTP/1.1 404 Not Found
POST /register HTTP/1.1 404 Not Found

Steps to Reproduce

Prerequisites:

  1. Claude Code v1.0.108 (confirmed version with claude --version)
  2. A working MCP server that accepts API key authentication
  3. Server accessible via HTTP (localhost or remote)

Minimal Reproduction Case:

1. Create a simple MCP server

Create a basic FastAPI MCP server with API key authentication:

from fastapi import FastAPI, HTTPException, Security
from fastapi.security import APIKeyHeader
from pydantic import BaseModel

app = FastAPI()
api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)

def validate_api_key(api_key: str = Security(api_key_header)) -> str:
    if not api_key or api_key != "test-key-12345":
        raise HTTPException(status_code=401, detail="Missing or invalid API key")
    return api_key

@app.get("/health")
async def health():
    return {"status": "healthy", "server": "Test MCP Server"}

class MCPRequest(BaseModel):
    jsonrpc: str
    method: str
    id: str

@app.post("/mcp")
async def mcp_endpoint(request: MCPRequest, api_key: str = Security(validate_api_key)):
    if request.method == "tools/list":
        return {
            "jsonrpc": "2.0",
            "id": request.id,
            "result": {
                "tools": [
                    {
                        "name": "test_tool",
                        "description": "A test tool",
                        "inputSchema": {"type": "object", "properties": {}}
                    }
                ]
            }
        }
    else:
        return {
            "jsonrpc": "2.0", 
            "id": request.id,
            "error": {"code": -32601, "message": "Method not found"}
        }

# Run with: uvicorn server:app --host 0.0.0.0 --port 8001

2. Verify server works with curl

# Test authentication works
curl -H "X-API-Key: test-key-12345" http://localhost:8001/health
# Should return: {"status":"healthy","server":"Test MCP Server"}

# Test MCP endpoint works  
curl -X POST -H "X-API-Key: test-key-12345" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":"test"}' \
  http://localhost:8001/mcp
# Should return tools list

3. Configure Claude Code with X-API-Key headers

Create .mcp.json:

{
  "mcpServers": {
    "test-server-http": {
      "type": "http", 
      "url": "http://localhost:8001",
      "headers": {
        "X-API-Key": "test-key-12345"
      }
    }
  }
}

4. Try to connect with Claude Code

claude mcp list  # Should show the configured server
# Try to use MCP functionality in Claude Code

5. Observe OAuth attempts in server logs

The server logs will show OAuth discovery requests instead of requests with the configured headers.

Confirmed reproduction logs:

INFO:     127.0.0.1:36194 - "GET /.well-known/oauth-protected-resource HTTP/1.1" 404 Not Found
INFO:     127.0.0.1:36210 - "GET /.well-known/oauth-authorization-server HTTP/1.1" 404 Not Found
INFO:     127.0.0.1:36194 - "GET /.well-known/openid-configuration HTTP/1.1" 404 Not Found
INFO:     127.0.0.1:36210 - "POST /register HTTP/1.1" 404 Not Found

This demonstrates that Claude Code completely ignores the X-API-Key: test-key-12345 header configured in .mcp.json and attempts OAuth2 Dynamic Client Registration instead.

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

1.0.108

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

VS Code integrated terminal

Additional Information

Related Issues

Metadata

Metadata

Labels

area:autharea:mcpbugSomething isn't workinghas reproHas detailed reproduction stepsplatform:linuxIssue specifically occurs on Linux

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions