MCP server for UK Parliament data — bills, votes, MPs, interests, debates, petitions
Five tools with complete input schemas and descriptions, but quality varies significantly. All tools have descriptions (10 - 200+ chars) and parameter types, meeting baseline requirements. However, descriptions are often verbose and example-heavy rather than LLM-optimized. Parameter descriptions are present but inconsistent in clarity. Output schemas are not documented, LLMs cannot predict response structure. Error handling is minimal (generic catch-all in index.ts). No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Tool composition is reasonable (each does one thing), but chaining support is weak, responses don't consistently include IDs needed for downstream calls.
Detect patterns across many parliamentary votes: 'close_votes' finds divisions with a small margin (near-misses or knife-edge votes), 'government_defeats' finds votes the government lost, 'party_rebellion_rate' shows which parties rebel most by percentage of votes cast. Use for trend analysis across many divisions.
Find MPs, bills, petitions, or declared financial interests. entity_type='mp': search members by name/party/constituency/house/status. entity_type='bill': search legislation by title keyword/stage/house. entity_type='petition': find petitions by keyword. entity_type='interest': fetch an MP's declared financial interests. Pass name='John McDonnell' OR mp_id=178 (member ID from a prior MP lookup). Optionally add keyword to filter by topic (e.g. keyword='property'). To find ALL MPs with a given interest topic, omit name/mp_id and pass only keyword='defence'.
Get recent parliamentary events: votes/divisions, party rebellions, bill stage changes, or a specific MP's voting record. event_type='division': recent votes with pass/fail results. event_type='rebellion': divisions with party rebels, optionally filtered by party. event_type='bill': bills filtered by stage or keyword. event_type='member_votes': full voting history for a specific MP — pass name='Nigel Farage' (or mp_id if already known). Shows each division, how the MP voted (Aye/No), and the result.
Cross-dataset query: find MPs matching multiple conditions spanning vote records AND financial interests. Examples: 'Labour MPs who voted No on division 1234', 'MPs who rebelled in division 5678 AND have defence interests', 'MPs with fossil fuel interests who voted Aye'. Specify division_id with voted='aye'/'no' or rebellion_only=true for vote filter. Specify has_interest keyword for interest filter. Results are the intersection of all conditions.
Output schemas not documented. LLMs cannot predict response structure or plan downstream calls. No documentation of what fields are returned, their types, or pagination behavior.
Descriptions contain example values (e.g., 'Nigel Farage', 'John McDonnell', 'defence') that LLMs may reuse literally rather than adapt to context. Should use enums or constraints instead.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). All tools are read-only, but this is not declared. Agents cannot determine retry safety or side effects.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 55 | 2026-07-28+ | v2 |
Rank MPs by rebellion count — how many times they voted against their party whip. Use this for any question about 'most rebellious MPs', 'rebel count', 'which Labour/Conservative MPs rebelled most', or rebellion frequency rankings. Scans all divisions in the date range internally and returns a sorted leaderboard in a single call. Filter by party='Labour' for Labour-specific results.
Error handling is generic. Catch-all in index.ts returns 'Error: <message>' with no recovery guidance. LLMs cannot determine if errors are retryable, user-fixable, or fatal.
Parameter descriptions lack format/constraint details. E.g., 'date_from' says 'YYYY-MM-DD format' but no validation or error message if wrong format is passed. 'limit' has no min/max bounds stated.