Boolean JSON Schema at a named property breaks MCP proxy construction — all tools of the server are dropped (#50194 still reproduces, wrong root cause)
Follow-up to #50194, which was closed as completed but still reproduces. That issue is locked, and its closing bot comment asks to file a new one referencing it.
More importantly, #50194's stated cause is wrong, which may be why a fix did not resolve it. It blamed additionalProperties: true. I enumerated all 57 tool schemas from the server's live tools/list — there are zero boolean values at additionalProperties (or items, not, propertyNames, contains, unevaluatedProperties, additionalItems). A guard placed only around additionalProperties would not help here. The actual offender is a boolean schema sitting at a named property.
What's Wrong?
With the Grafana MCP Server extension (v0.10.0, ant.dir.gh.grafana.grafana-mcp) installed and enabled, the extension connects fine and reports 57 tools, but Claude Desktop throws while building the SDK proxy. The result: none of the 57 tools reach the Claude Code session. The extension shows as installed and enabled and silently delivers nothing — ToolSearch returns no matches for any Grafana keyword.
Root cause
Two tools declare a property whose schema is the boolean true:
create_alert_rule -> inputSchema.properties.data.items.properties.model = true
update_alert_rule -> inputSchema.properties.data.items.properties.model = true
true is a valid JSON Schema from draft-6 onward — it means "any value is allowed" and is equivalent to {}. jsonSchemaToZodShape recurses into properties and evaluates 'properties' in node on each property's schema without first checking that the node is an object, so a boolean node throws TypeError: Cannot use 'in' operator to search for 'properties' in true.
Blast radius
Per the stack, createSdkServer maps over the tool list with Array.map inside a Promise.all, with no per-tool isolation. So two unconvertible schemas drop all 57 tools of that server. Even after the boolean case is handled, a per-tool try/catch that skips only the offending tool would keep a single odd schema from taking down an entire server.
What Should Happen?
A boolean schema node should be accepted (treated as {} for true, and as "never" / an always-failing schema for false), and the remaining 55 tools should be exposed regardless of whether these two convert.
Steps to Reproduce
- Install the Grafana MCP Server extension v0.10.0 in Claude Desktop.
- Configure it with any
grafana_urlandservice_account_token(the failure happens aftertools/list, so the credentials need not be valid — the schema conversion is purely local). - Start any Claude Code session in the desktop app.
- No Grafana tools are available;
~/Library/Logs/Claude/main.logshows the error below.
Generalized — this does not require Grafana. Any MCP server exposing a tool whose input schema nests a boolean schema at a named property should trigger it:
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": { "type": "object", "properties": { "model": true } }
}
}
}
Error Messages/Logs
~/Library/Logs/Claude/main.log (hostname redacted):
[info] [LocalMcpServerManager] Connecting to Grafana MCP Server
[info] Using basic execution for extension Grafana MCP Server: server.type is "binary" (not node/python/uv)
[info] [LocalMcpServerManager] Connected to Grafana MCP Server (57 tools)
[error] [LocalMcpServerManager] Failed to create proxy for Grafana MCP Server:
Cannot use 'in' operator to search for 'properties' in true
TypeError: Cannot use 'in' operator to search for 'properties' in true
at a (.../index.chunk-6k1UHY_-.js:1:1480)
at a (.../index.chunk-6k1UHY_-.js:1:1359)
at a (.../index.chunk-6k1UHY_-.js:1:1220)
at Object.p [as jsonSchemaToZodShape] (.../index.chunk-6k1UHY_-.js:1:2119)
at .../index.chunk-y08W5C7k.js:1:10761
at Array.map (<anonymous>)
at R.createSdkServer (.../index.chunk-y08W5C7k.js:1:10716)
at R.createProxyServers (.../index.chunk-y08W5C7k.js:1:4402)
at async Promise.all (index 0)
at async pi.createAllServers (.../index.chunk-CzaHV0Pg.js:171:18577)
at async j.setupMcpAndPlugins (.../index.chunk-DT0P6tKR.js:347:4990)
at async j.buildStartSdkOptions (.../index.chunk-DT0P6tKR.js:361:2717)
at async j.warmSession (.../index.chunk-DT0P6tKR.js:372:7987)
The extension itself is healthy — mcp-server-Grafana MCP Server.log shows a successful initialize and a tools/list result. Driving the same bundled binary directly over stdio outside the app returns 57 tools and real data from a tools/call, so the failure is entirely in the app's proxy construction.
Unrelated but visible in the same log, the extension's env template is not fully substituted — GRAFANA_ORG_ID arrives as the literal string ${user_config.org_id}, and the server logs Invalid GRAFANA_ORG_ID value, ignoring. It also reports basic_auth_set=true because GRAFANA_USERNAME / GRAFANA_PASSWORD are passed as unsubstituted placeholders rather than omitted. Neither is fatal; filing here only as a note, happy to split it out.
Suggested Fix
In the schema walker, handle boolean schemas before any in / property access:
if (typeof node === 'boolean') return node ? z.any() : z.never();
and wrap per-tool conversion in createSdkServer so one unconvertible tool is skipped and logged rather than discarding the whole server's tool list.
Environment
- Claude Code version: 2.1.220
- Claude Desktop: 1.24012.9
- Grafana MCP Server extension: v0.10.0 (
ant.dir.gh.grafana.grafana-mcp),server.type: binary, darwin-arm64 - OS: macOS 26.5.2 (Darwin 25.5.0), Apple Silicon
- Platform: Anthropic API
- Regression: I don't know — first install of this extension here; #50194 reports the same failure in April 2026 on Claude Code 2.1.111.
- Other extensions (Figma, Chrome Control) and other MCP servers load fine in the same sessions, so the proxy failure is isolated to the affected server.