Skip to content

[Server] Enforce x-mcp-header where a request uses it (SEP-2243) - #453

Merged
chr-hertel merged 2 commits into
modelcontextprotocol:mainfrom
chr-hertel:pr/2026-header-mirroring
Aug 18, 2026
Merged

[Server] Enforce x-mcp-header where a request uses it (SEP-2243)#453
chr-hertel merged 2 commits into
modelcontextprotocol:mainfrom
chr-hertel:pr/2026-header-mirroring

Conversation

@chr-hertel

Copy link
Copy Markdown
Member

Stacked on #452. The request-side half of x-mcp-header; the definition-side half merged as #441.

StandardHeaderValidator inspected only top-level properties, so an annotation on a nested property was silently unenforced — the Mcp-Param-* header could say anything. The walk now follows a chain of properties keys to any depth and reads the argument at that exact path.

Integer values compare numerically, so a client writing 42.0 for a body value of 42 is no longer rejected.

Part of SEP-2243.


Cross-fork PRs can only target main, so this diff also carries its ancestors until they merge. Only the last commit(s) belong to this PR — GitHub's "Commits" tab separates them.

Only top-level properties were inspected, so an annotation on a nested
property was silently unenforced - the header could say anything. The walk
now follows a chain of properties keys to any depth and reads the argument
at that exact path.

Integer values compare numerically, so a client writing 42.0 for a body
value of 42 is no longer rejected.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the server-side StandardHeaderValidator to correctly enforce x-mcp-header annotations beyond top-level tool input properties, ensuring nested Mcp-Param-* headers are validated against the exact body argument path. It also relaxes numeric comparison so integer header/body values can agree even when serialized differently (e.g., 42 vs 42.0).

Changes:

  • Recursively discover x-mcp-header annotations through nested properties chains and validate headers against the corresponding nested argument path.
  • Add numeric-aware comparison for mirrored params to avoid rejecting equivalent integer values with different decimal renderings.
  • Extend unit tests to cover nested mirroring discovery, unreachable annotations, nested argument validation, and numeric comparison behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/Server/Stateless/StandardHeaderValidator.php Recursively extracts mirrored properties and validates Mcp-Param-* values against nested arguments; adds numeric comparison behavior.
tests/Unit/Server/Stateless/StandardHeaderValidatorTest.php Adds coverage for nested x-mcp-header discovery and nested/header numeric validation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Server/Stateless/StandardHeaderValidator.php
is_numeric() and loose == both treat a string like "042" as equal to
"42", so a string argument could pass header validation against a
header that doesn't match it exactly. Gate the numeric comparison on
the argument's actual type and a decimal-only header instead.
@chr-hertel
chr-hertel merged commit 7e38c94 into modelcontextprotocol:main Aug 18, 2026
25 checks passed
@chr-hertel
chr-hertel deleted the pr/2026-header-mirroring branch August 18, 2026 22:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants