DEV Community

Cover image for How deep do MCP input schemas nest?
MCPulse
MCPulse

Posted on Originally published at getmcpulse.com

How deep do MCP input schemas nest?

A model filling in a tool call has to construct whatever shape your inputSchema describes. A flat object of strings is one thing; an array of objects each containing an object is another.

So how nested are real MCP schemas? We measured depth across 74,666 tools that take parameters, following properties, items, and anyOf/oneOf/allOf branches.

Then we split the undescribed-parameter rate by depth, expecting deep schemas to be worse. They're better, and the reason is more interesting than the number.

Almost everything is flat

Depth Tools Share
1 62,054 83.1%
2 9,279 12.4%
3 2,333 3.1%
4 599 0.8%
5 216 0.3%
6 77 0.1%
7–13 ~108 <0.1%

Five tools in six are a flat object of scalars. No nesting at all — {"query": string, "limit": integer} and nothing more.

Add depth 2 and you have 95.5% of the corpus. Depth 2 is the array-of-strings and the single options object: {"tags": string[]}, {"filter": {"from": string}}.

The deepest schema in the corpus is thirteen levels. There are five of those.

The finding that reverses the expectation

We expected deep schemas to be worse documented — more structure, more fields, more places to skip a description.

The opposite:

  • Tools at depth 3 or more: 18.2% of top-level parameters undescribed
  • Tools below depth 3: 21.8%

Deep schemas are better documented than flat ones, by 3.6 points.

Our reading is that it's about who writes them. A depth-5 schema isn't something you arrive at casually. It's either generated from a typed source — an OpenAPI spec, a Zod schema, a protobuf definition — where descriptions come along for the ride, or hand-built by someone modelling a genuinely structured input and paying attention.

Flat schemas are where the two-line afterthought lives. The single-parameter tool is the worst-described shape in the whole corpus, at 27.0%.

So depth isn't a warning sign. It correlates with care.

The caveat that matters more than the finding

That comparison counts top-level inputSchema.properties only. A field three levels down isn't in the denominator.

That was the right call for the survey — per-tool parameter counts had to mean one consistent thing — but it means the corpus number understates the real gap. A tool whose top-level parameters are all described and whose nested object is completely bare scores clean.

And an undescribed field at depth 4 is exactly as invisible to a model as one at depth 1. It has a name, a type, and nothing else.

What this means practically

Don't flatten a schema to look simpler. Depth isn't the problem the data points at. If your input genuinely has structure — a filter object, a list of line items — modelling it honestly beats a dozen underscore-joined top-level fields. The corpus suggests people who do it describe their fields better anyway.

Do describe the nested fields. They're the ones most likely to be missed, because most tooling shows you the top level. This is the one place where our own methodology would let you off and a model wouldn't.

Past about four levels, ask what the model is meant to construct. 0.4% of the corpus goes deeper than four. A model generating a five-level nested object has many more ways to get the shape wrong than right, and there's usually a flatter representation of the same request. Not always — but at that depth it's worth checking.

Watch anyOf and oneOf specifically. They're depth without looking like depth. A parameter that is "either a string or an object with three fields" is two shapes the model has to choose between, and the choice is rarely documented. A description on the branch point is worth more than one on either branch.

What this can't tell you

We measured depth, not difficulty. A depth-3 schema of well-named described fields is easier for a model than a flat one with two bare id parameters, and nothing here captures that.

The correlation between depth and better documentation is a correlation. The generated-from-typed-source explanation is our reading of it, not something the data shows — we can't see how a schema was produced.

And as always: no model was run against any of these servers. Whether nesting depth actually causes malformed arguments is unmeasured, and it's one of the more testable things on our list.

Measuring your own

The schema checker walks your schema to every depth — through properties, items and union branches — and names undescribed fields by their full path: filter.from, tags[].label. It reports the top-level count separately, so the number scored against the corpus stays comparable while the list of things to fix doesn't leave anything out.

Runs in your browser, nothing uploaded. Data in getmcpulse/mcp-schema-study.

Originally published at getmcpulse.com.

Top comments (2)

Collapse
 
jo-do profile image
Jo Do

The top-level caveat is important enough that I would report two depth numbers: structural depth and decision depth. A five-level object with one valid path can be tedious but deterministic; a depth-two schema with nested oneOf branches and overlapping required fields can force a harder choice.

For tool-call reliability, I would also count leaf paths, union branch entropy, and how many leaves lack descriptions. Then test malformed-call rate against those features separately. My guess is that ambiguous branches and conditional requirements will explain more failures than raw nesting once descriptions are controlled for.

Collapse
 
getmcpulse profile image
MCPulse

Structural depth versus decision depth is the right split, and it explains why the depth number came out counterintuitive. I measured how far down the schema goes, which is a proxy for how much work the model does — and you're pointing out that work and difficulty are different things. A deterministic five-level object is tedious. A depth-two schema with overlapping oneOf branches is a choice, and the model can be wrong about a choice in a way it can't be wrong about tedium.

Leaf paths is the obvious one I skipped. Depth is a max over the tree, so a tool with one field at depth 5 and a tool with forty fields at depth 5 score identically, and they are not remotely the same thing to fill in. Leaf count is the size of the job; depth is just how far you have to reach.

Union branch entropy is the one I'd have to think about how to compute. The naive version is branch count, but that treats "string or null" the same as "three structurally distinct objects", and only the second is a real decision. Something like distinguishability between branches — do they share a discriminator, do their required sets overlap — is closer to what actually costs a model. Which makes it the same shape as the tool-selection problem one level down: branches competing for the same input.

Conditional requirements I haven't measured at all, and can't from this corpus — the registry I pulled from strips the top-level required array. I found that by diffing the four official reference servers against their stored copies. So anything involving required-field logic is unavailable to me until I collect differently.

Your guess is testable and I'd bet the same way. Running it needs the model-in-the-loop pass rather than more static analysis, which is the next study: generate requests, record malformed calls, then regress against leaf count, branch ambiguity and description coverage separately rather than against depth. If ambiguous branches beat raw nesting once descriptions are controlled, the depth number becomes a curiosity and the branch metric becomes the thing worth reporting.