MCP server exposing the Ratebook tariff database and rate engine to agents.
Four well-named, read-only tools with clear descriptions (avg 180 chars) and complete input schemas. All parameters are typed and described. Tool names follow verb_noun pattern (lookup_, estimate_, compare_, best_). Descriptions explain WHAT, WHEN, and WHAT IS RETURNED. However, output schemas are not documented in the visible code, only input schemas are explicit. No error handling guidance, no parameter constraints (enums), and no mention of pagination or result limits despite tools returning structured data. Missing tool annotations (readOnlyHint). Composition is sound: each tool has one responsibility, and lookup_tariff feeds into the others via 'label' field.
Find the cheapest contiguous time block to charge (e.g. an EV) on a tariff. Returns the cheapest `charge_hours`-long window within the period, its average marginal $/kWh, and the estimated energy cost to add `kwh_to_add` kWh. Uses the tariff's time-of-use price signal (energy only; demand charges not modeled in v0).
Price several tariffs over the same usage and rank them cheapest-first. Returns `cheapest` (the winning label) and a sorted `comparison`. Plans that can't be priced from the given usage (e.g. time-of-use plans need `hourly_kwh`) are listed with their refusal reason rather than dropped.
Estimate the bill for a tariff (by `label`) over a billing window. `start_date` is ISO (YYYY-MM-DD); `days` is the billing-period length. Provide either `total_kwh` (a single number — sufficient for flat/tiered/seasonal plans) or `hourly_kwh` (a list of length days*24 — required for time-of-use plans). Returns the full result, including a typed `refusal` when the plan can't be priced from the given usage.
Find electricity tariffs by utility name, EIA id, or exact URDB label. Returns matches freshest-first with provenance (source URL, effective date, last update) and whether the rate engine can fully price each plan. Use the returned `label` with the other tools.
Output schemas not documented. Tool descriptions mention what is returned (e.g., 'Returns the full result, including a typed refusal'), but the actual response structure is not visible in the code. LLMs cannot plan downstream operations without knowing response fields.
No error handling guidance. Tools mention 'refusal' (estimate_bill, compare_plans) but do not explain what triggers it, what the refusal structure contains, or how the LLM should recover. Missing recovery guides.
No parameter constraints. 'sector' accepts free-form strings (default 'residential') with no enum or validation. 'limit' has no min/max bounds. LLMs may pass invalid sectors or absurd limits.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
Missing tool annotations. No readOnlyHint despite all tools being read-only. Agents cannot infer safety without explicit annotations.
Pagination not addressed. lookup_tariff returns up to 10 results by default; no mention of total count, next_cursor, or how to fetch more. Large result sets could blow context.