# All files / src/tools getPlenaryDocuments.ts

94.44% Statements 17/18
83.33% Branches 5/6
100% Functions 2/2
93.75% Lines 15/16

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

    18x
    18x

    5x
    5x
    5x

    13x
    13x
    3x
    2x

    10x

    10x

    10x

    9x

    2x

    4x

     /**
     * MCP Tool: get_plenary_documents
     *
     * Retrieve European Parliament plenary documents, with optional single document lookup.
     *
     * **Intelligence Perspective:** Plenary documents contain legislative texts, reports,
     * and amendments central to policy analysis and legislative tracking.
     *
     * **Business Perspective:** Provides access to legislative outputs for compliance
     * monitoring and regulatory intelligence products.
     *
     * **EP API Endpoints:**
     * - `GET /plenary-documents` (list)
     * - `GET /plenary-documents/{doc-id}` (single)
     *
     * ISMS Policy: SC-002 (Input Validation), AC-003 (Least Privilege)
     */

    import { GetPlenaryDocumentsSchema } 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_plenary_documents MCP tool request.
     *
     * Retrieves European Parliament plenary documents including legislative texts, reports, and
     * amendments. Supports both single-document lookup by document ID and list retrieval with
     * optional year filtering. Central to policy analysis and legislative tracking workflows.
     *
     * @param args - Raw tool arguments, validated against {@link GetPlenaryDocumentsSchema}
     * @returns MCP tool result containing either a single plenary document (when `docId` is
     *   provided) or a paginated list of documents, optionally filtered by year
     * @throws - If `args` fails schema validation (e.g., limit out of range 1–100)
     * - If the European Parliament API is unreachable or returns an error response
     *
     * @example
     * ```typescript
     * // List documents for a specific year
     * const result = await handleGetPlenaryDocuments({ year: 2024, limit: 25 });
     * // Returns up to 25 plenary documents from 2024
     *
     * // Fetch a single document by ID
     * const single = await handleGetPlenaryDocuments({ docId: 'DOC-2024-001' });
     * // Returns the full plenary document record
     * ```
     *
     * @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 getPlenaryDocumentsToolMetadata} for MCP schema registration
     * @see {@link handleGetPlenarySessions} for the sessions associated with these documents
     * @see {@link handleGetPlenarySessionDocuments} for session-level agendas and minutes
     */
    export async function handleGetPlenaryDocuments(args: unknown): Promise<ToolResult> {
      let params: ReturnType<typeof GetPlenaryDocumentsSchema.parse>;
      try {
        params = GetPlenaryDocumentsSchema.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_plenary_documents',
            operation: 'validateInput',
            message: `Invalid parameters: ${fieldErrors}`,
            isRetryable: false,
            cause: error,
          });
        }
        throw error;
      }

      try {
        if (params.docId !== undefined) {
          const result = await epClient.getPlenaryDocumentById(params.docId);
          return buildToolResponse(result);
        }

        const apiParams: Record<string, unknown> = {
          limit: params.limit,
          offset: params.offset,
        };
        if (params.year !== undefined) apiParams['year'] = params.year;

        const result = await epClient.getPlenaryDocuments(
          apiParams
        );

        return buildToolResponse(result);
      } catch (error: unknown) {
        throw new ToolError({
          toolName: 'get_plenary_documents',
          operation: 'fetchData',
          message: 'Failed to retrieve plenary documents',
          isRetryable: true,
          cause: error,
        });
      }
    }
    /** Tool metadata for get_plenary_documents */
    export const getPlenaryDocumentsToolMetadata = {
      name: 'get_plenary_documents',
      description:
        'Get European Parliament plenary documents. Supports single document lookup by docId or list with year filter. Data source: European Parliament Open Data Portal.',
      inputSchema: {
        type: 'object' as const,
        properties: {
          docId: { type: 'string', description: 'Document ID for single document lookup' },
          year: { type: 'number', description: 'Filter by year' },
          limit: { type: 'number', description: 'Maximum results to return (1-100)', default: 50 },
          offset: { type: 'number', description: 'Pagination offset', default: 0 },
        },
      },
    };