deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

Loose schemas and vague tool descriptions: two MCP failures that derail AI agents

Two dev.to posts detail how loose MCP input schemas and vague tool descriptions cause agents to send invalid parameters and pick the wrong tool in production.

Loose schemas and vague tool descriptions: two MCP failures that derail AI agents

Two posts published the same day on dev.to, both by Jeff PDC and part of a series on building MCP servers, catalogue a pair of failure modes that surface once AI agents start calling real tools: input schemas loose enough to let invalid arguments through, and descriptions vague enough that the model selects the wrong operation. In both cases the server looks correct on paper — the schema validates, permissions are in place — while the agent misbehaves in ways that are easy to misdiagnose as a model limitation.

Loose schemas push validation to the upstream API

An MCP tool declares its arguments as a JSON Schema, and that schema is the contract the model reads when constructing a call. According to the first post, tools are often wrapped in haste: every parameter typed as a string, required fields left unmarked, or a single untyped object standing in for a real shape. The happy path still works because the agent happens to send acceptable arguments. The failure arrives later, when a request omits a field or sends a number where the API expects an ISO date string, and the error comes back as a 400 from the upstream service — far from the code that caused it.

The core argument is that the model cannot respect constraints it was never given. The recommended schema discipline includes:

  • explicit types instead of strings everywhere
  • a required array naming mandatory fields
  • enums wherever the accepted set is closed, such as currency codes
  • constraints like minimum, pattern or maxLength that mirror the upstream API
  • additionalProperties set to false, with typed nested objects rather than catch-alls

Validation should also run at the tool boundary, the post argues, so invalid arguments fail fast with a local, structured error naming the violated constraint — something the model can act on, rather than an opaque upstream failure that costs a full round trip. The API remains the final authority; local checks just make mistakes cheap. Tightening the schema does not reduce what the agent can do, since it only enforces limits the upstream API already applies.

Vague descriptions turn tool selection into a guess

The second post covers a failure with the same root. The model chooses among tools by reading their names and descriptions, so a server can expose every operation correctly and still fail, because selection happens on the strength of the text the server publishes.

Three anti-patterns dominate, per the post: echoing the method name (getInvoice described as "Get invoice"), duplicating one sentence across near-identical operations (list versus search), and omitting the boundary that separates related actions (create versus update, draft versus publish).

The observable symptoms: the agent reaches for createInvoice when the user asked to update one, or picks a list endpoint and passes an ID belonging to a different resource. The post stresses that this is a signal problem, not a capability problem — sharpening the model without fixing the descriptions only makes the guess more assured.

The prescription is that a description should answer three questions in one or two sentences: what the tool does, when to use it, and when not to use it. The "do not use" clause is called the highest-value part, because it hands the model the negative condition that prevents the wrong call. The post also proposes a review loop: read each description without its name and check that the use case is still clear; write the separating condition for every near-identical pair; replay the ambiguous requests that previously failed; and where two operations are genuinely indistinguishable, consider consolidating them rather than exposing both.

Both posts converge on generating from the OpenAPI spec

Hand-maintained wrappers are where drift creeps back in, both posts argue. When the MCP tool and its input schema are generated from an OpenAPI document, with contract validation in CI, a field that becomes required or an enum that gains a value propagates automatically. Descriptions, likewise, should be enriched in the spec rather than maintained separately in the MCP layer, so the text the model selects from stays tied to actual behaviour and parameters.

Why it matters

Both failure modes are invisible to conventional integration testing: the tool works, the schema validates, the agent has permission, and it still misbehaves. What these posts capture is that for agent-facing tools, the schema and the description are not documentation polish — they are the interface the model reasons over. Fixing them is cheap compared to swapping models, and the wrong-tool failure mode carries real side effects: confusing create with update, or cancel with refund, is a mistake no retry loop undoes. As more services get wrapped in MCP servers, treating tool definitions as first-class contract artifacts may be the difference between an agent that occasionally guesses and one that reliably does what was asked.

  • #mcp
  • #ai-agents
  • #llm
  • #json-schema
  • #api-design

Related posts