Skip to content

streamable-http stale session returns UnexpectedContentType(None) instead of status-aware error #688

@adam-r-kowalski

Description

@adam-r-kowalski

Describe the bug
With streamable HTTP, when a client sends a stale/invalid mcp-session-id, the server returns 401 Unauthorized plain text without Content-Type. The reqwest streamable client then surfaces this as StreamableHttpError::UnexpectedContentType(None) instead of a status-aware error that preserves the real failure context (401 session not found).

To Reproduce
Steps to reproduce the behavior:

  1. Start a stateful StreamableHttpService.
  2. Send POST /mcp with headers:
    • Accept: application/json, text/event-stream
    • Content-Type: application/json
    • mcp-session-id: stale-session-id
  3. Send any valid JSON-RPC request body (for example ping/tool call).
  4. Observe raw HTTP response is 401 Unauthorized with body Unauthorized: Session not found and missing Content-Type.
  5. Observe reqwest streamable client error is UnexpectedContentType(None).

Expected behavior
For non-success HTTP responses, the streamable reqwest client should return a status-aware transport error (including HTTP status and response body), not a content-type parsing error.

Logs
Raw HTTP from stale session path:

  • status: 401 Unauthorized
  • body: Unauthorized: Session not found
  • Content-Type: missing

Current client error:

  • StreamableHttpError::UnexpectedContentType(None)

Validation commands run against patch branch:

cargo test -p rmcp --test test_streamable_http_stale_session --features "client server transport-streamable-http-client-reqwest transport-streamable-http-server"
cargo test -p rmcp --test test_streamable_http_priming --features "server client transport-streamable-http-server reqwest"
cargo test -p rmcp --test test_custom_headers --features "client server transport-streamable-http-client-reqwest transport-streamable-http-server"

Additional context
Per contribution guidance, posting this issue first to discuss before opening PR.

Patch is ready on fork branch:

If this direction looks good, I can open a PR immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High: significant functionality gap or spec violationT-transportTransport layer changesbugSomething is not workingready for workIssue is well-defined and ready to be picked up

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions