Skip to content

Every MCP tool declares its own contract, and the README links back to the directory - #13

Merged
illodev merged 2 commits into
mainfrom
tools-declare-their-own-contract
Aug 3, 2026
Merged

Every MCP tool declares its own contract, and the README links back to the directory#13
illodev merged 2 commits into
mainfrom
tools-declare-their-own-contract

Conversation

@illodev

@illodev illodev commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Glama graded the MCP surface C — 3.2/5 across all 30 tools, lowest 2.4. Its per-dimension breakdown put the deficit in Parameters, Completeness and Usage Guidelines, while Conciseness scored highest of the six. So nothing here pads prose; what was missing was declared structure.

What changed

Before After
Input properties with a description 3 / 157 157 / 157
Tools with an outputSchema 0 / 30 30 / 30
Properties declaring a default 0 19
Properties declaring an enum 3 14

outputSchema was not read off the code: all 11 read tools were called against this workspace and their live structuredContent validated against the declared shape. 11/11 conform.

Two judgement calls

Enums only where the vocabulary is genuinely closed. Card status, type, priority and effort come from frozen constants in config/defaults.ts. Areas, document kinds, changelog types and memory statuses go through validateStringList, which accepts any string — an enum there would refuse values a project has legitimately configured. Those point at project_workspace instead.

project_card_release is narrower than the protocol. releasedStatus() keeps the current status — a card just moved to done is not demoted by releasing it — and only doing becomes next. doing is refused as an explicit target, so it is omitted from the enum rather than declared and wrong.

The defect underneath the grade

project_card_transition accepted status as a free string while eight values are frozen in CARD_STATUSES, and its description named a constraint — "while enforcing claim and verification semantics" — that it never stated. A caller had to guess the vocabulary. It scored 1/5 on Completeness because it earned it.

Side effect

Typing the required parameter of schema() and output() as string[] instead of inheriting never[] took tools.ts from 34 strictNullChecks errors to zero. The ratchet asked for a new baseline; repo total is 554 across 56 files, none new.

Verification

  • test — 269/269 pass
  • strict — held, none new
  • doctor — 0 errors, 0 warnings
  • Server started, 30 tools listed, 11/11 replies conform to their declared schemas

CI runs Windows, which is why T-0146 is in review rather than done.

Also here

  • The README carries Glama's score chip and card badge, both verified as live SVGs.
  • T-0147 filed as discovered work: buildAgentContext returns truncated: boolean and toolResult overwrites it with { records: N } past maxToolResultBytes. Two meanings, one key. Not reproduced — it needs a bundle over 512 KB — and the card says so instead of assuming a fix.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WFQ2juk8bVSQQ8QivjopBR

illodev and others added 2 commits August 3, 2026 22:55
Glama publishes a score chip and a card badge for a listed server, and both
only exist once there is a release. The header carries the chip under the
tagline; the card closes the Model Context Protocol section, where the server
it describes is already documented.

Both SVGs were checked before being written in: HTTP 200, image/svg+xml.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WFQ2juk8bVSQQ8QivjopBR
… its reply

All 157 input properties across the 30 tools carry a description, up from
three. Closed protocol vocabularies declare an enum — card status, type,
priority and effort, frozen in config/defaults.ts. Areas, document kinds,
changelog types and memory statuses go through validateStringList, which
accepts any string, so those stay open and point at project_workspace instead
of pretending to be closed. Nineteen properties declare the default their
implementation already had.

Every tool declares an outputSchema, up from none. The shapes were validated
against live replies rather than read off the code, and they are open objects
on purpose: toolResult appends a truncated marker past maxToolResultBytes, so
a closed schema would invalidate the server's own degradation path.

project_card_transition took status as a free string while eight values are
frozen in CARD_STATUSES, and its description named a constraint it never
stated. That is what a caller pays for whether or not anyone is scoring it.

Typing the required parameter of schema() and output() as string[] instead of
inheriting never[] took tools.ts from 34 strictNullChecks errors to zero, so
the baseline is re-recorded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WFQ2juk8bVSQQ8QivjopBR
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workfile Ready Ready Preview Aug 3, 2026 8:56pm
workfile-site Ready Ready Preview Aug 3, 2026 8:56pm

@illodev
illodev merged commit 999d249 into main Aug 3, 2026
13 checks passed
@illodev
illodev deleted the tools-declare-their-own-contract branch August 3, 2026 20:58
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.

1 participant