# All files / src/tools getMEPDetails.ts

76.47% Statements 13/17
50% Branches 2/4
66.66% Functions 2/3
80% Lines 12/15

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

    12x
    12x

    6x
    9x
    6x

    6x
    6x

    4x

    4x

    2x

    2x

    4x

     /**
     * MCP Tool: get_mep_details
     *
     * Retrieve detailed information about a specific MEP
     *
     * **Intelligence Perspective:** Enables deep-dive MEP profiling including voting statistics,
     * committee memberships, political group alignment, and behavioral pattern analysis for
     * individual actor intelligence assessments.
     *
     * **Business Perspective:** Powers premium MEP profile products for corporate affairs teams,
     * lobbyists, and political consultancies requiring comprehensive stakeholder intelligence.
     *
     * **Marketing Perspective:** Demonstrates depth of EP data access—key differentiator
     * for attracting enterprise customers and academic researchers.
     *
     * ISMS Policy: SC-002 (Input Validation), AU-002 (Audit Logging), GDPR Compliance
     */

    import { GetMEPDetailsSchema, MEPDetailsSchema } from '../schemas/europeanParliament.js';
    import { epClient } from '../clients/europeanParliamentClient.js';
    import { buildToolResponse } from './shared/responseBuilder.js';
    import { ToolError } from './shared/errors.js';
    import { z } from 'zod';
    import type { ToolResult } from './shared/types.js';

    /**
     * Handles the get_mep_details MCP tool request.
     *
     * Retrieves comprehensive information about a single MEP identified by their unique ID,
     * including biography, contact details, committee memberships, voting statistics, and
     * parliamentary activities. Access to personal data is audit-logged for GDPR compliance.
     *
     * @param args - Raw tool arguments, validated against {@link GetMEPDetailsSchema}
     * @returns MCP tool result containing detailed MEP profile data including biography,
     *   contact information, committee roles, voting record, and activity statistics
     * @throws - If `args` fails schema validation (e.g., missing or empty `id` field)
     * - If the European Parliament API is unreachable or returns an error response
     *
     * @example
     * ```typescript
     * const result = await handleGetMEPDetails({ id: 'MEP-124810' });
     * // Returns full profile for MEP 124810, including committees and voting stats
     * ```
     *
     * @security Input is validated with Zod before any API call.
     *   Personal data (biography, contact info) access is audit-logged per GDPR Art. 5(2)
     *   and ISMS Policy AU-002. Data minimisation applied per GDPR Article 5(1)(c).
     * @since 0.8.0
     * @see {@link getMEPDetailsToolMetadata} for MCP schema registration
     * @see {@link handleGetMEPs} for listing MEPs and obtaining valid IDs
     */
    export async function handleGetMEPDetails(
      args: unknown
    ): Promise<ToolResult> {
      let params: ReturnType<typeof GetMEPDetailsSchema.parse>;
      try {
        params = GetMEPDetailsSchema.parse(args);
      } catch (error: unknown) {
        Eif (error instanceof z.ZodError) {
          const fieldErrors = error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join('; ');
          throw new ToolError({
            toolName: 'get_mep_details',
            operation: 'validateInput',
            message: `Invalid parameters: ${fieldErrors}`,
            isRetryable: false,
            cause: error,
          });
        }
        throw error;
      }

      try {
        const result = await epClient.getMEPDetails(params.id);

        const validated = MEPDetailsSchema.parse(result);

        return buildToolResponse(validated);
      } catch (error: unknown) {
        Iif (error instanceof z.ZodError) {
          const fieldErrors = error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join('; ');
          throw new ToolError({
            toolName: 'get_mep_details',
            operation: 'validateOutput',
            message: `Unexpected EP API response format: ${fieldErrors}`,
            isRetryable: false,
            cause: error,
          });
        }
        throw new ToolError({
          toolName: 'get_mep_details',
          operation: 'fetchData',
          message: 'Failed to retrieve MEP details',
          isRetryable: true,
          cause: error,
        });
      }
    }

    /**
     * Tool metadata for MCP registration
     */
    export const getMEPDetailsToolMetadata = {
      name: 'get_mep_details',
      description: 'Retrieve detailed information about a specific Member of European Parliament including biography, contact information, committee memberships, voting statistics, and parliamentary activities. Personal data access is logged for GDPR compliance.',
      inputSchema: {
        type: 'object' as const,
        properties: {
          id: {
            type: 'string',
            description: 'MEP identifier (e.g., "MEP-124810")',
            minLength: 1,
            maxLength: 100
          }
        },
        required: ['id']
      }
    };