Skip to content

feat(mcp): add MCP-025, MCP-026 tool description quality rules - #88

Open
bradAGI wants to merge 1 commit into
trustabl:mainfrom
bradAGI:feat/mcp-description-quality
Open

bradAGI wants to merge 1 commit into
trustabl:mainfrom
bradAGI:feat/mcp-description-quality

Conversation

@bradAGI

@bradAGI bradAGI commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Ports the CSDK-017/018 description-quality pair (merged in #40) to MCP. MCP-001 only checks that a docstring exists, so a tool whose docstring reads """TODO: describe this tool.""" or """Gets data.""" passes today while giving connecting clients no selection signal.

A placeholder costs more across a protocol boundary than inside an in-process SDK, for three reasons the rule text makes explicit:

  • The consumer has no fallback context. It can't read the source, the neighboring tools, or the project's docs the way a developer working in the repo can. The tools/list string is genuinely all it gets.
  • The server's authors never see the consequence. Mis-selection surfaces in someone else's client session as a wrong answer — not as an error on this side of the connection. Nothing brings it back to the maintainer.
  • The competition isn't just this server's tools. A client typically connects several servers at once and the model chooses across all of them from these strings alone, so a thin description loses to a well-described tool from an unrelated server that only approximately fits the request.

That third point drives MCP-026's fix: name the domain the tool acts on rather than assuming the server name conveys it, because the model sees the tool alongside every other connected server's.

Verification — engine built at main:

$ trustabl rules validate .
OK: 85 rule pack(s), 208 rule(s) valid under rule schema version 14

Fire (one tool with """TODO: describe this tool.""", one with """Gets data."""): MCP-025, MCP-026
Silent (full description naming when to prefer the neighboring tool): no findings

MCP-026 pairs description_length_lt: 40 with has_docstring: true so it doesn't double-report against MCP-001 on an empty docstring, same as CSDK-018.

No new predicates, so no schema_version bump.

Ports the CSDK-017/018 description-quality pair to MCP. MCP-001 only
checks that a docstring exists, so a tool whose docstring reads "TODO" or
"Gets data." passes today while giving connecting clients no selection
signal.

A placeholder costs more across a protocol boundary than inside an
in-process SDK. The consumer has no other context to fall back on — it
cannot read the source, the neighboring tools, or the project's docs the
way a developer in the repo can. The server's authors also never see the
consequence, since mis-selection surfaces in someone else's client
session as a wrong answer rather than as an error on this side. And a
client typically connects several servers at once, so the model chooses
across all of them from these strings alone and a thin description
competes badly against a well-described tool from an unrelated server.
@jhumel-code

Copy link
Copy Markdown
Collaborator

Thanks @bradAGI. The port is faithful to CSDK-017/018 (same severity, same confidence, same predicates) and, more importantly, the explanation and fix text is genuinely rewritten for the protocol boundary instead of copied across with the wrong framing. That is exactly what I want in an SDK-specific pack. MCP-025 and MCP-026 are free IDs (MCP-023 and MCP-024 are claimed by other open PRs, nothing here collides), mcp_tool is correct for tool scope, and you are right that no schema_version bump is needed, since has_description_text, has_docstring and description_length_lt all exist on main at schema 14.

I read the fixture half in trustabl/agent-reliability-analyzer#165 and it is byte identical to this file, so rules-sync will be satisfied as long as the two land together. Neither half should merge alone.

One note rather than a change request: has_description_text matches case-insensitively on any substring, so a task-management server whose tool reads "Add a todo item to the list." will fire MCP-025. I would rather keep the needle list identical to CSDK-017 than have the two diverge, so let us record that false positive in the rulebook rationale doc, which these two rules still need before they ship. Happy to pair on that part.

If you want a follow-up afterwards, the TypeScript side (the MCP-011 neighbourhood) has no placeholder or length rule yet.

ivanpaghubasan pushed a commit to ivanpaghubasan/agent-reliability-analyzer that referenced this pull request Sep 22, 2026
Engine half of a coordinated pair with trustabl/agent-reliability-rules#88, on a
branch of the same name so the rules-sync job resolves the matching pack
rather than main. Neither half should merge alone — check-rules-sync.sh
fails if they do.

Mirrors mcp/tool_definition.yaml into testdata/rules-fixture and adds
cases to policyRuleCases, as TestPolicyRules_AllRulesCovered requires.

Five cases rather than four. MCP-026 pairs description_length_lt with
has_docstring so an absent docstring stays MCP-001's finding instead of
double-reporting — an empty description is length 0, which is also under
the threshold — and the fifth case is what pins that guard.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants