Skip to main content
Glama

ISTAT MCP Suite

Server MCP che espone i dati statistici ufficiali dell'ISTAT a un agente LLM, attraverso le API SDMX REST di esploradati.istat.it.

L'obiettivo è pratico: le API SDMX dell'ISTAT sono complete ma poco indulgenti — id criptici, chiavi posizionali, codeliste da 12.000 voci, endpoint che a volte non rispondono affatto. Un agente lasciato a interrogarle direttamente spreca token, va in timeout e si fa bloccare l'IP. Questo server si occupa di quella parte.


Indice


Related MCP server: mcp-istat-it

Cosa fa

Ricerca dataset

Cerca fra i ~4.700 dataflow ISTAT per parole chiave, senza doverne conoscere l'id.

Metadati a costo graduato

Struttura, dimensioni e codici di un dataflow, chiedendo solo quello che serve invece di scaricare tutto.

Estrazione dati

Risposta inline per query piccole, download su file per quelle grandi, con diagnosi leggibile quando la chiave è sbagliata.

Risoluzione territoriale offline

8.039 codici REF_AREA (comuni, province, regioni, ripartizioni) risolti da un file locale, senza toccare la rete.

Cache a due livelli

In memoria (L1) + su disco (L2). Le codeliste sono condivise fra dataflow e valide 90 giorni.

Rate limiting adattivo

Due finestre scorrevoli separate per endpoint leggeri e pesanti, che si restringono da sole quando ISTAT protesta.


Installazione

Serve Python ≥ 3.11. Con uv:

git clone https://github.com/ManoloZocco/istat-mcp-suite.git
cd istat-mcp-suite
uv sync

Verifica che parta:

uv run python -m istat_mcp.cli --transport stdio

Il processo resta in attesa sullo stdin: è il comportamento corretto per un server MCP in modalità stdio. Interrompi con Ctrl+C.

Modalità di trasporto

# STDIO — per Claude Desktop, Claude Code, Cursor e client locali in genere
uv run python -m istat_mcp.cli --transport stdio

# SSE / HTTP — per deploy remoti o client che parlano HTTP
uv run python -m istat_mcp.cli --transport sse --host 0.0.0.0 --port 8000

Collegare un client MCP

Esempio per Claude Desktop (claude_desktop_config.json) o qualunque client che usi lo stesso formato:

{
  "mcpServers": {
    "istat": {
      "command": "uv",
      "args": [
        "--directory", "/percorso/assoluto/a/istat-mcp-suite",
        "run", "python", "-m", "istat_mcp.cli", "--transport", "stdio"
      ]
    }
  }
}

Con Claude Code:

claude mcp add istat -- uv --directory /percorso/assoluto/a/istat-mcp-suite \
  run python -m istat_mcp.cli --transport stdio

I tool disponibili

discover_dataflows(query, limit)

Cerca per parole chiave nel catalogo dei dataflow. Restituisce id, nome italiano e id della datastructure. È il punto di partenza quando non si conosce già l'id.

Il catalogo completo viene scaricato una volta (~2 MB, ~35 s) e messo in cache per 30 giorni; le ricerche successive sono locali.

get_constraints(dataflow_id, dimensions_only, dimension, max_codes_per_dimension, wait_seconds)

Metadati di un dataflow: dimensioni con la loro posizione SDMX, la codelist che sta dietro a ciascuna, e i codici validi con le etichette italiane.

Ha tre modalità, in ordine di costo crescente:

Chiamata

Cosa ottieni

Costo

dimensions_only=True

Ordine e posizione delle dimensioni, template della chiave

1 richiesta, pochi secondi su qualunque dataflow

dimension='NOME_DIM'

I codici di una sola dimensione

1–2 richieste

default

Tutte le dimensioni con i codici

Può richiedere minuti, o restituire un risultato parziale

Il troncamento è sempre dichiarato nella risposta (truncated, total_codes, truncation_note) e tiene per primi i codici più aggregati: le sezioni NACE e i totali prima delle sottoclassi, le regioni prima dei comuni.

