Skip to main content
Glama
soulnai

nl-opendata-mcp

by soulnai

NL OpenData MCP Server

A comprehensive Model Context Protocol (MCP) server for accessing Dutch government open data from CBS (Centraal Bureau voor de Statistiek) and data.overheid.nl.

This is a small side project to experiment with MCP and see if it can be useful for accessing Dutch government open data. It is not production ready and should not be used for production.

I have tested it with Claude Desktop and LM Studio and it works wreasonably well. It should work with the most MCP clients. The results are always dependent on the quality of the model you use. Frontier models understand data and mcp tools well and produce good results. Local models may not understand the tools calling and produce unexpected results.

For local models I got the best results using the Devstral2 small model with gpt-oss 20b close second. Context length is a very limiting factor for local models. Yo will need at least 30k tokens context length for basic analysis to work.


✨ Features

  • 📊 Access 4800+ CBS Datasets - Browse and query statistical data on population, economy, health, environment, and more

  • 🔍 Smart Search - Search datasets by title, summary, or both with local caching for fast results

  • 📥 Flexible Data Fetching - Query, filter, and download datasets in CSV or Parquet format

  • 🐍 Python Analysis - Execute Pandas code directly on datasets without downloading

  • 🗂️ Dual Source Support - Check availability across CBS OData and data.overheid.nl


Related MCP server: dutch-gov-mcp

📦 Installation

# Run directly from PyPI
uvx nl-opendata-mcp

# Or run directly from GitHub
uvx --from git+https://github.com/soulnai/nl-opendata-mcp.git nl-opendata-mcp

Install with pip/uv

# Install from PyPI
uv pip install nl-opendata-mcp

# Install from GitHub
uv pip install git+https://github.com/soulnai/nl-opendata-mcp.git

From Source (Development)

# Clone the repository
git clone https://github.com/soulnai/nl-opendata-mcp.git
cd nl-opendata-mcp

# Install dependencies and package in editable mode
uv sync
uv pip install -e .

# Run the server
uv run nl-opendata-mcp

🔧 Configuration

Claude Desktop

Add to your Claude Desktop configuration (claude_desktop_config.json):

{
  "mcpServers": {
    "nl-opendata-mcp": {
      "command": "uvx",
      "args": ["nl-opendata-mcp"]
    }
  }
}

LM Studio

Add to your LM Studio configuration (mcp.json):

{
  "mcpServers": {
    "nl-opendata-mcp": {
      "command": "uvx",
      "args": ["nl-opendata-mcp"]
    }
  }
}

With Environment Variables

The server supports different transport modes:

# Default: stdio transport
uvx nl-opendata-mcp

# HTTP transport (port 8000)
TRANSPORT=http uvx nl-opendata-mcp

# SSE transport (port 8000)
TRANSPORT=sse uvx nl-opendata-mcp

🛠️ Available Tools

Discovery Tools

Tool

Description

cbs_list_datasets

List available datasets from the CBS catalog

cbs_search_datasets

Search datasets by keyword (in title, summary, or both)

cbs_check_dataset_availability

Check if a dataset is available via CBS OData or data.overheid.nl

cbs_estimate_dataset_size

Estimate dataset size before fetching (rows, columns, recommended strategy)

cbs_inspect_dataset_details

Get comprehensive dataset summary (metadata, structure, sample data)

Metadata Tools

Tool

Description

cbs_get_metadata

Unified metadata tool - get info, structure, dimension values, or custom endpoints

cbs_get_metadata types:

  • metadata_type="info" - Dataset description (TableInfos)

  • metadata_type="structure" - Column definitions and data types (DataProperties)

  • metadata_type="endpoints" - Available metadata endpoints

  • metadata_type="dimensions" - Dimension values with codes for filtering (requires endpoint_name)

  • metadata_type="custom" - Query custom endpoint (requires endpoint_name)

Data Fetching Tools

Tool

Description

cbs_query_dataset

Query data with filtering and column selection

cbs_save_dataset

Save dataset to CSV (use fetch_all=True for complete dataset)

