Skip to content

Enforce 2026-07-28 Origin validation semantics #1191

Description

@lucarlig

Is your feature request related to a problem? Please describe.

The MCP 2026-07-28 Streamable HTTP specification requires servers to validate every present Origin header and return HTTP 403 Forbidden when it is invalid.

RMCP currently differs in two ways:

  • An empty allowed_origins list skips Origin validation, so any present Origin is accepted.
  • Malformed or non-UTF-8 Origin values return HTTP 400 instead of the required 403.

Requests without an Origin header should continue to pass for non-browser MCP clients.

Describe the solution you'd like

  • Keep Origin validation enabled by default.
  • Treat an empty allowed_origins list as allowing no present Origin values.
  • Preserve disable_allowed_origins() as the explicit opt-out from validation.
  • Return HTTP 403 for malformed, non-UTF-8, and non-allowlisted Origin values.
  • Leave existing port-matching behavior unchanged because the MCP specification does not define allowlist matching semantics.

Describe alternatives you've considered

  • Keeping an empty allowlist as an implicit way to disable validation. This makes an empty security policy accept every present Origin and duplicates the explicit disable_allowed_origins() option.
  • Returning HTTP 400 for malformed Origin values. This does not match the specification's required HTTP 403 response for an invalid present Origin.
  • Changing port-matching behavior at the same time. This is left unchanged because the specification does not define allowlist matching semantics.

Additional context

This changes the default behavior only for requests that carry an Origin header. Non-browser clients without that header remain unaffected. Deployments that intentionally accept arbitrary Origins can continue to call disable_allowed_origins().

Acceptance criteria:

  • Empty allowlist + present Origin returns 403.
  • Empty allowlist + missing Origin succeeds.
  • Explicitly disabled validation accepts a present Origin.
  • Malformed and non-UTF-8 Origin values return 403.
  • Existing allowlist and missing-Origin tests continue to pass.

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

Related bug: #1188

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium: important but non-blocking improvement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions