uk-parliament-mcp-server

v0.1.1 pre-1.0

Search UK Parliament bills, members, votes, Hansard, written questions, and committees via MCP. STDIO or Streamable HTTP.

uk-parliament.caseyjhand.com/mcp
claude mcp add --transport http uk-parliament-mcp-server https://uk-parliament.caseyjhand.com/mcp
codex mcp add uk-parliament-mcp-server --url https://uk-parliament.caseyjhand.com/mcp
{
  "mcpServers": {
    "uk-parliament-mcp-server": {
      "url": "https://uk-parliament.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http uk-parliament-mcp-server https://uk-parliament.caseyjhand.com/mcp
{
  "mcpServers": {
    "uk-parliament-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://uk-parliament.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "uk-parliament-mcp-server": {
      "type": "http",
      "url": "https://uk-parliament.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://uk-parliament.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

9

ukparl_lookup_reference

open-world

Resolve Parliament filter IDs and inspect source coverage before searching. Use identifiers for ID namespaces and required selectors, coverage for Hansard date limitations, or a named reference topic for filter IDs. Follow opaque collection cursors with the same filters; use contentCursor to reconstruct an oversized selected payload.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_lookup_reference",
    "arguments": {
      "topic": "<topic>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "topic": {
      "type": "string",
      "enum": [
        "identifiers",
        "coverage",
        "bill_stages",
        "bill_types",
        "parties",
        "departments",
        "answering_bodies"
      ],
      "description": "Reference topic or static identifier/coverage guide."
    },
    "house": {
      "description": "Commons or Lords; required for active parties.",
      "type": "string",
      "enum": [
        "commons",
        "lords"
      ]
    },
    "nameContains": {
      "description": "Case-insensitive AND tokens over the complete named reference set.",
      "type": "string",
      "minLength": 1
    },
    "cursor": {
      "description": "Opaque collection cursor; repeat the same normalized filters.",
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "default": 10,
      "description": "Requested whole reference rows; positive safe integer, default 10, effective cap 20.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "contentCursor": {
      "description": "Opaque same-selection recursive content continuation.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "topic",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_search_bills

open-world

Search Westminster bill summaries by title, House, session, sponsoring member, reference stage or bill type. Use ukparl_lookup_reference for stage/type IDs and ukparl_get_bill for complete selected records. No session or date scope is inferred. Follow collection cursors with the same filters; use contentCursor to reconstruct an oversized item.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_search_bills",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "query": {
      "description": "Bill title search text.",
      "type": "string",
      "minLength": 1
    },
    "house": {
      "description": "Current Commons or Lords House.",
      "type": "string",
      "enum": [
        "commons",
        "lords"
      ]
    },
    "sessionId": {
      "description": "Session identifier discovered in bill records.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "memberId": {
      "description": "Sponsoring member identifier.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "stageIds": {
      "description": "Reference stages, distinct from bill-specific stage IDs.",
      "maxItems": 20,
      "type": "array",
      "items": {
        "description": "Reference stage identifier.",
        "type": "string",
        "pattern": "^[0-9]+$"
      }
    },
    "billTypeIds": {
      "description": "Reference bill types.",
      "maxItems": 20,
      "type": "array",
      "items": {
        "description": "Reference bill type identifier.",
        "type": "string",
        "pattern": "^[0-9]+$"
      }
    },
    "cursor": {
      "description": "Opaque collection continuation; preserve filters.",
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "default": 10,
      "description": "Requested bills; positive safe integer, default 10, effective cap 20.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "contentCursor": {
      "description": "Opaque same-selection lossless content continuation.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_get_bill

open-world

Retrieve a Westminster bill overview or select stages, stage, publications, amendments, amendment, motions or motion. Stage/amendment/motion selections require the bill-specific billStageId from section=stages; singular amendment/motion also require itemId from their parent collection. Use amendmentId for amendment retrieval and motion.id for motions. Collection selectors paginate whole records. Statute handoff uses only actual supplied legislation.gov.uk URLs. Follow contentCursor with the original selection to reconstruct oversized records.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_get_bill",
    "arguments": {
      "billId": "<billId>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "billId": {
      "description": "Parent bill identifier from ukparl_search_bills.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "section": {
      "default": "overview",
      "description": "Selected bill section; overview by default.",
      "type": "string",
      "enum": [
        "overview",
        "stages",
        "stage",
        "publications",
        "amendments",
        "amendment",
        "motions",
        "motion"
      ]
    },
    "billStageId": {
      "description": "Bill-specific stage occurrence ID, required for stage/amendment/motion selections.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "itemId": {
      "description": "Amendment amendmentId or ping-pong motion.id; singular selections only.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "cursor": {
      "description": "Collection continuation; collections only.",
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "description": "Collection records; positive safe integer, default 20, effective cap 50; collections only.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "contentCursor": {
      "description": "Lossless same-selection content continuation.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "billId",
    "section"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_search_members

open-world

Find MPs and peers by name, location or constituency, party, House, and current or historical membership. currentOnly=false includes current and former members. asOf selects historical membership and accepts name only, without House, party or location filters. Search results preserve latest profile fields; retrieve sections with ukparl_get_member. Follow opaque cursors with unchanged filters and use contentCursor for oversized records.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_search_members",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "description": "Name substring; omission searches all names.",
      "type": "string",
      "minLength": 1
    },
    "constituency": {
      "description": "Source location or constituency text, not exact equality.",
      "type": "string",
      "minLength": 1
    },
    "partyId": {
      "description": "Party ID; active reference parties do not exhaust historical IDs.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "house": {
      "description": "Filter most recent House; unavailable with asOf.",
      "type": "string",
      "enum": [
        "commons",
        "lords"
      ]
    },
    "currentOnly": {
      "default": false,
      "description": "True restricts to current members; false includes former and current.",
      "type": "boolean"
    },
    "asOf": {
      "description": "Historical membership on YYYY-MM-DD; only name and pagination may accompany it.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "cursor": {
      "description": "Opaque collection cursor for the same filters.",
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "default": 10,
      "description": "Requested whole members; default 10, cap 20; safe over-cap integers are clamped.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "contentCursor": {
      "description": "Same-selection lossless content continuation.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "currentOnly",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_get_member

open-world

Retrieve a member profile, roles, committee seats, official contact information, registered interests or recorded voting history. Roles without category lists available biography categories; select category to page whole periods. Interests and voting require an explicit House. Committee person IDs differ from member IDs. Voting uses native 20-row pages and reports recorded lobby and teller facts, without lifetime participation metrics. Follow collection cursors with unchanged selectors; use contentCursor to reconstruct oversized records.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_get_member",
    "arguments": {
      "memberId": "<memberId>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "memberId": {
      "description": "Members API decimal identifier from ukparl_search_members.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "section": {
      "default": "profile",
      "description": "Selected member subsection; default profile.",
      "type": "string",
      "enum": [
        "profile",
        "roles",
        "committee_seats",
        "contact",
        "interests",
        "voting"
      ]
    },
    "category": {
      "description": "Roles only: select one complete biography collection.",
      "type": "string",
      "enum": [
        "representations",
        "electionsContested",
        "houseMemberships",
        "governmentPosts",
        "oppositionPosts",
        "otherPosts",
        "partyAffiliations",
        "committeeMemberships"
      ]
    },
    "house": {
      "description": "Required for interests and voting; forbidden for other sections.",
      "type": "string",
      "enum": [
        "commons",
        "lords"
      ]
    },
    "cursor": {
      "description": "Opaque whole-item collection continuation with unchanged selectors.",
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "default": 20,
      "description": "Requested whole rows; default 20, cap 50 for local histories. Voting uses native 20-row pages independently of limit.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "contentCursor": {
      "description": "Opaque same-selection lossless content continuation.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "memberId",
    "section",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_search_divisions

open-world

Search official Commons or Lords division summaries, or use detail, voters or party_totals with a divisionId from the same House. Search supports title/number text, member and inclusive division dates; member searches include teller participation. Detail preserves complete metadata and teller identities, with roster selectors for voters mode. Voters can filter exact source party labels and House-compatible lobbies. not_recorded means only the source list, never abstention. Party totals count listed non-tellers and tellers separately from official headline counts. Follow collection cursors with unchanged filters; reconstruct oversized content using contentCursor.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_search_divisions",
    "arguments": {
      "house": "<house>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "house": {
      "description": "Selected House and division ID namespace.",
      "type": "string",
      "enum": [
        "commons",
        "lords"
      ]
    },
    "mode": {
      "description": "Operation; defaults to search; accepts case-insensitive canonical mode names.",
      "default": "search",
      "type": "string",
      "enum": [
        "search",
        "detail",
        "voters",
        "party_totals"
      ]
    },
    "query": {
      "description": "Division title or number search text; search mode only.",
      "type": "string",
      "minLength": 1
    },
    "memberId": {
      "description": "Members API ID; search includes divisions where this member was a teller.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "divisionId": {
      "description": "Division ID in the selected House; required outside search.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "startDate": {
      "description": "Inclusive source division-date lower bound; search only.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "endDate": {
      "description": "Inclusive source division-date upper bound; search only.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "party": {
      "description": "Exact case-insensitive source party label; voters only, not a party ID.",
      "type": "string",
      "minLength": 1
    },
    "lobby": {
      "description": "Voters only: Commons aye/no/not_recorded or Lords content/not_content.",
      "type": "string",
      "enum": [
        "aye",
        "no",
        "content",
        "not_content",
        "not_recorded"
      ]
    },
    "limit": {
      "description": "Positive safe integer; search default 5/cap 10, voters default 20/cap 50; detail and party_totals do not paginate.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "cursor": {
      "description": "Opaque search/voters collection continuation; repeat the same filters.",
      "type": "string",
      "minLength": 1
    },
    "contentCursor": {
      "description": "Opaque same-selection lossless content continuation, separate from collection cursor.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "house",
    "mode"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_search_hansard

open-world

Search spoken Westminster Hansard contributions by topic, member, House, date or numeric debateSectionId. Returns full source contribution text where supplied, including HTML; previews are labelled summaries. Repeat with a returned debateSectionId to search that section, which does not establish an entire debate transcript. Historical completeness is not guaranteed, including the 2004–2006 website warning despite some API records. Use ukparl_lookup_reference topic=coverage for archive guidance. Follow collection cursors unchanged and contentCursor for lossless oversized contributions; retry timeouts with shorter date windows.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_search_hansard",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "query": {
      "description": "Spoken contribution search text; no date range is inferred.",
      "type": "string",
      "minLength": 1
    },
    "memberId": {
      "description": "Members API identifier discovered with ukparl_search_members.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "house": {
      "description": "Commons or Lords; exact official House aliases are accepted.",
      "type": "string",
      "enum": [
        "commons",
        "lords"
      ]
    },
    "startDate": {
      "description": "Inclusive earliest sitting date, real YYYY-MM-DD; no inferred archive cutoff.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "endDate": {
      "description": "Inclusive latest sitting date, real YYYY-MM-DD; must not precede startDate.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "debateSectionId": {
      "description": "Returned numeric debateSectionId, distinct from external debate IDs.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "limit": {
      "default": 5,
      "description": "Requested whole contributions; default 5, effective cap 20 with notice.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "cursor": {
      "description": "Opaque collection continuation; repeat the same filters and effective limit.",
      "type": "string",
      "minLength": 1
    },
    "contentCursor": {
      "description": "Opaque lossless content continuation; preserve original selection and collection cursor.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_search_questions

open-world

Search Westminster written questions and answer previews by text, asking member, House, answering body, answer state and dates. Use mode=detail with a returned questionId for complete question and answer HTML, corrections and attachment links. A UIN is not a questionId. Search includes all sessions and withdrawn questions. Follow collection cursors unchanged; use contentCursor for lossless oversized answers.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_search_questions",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "search",
      "description": "Search previews or retrieve one complete question.",
      "type": "string",
      "enum": [
        "search",
        "detail"
      ]
    },
    "query": {
      "description": "Question or answer content terms; search only.",
      "type": "string",
      "minLength": 1
    },
    "questionId": {
      "description": "Positive decimal Questions API ID required in detail; UIN is not this ID.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "memberId": {
      "description": "Asking Members API ID; search only.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "answeringBodyIds": {
      "description": "Up to 20 answering-body IDs resolved through ukparl_lookup_reference; search only.",
      "minItems": 1,
      "maxItems": 20,
      "type": "array",
      "items": {
        "description": "Official answering-body ID.",
        "type": "string",
        "pattern": "^[0-9]+$"
      }
    },
    "house": {
      "description": "Commons or Lords; search only.",
      "type": "string",
      "enum": [
        "commons",
        "lords"
      ]
    },
    "answered": {
      "description": "True answered, false unanswered, omission either; search only.",
      "type": "boolean"
    },
    "tabledFrom": {
      "description": "Inclusive tabling start YYYY-MM-DD; search only.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "tabledTo": {
      "description": "Inclusive tabling end YYYY-MM-DD; search only.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "answeredFrom": {
      "description": "Inclusive answer start YYYY-MM-DD; search only.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "answeredTo": {
      "description": "Inclusive answer end YYYY-MM-DD; search only.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "cursor": {
      "description": "Opaque search continuation; repeat unchanged filters.",
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "description": "Search page size, default 10, cap 20; larger safe integers are capped. Omit in detail.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "contentCursor": {
      "description": "Opaque lossless content continuation for this same selection.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "mode"
  ],
  "additionalProperties": false
}
view source ↗

ukparl_get_committee

open-world

Find Westminster committees with mode=search, then use committeeId for detail, members, inquiries or publications. Inquiries returns every committee business type, labelled by isInquiry; use businessId with mode=inquiry for complete business detail or to filter publications. Use publicationId with mode=publication for complete evidence/report document metadata and source links. Memberships retain all role periods; personId is distinct from Members API memberId. No document downloads or text extraction. Follow cursors with unchanged filters; contentCursor retrieves oversized records losslessly. Typed entities retain sourcePath relationships to reconstruct nested source metadata.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ukparl_get_committee",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "default": "search",
      "description": "Search, committee detail, members, business list/detail or publication list/detail.",
      "type": "string",
      "enum": [
        "search",
        "detail",
        "members",
        "inquiries",
        "inquiry",
        "publications",
        "publication"
      ]
    },
    "query": {
      "description": "Search terms for search, inquiries or publications; latter two require at least two characters.",
      "type": "string",
      "minLength": 1
    },
    "house": {
      "description": "Commons, Lords or Joint, case-insensitive; exact House of Commons/Lords aliases also accepted. Search only.",
      "type": "string",
      "enum": [
        "commons",
        "lords",
        "joint"
      ]
    },
    "committeeId": {
      "description": "Committee ID required for detail, members, inquiries and publications.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "businessId": {
      "description": "Business ID required for inquiry; optional additional publication filter.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "publicationId": {
      "description": "Publication ID required for publication detail.",
      "type": "string",
      "pattern": "^[0-9]+$"
    },
    "membership": {
      "description": "Members mode only, default all; filters role-period membership status.",
      "type": "string",
      "enum": [
        "all",
        "current",
        "former"
      ]
    },
    "cursor": {
      "description": "Opaque collection continuation; repeat unchanged filters and effective limit.",
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "description": "Collection size: search default 10 cap 20; nested default 20 cap 50. Safe over-cap values clamp. Omit for singular modes.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "contentCursor": {
      "description": "Opaque same-selection content continuation; reconstruct records before advancing collection cursor.",
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "mode"
  ],
  "additionalProperties": false
}
view source ↗