Se l'endpoint availableconstraint di ISTAT non risponde entro wait_seconds, la chiamata non si blocca: torna con status: "downloading" o "partial", la struttura resta valida, e il download prosegue in background finendo in cache per la chiamata successiva.

get_data(dataflow_id, key_filter, start_period, end_period, format, last_n_observations, max_inline_rows, force_file_download)

Estrae i dati veri e propri.

key_filter è una chiave SDMX puntata, non un dizionario: un segmento per dimensione, nell'ordine di posizione dato da get_constraints.

A.053011.W_SUPPL+W_TOTLOS     # frequenza annuale, comune di Grosseto, due misure
..W_SUPPL+W_TOTLOS            # le stesse due misure, tutti i comuni, ogni frequenza
  • Segmento vuoto = tutti i valori di quella dimensione.

  • Più valori sullo stesso segmento si separano con +.

  • TIME_PERIOD non fa parte della chiave: si filtra con start_period / end_period.

Sotto le 500 righe la risposta è inline; oltre — o sopra 1 MB, o con force_file_download=True — il dataset viene scritto su disco in ~/.cache/istat_mcp/downloads e la risposta contiene percorso, dimensione e anteprima.

Quando ISTAT rifiuta la chiave (422/400/404), la risposta include l'arità attesa, il template corretto, il messaggio SDMX originale e un suggerimento su cosa correggere, invece del solo errore HTTP.

get_territorial_codes(search, level, limit)

Risoluzione offline su 8.039 entità REF_AREA: 1 nazione, 5 ripartizioni, 22 regioni e province autonome, 107 province, 7.904 comuni. Ricerca case-insensitive su nome, codice REF_AREA e codice ISTAT.

search='Grosseto', level='comune'  ->  053011
search='Grosseto', level='provincia'  ->  053

Da preferire sempre a get_constraints per la dimensione territoriale: è istantaneo, non consuma slot del rate limiter e non rischia il blocco IP. Il dataset si rigenera con python scripts/build_territorial_codes.py.

get_concepts(concept_id)

Definizione semantica di un concetto SDMX (REF_AREA, FREQ, …).

get_structure_diagram(dataflow_id)

Diagramma Mermaid della struttura dimensionale di un dataflow. Usa internamente dimensions_only, quindi è veloce e immune allo stallo di availableconstraint.

get_cache_diagnostics()

Stato della cache, occupazione su disco, elenco dei file scaricati.


Come lo usa un agente

Il percorso che funziona, dal nome di un fenomeno alla tabella di dati:

flowchart TD
    A["Serve un dato ISTAT"] --> B["discover_dataflows('verde urbano')"]
    B --> C["get_constraints(id, dimensions_only=True)"]
    C --> D{"Serve un territorio?"}
    D -->|sì| E["get_territorial_codes('Grosseto', level='comune')"]
    D -->|no| F["get_constraints(id, dimension='DATA_TYPE')"]
    E --> F
    F --> G["get_data(id, key_filter='A.053011.W_SUPPL')"]
    G --> H{"Risposta grande?"}
    H -->|inline| I["Dati nel contesto"]
    H -->|file| J["Percorso su disco, da leggere con gli strumenti locali"]

Le regole che fanno la differenza fra una sessione che funziona e una che brucia token e finestre di rate limit:

  1. Partire sempre da dimensions_only=True. Dà l'ordine delle dimensioni e il template della chiave — cioè tutto quello che serve per costruire key_filter — in una sola richiesta. Enumerare i codici di tutte le dimensioni prima di sapere quali servono è lo spreco più comune.

  2. Per i territori usare get_territorial_codes, mai get_constraints. CL_ITTER107 ha 12.471 codici: chiederli a ISTAT quando la risposta è già su disco è tempo e rischio buttati.

  3. Chiedere una dimensione alla volta con dimension='<ID>' invece della risoluzione completa.

  4. Sui dataflow con serie storiche lunghe passare last_n_observations. Senza vincolo temporale ISTAT scandisce l'intera serie e la richiesta va in timeout; con last_n_observations=1 la stessa estrazione risponde in pochi secondi.

  5. Usare force_file_download per i dataset grandi, invece di far passare megabyte di TSV dalla finestra di contesto.

  6. Leggere status nella risposta. "downloading" e "partial" non sono errori: sono risposte valide su cui si può già lavorare, e la chiamata successiva troverà il resto in cache.


