Skip to main content
Glama
DV155

statistik-austria-mcp

by DV155

About The Project

A Model Context Protocol server for the free Open Government Data portal of Statistik Austria (data.statistik.gv.at). It lets an AI assistant such as Claude search the catalog, read a dataset's structure and fetch its data directly, instead of you downloading and pasting CSV files.

The portal publishes each dataset as a set of files with coded values, so a raw table is hard for a model to read correctly. The server joins the classification files onto the data, so every value arrives as a readable German label together with its original code, and marks the rows that are totals of other rows.

Built as a personal learning project to practise building MCP servers.

Features:

  • Keyword search over the full OGD catalog (around 540 datasets)

  • Dataset metadata: dimensions and measures

  • Data with codes resolved to German labels, formatted label <code>

  • Total rows are flagged, so the assistant doesn't add a total to its own parts

  • Filters by dimension value, so large tables don't have to be read in full

  • Paging that never drops rows silently: every response says how many rows exist and where to continue

  • Clear messages for datasets in formats the server can't read, instead of a bare error

  • Downloads are cached for an hour, so paging through a dataset doesn't download it again

Built With

Related MCP server: mcp-podatki-si

Getting Started

The server runs locally on your computer and talks to your MCP client over stdio. uvx installs and starts it, so there is nothing to clone for normal use.

Prerequisites

  • uv (it downloads a matching Python version automatically)

  • Git

  • Claude Desktop or Claude Code (or any other MCP client)

Installation

Claude Desktop

  1. Open the config file. In Claude Desktop, go to Settings → Developer → Edit Config, or open it directly:

    • Windows: %APPDATA%\Claude\claude_desktop_config.json

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  2. Add the server

    {
      "mcpServers": {
        "statistik-austria": {
          "command": "uvx",
          "args": ["--from", "git+https://github.com/DV155/Statistik-Austria-MCP-Server", "statistik-austria-mcp"]
        }
      }
    }
  3. Quit Claude Desktop completely and start it again.

Claude Code

claude mcp add --transport stdio --scope user statistik-austria -- uvx --from git+https://github.com/DV155/Statistik-Austria-MCP-Server statistik-austria-mcp

The first start takes a while, because uv installs the dependencies (pandas is the largest). To get that out of the way, run the uvx command above once in a terminal and stop it with Ctrl+C once it is running. If Claude can't find uvx, replace "uvx" with its full path (which uvx shows it). Claude Desktop writes the server's logs to %APPDATA%\Claude\logs on Windows and ~/Library/Logs/Claude on macOS.

Local development

  1. Clone the repo

    git clone https://github.com/DV155/Statistik-Austria-MCP-Server.git
    cd Statistik-Austria-MCP-Server
  2. Install the dependencies

    uv sync
  3. Start the server in the MCP Inspector

    uv run mcp dev src/statserver/server.py

Usage

Ask Claude a question about Austrian statistics, and it uses the tools on its own.

Tool

What it does

search_dataset

Searches the catalog by keyword and returns matching dataset IDs and titles

fetch_dataset_json

Returns a dataset's dimensions and measures with their codes

fetch_dataset_csv

Returns the data with labels, total-row flags and paging; filters keeps only the rows for given dimension values

The server also provides an ogd://catalog resource with the catalog's categories.

Tip: the catalog's titles are German, so the server searches in German. Claude translates the question itself, but asking in German works just as well.

Limitations

Tested against all 543 datasets in the catalog in October 2026:

  • 474 load fully

  • 66 are published in formats the server can't read (zip archives and map services such as WFS and WMS); the server says so instead of failing

  • 2 contain no data rows

  • 1 (OGDEXT_BINNENWAND_1) loads without labels and slowly

Other limitations:

  • Only the free OGD portal is supported, not the paid STATcube API

  • The catalog is read from the portal's HTML page, so search stops working if Statistik Austria changes that page's structure

  • The first request for a very large dataset can take several seconds while it downloads

Data Source

