@cyanheads/imf-mcp-server 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/AGENTS.md +377 -0
  2. package/CLAUDE.md +377 -0
  3. package/Dockerfile +105 -0
  4. package/LICENSE +201 -0
  5. package/README.md +290 -0
  6. package/changelog/0.1.x/0.1.1.md +33 -0
  7. package/changelog/template.md +127 -0
  8. package/dist/config/server-config.d.ts +13 -0
  9. package/dist/config/server-config.d.ts.map +1 -0
  10. package/dist/config/server-config.js +26 -0
  11. package/dist/config/server-config.js.map +1 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +28 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/mcp-server/prompts/definitions/index.d.ts +7 -0
  17. package/dist/mcp-server/prompts/definitions/index.d.ts.map +1 -0
  18. package/dist/mcp-server/prompts/definitions/index.js +7 -0
  19. package/dist/mcp-server/prompts/definitions/index.js.map +1 -0
  20. package/dist/mcp-server/resources/definitions/imf-database.resource.d.ts +9 -0
  21. package/dist/mcp-server/resources/definitions/imf-database.resource.d.ts.map +1 -0
  22. package/dist/mcp-server/resources/definitions/imf-database.resource.js +61 -0
  23. package/dist/mcp-server/resources/definitions/imf-database.resource.js.map +1 -0
  24. package/dist/mcp-server/resources/definitions/index.d.ts +9 -0
  25. package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -0
  26. package/dist/mcp-server/resources/definitions/index.js +8 -0
  27. package/dist/mcp-server/resources/definitions/index.js.map +1 -0
  28. package/dist/mcp-server/tools/definitions/imf-dataframe-describe.tool.d.ts +26 -0
  29. package/dist/mcp-server/tools/definitions/imf-dataframe-describe.tool.d.ts.map +1 -0
  30. package/dist/mcp-server/tools/definitions/imf-dataframe-describe.tool.js +96 -0
  31. package/dist/mcp-server/tools/definitions/imf-dataframe-describe.tool.js.map +1 -0
  32. package/dist/mcp-server/tools/definitions/imf-dataframe-query.tool.d.ts +24 -0
  33. package/dist/mcp-server/tools/definitions/imf-dataframe-query.tool.d.ts.map +1 -0
  34. package/dist/mcp-server/tools/definitions/imf-dataframe-query.tool.js +96 -0
  35. package/dist/mcp-server/tools/definitions/imf-dataframe-query.tool.js.map +1 -0
  36. package/dist/mcp-server/tools/definitions/imf-get-database.tool.d.ts +39 -0
  37. package/dist/mcp-server/tools/definitions/imf-get-database.tool.d.ts.map +1 -0
  38. package/dist/mcp-server/tools/definitions/imf-get-database.tool.js +155 -0
  39. package/dist/mcp-server/tools/definitions/imf-get-database.tool.js.map +1 -0
  40. package/dist/mcp-server/tools/definitions/imf-list-databases.tool.d.ts +19 -0
  41. package/dist/mcp-server/tools/definitions/imf-list-databases.tool.d.ts.map +1 -0
  42. package/dist/mcp-server/tools/definitions/imf-list-databases.tool.js +88 -0
  43. package/dist/mcp-server/tools/definitions/imf-list-databases.tool.js.map +1 -0
  44. package/dist/mcp-server/tools/definitions/imf-query-dataset.tool.d.ts +57 -0
  45. package/dist/mcp-server/tools/definitions/imf-query-dataset.tool.d.ts.map +1 -0
  46. package/dist/mcp-server/tools/definitions/imf-query-dataset.tool.js +277 -0
  47. package/dist/mcp-server/tools/definitions/imf-query-dataset.tool.js.map +1 -0
  48. package/dist/mcp-server/tools/definitions/index.d.ts +136 -0
  49. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
  50. package/dist/mcp-server/tools/definitions/index.js +22 -0
  51. package/dist/mcp-server/tools/definitions/index.js.map +1 -0
  52. package/dist/services/canvas/canvas-accessor.d.ts +11 -0
  53. package/dist/services/canvas/canvas-accessor.d.ts.map +1 -0
  54. package/dist/services/canvas/canvas-accessor.js +13 -0
  55. package/dist/services/canvas/canvas-accessor.js.map +1 -0
  56. package/dist/services/imf-sdmx/imf-sdmx-service.d.ts +38 -0
  57. package/dist/services/imf-sdmx/imf-sdmx-service.d.ts.map +1 -0
  58. package/dist/services/imf-sdmx/imf-sdmx-service.js +415 -0
  59. package/dist/services/imf-sdmx/imf-sdmx-service.js.map +1 -0
  60. package/dist/services/imf-sdmx/types.d.ts +157 -0
  61. package/dist/services/imf-sdmx/types.d.ts.map +1 -0
  62. package/dist/services/imf-sdmx/types.js +6 -0
  63. package/dist/services/imf-sdmx/types.js.map +1 -0
  64. package/package.json +106 -0
  65. package/server.json +99 -0
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @fileoverview Tool: imf_get_database — fetch a dataflow's dimension list and codelists.
3
+ * @module mcp-server/tools/definitions/imf-get-database.tool
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getImfSdmxService } from '../../../services/imf-sdmx/imf-sdmx-service.js';
8
+ const MAX_CODELIST_ENTRIES = 50;
9
+ export const imfGetDatabase = tool('imf_get_database', {
10
+ description: "Fetch a dataflow's dimension list and complete codelist for each dimension. " +
11
+ 'Resolves human-readable terms to SDMX codes (e.g. "United States" → USA, ' +
12
+ '"real GDP growth" → NGDP_RPCH). ' +
13
+ 'Required before imf_query_dataset — SDMX keys are opaque without codelist lookups. ' +
14
+ 'Country codes are ISO 3-letter (USA, GBR, DEU), not ISO 2-letter (US, GB, DE). ' +
15
+ 'The key_format field shows the exact dimension order required by imf_query_dataset.',
16
+ annotations: {
17
+ readOnlyHint: true,
18
+ idempotentHint: true,
19
+ openWorldHint: false,
20
+ },
21
+ input: z.object({
22
+ dataflow_id: z
23
+ .string()
24
+ .describe('Dataflow identifier from imf_list_databases, e.g. WEO, BOP, CPI. ' + 'Case-sensitive.'),
25
+ agency_id: z
26
+ .string()
27
+ .optional()
28
+ .describe('Agency ID that publishes this dataflow, e.g. IMF.RES or IMF.STA. ' +
29
+ 'Auto-detected from the dataflow list when omitted.'),
30
+ version: z
31
+ .string()
32
+ .optional()
33
+ .describe('Dataflow version, e.g. 9.0.0. Auto-detected from the dataflow list when omitted.'),
34
+ }),
35
+ output: z.object({
36
+ dataflow_id: z.string().describe('Dataflow identifier, e.g. WEO, BOP, CPI.'),
37
+ agency_id: z.string().describe('Agency that publishes this dataflow, e.g. IMF.RES, IMF.STA.'),
38
+ version: z.string().describe('Dataflow version string, e.g. 9.0.0.'),
39
+ name: z.string().describe('Human-readable dataflow name.'),
40
+ description: z.string().optional().describe('Extended description, if available.'),
41
+ key_format: z
42
+ .string()
43
+ .describe('Dimension names in dot-separated keyPosition order, e.g. COUNTRY.INDICATOR.FREQUENCY. ' +
44
+ 'Use this exact format when constructing the key for imf_query_dataset.'),
45
+ dimensions: z
46
+ .array(z
47
+ .object({
48
+ id: z.string().describe('Dimension identifier used in the key, e.g. COUNTRY.'),
49
+ name: z.string().describe('Human-readable dimension name.'),
50
+ position: z.number().describe('Zero-based position in the key string.'),
51
+ codelist: z
52
+ .array(z
53
+ .object({
54
+ id: z.string().describe('Machine code for this dimension value, e.g. USA.'),
55
+ name: z
56
+ .string()
57
+ .describe('Human-readable label for this value, e.g. United States.'),
58
+ })
59
+ .describe('A single codelist entry: machine code and human-readable name.'))
60
+ .describe('Valid codes for this dimension. ' +
61
+ `Up to ${MAX_CODELIST_ENTRIES} entries shown; full list available via the imf://database resource.`),
62
+ codelist_truncated: z
63
+ .boolean()
64
+ .describe(`True when the codelist has more than ${MAX_CODELIST_ENTRIES} entries and was truncated.`),
65
+ })
66
+ .describe('A single dimension with its codelist.'))
67
+ .describe('All dimensions of this dataflow with their codelists.'),
68
+ }),
69
+ errors: [
70
+ {
71
+ reason: 'dataflow_not_found',
72
+ code: JsonRpcErrorCode.NotFound,
73
+ when: 'dataflow_id does not match any known dataflow on api.imf.org',
74
+ recovery: 'Call imf_list_databases to browse available dataflow IDs.',
75
+ },
76
+ {
77
+ reason: 'structure_unavailable',
78
+ code: JsonRpcErrorCode.ServiceUnavailable,
79
+ when: 'api.imf.org returns non-200 on the DSD endpoint',
80
+ recovery: 'Retry after a short wait; the IMF SDMX 3.0 portal is occasionally slow.',
81
+ },
82
+ ],
83
+ async handler(input, ctx) {
84
+ const svc = getImfSdmxService();
85
+ const dataflow = await svc.findDataflow(input.dataflow_id, input.agency_id, input.version, ctx);
86
+ if (!dataflow) {
87
+ throw ctx.fail('dataflow_not_found', `Dataflow '${input.dataflow_id}' not found`, {
88
+ dataflowId: input.dataflow_id,
89
+ ...ctx.recoveryFor('dataflow_not_found'),
90
+ });
91
+ }
92
+ let structure;
93
+ try {
94
+ structure = await svc.fetchDataflowStructure(input.dataflow_id, input.agency_id ?? dataflow.agencyId, input.version ?? dataflow.version, ctx);
95
+ }
96
+ catch (err) {
97
+ const msg = err instanceof Error ? err.message : String(err);
98
+ if (msg.includes('not found')) {
99
+ throw ctx.fail('dataflow_not_found', msg, ctx.recoveryFor('dataflow_not_found'));
100
+ }
101
+ throw ctx.fail('structure_unavailable', msg, ctx.recoveryFor('structure_unavailable'));
102
+ }
103
+ ctx.log.info('Dataflow structure fetched', {
104
+ dataflowId: input.dataflow_id,
105
+ dimensions: structure.dimensions.length,
106
+ });
107
+ const dimensions = structure.dimensions.map((dim) => {
108
+ const truncated = dim.codelist.length > MAX_CODELIST_ENTRIES;
109
+ return {
110
+ id: dim.id,
111
+ name: dim.name,
112
+ position: dim.position,
113
+ codelist: dim.codelist.slice(0, MAX_CODELIST_ENTRIES),
114
+ codelist_truncated: truncated,
115
+ };
116
+ });
117
+ return {
118
+ dataflow_id: structure.dataflowId,
119
+ agency_id: structure.agencyId,
120
+ version: structure.version,
121
+ name: structure.name,
122
+ ...(structure.description ? { description: structure.description } : {}),
123
+ key_format: structure.keyFormat,
124
+ dimensions,
125
+ };
126
+ },
127
+ format: (result) => {
128
+ const lines = [];
129
+ lines.push(`## ${result.name}`);
130
+ lines.push(`**Dataflow:** ${result.dataflow_id} | **Agency:** ${result.agency_id} | **Version:** ${result.version}`);
131
+ if (result.description)
132
+ lines.push(`\n${result.description}`);
133
+ lines.push(`\n**Key format:** \`${result.key_format}\``);
134
+ lines.push('\n### Dimensions\n');
135
+ for (const dim of result.dimensions) {
136
+ lines.push(`#### ${dim.id} (position ${dim.position})`);
137
+ lines.push(`**Name:** ${dim.name}`);
138
+ if (dim.codelist.length > 0) {
139
+ lines.push('**Codes:**');
140
+ for (const code of dim.codelist) {
141
+ lines.push(`- \`${code.id}\` — ${code.name}`);
142
+ }
143
+ if (dim.codelist_truncated) {
144
+ lines.push(`_(truncated at ${MAX_CODELIST_ENTRIES} entries)_`);
145
+ }
146
+ }
147
+ else {
148
+ lines.push('_(no codelist entries available)_');
149
+ }
150
+ lines.push('');
151
+ }
152
+ return [{ type: 'text', text: lines.join('\n') }];
153
+ },
154
+ });
155
+ //# sourceMappingURL=imf-get-database.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imf-get-database.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/imf-get-database.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @fileoverview Tool: imf_list_databases — list all IMF SDMX dataflows available on the portal.
3
+ * @module mcp-server/tools/definitions/imf-list-databases.tool
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ export declare const imfListDatabases: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
7
+ filter: z.ZodOptional<z.ZodString>;
8
+ include_vintages: z.ZodDefault<z.ZodBoolean>;
9
+ }, z.core.$strip>, z.ZodObject<{
10
+ dataflows: z.ZodArray<z.ZodObject<{
11
+ id: z.ZodString;
12
+ agency_id: z.ZodString;
13
+ version: z.ZodString;
14
+ name: z.ZodString;
15
+ description: z.ZodOptional<z.ZodString>;
16
+ }, z.core.$strip>>;
17
+ total_count: z.ZodNumber;
18
+ }, z.core.$strip>, undefined, undefined>;
19
+ //# sourceMappingURL=imf-list-databases.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imf-list-databases.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/imf-list-databases.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAKjD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;wCAiG3B,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @fileoverview Tool: imf_list_databases — list all IMF SDMX dataflows available on the portal.
3
+ * @module mcp-server/tools/definitions/imf-list-databases.tool
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { getImfSdmxService } from '../../../services/imf-sdmx/imf-sdmx-service.js';
7
+ const VINTAGE_PATTERN = /VINTAGE/i;
8
+ export const imfListDatabases = tool('imf_list_databases', {
9
+ description: 'List all IMF SDMX dataflows available on the portal (193 total). ' +
10
+ 'Entry point for every query: imf_get_database and imf_query_dataset both require a dataflow id obtained here. ' +
11
+ 'Vintage (historical snapshot) dataflows such as WEO_2025_OCT_VINTAGE are excluded by default; set include_vintages=true to include them.',
12
+ annotations: {
13
+ readOnlyHint: true,
14
+ idempotentHint: true,
15
+ openWorldHint: false,
16
+ },
17
+ input: z.object({
18
+ filter: z
19
+ .string()
20
+ .optional()
21
+ .describe('Optional name or ID substring to filter results. Case-insensitive. ' +
22
+ 'Example: "exchange rate" returns ER and related dataflows.'),
23
+ include_vintages: z
24
+ .boolean()
25
+ .default(false)
26
+ .describe('Include vintage (historical snapshot) dataflows such as WEO_2025_OCT_VINTAGE. ' +
27
+ 'Default false — vintages are excluded to keep the discovery surface clean.'),
28
+ }),
29
+ output: z.object({
30
+ dataflows: z
31
+ .array(z
32
+ .object({
33
+ id: z.string().describe('Dataflow identifier, e.g. WEO, BOP, CPI.'),
34
+ agency_id: z.string().describe('Agency that publishes this dataflow, e.g. IMF.RES.'),
35
+ version: z.string().describe('Dataflow version, e.g. 9.0.0.'),
36
+ name: z.string().describe('Human-readable dataflow name.'),
37
+ description: z
38
+ .string()
39
+ .optional()
40
+ .describe('Extended description of the dataflow, if available.'),
41
+ })
42
+ .describe('A single IMF SDMX dataflow entry.'))
43
+ .describe('Matching dataflows; pass the id to imf_get_database to resolve dimension codelists.'),
44
+ total_count: z.number().describe('Total number of matching dataflows returned.'),
45
+ }),
46
+ async handler(input, ctx) {
47
+ const svc = getImfSdmxService();
48
+ let dataflows = await svc.fetchDataflows(ctx);
49
+ // Filter vintages
50
+ if (!input.include_vintages) {
51
+ dataflows = dataflows.filter((df) => !VINTAGE_PATTERN.test(df.id));
52
+ }
53
+ // Name/ID substring filter
54
+ const filterLower = input.filter?.toLowerCase().trim();
55
+ if (filterLower) {
56
+ dataflows = dataflows.filter((df) => df.id.toLowerCase().includes(filterLower) ||
57
+ df.name.toLowerCase().includes(filterLower) ||
58
+ (df.description?.toLowerCase().includes(filterLower) ?? false));
59
+ }
60
+ ctx.log.info('Dataflows listed', { count: dataflows.length, filter: input.filter });
61
+ const result = {
62
+ dataflows: dataflows.map((df) => ({
63
+ id: df.id,
64
+ agency_id: df.agencyId,
65
+ version: df.version,
66
+ name: df.name,
67
+ ...(df.description ? { description: df.description } : {}),
68
+ })),
69
+ total_count: dataflows.length,
70
+ };
71
+ return result;
72
+ },
73
+ format: (result) => {
74
+ const lines = [
75
+ `**${result.total_count} dataflow${result.total_count === 1 ? '' : 's'}**\n`,
76
+ ];
77
+ for (const df of result.dataflows) {
78
+ lines.push(`### ${df.id}`);
79
+ lines.push(`**Agency:** ${df.agency_id} | **Version:** ${df.version}`);
80
+ lines.push(`**Name:** ${df.name}`);
81
+ if (df.description)
82
+ lines.push(df.description);
83
+ lines.push('');
84
+ }
85
+ return [{ type: 'text', text: lines.join('\n') }];
86
+ },
87
+ });
88
+ //# sourceMappingURL=imf-list-databases.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imf-list-databases.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/imf-list-databases.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE5E,MAAM,eAAe,GAAG,UAAU,CAAC;AAEnC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE;IACzD,WAAW,EACT,mEAAmE;QACnE,gHAAgH;QAChH,0IAA0I;IAC5I,WAAW,EAAE;QACX,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,KAAK;KACrB;IACD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,qEAAqE;YACnE,4DAA4D,CAC/D;QACH,gBAAgB,EAAE,CAAC;aAChB,OAAO,EAAE;aACT,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CACP,gFAAgF;YAC9E,4EAA4E,CAC/E;KACJ,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,SAAS,EAAE,CAAC;aACT,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;YACnE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oDAAoD,CAAC;YACpF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC7D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC1D,WAAW,EAAE,CAAC;iBACX,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,qDAAqD,CAAC;SACnE,CAAC;aACD,QAAQ,CAAC,mCAAmC,CAAC,CACjD;aACA,QAAQ,CACP,qFAAqF,CACtF;QACH,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;KACjF,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;QAChC,IAAI,SAAS,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAE9C,kBAAkB;QAClB,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;YAC5B,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACrE,CAAC;QAED,2BAA2B;QAC3B,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QACvD,IAAI,WAAW,EAAE,CAAC;YAChB,SAAS,GAAG,SAAS,CAAC,MAAM,CAC1B,CAAC,EAAE,EAAE,EAAE,CACL,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;gBACzC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAC3C,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,CACjE,CAAC;QACJ,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAEpF,MAAM,MAAM,GAAG;YACb,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAChC,EAAE,EAAE,EAAE,CAAC,EAAE;gBACT,SAAS,EAAE,EAAE,CAAC,QAAQ;gBACtB,OAAO,EAAE,EAAE,CAAC,OAAO;gBACnB,IAAI,EAAE,EAAE,CAAC,IAAI;gBACb,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D,CAAC,CAAC;YACH,WAAW,EAAE,SAAS,CAAC,MAAM;SAC9B,CAAC;QAEF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa;YACtB,KAAK,MAAM,CAAC,WAAW,YAAY,MAAM,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM;SAC7E,CAAC;QACF,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,SAAS,mBAAmB,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YACvE,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YACnC,IAAI,EAAE,CAAC,WAAW;gBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @fileoverview Tool: imf_query_dataset — query a dataflow by dimension key over a time range.
3
+ * Large result sets spill to DataCanvas for SQL analysis.
4
+ * @module mcp-server/tools/definitions/imf-query-dataset.tool
5
+ */
6
+ import { z } from '@cyanheads/mcp-ts-core';
7
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
8
+ export declare const imfQueryDataset: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
9
+ dataflow_id: z.ZodString;
10
+ agency_id: z.ZodOptional<z.ZodString>;
11
+ version: z.ZodOptional<z.ZodString>;
12
+ key: z.ZodString;
13
+ start_period: z.ZodOptional<z.ZodString>;
14
+ end_period: z.ZodOptional<z.ZodString>;
15
+ canvas_id: z.ZodOptional<z.ZodString>;
16
+ }, z.core.$strip>, z.ZodObject<{
17
+ dataflow_id: z.ZodString;
18
+ key: z.ZodString;
19
+ start_period: z.ZodOptional<z.ZodString>;
20
+ end_period: z.ZodOptional<z.ZodString>;
21
+ observations: z.ZodArray<z.ZodObject<{
22
+ series_key: z.ZodString;
23
+ time_period: z.ZodString;
24
+ value: z.ZodNullable<z.ZodNumber>;
25
+ status: z.ZodNullable<z.ZodString>;
26
+ }, z.core.$strip>>;
27
+ series_attributes: z.ZodObject<{
28
+ unit: z.ZodNullable<z.ZodString>;
29
+ scale: z.ZodNullable<z.ZodString>;
30
+ decimals: z.ZodNullable<z.ZodNumber>;
31
+ }, z.core.$strip>;
32
+ observation_count: z.ZodNumber;
33
+ truncated: z.ZodBoolean;
34
+ canvas_id: z.ZodOptional<z.ZodString>;
35
+ table_name: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>, readonly [{
37
+ readonly reason: "dataflow_not_found";
38
+ readonly code: JsonRpcErrorCode.NotFound;
39
+ readonly when: "dataflow_id does not match any known dataflow on api.imf.org";
40
+ readonly recovery: "Call imf_list_databases to browse available dataflow IDs.";
41
+ }, {
42
+ readonly reason: "no_data";
43
+ readonly code: JsonRpcErrorCode.NotFound;
44
+ readonly when: "Key is structurally valid but returns an empty dataset — typically an unknown dimension code or no data for the time range";
45
+ readonly recovery: "Verify dimension codes with imf_get_database; check that start_period/end_period overlap available data.";
46
+ }, {
47
+ readonly reason: "key_dimension_mismatch";
48
+ readonly code: JsonRpcErrorCode.InvalidParams;
49
+ readonly when: "Number of dot-separated segments in key does not match the dataflow's DSD dimension count";
50
+ readonly recovery: "Call imf_get_database to get the correct key_format for this dataflow, then reconstruct the key.";
51
+ }, {
52
+ readonly reason: "structure_unavailable";
53
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
54
+ readonly when: "api.imf.org returns non-200 on the data endpoint";
55
+ readonly recovery: "Retry after a short wait.";
56
+ }], undefined>;
57
+ //# sourceMappingURL=imf-query-dataset.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imf-query-dataset.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/imf-query-dataset.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAMjE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkV1B,CAAC"}
@@ -0,0 +1,277 @@
1
+ /**
2
+ * @fileoverview Tool: imf_query_dataset — query a dataflow by dimension key over a time range.
3
+ * Large result sets spill to DataCanvas for SQL analysis.
4
+ * @module mcp-server/tools/definitions/imf-query-dataset.tool
5
+ */
6
+ import { tool, z } from '@cyanheads/mcp-ts-core';
7
+ import { spillover } from '@cyanheads/mcp-ts-core/canvas';
8
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
9
+ import { getCanvas } from '../../../services/canvas/canvas-accessor.js';
10
+ import { getImfSdmxService } from '../../../services/imf-sdmx/imf-sdmx-service.js';
11
+ const PREVIEW_CHARS = 100_000;
12
+ export const imfQueryDataset = tool('imf_query_dataset', {
13
+ description: 'Query an IMF SDMX dataflow by dimension key over a time range. ' +
14
+ 'Returns observations with time_period, value, unit, scale, and status attributes. ' +
15
+ 'Requires imf_get_database first to obtain the correct key_format and valid dimension codes. ' +
16
+ 'Country codes are ISO 3-letter (USA, GBR, DEU — not US, GB, DE). ' +
17
+ 'Key format: dot-separated codes in DSD keyPosition order (e.g. USA.NGDP_RPCH.A for WEO). ' +
18
+ 'Use + to specify multiple codes per position (e.g. USA+GBR.NGDP_RPCH.A). ' +
19
+ 'Large analytical result sets (multi-country, long time range) spill to DataCanvas; ' +
20
+ 'imf_dataframe_query provides SQL analysis of spilled results.',
21
+ annotations: {
22
+ readOnlyHint: true,
23
+ idempotentHint: true,
24
+ openWorldHint: true,
25
+ },
26
+ input: z.object({
27
+ dataflow_id: z
28
+ .string()
29
+ .describe('Dataflow identifier from imf_list_databases, e.g. WEO, BOP, CPI.'),
30
+ agency_id: z
31
+ .string()
32
+ .optional()
33
+ .describe('Agency ID, e.g. IMF.RES or IMF.STA. Auto-detected from dataflow list when omitted.'),
34
+ version: z
35
+ .string()
36
+ .optional()
37
+ .describe('Dataflow version. Auto-detected from dataflow list when omitted.'),
38
+ key: z
39
+ .string()
40
+ .describe('Dot-separated dimension codes in DSD keyPosition order. ' +
41
+ 'Call imf_get_database to get key_format and valid codes first. ' +
42
+ 'Use + to specify multiple codes (e.g. USA+GBR.NGDP_RPCH.A). ' +
43
+ 'Country codes are ISO 3-letter: USA not US, GBR not GB, DEU not DE.'),
44
+ start_period: z
45
+ .string()
46
+ .optional()
47
+ .describe('Requested start of time range. Format matches the dataflow frequency: ' +
48
+ 'YYYY (annual), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly). ' +
49
+ 'Note: the IMF SDMX 3.0 compact JSON endpoint returns the full available series ' +
50
+ 'regardless of this parameter — observations outside the requested range may still appear.'),
51
+ end_period: z
52
+ .string()
53
+ .optional()
54
+ .describe('Requested end of time range. Same format as start_period. ' +
55
+ 'See start_period note: the API returns the full series; this parameter is passed through ' +
56
+ 'but may not filter observations.'),
57
+ canvas_id: z
58
+ .string()
59
+ .optional()
60
+ .describe('Existing canvas ID to accumulate results into across multiple queries. ' +
61
+ 'Omit to allocate a fresh canvas; the response includes a canvas_id when results spill to DataCanvas.'),
62
+ }),
63
+ output: z.object({
64
+ dataflow_id: z.string().describe('Dataflow identifier that was queried, e.g. WEO.'),
65
+ key: z.string().describe('Dimension key used in the query, e.g. USA.NGDP_RPCH.A.'),
66
+ start_period: z
67
+ .string()
68
+ .optional()
69
+ .describe('Earliest period covered; absent when the full available range was used.'),
70
+ end_period: z
71
+ .string()
72
+ .optional()
73
+ .describe('Latest period covered; absent when the full available range was used.'),
74
+ observations: z
75
+ .array(z
76
+ .object({
77
+ series_key: z
78
+ .string()
79
+ .describe('Dot-separated dimension codes identifying this series, e.g. USA.NGDP_RPCH.A. ' +
80
+ 'Matches the single-country equivalent of the query key — useful when a query covers multiple countries.'),
81
+ time_period: z.string().describe('Time label, e.g. 2023 or 2023-Q1 or 2023-01.'),
82
+ value: z.number().nullable().describe('Observation value, null when missing.'),
83
+ status: z
84
+ .string()
85
+ .nullable()
86
+ .describe('Observation status flag, e.g. E (estimate) or null when absent.'),
87
+ })
88
+ .describe('A single time-series observation.'))
89
+ .describe('Inline observations. Empty when results spilled to canvas (see canvas_id / table_name).'),
90
+ series_attributes: z
91
+ .object({
92
+ unit: z.string().nullable().describe('Unit of measure, e.g. Percent, USD.'),
93
+ scale: z.string().nullable().describe('Scale multiplier, e.g. Billions.'),
94
+ decimals: z.number().nullable().describe('Number of decimal places shown.'),
95
+ })
96
+ .describe('Series-level attributes (unit, scale, decimals).'),
97
+ observation_count: z.number().describe('Total observations in the result.'),
98
+ truncated: z
99
+ .boolean()
100
+ .describe('True when the result exceeded the inline limit and was staged on a DataCanvas table; ' +
101
+ 'canvas_id and table_name are populated and imf_dataframe_query provides SQL access to the full set.'),
102
+ canvas_id: z
103
+ .string()
104
+ .optional()
105
+ .describe('DataCanvas session ID — present when truncated=true. ' +
106
+ 'Pass to imf_dataframe_query or imf_dataframe_describe to query the full result.'),
107
+ table_name: z
108
+ .string()
109
+ .optional()
110
+ .describe('DuckDB table name on the canvas — present when truncated=true; reference in SQL via FROM <table_name>.'),
111
+ }),
112
+ errors: [
113
+ {
114
+ reason: 'dataflow_not_found',
115
+ code: JsonRpcErrorCode.NotFound,
116
+ when: 'dataflow_id does not match any known dataflow on api.imf.org',
117
+ recovery: 'Call imf_list_databases to browse available dataflow IDs.',
118
+ },
119
+ {
120
+ reason: 'no_data',
121
+ code: JsonRpcErrorCode.NotFound,
122
+ when: 'Key is structurally valid but returns an empty dataset — typically an unknown dimension code or no data for the time range',
123
+ recovery: 'Verify dimension codes with imf_get_database; check that start_period/end_period overlap available data.',
124
+ },
125
+ {
126
+ reason: 'key_dimension_mismatch',
127
+ code: JsonRpcErrorCode.InvalidParams,
128
+ when: "Number of dot-separated segments in key does not match the dataflow's DSD dimension count",
129
+ recovery: 'Call imf_get_database to get the correct key_format for this dataflow, then reconstruct the key.',
130
+ },
131
+ {
132
+ reason: 'structure_unavailable',
133
+ code: JsonRpcErrorCode.ServiceUnavailable,
134
+ when: 'api.imf.org returns non-200 on the data endpoint',
135
+ recovery: 'Retry after a short wait.',
136
+ },
137
+ ],
138
+ async handler(input, ctx) {
139
+ const svc = getImfSdmxService();
140
+ // Resolve dataflow
141
+ const dataflow = await svc.findDataflow(input.dataflow_id, input.agency_id, input.version, ctx);
142
+ if (!dataflow) {
143
+ throw ctx.fail('dataflow_not_found', `Dataflow '${input.dataflow_id}' not found`, {
144
+ dataflowId: input.dataflow_id,
145
+ ...ctx.recoveryFor('dataflow_not_found'),
146
+ });
147
+ }
148
+ // Get DSD to validate key dimension count
149
+ let structure;
150
+ try {
151
+ structure = await svc.fetchDataflowStructure(input.dataflow_id, input.agency_id ?? dataflow.agencyId, input.version ?? dataflow.version, ctx);
152
+ }
153
+ catch (err) {
154
+ const msg = err instanceof Error ? err.message : String(err);
155
+ if (msg.includes('not found')) {
156
+ throw ctx.fail('dataflow_not_found', msg, ctx.recoveryFor('dataflow_not_found'));
157
+ }
158
+ throw ctx.fail('structure_unavailable', msg, ctx.recoveryFor('structure_unavailable'));
159
+ }
160
+ // Validate key dimension count
161
+ const expectedDims = structure.dimensions.length;
162
+ const keySegments = input.key.split('.');
163
+ if (expectedDims > 0 && keySegments.length !== expectedDims) {
164
+ throw ctx.fail('key_dimension_mismatch', `Key has ${keySegments.length} segment(s) but dataflow '${input.dataflow_id}' has ${expectedDims} dimension(s) (${structure.keyFormat})`, {
165
+ keySegments: keySegments.length,
166
+ expectedDimensions: expectedDims,
167
+ keyFormat: structure.keyFormat,
168
+ ...ctx.recoveryFor('key_dimension_mismatch'),
169
+ });
170
+ }
171
+ // Fetch data
172
+ let queryResult;
173
+ try {
174
+ queryResult = await svc.fetchData(dataflow.agencyId, input.dataflow_id, dataflow.version, input.key, input.start_period, input.end_period, ctx, ctx.signal);
175
+ }
176
+ catch {
177
+ throw ctx.fail('structure_unavailable', `IMF SDMX data endpoint unavailable for dataflow '${input.dataflow_id}'`, ctx.recoveryFor('structure_unavailable'));
178
+ }
179
+ // Detect empty result
180
+ if (queryResult.observations.length === 0) {
181
+ throw ctx.fail('no_data', `No data returned for key '${input.key}' in dataflow '${input.dataflow_id}'`, {
182
+ key: input.key,
183
+ dataflowId: input.dataflow_id,
184
+ ...ctx.recoveryFor('no_data'),
185
+ });
186
+ }
187
+ ctx.log.info('Data query completed', {
188
+ dataflowId: input.dataflow_id,
189
+ key: input.key,
190
+ observations: queryResult.observations.length,
191
+ });
192
+ // Canvas spill path
193
+ const canvas = getCanvas();
194
+ if (canvas) {
195
+ const instance = await canvas.acquire(input.canvas_id, ctx);
196
+ const rows = queryResult.observations.map((obs) => ({
197
+ dataflow_id: input.dataflow_id,
198
+ series_key: obs.series_key,
199
+ time_period: obs.time_period,
200
+ value: obs.value,
201
+ status: obs.status,
202
+ unit: queryResult.seriesAttributes.unit,
203
+ scale: queryResult.seriesAttributes.scale,
204
+ decimals: queryResult.seriesAttributes.decimals,
205
+ }));
206
+ const result = await spillover({
207
+ canvas: instance,
208
+ source: rows,
209
+ previewChars: PREVIEW_CHARS,
210
+ signal: ctx.signal,
211
+ });
212
+ if (result.spilled) {
213
+ return {
214
+ dataflow_id: input.dataflow_id,
215
+ key: input.key,
216
+ ...(input.start_period ? { start_period: input.start_period } : {}),
217
+ ...(input.end_period ? { end_period: input.end_period } : {}),
218
+ observations: result.previewRows.map((r) => ({
219
+ series_key: r.series_key,
220
+ time_period: r.time_period,
221
+ value: r.value,
222
+ status: r.status,
223
+ })),
224
+ series_attributes: queryResult.seriesAttributes,
225
+ observation_count: result.handle.rowCount,
226
+ truncated: true,
227
+ canvas_id: instance.canvasId,
228
+ table_name: result.handle.tableName,
229
+ };
230
+ }
231
+ }
232
+ // Inline path (no canvas, or result fit in preview)
233
+ return {
234
+ dataflow_id: input.dataflow_id,
235
+ key: input.key,
236
+ ...(input.start_period ? { start_period: input.start_period } : {}),
237
+ ...(input.end_period ? { end_period: input.end_period } : {}),
238
+ observations: queryResult.observations,
239
+ series_attributes: queryResult.seriesAttributes,
240
+ observation_count: queryResult.observations.length,
241
+ truncated: false,
242
+ };
243
+ },
244
+ format: (result) => {
245
+ const lines = [];
246
+ lines.push(`## IMF Data: ${result.dataflow_id} — \`${result.key}\``);
247
+ if (result.start_period || result.end_period) {
248
+ const range = [result.start_period, result.end_period].filter(Boolean).join(' – ');
249
+ lines.push(`**Requested period:** ${range} _(note: the IMF API returns the full available series; observations may extend beyond this range)_`);
250
+ }
251
+ const { unit, scale, decimals } = result.series_attributes;
252
+ if (unit || scale) {
253
+ const meta = [unit, scale, decimals != null ? `${decimals} decimals` : null]
254
+ .filter(Boolean)
255
+ .join(' | ');
256
+ lines.push(`**Series:** ${meta}`);
257
+ }
258
+ lines.push(`**Observations:** ${result.observation_count} | **Truncated:** ${result.truncated}`);
259
+ if (result.truncated) {
260
+ lines.push(`\n> Result exceeds inline limit. Full dataset staged on canvas.` +
261
+ `\n> **Canvas ID:** \`${result.canvas_id}\`` +
262
+ `\n> **Table:** \`${result.table_name}\`` +
263
+ `\n> Use \`imf_dataframe_describe\` then \`imf_dataframe_query\` to analyze.`);
264
+ }
265
+ if (result.observations.length > 0) {
266
+ lines.push('\n| Series Key | Time Period | Value | Status |');
267
+ lines.push('|:-----------|:------------|------:|:-------|');
268
+ for (const obs of result.observations) {
269
+ const val = obs.value != null ? obs.value.toString() : '—';
270
+ const status = obs.status ?? '—';
271
+ lines.push(`| ${obs.series_key} | ${obs.time_period} | ${val} | ${status} |`);
272
+ }
273
+ }
274
+ return [{ type: 'text', text: lines.join('\n') }];
275
+ },
276
+ });
277
+ //# sourceMappingURL=imf-query-dataset.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imf-query-dataset.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/imf-query-dataset.tool.ts"],"names":[],"mappings":"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"}