Personal Premier League analysis pipeline. Exposes deterministic query tools over MCP for English Premier League data from 1992/93 to present.
Terrace MCP exhibits strong naming conventions (verb_noun pattern: list_*, get_*, compare, head_to_head) and comprehensive descriptions (avg 180 chars, well above 34-char minimum). All 8 tools have clear, domain-specific descriptions explaining WHAT, WHEN, and context. However, input schemas are minimal: most tools accept only string/integer parameters with no enums, ranges, or validation constraints. Output schemas are entirely undocumented, no structured response definitions visible. Error handling guidance is absent. The server demonstrates good composition (single responsibility per tool) and natural identifiers (club names/ids accepted), but lacks the rigor expected of production-grade tools: no pagination guidance, no per-item error reporting, no recovery hints.
Every Premier League fixture one club played in one season, oldest first. season is the start year, so 2025 means 2025/26. Returns each result with its date, opponent, venue and score, plus the season record. A club that did not play that season comes back with no fixtures and the reason.
Compare one metric across two or more clubs over a season range. Returns each club's series aligned by season, gaps preserved. Use points per game rather than total points when the range crosses the 42-match seasons before 1995/96, or includes the in-progress current season, so the comparison is fair. A comparison is always a report. Build it as an artifact, calling report_style first, rather than printing tables or charts into the chat.
One metric's value for one club across a season range. club is a club name or id (case-insensitive). metric is an id from list_metrics. season_from and season_to are the start years of the range, for example 2015 for 2015/16; omit them for the full history. A season the club did not play, or a season before the metric exists, comes back with a null value and a gap reason. Present the gaps as gaps; never fill them with zero. A range covering more than one season is a report: build it as an artifact, calling report_style first. A single season is a single figure and belongs in chat.
Every Premier League meeting between two clubs, with both clubs' records. This is the fixture level view: individual results, scores, venue, and the win-draw-loss record from each side. Use it for any "who beats whom" or "head to head" question. The club-season metrics cannot answer those, since they hold how a season ended rather than who won a given match. Omit the seasons for the full history. Seasons the two never met come back in gaps, saying whether a club was outside the division or the fixture is still to be played. Cup ties are not held, only league meetings. A head to head is a report. Build it as an artifact, calling report_style first.
No output schemas documented. Tools return data structures (metrics, clubs, fixtures, themes) but LLMs cannot see field names, types, or nesting. Forces agents to guess response structure and risks parsing errors.
Input schemas lack constraints. Parameters accept free-form strings with no enums, ranges, or validation hints. E.g., 'metric' param in get_metric has no enum of valid metric IDs; 'season_from'/'season_to' have no range constraints (e.g., 1992 - 2025). Invites hallucinated invalid values.
No pagination or result-limit guidance. list_metrics and list_clubs descriptions do not state how many items are returned or whether pagination is supported. Large result sets risk context window exhaustion.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 52 | 2026-07-28+ | v2 |
List every canonical Premier League club Terrace holds, with ids.
List every metric that can be queried, from the Terrace registry. Each metric carries its kind. Report a value whose kind is "constructed" as constructed, never as a measurement, and mention its definition when it matters. Call this before answering so the metric ids and their availability are known. These are club-season metrics. For a fixture level question, who beat whom and when, use head_to_head or club_matches instead.
Every report theme, with its core colours and contrast facts. A report ships with two themes, one dark and one light. The rest are opt in. Mention that alternatives exist once, briefly, when you first produce a report, then let the reader raise it.
The house format for a Terrace report artifact. Call before building one. Returns the format contract, a JSX skeleton to copy rather than compose, and the resolved dark and light theme tokens. Pass theme only when the reader names one from list_themes; it replaces the slot matching its own mode. The themes carry computed contrast. Read it before assigning a colour a job: where accent_safe_for_text is false, that theme's accent must not carry words, only graphics.
Error handling absent. No guidance on what happens when a club/metric is not found, a season is invalid, or a theme ID does not exist. Descriptions mention 'gaps' and 'reasons' but do not specify error response structure or recovery steps.
Tool chaining IDs missing from descriptions. get_metric and compare mention building artifacts via report_style, but do not document what IDs/references are returned to enable that chaining. Agents must infer the contract.