Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | 27x 27x 27x 27x 19x 19x 19x 27x 4x 4x 4x | /**
* MCP Tool: get_voting_records
*
* Retrieve voting records from European Parliament plenary sessions
*
* **Intelligence Perspective:** Core intelligence product for voting pattern analysis,
* political group cohesion measurement, cross-party alliance detection, and MEP
* loyalty/independence scoring through structured analytic techniques.
*
* **Business Perspective:** High-value data product for political risk assessment firms,
* policy analysis consultancies, and corporate government affairs departments.
*
* **Marketing Perspective:** Most compelling data for data journalism partnerships,
* academic research collaborations, and transparency advocacy organizations.
*
* ISMS Policy: SC-002 (Input Validation), AC-003 (Least Privilege)
*/
import { GetVotingRecordsSchema, VotingRecordSchema, PaginatedResponseSchema } from '../schemas/europeanParliament.js';
import { epClient } from '../clients/europeanParliamentClient.js';
import { buildApiParams } from './shared/paramBuilder.js';
import type { ToolResult } from './shared/types.js';
/**
* Handles the get_voting_records MCP tool request.
*
* Retrieves voting records from European Parliament plenary sessions, supporting
* filtering by session, MEP, topic, and date range. Returns vote tallies
* (for/against/abstain), final results, and optionally individual MEP votes.
*
* @param args - Raw tool arguments, validated against {@link GetVotingRecordsSchema}
* @returns MCP tool result containing a paginated list of voting records with vote counts and results
* @throws - If `args` fails schema validation (e.g., missing required fields or invalid format)
* - If the European Parliament API is unreachable or returns an error response
*
* @example
* ```typescript
* const result = await handleGetVotingRecords({
* sessionId: 'PLENARY-2024-01',
* topic: 'Climate Change',
* limit: 20
* });
* // Returns voting records for the January 2024 plenary session on climate topics
* ```
*
* @security - Input is validated with Zod before any API call.
* - Personal data in responses is minimised per GDPR Article 5(1)(c).
* - All requests are rate-limited and audit-logged per ISMS Policy AU-002.
* @since 0.8.0
* @see {@link getVotingRecordsToolMetadata} for MCP schema registration
* @see [handleGetMeetingDecisions](../../getMeetingDecisions/functions/handleGetMeetingDecisions.md) for retrieving decisions linked to a specific sitting
*/
export async function handleGetVotingRecords(
args: unknown
): Promise<ToolResult> {
// Validate input
const params = GetVotingRecordsSchema.parse(args);
try {
// Fetch voting records from EP API (only pass defined properties)
const apiParams = {
limit: params.limit,
offset: params.offset,
...buildApiParams(params, [
{ from: 'sessionId', to: 'sessionId' },
{ from: 'mepId', to: 'mepId' },
{ from: 'topic', to: 'topic' },
{ from: 'dateFrom', to: 'dateFrom' },
{ from: 'dateTo', to: 'dateTo' },
]),
};
const result = await epClient.getVotingRecords(apiParams as Parameters<typeof epClient.getVotingRecords>[0]);
// Validate output
const outputSchema = PaginatedResponseSchema(VotingRecordSchema);
const validated = outputSchema.parse(result);
// Note: `_warning` is a meta-field added after Zod validation and is
// intentionally not part of the Zod output schema.
const responsePayload = {
...validated,
_warning:
params['mepId'] !== undefined
? 'The mepId parameter is not supported by the EP API and has no effect on results. ' +
'The EP votes endpoint only returns aggregate vote counts, not per-MEP positions.'
: undefined
};
// Return MCP-compliant response
return {
content: [{
type: 'text',
text: JSON.stringify(responsePayload, null, 2)
}]
};
} catch (error) {
// Handle errors without exposing internal details
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
throw new Error(`Failed to retrieve voting records: ${errorMessage}`);
}
}
/**
* Tool metadata for MCP registration
*/
export const getVotingRecordsToolMetadata = {
name: 'get_voting_records',
description: 'Retrieve voting records from European Parliament plenary sessions. Filter by session, MEP, topic, or date range. Returns vote counts (for/against/abstain), final result, and optionally individual MEP votes.',
inputSchema: {
type: 'object' as const,
properties: {
sessionId: {
type: 'string',
description: 'Plenary session identifier',
minLength: 1,
maxLength: 100
},
mepId: {
type: 'string',
description: 'MEP identifier to filter votes by specific MEP',
minLength: 1,
maxLength: 100
},
topic: {
type: 'string',
description: 'Vote topic or keyword to search',
minLength: 1,
maxLength: 200
},
dateFrom: {
type: 'string',
description: 'Start date filter (YYYY-MM-DD format)',
pattern: '^\\d{4}-\\d{2}-\\d{2}$'
},
dateTo: {
type: 'string',
description: 'End date filter (YYYY-MM-DD format)',
pattern: '^\\d{4}-\\d{2}-\\d{2}$'
},
limit: {
type: 'number',
description: 'Maximum number of results to return (1-100)',
minimum: 1,
maximum: 100,
default: 50
},
offset: {
type: 'number',
description: 'Pagination offset',
minimum: 0,
default: 0
}
}
}
};
|