Limiti dell'API ISTAT

Comportamenti verificati contro esploradati.istat.it. Non sono bug di questo server: sono il terreno su cui lavora, ed è utile conoscerli anche solo per interpretare le risposte.

availableconstraint è l'endpoint che si pianta. Su 183_1163_DF_DICA_ASIAULP_TERRIFDATA_7 non ha risposto dopo 600 s, mentre sullo stesso dataflow la struttura arriva in ~4 s e l'intera DSD con tutte le codeliste (11 MB) in ~9 s. Su altri dataflow lo stesso endpoint risponde in 34 s, o fra 4 e 46 s a seconda del momento. Per questo viene scaricato in background e la risposta torna comunque.

Le codeliste sono enormi ma veloci. CL_ITTER107 sono 12.471 codici (9,1 MB in ~4 s), CL_ATECO_2007 2.063. Il problema che creano non è il tempo ma il limite di token della risposta: di qui il troncamento dichiarato.

Un id di dataflow non è un id di datastructure. 609_1_DF_DCCV_URBANENV_1 è servito dalla DSD DCCV_URBANENV, 22_389 da DCIS_POPRES1. Interrogare datastructure/IT1/<dataflow_id> restituisce sempre 404.

ISTAT serve SDMX-CSV anche quando si chiede TSV. La risposta riporta il formato reale in format e quello richiesto in requested_format; il file salvato prende l'estensione reale.

Sugli endpoint di struttura serve un Accept XML esplicito, altrimenti ISTAT restituisce SDMX-JSON che i parser XML non digeriscono.

Un codice presente nella codelist può non essere pubblicato dal dataflow. CL_TIPO_DATO_CIS ha 260 tipi di dato, ma un dato dataflow può esporne due. In quel caso ISTAT risponde 404 NoRecordsFound, che significa "nessuna osservazione", non "codice inesistente".

Il catalogo dei dataflow va chiesto con detail=allstubs: ~2 MB / ~35 s invece di ~13 MB / ~70 s.


Blocco dell'indirizzo IP

⚠️ Il limite più importante da conoscere.

ISTAT non pubblica alcun limite di frequenza: le risposte non contengono header X-RateLimit-*Retry-After, e raffiche brevi passano senza throttling. Non esiste quindi una soglia documentata a cui attenersi.

Esiste però un blocco a livello di indirizzo IP: dopo un uso intenso e prolungato — molte estrazioni dati pesanti, sessioni lunghe, download ripetuti — esploradati.istat.it smette di rispondere da quell'IP. Non arriva un 429 con una spiegazione: le richieste iniziano semplicemente a fallire o a non tornare più, anche dopo aver rallentato.

Come si riconosce: tutte le richieste falliscono o vanno in timeout, comprese quelle leggere che prima rispondevano in pochi secondi, e il sito ISTAT è irraggiungibile anche dal browser sulla stessa rete.

Come si risolve: cambiando indirizzo IP pubblico.

  • Su una linea domestica con IP dinamico: riavviare il modem/router e attendere che il provider ne assegni uno nuovo (a volte servono alcuni minuti di modem spento perché il vecchio lease scada).

  • In alternativa: passare a un'altra rete (hotspot del telefono), o usare una VPN che esca da un IP diverso.

  • Se l'IP è statico, non c'è modo di sbloccarlo se non aspettare.

Come si evita. Il server è costruito per ridurre il rischio, ma non può azzerarlo:

  • La cache su disco (30 giorni per la struttura, 90 per le codeliste) fa sì che il lavoro ripetuto non arrivi mai a ISTAT.

  • Il rate limiter separa gli endpoint per costo: struttura a 20/min, dati e availableconstraint a 3/min, ed entrambe le finestre si dimezzano su un 429 o 503 e risalgono di uno slot ogni due minuti.

  • La risoluzione territoriale è completamente offline.