Analysis Tools (disabled by default)

Tool

Description

cbs_analyze_remote_dataset

Execute Python/Pandas code on a remote dataset

cbs_analyze_local_dataset

Execute Python/Pandas code on a local CSV file


📖 Usage Examples

1. Discovering Datasets

List available datasets:

Use cbs_list_datasets with top=20 to see the first 20 datasets

Search for population data:

Use cbs_search_datasets with query="bevolking" to find population datasets

Search only in titles:

Use cbs_search_datasets with query="inflatie" and search_field="title"

2. Exploring a Dataset

Get a comprehensive overview (recommended first step):

Use cbs_inspect_dataset_details with dataset_id="85313NED"

# Returns:
# - Source confirmation (CBS OData or data.overheid.nl)
# - Title and description
# - Column definitions with types
# - Sample data (first 5 rows)

Check dataset size before fetching:

Use cbs_estimate_dataset_size with dataset_id="85313NED"

# Returns:
# - Estimated row count
# - Column count
# - Recommended fetch strategy

Get detailed column structure:

Use cbs_get_metadata with dataset_id="85313NED" and metadata_type="structure"

# Returns CSV with: Key, Type, Title, Description for each column

3. Querying Data

Basic query with pagination:

Use cbs_query_dataset with:
  - dataset_id="85313NED"
  - top=100
  - skip=0

Query with OData filter:

Use cbs_query_dataset with:
  - dataset_id="85313NED"
  - filter="Perioden eq '2023JJ00'"
  - top=50

Select specific columns:

Use cbs_query_dataset with:
  - dataset_id="85313NED"
  - select=["Perioden", "TotaleBevolking_1", "Mannen_2", "Vrouwen_3"]
  - top=100

Query with multiple conditions:

Use cbs_query_dataset with:
  - dataset_id="85313NED"
  - filter="Perioden eq '2023JJ00' and Leeftijd eq '10000'"

4. Downloading Full Datasets

Save complete dataset to CSV:

Use cbs_save_dataset with:
  - dataset_id="85313NED"
  - file_name="population_data.csv"
  - fetch_all=true

5. Analyzing Data

Note: Analysis tools are disabled by default. To enable them, set USE_PYTHON_ANALYSIS=true in the environment. It is security risk to let the model write and execute Python code on a client machine. Recommended for advanced users only. It's better to let the model query and save the data to a file, and let your CLI LLM coding tool to analyse it by writing and executing scripts. If you are running it in a non CLI environment (like LM Studio) and still want to give it the ability to analyse data, you can enable it by setting USE_PYTHON_ANALYSIS=true in the environment.

Analyze remote dataset with Pandas:

Use cbs_analyze_remote_dataset with:
  - dataset_id="85313NED"
  - analysis_code="print(df.describe())"

Calculate statistics:

Use cbs_analyze_remote_dataset with:
  - dataset_id="85313NED"
  - analysis_code="result = df['TotaleBevolking_1'].mean()"

Filter and aggregate:

Use cbs_analyze_remote_dataset with:
  - dataset_id="85313NED"
  - analysis_code="""
    filtered = df[df['Perioden'].str.contains('2023')]
    result = filtered.groupby('Leeftijd')['TotaleBevolking_1'].sum()
    print(result)
    """

Analyze a local CSV file:

Use cbs_analyze_local_dataset with:
  - dataset_path="downloads/85313NED_full.csv"
  - analysis_code="print(df.info())"

6. Working with Metadata

Get classification codes (e.g., gender categories):

Use cbs_get_metadata with:
  - dataset_id="85313NED"
  - metadata_type="dimensions"
  - endpoint_name="Geslacht"

Get time period definitions:

Use cbs_get_metadata with:
  - dataset_id="85313NED"
  - metadata_type="dimensions"
  - endpoint_name="Perioden"

🎯 Common Workflows

Workflow 1: Quick Data Exploration

1. cbs_search_datasets(query="unemployment")              # Find relevant datasets
2. cbs_inspect_dataset_details(dataset_id="82809NED")     # Get overview
3. cbs_query_dataset(dataset_id="82809NED", top=10)       # Preview data

