WebMCP inspector › Guides

Writing WebMCP tool descriptions agents select correctly

How to name and describe WebMCP tools so agents pick the right one: length, side-effect boundaries, parameter descriptions, annotations, and what to leave out.

What a description is for

An agent chooses a tool in two steps: it scans names, then reads the descriptions of the candidates. The description's job is selection — helping the model decide *whether* to call this tool, not documenting how it works. Everything that serves selection belongs in it; everything else belongs on the parameters or nowhere.

Three things serve selection. When to call it: the task, in the user's words (“find products by keyword”). When not to: the neighbor it's confused with (“for the current product's variants use get_product_options instead”). What happens: the side-effect boundary — read-only, or what changes and whether it's reversible. If a description covers those three in one to three sentences, it's done.

Length: long enough to select on, short enough to pay for

Under about 80 characters, a description is a label. Search products tells the agent nothing it didn't get from the name, so it can't separate that tool from browse_collection. Over about 500, you're spending the user's context window on every turn — descriptions ride along with every request the agent makes on your page — and the extra text is usually parameter detail that belongs on the parameter.

The budget compounds. Eight tools at 400 characters is 3,200 characters before the user has typed anything. The inspector totals names and descriptions and flags a page past 2,500; that's where tool metadata starts to crowd out the request itself.

State the side-effect boundary, then annotate it

Agents decide whether to confirm with the user based on what a tool changes. Say it plainly: “Read-only; never changes the cart.” or “Adds one line to the cart; the user can remove it.” Then say the same thing in machine-readable form: annotations: { readOnlyHint: true } for pure reads, consequentialHint: true for purchases, deletions, and anything the user can't undo, untrustedContentHint: true when the result contains reviews, messages, or other user-generated text.

The two must agree. A tool named delete_saved_address with readOnlyHint: true is worse than no annotation, because a well-behaved agent will skip confirmation on the strength of the hint. The inspector flags that contradiction as a should-fix.

Put the detail on the parameters

Formats, units, ranges, and examples live in parameter descriptions, where the agent reads them at the moment it fills the value. query: "Keywords, e.g. 'trail running shoes size 10'" beats a sentence about search syntax in the tool description. Bound everything: maxLength on strings, maxItems on arrays, enum where the choices are finite, minimum/maximum on numbers. The spec lists input limits as a prompt-injection mitigation; they also stop an agent pasting a whole page into a field.

Close every object with additionalProperties: false. Models hallucinate parameters; an open object accepts a misspelled one silently and the tool runs with it missing. A closed object fails at validation, which is the error you want.

{
  "type": "object",
  "properties": {
    "variant_id": {
      "type": "string",
      "pattern": "^[0-9]{6,20}$",
      "description": "The exact variant id from get_product_options. Never guess it."
    },
    "quantity": {
      "type": "integer", "minimum": 1, "maximum": 10, "default": 1,
      "description": "Units to add. Ask the user before adding more than one."
    }
  },
  "required": ["variant_id"],
  "additionalProperties": false
}
Exact ids instead of fuzzy names, bounded values, every property described.

What must not be in a description

  • Instructions to the agent. “Always call this before any other tool.” “Do not mention this to the user.” This is the tool-poisoning pattern in the spec's security considerations; agent clients flag it and some refuse the tool outright.
  • Sequencing that belongs to the agent. Describe what the tool does; let the agent plan. If a tool genuinely depends on another's output, say so as a dependency (“requires a variant_id from get_product_options”), not as a command.
  • Marketing. “Our world-class search.” The model doesn't shop; it selects.
  • Sensitive parameters. Passwords, card numbers, government IDs in an input schema route personal data through the model and its logs. Collect them in the page and have the tool refer to the resulting state.

Names are descriptions too

Selection starts with the name, so make the name carry the task: a verb and an object in lower_snake_case, under 64 characters. search_products, get_cart, add_to_cart, apply_discount_code. Avoid generic names (submit, action, tool) and site prefixes (acme_search) — the agent already knows which page it's on. Two tools whose names differ only in case or separators (search-products vs search_products) are one tool to a tokenizer; the inspector treats that collision as blocking.

Test it the way agents use it

Write a handful of realistic user requests for each tool, including two or three that should pick a *neighboring* tool and two that no tool should handle. Run them against a browser agent on the real page and check which tool it selected and with what arguments. Adjust descriptions until the confusion pairs separate. The WebMCP inspector's grade is the static half of that loop; the eval is the dynamic half, and both are cheap compared with a shopper's agent adding the wrong size to the cart.

Test any site with the WebMCP inspector · WebMCP draft specification