Skip to content

Commit 9e0c3a6

Browse files
committed
fix: enforce MCP parameter header requirements
Signed-off-by: lucarlig <luca.carlig@ibm.com>
1 parent 8b963fb commit 9e0c3a6

6 files changed

Lines changed: 540 additions & 49 deletions

File tree

_context/wiki/architecture.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ backend and original tool name. When `UserConfig` contains that tool's input
8585
schema, it validates recognized `Mcp-Param-*` headers against the request body;
8686
it does not call backend `tools/list`. Without a published schema, parameter
8787
headers are unrecognized and forwarded without local validation.
88+
Published annotations are validated for MCP token, uniqueness, primitive type,
89+
and properties-only reachability constraints. Nested annotations read the exact
90+
argument path. Present non-null values require a matching header; absent or
91+
null values require no header.
8892
Parameter headers are forwarded unchanged; request plugins run afterward, so a
8993
plugin that changes an annotated argument also owns any resulting upstream
9094
mismatch.

_context/wiki/config.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,12 @@ BackendMCPGateway
139139
annotations without calling backend `tools/list`. The control plane may omit the
140140
field or individual unannotated tools. Without a published schema, parameter
141141
headers are forwarded as unrecognized intermediary headers and are not locally
142-
validated.
142+
validated. A published annotation must name a non-empty, case-insensitively
143+
unique HTTP token on a `string`, `integer`, or `boolean` property reachable from
144+
the schema root through `properties` keys only. Nested properties use their
145+
exact property path. For a recognized annotation, a non-null argument requires
146+
an equal header; an absent or null argument requires the header to be absent.
147+
Integer values are limited to the IEEE 754 safe range.
143148

144149
**Header apply order:** `passthrough_headers``add_headers` (override passthrough) → `remove_headers` (applied last).
145150

_context/wiki/security.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,14 @@ Backend header policy cannot add, remove, or replace MCP standard or parameter
9595
headers. For modern `tools/call`, the dataplane resolves the authenticated
9696
user, virtual host, backend, and original tool name before validating
9797
recognized `Mcp-Param-*` against the control-plane-published input schema. A
98-
recognized header/body mismatch fails closed with JSON-RPC `-32020`. When no
99-
schema is published, parameter headers are unrecognized and forwarded without
100-
local validation; their absence does not block the tool call.
98+
recognized missing, malformed, unexpected, conflicting repeated, or mismatched header fails closed
99+
with JSON-RPC `-32020`. Schema annotations also fail closed unless their names
100+
are non-empty, case-insensitively unique HTTP tokens, their properties have an
101+
allowed primitive type, and their paths are statically reachable through
102+
`properties` only. Nested values are checked at their exact path, and integers
103+
must remain in the IEEE 754 safe range. When no schema is published, parameter
104+
headers are unrecognized and forwarded without local validation; their absence
105+
does not block the tool call.
101106
Validation does not call backend `tools/list`. Parameter values are forwarded
102107
unchanged, while RMCP regenerates method, routed-name, and protocol-version
103108
headers. If a plugin later changes an annotated argument, the original header

_context/wiki/testing.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ Protocol-sensitive tests and fixtures must cover MCP `2026-07-28` and `2025-11-2
3535
These run in `cargo nextest run` with no Docker dependencies.
3636

3737
Parameter-header integration tests verify that calls without a published tool
38-
schema skip local `Mcp-Param-*` validation and still reach the backend.
38+
schema skip local `Mcp-Param-*` validation and still reach the backend. Unit and
39+
integration coverage also includes missing, malformed, unexpected, repeated,
40+
and mismatched recognized headers; Base64 encoding; nested paths; numerically
41+
equivalent integers; and invalid annotation names, types, duplicates, and
42+
non-`properties` paths.
3943

4044
## MCP Conformance
4145

0 commit comments

Comments
 (0)