{"name":"io.github.paulieb89/uk-legal-mcp","slug":"paulieb89-uk-legal-mcp","title":"UK Legal Research","description":"UK legal research — case law, legislation, Hansard, bills, votes, committees, HMRC, citations","url":"https://mcp.market/server/paulieb89-uk-legal-mcp","rating":null,"grade":"A","score":93,"certified":false,"status":"active","category":"other","tags":[],"presence":{"score":47,"stars":16,"forks":5,"downloads_week":258,"last_push_at":"2026-09-14T00:33:45.000Z","license":"MIT"},"uptime":{"percent":100,"checks":5,"ok":5,"last_checked_at":"2026-09-20T17:11:18.559Z","last_ok_at":"2026-09-20T17:11:18.559Z","latency_ms":70},"claimed":false,"transport":"mixed","callable_via_gateway":true,"default_price_micros":0,"repository":"https://github.com/paulieb89/uk-legal-mcp","website":"https://bouch.dev/products/uk-legal-mcp","version":"0.6.1","remotes":[{"type":"streamable-http","url":"https://uk-legal-mcp.fly.dev/mcp"}],"packages":[{"registryType":"pypi","identifier":"uk-legal-mcp","version":"0.6.1","runtimeHint":"uvx","transport":{"type":"stdio"}}],"tools":[{"name":"bills_get_bill","description":"USE THIS TOOL WHEN you have a bill_id (from bills_search_bills) and want the full detail.\n\nReturns sponsors, current stage, long title, summary, and Royal Assent\ndate if enacted. Summary text is capped per max_summary_chars — check\nsummary_truncated in the response.\n\nAFTER calling, use parliament_search_hansard(query=bill_short_title) to\nfind the bill's parliamentary debates, or bills_search_bills with a\nrelated keyword for adjacent bills.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"bill_id":{"description":"Bill ID from bills_search_bills results.","minimum":1,"type":"integer"},"max_summary_chars":{"default":5000,"description":"Maximum characters of the bill summary text to return. Default 5,000 (~1,250 tokens) covers most bills. Raise for substantive government bills (Finance Act, Levelling-up) whose summary runs longer. Check summary_truncated in the response to see if it was cut.","maximum":50000,"minimum":500,"type":"integer"}},"required":["bill_id"],"additionalProperties":false}},{"name":"bills_search_bills","description":"USE THIS TOOL WHEN searching UK parliamentary bills by keyword, session, house, or legislative stage.\n\nReturns a paginated page of bill summaries (title, originating and current\nhouse, current stage, whether it became an Act). AFTER calling, pass a bill_id into bills_get_bill for\nfull detail (sponsors, long title, Royal Assent date).\n\nAuthoritative source for UK parliamentary bill status.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"house":{"anyOf":[{"enum":["Commons","Lords","All"],"type":"string"},{"type":"null"}],"default":null,"description":"Filter by originating house: the House the bill was introduced in, wherever it sits now. Omit (or 'All') for all houses."},"limit":{"default":20,"description":"Maximum bills to return in this call. Default 20 keeps responses focused; raise up to 100 for bulk exports.","maximum":100,"minimum":1,"type":"integer"},"offset":{"default":0,"description":"Number of results to skip before this page. Default 0 for the first page. Re-call with offset=offset+returned while has_more is true to paginate.","maximum":2147483647,"minimum":0,"type":"integer"},"query":{"description":"Search term for bill titles and descriptions, e.g. 'online safety' or 'financial services'.","maxLength":500,"minLength":1,"type":"string"},"session":{"anyOf":[{"minimum":1,"type":"integer"},{"type":"null"}],"default":null,"description":"Numeric parliamentary session ID (e.g. 40 = 2024-25, 39 = 2023-24). NOT a year string like '2025'. If you only know the year, omit this and filter the results instead. Omit to search all sessions."},"stage":{"anyOf":[{"enum":["firstreading","secondreading","committee","report","thirdreading","royalassent"],"type":"string"},{"type":"null"}],"default":null,"description":"Filter by current legislative stage."}},"required":["query"],"additionalProperties":false}},{"name":"case_law_grep_judgment","description":"USE THIS TOOL WHEN you have a judgment slug and want to find paragraphs whose text matches a pattern.\n\nReturns a list of `{eId, snippet, match}` hits — small per-paragraph\nsnippets centred on the match. AFTER calling, read full paragraphs via\njudgment_get_paragraph(slug, eId) or the judgment://{slug}/para/{eId}\nresource.\n\nUse case: content search within one judgment (e.g. \"negligence\", \"test\nfor foreseeability\", \"Donoghue\"). For paragraph-number navigation by\neId, call judgment_get_index instead.\n\nPattern is regex; if it doesn't compile, falls back to literal substring\nsearch.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"case_insensitive":{"default":true,"description":"Default true. Set false for case-sensitive matching.","type":"boolean"},"max_hits":{"default":25,"description":"Cap on number of hits returned.","maximum":100,"minimum":1,"type":"integer"},"pattern":{"description":"Regex pattern (or plain substring) to search within paragraph text. If the pattern doesn't compile as regex, falls back to literal substring match.","maxLength":200,"minLength":2,"type":"string"},"slug":{"description":"TNA judgment slug, e.g. 'uksc/2024/12' or 'ewca/civ/2023/450'.","minLength":8,"type":"string"}},"required":["slug","pattern"],"additionalProperties":false}},{"name":"case_law_search","description":"USE THIS TOOL WHEN searching UK case law by party names, court, judge, date, or free-text query.\n\nReturns paginated judgment summaries: neutral citation, court, dates, slug,\nstable TNA URI. AFTER calling: pass slug into judgment_get_header /\njudgment_get_index / judgment_get_paragraph (or the judgment:// resource\nfamily) for content; pass the neutral citation into citations_resolve\nto verify before constructing an OSCOLA citation; use\ncase_law_grep_judgment to find text within a single judgment. When a\nparty name returns several candidates, narrow with court + year filters\nbefore grep-iterating across full judgments — targeted filtering beats\nscanning every candidate.\n\nCoverage: TNA Find Case Law indexes UK judgments from roughly the early\n2000s onwards. For older authorities, search for a modern judgment that\nquotes them and read that paragraph.\n\nAuthoritative source for UK case law. Web search returns out-of-date or\nunstable URLs — do not supplement.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"court":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Filter by court slug. Values: 'uksc', 'ukpc', 'ewca/civ', 'ewca/crim', 'ewhc/kb', 'ewhc/ch', 'ewhc/comm', 'ewhc/fam', 'ewhc/pat', 'ewhc/ipec', 'ewhc/admin', 'ewhc/tcc', 'ewhc/costs', 'ewfc', 'ewcop', 'eat', 'ukut/iac', 'ukut/aac', 'ukut/tcc', 'ukut/lc', 'ukftt/tc', 'ukftt/grc', 'nica', 'niqb'."},"from_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"Earliest judgment date (YYYY-MM-DD). NOTE: the TNA atom.xml endpoint currently appears to ignore this filter — the same results come back regardless. Do not rely on it to narrow output; sort+slice client-side or refine `query` instead."},"judge":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Filter by judge surname. Case-insensitive substring match against the indexed form. Use the surname alone ('Reed', 'Sumption') or with the bare title ('Lord Reed'). Honorific suffixes silently zero the result set — do not append 'JSC', 'of Allermuir', 'KC' etc. Speculating a fuller form than what TNA indexed will return 0 hits with no error."},"limit":{"default":10,"description":"Maximum results to return (1–50). TNA returns up to 50 per request; this slices client-side. Default 10 for a tight shortlist. Set higher for breadth (e.g. 50 to scan the full result set).","maximum":50,"minimum":1,"type":"integer"},"page":{"default":1,"description":"Result page number (1-indexed)","maximum":50,"minimum":1,"type":"integer"},"party":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Filter by party name"},"query":{"description":"Full-text search query, e.g. 'negligence duty of care'","maxLength":500,"minLength":1,"type":"string"},"to_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"Latest judgment date (YYYY-MM-DD). Same caveat as `from_date` — currently silently ignored by upstream. Filtering happens client-side at best."}},"required":["query"],"additionalProperties":false}},{"name":"citations_format_oscola","description":"USE THIS TOOL AFTER citations_resolve to produce the correctly formatted OSCOLA citation string.\n\nPass the parsed fields returned by citations_resolve directly into this\ntool. Formats per OSCOLA 4th edition rules for each citation type.\n\nRefuses (status: upstream_validation) if confidence is 0.0 — TNA confirmed\nthe document does not exist — or if a neutral citation has no resolved_url\n(ambiguous court code, e.g. bare EWHC without a division). In either case,\ndo NOT manufacture a citation; surface the failure and ask the user for\nthe source URL or better identifying details.\n\nDO NOT construct the input fields yourself. The structured input must come\nfrom citations_resolve — guessing fields is the primary citation-fabrication\nroute and this tool is the guard against it.\n\nAuthoritative OSCOLA formatting for UK legal citations (no network call).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"citation_type":{"description":"'type' field from citations_resolve result.","enum":["neutral","law_report","legislation","si","eu_retained"],"type":"string"},"confidence":{"description":"'confidence' from citations_resolve. Refuses to format if 0.0 — that means TNA confirmed the document does not exist. Pass only the value citations_resolve returned; do not guess.","maximum":1,"minimum":0,"type":"number"},"court":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"'court' from citations_resolve, e.g. 'UKSC', 'EWCA CIV', 'EWHC (KB)'."},"legislation_title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"'legislation_title' from citations_resolve, e.g. 'Companies Act 2006'."},"number":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"'number' from citations_resolve (judgment number within the year)."},"page":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"'page' from citations_resolve (starting page in the law report)."},"raw":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"'raw' from citations_resolve. Used as-is for EU retained law — the original text preserves the Regulation/Directive distinction."},"report_series":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"'report_series' from citations_resolve, e.g. 'WLR', 'AC', 'QB'."},"resolved_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"'resolved_url' from citations_resolve. Must be non-null for neutral citations."},"section":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"'section' from citations_resolve, e.g. '47', '12', '20A'."},"si_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"'si_number' from citations_resolve."},"si_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"'si_year' from citations_resolve."},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"'volume' from citations_resolve (law report volume, if any)."},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"'year' from citations_resolve."}},"required":["citation_type","confidence"],"additionalProperties":false}},{"name":"citations_network","description":"USE THIS TOOL WHEN you have a judgment slug and want to map every citation it makes — cases cited, legislation referenced, SIs, retained EU law.\n\nFetches the judgment XML from TNA and parses all OSCOLA citations\nwithin. Returns citations grouped by type, deduplicated and sorted.\nAFTER calling, pass any individual citation through citations_resolve\nto confirm it resolves and to retrieve its canonical URL.\n\nUseful for authority-network analysis (what did this judgment rely on?)\nand for surfacing the legislative landscape a case sits inside.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"case_uri":{"description":"TNA judgment URI slug, e.g. 'uksc/2024/12' or 'ewca/civ/2023/450'. Use the 'uri' field from case_law_search results — not the full URL. Do not include the 'https://caselaw.nationalarchives.gov.uk/' prefix.","minLength":5,"type":"string"}},"required":["case_uri"],"additionalProperties":false}},{"name":"citations_parse","description":"USE THIS TOOL WHEN you have free text (a memo, an email, a clause) and want every OSCOLA-style citation it contains extracted and classified.\n\nIdentifies: neutral citations ([2024] UKSC 12), law reports ([2024] 1 WLR\n100), legislation sections (s.47 Companies Act 2006), SIs (SI 2018/1234),\nretained EU law (Regulation (EU) 2016/679).\n\nParsing is pure regex by default. Ambiguous citations (e.g. bare [2024]\nEWHC without division) can OPTIONALLY be disambiguated by setting\ndisambiguate=True, which asks the CONNECTED CLIENT's own model (not this\nserver) to resolve the division via MCP sampling — off by default.\nCitations resolve to TNA / legislation.gov.uk URLs when possible.\n\nAFTER calling, pass each citation through citations_resolve to verify it\npoints at a real document before quoting or formatting it — the parser\nrecognises the SHAPE of a citation but does not confirm the document\nexists.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"disambiguate":{"default":false,"description":"Default False — pure-regex parsing, no model in the loop. If True, ambiguous citations (e.g. bare EWHC without a division) are sent to the connected client's own LLM, via MCP sampling, to resolve the division. Opt in only when you want best-effort division resolution and accept that a model shapes the result.","type":"boolean"},"text":{"description":"Free text containing OSCOLA citations to extract. Supported: neutral citations ([2024] UKSC 12), law reports ([2024] 1 WLR 100), legislation sections (s.47 Companies Act 2006), SIs (SI 2018/1234), retained EU law (Regulation (EU) 2016/679). Max 50,000 chars.","maxLength":50000,"minLength":1,"type":"string"}},"required":["text"],"additionalProperties":false}},{"name":"citations_resolve","description":"USE THIS TOOL BEFORE constructing an OSCOLA citation string from known fields, OR to confirm a citation points at a real document.\n\nParses + resolves a single citation (neutral citation, SI, legislation\nsection, retained EU law) and returns parsed fields plus resolved_url.\nFor neutral citations, performs a live TNA HEAD check — non-200 sets\nconfidence to 0.0 (document absent). Do NOT format or quote a\nconfidence-0.0 citation.\n\nIf the TNA HEAD check fails (timeout, connection error), raises ToolError\nwith {\"error_category\": \"transient\", \"is_retryable\": true}. One retry is\nattempted — retry this call or proceed without TNA verification.\n\nFormatting a citation from \"known\" fields without prior resolution is the\nmost common fabrication route. If this tool raises or returns no\nresolved_url, do NOT manufacture a citation — surface the failure and ask\nthe user for the source URL.\n\nAuthoritative source for UK legal-citation resolution.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"citation":{"description":"A single OSCOLA citation to parse and resolve. E.g. '[2024] UKSC 12', 'SI 2018/1234', 's.47 Companies Act 2006'","maxLength":500,"minLength":3,"type":"string"}},"required":["citation"],"additionalProperties":false}},{"name":"committees_get_committee","description":"USE THIS TOOL WHEN you have a committee_id and want the metadata + current membership.\n\nFetches committee detail and member list in parallel. AFTER calling,\npass committee_id into committees_search_evidence to see what evidence\nhas been submitted to this committee on what topics.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"committee_id":{"description":"Committee ID from committees_search_committees results.","minimum":1,"type":"integer"}},"required":["committee_id"],"additionalProperties":false}},{"name":"committees_search_committees","description":"USE THIS TOOL WHEN searching or listing UK parliamentary select committees by name, house, or active status.\n\nReturns committee summaries (name, house, active status, ID). AFTER\ncalling, pass committee_id into committees_get_committee for current\nmembership, or into committees_search_evidence to retrieve oral and\nwritten evidence submitted to that committee.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"active_only":{"default":true,"description":"If true, only return currently active committees.","type":"boolean"},"house":{"anyOf":[{"enum":["Commons","Lords","Joint"],"type":"string"},{"type":"null"}],"default":null,"description":"Filter by house."},"limit":{"default":100,"description":"Maximum committees to return. Default 100 comfortably covers all currently-active UK select committees. Raise only for historical sweeps.","maximum":500,"minimum":1,"type":"integer"},"query":{"anyOf":[{"maxLength":300,"type":"string"},{"type":"null"}],"default":null,"description":"Search term for committee names, e.g. 'defence' or 'treasury'. Filtered client-side against committee names. Omit to list all committees."}},"additionalProperties":false}},{"name":"committees_search_evidence","description":"USE THIS TOOL WHEN you have a committee_id and want the oral and written evidence submitted to it.\n\nReturns ONE PAGE of evidence (default 20) plus `total`, the source's\ncount of matching items. evidence_type='both' lists all oral evidence\nfirst, then all written evidence, each newest-published first as the\nsource orders it. Free-text titles are capped per max_title_chars;\nwitness lists are capped at 10 per item. An organisation witness (no\nnamed individual) is rendered as '<Organisation> (<Role>)'; a null\nentry means the source gave no name for that witness at all. For\ncommittees with many submissions, re-call with offset=offset+returned\nwhile has_more is true.\n\nAuthoritative source for parliamentary committee evidence.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"committee_id":{"description":"Committee ID from committees_search_committees results.","minimum":1,"type":"integer"},"evidence_type":{"default":"both","description":"Type of evidence to search.","enum":["oral","written","both"],"type":"string"},"limit":{"default":20,"description":"Maximum evidence items to return. Default 20. For evidence_type='both' a page may hold only oral, only written, or the last oral items followed by the first written items.","maximum":100,"minimum":1,"type":"integer"},"max_title_chars":{"default":300,"description":"Per-item cap on the free-text title field. Default 300 prevents context blow-up from verbose inquiry titles. Raise to 1000+ only when you need the full title text.","maximum":2000,"minimum":50,"type":"integer"},"offset":{"default":0,"description":"Number of evidence items to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true. For evidence_type='both' this is a position in the combined sequence (all oral evidence, then all written evidence).","maximum":2147483647,"minimum":0,"type":"integer"}},"required":["committee_id"],"additionalProperties":false}},{"name":"get_prompt","description":"Get a prompt by name with optional arguments.\n\nReturns the rendered prompt as JSON with a messages array.\nArguments should be provided as a dict mapping argument names\nto values.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"arguments":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Optional arguments for the prompt"},"name":{"description":"The name of the prompt to get","type":"string"}},"required":["name"],"additionalProperties":false}},{"name":"hmrc_check_mtd_status","description":"USE THIS TOOL WHEN you have a 9-digit VAT Registration Number and need that business's Making Tax Digital VAT mandate status.\n\nReturns whether the business is mandated for MTD, effective date, and\ntrading name.\n\nConnects to the HMRC sandbox by default. Set HMRC_API_BASE to\n'https://api.service.hmrc.gov.uk' for production. Requires\nHMRC_CLIENT_ID + HMRC_CLIENT_SECRET environment variables (OAuth 2.0).\nRaises if credentials are not configured — do not infer status.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"vrn":{"description":"VAT Registration Number: 9 digits, e.g. '123456789'. GB prefix accepted and stripped automatically.","maxLength":12,"minLength":9,"type":"string"}},"required":["vrn"],"additionalProperties":false}},{"name":"hmrc_get_vat_rate","description":"USE THIS TOOL WHEN you know the UK VAT category name for a good or service and want its VAT treatment.\n\nExact named-category lookup, not a free-text VAT classifier or tax\nadvice. The query must equal a category name, ignoring only case,\nspacing, hyphens and apostrophe style. Extra qualifying words are never\ndiscarded: 'pet food' is its own category, and 'baby food' is not\n'food'.\n\nA match returns `rate` (standard, reduced, zero or exempt),\n`rate_percentage` (None for exempt), conditions in `notes`, the GOV.UK\n`source_url`, and that entry's `verified_on` date.\n\nAn unresolved query returns no rate: `matched_category`, `rate`,\n`rate_percentage` and `verified_on` are all null, never a default.\nIts `notes` list the category names. AFTER an unresolved result, retry\nwith a listed name or call hmrc_search_guidance.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"commodity_code":{"description":"Commodity code or plain-English description. E.g. 'food', 'domestic fuel', 'software', 'financial services', 'new build residential'","maxLength":200,"minLength":2,"type":"string"}},"required":["commodity_code"],"additionalProperties":false}},{"name":"hmrc_search_guidance","description":"USE THIS TOOL WHEN searching GOV.UK for HMRC tax guidance on a topic (VAT, income tax, corporation tax, etc.).\n\nReturns matching guidance titles, URLs, summaries, and last-updated dates.\nSearches the official GOV.UK content API filtered to HMRC publications.\n\nAuthoritative source for current HMRC tax guidance. Web search returns\nout-of-date or third-party reproductions — do not supplement.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"limit":{"default":10,"description":"Maximum guidance results to return (1–25). Passed to the GOV.UK search count param.","maximum":25,"minimum":1,"type":"integer"},"query":{"description":"Search query for HMRC guidance, e.g. 'VAT digital services', 'R&D tax relief SME'","maxLength":300,"minLength":3,"type":"string"}},"required":["query"],"additionalProperties":false}},{"name":"judgment_get_header","description":"USE THIS TOOL WHEN you have a judgment slug and need metadata (parties, judges, neutral citation, court, dates).\n\nCall case_law_search FIRST to get the slug. AFTER calling, use\njudgment_get_index to discover paragraphs, then judgment_get_paragraph to\nread specific ones. Authoritative source for UK judgment metadata.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"slug":{"description":"Judgment slug, e.g. 'uksc/2024/12' or 'ewca/civ/2023/450'","maxLength":200,"minLength":3,"type":"string"}},"required":["slug"],"additionalProperties":false}},{"name":"judgment_get_index","description":"USE THIS TOOL WHEN you have a judgment slug and want the paragraph navigation index (eId + preview line for every paragraph).\n\nCall case_law_search FIRST to get the slug. AFTER calling, pass an eId\nfrom the returned list into judgment_get_paragraph to read that paragraph's\nfull text, or use case_law_grep_judgment for content search across all\nparagraphs.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"slug":{"description":"Judgment slug, e.g. 'uksc/2024/12'","maxLength":200,"minLength":3,"type":"string"}},"required":["slug"],"additionalProperties":false}},{"name":"judgment_get_paragraph","description":"USE THIS TOOL WHEN you have a judgment slug + LegalDocML eId and want that paragraph's full text.\n\nCall judgment_get_index FIRST to discover available eIds (or use\ncase_law_grep_judgment to locate paragraphs by content). Returns the\nparagraph XML content (400–1,700 tokens typical).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"eId":{"description":"Paragraph eId from judgment_get_index, e.g. 'para_12'. Numeric strings like '12' are accepted and normalized to 'para_12'.","maxLength":100,"minLength":1,"type":"string"},"slug":{"description":"Judgment slug, e.g. 'uksc/2024/12'","maxLength":200,"minLength":3,"type":"string"}},"required":["slug","eId"],"additionalProperties":false}},{"name":"legislation_get_section","description":"USE THIS TOOL WHEN you have a known Act / SI and want the parsed text of a specific section, regulation, or article, with extent and in-force metadata.\n\nReturns the provision's own text and its own heading — never a\nneighbouring or enclosing Part/Chapter's content. Also returns\nterritorial extent, in-force status, and prospective flag. Content\ncapped per max_chars (default 10,000, ~2,500 tokens) — raise for\nunusually long definition sections; check content_truncated in the\nresponse.\n\nWorks uniformly across Act sections ('section-N'), SI regulations\n('regulation-N'), and SI articles ('article-N') — pass the bare\nnumber regardless of which the document uses; you don't need to know\nwhich noun applies. Raises a not_found error (rather than returning\na plausible but wrong node) if the number doesn't exist in this\ndocument — check legislation_get_toc for valid numbers.\n\nALWAYS check `extent` — a section may apply to England & Wales but not\nScotland or Northern Ireland. Reciting a section without checking\nextent is a recurring legal-research error.\n\nAlternative: call read_resource(uri=\"legislation://{type}/{year}/{number}/\nsection/{section}\") for raw CLML XML; use this tool when you want the\nparsed structured response instead.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"max_chars":{"default":10000,"description":"Maximum characters of section content to return. Default 10,000 (~2,500 tokens) covers almost every section. Raise to 50,000+ only for unusually long Finance Act definition sections. Check content_truncated in the response to see if it was cut.","maximum":200000,"minimum":500,"type":"integer"},"number":{"description":"Chapter or SI number","minimum":1,"type":"integer"},"section":{"description":"Provision number, e.g. '47' or '12A' — works for Act sections, SI regulations, and SI articles alike. Use the numeric part only — not 'section-47'/'regulation-47'/'article-47'. Schedules are not currently supported.","maxLength":50,"minLength":1,"type":"string"},"type":{"description":"Legislation type code: 'ukpga' (Acts), 'uksi' (SIs), 'asp' (Scottish Acts), 'nia' (NI Acts). Use the value from legislation_search results.","maxLength":10,"minLength":2,"type":"string"},"year":{"description":"Year of enactment","maximum":2100,"minimum":1800,"type":"integer"}},"required":["type","year","number","section"],"additionalProperties":false}},{"name":"legislation_get_toc","description":"USE THIS TOOL WHEN you have a known Act / SI and want the structural table of contents (parts, chapters, individual sections/regulations/articles).\n\nReturns structural elements with XML id and title, in document order,\ne.g. 'section-47: Definitions' for an Act or 'regulation-4: Maximum\nweekly working time' for an SI. Individual provisions are listed\nalongside their enclosing Part/Chapter/crossheading headings — both\nlevels matter: the heading entries give you the document's shape,\nthe provision entries give you what to pass to legislation_get_section.\nA provision with no heading in the source (rare) is listed as a bare\nid with no title. AFTER calling, pass the numeric identifier (use\n'47', NOT 'section-47') into legislation_get_section for full text.\n\nLarge statutes (Companies Act 2006 has many hundreds of items) are\npaginated via offset/limit. Check has_more and total_items.\n\nAlternative: call read_resource(uri=\"legislation://{type}/{year}/{number}/\ntoc\") for the full TOC as a newline-separated `id: title` string (no\npagination). Use this tool when you need the structured response with\noffset / limit / has_more for stepping through large statutes.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"limit":{"default":200,"description":"Maximum items to return in this call (default 200, max 1000). Raise only when you need a larger slice in one response. Check has_more and total_items to know if further pages exist.","maximum":1000,"minimum":1,"type":"integer"},"number":{"description":"Chapter or SI number","minimum":1,"type":"integer"},"offset":{"default":0,"description":"Number of items to skip from the flattened TOC. Use with limit to page through very large statutes like the Companies Act 2006 (1300+ items).","minimum":0,"type":"integer"},"type":{"description":"Legislation type code: 'ukpga' (Acts), 'uksi' (SIs), 'asp' (Scottish Acts), 'nia' (NI Acts). Use the value from legislation_search results.","maxLength":10,"minLength":2,"type":"string"},"year":{"description":"Year of enactment","maximum":2100,"minimum":1800,"type":"integer"}},"required":["type","year","number"],"additionalProperties":false}},{"name":"legislation_search","description":"USE THIS TOOL WHEN searching UK Acts and Statutory Instruments by title, phrase, or full-text.\n\nReturns ranked results: title, type, year, number, legislation.gov.uk URL,\nand next_steps hints (toc URI, section template). AFTER calling, chain\nto legislation_get_toc then legislation_get_section for structural drill-in.\n\nFilter discipline: `type` and `year` are exact-match. Use only when you\nalready know the value. For currency-driven searches (\"the recent\nRenters' Rights Act\"), query by phrase alone and read the year from the\nresults — guessing a year and filtering by it zeroes results when wrong.\nFor broader concept queries across content, set `fulltext=True`.\n\nAuthoritative source for UK primary and secondary legislation\n(legislation.gov.uk).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"fulltext":{"default":false,"description":"Default false → searches Act/SI titles only (best for finding a named Act, e.g. 'Housing Act 1988' returns ukpga/1988/50 first). Set true to search the full text of every Act/SI for the query (returns SIs and regulations that cite the term — e.g. 'rental deposits' would return many implementing instruments).","type":"boolean"},"limit":{"default":20,"description":"Maximum results to return (1–50). Passed to the upstream results-count param.","maximum":50,"minimum":1,"type":"integer"},"query":{"description":"Search query, e.g. 'Housing Act 1988' or 'data protection personal data'","maxLength":500,"minLength":1,"type":"string"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Filter by type: 'ukpga' (Acts), 'uksi' (SIs), 'asp' (Scottish Acts), 'nia' (NI Acts). Exact-match — omit if you don't already know whether you're looking for an Act vs an SI."},"year":{"anyOf":[{"maximum":2100,"minimum":1800,"type":"integer"},{"type":"null"}],"default":null,"description":"Filter by year of enactment (exact-match — a single integer, not a range). Omit unless you already know the Act's year. Speculating a year (e.g. 'this is recent so it must be 2026') and getting it wrong will zero out the result set. Better workflow: query without `year`, then read the year from the returned results."}},"required":["query"],"additionalProperties":false}},{"name":"list_prompts","description":"List all available prompts.\n\nReturns JSON with prompt metadata including name, description,\nand optional arguments.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"additionalProperties":false}},{"name":"list_resources","description":"List all available resources and resource templates.\n\nReturns JSON with resource metadata. Static resources have a\n'uri' field, while templates have a 'uri_template' field with\nplaceholders like {name}.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{},"additionalProperties":false}},{"name":"parliament_find_member","description":"USE THIS TOOL WHEN you have a member's name and need their integer member_id.\n\nReturns all members matching the name query, each with the integer `id`,\nparty, constituency, house, and current-sitting status. Disambiguates\ncommon-name matches (e.g. \"Lord Smith\" returns multiple peers).\n\nCALL THIS BEFORE any tool that filters by member_id — including\nparliament_get_debate_contributions, parliament_member_debates, and\nparliament_member_interests. Name → ID first; ID-based filtering second.\nSkipping this step and text-searching by name returns unrelated results\n(see parliament_search_hansard's anti-bypass note for the Pannick case).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"name":{"description":"Name or partial name, e.g. 'Starmer', 'Baroness Hale'","maxLength":200,"minLength":2,"type":"string"}},"required":["name"],"additionalProperties":false}},{"name":"parliament_get_debate_contributions","description":"USE THIS TOOL WHEN you have a debate_ext_id and want verbatim contributions, optionally filtered to one member.\n\nCanonical path for \"everything a member said in this debate\" regardless\nof vocabulary — text-search tools (parliament_member_debates,\nparliament_search_hansard) filter by contribution TEXT, dropping members\nwho spoke without using your phrase verbatim. This tool filters by\nMemberId on the debate's Items list, so vocabulary doesn't matter.\n\nTypical chain: parliament_find_member(name) → member_id, then\nparliament_search_hansard or parliament_lookup_by_column → debate_ext_id,\nthen this tool. The parliament module's instructions describe the full\ncomposition pattern.\n\nWithout member_id, returns every contribution (~100-200 for a long debate).\n\nIf the wire returns no contributions for a member you expect to have\nspoken, report the empty result honestly — do NOT reconstruct quotes\nfrom training data. Authoritative source for member contributions.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"debate_ext_id":{"description":"Debate GUID (DebateSectionExtId). Chain from parliament_search_hansard top_debates[].debate_ext_id, parliament_lookup_by_column matches[].debate_ext_id, or any tool that surfaces a debate identifier.","minLength":8,"type":"string"},"member_id":{"anyOf":[{"minimum":1,"type":"integer"},{"type":"null"}],"default":null,"description":"Optional integer Members API ID. When given, only that member's contributions in this debate are returned — regardless of which words they used. Resolves via parliament_find_member. When omitted, every contribution in the debate is returned (typical debate: 100-200 items)."}},"required":["debate_ext_id"],"additionalProperties":false}},{"name":"parliament_get_debate_divisions","description":"USE THIS TOOL WHEN you have a debate_ext_id and want the divisions (formal votes) held within it.\n\nMost debates contain no divisions — Business of the House sittings,\nstatements, urgent questions, debates without a vote. A populated list\ntypically appears around bill stages, motions, and contested amendments.\nEmpty list is the honest result, not a failure mode.\n\nEach returned division carries TWO IDs:\n  - `id` — Hansard-side reference. Useful for cross-referencing in Hansard.\n  - `votes_id` — Lords/Commons Votes API ID (cross-resolved by date+number).\n    AFTER calling, pass `votes_id` as `division_id` into votes_get_division\n    for the full member-by-member voting record.\n\nThe two upstreams use distinct ID-spaces (Hansard Number=3 might be\nVotes-API divisionId=3392). The cross-resolve runs once per (date, house)\ngroup — typically one extra HTTP per debate. `votes_id` is None when the\ncross-resolve found no match.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"debate_ext_id":{"description":"Debate GUID (DebateSectionExtId). Chain from parliament_search_hansard contribution.debate_ext_id, top_debates[].debate_ext_id, or parliament_policy_position_summary top_debates[].debate_ext_id.","minLength":8,"type":"string"}},"required":["debate_ext_id"],"additionalProperties":false}},{"name":"parliament_lookup_by_column","description":"USE THIS TOOL WHEN you have an OSCOLA-style Hansard citation (column + volume + house) and need the debate.\n\nExample input: 'HL Deb 14 Oct 2025, vol 849, col 200'. AFTER calling, read\nthe contribution at the cited column via\nread_resource(uri=\"hansard://debate/{debate_ext_id}/header\") — or,\nequivalently, call parliament_get_debate_contributions(debate_ext_id) for\nthe full list as a structured tool response.\n\nEach match carries:\n  - `contribution_count` — real contribution count from the debate's Items\n  - `source` / `source_code` — citation finality (1=Rolling, 2=Daily,\n    3=BoundVolume, 4=Historic). Resolution is NOT gated on publication state.\n\nEmpty `matches` typically means the volume_number is wrong (opposing\ncounsel sometimes cites running-volume rather than bound-volume) or the\ncolumn is in a Written Statement (use the 'W'-suffixed column as-is).\nIt does NOT mean the citation is fabricated — surface the failure.\n\nAuthoritative source for OSCOLA Hansard column resolution.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"column_number":{"description":"Hansard column number from an OSCOLA footnote, e.g. '200' for 'HL Deb 14 Oct 2025, vol 849, col 200'. String (not integer) to accommodate column suffixes like '1162W' for written answers.","maxLength":20,"minLength":1,"type":"string"},"house":{"default":"both","description":"Restrict to one House. Default 'both' searches across both Houses.","enum":["Commons","Lords","both"],"type":"string"},"volume_number":{"description":"Hansard volume number (the 'vol 849' part of an OSCOLA citation). Required — the endpoint only resolves citations when given the volume; sitting date is NOT a substitute (verified live 2026-05-29).","exclusiveMinimum":0,"type":"integer"}},"required":["column_number","volume_number"],"additionalProperties":false}},{"name":"parliament_member_debates","description":"USE THIS TOOL WHEN you have a member_id and want contributions where THAT member used a specific topic phrase verbatim (text-body search).\n\nCALL parliament_find_member(name) FIRST to obtain the integer member_id.\n\nThis is a name-based text-body search — it matches contributions whose\nTEXT contains the topic phrase. A member who spoke in a debate but\ndidn't use your phrase verbatim is filtered out. For verbatim retrieval\nof every contribution by a member in a known debate (regardless of\nvocabulary), use parliament_get_debate_contributions(debate_ext_id,\nmember_id=...) instead.\n\nEach contribution's text field is capped at 3000 characters.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"limit":{"default":20,"description":"Maximum contributions to return. Default 20.","maximum":100,"minimum":1,"type":"integer"},"member_id":{"description":"Parliament Members API integer ID. Obtain from parliament_find_member.","minimum":1,"type":"integer"},"offset":{"default":0,"description":"Number of contributions to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true.","maximum":2000,"minimum":0,"type":"integer"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Optional phrase to find in THIS member's contribution text bodies. Hansard searches the words the member actually said, NOT the topic or title of the debate. Pass tokens this member would have spoken — distinctive arguments ('disproportionate sanction'), statutory references ('section 21'), or motion numbers ('Motion C1') — not the bill's name (members rarely say e.g. 'Renters\\' Rights Bill' verbatim in their speeches). If you want 'every contribution this member made in a specific debate' regardless of words used, find the debate_ext_id then use parliament_get_debate_contributions(debate_ext_id, member_id=...)."}},"required":["member_id"],"additionalProperties":false}},{"name":"parliament_member_interests","description":"USE THIS TOOL WHEN you have a member_id and need their registered financial interests (donations, directorships, land, gifts).\n\nCALL parliament_find_member(name) FIRST to obtain the integer member_id.\n\nReturns ONE PAGE of interests (default 20, caller controls via limit).\nFor prolific members (big donors, many directorships, extensive land\nholdings), re-call with offset=offset+returned while has_more is true\nto paginate. Description text is capped per max_description_chars;\nraise it for forensic provenance work that needs the full narrative.\n\nThis is the authoritative source for UK MP and peer financial-interest\ndeclarations (via the Members API). Web search returns stale snapshots.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"category":{"anyOf":[{"enum":["employment","employment_adhoc","employment_ongoing","donations","gifts_uk","overseas_visits","gifts_overseas","land","shareholdings","miscellaneous","family_employed","family_lobbying"],"type":"string"},{"type":"null"}],"default":null,"description":"Filter by interest category. Common categories: 'donations' (donations and support), 'gifts_uk' (gifts/hospitality from UK), 'employment' (employment and earnings), 'land' (land and property), 'shareholdings', 'overseas_visits'. Omit for all categories."},"limit":{"default":20,"description":"Max interests per call. Hard-capped at 20 by the upstream interests-api.parliament.uk (verified live 2026-05-29: Take=100 still returns 20). For prolific members, paginate via offset; total size is in totalResults on the response.","maximum":20,"minimum":1,"type":"integer"},"max_description_chars":{"default":500,"description":"Per-entry cap on the free-text description field. Default 500 prevents context blow-up on members with lengthy donation or directorship narratives. Raise to 2000+ only for forensic provenance work.","maximum":5000,"minimum":50,"type":"integer"},"member_id":{"description":"Parliament Members API integer ID. Get from parliament_find_member.","minimum":1,"type":"integer"},"offset":{"default":0,"description":"Number of interests to skip before this page. Default 0 for the first page. To paginate prolific members (100+ interests), re-call with offset=offset+returned while the previous response had has_more=true.","maximum":500,"minimum":0,"type":"integer"}},"required":["member_id"],"additionalProperties":false}},{"name":"parliament_policy_position_summary","description":"USE THIS TOOL WHEN you want debate-level corpus signals on a topic — by_house, by_year, by_section breakdowns — without reading every contribution.\n\nAggregates Hansard debate-level signals on a topic. Pure counts — no LLM,\nno editorial labels. Sweeps /search/Debates.json with pagination (up to\nmax_debates_scanned), then aggregates by_house, by_section, by_year,\nby_month, and top_debates from debate metadata. Also captures the\ncorpus-wide envelope counts (total_contributions, total_written_statements,\ntotal_divisions, etc.) from /search.json for cross-section scope.\n\nAFTER calling, pick a debate from top_debates and pass its debate_ext_id\ninto parliament_get_debate_contributions to drill into who said what.\n\nNote on member-level facets: Hansard's search API exposes debate\nmetadata, not per-contribution member identifiers, at the corpus\nlevel. by_party and top_contributors are therefore omitted from this\ndeterministic summary. To see who spoke in a specific debate, read\nhansard://debate/{debate_ext_id}/header for an ordered contribution\nindex, or call parliament_member_debates for one named member.\n\nThis is the authoritative source for UK Hansard corpus-level signals.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"from_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"Start date (YYYY-MM-DD)"},"house":{"default":"both","description":"Restrict to one House. Default 'both'.","enum":["Commons","Lords","both"],"type":"string"},"max_debates_scanned":{"default":200,"description":"Hard cap on debates sampled from /search/Debates.json to compute facets. Default 200 issues ≤4 upstream calls (take=50 each). Raise to 2000 (≤40 calls) for an exhaustive sweep on a heavily-debated topic. Hansard rate limit: 1000 req/5min.","maximum":2000,"minimum":50,"type":"integer"},"to_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"End date (YYYY-MM-DD)"},"topic":{"description":"Phrase to find in Hansard contribution text bodies for the facet aggregation. Same semantics as parliament_search_hansard.query: tokens that appear in members' actual speeches, not bill titles or topic metadata. The aggregator sweeps top_debates[] returned by /search/Debates.json — those debates are matched on the phrase appearing in titles or contribution text, so passing a Bill title (e.g. 'Renters\\' Rights Bill') usually works for THIS tool even though it wouldn't for member-level text search, because debate-level matching uses metadata in addition to body text.","maxLength":200,"minLength":2,"type":"string"}},"required":["topic"],"additionalProperties":false}},{"name":"parliament_search_hansard","description":"USE THIS TOOL WHEN searching Hansard by topic, bill title, or text phrase.\n\nReturns contributions with citation-grade metadata: member_id, attributed_to,\ncolumn_ref, debate_id, debate_ext_id, contribution_ext_id, public URL. AFTER\ncalling, drill into full content via read_resource(uri=\"hansard://debate/\n{debate_ext_id}/header\") — or, equivalently, call\nparliament_get_debate_contributions(debate_ext_id) for the same content\nas a structured tool response.\n\nDO NOT text-search by member name — to find what a named member said,\nchain parliament_find_member → parliament_get_debate_contributions\n(canonical path for verbatim retrieval). The parliament module's\ninstructions describe the full Pannick-style workflow.\n\nPagination: limit + offset honour the upstream paginated endpoint. For\nbreadth across a topic, see parliament_policy_position_summary.\n\nAuthoritative source for UK parliamentary debates — do not supplement\nwith web search or training-data recall.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"contribution_type":{"default":"Spoken","description":"Which Hansard section to paginate. 'Spoken' = chamber + Westminster Hall debates (the default; what a lawyer usually means). 'Written' = written answers and statements. 'Corrections' = published corrections to the record. The corpus envelope (total_debates, total_divisions, etc.) is independent of this and always populated.","enum":["Spoken","Written","Corrections"],"type":"string"},"from_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"Start date (YYYY-MM-DD)"},"house":{"default":"both","description":"Restrict to one House. Default 'both' returns Commons + Lords contributions.","enum":["Commons","Lords","both"],"type":"string"},"limit":{"default":20,"description":"Max contributions per call (1–100). Default 20. Paginate further with offset; total corpus size is in total_corpus on the response.","maximum":100,"minimum":1,"type":"integer"},"member_id":{"anyOf":[{"minimum":1,"type":"integer"},{"type":"null"}],"default":null,"description":"Filter to contributions by a single member. Pass the integer Members API ID (resolve a name via parliament_find_member). The prior `member` field accepted a name string but Hansard's /search.json silently ignored it — the spec requires `memberId`."},"offset":{"default":0,"description":"Skip this many contributions before the page. Default 0. Re-call with offset=offset+returned to paginate; has_more flags whether more remain.","maximum":5000,"minimum":0,"type":"integer"},"query":{"description":"Phrase to find in Hansard contribution text bodies. Hansard searches the words members actually said in their speeches — NOT debate titles, topic metadata, or written headlines. Pass tokens that would appear in someone's speech: distinctive arguments ('disproportionate sanction'), statutory references ('section 21'), or specific phrases. Bill titles (e.g. 'Renters\\'s Rights Bill') often DON'T match because members refer to 'the Bill' or 'this legislation' in their speeches. Tokenised matching: 'housing benefit fraud' will match contributions saying 'fraud in housing benefit claims'. For 'all contributions in a specific debate' regardless of words used, drill via top_debates[].debate_ext_id into parliament_get_debate_contributions.","maxLength":500,"minLength":1,"type":"string"},"text_mode":{"default":"preview","description":"'preview' returns the upstream ~250-char snippet (fast, low context cost). 'full' returns ContributionTextFull (still capped at 3000 chars). For full contribution text without the cap, read the resource hansard://debate/{debate_ext_id}/contribution/{contribution_ext_id}.","enum":["preview","full"],"type":"string"},"to_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"End date (YYYY-MM-DD)"}},"required":["query"],"additionalProperties":false}},{"name":"parliament_search_petitions","description":"USE THIS TOOL WHEN searching UK Parliament petitions by keyword or topic.\n\nReturns petition title, state, signature count, and dates for government\nresponse or parliamentary debate if applicable. Filter by state (open,\nclosed, debated, etc.) to narrow to live or historical petitions.\n\nThis is the authoritative source for UK Parliament petitions\n(petition.parliament.uk).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"limit":{"default":20,"description":"Maximum petitions to return. Default 20.","maximum":100,"minimum":1,"type":"integer"},"offset":{"default":0,"description":"Number of petitions to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true.","maximum":2000,"minimum":0,"type":"integer"},"query":{"description":"Search term for petition titles, e.g. 'ban trophy hunting' or 'NHS funding'.","maxLength":300,"minLength":2,"type":"string"},"state":{"default":"all","description":"Filter by petition state.","enum":["open","closed","all"],"type":"string"}},"required":["query"],"additionalProperties":false}},{"name":"read_resource","description":"Read a resource by its URI.\n\nFor static resources, provide the exact URI. For templated\nresources, provide the URI with template parameters filled in.\n\nReturns the resource content as a string. Binary content is\nbase64-encoded.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"uri":{"description":"The URI of the resource to read","type":"string"}},"required":["uri"],"additionalProperties":false}},{"name":"votes_get_division","description":"USE THIS TOOL WHEN you have a division_id + house and want the full member-by-member voting record.\n\nVoter lists are truncated to 100 per side to fit response limits; total\nvoter counts are always accurate regardless of truncation. Chain from\nvotes_search_divisions or parliament_get_debate_divisions (which\ncross-resolves Hansard division refs into votes-API division_ids).","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"division_id":{"description":"Division ID from votes_search_divisions results.","minimum":1,"type":"integer"},"house":{"default":"Commons","description":"Which house this division belongs to.","enum":["Commons","Lords"],"type":"string"}},"required":["division_id"],"additionalProperties":false}},{"name":"votes_search_divisions","description":"USE THIS TOOL WHEN searching Commons or Lords formal votes by topic, date, or member.\n\nReturns one page of division summaries (title, date, vote counts,\npass/fail) plus `total`, the source's count of all matching divisions.\nWhile `has_more` is true, re-call with offset=offset+returned. AFTER\ncalling, pass division_id + house into votes_get_division for the full\nmember-by-member voter lists.\n\nAuthoritative source for UK parliamentary vote records.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"from_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"Start date (YYYY-MM-DD)."},"house":{"default":"Commons","description":"Which house to search.","enum":["Commons","Lords"],"type":"string"},"limit":{"default":25,"description":"Maximum divisions to return. Default 25. The Lords API honours up to 100; the Commons API returns at most 25 per call, so page by `returned`, not `limit`.","maximum":100,"minimum":1,"type":"integer"},"member_id":{"anyOf":[{"minimum":1,"type":"integer"},{"type":"null"}],"default":null,"description":"Filter to divisions where this member voted. Get the member ID from parliament_find_member."},"offset":{"default":0,"description":"Number of divisions to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true.","maximum":2147483647,"minimum":0,"type":"integer"},"query":{"anyOf":[{"maxLength":500,"type":"string"},{"type":"null"}],"default":null,"description":"Search term for division titles, e.g. 'Rwanda' or 'Online Safety Bill'. Omit to browse recent divisions."},"to_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"default":null,"description":"End date (YYYY-MM-DD)."}},"additionalProperties":false}}],"scan":{"score":93,"grade":"A","scanned_at":"2026-09-20T11:40:01.021Z","report":{"scannerVersion":"0.1.9","scannedAt":"2026-09-20T11:40:00.964Z","components":{"code":{"score":25,"max":25,"notes":["47 source files scanned"]},"reliability":{"score":20,"max":20,"notes":["remote reachable in 1660ms"]},"poisoning":{"score":15,"max":15,"notes":["35 tool descriptions checked"]},"auth":{"score":10,"max":15,"notes":["open endpoint, read-only tools"]},"maintenance":{"score":15,"max":15,"notes":["last push 6 days ago"]},"identity":{"score":8,"max":10,"notes":["registry namespace matches repository owner","GitHub account older than a year"]}},"findings":[],"inputs":{"probes":[{"url":"https://uk-legal-mcp.fly.dev/mcp","reachable":true,"authRequired":false,"latencyMs":1660,"serverInfo":{"name":"uk-legal-mcp","version":"0.7.1"}}],"packages":[{"registryType":"pypi","identifier":"uk-legal-mcp","version":"0.6.1","found":true,"weeklyDownloads":258,"license":"MIT","dependencyCount":9,"publishedAt":"2026-09-04T21:22:45.137486Z","repositoryUrl":"https://github.com/paulieb89/uk-legal-mcp"}],"repo":{"found":true,"owner":"paulieb89","repo":"uk-legal-mcp","archived":false,"pushedAt":"2026-09-14T00:33:45Z","stars":16,"forks":5,"openIssues":5,"ownerType":"User","ownerAvatarUrl":"https://avatars.githubusercontent.com/u/6341227?v=4","ownerCreatedAt":"2014-01-07T16:37:08Z","license":"MIT"},"icon":{"url":"https://bouch.dev/favicon.ico?favicon.0x3dzn~oxb6tn.ico?dpl=dpl_7Nn4XZTh5BUg67Y4NGVpvE86g1Qd","source":"site","width":256,"height":256},"presence":{"stars":16,"forks":5,"downloadsWeek":258,"license":"MIT","lastPushAt":"2026-09-14T00:33:45.000Z","score":47}}}},"grade_history":[],"reviews":[]}