analyze_patterns
Detect voting patterns like close divisions, government defeats, and party rebellion rates across parliamentary votes for trend analysis.
Instructions
Detect patterns across many parliamentary votes: 'close_votes' finds divisions with a small margin (near-misses or knife-edge votes), 'government_defeats' finds votes the government lost, 'party_rebellion_rate' shows which parties rebel most by percentage of votes cast. Use for trend analysis across many divisions.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pattern_type | Yes | The pattern to detect. | |
| house | No | Which house to analyse. Defaults to Commons. | |
| days | No | How many days back to scan. Default 365. | |
| threshold | No | For close_votes: maximum majority to count as close. Default 10. | |
| max_divisions | No | Maximum divisions to scan. Default 100. | |
| limit | No | Maximum results to return. Default 20. |
Implementation Reference
- src/tools/patterns.ts:61-95 (handler)Main handler for analyze_patterns tool. Dispatches to sub-handlers based on pattern_type: close_votes, government_defeats, or party_rebellion_rate.
export async function handlePatternsTool( name: string, args: Record<string, unknown> ): Promise<string> { try { if (name !== "analyze_patterns") { throw new Error(`Unknown tool: ${name}`); } const patternType = args.pattern_type as string; const house = (args.house as "Commons" | "Lords") ?? "Commons"; const days = (args.days as number) ?? 365; const maxDivisions = (args.max_divisions as number) ?? 100; const limit = (args.limit as number) ?? 20; const startDate = daysAgoISO(days); const summaries = await fetchDivisionSummaries(house, startDate, maxDivisions); if (patternType === "close_votes") { return handleCloseVotes(summaries, house, days, limit, args); } else if (patternType === "government_defeats") { return handleGovernmentDefeats(summaries, house, days, limit); } else if (patternType === "party_rebellion_rate") { return await handlePartyRebellionRate(summaries, house, days, limit); } else { throw new Error( `Unknown pattern_type: ${patternType}. Use 'close_votes', 'government_defeats', or 'party_rebellion_rate'.` ); } } catch (error) { const message = error instanceof Error ? error.message : "An unknown error occurred."; throw new Error(message); } } - src/tools/patterns.ts:18-57 (schema)Tool definition and input schema for analyze_patterns. Declares 'analyze_patterns' with enum pattern_type (close_votes, government_defeats, party_rebellion_rate), optional house (Commons/Lords), days, threshold, max_divisions, and limit.
export const patternsTools = [ { name: "analyze_patterns", description: "Detect patterns across many parliamentary votes: 'close_votes' finds divisions with a small margin (near-misses or knife-edge votes), 'government_defeats' finds votes the government lost, 'party_rebellion_rate' shows which parties rebel most by percentage of votes cast. Use for trend analysis across many divisions.", inputSchema: { type: "object", properties: { pattern_type: { type: "string", enum: ["close_votes", "government_defeats", "party_rebellion_rate"], description: "The pattern to detect.", }, house: { type: "string", enum: ["Commons", "Lords"], description: "Which house to analyse. Defaults to Commons.", }, days: { type: "number", description: "How many days back to scan. Default 365.", }, threshold: { type: "number", description: "For close_votes: maximum majority to count as close. Default 10.", }, max_divisions: { type: "number", description: "Maximum divisions to scan. Default 100.", }, limit: { type: "number", description: "Maximum results to return. Default 20.", }, }, required: ["pattern_type"], }, }, ]; - src/index.ts:11-12 (registration)Import of patternsTools and handlePatternsTool from patterns.ts module.
import { patternsTools, handlePatternsTool } from "./tools/patterns.js"; import { findTools, handleFindTool } from "./tools/find.js"; - src/index.ts:20-26 (registration)Registration of patternsTools (including analyze_patterns) into the allTools array for ListToolsRequestSchema.
const allTools = [ ...rankTools, ...eventsTools, ...patternsTools, ...findTools, ...queryTools, ]; - src/index.ts:37-38 (registration)Routing of 'analyze_patterns' tool name to handlePatternsTool in the CallToolRequestSchema handler.
else if (name === "analyze_patterns") result = await handlePatternsTool(name, safeArgs); else if (name === "find_entities") result = await handleFindTool(name, safeArgs);