Il resto dipende dall'uso: preferire dimensions_only e dimension=, non riscaricare dataset già presenti in ~/.cache/istat_mcp/downloads, ed evitare di lanciare estrazioni sull'intero catalogo. La cache va tenuta, non svuotata: cancellarla significa rifare da capo tutte le richieste che aveva assorbito.


Configurazione

Tutte le impostazioni si sovrascrivono con variabili d'ambiente o con un file .env nella directory di lavoro.

Variabile

Default

Note

ISTAT_SDMX_BASE_URL

https://esploradati.istat.it/SDMXWS/rest

Endpoint SDMX

REQUEST_TIMEOUT_SECONDS

180

Timeout richieste normali

DOWNLOAD_TIMEOUT_SECONDS

900

Timeout lettura per i download in streaming

RATE_LIMIT_REQUESTS

3

Slot/minuto per data e availableconstraint

METADATA_RATE_LIMIT_REQUESTS

20

Slot/minuto per gli endpoint di struttura

RATE_LIMIT_WINDOW_SECONDS

60

Ampiezza della finestra scorrevole

RATE_LIMIT_RECOVERY_SECONDS

120

Intervallo di recupero di uno slot dopo un 429/503

CACHE_DIR

~/.cache/istat_mcp

Cache L2 su disco

MCP_STORAGE_DIR

~/.cache/istat_mcp/downloads

Dataset scaricati

MAX_INLINE_ROWS

500

Soglia oltre la quale si passa al file

METADATA_TTL_SECONDS

2592000 (30 g)

TTL metadati

DATA_TTL_SECONDS

86400 (24 h)

TTL dati

MCP_STORAGE_DIR sta sotto $HOME e non nella directory del progetto di proposito: un percorso relativo al repo non è raggiungibile da una shell in sandbox, e i file risulterebbero elencati dal tool ma non leggibili.


Sviluppo

uv run pytest              # suite completa
uv run pytest -q           # output compatto

Struttura del sorgente:

src/istat_mcp/
├── cli.py              # entry point, scelta del trasporto
├── config.py           # impostazioni (pydantic-settings)
├── server.py           # registrazione dei tool su FastMCP
├── core/
│   ├── cache.py        # cache L1 in memoria + L2 su disco
│   ├── client.py       # client SDMX, rate limiting, retry, streaming
│   └── storage.py      # scrittura dei dataset su disco
├── data/
│   ├── territorial_codes.json
│   └── territory.py    # risolutore territoriale offline
└── tools/
    ├── data.py         # get_data, diagnostica cache
    ├── discovery.py    # discover_dataflows
    └── metadata.py     # get_constraints, concetti, diagrammi, territori

Due vincoli da rispettare toccando il codice:

  • Le funzioni dei tool non accettano il client SDMX come parametro. FastMCP costruisce il modello degli argomenti con pydantic a partire dalle annotazioni: una classe arbitraria come IstatSDMXClient nella firma fa fallire ogni chiamata con PydanticSchemaGenerationError, prima ancora della richiesta HTTP. Tutti i tool usano il singleton istat_mcp.core.client.global_client.

  • I tool restituiscono oggetti JSON strutturati, non stringhe JSON annidate, così il client fa un solo parse.


Licenza

MIT.

I dati restano dell'Istituto Nazionale di Statistica e sono soggetti alle condizioni d'uso pubblicate su istat.it. Questo è un progetto indipendente, non affiliato con l'ISTAT.

Available Tools

7 tools
discover_dataflowsA

