warn surface/tool-budget
Tool selection accuracy degrades as the surface grows: more near-neighbours to confuse, more tokens spent before the first user message. Fewer, intent-shaped tools outperform one-tool-per-endpoint surfaces.
19 rules, six categories. Each finding in a report links back to its rule here. Everything is static: mcplint reads your tools/list and never calls a tool.
How much of the context window the tool surface consumes before anyone says anything.
Tool selection accuracy degrades as the surface grows: more near-neighbours to confuse, more tokens spent before the first user message. Fewer, intent-shaped tools outperform one-tool-per-endpoint surfaces.
The serialized tools/list payload is injected into every conversation that connects the server, before any work happens. Its token cost is a per-message tax.
Whether tool names are internally consistent enough for a model to generalise from.
Mixed naming styles read as multiple authors and break the model's ability to predict names it has not seen. One convention, applied everywhere.
Whether each tool explains itself well enough to be chosen correctly.
A tool with no description forces the model to guess intent from the name alone. The description is the single highest-leverage piece of context for tool selection.
Descriptions under ~20 characters carry no disambiguation signal. The model needs enough context to pick this tool over its neighbours without trial calls.
Very long tool descriptions are paid for in every conversation. Detail that only matters once a parameter is used belongs in that parameter's description.
Whether the input schemas are tight enough to constrain what the model sends.
Undescribed parameters get filled by guesswork. Every property the model must populate deserves a sentence saying what it means and what shape it takes.
Loose schemas (bare objects, untyped arrays, open additionalProperties) turn schema validation off exactly where the model is most likely to hallucinate argument shapes.
Deeply nested inputs, very wide property lists, and stacked oneOf/anyOf force the model to solve a constraint puzzle before every call. Flatter, narrower inputs get filled correctly more often.
Whether clients can tell a read from a write before they run it.
readOnlyHint/destructiveHint are machine-readable: clients use them to decide when to ask the user for confirmation. Prose like 'confirm with the user first' is invisible to that machinery.
The interesting half. Whether the surface is shaped around your users' intents or around your REST endpoints.
Tools whose descriptions substantially overlap force the model to pick between near-synonyms — the classic cause of wrong-tool calls. Clusters are usually one tool wearing several names; consolidate with include-flags or a mode parameter.
A get/create/update/delete family over one noun is the fingerprint of an OpenAPI-autogenerated surface: it mirrors your REST API, not your users' intents. Agents work in workflows, not endpoints — consolidate around tasks.
The same concept spelled differently across tools (hotel_id vs hotelId vs id) makes the model carry a per-tool spelling table and produces cross-tool argument bleed. One concept, one name, everywhere.
Values enumerated in prose ('one of: a, b, c') are invisible to schema validation: the model can misspell them and the server only finds out at call time. If the value set is closed, encode it as an enum.
Models disambiguate tools primarily by their leading tokens. When several descriptions open with the same words, the distinguishing signal is buried — and identical openings usually mean a copy-pasted block that belongs in one place.
A description should say what the tool does. Imperatives aimed at the client ('RENDER RESULTS IMMEDIATELY', 'do not call tool X') are prompt injection into your own surface: paid for in every conversation, unevenly obeyed, and when copy-pasted across tools they drown the words that actually disambiguate. Escalates to warn when the same directive block appears in multiple tools.
Positive check. 'When NOT to use this tool' guidance is one of the highest-value lines a description can carry — it prevents speculative calls that waste quota and context. Credit it; keep it during any consolidation.
A list/search tool with no limit or pagination parameter can dump an unbounded payload into the context window. The caller must be able to ask for less.
When the same enum is reused across tools but not every combination is valid (e.g. not every product supports every tier), the schema cannot say so — the model finds out via runtime errors. Flag shared enums for a validity review.