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 | 35x 24x 6x 2x 3x 1x 24x 24x 5x 5x 2x 2x 2x 1x 4x 5x 4x 3x 3x 1x 3x 2x 4x 4x 3x | // SPDX-FileCopyrightText: 2024-2026 Hack23 AB
// SPDX-License-Identifier: Apache-2.0
/**
* @module MCP/imf/observations
* @description SDMX observation counting and MCP result-wrapping helpers.
*/
import type { MCPToolResult } from '../../types/index.js';
import type { SDMXObservationPayload } from './types.js';
/**
* Unwrap SDMX localised labels to a plain string.
*
* SDMX 3.0 sometimes returns `name`/`description` as a language-keyed
* object (`{ en: "World Economic Outlook" }`); older payloads return a
* raw string. Prefer English, fall back to the first available value.
* @param raw - Raw label value from SDMX API response.
* @returns Plain string, or empty string when `raw` is empty/undefined.
*/
export function unwrapLocalisedLabel(raw: string | Record<string, string> | undefined): string {
if (!raw) return '';
if (typeof raw === 'string') return raw;
if (typeof raw['en'] === 'string') return raw['en'];
for (const v of Object.values(raw)) {
if (typeof v === 'string') return v;
}
return '';
}
/**
* Wrap a JSON-serialisable value in the canonical MCP tool-result shape.
* @param payload - Any JSON-serialisable value to embed.
* @returns MCP tool result with `content[0].type === 'text'`.
*/
export function wrapAsMCPResult(payload: unknown): MCPToolResult {
const text = typeof payload === 'string' ? payload : JSON.stringify(payload ?? null);
return { content: [{ type: 'text', text }] };
}
/**
* Count observations in an IMF SDMX-JSON data payload.
*
* The IMF API can return observations either directly on a dataset or nested
* under `data.dataSets[].series[*].observations`.
*
* @param payload - Raw JSON string or already-parsed SDMX-JSON payload.
* @returns Number of observation cells found; `0` for invalid or empty input.
*/
export function countIMFSDMXObservations(payload: string | unknown): number {
let parsed: unknown = payload;
if (typeof payload === 'string') {
Iif (!payload.trim()) return 0;
try {
parsed = JSON.parse(payload);
} catch {
return 0;
}
}
const dataSets = (parsed as SDMXObservationPayload | null)?.data?.dataSets;
Iif (!Array.isArray(dataSets)) return 0;
return dataSets.reduce((total, dataSet) => {
let count = 0;
if (dataSet.observations && typeof dataSet.observations === 'object') {
count += Object.keys(dataSet.observations).length;
}
if (dataSet.series && typeof dataSet.series === 'object') {
for (const row of Object.values(dataSet.series)) {
Eif (row?.observations && typeof row.observations === 'object') {
count += Object.keys(row.observations).length;
}
}
}
return total + count;
}, 0);
}
|