ax-check rule

AXC-D013: Near-duplicate descriptions

Two entries have descriptions so similar that an agent has no text to tell them apart.

ax-check is a checker being prepared for release. This page documents the rule ahead of that release; see all 50 rules.

Severitywarn
KindHeuristic. A pattern match: a prompt to look, not a verdict.
Modeax-check lint
Applies toMCP tool lists, OpenAPI, SKILL.md, CLI help
Pattern tagsselection, description
Fix in one lineRewrite both descriptions to state the difference, and name each as the other's neighbour.

Two entries in the same file have descriptions so similar that an agent has no text to tell them apart. It will pick one of them by position, by name or by chance. This usually happens when one description was copied from another and never rewritten.

What it checks

ax-check compares the description of every entry with the description of every other entry in the same file, and reports pairs that are identical or nearly so.

Why it matters

Overlapping tools are common across MCP marketplaces. Tang, Chen and Xiao mapped 1,328,233 tool specifications from 124,267 MCP servers; the paper’s claim (October 2026) is that 98.5% of tools have at least one functional alternative somewhere in the ecosystem. Overlap is fine when each description says what makes its tool different. It is a problem when the text is the same.

Anand and Chattaraj tested how models handle tools built to look right while being wrong, including “semantic decoys” and “capability mirages”. The paper’s claim (8 models, 120 tasks, August 2026) is that such decoys mislead tool selection, with susceptibility varying about 36 times across models. Two near-identical descriptions in your own catalogue may act as accidental decoys for each other. That is design rationale: the paper planted deliberate decoys and did not test accidental duplicates.

How to fix

Rewrite both descriptions so each one states the difference: what it does that the other does not, and when to choose it. Name each as the other’s neighbour (see AXC-D006). If the two entries really do the same thing, remove one.

Example

Before

[
  {
    "name": "archive_invoice",
    "description": "Archives an invoice so it no longer appears in customer invoice lists."
  },
  {
    "name": "void_invoice",
    "description": "Archives the invoice so it no longer appears in the invoice lists for a customer."
  }
]

After

[
  {
    "name": "archive_invoice",
    "description": "Archives an invoice so it no longer appears in invoice lists. It can be restored later with restore_invoice. Use void_invoice instead when the invoice was issued in error and must never be paid."
  },
  {
    "name": "void_invoice",
    "description": "Voids an invoice that was issued in error, so it can never be paid and cannot be restored. Use archive_invoice instead to tidy up a paid invoice that may be needed again."
  }
]

How ax-check detects it

The rule compares every pair of entries that have a real description. Entries with no description, or a placeholder (AXC-D002), are left out. Entries that share a name are skipped, because AXC-D014 reports them.

  1. Two descriptions are identical when they match after lower-casing and dropping everything except letters and digits. Differences in punctuation or spacing do not count.
  2. Otherwise, each description is reduced to a set of content words: stop words and bare numbers are removed, and a light stemmer maps “archives” to “archive” and “lists” to “list”.
  3. If both sets have at least four words, the similarity is the Jaccard index: the number of shared words divided by the number of distinct words across both.
  4. The rule fires when the similarity is 0.8 or more. The default can be changed only through the duplicateThreshold option of the lintSurface library function; there is no command-line flag for it.

Each pair is reported once, on the later entry, with the other entry’s name and the similarity.

Known false negatives: the threshold is strict on purpose. “Lists open invoices for a customer account” and “Lists paid invoices for a customer account” score about 0.67 and are not reported, although an agent may still confuse them. Very short descriptions, with fewer than four content words, are compared only for an exact match. Names are not compared.

Known false positives: entries that genuinely differ only in a detail the words do not show, such as two API versions of one operation, may be reported. State the difference in the text, or silence the rule with --disable AXC-D013.

Sources

  • Paper: Anand and Chattaraj, “Diagnosing Tool-Selection Reasoning in LLM Agents with Canary Tools”, arXiv 2608.04719, 5 August 2026 (preprint, not peer reviewed). https://arxiv.org/abs/2608.04719 . The paper’s claim, across 8 models and 120 tasks, is that decoys such as semantic decoys and capability mirages mislead tool selection, with susceptibility varying about 36 times across models.
  • Paper: Tingxuan Tang, Zilong Chen and Yue (Luna) Xiao, “Understanding the Hierarchical Structure and Functional Landscape of the Model Context Protocol Ecosystem”, arXiv 2610.05319, 4 October 2026 (preprint, not peer reviewed). https://arxiv.org/abs/2610.05319 . The paper’s claim is that 98.5% of 1,328,233 MCP tools have at least one functional alternative.
  • Site guide: Write tool descriptions an agent can act on, agentexperience.tech. https://agentexperience.tech/insights/tool-descriptions/ . Asks every description to name the nearest neighbouring tool and say when it is the wrong choice.

Records in the AX evidence register that share a pattern tag with this rule. A shared tag means the record is about the same pattern, not that it tests this rule. Read the evidence class before the number.