Skip to content

Streamable HTTP returns 400 instead of 403 for malformed Origin #1188

Description

@lucarlig

Problem

When Streamable HTTP Origin validation is enabled, a present malformed or non-UTF-8 Origin header is rejected with HTTP 400. The MCP 2026-07-28 Streamable HTTP transport specification requires a server to respond with HTTP 403 when a present Origin is invalid.

A syntactically valid but non-allowlisted origin already returns 403, so malformed values currently have observably different behavior.

Reproduction

On current main / rmcp 3.1.3:

  1. Configure StreamableHttpService with with_allowed_origins(["https://app.example.com"]).
  2. Send a request containing Origin: not-an-origin.
  3. Observe HTTP 400.

Expected: HTTP 403.

The same mismatch occurs when the header cannot be decoded as text.

Implementation: https://github.com/modelcontextprotocol/rust-sdk/blob/main/crates/rmcp/src/transport/streamable_http_server/tower.rs

Specification: https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http

Proposed change

Return the existing forbidden response for Origin encoding and parsing failures, and add integration coverage for both malformed and non-UTF-8 values. Missing Origin behavior and explicitly disabled validation would remain unchanged.

This follows up on #822 / #823. I can submit the focused patch after confirmation, per the discuss-first contribution guidance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions