A tool on r/mcp sat invisible to Claude Code for 17 days. A root oneOf in the input schema. No error on the server, no error on the client. The tool just never appeared in the client's list.
Last week SineFrame published a run of Claude Code and Codex against the same ten MCP servers at pinned versions. Five of the ten features split the clients, and the two never failed on the same feature. A tool argument named ids[]? Claude Code drops the tool silently. A 14 KB input schema? Codex compacts it and loses your required nested fields. 2049 tools on one server? Codex keeps the first 2048.
I wanted that list as a check I could run in CI, so I built canimcp: point it at a saved tools/list response or at your server command, and it reports which client+version breaks on what, each finding carrying its evidence grade and a source link.
$ npx canimcp fixtures/quirky-tools.json --client codex
8 findings . 1 error . 5 warnings . 2 advisories . 10 tools checked
tool: create_payment
[error] root-composition-adjacent . codex 0.162.0
root oneOf sits next to "properties" (inputSchema)
A root oneOf or anyOf placed next to "properties" made Codex lose
the property names - the call reached the server mangled.
fix: move the composition inside each property
src: m3-probes-2026-10 . evidence: probe
Two things the evidence forced me to change in my own design:
I almost shipped probe results as equal to measured ones. The published matrix grades some rows as direct binary probes not yet run under the harness, so the corpus carries evidence grades (measured, probe, historical, field-report) and output labels them. A probe is a lead, not a verdict.
I thought of this as a schema linter. Then the Codex detail sunk in: in code mode the model never sees your JSON Schema at all, only a compacted TypeScript declaration generated from it. This is not a "does your schema validate" tool. It is a "what does each client actually see" corpus. The schema is just the part I can check statically.
What it is not: a live test. It sees the schema, not runtime result shapes or tonight's client build. For real client trials there is M3; canimcp is the fast pass in CI before that.
Corpus PRs need a reproduction and client versions. Cursor, Gemini CLI and friends stay unseeded until someone ships evidence.
github.com/princejain756/canimcp - npx canimcp - zero dependencies, Node 18+.
Which MCP client should get seeded into the corpus next?
Top comments (2)
The evidence grades are what make this trustworthy — a probe being a lead, not a verdict, is exactly the nuance most compatibility checklists flatten away. And the Codex code-mode detail reframes it completely: if the model only sees a compacted TypeScript declaration, checking the raw schema is checking something the model never saw. For the next seed, I'd vote Cursor — it's widely used for MCP and its failure modes would probably split from both Claude Code and Codex, which is where this corpus gets most useful.
The ids[] drop is especially nasty because standard json schema validators accept array parameter names without throwing. Tool definitions that work in unit tests or local schema runners silently vanish once the client parses the definition into its internal dictionary.
On Codex code mode, another subtle issue with TypeScript declaration compaction is union flattening. If a tool accepts a union of specific object shapes, Codex often collapses the properties into an optional grab-bag interface. The model then invents hybrid payloads that merge fields from two mutually exclusive branches, and the server rejects them on validation.