@pipeworx/mcp-cbs-nl 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 +56 -2
- package/src/server.ts +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Statistics Netherlands (CBS) StatLine — the Dutch national statistics office's
|
|
|
4
4
|
open-data catalogue, over OData v3. Population, labour, energy, prices, trade and
|
|
5
5
|
several thousand other official tables, in Dutch and English.
|
|
6
6
|
|
|
7
|
-
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to
|
|
7
|
+
Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1684+ live data sources.
|
|
8
8
|
|
|
9
9
|
## Tools
|
|
10
10
|
|
|
@@ -82,7 +82,7 @@ directly, instead of just this one's:
|
|
|
82
82
|
}
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
Both URLs reach the same gateway and the same
|
|
85
|
+
Both URLs reach the same gateway and the same 1684+ data sources. The
|
|
86
86
|
only difference is which pack's tools are listed **directly**; `ask_pipeworx`
|
|
87
87
|
reaches all of them from either one.
|
|
88
88
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipeworx/mcp-cbs-nl",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Statistics Netherlands (CBS / StatLine) OData MCP.",
|
|
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-1f4013c99a6c89d86557fa722f1ed30372a6b8f380159c808b093354aeb4e965",
|
|
30
|
+
"sourceCommit": "a00767651388cfd017fdeac82188622721db2051"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.pipeworx-io/cbs-nl",
|
|
4
4
|
"title": "Cbs Nl",
|
|
5
5
|
"description": "Statistics Netherlands (CBS / StatLine) OData MCP.",
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.3",
|
|
7
7
|
"websiteUrl": "https://pipeworx.io/packs/cbs-nl",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/pipeworx-io/mcp-cbs-nl",
|
package/src/index.ts
CHANGED
|
@@ -764,6 +764,32 @@ const tools: McpToolExport['tools'] = [
|
|
|
764
764
|
];
|
|
765
765
|
|
|
766
766
|
async function callTool(name: string, args: Record<string, unknown>): Promise<unknown> {
|
|
767
|
+
try {
|
|
768
|
+
return await dispatch(name, args);
|
|
769
|
+
} catch (err) {
|
|
770
|
+
// CBS answers an unknown table id (and an unknown dimension endpoint) with
|
|
771
|
+
// a 404 ASP.NET page titled "The resource cannot be found." That threw as a
|
|
772
|
+
// bare `CBS: 404 …` and booked as a Pipeworx defect with "retry the same
|
|
773
|
+
// tool" (fleet #2496). It is the caller naming a thing CBS does not have.
|
|
774
|
+
if (err instanceof CbsHttpError && err.status === 404 && /resource cannot be found/i.test(err.body)) {
|
|
775
|
+
const table = typeof args.table === 'string' ? args.table : '';
|
|
776
|
+
const what =
|
|
777
|
+
name === 'dimension_values'
|
|
778
|
+
? `no table "${table}" or no dimension "${String(args.dimension ?? '')}" in it`
|
|
779
|
+
: `no table "${table}"`;
|
|
780
|
+
return {
|
|
781
|
+
error: 'not_found',
|
|
782
|
+
message:
|
|
783
|
+
`CBS StatLine has ${what}. Call search_tables({keyword: "..."}) to find the table id` +
|
|
784
|
+
`${name === 'dimension_values' ? ', then table_dimensions for its dimension names' : ''}.`,
|
|
785
|
+
table,
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
throw err;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
async function dispatch(name: string, args: Record<string, unknown>): Promise<unknown> {
|
|
767
793
|
PROXY =
|
|
768
794
|
typeof args._proxyUrl === 'string' && typeof args._proxyToken === 'string'
|
|
769
795
|
? { url: args._proxyUrl, token: args._proxyToken }
|
|
@@ -798,7 +824,23 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
|
|
|
798
824
|
if (typeof args.select === 'string' && args.select.trim()) params.set('$select', args.select);
|
|
799
825
|
if (typeof args.filter === 'string' && args.filter.trim()) params.set('$filter', args.filter);
|
|
800
826
|
if (args.skip !== undefined) params.set('$skip', String(numArg(args.skip, 0)));
|
|
801
|
-
|
|
827
|
+
const out = (await cbsGet(`${TABLE}/${tableId(args)}/TypedDataSet?${params.toString()}`)) as {
|
|
828
|
+
value?: unknown[];
|
|
829
|
+
};
|
|
830
|
+
// `value: []` is an honest no-match (the filter or skip matched no rows)
|
|
831
|
+
// and used to go out as a bare empty success (fleet #2496).
|
|
832
|
+
if (Array.isArray(out?.value) && out.value.length === 0) {
|
|
833
|
+
return {
|
|
834
|
+
...out,
|
|
835
|
+
empty_reason: 'no_match',
|
|
836
|
+
note:
|
|
837
|
+
`CBS table "${tableId(args)}" has no rows matching` +
|
|
838
|
+
`${typeof args.filter === 'string' && args.filter.trim() ? ` filter ${args.filter}` : ' this request'}` +
|
|
839
|
+
`${args.skip !== undefined ? ` at skip ${String(args.skip)}` : ''}. ` +
|
|
840
|
+
`Check the codes with dimension_values (e.g. dimension "Periods") before filtering.`,
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
return out;
|
|
802
844
|
}
|
|
803
845
|
default:
|
|
804
846
|
throw new Error(`Unknown tool: ${name}`);
|
|
@@ -821,7 +863,9 @@ async function cbsGet(url: string): Promise<unknown> {
|
|
|
821
863
|
if (!res.ok) {
|
|
822
864
|
const body = await res.text().catch(() => '');
|
|
823
865
|
const title = body.match(/<title>([\s\S]*?)<\/title>/i)?.[1]?.trim();
|
|
824
|
-
throw new
|
|
866
|
+
throw new CbsHttpError(
|
|
867
|
+
res.status,
|
|
868
|
+
body,
|
|
825
869
|
`CBS: ${res.status}${title ? ` ${title}` : ''} — ${url} — ${body.replace(/\s+/g, ' ').slice(0, 300)}`,
|
|
826
870
|
);
|
|
827
871
|
}
|
|
@@ -834,6 +878,16 @@ async function cbsGet(url: string): Promise<unknown> {
|
|
|
834
878
|
}
|
|
835
879
|
}
|
|
836
880
|
|
|
881
|
+
class CbsHttpError extends Error {
|
|
882
|
+
readonly status: number;
|
|
883
|
+
readonly body: string;
|
|
884
|
+
constructor(status: number, body: string, message: string) {
|
|
885
|
+
super(message);
|
|
886
|
+
this.status = status;
|
|
887
|
+
this.body = body;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
837
891
|
function tableId(args: Record<string, unknown>): string {
|
|
838
892
|
return reqStr(args, 'table', '"37296eng"').trim().replace(/[^A-Za-z0-9_]/g, '');
|
|
839
893
|
}
|
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-cbs-nl', version: '0.1.
|
|
12
|
+
{ name: '@pipeworx/mcp-cbs-nl', version: '0.1.3' },
|
|
13
13
|
{ capabilities: { tools: {} } },
|
|
14
14
|
);
|
|
15
15
|
|