Search ~4,700 available ISTAT statistical datasets (dataflows) by keywords. Returns dataflow id, Italian name and the datastructure id to feed into get_constraints.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoNumero massimo di dataflow restituiti (default 10).
queryYesParole chiave da cercare nel nome o nell'ID del dataflow, es. 'ambiente urbano'.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It discloses the search scope and return fields, but does not detail search semantics (e.g., case sensitivity, fuzzy matching), pagination behavior, error handling, or potential rate limits. The description gives a basic behavioral overview but lacks depth beyond the obvious read-only search nature.

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 long, front-loaded with the primary action, and contains no filler. Every sentence contributes useful information—what it does, what it returns, and how the output is used.

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 search tool with a full input schema and an output schema present, the description is complete. It provides the purpose, the output fields, and the downstream usage context (get_constraints), leaving no critical gaps for an agent to invoke it effectively.

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?

The schema covers 100% of parameters with descriptions (query and limit). The tool description adds the workflow context that the datastructure id is used for get_constraints, but it does not add new meaning to the parameters themselves. Baseline 3 is appropriate given the high schema coverage.

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 a specific purpose: 'Search ~4,700 available ISTAT statistical datasets (dataflows) by keywords.' It distinguishes this tool from siblings by focusing on the discovery step and specifying the return fields (dataflow id, Italian name, datastructure id), which directly supports downstream use with get_constraints.

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 explicitly indicates when to use this tool by stating the output is 'to feed into get_constraints,' providing a clear workflow context. It does not explicitly mention exclusions or alternative tools, but the context is sufficient for an agent to understand this is for discovering dataflows before retrieving constraints.

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

get_cache_diagnosticsA

Inspect cache hit/miss diagnostics, disk usage, and downloaded files list.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. 'Inspect' implies a read-only operation, but it does not explicitly state there are no side effects, whether diagnostic state is refreshed, or if certain permissions are required. It names what is inspected but omits behavioral details.

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 a single, well-structured sentence that front-loads the key action ('Inspect cache diagnostics') and appends the supporting details. Every word earns its place, with no redundancy or fluff.

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 zero-parameter nature and the existence of an output schema, the description adequately scopes the tool's purpose. It lists the three diagnostic areas covered, which is sufficient for an agent to decide when to use it and what to expect.

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 trivially 100%. The description correctly omits parameter details since none exist, and no additional semantics are needed for this parameterless tool.

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 uses the specific verb 'Inspect' and names a clear resource: cache hit/miss diagnostics, disk usage, and downloaded files list. This clearly distinguishes it from sibling tools that focus on constraints, concepts, dataflows, structure diagrams, and data retrieval.

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 provides clear context on what data is returned (cache diagnostics, disk usage, files list), making it straightforward to know when to use this tool. It does not explicitly name alternatives or exclusions, but the subject matter is distinct from all sibling tools.

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

get_conceptsA

Get semantic definitions for ISTAT SDMX concept IDs (e.g. REF_AREA, FREQ).

ParametersJSON Schema
NameRequiredDescriptionDefault
concept_idNoID del concetto SDMX da descrivere, es. 'REF_AREA', 'FREQ', 'DATA_TYPE'. Se omesso restituisce l'intero ConceptScheme CS_ISTAT.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It indicates a non-mutating read operation ('Get'), but it does not disclose error handling, length limits, or the behavior when concept_id is omitted (though this is partially covered by the schema). For a simple read tool, this is adequate but not rich.

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 a single, front-loaded sentence that immediately states the action and target. It contains no filler words and is optimally concise for a simple read operation.

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's simplicity (one optional parameter), an output schema, and a clear description, the context is mostly complete. It could mention that omitting concept_id returns the full ConceptScheme, but that detail is already in the schema, so the description suffices.

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?

The schema already describes the single parameter completely (100% coverage), including the default behavior and examples. The tool description adds no new information beyond repeating the examples, so it meets the baseline for high schema coverage.

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 the tool retrieves semantic definitions for ISTAT SDMX concept IDs, with concrete examples (REF_AREA, FREQ). This specific verb+resource combination distinguishes it from sibling tools like get_data or get_constraints.

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 purpose implies when to use the tool (when you need concept definitions), but there is no explicit guidance on when not to use it or which sibling tool to choose instead. A brief note on exclusion would improve clarity.

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