All data comes from Statistik Austria - data.statistik.gv.at, licensed under CC BY 4.0. When you publish results obtained through this server, credit Statistik Austria as the source.

This is an independent project and is not affiliated with or endorsed by Statistik Austria.

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project

  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)

  3. Commit your Changes (git commit -m 'Add some AmazingFeature')

  4. Push to the Branch (git push origin feature/AmazingFeature)

  5. Open a Pull Request

Top contributors:

License

Distributed under the MIT license. See LICENSE for more information.

Contact

Daniil Vasilcovschii - LinkedIn - GitHub

Project Link: https://github.com/DV155/Statistik-Austria-MCP-Server

Available Tools

3 tools
fetch_dataset_csvA

Fetch an OGD dataset's data with codes resolved to German labels, formatted "label ". dataset_id is the Statistik Austria dataset identifier (e.g. "OGD_vpi86_VPI_1986_1"). "aggregate" names the dimensions in which a row is a total of other rows; never sum it with them. Empty "aggregate" does not guarantee rows can be summed (overlapping groupings exist, e.g. VPI). Dimensions in "unlabeled_dimensions" have raw codes and no aggregate information. filters: {dimension code: [value codes]} keeps matching rows, e.g. {"C-A10-0": ["A10-2024"]}; values are the parts. Pages: at most limit rows (max 5000, fewer if rows are large); if "truncated", continue at offset + returned with the same filters.

NameRequiredDescriptionDefault
limitNo
offsetNo
filtersNo
dataset_idYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it discloses pagination behavior and the "truncated" flag, the 5000-row cap with rows possibly being large, the aggregate-total pitfall, and that empty aggregate does not guarantee summable rows. It omits any mention of error behavior for invalid dataset_ids or permissions.

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?

Purpose is front-loaded, then detail escalates from identifier to aggregate semantics to filters to paging — a sensible order. The paging sentence ("continue at offset + returned") is slightly compressed and takes a reread, but no line is wasted.

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 4-parameter tool with no annotations and no output schema, the description covers the response shape (label-and-code formatting, aggregate and unlabeled_dimensions columns, truncation) well enough to call it correctly. What it lacks is any statement of failure modes or how to discover valid dataset_ids and dimension codes beforehand.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate and it does: dataset_id is explained with a concrete example, filters get exact syntax and a worked example with the caveat that values are the <code> parts, and limit/offset are given defaults semantics, a max, and a continuation rule.

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?

States a specific verb and resource ("Fetch an OGD dataset's data") plus a distinguishing output trait (codes resolved to German labels, formatted "label <code>"). It never mentions the sibling fetch_dataset_json, so the agent must infer the CSV-vs-JSON distinction from the tool names alone.

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?

Operational guidance is strong — how to filter, how to page with offset/limit, and the caveat about summing aggregate rows — but there is no explicit statement of when to choose this tool over fetch_dataset_json or search_dataset. Usage is implied by the output format rather than stated as a selection rule.

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

fetch_dataset_jsonA

Return the dimension and measure metadata for an OGD dataset. dataset_id is the Statistik Austria dataset identifier (e.g. "OGD_vpi86_VPI_1986_1").

NameRequiredDescriptionDefault
dataset_idYes

TDQS

A3.6/5.0
Behavior3/5

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

No annotations exist, so the description carries the full burden. It does usefully disclose that the response is metadata (dimensions and measures), not the underlying observations, which prevents a caller from expecting data rows. However, it says nothing about failure behavior for invalid dataset_ids, response size, or any access constraints.

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?

Two short sentences, both load-bearing, with the return content stated first and the parameter clarification second. No filler.

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?

For a single-parameter read tool with no output schema, the description covers what is returned only at a high level ('dimension and measure metadata') and does not indicate the shape of that metadata. Adequate to call correctly, but thin on what to expect back.

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 0% — the schema only says 'Dataset Id' with no description — so the description must compensate. It does: it identifies the identifier as a Statistik Austria dataset id and gives a concrete format example ('OGD_vpi86_VPI_1986_1'), which is exactly what the schema lacks.

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 states a specific verb and resource: returns 'dimension and measure metadata for an OGD dataset.' That is materially more precise than the name alone, which only says 'json.' It doesn't explicitly contrast with fetch_dataset_csv or search_dataset, so differentiation from siblings is left to the name.

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?

