Model Context Protocol server for accessing Italian National Statistical Institute (ISTAT) data
The ISTAT MCP server provides 6 read-only tools for accessing Italian statistical data. Tool naming follows verb_noun convention (get_, search_, list_) which is strong. However, descriptions are minimal, input schemas are sparse (only 2 parameters total across all tools), and critical details about output structure, pagination, and error handling are absent. The server uses fastmcp (HTTP transport), which is positive for protocol readiness. Definition quality places this at fair/C-tier: functional but with significant gaps in parameter documentation, output schema specification, and error recovery guidance.
Get data from a dataset with filters. Attempt to retrieve data, if it times out or is too big, return the URL of the file to download.
Get limited data from a dataset with filters. Returns only the first N records. Attempt to retrieve data, if it times out or is too big, return the URL of the file to download.
Get the dimensions of a dataset
Get the values of a dimension for a given dataset
Get a list of available datasets from ISTAT
Search datasets in ISTAT website by a query string
Output schemas not documented. Tools return JSON strings (via `.to_json(orient='records')`) but LLM has no visibility into field names, types, or structure. Response structure for `get_list_of_available_datasets`, `search_datasets`, `get_dataset_dimensions`, `get_dimension_values` is opaque to the agent.
No pagination support documented or implemented. `get_list_of_available_datasets()` and `search_datasets()` return all results as JSON strings with no offset, limit, or next_cursor parameters. If ISTAT returns thousands of datasets, context window is exhausted and LLM reasoning degrades.
Input schema for `get_data` and `get_data_limited` is underspecified. 'filters' parameter accepts `{"type": "object"}` with no properties, required fields, or examples. LLM cannot infer valid filter keys (e.g., must filters be dimension names? Are wildcards supported?). Description states 'A dictionary of filters' but provides no detail on structure.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 57 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Error handling incomplete. Main.py includes try-catch blocks with detailed error logging, but error responses returned to the LLM are minimal. Example: 'Error in get_dataset_dimensions' with suggestion text, but this is reactive logging, not forward guidance. LLM does not know if error is retryable, user-fixable, or fatal.
Descriptions are too brief to guide LLM decision-making. E.g., 'Get a list of available datasets from ISTAT' (46 chars) does not explain when to call this vs `search_datasets`, what structure is returned, or whether results are paginated. Baseline for A+ tools: 50-200 chars with WHAT/WHEN/FORMAT details.
Parameter descriptions are missing or minimal. 'dataflow_identifier' has description 'The identifier of the dataset' (33 chars), does not clarify format (alphanumeric? dots? example '139_176'?), case sensitivity, or where to find it. LLM must guess or call discovery tool first.
No tool annotation hints (readOnlyHint, destructiveHint, idempotentHint) present. Tools are read-only but do not declare this explicitly. Modern MCP clients could use readOnlyHint to optimize execution strategies.