@pipeworx/mcp-data360 0.1.2 → 0.1.3
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.
- package/README.md +2 -2
- package/package.json +3 -3
- package/server.json +1 -1
- package/src/index.ts +43 -5
- package/src/server.ts +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
World Bank Data360 MCP — the World Bank's modern unified data platform.
|
|
4
4
|
|
|
5
|
-
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to
|
|
5
|
+
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1684+ live data sources.
|
|
6
6
|
|
|
7
7
|
## Tools
|
|
8
8
|
|
|
@@ -56,7 +56,7 @@ directly, instead of just this one's:
|
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Both URLs reach the same gateway and the same
|
|
59
|
+
Both URLs reach the same gateway and the same 1684+ data sources. The
|
|
60
60
|
only difference is which pack's tools are listed **directly**; `ask_pipeworx`
|
|
61
61
|
reaches all of them from either one.
|
|
62
62
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipeworx/mcp-data360",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "World Bank Data360 MCP — the World Bank's modern unified data platform.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@cloudflare/workers-types": "^4.20260405.1"
|
|
27
27
|
},
|
|
28
28
|
"pipeworx": {
|
|
29
|
-
"sourceHash": "v1-
|
|
30
|
-
"sourceCommit": "
|
|
29
|
+
"sourceHash": "v1-65667b630bb15d46ce130f4a24495fed088134e0b2301b8e8f7e71ea0734d4c1",
|
|
30
|
+
"sourceCommit": "904686a205e7659f86731df3f45eb88b9333c5a0"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.pipeworx-io/data360",
|
|
4
4
|
"title": "Data360",
|
|
5
5
|
"description": "World Bank Data360 MCP — the World Bank's modern unified data platform.",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.3",
|
|
7
7
|
"websiteUrl": "https://pipeworx.io/packs/data360",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/pipeworx-io/mcp-data360",
|
package/src/index.ts
CHANGED
|
@@ -796,7 +796,39 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
|
|
|
796
796
|
if (period) params.set('TIME_PERIOD', period);
|
|
797
797
|
params.set('skip', String(numArg(args.skip, 0)));
|
|
798
798
|
params.set('top', String(numArg(args.top, 100)));
|
|
799
|
-
|
|
799
|
+
const res = await pwFetch(`${BASE}/data?${params.toString()}`, {
|
|
800
|
+
headers: { Accept: 'application/json', 'User-Agent': UA },
|
|
801
|
+
});
|
|
802
|
+
if (!res.ok) {
|
|
803
|
+
const text = await res.text();
|
|
804
|
+
// Data360 answers an unknown DATABASE_ID with 417 EA500001 "Data
|
|
805
|
+
// retrieval failed" -- the same body it sends on a real outage, so the
|
|
806
|
+
// body cannot tell them apart. Check the id against the database list
|
|
807
|
+
// and only call it not_found when it is genuinely absent (fleet #2497).
|
|
808
|
+
const dbId = params.get('DATABASE_ID')!;
|
|
809
|
+
const known = await databaseIds().catch(() => null);
|
|
810
|
+
if (known && !known.includes(dbId)) {
|
|
811
|
+
const near = known.find((k) => k.toLowerCase() === dbId.toLowerCase());
|
|
812
|
+
return {
|
|
813
|
+
error: 'not_found',
|
|
814
|
+
message: near
|
|
815
|
+
? `Data360 has no database "${dbId}" -- ids are case-sensitive; did you mean "${near}"?`
|
|
816
|
+
: `Data360 has no database "${dbId}". Call data360_list_databases for valid DATABASE_IDs (e.g. "WB_WDI").`,
|
|
817
|
+
DATABASE_ID: dbId,
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
throw new Error(`Data360: ${res.status} ${text.slice(0, 200)}`);
|
|
821
|
+
}
|
|
822
|
+
const data = (await res.json()) as { count?: number; value?: unknown[] };
|
|
823
|
+
if ((data.count ?? data.value?.length ?? 0) === 0) {
|
|
824
|
+
// An unknown INDICATOR / REF_AREA pair is a 200 with zero rows, not an error.
|
|
825
|
+
return {
|
|
826
|
+
...data,
|
|
827
|
+
empty_reason: 'no_match',
|
|
828
|
+
note: `No observations for INDICATOR "${params.get('INDICATOR')}" in ${params.get('DATABASE_ID')} for REF_AREA "${params.get('REF_AREA')}"${period ? ` in ${period}` : ''}. Check the code with data360_search_indicators (database_id: "${params.get('DATABASE_ID')}"), or drop TIME_PERIOD.`,
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
return data;
|
|
800
832
|
}
|
|
801
833
|
|
|
802
834
|
default:
|
|
@@ -814,10 +846,16 @@ async function searchPost(body: unknown): Promise<unknown> {
|
|
|
814
846
|
return res.json();
|
|
815
847
|
}
|
|
816
848
|
|
|
817
|
-
async function
|
|
818
|
-
const res = await
|
|
819
|
-
|
|
820
|
-
|
|
849
|
+
async function databaseIds(): Promise<string[]> {
|
|
850
|
+
const res = (await searchPost({
|
|
851
|
+
count: true,
|
|
852
|
+
search: '*',
|
|
853
|
+
top: 0,
|
|
854
|
+
facets: ['series_description/database_id,count:1000'],
|
|
855
|
+
})) as any;
|
|
856
|
+
const ids: Array<{ value: string }> = res?.['@search.facets']?.['series_description/database_id'] ?? [];
|
|
857
|
+
if (ids.length === 0) throw new Error('Data360 database list came back empty');
|
|
858
|
+
return ids.map((d) => d.value);
|
|
821
859
|
}
|
|
822
860
|
|
|
823
861
|
function reqStr(args: Record<string, unknown>, key: string, example: string): string {
|
package/src/server.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
|
|
|
9
9
|
import pack from './index.js';
|
|
10
10
|
|
|
11
11
|
const server = new Server(
|
|
12
|
-
{ name: '@pipeworx/mcp-data360', version: '0.1.
|
|
12
|
+
{ name: '@pipeworx/mcp-data360', version: '0.1.3' },
|
|
13
13
|
{ capabilities: { tools: {} } },
|
|
14
14
|
);
|
|
15
15
|
|