Skip to content

Commit ed5868d

Browse files
committed
fix(server): normalize bare-boolean subschemas in generated tool schemas
`schemars` emits `true.into()` for `serde_json::Value::json_schema()`, so `Value` / `Vec<Value>` / `BTreeMap<_, Value>` / `#[serde(deny_unknown_fields)]` fields produce bare boolean subschemas (`"<name>": true`, `"items": true`, `additionalProperties: true`/`false`). JSON Schema 2020-12 §4.3.2 explicitly permits these as `{}` / `{"not": {}}` shortcuts, but Claude Code's `LocalMcpServerManager` schema walker throws TypeError: Cannot use 'in' operator to search for 'properties' in true while building the per-server proxy after `tools/list` parses successfully, silently dropping the entire server's tool list for the session (anthropics/claude-code#50194 — Grafana MCP, current as of CC 2.1.111; also #25081, #10606, #28620). The TypeScript SDK's Zod validator accepts bare booleans correctly; the failure is a Claude Code walker defect. Apply `schemars::transform::ReplaceBoolSchemas::default()` via `transform_subschemas` (not `SchemaSettings::with_transform`) so - bool subschemas in `properties.*`, `items`, `additionalProperties`, `prefixItems[*]`, `oneOf`/`anyOf`/`allOf[*]`, `not`/`if`/`then`/`else`, `contains`, `propertyNames`, `additionalItems`, `$defs.*`, `definitions.*`, `patternProperties.*` are normalized to object form - degenerate `Json<serde_json::Value>` roots stay non-`"type":"object"` and the existing `schema_for_output` root-type rejection still fires Patched both `handler::server::common::schema_for_type` (the funnel for tool/prompt schemas, `Tool::with_input_schema`, `with_output_schema`, `schema_for_output`, `cached_arguments_from_schema`, and the `#[tool]` macro default code-gen) and `model::elicitation_schema::ElicitationSchema::from_type` (the parallel funnel for elicitation prompts). 10 new unit tests pin the contract: every documented schemars field shape, idempotency, the canonical #50194 reproducer (`BTreeMap<_, Value>`), and the degenerate root rejection.
1 parent dd2cf24 commit ed5868d

10 files changed

Lines changed: 370 additions & 15 deletions

File tree

conformance/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ rmcp = { path = "../crates/rmcp", features = [
2222
"transport-streamable-http-client-reqwest",
2323
] }
2424
tokio = { version = "1", features = ["full"] }
25-
tokio-util = { version = "0.7" }
2625
serde = { version = "1", features = ["derive"] }
2726
serde_json = "1"
2827
tracing = "0.1"

crates/rmcp-macros/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ proc-macro = true
1818
syn = {version = "2", features = ["full"]}
1919
quote = "1"
2020
proc-macro2 = "1"
21-
serde_json = "1.0"
2221
darling = { version = "0.23" }
2322

2423
[features]

crates/rmcp/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- *(server)* Normalise bare boolean subschemas (`true` / `false`) in generated `inputSchema`, `outputSchema`, and `ElicitationSchema` to their object-form equivalents (`{}` / `{"not": {}}`) before serialisation. Triggered by `serde_json::Value` field expansions, `Vec<serde_json::Value>`, `BTreeMap<String, serde_json::Value>`, and `#[serde(deny_unknown_fields)]`. Claude Code's `LocalMcpServerManager` schema walker throws `TypeError: Cannot use 'in' operator to search for 'properties' in <bool>` on bare booleans, silently dropping the entire server's tool list ([anthropics/claude-code#50194](https://github.com/anthropics/claude-code/issues/50194), [#25081](https://github.com/anthropics/claude-code/issues/25081)). The fix is unconditional — boolean subschemas are spec-legal per JSON Schema 2020-12 §4.3.2, but real-world MCP clients can't always handle them, so emit object form universally.
13+
1014
## [1.5.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-v1.4.0...rmcp-v1.5.0) - 2026-04-16
1115

1216
### Added

crates/rmcp/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ which = { version = "8", optional = true }
8989
# tokio-tungstenite ={ version = "0.26", optional = true }
9090

9191
# for http-server transport
92-
rand = { version = "0.10", optional = true }
9392
tokio-stream = { version = "0.1", optional = true }
9493
uuid = { version = "1", features = ["v4"], optional = true }
9594
http-body = { version = "1", optional = true }
@@ -136,7 +135,6 @@ reqwest-native-tls = ["__reqwest", "reqwest?/native-tls"]
136135

137136
server-side-http = [
138137
"uuid",
139-
"dep:rand",
140138
"dep:tokio-stream",
141139
"dep:http",
142140
"dep:http-body",

0 commit comments

Comments
 (0)