Workflow 2: Full Dataset Analysis

1. cbs_estimate_dataset_size(dataset_id="85313NED")           # Check size
2. cbs_save_dataset(dataset_id="85313NED", fetch_all=True)    # Save full dataset to CSV
3. cbs_analyze_local_dataset(...)                            # Analyze locally with Pandas

Workflow 3: Filtered Data Export

1. cbs_get_metadata(dataset_id="85313NED", metadata_type="structure")  # Get column names
2. cbs_get_metadata(dataset_id="85313NED", metadata_type="dimensions", endpoint_name="Perioden")  # Get period codes
3. cbs_query_dataset(dataset_id="85313NED", filter="Perioden eq '2023JJ00'", select=["..."])  # Query
4. cbs_save_dataset(dataset_id="85313NED", file_name="filtered_data.csv")  # Export

📁 Output Formats

Format

Use Case

CSV

Universal compatibility, works with Excel, Pandas, etc.


🔗 OData Filter Examples

The CBS OData API uses OData v3 syntax for filtering:

# Exact match
Perioden eq '2023JJ00'

# Substring match
substringof('Amsterdam', RegioS)

# Multiple conditions
Perioden eq '2023JJ00' and Leeftijd eq '10000'

# OR conditions
Geslacht eq '1100' or Geslacht eq '2000'

# Numeric comparisons
TotaleBevolking_1 gt 100000

📚 Resources


Available Tools

9 tools
cbs_check_dataset_availabilityA
Read-onlyIdempotent

Checks if a dataset is available via CBS OData (queryable) or data.overheid.nl (download-only).

Args: params: DatasetIdInput containing: - dataset_id (str): Dataset ID (e.g., '83583NED')

Returns: str: Availability status and source information

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for operations that only need a dataset ID.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint, idempotentHint, openWorldHint. The description adds context about the two sources and return type, but does not detail the response structure beyond a string status. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with two short paragraphs covering purpose, args, and returns. It is front-loaded with the main purpose and contains no unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has one parameter, high schema coverage, annotations, and an output schema, the description provides sufficient context for basic usage. It could specify the return format more precisely, but overall is adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for both params and dataset_id. The description repeats the example and mentions DatasetIdInput, adding minimal value beyond the schema. It does list the sources, which is additional context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Checks if a dataset is available via CBS OData (queryable) or data.overheid.nl (download-only),' which is a specific verb and resource, and distinguishes between two sources, helping differentiate from sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool (to check availability) and the two sources, but does not explicitly state when not to use it or compare with alternatives. It is clear but lacks exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_estimate_dataset_sizeA
Read-onlyIdempotent

Estimates the size of a dataset before fetching.

Args: params: DatasetIdInput containing: - dataset_id (str): Dataset ID (e.g., '85313NED')

Returns: str: Size estimation with row count, column count, and recommended fetch strategy

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for operations that only need a dataset ID.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover readOnly, destructive, idempotent, openWorld hints fully. Description adds output details (row count, column count, fetch strategy), which is useful context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Short and to the point. The 'Args:' and 'Returns:' formatting is slightly verbose but still concise overall. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given one parameter, full schema coverage, and existing output schema, the description fully covers what an agent needs. No missing details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, description essentially repeats schema with minor restructuring. Adds some clarity on nested object but no novel meaning beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it estimates dataset size before fetching, with a specific verb and resource. This distinguishes it from siblings like cbs_check_dataset_availability or cbs_get_metadata.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implied usage from 'before fetching', but no explicit when-not-to-use or alternatives among siblings. Provides some guidance via return value mentioning 'recommended fetch strategy'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_get_metadataA
Read-onlyIdempotent

Unified metadata tool for detailed info, structure, dimension values, or custom endpoints.

