Query Dutch national statistics (CBS StatLine) via @pipeworx/mcp-cbs-nl — OData v3 API, 5 tools
How do I query Statistics Netherlands (CBS) data — population totals, CPI inflation, trade, energy — via MCP? I need to search for tables by keyword, understand their dimension structure, and pull time-series observations with filtering.
@pipeworx/mcp-cbs-nl v latest — Statistics Netherlands (CBS StatLine) via OData v3
Package: npm install @pipeworx/mcp-cbs-nl Transport: Library-style TypeScript export ({tools, callTool}) — NOT stdio. Copy src/index.ts out of node_modules, run with node --experimental-strip-types. Auth: None — keyless public OData API at opendata.cbs.nl. Remote gateway: https://gateway.pipeworx.io/cbs-nl/mcp (streamable-http).
5 tools
| Tool | Params | What it does |
|---|---|---|
search_tables | keyword, english_only?, top? | Search CBS datasets by title substring. english_only: true filters to IDs ending in "eng"/"ENG". |
table_info | table | Metadata: title, summary, period covered, frequency, last updated. |
table_dimensions | table | Column/dimension definitions (DataProperties): Key, Type, Title, Unit. Use before get_data. |
dimension_values | table, dimension, top? | Valid codes/labels for one dimension (e.g. "Periods", "ExpenditureCategories"). |
get_data | table, select?, filter?, top?, skip? | Fetch observations (TypedDataSet). Supports OData v3 $select/$filter/$top. |
Execution trace — 16 calls, 14 OK + 2 correct error handling
1. search_tables — English population tables:
search_tables({keyword: "population", english_only: true, top: 5}) → 634ms
5 results: 83774ENG (Caribbean NL births/deaths), 85723ENG (Caribbean NL by nationality),
83698ENG (Caribbean NL by sex), plus mainland tables. All have Language: "en".2. search_tables — Dutch keyword:
search_tables({keyword: "bevolking", top: 3}) → 433ms
3 results in Dutch: 86219NED (arbeidsverleden), 86082NED, 85388NED. Dutch tables have NED suffix.3. table_info:
table_info({table: "37296eng"}) → 88ms
Title: "Population; key figures, 1950-2022"
Period: "1950 - 2022", Frequency: "Discontinued"4. table_dimensions:
table_dimensions({table: "37296eng"}) → 688ms
99 properties! Types: TimeDimension (Periods), TopicGroup (headers), Topic (data columns).
Population by sex: TotalPopulation_1, Males_2, Females_3
Population by age: YoungerThan20Years_10, etc.5. dimension_values — Period codes:
dimension_values({table: "37296eng", dimension: "Periods", top: 10}) → 245ms
Format: "1950JJ00" → "1950", "2022JJ00" → "2022" (JJ00 = annual).6. get_data — population 2020-2022:
get_data({table: "37296eng", select: "Periods,TotalPopulation_1,Males_2,Females_3",
filter: "substringof('2020',Periods) or substringof('2021',Periods) or substringof('2022',Periods)"}) → 570ms
2020JJ00 | Total: 17,407,585 | M: 8,648,031 | F: 8,759,554
2021JJ00 | Total: 17,475,415
2022JJ00 | Total: 17,590,6727. CPI table structure:
table_dimensions({table: "86141ENG"}) → 552ms
Dimensions: ExpenditureCategories, Periods
Topics: CPI_1, DerivedCPI_2, MonthlyRateOfChangeCPI_3, AnnualRateOfChangeCPI_5, WeightingCoefficient_78. CPI expenditure categories:
dimension_values({table: "86141ENG", dimension: "ExpenditureCategories", top: 15}) → 528ms
T001112 = "000000 All items" (key has trailing whitespace!)
CPI010000 = "010000 Food and non-alcoholic beverages"
CPI011000 = "011000 Food", etc.9. ⚠️ CRITICAL BUG: Exact-match filter SILENTLY FAILS:
get_data({filter: "ExpenditureCategories eq 'T001112'"}) → 301ms → 0 rows!
REASON: CBS stores keys with TRAILING WHITESPACE ("T001112 " not "T001112").10. WORKAROUND — use trim() or substringof:
get_data({filter: "trim(ExpenditureCategories) eq 'T001112'"}) → 541ms → 6 rows ✓
get_data({filter: "substringof('T001112',ExpenditureCategories) and substringof('2025',Periods)"}) → 221ms → 12 rows ✓11. CPI 2025 full year:
Jan: 97.60 (YoY +3.3%), Feb: 98.67 (+3.7%), Mar: 99.09 (+3.6%),
Apr: 100.10 (+4.0%), May: 99.53 (+3.2%), Jun: 99.49 (+3.0%),
Jul: 100.87 (+2.9%), Aug: 101.06 (+2.8%), Sep: 100.97 (+3.2%),
Oct: 101.37 (+3.1%), Nov: 100.51 (+2.8{ "package": "@pipeworx/mcp-cbs-nl", "version": "latest", "transport": "library-style TypeScript", "tools": ["search_tables", "table_info", "table_dimensions", "dimension_values", "get_data"], "calls": 16, "success_rate": "87.5% (14 OK + 2 correct errors)", "p50_ms": 379, "key_data": { "netherlands_population_2022": 17590672, "cpi_2026_may": 103.01, "cpi_yoy_may_2026": "3.5%" }, "critical_bugs": ["dimension keys have trailing whitespace — eq filter silently returns 0 rows", "$skip causes HTTP 500 on TypedDataSet endpoint"] }