get_constraintsA

Single-Call Metadata Tool: retrieves dimensions (with their position), valid constrained code values, and human-readable Italian/English labels for an ISTAT dataset in 1 query. Replaces the separate get_structure and get_codelist_description tools of earlier versions. Call this before get_data to build the key_filter.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataflow_idYesID del dataflow ISTAT, come restituito da discover_dataflows. Esempio: '609_1_DF_DCCV_URBANENV_1'. (Nelle versioni precedenti del server questo parametro si chiamava 'id_dataflow'.)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

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

No annotations are provided, so the description carries the full burden. It discloses that the call is a single query, returns three kinds of data (dimensions, codes, labels), and notes that the parameter name changed from 'id_dataflow' in earlier versions. This is useful behavioral context, though it does not mention error conditions 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.

Conciseness5/5

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

The description is three sentences long, with the main purpose in the first sentence, differentiation in the second, and usage direction in the third. Each sentence adds distinct value without redundancy.

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 tool has only one required parameter and an output schema, so the description doesn't need to detail return formats. It covers the tool's role in the workflow ('before get_data'), the parameter source (in schema), and replaces older tools. A slight gap is that it doesn't explain how to construct the key_filter, but that is likely beyond the tool's scope.

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?

The input schema already provides 100% coverage for dataflow_id, including an example and note about the previous parameter name. The description itself does not add additional parameter-level semantics beyond that, so the baseline score of 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 the tool 'retrieves dimensions (with their position), valid constrained code values, and human-readable Italian/English labels' for an ISTAT dataset. It distinguishes this tool from siblings by noting it replaces get_structure and get_codelist_description and by emphasizing 'Single-Call'. This makes the purpose unambiguous.

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 explicitly instructs 'Call this before get_data to build the key_filter', giving a clear temporal usage context. It also names the separate tools it replaces, effectively telling the agent which older alternatives to avoid. This provides both a when and a when-not.

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

get_dataA

Fetch statistical data from ISTAT. Returns formatted text inline for small queries and automatically downloads to a local disk file for large datasets, for payloads above 1 MB, or when force_file_download=True. The key_filter is a dotted SDMX key string (e.g. 'A.053011.W_SUPPL+W_TOTLOS'), not a dictionary. On dataflows with long time series (e.g. 22_389) pass last_n_observations=1, otherwise ISTAT scans the whole series and the request times out.