Args: params: GetMetadataInput containing: - dataset_id (str): Dataset ID (e.g., '85313NED') - metadata_type (str): Type of metadata: - 'info': Dataset description (TableInfos) - 'structure': Column definitions (DataProperties) - 'endpoints': Available metadata endpoints - 'dimensions': Dimension values with codes for filtering (requires endpoint_name) - 'custom': Custom endpoint query (requires endpoint_name) - endpoint_name (str, optional): Required for 'dimensions' and 'custom' types (e.g., 'Geslacht', 'Perioden', 'Luchthavens')

Returns: str: CSV for info/structure/dimensions, JSON for endpoints/custom

Examples: - Get columns: metadata_type="structure" - Get dimension codes: metadata_type="dimensions", endpoint_name="Geslacht" - Get raw endpoint: metadata_type="custom", endpoint_name="CategoryGroups"

IMPORTANT - Finding Dimension Codes: Use metadata_type="dimensions" to find codes for OData filtering. CBS uses coded values (e.g., 'A043591') that map to names (e.g., 'Eindhoven Airport').

Workflow:
1. Get dimension codes: metadata_type="dimensions", endpoint_name="Luchthavens"
2. Use code in query: filter="Luchthavens eq 'A043591'"
ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for unified metadata retrieval.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=true. The description adds context about return formats (CSV for info/structure/dimensions, JSON for endpoints/custom) and constraints like endpoint_name requirement, enhancing transparency without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections and examples. It is front-loaded with the purpose. However, some repetition occurs (e.g., the 'IMPORTANT' section slightly duplicates earlier info), making it a bit longer than necessary, but still effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and that an output schema exists, the description covers all metadata types, explains return formats, and provides a complete workflow for dimension codes. It addresses the tool's role in relation to sibling tools and leaves no obvious gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds significant value by providing explanations, examples, and clarifying the interdependency between metadata_type and endpoint_name. It also includes a workflow example that enriches understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states it is a 'Unified metadata tool' and lists five specific metadata types (info, structure, dimensions, endpoints, custom), making the verb-resource pair very clear. It distinguishes itself from sibling tools like cbs_query_dataset and cbs_inspect_dataset_details which handle data queries or dataset inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides detailed guidance including a workflow for finding dimension codes for OData filtering, explicit requirements for endpoint_name, and example use cases. It effectively tells when to use each metadata_type, though it doesn't explicitly state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_inspect_dataset_detailsA
Read-onlyIdempotent

Compact dataset overview: title, dimensions, measures, and sample data. Use this first to understand a dataset's structure.

Args: params: DatasetIdInput containing: - dataset_id (str): Dataset ID (e.g., '85313NED')

Returns: str: Compact report with title, column list, and 3-row sample

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for operations that only need a dataset ID.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true, openWorldHint=true. The description adds behavioral details: returns a compact report with title, column list, and 3-row sample. No contradictions, and adds value beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences plus an Args/Returns block, no wasted words. Front-loaded with purpose and usage guidance. Efficient and well-organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter and an output schema, the description provides sufficient context: what it does, when to use, and what the output contains (sample data, column list). No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with both 'params' and 'dataset_id' having descriptions. The description repeats these ('Dataset ID (e.g., '85313NED')') but adds no new semantic information. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Compact dataset overview: title, dimensions, measures, and sample data. Use this first to understand a dataset's structure.' It specifies the verb 'inspect' and resource 'dataset details', and distinguishes from siblings by emphasizing it's an initial overview tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Use this first to understand a dataset's structure,' providing clear when-to-use context. Does not explicitly mention when not to use or alternatives, but the context from siblings makes usage clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_list_datasetsB
Read-onlyIdempotent

Lists available datasets from the CBS OData Catalog.

Args: params: ListDatasetsInput containing: - top (int): Number of records to return (default: 10, max: 1000) - skip (int): Number of records to skip (default: 0)

