UK Legal Research
Server Details
UK legal research — case law, legislation, Hansard, bills, votes, committees, HMRC, citations
- Status
- Healthy
- Uptime
- 97.0% over 77 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- paulieb89/uk-legal-mcp
- GitHub Stars
- 20
- Server Listing
- UK Legal Research MCP Server
- ChatGPT
- –
- Claude
- –
TDQS
Scored across 37 tools
Descriptions actively differentiate the near-neighbours (parliament_get_debate_contributions vs parliament_member_debates vs parliament_search_hansard; judgment_get_index vs case_law_grep_judgment; citations_parse vs citations_resolve vs citations_format_oscola). A few pairs still require careful reading — parliament_search_petitions/parliament_search_hansard/parliament_policy_position_summary all 'search parliament', and citations_network vs citations_parse both extract citations — but the chaining guidance resolves most ambiguity.
Dominant pattern is domain_verb_noun (bills_get_bill, legislation_get_section, committees_search_evidence, votes_get_division), applied consistently across the legal domains. Minor deviations: case_law_grep_judgment uses an irregular verb, parliament_lookup_by_column and parliament_policy_position_summary omit the verb_noun shape, and the generic MCP tools (list_prompts, read_resource, get_prompt, list_resources) have no domain prefix.
37 tools is heavy on raw count, but the server spans ten distinct read-only domains (bills, case law, legislation, committees, parliament, votes, HMRC, citations, resources, prompts), averaging under four tools each. The surface is defensible for the scope, though trimming the four generic MCP scaffolding tools and consolidating parliament search variants would sharpen it.
Coverage is strong: full drill-down chains for judgments (search→header→index→paragraph→grep), legislation (search→toc→section), bills, committees, divisions and Hansard, plus citation resolution/formatting and HMRC lookups. Minor gaps remain — no bill amendment/stage history, no committee report full text, limited HMRC surface beyond VAT/MTD, and no written-answers or EDMs — but core research workflows have no dead ends.
Available Tools
37 toolsbills_get_billGet Bill DetailARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a bill_id (from bills_search_bills) and want the full detail.
Returns sponsors, current stage, long title, summary, and Royal Assent date if enacted. Summary text is capped per max_summary_chars — check summary_truncated in the response.
AFTER calling, use parliament_search_hansard(query=bill_short_title) to find the bill's parliamentary debates, or bills_search_bills with a related keyword for adjacent bills.
| Name | Required | Description | Default |
|---|---|---|---|
| bill_id | Yes | Bill ID from bills_search_bills results. | |
| max_summary_chars | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Bill ID |
| url | Yes | Parliament URL for this bill |
| is_act | No | Whether the bill has received Royal Assent |
| stages | No | Legislative stages the bill has passed through |
| summary | No | Bill summary text, possibly truncated per max_summary_chars. Check summary_truncated and summary_original_length for full-text info. |
| sponsors | No | Bill sponsors |
| long_title | No | Full long title |
| short_title | Yes | Short title of the bill |
| current_house | No | House where the bill currently sits |
| current_stage | No | Current legislative stage |
| originating_house | No | House where the bill was introduced |
| royal_assent_date | No | Date Royal Assent was given |
| summary_truncated | No | True if summary was cut to fit max_summary_chars |
| summary_original_length | No | Original summary length in characters before any truncation |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnly, idempotent, and non-destructive. The description adds concrete behavioral detail about summary truncation and the summary_truncated response flag, which helps the agent anticipate output limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, roughly four sentences, with a clear 'USE THIS TOOL WHEN' lead and no redundant filler. Each segment (condition, returns, follow-up) earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a comprehensive output schema, read-only annotations, and full parameter documentation, the description covers the essential context: when to call, what it returns, truncation behavior, and suggested subsequent actions. It's complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents both parameters comprehensively (source of bill_id, default and bounds for max_summary_chars), so the description's mention of truncation adds a minor cross-reference to the response flag but doesn't materially expand on the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves full bill detail including sponsors, current stage, long title, summary, and Royal Assent date, and specifies the trigger condition (having a bill_id from bills_search_bills). This distinguishes it from the sibling search tool by framing it as the detail-fetching follow-up.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description opens with an explicit conditional: 'USE THIS TOOL WHEN you have a bill_id (from bills_search_bills) and want the full detail.' It also provides a clear follow-up action (parliament_search_hansard) and alternative search suggestion, though it doesn't explicitly name competing tools to exclude.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bills_search_billsSearch Parliamentary BillsARead-onlyIdempotentInspect
USE THIS TOOL WHEN searching UK parliamentary bills by keyword, session, house, or legislative stage.
Returns a paginated page of bill summaries (title, originating and current house, current stage, whether it became an Act). AFTER calling, pass a bill_id into bills_get_bill for full detail (sponsors, long title, Royal Assent date).
Authoritative source for UK parliamentary bill status.
| Name | Required | Description | Default |
|---|---|---|---|
| house | No | Filter by originating house: the House the bill was introduced in, wherever it sits now. Omit (or 'All') for all houses. | |
| limit | No | Maximum bills to return in this call. Default 20 keeps responses focused; raise up to 100 for bulk exports. | |
| query | Yes | Search term for bill titles and descriptions, e.g. 'online safety' or 'financial services'. | |
| stage | No | Filter by current legislative stage. | |
| offset | No | 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. | |
| session | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| bills | No | Matching bills. Use the integer `id` field from any bill to call bills_get_bill for full detail. |
| limit | Yes | Maximum results requested in this call |
| query | Yes | The search term that was used |
| total | No | Total results matching the query across all pages, if the upstream API reported it. None if unknown. |
| offset | Yes | Number of results skipped before this page |
| has_more | Yes | True if more results exist beyond this page. Re-call with offset=offset+returned to fetch the next page. |
| returned | Yes | Number of results actually on this page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds value beyond the readOnlyHint annotation by detailing the return structure (paginated page of bill summaries with title, houses, stage, Act status) and mentioning pagination implicitly. It also notes the workflow to bills_get_bill. However, it does not disclose potential rate limits or error conditions, though these are minor for a read-only search. The description is consistent with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: it leads with the usage trigger, then the return summary, then the follow-up workflow, and ends with a credibility statement. Every sentence serves a purpose with no fluff, and the most important usage guidance is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential usage context: when to use, what it returns, and how to follow up. It mentions pagination and the fields returned, which aligns with the output schema. The guidance to use bills_get_bill for detail completes the workflow. For a search tool with a rich schema and output schema, this is comprehensive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all parameters are already well-documented in the input schema. The description mentions search dimensions (keyword, session, house, stage) which map to parameters, but it does not add further semantic depth beyond what the schema provides. It appropriately relies on the schema's detailed parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool's function: searching UK parliamentary bills by keyword, session, house, or legislative stage. It clearly distinguishes itself from the sibling bills_get_bill, which provides full detail, by noting it returns summaries. The purpose is unambiguous and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description begins with 'USE THIS TOOL WHEN searching...' which is an explicit usage instruction. It also directs the agent to bills_get_bill after calling for full detail, clearly defining when to use this tool versus its sibling. The statement 'Authoritative source for UK parliamentary bill status' further reinforces its intended role.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
case_law_grep_judgmentSearch within a UK Court JudgmentARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a judgment slug and want to find paragraphs whose text matches a pattern.
Returns a list of {eId, snippet, match} hits — small per-paragraph
snippets centred on the match. AFTER calling, read full paragraphs via
judgment_get_paragraph(slug, eId) or the judgment://{slug}/para/{eId}
resource.
Use case: content search within one judgment (e.g. "negligence", "test for foreseeability", "Donoghue"). For paragraph-number navigation by eId, call judgment_get_index instead.
Pattern is regex; if it doesn't compile, falls back to literal substring search.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | TNA judgment slug, e.g. 'uksc/2024/12' or 'ewca/civ/2023/450'. | |
| pattern | Yes | Regex pattern (or plain substring) to search within paragraph text. If the pattern doesn't compile as regex, falls back to literal substring match. | |
| max_hits | No | Cap on number of hits returned. | |
| case_insensitive | No | Default true. Set false for case-sensitive matching. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hits | Yes | Matching paragraphs in document order |
| slug | Yes | The judgment slug that was searched |
| pattern | Yes | The pattern that was searched for |
| truncated | Yes | True if hit count reached max_hits and more matches may exist |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, covering safety. The description adds valuable behavioral context: it returns only small snippets (not full paragraphs), and it discloses the regex fallback to literal substring search if compilation fails. This goes beyond the annotations and is helpful for setting expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with a directive usage trigger, followed by concise notes on return format, post-processing, and fallback behavior. It contains no redundant filler, though the 'AFTER calling' clause could be seen as slightly verbose but is still informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (4 parameters, output schema present), the description covers purpose, usage, output format, and follow-up actions, which is sufficient for tool selection. It does not mention max_hits or case_insensitive defaults, but those are already well-documented in the schema, so the description need not repeat them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description does not add new parameter-level meaning beyond the schema; it only restates the regex fallback already present in the pattern property description. The schema itself documents all four parameters well, so no extra benefit is derived from the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool searches paragraphs within a specific UK court judgment matching a pattern, using a specific verb and resource. It also distinguishes from siblings by explicitly mentioning judgment_get_index for paragraph-number navigation and judgment_get_paragraph for reading full paragraphs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description opens with 'USE THIS TOOL WHEN you have a judgment slug and want to find paragraphs whose text matches a pattern', providing a clear trigger condition. It also gives a concrete use case, an explicit alternative for index navigation, and follow-up guidance to retrieve full paragraphs, making usage guidance explicit and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
case_law_searchSearch UK Case LawARead-onlyIdempotentInspect
USE THIS TOOL WHEN searching UK case law by party names, court, judge, date, or free-text query.
Returns paginated judgment summaries: neutral citation, court, dates, slug, stable TNA URI. AFTER calling: pass slug into judgment_get_header / judgment_get_index / judgment_get_paragraph (or the judgment:// resource family) for content; pass the neutral citation into citations_resolve to verify before constructing an OSCOLA citation; use case_law_grep_judgment to find text within a single judgment. When a party name returns several candidates, narrow with court + year filters before grep-iterating across full judgments — targeted filtering beats scanning every candidate.
Coverage: TNA Find Case Law indexes UK judgments from roughly the early 2000s onwards. For older authorities, search for a modern judgment that quotes them and read that paragraph.
Authoritative source for UK case law. Web search returns out-of-date or unstable URLs — do not supplement.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Result page number (1-indexed) | |
| court | No | 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'. | |
| judge | No | 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 | No | 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). | |
| party | No | Filter by party name | |
| query | Yes | Full-text search query, e.g. 'negligence duty of care' | |
| to_date | No | Latest judgment date (YYYY-MM-DD). Same caveat as `from_date` — currently silently ignored by upstream. Filtering happens client-side at best. | |
| from_date | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | Current page number (1-indexed) |
| results | Yes | Matching judgments for this page |
| has_more | Yes | Whether additional pages exist |
| total_pages | No | Total page count if available from API |
| unparsed_results | No | Feed entries on this page that could not be parsed and are omitted from `results`. When greater than zero, `results` is incomplete for this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/openWorld/idempotent, and the description adds real value on top: coverage window (roughly early 2000s onward), fallback for older authorities, the returned summary fields, and a warning about unstable web URLs. The one defect is the advice to 'narrow with court + year filters', which conflicts with the schema's own note that from_date/to_date are silently ignored upstream — an agent following that tip would waste a call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded trigger phrase, then short paragraphs for returns, after-call routing, and coverage — each sentence carries information. It is on the long side for a single tool, and one of its lines (year filters) does not earn its place because it is inaccurate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so it does not need to explain return values, yet it does briefly and harmlessly. What it omits is consistency: it recommends year filtering while the schema says date filters are no-ops, leaving the agent with two conflicting stories about how to narrow results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so per-parameter semantics (court slugs, judge surname matching, limit slicing, date caveats) are already carried by the schema. The description adds only marginal parameter context by enumerating the searchable facets and the party-name narrowing tactic; baseline 3 is right when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with an explicit verb and resource ('searching UK case law') plus the exact facets it accepts (party names, court, judge, date, free text). It also distinguishes itself from the near-siblings by naming judgment_get_header / judgment_get_index / judgment_get_paragraph, case_law_grep_judgment and citations_resolve as downstream steps rather than substitutes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use trigger, then a full after-call routing map: slug into judgment_get_*, neutral citation into citations_resolve, grep for in-judgment text. It even states the exclusion ('do not supplement' with web search) and the narrowing strategy for ambiguous party names, so no alternative is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
citations_format_oscolaFormat OSCOLA Citation StringARead-onlyIdempotentInspect
USE THIS TOOL AFTER citations_resolve to produce the correctly formatted OSCOLA citation string.
Pass the parsed fields returned by citations_resolve directly into this tool. Formats per OSCOLA 4th edition rules for each citation type.
Refuses (status: upstream_validation) if confidence is 0.0 — TNA confirmed the document does not exist — or if a neutral citation has no resolved_url (ambiguous court code, e.g. bare EWHC without a division). In either case, do NOT manufacture a citation; surface the failure and ask the user for the source URL or better identifying details.
DO NOT construct the input fields yourself. The structured input must come from citations_resolve — guessing fields is the primary citation-fabrication route and this tool is the guard against it.
Authoritative OSCOLA formatting for UK legal citations (no network call).
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | 'raw' from citations_resolve. Used as-is for EU retained law — the original text preserves the Regulation/Directive distinction. | |
| page | No | 'page' from citations_resolve (starting page in the law report). | |
| year | No | 'year' from citations_resolve. | |
| court | No | 'court' from citations_resolve, e.g. 'UKSC', 'EWCA CIV', 'EWHC (KB)'. | |
| number | No | 'number' from citations_resolve (judgment number within the year). | |
| volume | No | 'volume' from citations_resolve (law report volume, if any). | |
| section | No | 'section' from citations_resolve, e.g. '47', '12', '20A'. | |
| si_year | No | 'si_year' from citations_resolve. | |
| si_number | No | 'si_number' from citations_resolve. | |
| confidence | Yes | '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. | |
| resolved_url | No | 'resolved_url' from citations_resolve. Must be non-null for neutral citations. | |
| citation_type | Yes | 'type' field from citations_resolve result. | |
| report_series | No | 'report_series' from citations_resolve, e.g. 'WLR', 'AC', 'QB'. | |
| legislation_title | No | 'legislation_title' from citations_resolve, e.g. 'Companies Act 2006'. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint, destructiveHint), the description discloses refusal behavior: 'Refuses (status: upstream_validation) if confidence is 0.0... or if a neutral citation has no resolved_url.' It also states 'no network call' and warns against manufacturing citations. This adds significant behavioral context that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the critical workflow instruction and is organized into short, purposeful sentences. There is some repetition ('do NOT construct the input fields yourself' and 'do not guess'), but it is a safety-critical guardrail that benefits from emphasis. Overall, every sentence earns its place, though minor tightening could remove redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (14 parameters, multiple citation types) and the existence of an output schema, the description fully covers what an agent needs: the pipeline sequence, refusal conditions, the anti-fabrication rule, and the authoritative format. It does not explain return values, but the output schema covers that. The description is complete for its role.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully explains each parameter. The description adds an overarching rule that all parameters must come from citations_resolve, but this is more of a usage guideline than parameter semantics. The schema already covers details like confidence refusal and the EU-retained-law raw handling, so the description adds no new per-parameter meaning. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'produce the correctly formatted OSCOLA citation string.' It also distinguishes from siblings by explicitly saying 'USE THIS TOOL AFTER citations_resolve,' placing it clearly in the pipeline relative to citations_parse and citations_resolve.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: 'USE THIS TOOL AFTER citations_resolve' and 'Pass the parsed fields returned by citations_resolve directly into this tool.' It also gives strong exclusions and failure-handling instructions: 'DO NOT construct the input fields yourself,' 'surface the failure and ask the user for the source URL or better identifying details.' This is comprehensive and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
citations_networkGet Case Citation NetworkARead-onlyIdempotentInspect
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.
Fetches the judgment XML from TNA and parses all OSCOLA citations within. Returns citations grouped by type, deduplicated and sorted. AFTER calling, pass any individual citation through citations_resolve to confirm it resolves and to retrieve its canonical URL.
Useful for authority-network analysis (what did this judgment rely on?) and for surfacing the legislative landscape a case sits inside.
| Name | Required | Description | Default |
|---|---|---|---|
| case_uri | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| eu_refs | No | Retained EU law references, e.g. 'Regulation (EU) 2016/679' |
| si_refs | No | Statutory Instrument references, e.g. 'SI 2018/1234' |
| case_uri | Yes | The judgment URI that was fetched and parsed |
| law_report_refs | No | Law report citations, e.g. '[2020] 1 WLR 100' |
| total_citations | Yes | Sum of all de-duplicated citations across every bucket |
| legislation_refs | No | Legislation section references, e.g. 's.47 Companies Act 2006' |
| neutral_citations | No | Neutral citations referenced, e.g. '[2020] UKSC 14' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as readOnly/idempotent/non-destructive. The description adds valuable behavior details: fetching judgment XML from TNA, parsing OSCOLA citations, grouping by type, deduplicating, and sorting. It also discloses that the tool does not resolve citations, which is a key behavioral limitation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the usage condition and is organized into three focused paragraphs. All sentences contribute useful context, though the format is slightly more verbose than necessary for the information conveyed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the input precondition (judgment slug), what the tool does (parse TNA XML for OSCOLA citations), output characteristics (grouped, deduplicated, sorted), and follow-up action (use citations_resolve). With an output schema present, it is fully complete for this tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description for case_uri is thorough (slug format, use 'uri' field, no prefix), providing 100% coverage. The description only reiterates the concept of a 'judgment slug' without adding new parameter-level semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool maps all citations a judgment makes, including cases, legislation, SIs, and retained EU law. It distinguishes itself from sibling tools by emphasizing the network-wide mapping and integration with citations_resolve.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly starts with 'USE THIS TOOL WHEN you have a judgment slug and want to map every citation it makes' and directs the user to pass citations through citations_resolve after. This provides clear when-to-use and a follow-up alternative, aligning with the sibling tool's purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
citations_parseParse OSCOLA CitationsARead-onlyInspect
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.
Identifies: 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).
Parsing is pure regex by default. Ambiguous citations (e.g. bare [2024] EWHC without division) can OPTIONALLY be disambiguated by setting disambiguate=True, which asks the CONNECTED CLIENT's own model (not this server) to resolve the division via MCP sampling — off by default. Citations resolve to TNA / legislation.gov.uk URLs when possible.
AFTER calling, pass each citation through citations_resolve to verify it points at a real document before quoting or formatting it — the parser recognises the SHAPE of a citation but does not confirm the document exists.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | 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. | |
| disambiguate | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ambiguous | Yes | Citations with confidence < 0.7; may have been partially disambiguated via sampling |
| citations | Yes | All successfully parsed citations (confidence >= 0.7) |
| text_length | Yes | Character length of the input text |
| parse_duration_ms | Yes | Time taken to parse, in milliseconds |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=true, destructiveHint=false), the description adds critical behavioral context: parsing is pure regex by default, optional disambiguation invokes the client's own LLM via MCP sampling, and recognition of citation shape does not guarantee document existence. This meaningfully informs the agent of limitations and side effects (model-in-the-loop) that annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections: a bolded usage trigger, a list of supported citation types, parsing behavior, and a follow-up instruction. It is front-loaded with the most important 'when to use' information and every sentence contributes operational value without redundancies.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has only 2 parameters, an output schema, and rich sibling context, the description fully covers the essential operational details: input type, output scope, disambiguation behavior, URL resolution, and the requirement to verify via citations_resolve. It clearly differentiates itself from the resolve and format siblings, so an agent can select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the parameter descriptions already fully explain the text and disambiguate parameters. The tool description repeats the supported citation types and the disambiguation behavior, adding little new semantic value beyond the schema. It does hint at URL resolution as output, but that is not a parameter-level detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action ('extract and classify every OSCOLA-style citation') and identifies the target resource (free text). It lists concrete citation types and explicitly separates itself from sibling tools like citations_resolve by stating what it does not do (confirm existence). The verb and scope are precise and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states when to use the tool ('USE THIS TOOL WHEN you have free text... and want every OSCOLA-style citation... extracted and classified') and explicitly directs the agent to follow up with citations_resolve for verification. It does not explicitly say when not to use it, but the alternative/next-step guidance is strong and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
citations_resolveResolve Single OSCOLA CitationARead-onlyIdempotentInspect
USE THIS TOOL BEFORE constructing an OSCOLA citation string from known fields, OR to confirm a citation points at a real document.
Parses + resolves a single citation (neutral citation, SI, legislation section, retained EU law) and returns parsed fields plus resolved_url. For neutral citations, performs a live TNA HEAD check — non-200 sets confidence to 0.0 (document absent). Do NOT format or quote a confidence-0.0 citation.
If the TNA HEAD check fails (timeout, connection error), raises ToolError with {"error_category": "transient", "is_retryable": true}. One retry is attempted — retry this call or proceed without TNA verification.
Formatting a citation from "known" fields without prior resolution is the most common fabrication route. If this tool raises or returns no resolved_url, do NOT manufacture a citation — surface the failure and ask the user for the source URL.
Authoritative source for UK legal-citation resolution.
| Name | Required | Description | Default |
|---|---|---|---|
| citation | Yes | A single OSCOLA citation to parse and resolve. E.g. '[2024] UKSC 12', 'SI 2018/1234', 's.47 Companies Act 2006' |
Output Schema
| Name | Required | Description |
|---|---|---|
| raw | Yes | Original citation text as found in the source |
| page | No | Starting page in the law report |
| type | Yes | Classification of the citation type |
| year | No | Year component of the citation |
| court | No | Court code: UKSC, UKPC, EWCA Civ, EWCA Crim, EWHC (KB), EWHC (Ch), EWHC (Comm), EWHC (Fam), EWHC (Pat), EWHC (IPEC), UKUT (IAC), UKUT (TCC), UKUT (AAC), UKUT (LC), EAT, UKFTT (TC), UKFTT (GRC) |
| number | No | Judgment number within the year |
| volume | No | Report volume number (for law reports) |
| section | No | Section number referenced |
| si_year | No | SI year (for SI YYYY/NNN citations) |
| si_number | No | SI number |
| confidence | Yes | Parse confidence 0.0–1.0. Citations below 0.7 are ambiguous and may have been sent for LLM disambiguation. |
| resolved_url | No | TNA Find Case Law or legislation.gov.uk URL if successfully resolved |
| report_series | No | Law report series abbreviation: WLR, AC, QB, KB, Ch, All ER, EWCA Civ, etc. |
| legislation_title | No | Title of legislation (for s.NN Act YYYY citations) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description reveals live TNA HEAD-check behavior, confidence scores dropping to 0.0 on non-200 responses, and ToolError with retryable semantics. It also warns about quoting low-confidence results, which is important behavioral context for downstream use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loads the usage directive, but some safety warnings are repeated (e.g., not formatting or quoting unresolved citations). The redundancy is understandable for risk mitigation but prevents a perfect conciseness score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers input, output shape, error behavior, retry semantics, and downstream safety considerations. Given the presence of an output schema, the additional context about confidence and resolved_url is sufficient for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully describes the single required citation parameter with length constraints and concrete examples. The tool description additionally enumerates accepted citation types, making the parameter semantics clear and actionable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool parses and resolves a single OSCOLA citation, returning parsed fields and a resolved_url. It also distinguishes this from sibling tools like citations_parse and citations_format_oscola by emphasizing real-document resolution.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs agents to use this tool before constructing an OSCOLA citation string or confirming that a citation points to a real document. It also provides critical guidance about not manufacturing citations when resolution fails, which clearly defines when and how to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
committees_get_committeeGet Committee DetailARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a committee_id and want the metadata + current membership.
Fetches committee detail and member list in parallel. AFTER calling, pass committee_id into committees_search_evidence to see what evidence has been submitted to this committee on what topics.
| Name | Required | Description | Default |
|---|---|---|---|
| committee_id | Yes | Committee ID from committees_search_committees results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Committee ID |
| url | No | Parliament URL for this committee |
| name | Yes | Committee name |
| No | Contact email | |
| house | No | Commons, Lords, or Joint |
| phone | No | Contact phone number |
| members | No | Current committee members |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, lowering the burden. The description adds valuable behavioral context by noting that committee detail and member list are fetched in parallel, and it reveals the intended follow-up workflow. This goes beyond simple safety disclosure, though it doesn't detail response structure or pagination (which are covered by the output schema).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the key usage condition, followed by the action and a next-step suggestion. Every sentence provides distinct value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter get-by-ID tool with rich annotations and an output schema, the description fully covers the necessary context: when to use it, what it returns, and what to do next. The workflow hint to committees_search_evidence completes the contextual picture.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter committee_id is already well-described in the schema as coming from committees_search_committees results. The description does not add additional semantic meaning beyond that, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states this tool fetches committee detail and member list, with an explicit 'USE THIS TOOL WHEN...' condition. It distinguishes itself from sibling search tools by requiring a committee_id and focusing on metadata + membership.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance ('when you have a committee_id and want metadata + current membership') and adds a workflow pointer to committees_search_evidence. However, it does not explicitly state when not to use it or name alternative tools for lookup scenarios, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
committees_search_businessesSearch Committee Inquiries and BusinessARead-onlyIdempotentInspect
USE THIS TOOL WHEN identifying a committee inquiry or business before evidence retrieval.
Returns official business IDs, titles, types, dates, and report/status metadata. AFTER calling, use an exact ID as committee_business_id in committees_search_evidence. Source: UK Parliament Committees API CommitteeBusiness endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum inquiry/business records to return (1–100). | |
| query | No | Optional official inquiry/business title search term. Returns source-supplied IDs; do not infer an ID from a title. | |
| committee_id | Yes | Committee ID from committees_search_committees results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | No | Source search term applied, if any |
| total | Yes | Number of businesses returned in this page |
| businesses | No | Matching source-supplied committee businesses or inquiries |
| committee_id | Yes | Committee ID used to scope the discovery request |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds value beyond that by disclosing the workflow position and the exact handoff field name into the evidence tool. It stops short of stating anything about result-set size or paging behavior, which is the only remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short lines, front-loaded with the trigger condition in caps, then return payload, then the next-step handoff. Every sentence carries a distinct, actionable fact with no repetition of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Workflow entry and exit are both described, the return contents are summarized, and an output schema exists so field-level return detail is handled elsewhere. For a three-parameter read-only search, an agent has everything needed to call it and chain onward correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already explains limit bounds, the query title-search caveat, and the committee_id provenance, so the baseline is 3. The description adds the downstream use of the returned ID but contributes no additional parameter semantics of its own.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('identifying a committee inquiry or business') and states what it returns (IDs, titles, types, dates, report/status metadata). It is clearly separable from the sibling committees_search_evidence, which is a downstream step rather than the same lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('USE THIS TOOL WHEN identifying a committee inquiry or business before evidence retrieval') and an explicit follow-up ('AFTER calling, use an exact ID as committee_business_id in committees_search_evidence'). The when-to-use and the alternative are both spelled out, so nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
committees_search_committeesSearch Parliamentary CommitteesARead-onlyIdempotentInspect
USE THIS TOOL WHEN searching or listing UK parliamentary select committees by name, house, or active status.
Returns committee summaries (name, house, active status, ID). AFTER calling, pass committee_id into committees_get_committee for current membership, or into committees_search_evidence to retrieve oral and written evidence submitted to that committee.
| Name | Required | Description | Default |
|---|---|---|---|
| house | No | Filter by house. | |
| limit | No | Maximum committees to return. Default 100 comfortably covers all currently-active UK select committees. Raise only for historical sweeps. | |
| query | No | Search term for committee names, e.g. 'defence' or 'treasury'. Searched by the upstream API before `limit` is applied. Omit to list all committees. | |
| active_only | No | If true, only return currently active committees. |
Output Schema
| Name | Required | Description |
|---|---|---|
| house | No | House filter applied, or None |
| query | No | Name substring filter applied, or None |
| total | Yes | Number of committees returned in this call |
| committees | No | Matching committees. Use committees_get_committee for membership detail. |
| active_only | Yes | Whether results were restricted to currently active committees |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnly/idempotent/non-destructive safety, so the description's added value is the return shape and the downstream chaining contract (pass committee_id onward), which is genuinely useful workflow context. It does not mention result-volume or upstream-search ordering, though the schema covers the latter.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short blocks, front-loaded with the trigger condition, then the return contract and follow-on routing. No sentence is redundant with another, and nothing buries the invocation condition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, full annotation coverage, and 100%-documented parameters, the description only needs to supply purpose, trigger, and chaining — all of which it does. Nothing required to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema itself explains each parameter's intent (including why limit defaults to 100), so the description adds no parameter-level meaning beyond its one-line mention of 'name, house, or active status'. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (search/list) and resource (UK parliamentary select committees) plus the three filter axes: name, house, active status. It also declares the return payload (name, house, active status, ID), so an agent can distinguish it from committees_get_committee and committees_search_evidence without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Opens with an explicit 'USE THIS TOOL WHEN' trigger condition and routes the agent forward to committees_get_committee for membership and committees_search_evidence for evidence. It stops short of naming an explicit exclusion ('do not use for X'), but the search-versus-retrieve split against its closest siblings is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
committees_search_evidenceSearch Committee EvidenceARead-onlyIdempotentInspect
USE THIS TOOL WHEN retrieving committee evidence, especially for an identified inquiry.
Returns ONE PAGE of evidence (default 20) plus total, the source's
count of matching items. evidence_type='both' lists all oral evidence
first, then all written evidence, each newest-published first as the
source orders it. Free-text titles are capped per max_title_chars;
witness lists are capped at 10 per item. An organisation witness (no
named individual) is rendered as ' ()'; a null
entry means the source gave no name for that witness at all. For
committees with many submissions, re-call with offset=offset+returned
while has_more is true. For inquiry-specific research, first call
committees_search_businesses and pass its exact committee_business_id;
this filters at the authoritative source before pagination.
Source: UK Parliament Committees API oral and written evidence endpoints.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | 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. | |
| offset | No | 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). | |
| committee_id | Yes | Committee ID from committees_search_committees results. | |
| published_to | No | Optional inclusive source publication-date upper bound (YYYY-MM-DD). Applied upstream before pagination. | |
| evidence_type | No | Type of evidence to search. | both |
| published_from | No | Optional inclusive source publication-date lower bound (YYYY-MM-DD). Applied upstream before pagination. | |
| max_title_chars | No | 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. | |
| committee_business_id | No | Exact official inquiry/business ID from committees_search_businesses. Applies the source filter before pagination; do not infer this from a title. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | Yes | Max evidence items requested for this page |
| total | Yes | Evidence items matching this query, from committees-api's totalResults (for evidence_type='both', the oral count plus the written count) |
| offset | Yes | Number of evidence items skipped before this page |
| evidence | No | Evidence items in this page. Titles are capped per max_title_chars; witness lists are capped at 10 per item. |
| has_more | Yes | True if evidence exists beyond this page (offset + returned < total). Re-call with offset=offset+returned to fetch the next page. |
| returned | Yes | Number of evidence items actually returned in this call |
| committee_id | Yes | Committee ID this page belongs to |
| evidence_type | Yes | Evidence type filter applied to this query |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint, but the description adds substantial behavioral detail beyond them: one-page default of 20, source ordering of oral-then-written evidence, title and witness caps, null-witness semantics, and the upstream-before-pagination filter behavior. This is exactly the context an agent needs to interpret pagination and output correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the use case and then proceeds through pagination, ordering, formatting, and workflow in a logical sequence. It is dense but every sentence carries operational value; the only slight cost is that several distinct concerns are packed into one block without paragraph breaks.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an 8-parameter tool with an output schema and rich annotations, the description covers the remaining gaps: pagination mechanics (offset=offset+returned while has_more is true), source ordering, witness rendering, and how to obtain committee_business_id. Nothing needed to call it correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning beyond the schema: evidence_type='both' ordering (all oral first, then written, each newest first), max_title_chars context-blow-up rationale, and witness-list capping. It does not re-explain every parameter (e.g., date range semantics are left largely to the schema), but it compensates well for the most consequential parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('retrieving committee evidence') and scopes it to identified inquiries. It is clearly distinguishable from sibling tools like committees_search_businesses and committees_search_committees, which it references as upstream sources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it ('USE THIS TOOL WHEN retrieving committee evidence, especially for an identified inquiry') and names the alternative workflow: first call committees_search_businesses and pass its exact committee_business_id. It also tells the agent where committee_id comes from.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_promptARead-onlyIdempotentInspect
Get a prompt by name with optional arguments.
Returns the rendered prompt as JSON with a messages array. Arguments should be provided as a dict mapping argument names to values.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name of the prompt to get | |
| arguments | No | Optional arguments for the prompt |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations indicate readOnlyHint, idempotentHint, and non-destructive behavior, which match the description's 'get' action. The description does not mention side effects, but the annotations cover this. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, using two short sentences to convey the purpose and parameter format. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides enough context for retrieval, including the return format (rendered JSON with messages array). The output schema exists and covers the response, so no further detail is required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters are fully described: 'name' as the prompt identifier and 'arguments' as an optional mapping. The schema already covers this, and the description reinforces the meaning with no ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool retrieves a prompt by name with optional arguments, distinguishing it from sibling tools like list_prompts which list available prompts. The verb 'get' and resource 'prompt' are explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when a specific prompt is needed, and the sibling list_prompts provides the alternative for listing. Though not explicit, the context is sufficient for an agent to decide when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hmrc_check_mtd_statusCheck MTD VAT StatusARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a 9-digit VAT Registration Number and need that business's Making Tax Digital VAT mandate status.
Returns whether the business is mandated for MTD, effective date, and trading name.
Connects to the HMRC sandbox by default. Set HMRC_API_BASE to 'https://api.service.hmrc.gov.uk' for production. Requires HMRC_CLIENT_ID + HMRC_CLIENT_SECRET environment variables (OAuth 2.0). Raises if credentials are not configured — do not infer status.
| Name | Required | Description | Default |
|---|---|---|---|
| vrn | Yes | VAT Registration Number: 9 digits, e.g. '123456789'. GB prefix accepted and stripped automatically. |
Output Schema
| Name | Required | Description |
|---|---|---|
| vrn | Yes | VAT Registration Number queried |
| mandated | Yes | Whether this business is mandated for MTD VAT |
| trading_name | No | Registered trading name if available |
| effective_date | No | Date from which MTD obligation applies |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as readOnly and idempotent, and the description adds valuable behavioral context: default sandbox connection, production override via HMRC_API_BASE, required OAuth credentials, and that it raises if credentials are missing. This goes beyond the structured fields without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the core purpose, followed by return details and environment notes. Every sentence provides value, though the environment configuration section could be trimmed without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the description covers the main use case, return fields, environment defaults, and error behavior. The presence of an output schema further reduces the need to explain return format, making this complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully describes the only parameter (vrn) with format and example, and the description does not add new parameter information. With schema coverage at 100%, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'USE THIS TOOL WHEN you have a 9-digit VAT Registration Number and need that business's Making Tax Digital VAT mandate status.' It clearly explains the return value (mandated status, effective date, trading name) and distinguishes from other HMRC tools like hmrc_get_vat_rate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an explicit trigger: 'USE THIS TOOL WHEN you have a 9-digit VAT Registration Number and need that business's Making Tax Digital VAT mandate status.' It also gives environment setup and warns against inferring status without credentials, though it does not name alternative tools for when-not-to-use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hmrc_get_manual_pageRead HMRC Internal Manual PageARead-onlyIdempotentInspect
USE THIS TOOL WHEN a cited HMRC internal-manual page must be read.
Returns bounded source-order text, canonical URL, manual reference, source metadata, and retrieval provenance. AFTER calling, cite or analyse only returned text; if retrieval fails, do not infer the page's contents. Source: the allowlisted official GOV.UK HMRC internal-manual page.
| Name | Required | Description | Default |
|---|---|---|---|
| max_chars | No | Maximum main-text characters to return (500–20000). Truncation is explicitly reported. | |
| reference | No | Manual page reference, e.g. 'EIM00500'. Required with manual_family when manual_url is omitted. | |
| manual_url | No | Canonical HTTPS GOV.UK HMRC internal-manual page URL. Provide this OR manual_family plus reference. | |
| manual_family | No | GOV.UK manual-family slug, e.g. 'employment-income-manual'. Required with reference when manual_url is omitted. |
Output Schema
| Name | Required | Description |
|---|---|---|
| title | Yes | Page heading supplied by GOV.UK |
| content | Yes | Source-order main page text, bounded by max_chars; never an LLM summary |
| updated | No | Source page update date where GOV.UK supplied one |
| reference | Yes | Manual page reference from the canonical GOV.UK path, e.g. eim00500 |
| breadcrumbs | No | Source-supplied GOV.UK breadcrumb labels, in display order |
| retrieved_at | Yes | UTC timestamp when this official GOV.UK page was retrieved |
| canonical_url | Yes | Final allowlisted GOV.UK URL retrieved for this manual page |
| manual_family | Yes | GOV.UK manual-family slug, e.g. employment-income-manual |
| original_length | Yes | Main-text character length before any truncation |
| content_truncated | Yes | True when content was cut to max_chars |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and open-world, so the safety profile is covered. The description adds value beyond them: bounded source-order output, reported truncation, returned provenance/metadata, and an explicit failure-handling rule against inferring content. Return-format detail is partially redundant with the existing output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The trigger condition is front-loaded in the first sentence and the total length is short. The source-attribution line is slightly redundant with the title, but it earns its place as an allowlist/trust signal for an open-world fetch.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a full output schema and complete annotations, the description supplies the remaining essentials: read-only fetch semantics, truncation behavior, provenance return, and the do-not-infer-on-failure rule. The only gap is not telling the agent where to obtain a reference or family slug when it has none.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters (including the manual_url OR family+reference alternative and the 500–20000 max_chars bound) are already documented in the schema. The description mentions 'bounded' text and truncation reporting but adds no syntax or selection guidance beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (read) and a specific resource (a cited HMRC internal-manual page), and the 'cited ... must be read' framing implicitly separates it from the search tools in the sibling list. It does not, however, name a sibling such as hmrc_search_guidance or legislation_get_section to make the boundary explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'USE THIS TOOL WHEN a cited HMRC internal-manual page must be read' gives a clear triggering condition, and 'if retrieval fails, do not infer the page's contents' supplies a useful negative rule. Missing is the prerequisite path: when the agent only has a topic, it should search for a reference first, and no alternative is named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hmrc_get_vat_rateGet VAT Rate for CommodityARead-onlyIdempotentInspect
USE THIS TOOL WHEN you know the UK VAT category name for a good or service and want its VAT treatment.
Exact named-category lookup, not a free-text VAT classifier or tax advice. The query must equal a category name, ignoring only case, spacing, hyphens and apostrophe style. Extra qualifying words are never discarded: 'pet food' is its own category, and 'baby food' is not 'food'.
A match returns rate (standard, reduced, zero or exempt),
rate_percentage (None for exempt), conditions in notes, the GOV.UK
source_url, and that entry's verified_on date.
An unresolved query returns no rate: matched_category, rate,
rate_percentage and verified_on are all null, never a default.
Its notes list the category names. AFTER an unresolved result, retry
with a listed name or call hmrc_search_guidance.
| Name | Required | Description | Default |
|---|---|---|---|
| commodity_code | Yes | Commodity code or plain-English description. E.g. 'food', 'domestic fuel', 'software', 'financial services', 'new build residential' |
Output Schema
| Name | Required | Description |
|---|---|---|
| rate | No | VAT rate category, or None when no specific category was confidently matched. None here is NOT a stand-in for any real rate — it means the lookup did not resolve, not that the item is outside VAT's scope. |
| notes | No | Any additional notes or conditions on this rate |
| source_url | Yes | GOV.UK/HMRC guidance page backing the matched entry; for an unresolved query, the general VAT rates page to consult instead |
| verified_on | No | Date the matched entry was last checked against GOV.UK/HMRC guidance. None for an unresolved query, since no entry was matched. A data-currency signal only — see `effective_from` for the rate's own legal commencement date, when known. |
| commodity_code | Yes | Commodity code or description queried |
| effective_from | No | Date the represented VAT treatment is known, on researched evidence, to have taken legal effect. None when no such commencement date has been established for this entry — that is common and does NOT imply the rate is new, uncertain, or unmatched. For data currency (when this entry was last checked against GOV.UK/HMRC guidance) see `verified_on` instead — the two are deliberately independent. |
| rate_percentage | No | Rate charged on a taxable supply: 20.0 (standard), 5.0 (reduced), 0.0 (zero). None for an exempt supply, which is not taxed at any rate (exempt is not the same as 0%), and None when `rate` is None. |
| matched_category | No | The static lookup table category the query exactly named (e.g. 'hot food'), or None when the query is not a category name. `rate`/`rate_percentage` are None whenever this is None — see `notes`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already mark the tool read-only, idempotent, and non-destructive; the description adds important behavioral details such as exact-match normalization, the rule that extra qualifying words are not discarded, the null response for unresolved queries, and the fact that notes list category names. This goes well beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the triggering condition and is generally dense and efficient. A few details about return fields overlap with what an output schema would likely provide, but every section contributes actionable guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only, idempotent lookup tool, the description covers when to use it, exact matching semantics, success and failure output shapes, and a retry/alternative path. Nothing essential is missing for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description materially enhances the single parameter by clarifying it must exactly equal a category name, not free text, and by giving normalization rules and explicit examples. It also explains what happens when the parameter does not resolve to a category.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the exact purpose: a named-category VAT lookup, and explicitly contrasts it with a free-text classifier. It is specific about the resource and behavior, and the sibling tools like hmrc_search_guidance are clearly distinct.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It begins with 'USE THIS TOOL WHEN you know the UK VAT category name', gives explicit negative guidance ('not a free-text VAT classifier or tax advice'), and names hmrc_search_guidance as the follow-up alternative after an unresolved result. This is model-level routing guidance, not just a vague hint.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hmrc_search_guidanceSearch HMRC GuidanceARead-onlyIdempotentInspect
USE THIS TOOL WHEN discovering HMRC GOV.UK guidance on a topic.
Returns official-search titles, URLs, descriptions, and published dates; descriptions do not establish the contents of a cited page. AFTER calling, use hmrc_get_manual_page when a result is an HMRC internal-manual URL. Source: GOV.UK's HMRC-filtered content search API.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum guidance results to return (1–25). Passed to the GOV.UK search count param. | |
| query | Yes | Search query for HMRC guidance, e.g. 'VAT digital services', 'R&D tax relief SME' |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | Yes | The search query that was run |
| total | Yes | Number of guidance documents returned in this call |
| results | No | Matching HMRC guidance pages. Each entry's `summary` is capped per the max_summary_chars input parameter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world, non-destructive behavior. The description adds real value beyond that: it names the underlying source API and warns that result descriptions 'do not establish the contents of a cited page', which prevents the agent from treating snippets as authoritative. It stops short of noting rate limits or result-ranking behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded trigger sentence followed by return shape, caveat, and next-step routing — no filler. The enumeration of returned fields partially duplicates the output schema, which is the only small inefficiency.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still supplies the interpretive caveat about snippet reliability and the cross-tool handoff that no structured field carries. An agent has everything needed to call it correctly and interpret the results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% — both 'query' and 'limit' are fully documented in the input schema, including bounds and examples. The description adds no parameter-level detail (e.g. query syntax or search-operator support), so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb + resource + source ('discovering HMRC GOV.UK guidance on a topic', 'GOV.UK's HMRC-filtered content search API'), which is distinct from legislation_search or parliament_search_hansard siblings. The mention of hmrc_get_manual_page as a follow-up further delimits its role in the HMRC tool cluster.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Opens with an explicit trigger ('USE THIS TOOL WHEN discovering HMRC GOV.UK guidance on a topic') and gives a conditional next step ('use hmrc_get_manual_page when a result is an HMRC internal-manual URL'). It lacks an explicit negative case (e.g. 'do not use for legislation text'), but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
judgment_get_headerGet Judgment HeaderARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a judgment slug and need metadata (parties, judges, neutral citation, court, dates).
Call case_law_search FIRST to get the slug. AFTER calling, use judgment_get_index to discover paragraphs, then judgment_get_paragraph to read specific ones. Authoritative source for UK judgment metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Judgment slug, e.g. 'uksc/2024/12' or 'ewca/civ/2023/450' |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and non-destructive. Description adds useful context about being the authoritative source for UK judgment metadata, and the workflow context. No contradiction or hidden behavior disclosed, but adds value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with 'USE THIS TOOL WHEN', each sentence earns its place: usage trigger, workflow, authority. No redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a single parameter, full schema coverage, output schema present, and strong annotations, the description covers the workflow, tool distinction, and metadata scope. Complete for a simple read-only tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a clear description and examples for the 'slug' parameter. The description adds the context of needing a slug from case_law_search but doesn't provide new parameter-level semantics beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: 'get metadata' for a judgment header, with explicit list of metadata types (parties, judges, neutral citation, court, dates). Clearly distinguishes from siblings judgment_get_index and judgment_get_paragraph by focusing on header metadata vs paragraphs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'when you have a judgment slug and need metadata'. Provides workflow: call case_law_search first, then use judgment_get_index/paragraph. Naming alternatives and prerequisite tools makes usage context unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
judgment_get_indexGet Judgment Paragraph IndexARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a judgment slug and want the paragraph navigation index (eId + preview line for every paragraph).
Call case_law_search FIRST to get the slug. AFTER calling, pass an eId from the returned list into judgment_get_paragraph to read that paragraph's full text, or use case_law_grep_judgment for content search across all paragraphs.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Judgment slug, e.g. 'uksc/2024/12' |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false, so safety is covered. The description adds that the tool returns an eId and preview line for every paragraph, which is useful behavioral context beyond the annotations. It does not mention error handling or pagination, but the output schema likely covers return structure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the usage trigger. Every sentence provides necessary information: what it does, when to use it, and how it fits with other tools. No wasted words or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with rich annotations and an output schema, the description fully covers purpose, usage, and relationships to related tools. It even includes the output format (eId + preview line), making it complete for an agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully describes the single 'slug' parameter with an example. The description adds value by explaining how to obtain the slug ('Call case_law_search FIRST to get the slug'), which is not in the schema. Since schema coverage is 100%, the baseline is 3, and the workflow hint lifts it to 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'get the paragraph navigation index (eId + preview line for every paragraph)' with a specific verb and resource. It clearly distinguishes from siblings by mentioning judgment_get_paragraph for full text and case_law_grep_judgment for content search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'USE THIS TOOL WHEN you have a judgment slug and want the paragraph navigation index', and provides a clear workflow: call case_law_search first to get the slug, then pass an eId to judgment_get_paragraph or use case_law_grep_judgment. This gives both when-to-use and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
judgment_get_paragraphGet Judgment ParagraphARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a judgment slug + LegalDocML eId and want that paragraph's full text.
Call judgment_get_index FIRST to discover available eIds (or use case_law_grep_judgment to locate paragraphs by content). Returns the paragraph XML content (400–1,700 tokens typical).
| Name | Required | Description | Default |
|---|---|---|---|
| eId | Yes | Paragraph eId from judgment_get_index, e.g. 'para_12'. Numeric strings like '12' are accepted and normalized to 'para_12'. | |
| slug | Yes | Judgment slug, e.g. 'uksc/2024/12' |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the description adds value by stating it returns paragraph XML content and a typical token range. It could mention error handling or what happens if eId is invalid, but the key behavior is covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences with no fluff. The purpose is front-loaded, and each sentence adds crucial navigational or return-value information. Perfectly sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and full annotations, the description still manages to provide essential workflow (call judgment_get_index first) and alternative search method. It is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and includes a detailed eId description with normalization rule. The description itself doesn't add new parameter details beyond referencing them, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool gets a judgment paragraph's full text given a slug and eId. It distinguishes from siblings by explicitly routing users to judgment_get_index for eIds and case_law_grep_judgment for content-based search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use criteria ('when you have a judgment slug + LegalDocML eId and want that paragraph's full text') and names alternatives (judgment_get_index, case_law_grep_judgment). This is exemplary guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
legislation_get_sectionGet Legislation SectionARead-onlyIdempotentInspect
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.
Returns the provision's own text and heading, never a neighbouring Part/Chapter. Also returns extent, in-force/prospective data, and truncation metadata. Pass the bare number: the tool handles Act sections and SI regulations/articles. A missing provision raises not_found rather than returning a plausible neighbouring node.
AFTER calling, check extent before relying on the provision and
inspect content_truncated for long text. Call legislation_get_toc to
discover valid numbers, or read_resource with a legislation:// URI
when raw CLML XML is required.
Source: legislation.gov.uk CLML, with an explicitly marked public-HTML fallback only when CLML is unavailable.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Legislation type code: 'ukpga' (Acts), 'uksi' (SIs), 'asp' (Scottish Acts), 'nia' (NI Acts). Use the value from legislation_search results. | |
| year | Yes | Year of enactment | |
| number | Yes | Chapter or SI number | |
| section | Yes | 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. | |
| max_chars | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| title | Yes | Section title or heading |
| extent | No | Territorial extent: list of 'England', 'Wales', 'Scotland', 'Northern Ireland'. Empty list means unknown — do not assume full UK extent. |
| content | Yes | Plain text content of the section, possibly truncated per max_chars. Check content_truncated and original_length for full-text information. |
| in_force | No | False if the section is explicitly marked repealed in CLML. True only when an InForce element is present in the section body (rare). Null for most sections — the data.xml endpoint does not carry a per-section current in-force boolean; null does not mean repealed. |
| warnings | No | Non-fatal retrieval or parsing warnings the caller should disclose where relevant. |
| prospective | No | True if this section has not yet come into force; None if unknown |
| version_date | No | Date of the version retrieved |
| source_format | No | Source parsed for this response. html_fallback means CLML XML was unavailable and text was parsed from the public HTML page. |
| section_number | Yes | Section number, e.g. '47', '12A', 'Schedule 2' |
| original_length | No | Original plain-text length in characters before any truncation |
| content_truncated | No | True if content was cut to fit max_chars |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations (which only declare read-only/idempotent/open-world). It discloses that only the provision's own text is returned (never a neighbouring Part/Chapter), that a missing provision raises not_found instead of returning a plausible neighbour, the CLML source with an explicitly marked public-HTML fallback, and post-call checks on extent and content_truncated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The trigger condition is front-loaded in the first clause, followed by behavioural guarantees, then post-call guidance, then alternatives. Every sentence carries distinct information with no restatement of the name or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter read tool with an output schema and full annotation coverage, this covers the remaining gaps: numbering conventions, missing-provision behaviour, source provenance, and a truncation workflow. Nothing an agent needs to call it correctly or interpret the response is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already explains 'type', 'year', 'number', and the bare-number rule for 'section'. The description reinforces the bare-number convention and points to content_truncated, but adds little parameter meaning the schema does not already carry.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('want the parsed text of a specific section, regulation, or article') and scopes it to a known Act/SI. It explicitly contrasts with legislation_get_toc and read_resource, so an agent can pick it out of a crowded sibling list without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Opens with an explicit trigger ('USE THIS TOOL WHEN you have a known Act / SI'), and gives alternatives with their selection conditions: legislation_get_toc to discover valid numbers, read_resource for raw CLML XML. Preconditions and fallbacks are all named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
legislation_get_tocGet Legislation Table of ContentsARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a known Act / SI and want the structural table of contents (parts, chapters, individual sections/regulations/articles).
Returns XML ids and titles in document order, including Parts, chapters, crossheadings, and provisions; a rare untitled provision is retained as its bare id. Results are paginated with offset/limit.
AFTER calling, pass a provision's bare number (for example 47, not
section-47) to legislation_get_section. Check has_more and
total_items for large statutes. Use read_resource with the
legislation:// toc URI for the full raw listing.
Source: legislation.gov.uk CLML table of contents.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Legislation type code: 'ukpga' (Acts), 'uksi' (SIs), 'asp' (Scottish Acts), 'nia' (NI Acts). Use the value from legislation_search results. | |
| year | Yes | Year of enactment | |
| limit | No | 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. | |
| number | Yes | Chapter or SI number | |
| offset | No | 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). |
Output Schema
| Name | Required | Description |
|---|---|---|
| type | Yes | Legislation type code echoed from the request |
| year | Yes | Year of enactment echoed from the request |
| items | No | TOC entries in XML document order, formatted as '<id>: <title>', e.g. 'section-47: Definitions'. When calling legislation_get_section pass only the numeric part ('47', not 'section-47'). |
| limit | Yes | Page size applied after offset |
| number | Yes | Chapter or SI number echoed from the request |
| offset | Yes | Offset applied to the full TOC item list |
| has_more | Yes | True if more items remain beyond offset+returned |
| returned | Yes | Number of items in this response |
| total_items | Yes | Total structural items parsed from the XML, before offset/limit. Compare to `returned` and `has_more` to decide whether to paginate. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses that results are XML ids and titles in document order, includes structural elements and provisions, retains rare untitled provisions as bare ids, and is paginated with offset/limit. It also tells the agent to inspect has_more and total_items for large statutes, which is useful behavioral guidance for consuming the result.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the primary usage condition, then follows with return details, downstream guidance, and an alternative resource. Every sentence supports correct selection or invocation, and the source note adds useful provenance without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, paginated TOC tool with full schema coverage, annotations, and an output schema, the description provides enough context to select it, understand the shape of results, handle pagination, and route to legislation_get_section or read_resource afterward.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents type, year, number, limit, and offset, including examples and pagination behavior. The description reinforces pagination and downstream use of bare provision numbers, but adds little parameter-specific meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: getting the structural table of contents for a known Act/SI, including parts, chapters, sections, regulations, and articles. It clearly distinguishes this from legislation_get_section by explaining that the TOC is used first and its bare provision number is then passed to the section tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger: use this when you already have a known Act/SI and want the structural listing. It also routes follow-up work to legislation_get_section and points to read_resource for the full raw listing, covering both primary usage and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
legislation_searchSearch UK LegislationARead-onlyIdempotentInspect
USE THIS TOOL WHEN searching UK Acts and Statutory Instruments by title, phrase, or full-text.
Returns ranked results: title, type, year, number, legislation.gov.uk URL, and next_steps hints (toc URI, section template). AFTER calling, chain to legislation_get_toc then legislation_get_section for structural drill-in.
Filter discipline: type and year are exact-match. Use only when you
already know the value. For currency-driven searches, query by phrase
and read the returned year; guessing an exact year can zero results.
For broader concept queries across content, set fulltext=True. If the
default title route receives a typed legislation.gov.uk WAF/non-XML
failure, the tool automatically tries that documented full-text route
once and marks search_mode="fulltext_fallback"; its broader relevance
semantics must not be treated as a title-ranked result. Render-pending
and ordinary HTTP failures do not trigger this fallback.
Source: legislation.gov.uk Atom search feed, with an explicit fallback marker when the alternative official full-text route supplied results.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | 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 | No | 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. | |
| limit | No | Maximum results to return (1–50). Passed to the upstream results-count param. | |
| query | Yes | Search query, e.g. 'Housing Act 1988' or 'data protection personal data' | |
| fulltext | No | 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). |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | Yes | Total number of matches |
| results | Yes | Matching legislation items |
| search_mode | No | Route that produced these results. fulltext_fallback means the title route was unavailable because legislation.gov.uk returned a typed WAF/non-XML failure, so the server retried once using the documented full-text route; relevance may therefore be broader than title search. |
| fallback_reason | No | Typed upstream reason that triggered the automatic full-text fallback, or null when the requested route completed normally. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description goes well beyond them: the automatic full-text fallback on WAF/non-XML failures, the search_mode="fulltext_fallback" marker, the warning that fallback relevance is not title-ranked, and the explicit statement that render-pending/ordinary HTTP errors do not trigger it. That is precisely the kind of hidden behavior an agent would otherwise misread.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the trigger condition and the chaining instruction, which is the right order. It runs long and the 'Filter discipline' passage restates what the type/year schema descriptions already say, so a few sentences could be trimmed, but nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description names the returned fields and next_steps hints so the agent knows what it can chain on, and it fully documents the fallback mode. Nothing needed to call or interpret the result is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema carries the parameter definitions; the description mostly reinforces them (exact-match type/year, fulltext semantics). It does add a workflow-level insight the schema lacks – that guessing a year can zero the result set and you should read the year off results instead – but much of the filter discussion duplicates schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('searching UK Acts and Statutory Instruments') plus the search modes (title, phrase, full-text), which clearly separates it from structural siblings like legislation_get_toc and legislation_get_section. An agent can tell exactly what to reach it for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Opens with an explicit 'USE THIS TOOL WHEN' condition and adds an 'AFTER calling, chain to legislation_get_toc then legislation_get_section' routing rule. It also gives negative guidance for the filters (only use type/year when you already know the value; omit year and read it from results), which is real when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_promptsARead-onlyIdempotentInspect
List all available prompts.
Returns JSON with prompt metadata including name, description, and optional arguments.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnly, idempotent, and non-destructive behavior. The description adds that the result is JSON metadata, which is useful context. No contradictions are present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is brief, direct, and free of unnecessary detail. Two sentences convey the action and the return format efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple no-argument list operation, the description is sufficiently complete. It names the return type and the key fields, though it does not specify ordering or pagination, which are not critical here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes no parameters, so the parameter semantics are trivially satisfied. The description does not need to elaborate on inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to list all prompts and return their metadata. It is distinguishable from the sibling get_prompt tool, which retrieves a specific prompt.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage is implied by 'List all prompts', but there is no explicit guidance about when to prefer this over get_prompt or other listing tools. It is adequate but not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_resourcesARead-onlyIdempotentInspect
List all available resources and resource templates.
Returns JSON with resource metadata. Static resources have a 'uri' field, while templates have a 'uri_template' field with placeholders like {name}.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, covering safety and idempotency. The description adds value by explaining the output structure: 'Returns JSON with resource metadata' and the distinction between 'uri' and 'uri_template' fields, which is useful behavioral context beyond what annotations state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero filler. The first sentence states the core purpose, and the second adds the crucial detail about output fields. It is front-loaded and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and an output schema present, the description is complete for an agent to understand when and how to call this tool. It explains what it lists and the format of the output. The presence of an output schema means the description does not need to detail return values further, but it still gives a helpful preview.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline for this dimension is 4. The description does not need to explain parameters because there are none, and the schema confirms an empty object. No additional parameter semantics are required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and target: 'List all available resources and resource templates.' It clearly distinguishes static resources (with 'uri') from templates (with 'uri_template'), which helps differentiate from siblings like read_resource that fetch a specific resource. The verb 'List' and the resource type are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies this tool is for enumeration, but it does not explicitly state when to use it over alternatives or mention any exclusion criteria. It does not say, for example, 'Use this to discover resources before calling read_resource.' While the purpose is clear, the guidance is implicit rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_find_memberFind Member of ParliamentARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a member's name and need their integer member_id.
Returns all members matching the name query, each with the integer id,
party, constituency, house, and current-sitting status. Disambiguates
common-name matches (e.g. "Lord Smith" returns multiple peers).
CALL THIS BEFORE any tool that filters by member_id — including parliament_get_debate_contributions, parliament_member_debates, and parliament_member_interests. Name → ID first; ID-based filtering second. Skipping this step and text-searching by name returns unrelated results (see parliament_search_hansard's anti-bypass note for the Pannick case).
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name or partial name, e.g. 'Starmer', 'Baroness Hale' |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | Yes | The name that was searched |
| total | Yes | Number of members matching the query |
| members | No | Matching members. Use the integer `id` field from any member to call parliament_member_debates or parliament_member_interests. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, open-world, idempotent, and non-destructive behavior. The description adds useful behavioral context beyond annotations: it says all matching members are returned with specific fields, that common-name matches are disambiguated, and that skipping it produces unrelated results. It does not mention rate limits or auth needs, but those are less relevant for this read-only lookup.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the primary trigger in the first sentence, then returns, then ordering rules. It is compact and every sentence serves selection or invocation; no wasted preamble.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the annotations covering safety and the presence of an output schema, the description supplies everything needed: when to use it, what it returns, why disambiguation matters, and how it fits before ID-filtering sibling tools. No critical selection or invocation detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the parameter already has an example. The description adds meaning beyond the schema by clarifying that the name query may match multiple members, that common names need disambiguation, and that the result is an integer ID for downstream filtering.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: find a Member of Parliament by name and return their integer member_id. It distinguishes itself from sibling tools that filter by member_id and from text-search alternatives, so an agent can select it without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger ('USE THIS TOOL WHEN you have a member's name and need their integer member_id') and an explicit ordering rule ('CALL THIS BEFORE any tool that filters by member_id'), naming three downstream tools. It also warns what happens if skipped, which is strong when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_get_debate_contributionsGet Contributions In A DebateARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a debate_ext_id and want verbatim contributions, optionally filtered to one member.
Canonical path for "everything a member said in this debate" regardless of vocabulary — text-search tools (parliament_member_debates, parliament_search_hansard) filter by contribution TEXT, dropping members who spoke without using your phrase verbatim. This tool filters by MemberId on the debate's Items list, so vocabulary doesn't matter.
Typical chain: parliament_find_member(name) → member_id, then parliament_search_hansard or parliament_lookup_by_column → debate_ext_id, then this tool. The parliament module's instructions describe the full composition pattern.
Without member_id, returns every contribution (~100-200 for a long debate).
If the wire returns no contributions for a member you expect to have spoken, report the empty result honestly — do NOT reconstruct quotes from training data. Authoritative source for member contributions.
| Name | Required | Description | Default |
|---|---|---|---|
| member_id | No | 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). | |
| debate_ext_id | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | No | Page size requested |
| topic | No | Topic phrase filter applied, if any |
| total | Yes | Number of contributions returned in this call |
| offset | No | Skip applied to this page |
| has_more | No | True if a full page was returned (more may exist) |
| member_id | Yes | Parliament Members API member ID |
| contributions | No | Hansard contributions for the member. Each `text` field is capped at 3000 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent safety, so the description is free to add what they cannot: the vocabulary-independence of the MemberId filter, the expected result volume (~100-200 items for a long debate), and an integrity instruction to report empty results honestly rather than reconstruct quotes from training data. That is substantive behavioral context beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The trigger condition and sibling differentiation are front-loaded, which is exactly right for a selection decision. It runs a little long with some restatement of the member_id filtering point across the opening and closing paragraphs, but each paragraph carries a distinct idea.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return-value explanation is unnecessary, and the description still supplies the chaining path, volume expectations, and fallback behavior. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already fully documented (member_id semantics, debate_ext_id chaining, defaults, volume). The description restates the member_id filtering behavior rather than adding new syntax or format detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('get') and resource ('contributions in a debate') and explicitly distinguishes itself from siblings parliament_member_debates and parliament_search_hansard by explaining it filters on MemberId rather than contribution text. An agent can select it correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger ('USE THIS TOOL WHEN you have a debate_ext_id'), names the alternatives and why they are worse for this job, and lays out the canonical composition chain (find_member → search_hansard/lookup_by_column → this tool). When-not guidance is present via the text-filter caveat.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_get_debate_divisionsGet Divisions Held In A DebateARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a debate_ext_id and want the divisions (formal votes) held within it.
Most debates contain no divisions — Business of the House sittings, statements, urgent questions, debates without a vote. A populated list typically appears around bill stages, motions, and contested amendments. Empty list is the honest result, not a failure mode.
Each returned division carries TWO IDs:
id— Hansard-side reference. Useful for cross-referencing in Hansard.votes_id— Lords/Commons Votes API ID (cross-resolved by date+number). AFTER calling, passvotes_idasdivision_idinto votes_get_division for the full member-by-member voting record.
The two upstreams use distinct ID-spaces (Hansard Number=3 might be
Votes-API divisionId=3392). The cross-resolve runs once per (date, house)
group — typically one extra HTTP per debate. votes_id is None when the
cross-resolve found no match.
| Name | Required | Description | Default |
|---|---|---|---|
| debate_ext_id | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| divisions | No | Divisions held in this debate, in chronological order. Empty when no divisions occurred. Each element's `id` chains to votes_get_division. |
| debate_ext_id | Yes | Echo of the input debate GUID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations indicating safe read-only behavior, the description adds valuable behavioral details: empty list is an honest result, cross-resolve happens once per (date, house) group with an extra HTTP, votes_id can be None, and the two ID spaces are distinct. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the usage condition and contains well-structured bullet points for the two IDs. It is longer than minimal but every sentence adds meaningful context; no waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema, the description focuses on critical nuances: the possibility of an empty list, the meaning of votes_id, the cross-resolve behavior, and the None case. This provides a complete mental model for correct invocation and interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single parameter debate_ext_id, which already includes a detailed description with chaining sources. The tool description itself adds no additional parameter semantics beyond the usage line, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves divisions (formal votes) held within a debate. It distinguishes itself from siblings like parliament_get_debate_contributions and votes_get_division by focusing on the debate-level divisions list and explicitly referencing the votes_id linkage.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'USE THIS TOOL WHEN you have a debate_ext_id and want the divisions'. Also provides when-not-to-use context (most debates have no divisions) and directs users to votes_get_division with the votes_id, giving clear alternative and follow-up guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_lookup_by_columnResolve A Hansard Column CitationARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have an OSCOLA-style Hansard citation (column + volume + house) and need the debate.
Example input: 'HL Deb 14 Oct 2025, vol 849, col 200'. AFTER calling, read the contribution at the cited column via read_resource(uri="hansard://debate/{debate_ext_id}/header") — or, equivalently, call parliament_get_debate_contributions(debate_ext_id) for the full list as a structured tool response.
Each match carries:
contribution_count— real contribution count from the debate's Itemssource/source_code— citation finality (1=Rolling, 2=Daily, 3=BoundVolume, 4=Historic). Resolution is NOT gated on publication state.
Empty matches typically means the volume_number is wrong (opposing
counsel sometimes cites running-volume rather than bound-volume) or the
column is in a Written Statement (use the 'W'-suffixed column as-is).
It does NOT mean the citation is fabricated — surface the failure.
Authoritative source for OSCOLA Hansard column resolution.
| Name | Required | Description | Default |
|---|---|---|---|
| house | No | Restrict to one House. Default 'both' searches across both Houses. | both |
| column_number | Yes | 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. | |
| volume_number | Yes | 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). |
Output Schema
| Name | Required | Description |
|---|---|---|
| house | Yes | House filter applied. |
| matches | No | Debate sections containing the cited column, in upstream relevance order. Each element's `debate_ext_id` chains to hansard://debate/{debate_ext_id}/header, and carries `source`/`source_code` for the citation's publication state. Resolution is NOT gated on publication state — Daily Part, Bound Volume, and Historic columns all resolve. Empty matches typically mean the volume number is wrong (running-volume vs bound-volume number), the column is a Written Answer/Statement needing its suffix (e.g. '1162W'), or a very recent column not yet indexed upstream. |
| column_number | Yes | Echo of the requested column number. |
| total_results | Yes | Number of debate matches found. |
| volume_number | Yes | Echo of the requested volume number. |
| unparsed_results | No | Upstream matches that could not be parsed and are omitted from `matches`. When greater than zero, `matches` is incomplete and `total_results` is larger than the number of matches returned. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/openWorld, but the description adds substantial context beyond them: the source_code finality scale, the fact that resolution is not gated on publication state, and the diagnostic meaning of empty matches. It stops short of explaining pagination or match ordering, but the behavioral picture is strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the trigger condition and example, then uses tight bullets for return fields and troubleshooting. It is longer than a minimal definition but nearly every line carries actionable information, with only minor redundancy against the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description still surfaces the most decision-relevant return fields (contribution_count, source_code) and the interpretation of empty results. Combined with the follow-up pointers, an agent has everything needed to call and act on this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above that by reinforcing the 'W'-suffixed column convention, the running-volume vs bound-volume trap, and the sitting-date-is-not-a-substitute constraint. It adds real interpretation on top of an already well-documented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('resolve a Hansard column citation' via OSCOLA column+volume+house) and complements the title by defining exact input shape. An agent can tell this apart from parliament_search_hansard, which is keyword search rather than citation resolution.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Opens with an explicit trigger ('USE THIS TOOL WHEN you have an OSCOLA-style Hansard citation'), gives a concrete example, and names follow-up alternatives (read_resource or parliament_get_debate_contributions). It also documents the failure mode for empty matches, which is unusually complete guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_member_debatesGet Member DebatesARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a member_id and want contributions where THAT member used a specific topic phrase verbatim (text-body search).
CALL parliament_find_member(name) FIRST to obtain the integer member_id.
This is a name-based text-body search — it matches contributions whose TEXT contains the topic phrase. A member who spoke in a debate but didn't use your phrase verbatim is filtered out. For verbatim retrieval of every contribution by a member in a known debate (regardless of vocabulary), use parliament_get_debate_contributions(debate_ext_id, member_id=...) instead.
Each contribution's text field is capped at 3000 characters.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum contributions to return. Default 20. | |
| topic | No | 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=...). | |
| offset | No | Number of contributions to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true. | |
| member_id | Yes | Parliament Members API integer ID. Obtain from parliament_find_member. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | No | Page size requested |
| topic | No | Topic phrase filter applied, if any |
| total | Yes | Number of contributions returned in this call |
| offset | No | Skip applied to this page |
| has_more | No | True if a full page was returned (more may exist) |
| member_id | Yes | Parliament Members API member ID |
| contributions | No | Hansard contributions for the member. Each `text` field is capped at 3000 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive), so the bar is lower, and the description adds genuine non-structured context: the verbatim text-body matching semantics, the 3000-char text cap, and the filtering consequence of missing tokens. It does not describe pagination behavior, though the schema's offset field partially covers that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the trigger condition, then prerequisites, then the key semantic caveat. Slightly redundant between the two verbatim-search explanations, but every sentence carries routing or behavioral weight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists and annotations cover safety, the description fills every remaining gap an agent needs: the prerequisite call, the text-matching semantics, the 3000-char cap, and the disambiguation from siblings. Nothing required to invoke correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description meaningfully augments the topic parameter by explaining what text is actually searched, what tokens to pass, and what not to pass ('not the bill's name'). This is additive semantic guidance beyond the schema's own prose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('contributions where THAT member used a topic phrase verbatim') and explicitly distinguishes itself from the closest siblings parliament_search_hansard and parliament_get_debate_contributions. An agent can route correctly without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit precondition ('WHEN you have a member_id'), a named prerequisite tool to call first (parliament_find_member), and a named alternative with the exact condition that selects it (parliament_get_debate_contributions for vocabulary-independent retrieval). This is textbook when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_member_interestsGet Member Financial InterestsARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a member_id and need their registered financial interests (donations, directorships, land, gifts).
CALL parliament_find_member(name) FIRST to obtain the integer member_id.
Returns ONE PAGE of interests (default 20, caller controls via limit). For prolific members (big donors, many directorships, extensive land holdings), re-call with offset=offset+returned while has_more is true to paginate. Description text is capped per max_description_chars; raise it for forensic provenance work that needs the full narrative.
This is the authoritative source for UK MP and peer financial-interest declarations (via the Members API). Web search returns stale snapshots.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | 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. | |
| offset | No | 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. | |
| category | No | 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. | |
| member_id | Yes | Parliament Members API integer ID. Get from parliament_find_member. | |
| max_description_chars | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | Yes | Max interests requested for this page |
| offset | Yes | Number of interests skipped before this page |
| category | No | Category filter applied to this query, or None for all categories |
| has_more | Yes | True if there may be more interests beyond this page. Re-call with offset=offset+returned to fetch the next page. |
| returned | Yes | Number of interests actually returned in this call |
| interests | No | The interests in this page. `description` text is capped per the max_description_chars input parameter. |
| member_id | Yes | Parliament Members API member ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond annotations (readOnlyHint, idempotentHint) by detailing pagination behavior (one page of 20, has_more flag), the hard upstream cap on limit (verified live), and the max_description_chars truncation behavior. It also notes that web search returns stale snapshots, adding value. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the key usage signal ('USE THIS TOOL WHEN'), then provides necessary operational detail in clearly separated paragraphs. Every sentence serves a purpose—no filler, tautology, or repetition of schema. It is long but information-dense and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is moderately complex with 5 parameters and pagination behavior, but the description fully covers when to use it, prerequisite steps, pagination, limits, and the authoritative nature of the data. An output schema exists, so return values needn't be detailed. This is complete for the agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% parameter coverage with rich descriptions, so the baseline is 3. The description adds practical semantics like how to paginate (offset=offset+returned while has_more is true) and when to raise max_description_chars for forensic work. This is additional guiding context beyond the schema, so a 4 is warranted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves registered financial interests for a given member_id, listing specific categories (donations, directorships, land, gifts). It distinguishes from siblings by positioning as the authoritative source for MP/peer financial-interest declarations, and explicitly instructs to call parliament_find_member first, which differentiates it from that lookup tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is explicitly conditioned: 'USE THIS TOOL WHEN you have a member_id and need their registered financial interests.' It provides a clear prerequisite (call parliament_find_member first), directs away from web search due to stale data, and gives pagination guidance for prolific members. This is excellent when-to-use and alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_policy_position_summaryHansard Policy Position Summary (deterministic facets)ARead-onlyIdempotentInspect
USE THIS TOOL WHEN you want debate-level corpus signals on a topic — by_house, by_year, by_section breakdowns — without reading every contribution.
Aggregates Hansard debate-level signals on a topic. Pure counts — no LLM, no editorial labels. Sweeps /search/Debates.json with pagination (up to max_debates_scanned), then aggregates by_house, by_section, by_year, by_month, and top_debates from debate metadata. Also captures the corpus-wide envelope counts (total_contributions, total_written_statements, total_divisions, etc.) from /search.json for cross-section scope.
AFTER calling, pick a debate from top_debates and pass its debate_ext_id into parliament_get_debate_contributions to drill into who said what.
Note on member-level facets: Hansard's search API exposes debate metadata, not per-contribution member identifiers, at the corpus level. by_party and top_contributors are therefore omitted from this deterministic summary. To see who spoke in a specific debate, read hansard://debate/{debate_ext_id}/header for an ordered contribution index, or call parliament_member_debates for one named member.
This is the authoritative source for UK Hansard corpus-level signals.
| Name | Required | Description | Default |
|---|---|---|---|
| house | No | Restrict to one House. Default 'both'. | both |
| topic | Yes | 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. | |
| to_date | No | End date (YYYY-MM-DD) | |
| from_date | No | Start date (YYYY-MM-DD) | |
| max_debates_scanned | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| house | Yes | House filter applied |
| topic | Yes | Phrase searched in Hansard |
| by_year | No | Counts of debates by sitting year, desc by year |
| to_date | No | End date filter applied |
| by_house | No | Counts of debates by house (Commons vs Lords) |
| by_party | No | Counts by party. ALWAYS EMPTY in this summary — Hansard's search API only exposes member identifiers at the per-debate level, not the corpus level. For party breakdown within one debate, read hansard://debate/{ext_id}/header. For one member's contributions across the corpus, use parliament_member_debates. |
| from_date | No | Start date filter applied |
| by_section | No | Counts of debates by Hansard section bucket (Chamber / Westminster Hall / Written Answers / Written Statements) |
| top_debates | No | Top 20 debates ranked by upstream relevance_rank, with debate_ext_id for hansard://debate/{debate_ext_id}/header drill-down. contribution_count is null in this preview shape (would require a secondary call per debate). |
| total_debates | Yes | Total distinct debates touching this topic (TotalDebates) |
| debates_scanned | Yes | Number of debates pulled from /search/Debates.json for the facet breakdown (≤ max_debates_scanned) |
| total_divisions | Yes | TotalDivisions upstream count. Non-zero → consider votes_search_divisions. |
| top_contributors | No | ALWAYS EMPTY in this summary — see by_party note. Use parliament_member_debates after picking a debate from top_debates. |
| by_month_recent_12 | No | Counts of debates by YYYY-MM for the most recent 12 months in the sample, desc by month |
| total_contributions | Yes | Total contributions in Hansard matching topic+filters (TotalContributions) |
| total_written_answers | Yes | TotalWrittenAnswers upstream count |
| total_written_statements | Yes | TotalWrittenStatements upstream count |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint, idempotentHint, openWorldHint, destructiveHint=false. The description adds behavior beyond that: it sweeps /search/Debates.json with pagination, states the hard cap semantics, discloses the rate limit ('1000 req/5min'), notes that by_party and top_contributors are deliberately omitted due to upstream limitations, and confirms 'no LLM, no editorial labels'. The omission disclosure is unusually valuable context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the WHEN clause; each sentence carries a distinct point (trigger, mechanics, follow-up, member-facet caveat, authority claim). The member-facet note is a bit long but earns its place by explaining an omission. Some repetition between the title and 'authoritative source' sentence, but overall tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
All key facets of the tool's behavior are covered for an agent: when to use it, what it aggregates, the sweep mechanism and cost, the follow-up path, and known limitations (missing member-level facets). With an output schema present, no return-value explanation is required, and nothing material is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all five parameters, including defaults, enums, and the rate-limit note in max_debates_scanned. The description briefly contrasts topic semantics with parliament_search_hansard.query (debate-level metadata matching vs body text), which is a small addition, but mostly repeats what the schema already says. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The title and body state a specific verb (aggregate) and resource (Hansard debate-level signals on a topic), and it explicitly differentiates itself from text-search siblings (parliament_search_hansard) by describing the facet-aggregation output (by_house, by_year, by_section). The mention of 'authoritative source for UK Hansard corpus-level signals' anchors the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The opening 'USE THIS TOOL WHEN...' clause states the trigger condition, and it names a clear follow-up ('pass debate_ext_id into parliament_get_debate_contributions') plus an alternative for member-level queries (hansard://debate/.../header or parliament_member_debates). It doesn't fully name what this tool is not for versus parliament_search_hansard, but the WHEN clause plus alternatives is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_search_hansardSearch Hansard DebatesARead-onlyIdempotentInspect
USE THIS TOOL WHEN searching Hansard by topic, bill title, or text phrase.
Returns source-backed contributions with citation-grade metadata: member_id, attributed_to, column_ref, debate_id, debate_ext_id, contribution_ext_id, and public URL. The independent corpus envelope is optional enrichment: if it cannot be retrieved after one bounded retry, contributions still return with enrichment_status="degraded" and an explicit warning; omitted corpus totals and previews must not be inferred. AFTER calling, drill into full content via read_resource(uri="hansard://debate/{debate_ext_id}/header") — or call parliament_get_debate_contributions(debate_ext_id) for the same content as a structured tool response.
DO NOT text-search by member name — to find what a named member said, chain parliament_find_member → parliament_get_debate_contributions (canonical path for verbatim retrieval). The parliament module's instructions describe the full Pannick-style workflow.
Pagination: limit + offset honour the upstream paginated endpoint. For breadth across a topic, see parliament_policy_position_summary.
Source: UK Parliament Hansard API. Contributions remain the authoritative retrieval result; envelope fields are source-backed only when complete.
| Name | Required | Description | Default |
|---|---|---|---|
| house | No | Restrict to one House. Default 'both' returns Commons + Lords contributions. | both |
| limit | No | Max contributions per call (1–100). Default 20. Paginate further with offset; total corpus size is in total_corpus on the response. | |
| query | Yes | 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. | |
| offset | No | Skip this many contributions before the page. Default 0. Re-call with offset=offset+returned to paginate; has_more flags whether more remain. | |
| to_date | No | End date (YYYY-MM-DD) | |
| from_date | No | Start date (YYYY-MM-DD) | |
| member_id | No | 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`. | |
| text_mode | No | '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}. | preview |
| contribution_type | No | 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. | Spoken |
Output Schema
| Name | Required | Description |
|---|---|---|
| house | No | House filter applied |
| limit | No | Page size requested |
| query | Yes | The phrase that was searched in Hansard |
| total | Yes | Number of contributions returned in this call |
| offset | No | Skip applied to this page (Hansard API: skip) |
| to_date | No | End date filter applied, if any |
| has_more | No | True if a full page was returned (more may exist; re-call with offset=offset+limit) |
| from_date | No | Start date filter applied, if any |
| member_id | No | Members API integer ID filter applied, if any (echoed from input). |
| text_mode | No | Whether contribution `text` carries the upstream preview or full body (still capped). |
| date_range | No | (min, max) SittingDate of returned contributions, or None if empty |
| top_debates | No | Top-ranked debates touching this topic (from upstream Debates[] preview, capped at 4 by Hansard's /search.json). Each entry's `debate_ext_id` chains to hansard://debate/{debate_ext_id}/header. |
| total_corpus | No | Total contributions in Hansard matching this query (TotalContributions). Use to decide whether to paginate further or escalate to parliament_policy_position_summary. |
| contributions | No | Matching Hansard contributions with full citation metadata. |
| top_divisions | No | Top-ranked divisions touching this topic (from upstream Divisions[] preview, capped at 4). Each entry's `id` chains to votes_get_division; `debate_section_ext_id` chains back to the parent debate. |
| total_debates | No | TotalDebates — distinct debates touching this topic. |
| total_members | No | TotalMembers — member-name matches in the corpus. |
| house_breakdown | No | Counts by house across the returned page |
| party_breakdown | No | ALWAYS EMPTY. Hansard's contribution schema has no structured party field (see HansardContribution.party) — an aggregation over unjustified values would just be a party-shaped guess. Kept as a field (rather than removed) for schema stability. For real party facets, resolve member_id per contribution via parliament_find_member; this tool does not do that automatically — it would cost one extra HTTP call per distinct member in the page. |
| total_divisions | No | TotalDivisions. Non-zero → consider `top_divisions` previews below or chain to votes_search_divisions. |
| total_petitions | No | TotalPetitions. |
| total_committees | No | TotalCommittees. |
| enrichment_status | No | Whether the optional /search.json corpus envelope was retrieved. 'degraded' means contribution results are source-backed and usable, but corpus totals and previews were unavailable. |
| total_corrections | No | TotalCorrections — published corrections to the Hansard record. |
| upstream_warnings | No | Explicit warnings for unavailable optional upstream enrichment. Do not infer omitted corpus totals or previews when this is non-empty. |
| total_written_answers | No | TotalWrittenAnswers. |
| total_written_statements | No | TotalWrittenStatements. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, openWorld), yet the description adds real operational disclosure beyond them: the independent corpus envelope may fail with one bounded retry, contributions then return enrichment_status='degraded' with a warning, and 'omitted corpus totals and previews must not be inferred' — a critical anti-hallucination constraint. It also states that envelope fields are source-backed only when complete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a capitalized trigger, then organized into returns, degraded-mode caveat, follow-up calls, exclusions, pagination, and source authority. Nearly every sentence earns its place for a routing-critical tool, though the 'bill title' clause in the opening sentence is a wasteful inaccuracy and the closing source-authority note partially restates the degraded-mode paragraph.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need not be detailed, yet the description still names the citation fields and explains the degraded envelope path — more than adequate for a 9-parameter tool. The gap is that nothing tells the agent the relationship between house/member_id/date filters and the query semantics (e.g. whether filters can be combined with free text), and the bill-title claim muddies the calling recipe.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the per-parameter docs are already excellent (text_mode cap sizes, contribution_type section meanings, member_id integer requirement), so the baseline is 3. The description only adds 'limit + offset honour the upstream paginated endpoint' and does not touch text_mode, contribution_type, or the date filters — marginal additive value over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('searching Hansard') and enumerates the retrieval axes: topic, bill title, text phrase, with the return payload named (contributions with citation-grade metadata). The one flaw is that the opening line advertises 'bill title' searching, which the query parameter description explicitly warns 'often DON'T match' — an internal tension an agent must resolve by reading the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('searching Hansard by topic... text phrase', 'DO NOT text-search by member name'), names the alternative chain parliament_find_member → parliament_get_debate_contributions as the canonical path for named members, and points to parliament_policy_position_summary for breadth and parliament_get_debate_contributions for whole-debate retrieval. Both positive routing and a negative exclusion are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parliament_search_petitionsSearch UK Parliament PetitionsARead-onlyIdempotentInspect
USE THIS TOOL WHEN searching UK Parliament petitions by keyword or topic.
Returns petition title, state, signature count, and dates for government response or parliamentary debate if applicable. Filter by state (open, closed, debated, etc.) to narrow to live or historical petitions.
This is the authoritative source for UK Parliament petitions (petition.parliament.uk).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum petitions to return. Default 20. | |
| query | Yes | Search term for petition titles, e.g. 'ban trophy hunting' or 'NHS funding'. | |
| state | No | Filter by petition state. | all |
| offset | No | Number of petitions to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true. |
Output Schema
| Name | Required | Description |
|---|---|---|
| limit | No | Page size requested |
| query | Yes | The term that was searched in petitions |
| state | Yes | Petition state filter applied to this query |
| total | Yes | Number of petitions returned in this call |
| offset | No | Skip applied to this page |
| has_more | No | True if a full page was returned (more may exist) |
| petitions | No | Matching petitions (title, state, signature count, key dates, URL). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the bar is lower. The description adds valuable context about return fields (title, state, signature count, dates) and the authoritative source, but does not disclose behavioral details like pagination or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized, with the key usage directive front-loaded. Each sentence serves a purpose: usage, returned data, filtering, and authoritative source. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has a rich output schema and fully described parameters, the description covers the essential usage context well. It does not explain pagination, but the offset parameter schema already handles that, and the output schema likely documents the return shape. Slight gap on the debated state discrepancy.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description mentions filtering by state but inconsistently lists 'debated' as an option while the schema enum only allows 'open', 'closed', and 'all', which could mislead. It does not add significant meaning beyond the schema's already descriptive parameter fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('search') and resource ('UK Parliament petitions') with clear scope ('by keyword or topic'). It distinguishes itself from sibling tools like parliament_search_hansard and bills_search_bills by focusing on petitions specifically.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description opens with 'USE THIS TOOL WHEN searching UK Parliament petitions by keyword or topic,' providing explicit usage context. However, it does not explicitly mention when not to use it or name alternative tools, falling short of the highest bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_resourceARead-onlyIdempotentInspect
Read a registered server resource URI, not an ordinary web URL.
USE WHEN you have a judgment://, legislation://, hansard://, or server:// URI returned by this server. Do not use for https:// URLs; use the source-specific tool instead (for a canonical GOV.UK HMRC internal-manual URL, call hmrc_get_manual_page).
Returns the resource content as a string. Binary content is base64-encoded.
AFTER calling, use the returned primary-source content and URI in citations; if the URI is rejected, follow the named source-specific tool rather than treating the URL as retrieved evidence.
Source: registered UK Legal MCP resource providers.
| Name | Required | Description | Default |
|---|---|---|---|
| uri | Yes | A server resource URI such as judgment://..., legislation://..., hansard://..., or server://about |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the operation as read-only, idempotent, non-destructive, and open-world. Beyond that, the description adds useful behavioral detail: content is returned as a string, binary content is base64-encoded, and rejected URIs should be handled by following the named source-specific tool rather than treating the URL as retrieved evidence.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose, followed by clear USE WHEN, return-value, and post-call guidance. Every section contributes directly to correct tool selection and invocation, with no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a simple one-parameter schema, full schema coverage, an output schema, and annotations covering safety and identity behavior. The description completes the picture by explaining accepted URI types, exclusions, return encoding, and error-handling guidance for rejected URIs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already defines the single uri parameter and gives examples. The description adds meaningful semantics by clarifying that the URI must be a registered server resource URI rather than an ordinary web URL and by naming the relevant schemes and fallback tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: read a registered server resource URI, explicitly not an ordinary web URL. It names the accepted URI schemes and distinguishes this tool from source-specific siblings such as hmrc_get_manual_page, so an agent can identify its role immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit USE WHEN guidance tied to judgment://, legislation://, hansard://, and server:// URIs returned by the server. It also states when not to use it for https:// URLs and directs the agent to the source-specific alternative with a concrete example.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
votes_get_divisionGet Division DetailARead-onlyIdempotentInspect
USE THIS TOOL WHEN you have a division_id + house and want the full member-by-member voting record.
Voter lists are truncated to 100 per side to fit response limits; total voter counts are always accurate regardless of truncation. Chain from votes_search_divisions or parliament_get_debate_divisions (which cross-resolves Hansard division refs into votes-API division_ids).
| Name | Required | Description | Default |
|---|---|---|---|
| house | No | Which house this division belongs to. | Commons |
| division_id | Yes | Division ID from votes_search_divisions results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Division ID |
| date | Yes | Date of the division |
| house | Yes | Commons or Lords |
| title | Yes | Division title / motion text |
| passed | Yes | Whether the motion passed |
| truncated | No | Whether voter lists were truncated to fit response limits |
| aye_voters | No | Members who voted Aye (may be truncated) |
| ayes_count | Yes | Total Aye votes |
| noe_voters | No | Members who voted No (may be truncated) |
| noes_count | Yes | Total No votes |
| total_aye_voters | No | Total number of Aye voters before truncation |
| total_noe_voters | No | Total number of No voters before truncation |
| is_government_win | No | Whether the government won (Lords only) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (read-only, idempotent), the description discloses a critical behavioral trait: voter lists are truncated to 100 per side while total counts remain accurate. This level of transparency helps agents set expectations and avoid misinterpreting truncated data. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is highly concise, front-loaded with an explicit 'USE THIS TOOL WHEN' directive, and packs essential information (purpose, input prerequisites, truncation caveat, chaining) into two sentences. Every sentence adds value, and the capitalization draws appropriate attention.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only two parameters and an existing output schema, the description covers all critical aspects: what the tool does, when to use it, key limitations (truncation), and how to obtain inputs. No additional context is needed for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides full coverage (100%) with descriptions for both parameters, including the source of division_id. The description only restates 'division_id + house' without adding further semantic detail, so it meets the baseline but does not elevate parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action—retrieving the full member-by-member voting record for a division—and immediately distinguishes itself from sibling search and debate tools. The resource (division_id + house) is explicit, and the chaining reference to votes_search_divisions and parliament_get_debate_divisions further differentiates it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells agents when to use this tool ('USE THIS TOOL WHEN you have a division_id + house'), and provides guidance on how to obtain the ID via sibling tools. It also clarifies the chaining workflow, though it could be more explicit about when not to use it; still, the guidance is strong and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
votes_search_divisionsSearch Parliamentary DivisionsARead-onlyIdempotentInspect
USE THIS TOOL WHEN searching Commons or Lords formal votes by topic, date, or member.
Returns one page of division summaries (title, date, vote counts,
pass/fail) plus total, the source's count of all matching divisions.
While has_more is true, re-call with offset=offset+returned. AFTER
calling, pass division_id + house into votes_get_division for the full
member-by-member voter lists.
Authoritative source for UK parliamentary vote records.
| Name | Required | Description | Default |
|---|---|---|---|
| house | No | Which house to search. | Commons |
| limit | No | 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`. | |
| query | No | Search term for division titles, e.g. 'Rwanda' or 'Online Safety Bill'. Omit to browse recent divisions. | |
| offset | No | Number of divisions to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true. | |
| to_date | No | End date (YYYY-MM-DD). | |
| from_date | No | Start date (YYYY-MM-DD). | |
| member_id | No | Filter to divisions where this member voted. Get the member ID from parliament_find_member. |
Output Schema
| Name | Required | Description |
|---|---|---|
| house | Yes | Commons or Lords |
| limit | No | Page size requested (the Commons API returns at most 25 regardless) |
| query | No | The search term, if any (None = browse recent) |
| total | Yes | Total divisions matching the filters, from the source API's searchTotalResults count |
| offset | No | Skip applied to this page |
| has_more | No | True if divisions beyond this page exist (offset + returned < total) |
| returned | Yes | Number of divisions returned in this call |
| divisions | No | Matching divisions. Use the integer `id` field with votes_get_division to fetch the full voter list. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavior beyond annotations: it returns one page of summaries, includes a `total` count, explains pagination with offset=offset+returned, and describes what is not included (full member lists). It also notes the authoritative source, which helps set expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and every sentence earns its place: the when-to-use directive, the return shape, pagination logic, the next-step linkage, and the source authority. The all-caps phrases are intentional emphasis for an agent, and the paragraph is front-loaded with the most actionable guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and 100% parameter schema coverage, the description only needs to supply usage context and behavior not already in structured fields. It does so thoroughly, covering search scope, pagination, what the response contains, and the follow-up tool to use. Nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter. The description reinforces that search can be by topic, date, or member, but doesn't add new semantic details beyond what the schema provides. Per the baseline rule, 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with an explicit directive: 'USE THIS TOOL WHEN searching Commons or Lords formal votes by topic, date, or member.' This names the verb (search), the resource (formal votes), and the filtering dimensions. It is clearly distinguished from the sibling votes_get_division by specifying that this returns summaries and that the full voter lists are obtained via the follow-up call.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear when-to-use statement and instructs the agent to re-call with offset while has_more is true, and to pass division_id + house into votes_get_division afterward. It doesn't explicitly exclude alternatives like parliament_search_hansard or parliament_get_debate_divisions, but the formal-votes scope and the named follow-up make the intended usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
- Changed
case_law_search1 field changed- added
Output schema / properties / unparsed_resultsAdded value: +{ + "default": 0, + "description": "Feed entries on this page that could not be parsed and are omitted from `results`. When greater than zero, `results` is incomplete for this page.", + "minimum": 0, + "type": "integer" +}
- Changed
committees_search_committees1 field changed- changed
Input schema / properties / query / descriptionPrevious value: -"Search term for committee names, e.g. 'defence' or 'treasury'. Filtered client-side against committee names. Omit to list all committees."New value: +"Search term for committee names, e.g. 'defence' or 'treasury'. Searched by the upstream API before `limit` is applied. Omit to list all committees."
- Changed
parliament_lookup_by_column1 field changed- added
Output schema / properties / unparsed_resultsAdded value: +{ + "default": 0, + "description": "Upstream matches that could not be parsed and are omitted from `matches`. When greater than zero, `matches` is incomplete and `total_results` is larger than the number of matches returned.", + "minimum": 0, + "type": "integer" +}
- Changed
parliament_search_hansard2 fields changed- changed
Output schema / properties / upstream_warnings / items / properties / error_category / descriptionPrevious value: -"Safe failure category for the unavailable optional enrichment."New value: +"Safe failure category for the unavailable optional enrichment. 'malformed' means the upstream answered but its aggregate totals were missing or invalid." - changed
Output schema / properties / upstream_warnings / items / properties / error_category / enumPrevious value: -[ - "transient", - "unknown" -]New value: +[ + "transient", + "unknown", + "malformed" +]
6 tool updates
- Added
committees_search_businesses - Changed
committees_search_evidence13 fields changed- added
Input schema / properties / committee_business_idAdded value: +{ + "anyOf": [ + { + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Exact official inquiry/business ID from committees_search_businesses. Applies the source filter before pagination; do not infer this from a title." +} - added
Input schema / properties / published_fromAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional inclusive source publication-date lower bound (YYYY-MM-DD). Applied upstream before pagination." +} - added
Input schema / properties / published_toAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional inclusive source publication-date upper bound (YYYY-MM-DD). Applied upstream before pagination." +} - added
Output schema / properties / evidence / items / properties / committee_businessesAdded value: +{ + "description": "Source inquiry/business identities associated with this evidence item", + "items": { + "description": "Source-supplied parliamentary committee business or inquiry identity.", + "properties": { + "close_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied business closing date" + }, + "id": { + "description": "Official CommitteeBusiness ID; use as committee_business_id for exact evidence filtering", + "type": "integer" + }, + "is_inquiry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied type flag; null when absent" + }, + "latest_report": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied latest-report metadata, unmodified when present" + }, + "open_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied business opening date" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied business status where present" + }, + "title": { + "description": "Source-supplied inquiry or business title", + "type": "string" + }, + "type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied business type name, e.g. Inquiry" + } + }, + "required": [ + "id", + "title" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / evidence / items / properties / date / descriptionPrevious value: -"Date the evidence was given or submitted"New value: +"Compatibility date: oral meeting_date when present, otherwise publication_date; use the source-specific fields for research" - added
Output schema / properties / evidence / items / properties / documentAdded value: +{ + "anyOf": [ + { + "properties": { + "document_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source document ID" + }, + "files": { + "description": "Source-supplied document file metadata", + "items": { + "properties": { + "file_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied document filename" + }, + "format": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied document file format" + }, + "size_bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied document file size in bytes" + }, + "url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source-supplied file URL; null means the source supplied no direct URL" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source document metadata; null when no document is supplied" +} - added
Output schema / properties / evidence / items / properties / hc_numberAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source HC paper number where supplied" +} - added
Output schema / properties / evidence / items / properties / internal_referenceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source internal submission reference, usually for written evidence" +} - added
Output schema / properties / evidence / items / properties / legacy_html_urlAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source legacy HTML URL where supplied" +} - added
Output schema / properties / evidence / items / properties / legacy_pdf_urlAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source legacy PDF URL where supplied" +} - added
Output schema / properties / evidence / items / properties / meeting_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source oral-evidence meeting date; null for written evidence or absent source data" +} - added
Output schema / properties / evidence / items / properties / publication_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source publication date; null only when the upstream record omits it" +} - added
Output schema / properties / evidence / items / properties / sessionAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source parliamentary session description where supplied" +}
- Added
hmrc_get_manual_page - Changed
legislation_search2 fields changed- added
Output schema / properties / fallback_reasonAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Typed upstream reason that triggered the automatic full-text fallback, or null when the requested route completed normally." +} - added
Output schema / properties / search_modeAdded value: +{ + "default": "title", + "description": "Route that produced these results. fulltext_fallback means the title route was unavailable because legislation.gov.uk returned a typed WAF/non-XML failure, so the server retried once using the documented full-text route; relevance may therefore be broader than title search.", + "enum": [ + "title", + "fulltext", + "fulltext_fallback" + ], + "type": "string" +}
- Changed
parliament_search_hansard2 fields changed- added
Output schema / properties / enrichment_statusAdded value: +{ + "default": "complete", + "description": "Whether the optional /search.json corpus envelope was retrieved. 'degraded' means contribution results are source-backed and usable, but corpus totals and previews were unavailable.", + "enum": [ + "complete", + "degraded" + ], + "type": "string" +} - added
Output schema / properties / upstream_warningsAdded value: +{ + "description": "Explicit warnings for unavailable optional upstream enrichment. Do not infer omitted corpus totals or previews when this is non-empty.", + "items": { + "description": "A failed optional Hansard upstream call retained with its provenance.", + "properties": { + "detail": { + "description": "Bounded upstream failure detail; it does not describe contribution content.", + "type": "string" + }, + "endpoint": { + "description": "Hansard endpoint whose optional enrichment was unavailable.", + "type": "string" + }, + "error_category": { + "description": "Safe failure category for the unavailable optional enrichment.", + "enum": [ + "transient", + "unknown" + ], + "type": "string" + }, + "retry_attempted": { + "description": "True when the bounded one-retry policy was used.", + "type": "boolean" + } + }, + "required": [ + "endpoint", + "retry_attempted", + "error_category", + "detail" + ], + "type": "object" + }, + "type": "array" +}
- Changed
read_resource1 field changed- changed
Input schema / properties / uri / descriptionPrevious value: -"The URI of the resource to read"New value: +"A server resource URI such as judgment://..., legislation://..., hansard://..., or server://about"
4 tool updates
- Changed
bills_search_bills3 fields changed- changed
Input schema / properties / house / descriptionPrevious value: -"Filter by originating house. Omit for all houses."New value: +"Filter by originating house: the House the bill was introduced in, wherever it sits now. Omit (or 'All') for all houses." - changed
Input schema / properties / offset / maximumPrevious value: -2000New value: +2147483647 - added
Output schema / properties / bills / items / properties / originating_houseAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "House where the bill was introduced (what the search `house` filter matches)" +}
- Changed
committees_search_evidence7 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum evidence items to return. Default 20. When evidence_type='both' the limit is split across oral and written (roughly half each)."New value: +"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." - changed
Input schema / properties / offset / descriptionPrevious value: -"Number of evidence items to skip before this page. Default 0. Re-call with offset=offset+returned while has_more is true."New value: +"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)." - changed
Input schema / properties / offset / maximumPrevious value: -2000New value: +2147483647 - changed
Output schema / descriptionPrevious value: -"A page of evidence submissions to a parliamentary committee.\n\nReturned by committees_search_evidence. Callers paginate by\nre-calling with offset=offset+returned while has_more is True.\nWhen evidence_type=\"both\", oral and written evidence are\ninterleaved in a single `evidence` list and the limit is split\nacross both."New value: +"A page of evidence submissions to a parliamentary committee.\n\nReturned by committees_search_evidence. Callers paginate by\nre-calling with offset=offset+returned while has_more is True.\nWhen evidence_type=\"both\", the sequence being paged is all oral\nevidence followed by all written evidence." - changed
Output schema / properties / has_more / descriptionPrevious value: -"True if there may be more evidence beyond this page. Re-call with offset=offset+returned to fetch the next page. Conservative: when evidence_type='both', True if either oral or written upstream page came back full."New value: +"True if evidence exists beyond this page (offset + returned < total). Re-call with offset=offset+returned to fetch the next page." - added
Output schema / properties / totalAdded value: +{ + "description": "Evidence items matching this query, from committees-api's totalResults (for evidence_type='both', the oral count plus the written count)", + "type": "integer" +} - changed
Output schema / requiredPrevious value: -[ - "committee_id", - "evidence_type", - "offset", - "limit", - "returned", - "has_more" -]New value: +[ + "committee_id", + "evidence_type", + "offset", + "limit", + "returned", + "total", + "has_more" +]
- Changed
hmrc_get_vat_rate10 fields changed- changed
Output schema / descriptionPrevious value: -"VAT rate for a commodity or service.\n\nBacked by a small static lookup table, not a live HMRC/GOV.UK query.\n\n`matched_category` is None whenever no specific table category matched\n(including a genuine tie between two equally-specific categories). In\nthat case `rate` and `rate_percentage` are ALSO None — this tool never\nfabricates a rate for an unresolved query. Callers must not assume a\ndefault (e.g. standard 20%) when `rate` is None; read `notes` for\nguidance on where to check instead."New value: +"VAT rate for a commodity or service.\n\nBacked by a small static lookup table, not a live HMRC/GOV.UK query.\n\n`matched_category` is None whenever the query is not exactly a table\ncategory name (or alias). In that case `rate`, `rate_percentage` and\n`verified_on` are ALSO None — this tool never fabricates a rate for an\nunresolved query. Callers must not assume a default (e.g. standard 20%)\nwhen `rate` is None; read `notes` for guidance on where to check instead.\n\nExempt and zero-rated are different treatments: zero-rated has\n`rate_percentage` 0.0, exempt has `rate_percentage` None." - changed
Output schema / properties / matched_category / descriptionPrevious value: -"The static lookup table category actually matched (e.g. 'hot food'), or None when no specific category matched, or the match was ambiguous between two equally-specific categories. `rate`/`rate_percentage` are None whenever this is None — see `notes`."New value: +"The static lookup table category the query exactly named (e.g. 'hot food'), or None when the query is not a category name. `rate`/`rate_percentage` are None whenever this is None — see `notes`." - changed
Output schema / properties / rate_percentage / descriptionPrevious value: -"Applicable rate as percentage: 20.0 (standard), 5.0 (reduced), 0.0 (zero/exempt), or None when `rate` is None (no confident match)."New value: +"Rate charged on a taxable supply: 20.0 (standard), 5.0 (reduced), 0.0 (zero). None for an exempt supply, which is not taxed at any rate (exempt is not the same as 0%), and None when `rate` is None." - changed
Output schema / properties / source_url / descriptionPrevious value: -"GOV.UK/HMRC guidance page backing this rate"New value: +"GOV.UK/HMRC guidance page backing the matched entry; for an unresolved query, the general VAT rates page to consult instead" - added
Output schema / properties / verified_on / anyOfAdded value: +[ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / properties / verified_on / defaultAdded value: +null - changed
Output schema / properties / verified_on / descriptionPrevious value: -"Date this entry (or, for an unresolved query, the lookup table's category set as a whole) was last checked against GOV.UK/HMRC guidance. A data-currency signal only — see `effective_from` for the rate's own legal commencement date, when known."New value: +"Date the matched entry was last checked against GOV.UK/HMRC guidance. None for an unresolved query, since no entry was matched. A data-currency signal only — see `effective_from` for the rate's own legal commencement date, when known." - removed
Output schema / properties / verified_on / formatRemoved value: -"date" - removed
Output schema / properties / verified_on / typeRemoved value: -"string" - changed
Output schema / requiredPrevious value: -[ - "commodity_code", - "verified_on", - "source_url" -]New value: +[ + "commodity_code", + "source_url" +]
- Changed
votes_search_divisions7 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum divisions to return. Default 25 (Commons API max-per-page)."New value: +"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`." - changed
Input schema / properties / offset / maximumPrevious value: -2000New value: +2147483647 - changed
Output schema / properties / has_more / descriptionPrevious value: -"True if a full page was returned (more may exist)"New value: +"True if divisions beyond this page exist (offset + returned < total)" - changed
Output schema / properties / limit / descriptionPrevious value: -"Page size requested"New value: +"Page size requested (the Commons API returns at most 25 regardless)" - added
Output schema / properties / returnedAdded value: +{ + "description": "Number of divisions returned in this call", + "type": "integer" +} - changed
Output schema / properties / total / descriptionPrevious value: -"Number of divisions returned in this call"New value: +"Total divisions matching the filters, from the source API's searchTotalResults count" - changed
Output schema / requiredPrevious value: -[ - "house", - "total" -]New value: +[ + "house", + "returned", + "total" +]
8 tool updates
- Changed
committees_search_evidence2 fields changed- changed
Output schema / properties / evidence / items / properties / witnesses / anyOfPrevious value: -[ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -]New value: +[ + { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } +] - changed
Output schema / properties / evidence / items / properties / witnesses / descriptionPrevious value: -"Witness names (oral evidence only, capped at 10 per item)"New value: +"Witness display names (oral evidence only, capped at 10 per item). An organisation witness (e.g. a regulator or company giving evidence collectively, not through one named individual) has no personal name upstream — that entry is rendered as '<Organisation> (<Role>)' instead, e.g. 'Bank of England (Governor)'. A null entry means committees-api.parliament.uk supplied neither a personal name nor an organisation for that witness slot — honest absence, not a fabricated placeholder; it is not omitted from the list, so the count of entries still matches the number of witnesses upstream."
- Changed
hmrc_get_vat_rate19 fields changed- changed
Output schema / descriptionPrevious value: -"VAT rate for a commodity or service."New value: +"VAT rate for a commodity or service.\n\nBacked by a small static lookup table, not a live HMRC/GOV.UK query.\n\n`matched_category` is None whenever no specific table category matched\n(including a genuine tie between two equally-specific categories). In\nthat case `rate` and `rate_percentage` are ALSO None — this tool never\nfabricates a rate for an unresolved query. Callers must not assume a\ndefault (e.g. standard 20%) when `rate` is None; read `notes` for\nguidance on where to check instead." - added
Output schema / properties / effective_from / anyOfAdded value: +[ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / properties / effective_from / defaultAdded value: +null - changed
Output schema / properties / effective_from / descriptionPrevious value: -"Date from which this rate applies"New value: +"Date the represented VAT treatment is known, on researched evidence, to have taken legal effect. None when no such commencement date has been established for this entry — that is common and does NOT imply the rate is new, uncertain, or unmatched. For data currency (when this entry was last checked against GOV.UK/HMRC guidance) see `verified_on` instead — the two are deliberately independent." - removed
Output schema / properties / effective_from / formatRemoved value: -"date" - removed
Output schema / properties / effective_from / typeRemoved value: -"string" - added
Output schema / properties / matched_categoryAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The static lookup table category actually matched (e.g. 'hot food'), or None when no specific category matched, or the match was ambiguous between two equally-specific categories. `rate`/`rate_percentage` are None whenever this is None — see `notes`." +} - added
Output schema / properties / rate / anyOfAdded value: +[ + { + "enum": [ + "standard", + "reduced", + "zero", + "exempt", + "outside_scope" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / properties / rate / defaultAdded value: +null - changed
Output schema / properties / rate / descriptionPrevious value: -"VAT rate category"New value: +"VAT rate category, or None when no specific category was confidently matched. None here is NOT a stand-in for any real rate — it means the lookup did not resolve, not that the item is outside VAT's scope." - removed
Output schema / properties / rate / enumRemoved value: -[ - "standard", - "reduced", - "zero", - "exempt", - "outside_scope" -] - removed
Output schema / properties / rate / typeRemoved value: -"string" - added
Output schema / properties / rate_percentage / anyOfAdded value: +[ + { + "type": "number" + }, + { + "type": "null" + } +] - added
Output schema / properties / rate_percentage / defaultAdded value: +null - changed
Output schema / properties / rate_percentage / descriptionPrevious value: -"Applicable rate as percentage: 20.0 (standard), 5.0 (reduced), 0.0 (zero/exempt)"New value: +"Applicable rate as percentage: 20.0 (standard), 5.0 (reduced), 0.0 (zero/exempt), or None when `rate` is None (no confident match)." - removed
Output schema / properties / rate_percentage / typeRemoved value: -"number" - added
Output schema / properties / source_urlAdded value: +{ + "description": "GOV.UK/HMRC guidance page backing this rate", + "type": "string" +} - added
Output schema / properties / verified_onAdded value: +{ + "description": "Date this entry (or, for an unresolved query, the lookup table's category set as a whole) was last checked against GOV.UK/HMRC guidance. A data-currency signal only — see `effective_from` for the rate's own legal commencement date, when known.", + "format": "date", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "commodity_code", - "rate", - "rate_percentage", - "effective_from" -]New value: +[ + "commodity_code", + "verified_on", + "source_url" +]
- Changed
legislation_get_section1 field changed- changed
Input schema / properties / section / descriptionPrevious value: -"Section number, e.g. '47' or '12A'. Use the numeric part only — not 'section-47'. Schedules are not currently supported."New value: +"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."
- Changed
parliament_find_member5 fields changed- added
Output schema / properties / members / items / properties / is_current / anyOfAdded value: +[ + { + "type": "boolean" + }, + { + "type": "null" + } +] - added
Output schema / properties / members / items / properties / is_current / defaultAdded value: +null - changed
Output schema / properties / members / items / properties / is_current / descriptionPrevious value: -"Whether the member currently sits"New value: +"Whether the member currently sits, in priority order: (1) the source's own membershipStatus.statusIsActive when membershipStatus is present — authoritative, used directly; (2) False when membershipStatus is null/absent but this record's own membershipEndDate is set — an authoritative end date, not an inference from how other records look; (3) None when neither is available — genuinely indeterminate, not fabricated as True or False. A null membershipStatus is NOT by itself read as 'ended'." - removed
Output schema / properties / members / items / properties / is_current / typeRemoved value: -"boolean" - changed
Output schema / properties / members / items / requiredPrevious value: -[ - "id", - "name", - "party", - "house", - "is_current" -]New value: +[ + "id", + "name", + "party", + "house" +]
- Changed
parliament_get_debate_contributions9 fields changed- changed
Output schema / properties / contributions / items / properties / attributed_to / descriptionPrevious value: -"Full citable attribution string, e.g. 'The Minister of State, DESNZ (Lord Whitehead) (Lab)'. Includes role-at-time of contribution for ministerial interventions."New value: +"Full citable attribution string, verbatim from Hansard, e.g. 'The Minister of State, DESNZ (Lord Whitehead) (Lab)' or 'Lord Pannick (CB)'. This is the authoritative citation text — quote it as-is rather than reconstructing it from other fields." - changed
Output schema / properties / contributions / items / properties / constituency / descriptionPrevious value: -"Constituency (Commons only; None for Lords)"New value: +"Constituency (Commons only; None for Lords). Not currently populated from AttributedTo — see `party`'s note on why positional parsing of that string is unsafe; use parliament_find_member for authoritative constituency." - changed
Output schema / properties / contributions / items / properties / member_id / descriptionPrevious value: -"Members API integer ID. Use as {member_id} in hansard://member/{member_id}/biography for the member's role history."New value: +"Members API integer ID. Use as {member_id} in hansard://member/{member_id}/biography for the member's role history. None for a collective or otherwise unresolved attribution (e.g. 'Hon. Members') — Hansard itself has no member to identify there." - added
Output schema / properties / contributions / items / properties / member_name / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / properties / contributions / items / properties / member_name / defaultAdded value: +null - changed
Output schema / properties / contributions / items / properties / member_name / descriptionPrevious value: -"Name of the contributing member (MemberName)"New value: +"Authoritative display name of the contributing member — populated ONLY when the source endpoint itself supplies a real name field, never derived by parsing `attributed_to`. Populated from Hansard's MemberName field on the search endpoints (parliament_search_hansard, parliament_member_debates). ALWAYS None from parliament_get_debate_contributions (backed by /debates/Debate/{ext}.json), because DebateItem has no MemberName field at all — only `AttributedTo` (a citation-display string) and `member_id`. AttributedTo's shape varies unpredictably (own name first, hereditary-title styling, ministerial office, chair/speaker role, annotations, collective labels — e.g. 'Lord Pannick (CB)' vs 'The Earl of Devon (CB)' vs 'Madam Deputy Speaker (Judith Cummins)' vs 'Madam Deputy Speaker' alone, all verified live) with no positional rule that reliably recovers the person's name across all of them — two earlier attempts ('use the last parenthesis', then 'unless it starts with `The `') were each falsified by a real, live counterexample. `attributed_to` is preserved in full instead of being decomposed into a guess. Resolve authoritative identity via `member_id` and parliament_find_member when this is None." - removed
Output schema / properties / contributions / items / properties / member_name / typeRemoved value: -"string" - changed
Output schema / properties / contributions / items / properties / party / descriptionPrevious value: -"Political party affiliation parsed from the trailing '(Party)' suffix in AttributedTo"New value: +"ALWAYS None. Hansard's AttributedTo is a citation-display string Hansard composes for readability, not structured party data — neither the search-contributions nor the debate-items schema declares a Party field, and the parenthesised text varies by convention (constituency, party, office, 'Maiden Speech', a virtual-attendance marker, or nothing at all) in ways that cannot be told apart by position alone. Guessing a party from it previously produced fabricated values for ministers/officeholders (e.g. party='Lucy Powell' for 'The Leader of the House of Commons (Lucy Powell)'). For a member's authoritative party, resolve `member_id` via parliament_find_member against the Members API's structured latestParty field." - changed
Output schema / properties / contributions / items / requiredPrevious value: -[ - "member_name", - "attributed_to", - "date", - "debate_title", - "debate_id", - "debate_ext_id", - "contribution_ext_id", - "chamber_section", - "house", - "text", - "url" -]New value: +[ + "attributed_to", + "date", + "debate_title", + "debate_id", + "debate_ext_id", + "contribution_ext_id", + "chamber_section", + "house", + "text", + "url" +]
- Changed
parliament_member_debates9 fields changed- changed
Output schema / properties / contributions / items / properties / attributed_to / descriptionPrevious value: -"Full citable attribution string, e.g. 'The Minister of State, DESNZ (Lord Whitehead) (Lab)'. Includes role-at-time of contribution for ministerial interventions."New value: +"Full citable attribution string, verbatim from Hansard, e.g. 'The Minister of State, DESNZ (Lord Whitehead) (Lab)' or 'Lord Pannick (CB)'. This is the authoritative citation text — quote it as-is rather than reconstructing it from other fields." - changed
Output schema / properties / contributions / items / properties / constituency / descriptionPrevious value: -"Constituency (Commons only; None for Lords)"New value: +"Constituency (Commons only; None for Lords). Not currently populated from AttributedTo — see `party`'s note on why positional parsing of that string is unsafe; use parliament_find_member for authoritative constituency." - changed
Output schema / properties / contributions / items / properties / member_id / descriptionPrevious value: -"Members API integer ID. Use as {member_id} in hansard://member/{member_id}/biography for the member's role history."New value: +"Members API integer ID. Use as {member_id} in hansard://member/{member_id}/biography for the member's role history. None for a collective or otherwise unresolved attribution (e.g. 'Hon. Members') — Hansard itself has no member to identify there." - added
Output schema / properties / contributions / items / properties / member_name / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / properties / contributions / items / properties / member_name / defaultAdded value: +null - changed
Output schema / properties / contributions / items / properties / member_name / descriptionPrevious value: -"Name of the contributing member (MemberName)"New value: +"Authoritative display name of the contributing member — populated ONLY when the source endpoint itself supplies a real name field, never derived by parsing `attributed_to`. Populated from Hansard's MemberName field on the search endpoints (parliament_search_hansard, parliament_member_debates). ALWAYS None from parliament_get_debate_contributions (backed by /debates/Debate/{ext}.json), because DebateItem has no MemberName field at all — only `AttributedTo` (a citation-display string) and `member_id`. AttributedTo's shape varies unpredictably (own name first, hereditary-title styling, ministerial office, chair/speaker role, annotations, collective labels — e.g. 'Lord Pannick (CB)' vs 'The Earl of Devon (CB)' vs 'Madam Deputy Speaker (Judith Cummins)' vs 'Madam Deputy Speaker' alone, all verified live) with no positional rule that reliably recovers the person's name across all of them — two earlier attempts ('use the last parenthesis', then 'unless it starts with `The `') were each falsified by a real, live counterexample. `attributed_to` is preserved in full instead of being decomposed into a guess. Resolve authoritative identity via `member_id` and parliament_find_member when this is None." - removed
Output schema / properties / contributions / items / properties / member_name / typeRemoved value: -"string" - changed
Output schema / properties / contributions / items / properties / party / descriptionPrevious value: -"Political party affiliation parsed from the trailing '(Party)' suffix in AttributedTo"New value: +"ALWAYS None. Hansard's AttributedTo is a citation-display string Hansard composes for readability, not structured party data — neither the search-contributions nor the debate-items schema declares a Party field, and the parenthesised text varies by convention (constituency, party, office, 'Maiden Speech', a virtual-attendance marker, or nothing at all) in ways that cannot be told apart by position alone. Guessing a party from it previously produced fabricated values for ministers/officeholders (e.g. party='Lucy Powell' for 'The Leader of the House of Commons (Lucy Powell)'). For a member's authoritative party, resolve `member_id` via parliament_find_member against the Members API's structured latestParty field." - changed
Output schema / properties / contributions / items / requiredPrevious value: -[ - "member_name", - "attributed_to", - "date", - "debate_title", - "debate_id", - "debate_ext_id", - "contribution_ext_id", - "chamber_section", - "house", - "text", - "url" -]New value: +[ + "attributed_to", + "date", + "debate_title", + "debate_id", + "debate_ext_id", + "contribution_ext_id", + "chamber_section", + "house", + "text", + "url" +]
- Changed
parliament_policy_position_summary1 field changed- changed
Output schema / properties / top_contributors / items / properties / party / descriptionPrevious value: -"Party affiliation parsed from AttributedTo"New value: +"Not derivable from Hansard's AttributedTo (see HansardContribution.party) — would require resolving member_id via parliament_find_member. Currently unused: top_contributors is always empty (see PolicyPositionSummary.by_party)."
- Changed
parliament_search_hansard10 fields changed- changed
Output schema / properties / contributions / items / properties / attributed_to / descriptionPrevious value: -"Full citable attribution string, e.g. 'The Minister of State, DESNZ (Lord Whitehead) (Lab)'. Includes role-at-time of contribution for ministerial interventions."New value: +"Full citable attribution string, verbatim from Hansard, e.g. 'The Minister of State, DESNZ (Lord Whitehead) (Lab)' or 'Lord Pannick (CB)'. This is the authoritative citation text — quote it as-is rather than reconstructing it from other fields." - changed
Output schema / properties / contributions / items / properties / constituency / descriptionPrevious value: -"Constituency (Commons only; None for Lords)"New value: +"Constituency (Commons only; None for Lords). Not currently populated from AttributedTo — see `party`'s note on why positional parsing of that string is unsafe; use parliament_find_member for authoritative constituency." - changed
Output schema / properties / contributions / items / properties / member_id / descriptionPrevious value: -"Members API integer ID. Use as {member_id} in hansard://member/{member_id}/biography for the member's role history."New value: +"Members API integer ID. Use as {member_id} in hansard://member/{member_id}/biography for the member's role history. None for a collective or otherwise unresolved attribution (e.g. 'Hon. Members') — Hansard itself has no member to identify there." - added
Output schema / properties / contributions / items / properties / member_name / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / properties / contributions / items / properties / member_name / defaultAdded value: +null - changed
Output schema / properties / contributions / items / properties / member_name / descriptionPrevious value: -"Name of the contributing member (MemberName)"New value: +"Authoritative display name of the contributing member — populated ONLY when the source endpoint itself supplies a real name field, never derived by parsing `attributed_to`. Populated from Hansard's MemberName field on the search endpoints (parliament_search_hansard, parliament_member_debates). ALWAYS None from parliament_get_debate_contributions (backed by /debates/Debate/{ext}.json), because DebateItem has no MemberName field at all — only `AttributedTo` (a citation-display string) and `member_id`. AttributedTo's shape varies unpredictably (own name first, hereditary-title styling, ministerial office, chair/speaker role, annotations, collective labels — e.g. 'Lord Pannick (CB)' vs 'The Earl of Devon (CB)' vs 'Madam Deputy Speaker (Judith Cummins)' vs 'Madam Deputy Speaker' alone, all verified live) with no positional rule that reliably recovers the person's name across all of them — two earlier attempts ('use the last parenthesis', then 'unless it starts with `The `') were each falsified by a real, live counterexample. `attributed_to` is preserved in full instead of being decomposed into a guess. Resolve authoritative identity via `member_id` and parliament_find_member when this is None." - removed
Output schema / properties / contributions / items / properties / member_name / typeRemoved value: -"string" - changed
Output schema / properties / contributions / items / properties / party / descriptionPrevious value: -"Political party affiliation parsed from the trailing '(Party)' suffix in AttributedTo"New value: +"ALWAYS None. Hansard's AttributedTo is a citation-display string Hansard composes for readability, not structured party data — neither the search-contributions nor the debate-items schema declares a Party field, and the parenthesised text varies by convention (constituency, party, office, 'Maiden Speech', a virtual-attendance marker, or nothing at all) in ways that cannot be told apart by position alone. Guessing a party from it previously produced fabricated values for ministers/officeholders (e.g. party='Lucy Powell' for 'The Leader of the House of Commons (Lucy Powell)'). For a member's authoritative party, resolve `member_id` via parliament_find_member against the Members API's structured latestParty field." - changed
Output schema / properties / contributions / items / requiredPrevious value: -[ - "member_name", - "attributed_to", - "date", - "debate_title", - "debate_id", - "debate_ext_id", - "contribution_ext_id", - "chamber_section", - "house", - "text", - "url" -]New value: +[ + "attributed_to", + "date", + "debate_title", + "debate_id", + "debate_ext_id", + "contribution_ext_id", + "chamber_section", + "house", + "text", + "url" +] - changed
Output schema / properties / party_breakdown / descriptionPrevious value: -"Counts by party across the returned page"New value: +"ALWAYS EMPTY. Hansard's contribution schema has no structured party field (see HansardContribution.party) — an aggregation over unjustified values would just be a party-shaped guess. Kept as a field (rather than removed) for schema stability. For real party facets, resolve member_id per contribution via parliament_find_member; this tool does not do that automatically — it would cost one extra HTTP call per distinct member in the page."
4 tool updates
- Changed
get_prompt1 field changed- added
Output schema / descriptionAdded value: +"Generic wrapper for non-object return types."
- Changed
list_prompts1 field changed- added
Output schema / descriptionAdded value: +"Generic wrapper for non-object return types."
- Changed
list_resources1 field changed- added
Output schema / descriptionAdded value: +"Generic wrapper for non-object return types."
- Changed
read_resource1 field changed- added
Output schema / descriptionAdded value: +"Generic wrapper for non-object return types."
3 tool updates
- Changed
parliament_lookup_by_column1 field changed- changed
Output schema / properties / matches / items / properties / debate_id / descriptionPrevious value: -"Internal Hansard debate ID (DebateSectionId)"New value: +"Internal Hansard debate ID."
- Changed
parliament_policy_position_summary1 field changed- changed
Output schema / properties / top_debates / items / properties / debate_id / descriptionPrevious value: -"Internal Hansard debate ID (DebateSectionId)"New value: +"Internal Hansard debate ID."
- Changed
parliament_search_hansard1 field changed- changed
Output schema / properties / top_debates / items / properties / debate_id / descriptionPrevious value: -"Internal Hansard debate ID (DebateSectionId)"New value: +"Internal Hansard debate ID."
1 tool update
- Added
citations_format_oscola
27 tool updates
- Changed
bills_get_bill4 fields changed- added
Input schema / properties / bill_idAdded value: +{ + "description": "Bill ID from bills_search_bills results.", + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / max_summary_charsAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "BillDetailInput.", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "bill_id" +]
- Changed
bills_search_bills8 fields changed- added
Input schema / properties / houseAdded value: +{ + "anyOf": [ + { + "enum": [ + "Commons", + "Lords", + "All" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Filter by originating house. Omit for all houses." +} - added
Input schema / properties / limitAdded value: +{ + "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" +} - added
Input schema / properties / offsetAdded value: +{ + "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": 2000, + "minimum": 0, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "BillSearchInput.", - "properties": { - "house": { - "anyOf": [ - { - "enum": [ - "Commons", - "Lords", - "All" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Filter by originating house. Omit 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": 2000, - "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" - ], - "type": "object" -} - added
Input schema / properties / queryAdded value: +{ + "description": "Search term for bill titles and descriptions, e.g. 'online safety' or 'financial services'.", + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / sessionAdded value: +{ + "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." +} - added
Input schema / properties / stageAdded value: +{ + "anyOf": [ + { + "enum": [ + "firstreading", + "secondreading", + "committee", + "report", + "thirdreading", + "royalassent" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Filter by current legislative stage." +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "query" +]
- Changed
case_law_grep_judgment6 fields changed- added
Input schema / properties / case_insensitiveAdded value: +{ + "default": true, + "description": "Default true. Set false for case-sensitive matching.", + "type": "boolean" +} - added
Input schema / properties / max_hitsAdded value: +{ + "default": 25, + "description": "Cap on number of hits returned.", + "maximum": 100, + "minimum": 1, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CaseLawGrepInput.", - "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" - ], - "type": "object" -} - added
Input schema / properties / patternAdded value: +{ + "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" +} - added
Input schema / properties / slugAdded value: +{ + "description": "TNA judgment slug, e.g. 'uksc/2024/12' or 'ewca/civ/2023/450'.", + "minLength": 8, + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "slug", + "pattern" +]
- Changed
case_law_search10 fields changed- added
Input schema / properties / courtAdded value: +{ + "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'." +} - added
Input schema / properties / from_dateAdded value: +{ + "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." +} - added
Input schema / properties / judgeAdded value: +{ + "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." +} - added
Input schema / properties / limitAdded value: +{ + "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" +} - added
Input schema / properties / pageAdded value: +{ + "default": 1, + "description": "Result page number (1-indexed)", + "maximum": 50, + "minimum": 1, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CaseLawSearchInput.", - "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" - ], - "type": "object" -} - added
Input schema / properties / partyAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Filter by party name" +} - added
Input schema / properties / queryAdded value: +{ + "description": "Full-text search query, e.g. 'negligence duty of care'", + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / to_dateAdded value: +{ + "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." +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "query" +]
- Changed
citations_network3 fields changed- added
Input schema / properties / case_uriAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CitationsNetworkInput with case_uri (TNA slug, e.g. 'uksc/2024/12').", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "case_uri" +]
- Changed
citations_parse4 fields changed- added
Input schema / properties / disambiguateAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CitationsParseInput.", - "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" - ], - "type": "object" -} - added
Input schema / properties / textAdded value: +{ + "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" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "text" +]
- Changed
citations_resolve3 fields changed- added
Input schema / properties / citationAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CitationsResolveInput.", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "citation" +]
- Changed
committees_get_committee3 fields changed- added
Input schema / properties / committee_idAdded value: +{ + "description": "Committee ID from committees_search_committees results.", + "minimum": 1, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CommitteeDetailInput.", - "properties": { - "committee_id": { - "description": "Committee ID from committees_search_committees results.", - "minimum": 1, - "type": "integer" - } - }, - "required": [ - "committee_id" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "committee_id" +]
- Changed
committees_search_committees6 fields changed- added
Input schema / properties / active_onlyAdded value: +{ + "default": true, + "description": "If true, only return currently active committees.", + "type": "boolean" +} - added
Input schema / properties / houseAdded value: +{ + "anyOf": [ + { + "enum": [ + "Commons", + "Lords", + "Joint" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Filter by house." +} - added
Input schema / properties / limitAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CommitteeSearchInput.", - "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." - } - }, - "type": "object" -} - added
Input schema / properties / queryAdded value: +{ + "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." +} - removed
Input schema / requiredRemoved value: -[ - "params" -]
- Changed
committees_search_evidence7 fields changed- added
Input schema / properties / committee_idAdded value: +{ + "description": "Committee ID from committees_search_committees results.", + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / evidence_typeAdded value: +{ + "default": "both", + "description": "Type of evidence to search.", + "enum": [ + "oral", + "written", + "both" + ], + "type": "string" +} - added
Input schema / properties / limitAdded value: +{ + "default": 20, + "description": "Maximum evidence items to return. Default 20. When evidence_type='both' the limit is split across oral and written (roughly half each).", + "maximum": 100, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / max_title_charsAdded value: +{ + "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" +} - added
Input schema / properties / offsetAdded value: +{ + "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.", + "maximum": 2000, + "minimum": 0, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "CommitteeEvidenceInput.", - "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. When evidence_type='both' the limit is split across oral and written (roughly half each).", - "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.", - "maximum": 2000, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "committee_id" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "committee_id" +]
- Changed
hmrc_check_mtd_status3 fields changed- removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "HMRCMTDStatusInput.", - "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" - ], - "type": "object" -} - added
Input schema / properties / vrnAdded value: +{ + "description": "VAT Registration Number: 9 digits, e.g. '123456789'. GB prefix accepted and stripped automatically.", + "maxLength": 12, + "minLength": 9, + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "vrn" +]
- Changed
hmrc_get_vat_rate3 fields changed- added
Input schema / properties / commodity_codeAdded value: +{ + "description": "Commodity code or plain-English description. E.g. 'food', 'domestic fuel', 'software', 'financial services', 'new build residential'", + "maxLength": 200, + "minLength": 2, + "type": "string" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "HMRCVATRateInput.", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "commodity_code" +]
- Changed
hmrc_search_guidance4 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 10, + "description": "Maximum guidance results to return (1–25). Passed to the GOV.UK search count param.", + "maximum": 25, + "minimum": 1, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "HMRCGuidanceSearchInput.", - "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" - ], - "type": "object" -} - added
Input schema / properties / queryAdded value: +{ + "description": "Search query for HMRC guidance, e.g. 'VAT digital services', 'R&D tax relief SME'", + "maxLength": 300, + "minLength": 3, + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "query" +]
- Changed
legislation_get_section7 fields changed- added
Input schema / properties / max_charsAdded value: +{ + "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" +} - added
Input schema / properties / numberAdded value: +{ + "description": "Chapter or SI number", + "minimum": 1, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "LegislationGetSectionInput.", - "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": "Section number, e.g. '47' or '12A'. Use the numeric part only — not 'section-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" - ], - "type": "object" -} - added
Input schema / properties / sectionAdded value: +{ + "description": "Section number, e.g. '47' or '12A'. Use the numeric part only — not 'section-47'. Schedules are not currently supported.", + "maxLength": 50, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / typeAdded value: +{ + "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" +} - added
Input schema / properties / yearAdded value: +{ + "description": "Year of enactment", + "maximum": 2100, + "minimum": 1800, + "type": "integer" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "type", + "year", + "number", + "section" +]
- Changed
legislation_get_toc7 fields changed- added
Input schema / properties / limitAdded value: +{ + "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" +} - added
Input schema / properties / numberAdded value: +{ + "description": "Chapter or SI number", + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "LegislationGetTocInput.", - "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" - ], - "type": "object" -} - added
Input schema / properties / typeAdded value: +{ + "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" +} - added
Input schema / properties / yearAdded value: +{ + "description": "Year of enactment", + "maximum": 2100, + "minimum": 1800, + "type": "integer" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "type", + "year", + "number" +]
- Changed
legislation_search7 fields changed- added
Input schema / properties / fulltextAdded value: +{ + "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" +} - added
Input schema / properties / limitAdded value: +{ + "default": 20, + "description": "Maximum results to return (1–50). Passed to the upstream results-count param.", + "maximum": 50, + "minimum": 1, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "LegislationSearchInput.", - "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" - ], - "type": "object" -} - added
Input schema / properties / queryAdded value: +{ + "description": "Search query, e.g. 'Housing Act 1988' or 'data protection personal data'", + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / typeAdded value: +{ + "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." +} - added
Input schema / properties / yearAdded value: +{ + "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." +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "query" +]
- Changed
parliament_find_member3 fields changed- added
Input schema / properties / nameAdded value: +{ + "description": "Name or partial name, e.g. 'Starmer', 'Baroness Hale'", + "maxLength": 200, + "minLength": 2, + "type": "string" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "FindMemberInput with the name (full or partial).", - "properties": { - "name": { - "description": "Name or partial name, e.g. 'Starmer', 'Baroness Hale'", - "maxLength": 200, - "minLength": 2, - "type": "string" - } - }, - "required": [ - "name" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "name" +]
- Changed
parliament_get_debate_contributions4 fields changed- added
Input schema / properties / debate_ext_idAdded value: +{ + "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" +} - added
Input schema / properties / member_idAdded value: +{ + "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)." +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "GetDebateContributionsInput with debate_ext_id (required) and\noptional member_id filter.", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "debate_ext_id" +]
- Changed
parliament_get_debate_divisions3 fields changed- added
Input schema / properties / debate_ext_idAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "GetDebateDivisionsInput with the debate_ext_id GUID\n(chain from parliament_search_hansard contribution.debate_ext_id\nor top_debates[].debate_ext_id).", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "debate_ext_id" +]
- Changed
parliament_lookup_by_column5 fields changed- added
Input schema / properties / column_numberAdded value: +{ + "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" +} - added
Input schema / properties / houseAdded value: +{ + "default": "both", + "description": "Restrict to one House. Default 'both' searches across both Houses.", + "enum": [ + "Commons", + "Lords", + "both" + ], + "type": "string" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "LookupByColumnInput with column_number, volume_number, house.", - "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" - ], - "type": "object" -} - added
Input schema / properties / volume_numberAdded value: +{ + "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" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "column_number", + "volume_number" +]
- Changed
parliament_member_debates6 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 20, + "description": "Maximum contributions to return. Default 20.", + "maximum": 100, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / member_idAdded value: +{ + "description": "Parliament Members API integer ID. Obtain from parliament_find_member.", + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "MemberDebatesInput with member_id and optional topic filter.", - "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" - ], - "type": "object" -} - added
Input schema / properties / topicAdded value: +{ + "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=...)." +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "member_id" +]
- Changed
parliament_member_interests7 fields changed- added
Input schema / properties / categoryAdded value: +{ + "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." +} - added
Input schema / properties / limitAdded value: +{ + "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" +} - added
Input schema / properties / max_description_charsAdded value: +{ + "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" +} - added
Input schema / properties / member_idAdded value: +{ + "description": "Parliament Members API integer ID. Get from parliament_find_member.", + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "member_id, optional category filter, pagination (offset/limit),\nand max_description_chars content cap.", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "member_id" +]
- Changed
parliament_policy_position_summary7 fields changed- added
Input schema / properties / from_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Start date (YYYY-MM-DD)" +} - added
Input schema / properties / houseAdded value: +{ + "default": "both", + "description": "Restrict to one House. Default 'both'.", + "enum": [ + "Commons", + "Lords", + "both" + ], + "type": "string" +} - added
Input schema / properties / max_debates_scannedAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "PolicyPositionSummaryInput with topic, optional date range, house, max_debates_scanned.", - "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" - ], - "type": "object" -} - added
Input schema / properties / to_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "End date (YYYY-MM-DD)" +} - added
Input schema / properties / topicAdded value: +{ + "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" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "topic" +]
- Changed
parliament_search_hansard11 fields changed- added
Input schema / properties / contribution_typeAdded value: +{ + "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" +} - added
Input schema / properties / from_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Start date (YYYY-MM-DD)" +} - added
Input schema / properties / houseAdded value: +{ + "default": "both", + "description": "Restrict to one House. Default 'both' returns Commons + Lords contributions.", + "enum": [ + "Commons", + "Lords", + "both" + ], + "type": "string" +} - added
Input schema / properties / limitAdded value: +{ + "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" +} - added
Input schema / properties / member_idAdded value: +{ + "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`." +} - added
Input schema / properties / offsetAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "HansardSearchInput.", - "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' 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" - ], - "type": "object" -} - added
Input schema / properties / queryAdded value: +{ + "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" +} - added
Input schema / properties / text_modeAdded value: +{ + "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" +} - added
Input schema / properties / to_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "End date (YYYY-MM-DD)" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "query" +]
- Changed
parliament_search_petitions6 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 20, + "description": "Maximum petitions to return. Default 20.", + "maximum": 100, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "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" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "PetitionSearchInput with query and optional state filter.", - "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" - ], - "type": "object" -} - added
Input schema / properties / queryAdded value: +{ + "description": "Search term for petition titles, e.g. 'ban trophy hunting' or 'NHS funding'.", + "maxLength": 300, + "minLength": 2, + "type": "string" +} - added
Input schema / properties / stateAdded value: +{ + "default": "all", + "description": "Filter by petition state.", + "enum": [ + "open", + "closed", + "all" + ], + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "query" +]
- Changed
votes_get_division4 fields changed- added
Input schema / properties / division_idAdded value: +{ + "description": "Division ID from votes_search_divisions results.", + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / houseAdded value: +{ + "default": "Commons", + "description": "Which house this division belongs to.", + "enum": [ + "Commons", + "Lords" + ], + "type": "string" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "DivisionDetailInput.", - "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" - ], - "type": "object" -} - changed
Input schema / requiredPrevious value: -[ - "params" -]New value: +[ + "division_id" +]
- Changed
votes_search_divisions9 fields changed- added
Input schema / properties / from_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Start date (YYYY-MM-DD)." +} - added
Input schema / properties / houseAdded value: +{ + "default": "Commons", + "description": "Which house to search.", + "enum": [ + "Commons", + "Lords" + ], + "type": "string" +} - added
Input schema / properties / limitAdded value: +{ + "default": 25, + "description": "Maximum divisions to return. Default 25 (Commons API max-per-page).", + "maximum": 100, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / member_idAdded value: +{ + "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." +} - added
Input schema / properties / offsetAdded value: +{ + "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": 2000, + "minimum": 0, + "type": "integer" +} - removed
Input schema / properties / paramsRemoved value: -{ - "additionalProperties": false, - "description": "DivisionSearchInput.", - "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 (Commons API max-per-page).", - "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": 2000, - "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)." - } - }, - "type": "object" -} - added
Input schema / properties / queryAdded value: +{ + "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." +} - added
Input schema / properties / to_dateAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "End date (YYYY-MM-DD)." +} - removed
Input schema / requiredRemoved value: -[ - "params" -]
2 tool updates
- Changed
hmrc_search_guidance1 field changed- added
Input schema / properties / params / properties / limitAdded value: +{ + "default": 10, + "description": "Maximum guidance results to return (1–25). Passed to the GOV.UK search count param.", + "maximum": 25, + "minimum": 1, + "type": "integer" +}
- Changed
legislation_search1 field changed- added
Input schema / properties / params / properties / limitAdded value: +{ + "default": 20, + "description": "Maximum results to return (1–50). Passed to the upstream results-count param.", + "maximum": 50, + "minimum": 1, + "type": "integer" +}
1 tool update
- Changed
case_law_search1 field changed- added
Input schema / properties / params / properties / limitAdded value: +{ + "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" +}
1 tool update
- Changed
legislation_get_section1 field changed- changed
Output schema / properties / in_force / descriptionPrevious value: -"Whether this section is currently in force; None if unknown"New value: +"False if the section is explicitly marked repealed in CLML. True only when an InForce element is present in the section body (rare). Null for most sections — the data.xml endpoint does not carry a per-section current in-force boolean; null does not mean repealed."
2 tool updates
- Changed
bills_search_bills1 field changed- changed
Input schema / properties / params / properties / session / descriptionPrevious value: -"Parliamentary session ID. Omit to search all sessions. Session numbers change each year (e.g. 40 = 2024-25, 39 = 2023-24)."New value: +"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."
- Changed
citations_parse2 fields changed- changed
Input schema / properties / params / properties / disambiguate / defaultPrevious value: -trueNew value: +false - changed
Input schema / properties / params / properties / disambiguate / descriptionPrevious value: -"If True, ambiguous citations (e.g. bare EWHC without division) are sent to the LLM for disambiguation via sampling."New value: +"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."
21 tool updates
- Changed
bills_get_bill1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"BillDetailInput with bill_id and optional max_summary_chars."New value: +"BillDetailInput."
- Changed
bills_search_bills1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"BillSearchInput with query, optional session/house/stage filters, pagination."New value: +"BillSearchInput."
- Changed
case_law_grep_judgment1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"Input schema for case_law_grep_judgment."New value: +"CaseLawGrepInput."
- Changed
case_law_search1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"CaseLawSearchInput with query, optional filters (court, judge,\nparty, from_date, to_date), and page number."New value: +"CaseLawSearchInput."
- Changed
citations_parse1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"CitationsParseInput with text (max 50,000 chars) and disambiguate flag."New value: +"CitationsParseInput."
- Changed
citations_resolve1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"CitationsResolveInput with a single citation string."New value: +"CitationsResolveInput."
- Changed
committees_get_committee1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"CommitteeDetailInput with committee_id from committees_search_committees."New value: +"CommitteeDetailInput."
- Changed
committees_search_committees1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"CommitteeSearchInput with optional query, house, active_only, limit."New value: +"CommitteeSearchInput."
- Changed
committees_search_evidence1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"CommitteeEvidenceInput with committee_id, evidence_type,\noffset/limit pagination, and max_title_chars."New value: +"CommitteeEvidenceInput."
- Changed
hmrc_check_mtd_status1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"HMRCMTDStatusInput with the 9-digit VAT Registration Number."New value: +"HMRCMTDStatusInput."
- Changed
hmrc_get_vat_rate1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"HMRCVATRateInput with the commodity_code (description of goods or service)."New value: +"HMRCVATRateInput."
- Changed
hmrc_search_guidance1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"HMRCGuidanceSearchInput with query (topic to search)."New value: +"HMRCGuidanceSearchInput."
- Changed
legislation_get_section1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"type, year, number, section identifier, optional max_chars."New value: +"LegislationGetSectionInput."
- Changed
legislation_get_toc1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"LegislationGetTocInput with type, year, number, offset, limit."New value: +"LegislationGetTocInput."
- Changed
legislation_search1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"LegislationSearchInput with query, optional type filter, optional year."New value: +"LegislationSearchInput."
- Added
list_resources - Changed
parliament_lookup_by_column1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"LookupByColumnInput with column_number (string), volume_number\n(int), and optional house. Date is NOT a valid lookup key — the\nendpoint requires the volume number."New value: +"LookupByColumnInput with column_number, volume_number, house."
- Changed
parliament_search_hansard1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"HansardSearchInput with query, optional date range, house, member_id,\ntext_mode, contribution_type, offset, limit."New value: +"HansardSearchInput."
- Added
read_resource - Changed
votes_get_division1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"DivisionDetailInput with division_id and house."New value: +"DivisionDetailInput."
- Changed
votes_search_divisions1 field changed- changed
Input schema / properties / params / descriptionPrevious value: -"DivisionSearchInput with optional query, house, date range, member filter."New value: +"DivisionSearchInput."
4 tool updates
- Added
parliament_get_debate_contributions - Changed
parliament_member_debates1 field changed- changed
Input schema / properties / params / properties / topic / descriptionPrevious value: -"Optional phrase to filter this member's contributions by topic, e.g. 'housing benefit' or 'net zero'. Searched as an exact phrase."New value: +"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=...)."
- Changed
parliament_policy_position_summary1 field changed- changed
Input schema / properties / params / properties / topic / descriptionPrevious value: -"Phrase to search in Hansard, e.g. 'short selling regulation'. Searched as an exact phrase. For broader recall, drop quotes by shortening the topic."New value: +"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."
- Changed
parliament_search_hansard1 field changed- changed
Input schema / properties / params / properties / query / descriptionPrevious value: -"Full phrase to search in Hansard debates. Pass the complete topic, e.g. 'short selling regulation' or 'artificial intelligence liability'. Searched as an exact phrase — do not truncate to a single keyword."New value: +"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' 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."
3 tool updates
- Changed
parliament_lookup_by_column3 fields changed- changed
Output schema / properties / matches / descriptionPrevious value: -"Debate sections containing the cited column, in upstream relevance order. Each element's `debate_ext_id` chains to hansard://debate/{debate_ext_id}/header. Empty when the citation does not resolve — typically because the column is from a Daily Part (not yet consolidated into a Bound Volume) or the volume number is wrong."New value: +"Debate sections containing the cited column, in upstream relevance order. Each element's `debate_ext_id` chains to hansard://debate/{debate_ext_id}/header, and carries `source`/`source_code` for the citation's publication state. Resolution is NOT gated on publication state — Daily Part, Bound Volume, and Historic columns all resolve. Empty matches typically mean the volume number is wrong (running-volume vs bound-volume number), the column is a Written Answer/Statement needing its suffix (e.g. '1162W'), or a very recent column not yet indexed upstream." - added
Output schema / properties / matches / items / properties / sourceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Human-readable Hansard publication state (Swagger Source enum name). Tells a lawyer the citation's finality — RollingHansard/DailyHansard are pre-consolidation, BoundVolume/Historic are final bound volumes. Does NOT indicate whether the citation resolves: column lookup resolves across all four states." +} - added
Output schema / properties / matches / items / properties / source_codeAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Raw Hansard Overview.Source ordinal: 1=RollingHansard, 2=DailyHansard, 3=BoundVolume, 4=Historic. Populated only when the emitting tool fetches the debate payload (today: parliament_lookup_by_column); null otherwise." +}
- Changed
parliament_policy_position_summary2 fields changed- added
Output schema / properties / top_debates / items / properties / sourceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Human-readable Hansard publication state (Swagger Source enum name). Tells a lawyer the citation's finality — RollingHansard/DailyHansard are pre-consolidation, BoundVolume/Historic are final bound volumes. Does NOT indicate whether the citation resolves: column lookup resolves across all four states." +} - added
Output schema / properties / top_debates / items / properties / source_codeAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Raw Hansard Overview.Source ordinal: 1=RollingHansard, 2=DailyHansard, 3=BoundVolume, 4=Historic. Populated only when the emitting tool fetches the debate payload (today: parliament_lookup_by_column); null otherwise." +}
- Changed
parliament_search_hansard2 fields changed- added
Output schema / properties / top_debates / items / properties / sourceAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Human-readable Hansard publication state (Swagger Source enum name). Tells a lawyer the citation's finality — RollingHansard/DailyHansard are pre-consolidation, BoundVolume/Historic are final bound volumes. Does NOT indicate whether the citation resolves: column lookup resolves across all four states." +} - added
Output schema / properties / top_debates / items / properties / source_codeAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Raw Hansard Overview.Source ordinal: 1=RollingHansard, 2=DailyHansard, 3=BoundVolume, 4=Historic. Populated only when the emitting tool fetches the debate payload (today: parliament_lookup_by_column); null otherwise." +}
Related MCP Connectors
UK tax and legal research grounded in legislation, HMRC guidance and case law, with citations.
Search and read UK legislation at any date, resolve citations, list amendments, track changes.
Search UK Acts, Statutory Instruments, and legislation with full text retrieval
UK case law — Find Case Law, The National Archives.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables searching and retrieval of UK legislation (Acts, Statutory Instruments) from legislation.gov.uk with persistent identifiers and verifiable citations.9132 PyPIApache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables searching and retrieving full-text UK court judgments and tribunal decisions from The National Archives' Find Case Law service by subject, party, judge, or neutral citation.202 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables searching and reading UK legislation as it stands now, as enacted, or on any date, resolving citations to canonical items and provisions, listing amendments and effects, and tracking daily changes via the legislation.gov.uk publication log.691 npm2Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables searching and retrieving UK case law from The National Archives, including full judgments with filtering by court, legal area, and date range.26PolyForm Noncommercial 1.0.0
Glama MCP Gateway
Add one secure layer between your agents and this server.