anthropics / anthropics/claude-code
MCP (stdio): one boolean property schema silently drops ALL tools of the server (SDK 0.1.77; stdio twin of #88049, re-filing of #82949)
- Lenguaje dominante
- Python
- Estrellas
- 145k
- Forks
- 23.1k
- Métricas de merge de PR
- Métricas de PR pendientes
Descripción
## Summary
If **any single tool** advertised by a stdio MCP server has an `inputSchema` containing a
**boolean property schema** — e.g. `"payload": true` inside a `properties` map, which is legal
JSON Schema meaning "any value" (JSON Schema 2020-12 §4.3.2) — the SDK's bundled CLI rejects that
schema during MCP tool conversion and silently drops the **entire server's tool list**. Not just
the offending tool: every tool from that server vanishes from the outgoing API request. There are
**zero diagnostics anywhere** — no stderr warning, no error message — and the server still reports
as "connected". The model simply never sees any of the server's tools.
This is the same root cause and blast radius as #82949 (a boolean schema at a named property
throwing inside `jsonSchemaToZodShape`) and #88049 (a non-object top-level schema, HTTP
transport), reproduced independently against a **stdio** MCP server. #82949 was closed
`NOT_PLANNED` by an inactivity bot on 2026-09-08 with no fix landed, so this re-files it with a
concrete stdio-side repro, a bisect, and a suggested fix — per that issue's own closing-bot
guidance ("open a new issue if still relevant").
## Affected version
- `@anthropic-ai/claude-agent-sdk` **0.1.77** (declared `^0.1.0`, lockfile-resolved `0.1.77`) and
its bundled `cli.js`
- Node.js 22.x, via `tsx`
- Linux x86_64
No newer SDK version was tested against this repro.
## Minimal repro
1. Stand up a stdio MCP server whose `tools/list` returns several tools, exactly one of which
carries a boolean property schema in its `inputSchema`, e.g.:
```json
{
"name": "propose",
"inputSchema": {
"type": "object",
"properties": {
"target": { "type": "string" },
"op": { "type": "string", "enum": ["set", "delete"] },
"payload": true
}
}
}
```
(`"payload": true` is the trigger — a boolean schema in a `properties` map. `true` = "accept
any value" per JSON Schema 2020-12 §4.3.2. `false` presumably triggers the same rejection
path; the proven case is `true`.)
2. Configure that server under `mcpServers` (stdio transport) and run a query through
`@anthropic-ai/claude-agent-sdk` 0.1.77.
3. Capture the outgoing API request (we pointed `ANTHROPIC_BASE_URL` at a credential-free
Anthropic-format capture stub and counted the `tools` array in the recorded request body).
**Observed:** 0 of the server's tools reach the API request. Server status: "connected". No
warning or error is emitted anywhere.
**Expected:** either (a) the boolean schema is accepted (it is valid JSON Schema — a boolean is a
legal schema everywhere a schema may appear), or (b) at minimum, only the offending **tool** is
dropped, **with a diagnostic** naming the tool and the reason. Silently discarding all N tools of
a connected server with no signal anywhere is the worst of every option.
## Bisect evidence
Our MCP bridge advertises 53 tools whose schemas are enriched from an OpenAPI document. Two
operations declared `"payload": true` (an honest any-value payload). Per-path bisect via the
capture stub:
- With any single path **not** containing `"payload": true` in the doc → **53/53** tools reach
the API request.
- With only a path containing `"payload": true` → **0/53** tools reach the API request.
- Replacing both occurrences with the semantically-equivalent **object-form** any-value schema
`{"description": "Any JSON value ..."}` (no `type`) → **53/53** again.
This isolates the trigger to the one boolean schema node, independent of tool count or catalog
size, and matches #88049's own bisect showing the same all-or-nothing behavior for a different
non-object-at-schema-root trigger.
## Impact
- **Server-wide blast radius from one property:** a single legal schema construct anywhere in one
tool disables an entire MCP server.
- **Silent:** the failure mode presents as "the model chose not to use my tools." We burned a
credentialed eval run (a capability floor collapsed from 11/11 to 1/6) and a bisect session
root-causing what looked like a model-behavior regression but was actually a tool-palette drop.
- Boolean schemas are common in generated schemas (OpenAPI → JSON Schema pipelines,
`additionalProperties: false`-style toolchains, some `zod`-based converters' `z.any()`
emission), so this is easy to hit and near-impossible to self-diagnose — exactly the pattern
#82949 and #88049 both independently report.
## Workaround
1. Replace every boolean property schema with the object-form equivalent: `true` →
`{ "description": "Any JSON value" }` (a bare schema object with no `type` keeps the identical
"any value" contract and passes the CLI's conversion).
2. A lint check that walks every schema node in our tool-schema source and fails if any value in
any `properties` map is not a JSON object, so the construct can never be reintroduced.
## Suggested fix
Accept boolean schemas per JSON Schema (ideal: `true` → `{}`, `false` → `{"not": {}}` during
conversion), matching #82949's own suggested fix (`typeof node === 'boolean'` handled before any
`'properties' in node` check in `jsonSchemaToZodShape`). Failing that: drop only the offending
tool and emit a diagnostic naming the server, the tool, and the schema path — never silently drop
the whole server's tool list. #82949's suggested per-tool `try/catch` isolation in
`createSdkServer` would close this stdio case, #88049's HTTP case, and #82949's Desktop case at
once, since all three share the same "one bad schema drops the whole server" mechanism.
## Related
- #82949 — same root cause (boolean schema at a named property, `jsonSchemaToZodShape` throwing),
Claude Desktop + binary extension transport. **Closed `NOT_PLANNED` by an inactivity bot on
2026-09-08** with no fix landed; this issue re-files it with an independent stdio-side repro
and bisect, per that closing comment's own "open a new issue if still relevant" guidance.
- #88049 — open, same blast radius and same "completely silent on both sides" symptom, different
trigger (non-object top-level schema, e.g. bare `anyOf`) and different transport (HTTP).
- #50194 — the original report of this blast radius (Claude Desktop, Grafana MCP server),
closed; #82949 established its stated root cause (`additionalProperties: true`) was wrong.
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Línea de trabajo
Read the bundled cli.js around jsonSchemaToZodShape and createSdkServer, then run the stdio repro with the credential-free capture stub. Verify that a boolean property schema no longer removes the entire server tool list, and that invalid tools are isolated or diagnostics are emitted.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- node.js
- Área
- api, cli
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Activo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 52/100