Returns: str: CSV string containing dataset list with columns: Identifier, Title, Summary

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for listing datasets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and idempotentHint=true, so the description adds limited behavioral context. It does disclose the return format (CSV string with columns), which is helpful. No additional behaviors (e.g., pagination details beyond what schema provides) are described.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with no unnecessary words. It uses a clear structured format (Args, Returns) that is easy to parse. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, parameters, and return format adequately. An output schema exists (not shown), but the description states the CSV columns, which is sufficient for understanding what the tool does. Could mention error handling or rate limits, but not essential for a read-only list operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema coverage is 100%, and the description repeats parameter defaults and boundaries already present in the schema. It adds explicit default values (10 for top, 0 for skip), but this is marginal value. The baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Lists available datasets from the CBS OData Catalog', which is a specific verb+resource. However, it does not explicitly differentiate from siblings like 'cbs_search_datasets' or 'cbs_list_local_datasets', which could cause confusion about when to use this tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. Siblings exist (e.g., search, local), but the description does not mention them or specify scenarios. This leaves the agent to infer usage without support.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_list_local_datasetsA
Read-onlyIdempotent

Lists all locally saved CSV datasets in the downloads directory.

Returns: str: List of CSV files with sizes and row counts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint, and idempotentHint as true, indicating safe, non-destructive behavior. The description adds transparency by stating the return format includes 'sizes and row counts,' which is not captured in annotations. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, no unnecessary words, and front-loads the core purpose. Every sentence adds value: the first states the action, the second describes the return format.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with no parameters and rich annotations, the description is largely complete. It specifies the return as a string with CSV files, sizes, and row counts. A minor gap is not stating whether file paths are included or just names, but given the output schema exists (though not shown), this is acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so schema coverage is 100%. The description does not need to add parameter details. According to calibration, baseline is 4 for no parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'Lists all locally saved CSV datasets in the downloads directory,' which clearly indicates the tool's purpose with a specific verb and resource. It distinguishes itself from siblings like cbs_list_datasets (likely global) and cbs_inspect_dataset_details (detailed inspection) by specifying 'locally saved' and 'CSV'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for listing local CSV files but provides no explicit guidance on when to use this tool versus alternatives such as cbs_list_datasets or cbs_search_datasets. It lacks when-not-to-use or alternative recommendations, leaving reliance on agent inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_query_datasetA
Read-onlyIdempotent

Queries data from a dataset with optional filtering and column selection.

Args: params: QueryDatasetInput containing: - dataset_id (str): Dataset ID (e.g., '85313NED') - top (int): Number of records (default: 10) - skip (int): Records to skip (default: 0) - filter (str, optional): OData filter (e.g., "Perioden eq '2023JJ00'") - select (List[str], optional): Column names to return - compact (bool): Return summary for large results (default: True) - translate (bool): Translate coded dimension values to text (default: True)

Returns: str: CSV data with human-readable dimension values

Note: Use cbs_get_metadata with metadata_type="dimensions" to find filter codes.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for querying datasets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds behavioral context beyond annotations: returns CSV, uses OData filter syntax, and translates dimension values. Annotations already provide safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with Args and Returns sections, but slightly verbose. Could be more concise while retaining clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all parameters, explains return format (CSV), includes annotations, and references sibling for metadata. Sufficient for a query tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline 3. Description repeats parameter info but adds example filter and translate explanation, adding marginal value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb 'Queries' and resource 'data from a dataset', with optional filtering and column selection. Distinguishes from siblings by referencing cbs_get_metadata for filter codes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage for querying data and hints at using cbs_get_metadata for filter codes, but lacks explicit guidance on when to use this tool versus alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_save_datasetB
Idempotent

Saves a dataset to a CSV file.

Args: params: SaveDatasetInput containing: - dataset_id (str): Dataset ID (e.g., '85313NED') - file_name (str): File name to save the dataset - top (int): Records per request (default: 1000) - skip (int): Records to skip (default: 0) - fetch_all (bool): Fetch all records with pagination (default: False) - translate (bool): Translate coded values to text (default: True)