ParametersJSON Schema
NameRequiredDescriptionDefault
formatNoFormato richiesto a ISTAT (default 'tsv'). Attenzione: l'endpoint SDMX di ISTAT serve SDMX-CSV anche quando si chiede TSV. Il campo 'format' della risposta riporta il formato effettivamente ricevuto, 'requested_format' quello richiesto.tsv
end_periodNoPeriodo finale SDMX, es. '2022' o '2022-12'.
key_filterNoChiave SDMX in forma di stringa puntata, NON un dizionario. Un segmento per dimensione, nell'ordine di posizione restituito da get_constraints; segmento vuoto = tutti i valori; piu' valori sullo stesso segmento si separano con '+'. Esempio 609_1_DF_DCCV_URBANENV_1 (FREQ.REF_AREA.DATA_TYPE.TIME_PERIOD...): 'A.053011.W_SUPPL+W_TOTLOS' oppure '..W_SUPPL+W_TOTLOS' per tutti i comuni. Omesso, '.', 'all' o '*' = nessun filtro (l'intero dataflow). (Nelle versioni precedenti del server si chiamava 'dimension_filters'.)
dataflow_idYesID del dataflow ISTAT, es. '609_1_DF_DCCV_URBANENV_1'.
start_periodNoPeriodo iniziale SDMX, es. '2022' o '2022-01'.
max_inline_rowsNoSoglia di righe oltre la quale il risultato viene salvato su file invece che restituito inline (default 500).
force_file_downloadNoSe True salta l'output inline e scrive sempre il dataset su disco in MCP_STORAGE_DIR, restituendo percorso, dimensione e anteprima. Da usare per dataflow grandi (es. 22_389 popolazione residente).
last_n_observationsNoRestituisce solo le ultime N osservazioni di ogni serie. Indispensabile sui dataflow con serie storiche lunghe (es. 22_389): senza vincolo temporale ISTAT scandisce tutta la serie e la richiesta va in timeout, con last_n_observations=1 risponde in pochi secondi.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and discloses key behaviors: automatic switch from inline to file download based on payload size or force_file_download, the requirement for key_filter as a dotted SDMX string (not a dictionary), and timeout risks with long time series. This gives the agent a clear behavioral model before invocation.

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 three tight sentences, front-loaded with the core purpose, then the output behavior, then two critical parameter tips. Every sentence earns its place; there is no fluff or repetition.

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 8 parameters and an existing output schema, the description covers the essential operational decision (inline vs file), the key_filter syntax pitfall, and the timeout issue, all in a compact form. The output schema and rich parameter descriptions handle the remaining details, so the description is complete for its role.

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 the baseline is 3. The description adds operational depth beyond the schema: it explains the file-download trigger threshold, elaborates on the key_filter format with a concrete example, and contextualizes last_n_observations as a timeout mitigation for specific dataflows. Some information duplicates the schema, but the added usage context justifies a 4.

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 opens with 'Fetch statistical data from ISTAT', a specific verb and resource, and clearly distinguishes from sibling metadata tools (get_constraints, get_concepts, discover_dataflows) by targeting actual data retrieval. It also includes scope details like inline vs file output, making the purpose unambiguous.

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 provides clear contextual usage guidance: small queries return inline text, large datasets auto-download to a file, and force_file_download=True forces file output. It also gives an explicit troubleshooting tip (pass last_n_observations=1 for long time series to avoid timeouts). However, it does not explicitly name when-not-to-use alternatives, so it stops short of a 5.

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

get_structure_diagramA

Generate a Mermaid.js diagram showing dataset dimensions, codelists, and hierarchies.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataflow_idYesID del dataflow ISTAT, come restituito da discover_dataflows. Esempio: '609_1_DF_DCCV_URBANENV_1'. (Nelle versioni precedenti del server questo parametro si chiamava 'id_dataflow'.)

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?

No annotations are provided, so the description carries responsibility for disclosing behavior. The verb 'Generate' implies a read-only operation, and the output is described as a Mermaid.js diagram, but no details are given about potential side effects, permissions, or edge cases. With no annotations, this is minimal but not misleading.

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?

A single, front-loaded sentence states the tool's purpose and output format with no filler or repetition. Every word contributes to understanding, making it highly concise while retaining key 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?

The tool is simple with one parameter, a high-coverage schema, and an output schema, so the description does not need to explain return values. The only gap is the lack of explicit usage alternatives, but given the self-explanatory nature of generating a structural diagram, the description is sufficiently complete for an agent to select and invoke the 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% with one parameter, dataflow_id, fully described including an example and a note about a previous parameter name. The tool description itself adds no parameter-level information, so it relies entirely on the schema, which is sufficient at the baseline level.

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 uses a specific verb 'Generate' and clearly identifies the resource as a Mermaid.js diagram showing dataset dimensions, codelists, and hierarchies. This distinguishes it from sibling tools like get_data or get_constraints, which retrieve raw data or constraints rather than a structural diagram.

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 visual structural overview of a dataset is needed, but it does not explicitly state when to use this tool over alternatives like get_constraints or get_concepts. There is no when-not guidance or explicit mention of prerequisites, though the schema hints that dataflow_id comes from discover_dataflows.

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

get_territorial_codesA

Instant offline lookup across 8,039 official ISTAT REF_AREA territorial codes (Comuni, Province, Regioni, Ripartizioni). Case-insensitive on name, REF_AREA code and ISTAT code. Example: search='Grosseto', level='comune' -> 053011.

ParametersJSON Schema
NameRequiredDescriptionDefault
levelNoFiltro opzionale sul livello amministrativo. Omesso = tutti i livelli. Utile per distinguere il comune di Grosseto (053011) dalla provincia (053).
limitNoNumero massimo di risultati (default 10).
searchYesNome del territorio o codice REF_AREA da risolvere. Esempi: 'Grosseto', 'Toscana', '053011', 'ITE1'. Ricerca case-insensitive.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/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 burden of behavioral disclosure. It adds key traits: offline operation, case-insensitive search, and the ability to match by three fields (name, REF_AREA, ISTAT). It also gives a concrete example that illustrates expected input/output behavior. It does not mention error handling or edge cases, but for a simple lookup tool this is a reasonably transparent description.

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 exceptionally concise: two sentences that convey the tool's purpose, scope, matching behavior, and a worked example. There is no filler or repetition; every clause adds information. The example is well-placed and illustrative.

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, the complete parameter schema, and the presence of an output schema, the description is fully adequate. It explains what the tool does, how it matches, and what one can expect from a query. No critical information is missing for an agent to select and invoke this tool correctly.

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?

The schema already covers all three parameters with descriptions (100% coverage), so baseline is 3. The description adds value by clarifying that 'search' can match on name, REF_AREA code, and ISTAT code, and by providing a concrete example that ties 'search' and 'level' together. This goes slightly beyond the schema's individual 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 the tool performs an offline lookup for ISTAT territorial codes, enumerates the levels (Comuni, Province, Regioni, Ripartizioni), and gives an example. It distinguishes itself from sibling tools (which handle constraints, concepts, dataflows, etc.) by specifying a concrete lookup resource and scope.

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 implies when to use this tool: any time a user needs to resolve or search territorial names or codes. It provides context with the example and mentions case-insensitivity and the optional level filter. However, it does not explicitly state when not to use it or directly reference alternatives among sibling tools, so it misses full exclusionary guidance.

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. 7 tool updatesv0.1.0
    • First observeddiscover_dataflows
    • First observedget_cache_diagnostics
    • First observedget_concepts
    • First observedget_constraints
    • First observedget_data
    • First observedget_structure_diagram
    • First observedget_territorial_codes

TDQS

A4.1/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a distinct role: dataflow discovery, dataset constraints, concept definitions, structure diagrams, territorial code lookup, data retrieval, and cache diagnostics. Even the metadata-related tools (constraints, concepts, diagram, codes) are clearly separated by their specific inputs and outputs, so an agent should rarely confuse them.

Naming Consistency4/5

Most tools follow a consistent get_<noun> pattern (get_constraints, get_concepts, get_data, etc.), with one notable deviation: discover_dataflows. This is still acceptable since 'discover' conveys a search action, but it breaks the uniform get_ prefix. Overall the naming is predictable and readable.

Tool Count5/5

7 tools is well within the ideal range for a domain-specific server. Each tool serves a clear purpose in the workflow (discover → constrain → fetch → diagnose), and none are redundant or unnecessary. The count feels intentionally scoped.

Completeness4/5

The core workflow of discovering datasets, retrieving their constraints, and fetching data is fully covered. Supporting tools for semantic concepts, territorial codes, structure visualization, and cache diagnostics fill out the domain nicely. Minor gaps include an inability to list all dataflows without a keyword and no explicit way to get raw dataflow metadata beyond constraints, but these are workarounds rather than dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Provides access to Catalonia's statistical data via the IDESCAT Tables API v2. It enables users to navigate catalogs, inspect metadata, and query data with territorial filters and resolved labels.
    5
    1
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables querying Italian national statistics (ISTAT) data through natural language questions, with tools for accessing demographic, economic, and social indicators.
    6 npm
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables LLMs to access and analyze Italian statistical data from ISTAT via natural language queries, supporting dataset discovery, exploration, and data retrieval.
    9
    2
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables natural language discovery, querying, and analysis of Thailand's official statistics from the National Statistical Office via SDMX REST API. It provides tools for searching dataflows, exploring structures, and fetching data with caching and bilingual support.
    8
    MIT