Return a reason string if any `x-mcp-header` annotation in `input_schema` is invalid; else `None`. Walks every JSON Schema 2020-12 schema position. An annotation is valid only when it sits on a property statically reachable from the root via a chain of pure `properties` keys, names a no
(input_schema: Any)
| 174 | |
| 175 | |
| 176 | def find_invalid_x_mcp_header(input_schema: Any) -> str | None: |
| 177 | """Return a reason string if any `x-mcp-header` annotation in `input_schema` is invalid; else `None`. |
| 178 | |
| 179 | Walks every JSON Schema 2020-12 schema position. An annotation is valid |
| 180 | only when it sits on a property statically reachable from the root via a |
| 181 | chain of pure `properties` keys, names a non-empty RFC 9110 token, is on |
| 182 | an integer/string/boolean property, and is case-insensitively unique |
| 183 | across the whole schema. A `None` / non-mapping schema has no schema |
| 184 | positions and returns `None`. |
| 185 | """ |
| 186 | seen: dict[str, str] = {} |
| 187 | for path, schema in _walk_schema_positions(input_schema): |
| 188 | if X_MCP_HEADER_KEY not in schema: |
| 189 | continue |
| 190 | if not path: # None (off the pure-properties chain) or () (the root itself) |
| 191 | return f"{X_MCP_HEADER_KEY} found at a schema position not reachable via a pure `properties` chain" |
| 192 | where = ".".join(path) |
| 193 | header = schema[X_MCP_HEADER_KEY] |
| 194 | if not isinstance(header, str) or not _RFC9110_TOKEN.fullmatch(header): |
| 195 | return f"property {where!r}: {X_MCP_HEADER_KEY} {header!r} is not an RFC 9110 token" |
| 196 | prop_type = schema.get("type") |
| 197 | if not isinstance(prop_type, str) or prop_type not in _X_MCP_HEADER_PRIMITIVE_TYPES: |
| 198 | return ( |
| 199 | f"property {where!r}: {X_MCP_HEADER_KEY} is only permitted on " |
| 200 | f"integer/string/boolean properties (got {prop_type!r})" |
| 201 | ) |
| 202 | lower = header.lower() |
| 203 | if lower in seen: |
| 204 | return f"{X_MCP_HEADER_KEY} {header!r} on property {where!r} duplicates property {seen[lower]!r}" |
| 205 | seen[lower] = where |
| 206 | return None |
| 207 | |
| 208 | |
| 209 | # INTERNAL_ERROR is deliberately unmapped (→ HTTP 200): the spec assigns no status to |