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 | 14x 13x 13x 1x 1x 1x 1x 1x 1x 1x 19x 19x 5x 5x 5x 14x 14x 14x 13x 4x 3x 9x 8x 2x 4x | /**
* MCP Tool: get_controlled_vocabularies
*
* Retrieve European Parliament controlled vocabularies, with optional single vocabulary lookup.
*
* **Intelligence Perspective:** Controlled vocabularies define standardized terms used
* across EP data—essential for accurate query construction and data interpretation.
*
* **Business Perspective:** Vocabulary data enables proper classification and
* categorization in data products.
*
* **EP API Endpoints:**
* - `GET /controlled-vocabularies` (list)
* - `GET /controlled-vocabularies/{voc-id}` (single)
*
* ISMS Policy: SC-002 (Input Validation), AC-003 (Least Privilege)
*/
import { GetControlledVocabulariesSchema } 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';
import { loadWeeklyVocabulariesCache } from '../utils/weeklyDataCache.js';
type GetControlledVocabulariesParams = ReturnType<typeof GetControlledVocabulariesSchema.parse>;
async function getCachedVocabularyResponse(params: GetControlledVocabulariesParams): Promise<ToolResult | null> {
if (params.live) return null;
const cached = await loadWeeklyVocabulariesCache();
if (cached === null) return null;
Eif (params.vocId !== undefined) {
const fromDetails = cached.vocabularyDetails?.[params.vocId];
Iif (fromDetails !== undefined) return buildToolResponse(fromDetails);
const vocabulary = cached.vocabularies.find((item) => {
const id = item['id'];
return typeof id === 'string' && id === params.vocId;
});
return vocabulary !== undefined ? buildToolResponse(vocabulary) : null;
}
const paged = cached.vocabularies.slice(params.offset, params.offset + params.limit);
return buildToolResponse({
data: paged,
total: cached.vocabularies.length,
limit: params.limit,
offset: params.offset,
hasMore: params.offset + paged.length < cached.vocabularies.length,
});
}
/**
* Handles the get_controlled_vocabularies MCP tool request.
*
* Retrieves European Parliament controlled vocabularies—standardised classification terms
* used across EP datasets. Supports both a paginated list view and a single-vocabulary
* lookup when `vocId` is provided. These vocabularies are essential for accurate query
* construction and data interpretation across other EP API tools.
*
* @param args - Raw tool arguments, validated against {@link GetControlledVocabulariesSchema}
* @returns MCP tool result containing vocabulary data (single vocabulary or paginated list)
* @throws - If `args` fails schema validation (e.g., invalid field types or formats)
* - If the European Parliament API is unreachable or returns an error response
*
* @example
* ```typescript
* // Single vocabulary lookup
* const single = await handleGetControlledVocabularies({ vocId: 'activities-type' });
* // Returns the controlled vocabulary for activity types
*
* // List all vocabularies
* const list = await handleGetControlledVocabularies({ limit: 50, offset: 0 });
* // Returns up to 50 controlled vocabulary entries
* ```
*
* @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 getControlledVocabulariesToolMetadata} for MCP schema registration
* @see {@link handleSearchDocuments} for tools that consume vocabulary terms as filter values
*/
export async function handleGetControlledVocabularies(args: unknown): Promise<ToolResult> {
let params: GetControlledVocabulariesParams;
try {
params = GetControlledVocabulariesSchema.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_controlled_vocabularies',
operation: 'validateInput',
message: `Invalid parameters: ${fieldErrors}`,
isRetryable: false,
cause: error,
});
}
throw error;
}
try {
const cachedResponse = await getCachedVocabularyResponse(params);
if (cachedResponse !== null) return cachedResponse;
if (params.vocId !== undefined) {
const result = await epClient.getControlledVocabularyById(params.vocId);
return buildToolResponse(result);
}
const result = await epClient.getControlledVocabularies({
limit: params.limit,
offset: params.offset,
});
return buildToolResponse(result);
} catch (error: unknown) {
throw new ToolError({
toolName: 'get_controlled_vocabularies',
operation: 'fetchData',
message: 'Failed to retrieve controlled vocabularies',
isRetryable: true,
cause: error,
});
}
}
/** Tool metadata for get_controlled_vocabularies */
export const getControlledVocabulariesToolMetadata = {
name: 'get_controlled_vocabularies',
description:
'Get European Parliament controlled vocabularies (standardized classification terms). Supports single vocabulary lookup by vocId. Data source: European Parliament Open Data Portal.',
inputSchema: {
type: 'object' as const,
properties: {
vocId: { type: 'string', description: 'Vocabulary ID for single vocabulary lookup' },
limit: { type: 'number', description: 'Maximum results to return (1-100)', default: 50 },
offset: { type: 'number', description: 'Pagination offset', default: 0 },
live: {
type: 'boolean',
description: 'When true, bypasses weekly cache and fetches directly from the live EP API.',
default: false,
},
},
},
};
|