Usage is implied rather than stated: an agent can infer this is the JSON-format metadata variant, but the description never says when to prefer it over fetch_dataset_csv or search_dataset, and gives no prerequisites or exclusions.

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

search_datasetA

Search the OGD catalog by keyword. Every query word of 3+ characters must appear in a result; word parts match too. An empty query returns recently updated datasets. Titles are in German, so search with German keywords (e.g. "Bevölkerung", not "population"). Pass a result's "id" to fetch_dataset_json or fetch_dataset_csv.

NameRequiredDescriptionDefault
limitNo
queryNo

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden and discloses the non-obvious matching semantics: all query words of 3+ characters must be present, and partial word matching applies. The empty-query fallback behavior and the German-language constraint are also surfaced. It stops short of stating rate limits, pagination, or what fields a result contains beyond "id".

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?

Front-loads the core purpose, then matching rules, then the language caveat, then the follow-up routing — a logical order with no filler. Slightly dense with line-break artifacts, but every sentence carries information.

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 two-parameter search tool with no annotations and no output schema, the description covers the critical unknowns: matching logic, empty-query behavior, language of titles, and the ID handoff to fetch tools. The remaining gap is the shape of a result and the meaning/bounds of "limit", which an agent must discover by calling.

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 0%, so the description must compensate. It explains the "query" parameter thoroughly (AND-matching, 3-character minimum, empty-string meaning) but says nothing about "limit" — its default of 20 is visible in the schema, yet the maximum or cost implications are unexplained.

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?

States a specific verb and resource ("Search the OGD catalog by keyword") and explicitly distinguishes itself from the two siblings by naming them and describing the follow-up step. An agent can tell instantly this is the discovery entry point and that fetch_dataset_json/csv are the retrieval steps.

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?

Gives concrete when-to-use guidance: empty query returns recently updated datasets, and keywords must be German because titles are German (with an example contrasting "Bevölkerung" vs "population"). It also routes the agent onward by telling it to pass a result's "id" to the fetch siblings.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv1.0.0
    • First observedfetch_dataset_csv
    • First observedfetch_dataset_json
    • First observedsearch_dataset

TDQS

A4.1/5.0

Scored across 3 tools

Disambiguation5/5

The three tools map cleanly to distinct stages: catalog search, dataset metadata, and dataset data retrieval. The JSON vs CSV tools are differentiated by description as metadata versus data, so an agent can choose without ambiguity.

Naming Consistency5/5

All names use lowercase snake_case and identify the dataset resource clearly. fetch_dataset_json and fetch_dataset_csv share a predictable pattern, while search_dataset follows the same verb_noun style.

Tool Count5/5

Three tools are well scoped for a focused statistics-catalog server: search, inspect metadata, and fetch data. Each has a clear role, with no redundant tools.

Completeness4/5

The core workflow is covered: find a dataset, inspect its dimensions and measures, then fetch filtered paginated data. Minor gaps remain around catalog browsing features or data validation, but the main lifecycle is usable.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to search, explore, and query any CKAN open data portal through natural language, making public datasets accessible without requiring knowledge of the portal's API.
    20
    1,614 npm
    59
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to search and query datasets from Slovenia Open Data (podatki.gov.si) via its CKAN API, including searching datasets, retrieving metadata, and querying tabular resources.
    8 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables language models to search and query Statistics Netherlands open data, turning natural-language questions into traceable statistics by discovering tables, resolving codes, and retrieving filtered observations.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to search, preview, and query Ireland's public-sector open data catalogue, including CSV, Excel, JSON, GeoJSON, and JSON-stat resources. It supports filtering, grouping, counting, summing, and sorting datasets conversationally without manual downloads or cleanup.
    MIT