stompy-ticketing presents a consolidated ticketing interface with 4 tools that replace ~33 Linear tools. Tool definitions are visible and partially structured, with schemas present and descriptions non-empty. However, several definition quality issues lower the overall score: (1) parameter descriptions exist but are frequently terse (8-30 chars) and lack actionable constraints; (2) output schemas are not documented, responses are opaque JSON serialized via TOON; (3) the 'ticket' tool is overly broad, combining 15 distinct actions (create, update, move, close, archive, batch_archive, unarchive, batch_move, batch_close, claim, release, claim_next, get, list, list_tags) into a single verb_action pattern rather than separate tools; (4) error handling is mentioned in code but not visible in tool definitions; (5) some parameters are ambiguous (e.g., 'ticket_ref' vs 'ticket_id', 'type' filter on ticket_board has no enum in the schema shown). The code demonstrates defensive practices (contextvars for display_id injection, URL stamping abstraction, actor redaction) but these are implementation details not reflected in the MCP surface layer. Naming follows verb_noun for most tools (ticket, ticket_link, ticket_board, ticket_search), but 'ticket' lacks clarity about which of 15 actions it performs.
Primary CRUD + transitions tool for ticket management
Dashboard view tool for kanban or summary board visualization
Relationship management tool for ticket links
Full-text search tool for tickets
The 'ticket' tool combines 15 distinct actions (create, update, move, close, archive, batch_archive, unarchive, batch_move, batch_close, claim, release, claim_next, get, list, list_tags) into a single tool with an action enum. This violates the single-responsibility principle and forces LLMs to reason about which of 15 parameter combinations are valid. Recommendation: split into separate tools like create_ticket, update_ticket, move_ticket, close_ticket, get_ticket, list_tickets, etc.
Parameter descriptions are terse and lack actionable constraints. Example: 'ticket_id' is described as 'Ticket ID (for single ticket operations)' (38 chars), but does not specify valid range, format, or how it differs from ticket_ref. Similarly, 'action' on ticket lacks examples of when each action applies.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 57 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Output schemas are not documented in the tool definitions. The code uses TOON encoding and JSON serialization via _safe_json, with display_id decoration and URL stamping applied dynamically. LLMs cannot plan downstream tool calls without knowing what fields to expect. Each tool should include a documented return schema listing field names, types, and purposes.
No error handling guidance in tool definitions. The code imports error classes (mcp_error, not_found_error, recoverable_error) and raises InvalidTransitionError, ParkArgumentError, LinkAlreadyExistsError, ArchiveRefused, LeaseRefused, but tool definitions do not document what errors are possible, whether they are retryable, or how to recover. Error responses must tell LLMs what to do next per pattern:recovery-guide.
The 'type' parameter on ticket_board lacks an enum in the provided schema. The description says 'Filter by ticket type' but does not specify valid values (e.g., 'bug, feature, task'). Similarly, 'status' parameter on ticket_board and ticket_search lack enum definitions. Free-form strings invite hallucinated values.
Parameter naming is inconsistent across tools. The 'ticket' tool accepts 'ticket_id' (integer) and 'ticket_ref' (string) as separate parameters, forcing LLMs to reason about which to pass. Per pattern:natural-identifiers, tools should accept human-friendly names (display_id) and resolve them server-side, or provide a single overloaded parameter with clear coercion logic.
No pagination guidance in tool definitions. The 'ticket' tool's 'list' action and 'ticket_search' tool do not document whether results are paginated, what the default/max limit is, or how to fetch subsequent pages. The 'limit' parameter on ticket_search is documented as 'Maximum results to return (1-100)' but no default or cursor/offset behavior is specified.
Batch operations (batch_move, batch_archive, batch_close) require a 'confirm' boolean parameter (default false) to preview before executing. This is not documented in the tool description, making it unclear to LLMs when to set confirm=true. A better pattern would be to split preview and execute into separate tools or document the preview/confirm flow explicitly.