Returns: str: Success message with file path and record count

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for saving datasets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate idempotentHint=true and destructiveHint=false, suggesting overwrite behavior. The description does not add details about file overwrite, error handling, or permission requirements. With annotations present, the bar is lower, but missing file behavior context limits transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence followed by a parameter list. While concise, the parameter list is redundant with the input schema. Still, it is front-loaded and not verbose, earning a 4.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool saves to a file, but the description lacks details about file handling (overwrite behavior, required permissions, supported formats). An output schema exists, mitigating the need for return value details, but file behavior context is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description repeats parameter meanings from the schema without adding new insights. It does not clarify parameter interactions beyond what the schema already provides (e.g., fetch_all vs top/skip).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Saves a dataset to a CSV file,' specifying the verb and resource. It differentiates from siblings like cbs_save_dataset_to_duckdb (saves to DuckDB) and other query/list tools, making the purpose specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives (e.g., cbs_save_dataset_to_duckdb or cbs_query_dataset). The description only lists parameters without explaining context, prerequisites, or situations where this tool is preferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cbs_search_datasetsA
Read-onlyIdempotent

Searches for datasets in the CBS OData Catalog by keyword.

Args: params: SearchDatasetsInput containing: - query (str): Search term (e.g., "Bevolking", "Inflation") - top (int): Number of records to return (default: 10) - skip (int): Number of records to skip (default: 0) - search_field (str): Where to search - "all", "title", or "summary"

Returns: str: CSV string containing matching datasets

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYesInput model for searching datasets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint, idempotentHint, and openWorldHint, covering safety and idempotency. The description adds that results are returned as a CSV string, which is useful but not a major behavioral disclosure beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise: two sentences for overall purpose, followed by a structured bullet list for parameters. It avoids fluff and is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity and the existence of annotations and output schema mention (CSV string), the description fully covers what the tool does, its parameters, and its return type. No gaps remain for this search tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with each parameter already documented in the schema. The description repeats those descriptions verbatim (e.g., 'query (str): Search term'). It adds no new meaning or context beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Searches for datasets in the CBS OData Catalog by keyword,' specifying the action (searches), resource (datasets), and context (CBS OData Catalog). This distinguishes it from sibling tools like cbs_list_datasets (which lists all) and cbs_inspect_dataset_details (which shows details of a specific dataset).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when a keyword search is needed, but it does not explicitly state when to use this tool over alternatives (e.g., cbs_list_datasets). Given multiple siblings, explicit when-to-use and when-not-to-use guidance would be helpful.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.1/5.0
Disambiguation5/5

Every tool serves a clearly distinct purpose: listing, searching, checking availability, estimating size, retrieving metadata, inspecting details, querying data, saving to file, and listing local files. There is no overlap or ambiguity.

Naming Consistency5/5

All tools follow a consistent 'cbs_verb_noun' pattern in snake_case (e.g., cbs_list_datasets, cbs_query_dataset). The naming is predictable and well-structured.

Tool Count5/5

With 9 tools covering discovery, metadata, querying, and local storage, the count is well-scoped for a data access server. Each tool is justified and the set feels neither sparse nor bloated.

Completeness4/5

The tool surface covers the full lifecycle of working with CBS datasets: discovery, metadata inspection, size estimation, querying with filtering, and saving locally. Minor gaps exist (e.g., no delete for local files, no direct download without saving), but these do not hinder core workflows.

Maintenance

ActivityStale
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    Not graded
    maintenance
    Enables AI assistants and CLI tools to explore and analyze datasets from 600+ global CKAN open-data portals. Provides comprehensive tools for dataset discovery, datastore queries, metadata analysis, and local downloads without writing custom CKAN integrations.
    14
  • A
    license
    B
    quality
    D
    maintenance
    An unofficial MCP server providing access to Dutch government open data from data.overheid.nl, CBS statistics, and KVK business registry. Enables natural language queries for discovering datasets, inspecting metadata, and querying data without API keys or authentication.
    14
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables querying and analyzing over 90,000 public datasets from the Spanish Government Open Data Portal (datos.gob.es) using natural language, with tools for search, filtering, metadata access, and SPARQL queries.
    10
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables querying Statistics Netherlands (CBS) data, including metadata for tables like '37296eng', through an MCP interface.
    15
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/soulnai/nl-opendata-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server