Skip to main content
Glama
SidneyBissoli

ILO Statistics (ILOSTAT) MCP Server

ILO Labour Statistics (ILOSTAT) — MCP Server

MCP CI Version Tools Resources Prompts npm MCP Registry ilo-mcp-server MCP server License: MIT Status

🇧🇷 Leia em Português

A public, hosted, provenance-first MCP server for the International Labour Organization (ILO) statistics — the ILOSTAT database — no installation, no account, no API key. Point your MCP client at the hosted endpoint and ask about unemployment, employment, wages, working time and other labour indicators by country, year, sex and age. It runs on Cloudflare Workers over Streamable HTTP and talks to the official ILOSTAT SDMX REST API.

Independent project. This is an unofficial, community-built client of the ILO's public ILOSTAT API — not affiliated with or endorsed by the International Labour Organization. Data remain © ILO under CC BY 4.0; see Data license and attribution.

Every response carries a provenance block (source URL, data vintage, real retrieval timestamp, license, ILO citation) — exact figures with an audit trail, not numbers guessed from training data.

🇧🇷 Em português. Servidor MCP remoto e hospedado (nada para instalar, sem conta e sem chave) para as estatísticas de mercado de trabalho da OIT — desemprego, emprego, salários, jornada e informalidade por país, ano, sexo e idade, direto no Claude, no ChatGPT ou em qualquer cliente MCP, com proveniência e citação da fonte em cada resposta: README em português.

Questions it answers

In plain language, inside the MCP client — the assistant picks the tool and the filters:

  • "What has happened to unemployment in Brazil since 2015?" (ilo_get_data)

  • "Compare youth unemployment in Brazil, Mexico and South Africa." (ilo_compare_countries)

  • "How large is the gender pay gap, and where does the ILO publish it?" (ilo_search_indicatorsilo_get_data)

  • "What share of employment in India is informal?" (ilo_search_indicatorsilo_get_data)

  • "Which ILOSTAT dataflow has average monthly earnings by sex and economic activity?" (ilo_search_indicators)

  • "Which country, age and sex codes can I filter this indicator by?" (ilo_list_dimension_values)

  • "Give me a labour-market profile of Viet Nam." (ilo_country_labour_profile)

Ask in your words, not the ILO's. ILOSTAT is worded in British statistical English, and the catalogue is matched on the dataflow name — so the everyday or US word used to return nothing at all. Measured over the 1,212 dataflows of the official catalogue (2026-09-13), and fixed since 0.6.0: the search translates the term and tells you it did.

you ask

hits before

ILOSTAT writes

hits

labor, labor force

0

labour, labour force

176, 122

wages, salary

0

earnings

107

informality

0

informal

133

gender

2

sex

1,131

productivity

0

output per worker

4

jobless

0

unemployment

108

Related MCP server: world-bank-economic-mcp

Comparison with the alternatives

Anyone who already works with ILOSTAT has good tools, and this server replaces none of them — it sits somewhere else in the chain: it answers the question at the point where the question is asked, inside the assistant, with source, vintage and licence attached to the answer. Detail, side-by-side examples and the measured numbers in docs/alternatives.md.

Tool

What it is

When to prefer it

ilo-mcp-server (this)

Remote MCP server, hosted, nothing to install: 6 tools over the ~1,200 ILOSTAT dataflows, with a provenance block per answer

The question is asked in an assistant (Claude, ChatGPT, Cursor, Claude Code) and the answer has to be auditable

Rilostat 2.5.0 (R, CRAN)

The ILO's own R package, written by ILO staff: bulk download, metadata, filtering and reshaping

You are in R and want the dataset in a data frame — a whole table, repeatedly, for analysis

sdmx1 2.27.0 / pandaSDMX 1.10.0 (Python)

Generic SDMX clients; ILO is one of ~36 sources they know

Your pipeline is Python and you want SDMX objects, or the same code across several SDMX agencies

DBnomics (API, dbnomics for Python, rdbnomics 0.6.4 for R)

Aggregator that republishes 1,071 ILO datasets next to other providers, one API for all

You want ILO series alongside IMF, OECD, Eurostat in a single interface

ILOSTAT SDMX REST API

The source itself, which this server calls

You are building your own client and want full control

Do not use this server when you need a whole dataset rather than an answer (Rilostat's bulk download is the right tool), when the question is not labour statistics published by the ILO (education → UNESCO UIS, national accounts → IMF/World Bank), or when you need microdata: ILOSTAT publishes aggregates, and so does this server.

Sister servers, same design and same provenance block, for other official sources: IBGE (Brazilian statistics), BCB (Central Bank of Brazil), Senado (Brazilian Senate open data), SIH/SUS (Brazilian hospital admissions) and medical terminologies (ICD-11, ICD-10, LOINC, RxNorm, ATC, MeSH).

Use it (hosted — no setup)

Point any MCP client at the Streamable HTTP endpoint:

https://ilo.sidneybissoli.com/mcp

Claude Desktop / Claude Code and other clients with native remote support:

{
  "mcpServers": {
    "ilostat": {
      "url": "https://ilo.sidneybissoli.com/mcp"
    }
  }
}

For clients that launch MCP servers as a command, use the mcp-remote bridge:

{
  "mcpServers": {
    "ilostat": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://ilo.sidneybissoli.com/mcp"]
    }
  }
}

The ilo-mcp-server.sidneybissoli.workers.dev hostname is also served, as a secondary.

ChatGPT (Deep Research)

ChatGPT deep research (and company knowledge, and research workflows over the Responses API) only uses an MCP server that exposes exactly search and fetch — this server does, on top of the ilo_* tools. Point the connector at the hosted endpoint, no key required:

https://ilo.sidneybissoli.com/mcp

search ranks the query against the full ILOSTAT dataflow catalogue (~1,200 SDMX dataflows — employment, unemployment, wages, working time, informality, SDG labour indicators) and returns { id, title, url } (ind:<DATAFLOW_ID>, e.g. ind:DF_UNE_2EAP_SEX_AGE_RT); fetch returns the dataflow as readable Markdown — name, data vintage, dimensions and codelists, the ILO's default selection and how to query it with ilo_get_data — with the public ILOSTAT data explorer page as url, which is what ChatGPT cites. Both carry the same provenance block as every other tool, in structuredContent and _meta (the text channel is the contract's JSON). In ChatGPT's developer mode (Settings → Security and login → Developer mode) any tool is callable — the ilo_* tools remain the ones to use for data.

Run locally (stdio)

Prefer not to route queries through a third-party host? The same server also runs as a local stdio process that talks directly to the official ILOSTAT API — same 6 tools, resources and prompts, same limits, same provenance block, no Cloudflare in the loop.

No install needed — the package is on npm (ilo-mcp-server, Node ≥ 20):

{
  "mcpServers": {
    "ilostat": {
      "command": "npx",
      "args": ["-y", "ilo-mcp-server"]
    }
  }
}

Or from source:

git clone https://github.com/SidneyBissoli/ilo-mcp-server
cd ilo-mcp-server
npm install
npm run build
node dist/cli.js   # serves MCP over stdio (Ctrl+C to stop)

(then point the client at node /path/to/ilo-mcp-server/dist/cli.js).

Differences from the hosted server, all due to the absence of Cloudflare bindings: the SDMX cache lives in process memory (structures and codelists are reused within a session, not across sessions); the search catalogue is downloaded from the official endpoint on the first search (its real retrieved_at is reported in provenance); no usage metrics, rate limit or auth. Logs go to stderr — stdout carries only the JSON-RPC stream. The repository Dockerfile builds this runtime (used by the Glama registry).

Tools

Tool

What it does

Source

ilo_search_indicators

keyword search over ~1,210 dataflows (paginated by offset)

local catalogue (no upstream call)

ilo_get_indicator_metadata

dimensions, codelists, vintage and default selection of a dataflow

cached structure (miss → upstream)

ilo_list_dimension_values

valid codes of one dimension (paginated by offset)

cached codelist (miss → upstream)

ilo_get_data

observations filtered by dimension and period

1 live REST call per query

search

ChatGPT Deep Research contract: ranks a query against the full dataflow catalogue, returns { id, title, url } (ind:<DATAFLOW_ID>)

in-memory index built from the local catalogue (24 h)

fetch

ChatGPT Deep Research contract: one dataflow as readable Markdown with the public data explorer page as url

cached structure (miss → upstream)

Typical flow: ilo_search_indicatorsilo_get_indicator_metadata / ilo_list_dimension_values to discover valid filter codes → ilo_get_data with country and period filters.

Every response carries the provenance block v1.0 (@sbissoli/mcp-provenance, modes concise/detailed via the provenance_mode parameter) on three channels: structuredContent, namespaced _meta (com.sidneybissoli.ilostat/*) and a text footer.

Resources and prompts

Three resources (static, text/markdown, no upstream call) that a client can attach to the context before calling tools — they save the 2–3 discovery calls most sessions spend on "which dataflow, which codes":

URI

Content

ilostat://guide

tool workflow, stable code conventions (REF_AREA ISO3 + X-aggregates, SEX, AGE, FREQ, dataflow id suffixes), limits, reporting rules

ilostat://reference/key-dataflows

verified dataflow ids by topic (unemployment, employment, participation, wages, hours, informality, NEET, SDG 8, productivity)

ilostat://reference/provenance

meaning of every provenance field and how to cite the ILO

Three prompts — ready-made workflows that chain the tools and end with the citation rules (arguments are strings; period arguments optional):

Prompt

Arguments

Result

ilo_country_labour_profile

country, start_period, end_period

labour-market profile of one country (unemployment, participation, employment ratio, informality, NEET, earnings, hours)

ilo_compare_countries

countries, indicator, start_period, end_period

comparison table across countries/aggregates in one data call, flagging modelled estimates vs reported data

ilo_indicator_trend

indicator, country, start_period, end_period

time series of one indicator with first/last, peak/trough and OBS_STATUS breaks

Every dataflow id quoted in the resources and prompts is checked against the catalogue seed by the test suite, so the documentation cannot point at an id the search would not find.

Behaviour and limits

  • REF_AREA is required in ilo_get_data, up to 30 areas per call. The ILO gateway times out (HTTP 504) on unrestricted queries, so the server never issues one; for broad panels, split the areas into batches and/or paginate by period (start_period/end_period). The error message explains how.

  • One live REST call per data query. Data is never cached — every ilo_get_data result is fetched from ILOSTAT at request time. Dataflow structures (TTL 24 h) and codelists (TTL 7 days, shared across dataflows) are cached.

  • data_vintage is the dataflow's last-update date as published by the ILO (LAST_UPDATE annotation, normalised to ISO).

  • retrieved_at is always the real instant of extraction from ILOSTAT, preserved alongside any cached value — never the build or response time. Cached responses say so (served_from_cache: true).

  • The indicator catalogue is a local snapshot (~1,210 dataflows), refreshed periodically; its own retrieved_at is reported in the provenance of ilo_search_indicators, so its age is always visible.

  • Every upstream call carries an identifiable User-Agent (service URL + contact), so ILO administrators can reach the operator.

  • Language: English; timezone: UTC (ILO data is published in English).

Provenance fields

  • derivedtrue only for real transformation (aggregation, server-computed rate, interpolation, harmonisation), always with a derivation_note; unit conversion and rounding do not count. This server does not transform values, so derived is always false.

  • notices — reproduces the values of OBS_STATUS (the SDMX status/disclaimer channel, e.g. "Break in series"), verbatim and with counts. Technical per-observation attributes (DECIMALS etc.) stay on the rows (rows[].attributes).

Data license and attribution

  • ILOSTAT data and metadata: CC BY 4.0 (since 2023-05-03; license verified 2026-08-04).

  • ILO attribution in every response (citation field): International Labour Organization, ILOSTAT, https://ilostat.ilo.org/data/, accessed <date>.

  • The ILO logo is not used. This service is not endorsed by the ILO.

Self-hosting / development

Everything below is only needed to run your own instance — it is not required to use the public server.

npm install
npm run typecheck && npm test   # offline suite (parsers, key, tools, output contract, resources/prompts, in-memory catalogue, vocabulary, eval fixtures)
npm run dev                     # http://localhost:8787/mcp (Worker)
npm run build && npm start      # stdio runtime (dist/cli.js)

# Catalogue seed (D1) — required before first use:
node scripts/seed-catalog.mjs   # downloads via curl and generates scripts/seed-catalog.sql
npx wrangler d1 execute ilostat-catalog --local  --file=scripts/seed-catalog.sql
npx wrangler d1 execute ilostat-catalog --remote --file=scripts/seed-catalog.sql

npm run deploy
node scripts/smoke-mcp.mjs      # smoke test against production (initialize → 6 tools → search → fetch → errors)
npm run manifest:lhm            # regenerate tools/resources/prompts in lhm.plugin.json from the real server
# (the seed also writes tests/fixtures/catalog-ids.txt — the versioned id list the tests check resources/prompts against)

Bindings (see wrangler.jsonc): KV SDMX_CACHE, D1 CATALOG_DB, Durable Object USAGE (SQLite-backed usage counters), CF_VERSION_METADATA. Optional Bearer auth (wrangler secret put API_KEY); token-bucket rate limit per IP.

Notes for operators:

  • ILOSTAT returns JSON only when negotiated via the Accept header (application/vnd.sdmx.{structure,data}+json); ?format= is ignored and returns XML.

  • The ILO gateway answers HTTP 500 (languageTag1) to the Accept-Language: * header that Node's fetch (undici) sends by default; every upstream call therefore sets Accept-Language: en explicitly (Cloudflare's runtime sends no such header, so the Worker was never affected). It also expects an identifiable User-Agent.

  • Catalogue refresh is manual (no cron): quarterly, or immediately if a dataflow that exists upstream does not show up in search. Procedure: the three seed commands above. Data queries are always live, so only the search catalogue can age — and its age is exposed in provenance.

Evals

@sbissoli/mcp-evals: 24 fixtures in evals/fixtures/queries.ts, validated offline in npm test. The run with a real model (npm run eval) uses the Anthropic API and needs ANTHROPIC_API_KEY (without it, it exits with instructions). Run of 2026-08-07: top-1 100% (24/24)evals/results/.

End-to-end: 10 complex questions with a single verifiable answer in evals/e2e/evaluation.xml, answers validated manually against production (evals/e2e/validacao-respostas.md). Run of 2026-08-07 (Sonnet): 9/10 exact string; 10/10 substantiveevals/results/2026-08-07-e2e.md.

Endpoints

Route

Purpose

/

landing page (service identity + contact — public)

/health

liveness

/status

version, tool/resource/prompt counts and names, provenance contract version, current deploy (feeds the README badges)

/metrics

aggregated usage (MCP endpoint only; no IPs, no query content)

/mcp

MCP Streamable HTTP

Security

Snyk Agent Scan (2026-08-07): passed — report in security/.

License

Code: MIT. Data: ILOSTAT, CC BY 4.0 (see "Data license and attribution" above).

Privacy

Privacy policy of the hosted service: PRIVACY.md.

Contact

Sidney da S. P. Bissoli — sbissoli76@gmail.com. This service is not endorsed by the ILO.

Available Tools

6 tools
fetchDeep Research DocumentA
Read-onlyIdempotent
Inspect

Returns the full document for an id obtained from search, as { id, title, text, url, metadata }: text is the readable content (Markdown) and url the canonical public page to cite.

Companion of search in the OpenAI Deep Research contract, over the ILOSTAT labour statistics (≈1,200 SDMX dataflows: employment, unemployment, wages, working time, informality, SDG labour indicators) catalog. Only ids returned by search are valid; an unknown id returns an error. The ilo_* tools remain the tools for data queries.

Behavior: read-only and idempotent — a live GET against the public source when the document needs it.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesIdentifier of a document returned by `search`

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUnique identifier of the document on this server; what `fetch` takes
urlYesCanonical public URL of the document — ChatGPT's citation depends on it
textYesFull readable content of the document (Markdown)
titleYesHuman-readable title of the document
metadataNoAdditional key/value pairs about the document (kind, source, period…)
provenanceYes
attributionYes

TDQS

A4.9/5.0
Behavior5/5

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

The description adds meaningful behavior beyond the annotations: it is read-only and idempotent, performs a live GET against the public source when needed, and returns an error for unknown ids. It also discloses the return shape. This complements, rather than contradicts, the 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 well-structured: the core function and return shape come first, followed by context and behavior. It is concise enough that every sentence adds useful information, and it avoids repeating the schema or annotations.

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 one-parameter tool with an output schema and safety annotations, the description covers everything needed: source of ids, return format, error behavior, read-only nature, and relationship to sibling tools. Nothing critical is missing for correct invocation.

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 extra semantic value by specifying that the id must come from `search`, that only such ids are valid, and that unknown ids produce errors—details not present in the schema's parameter description.

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 action ('Returns the full document') and names the resource (document identified by an id from `search`). It also distinguishes itself from siblings by explicitly separating the `ilo_*` data-query tools from this document-fetch contract.

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?

It explicitly states when to use the tool: after obtaining an id from `search`, and only ids from `search` are valid. It also provides an exclusion by reserving `ilo_*` tools for data queries, so an agent knows this is not for statistical data retrieval.

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

ilo_get_dataGet ILOSTAT dataA
Read-onlyIdempotent
Inspect

Statistical observations from one ILOSTAT dataflow, filtered by dimension codes (filters, e.g. {"REF_AREA": ["BRA","ARG"], "SEX": "SEX_T"}) and period (start_period/end_period, e.g. "2015"/"2024"). REF_AREA is required, maximum 30 areas per call — for broad panels, split areas into batches and/or paginate by period. Unfiltered dimensions return all their categories. Does not aggregate, convert or otherwise transform values (raw ILOSTAT data only), and does not search indicators (use ilo_search_indicators).

ParametersJSON Schema
NameRequiredDescriptionDefault
filtersYesDimension id → code or list of codes (from ilo_list_dimension_values). REF_AREA is required (up to 30 area codes); any other dimension is optional and, left out, returns all of its categories.
dataflowYesDataflow id from ilo_search_indicators (e.g. "DF_UNE_DEAP_SEX_AGE_RT")
end_periodNoLast period, e.g. "2024"
start_periodNoFirst period, e.g. "2015"
provenance_modeNoProvenance verbosity: 'concise' (default — source, url, vintage, retrieval date, citation, license) or 'detailed' (full canonical block with dataset, dimension key and notices)
last_n_observationsNoAlternative to periods: only the latest N observations per series

Output Schema

ParametersJSON Schema
NameRequiredDescription
rowsYes
columnsYes
dataflowYes
provenanceYes
rows_countYes
attributionYes

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world), and the description adds real operational context beyond them: a 30-area cap per call, batching/pagination strategies, and the guarantee that values are never aggregated or transformed. It stops short of describing rate limits or failure modes beyond the schema's timeout note.

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?

It is front-loaded with the core purpose, then filters, then constraints, then exclusions — a logical progression with no filler. The sentences are long and dense, but each carries distinct information.

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?

With an output schema present, return values need not be explained, and the description covers everything else an agent needs: required filtering, size limits, period vs. last-N options, and scope exclusions. Nothing material is missing for correct invocation.

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, but the description goes further by showing a worked filter example that illustrates the string-vs-array value shapes and by clarifying the period parameters' format. This adds genuine meaning beyond the schema field 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 states a specific verb and resource — returning statistical observations from one ILOSTAT dataflow — and scopes it by dimension codes and period. It also explicitly distinguishes itself from the sibling ilo_search_indicators, so an agent can route between them without opening either schema.

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?

It gives concrete usage conditions (filter by dimension codes and period, unfiltered dimensions return everything) and names an alternative for a different job (ilo_search_indicators for indicator lookup). It also advises batching/pagination for broad panels, though it does not discuss the other siblings (fetch, ilo_get_indicator_metadata).

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

ilo_get_indicator_metadataGet ILOSTAT indicator metadataA
Read-onlyIdempotent
Inspect

Structure of one ILOSTAT dataflow: dimensions (in SDMX key order), their codelists, the time dimension, the source's default selection and the data vintage (last update at the ILO). Use before ilo_get_data to know which filters exist. Does not return statistical values and does not list the codes themselves (use ilo_list_dimension_values).

ParametersJSON Schema
NameRequiredDescriptionDefault
dataflowYesDataflow id from ilo_search_indicators (e.g. "DF_UNE_DEAP_SEX_AGE_RT")
provenance_modeNoProvenance verbosity: 'concise' (default — source, url, vintage, retrieval date, citation, license) or 'detailed' (full canonical block with dataset, dimension key and notices)

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
nameYes
versionYes
dimensionsYes
provenanceYes
attributionYes
data_vintageYes
time_dimensionYes

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/openWorld, so the safety profile is covered. The description adds substantive context beyond them: it defines the shape of the response and explicitly states two negative behaviors (no statistical values, no code enumeration), which prevents misuse. It does not mention pagination or response size, but for a metadata lookup that is minor.

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?

Three sentences, each load-bearing: the return structure first, the usage ordering second, the exclusions and alternative third. No filler and the most important content (what it returns and when to call it) is front-loaded.

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?

An output schema exists, so return-value detail is not the description's burden, and it still summarizes the payload structure. Combined with the explicit sibling routing, an agent has everything needed 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.

Parameters3/5

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

Schema description coverage is 100% and both parameters are documented there, including the dataflow id source and the provenance_mode enum values. The description adds no parameter-level detail, so the baseline 3 applies — the schema does the heavy lifting.

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+resource ('Structure of one ILOSTAT dataflow') and enumerates exactly what is returned: dimensions in SDMX key order, codelists, time dimension, default selection, and data vintage. It explicitly distinguishes itself from ilo_get_data (values) and ilo_list_dimension_values (codes).

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 explicit sequencing guidance ('Use before ilo_get_data to know which filters exist') and two clear exclusions with the correct alternative named for each ('does not return statistical values', 'does not list the codes themselves (use ilo_list_dimension_values)'). Nothing is left to inference.

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

ilo_list_dimension_valuesList valid codes of a dimensionA
Read-onlyIdempotent
Inspect

Valid codes (id + label) of one dimension of an ILOSTAT dataflow — e.g. the country/area codes of REF_AREA (ISO 3166-1 alpha-3 such as BRA, plus X-codes for aggregates such as X01 World) or the categories of SEX (SEX_T/SEX_M/SEX_F) and AGE. Use search to resolve a name to a code (e.g. search "Brazil") instead of paging through hundreds of codes; codelists are shared across dataflows, so a code found here is valid wherever the same codelist is used. Use to build correct ilo_get_data filters. Does not return statistical values, does not say which codes actually have data for a given dataflow, and is not applicable to the time dimension (filter it via start_period/end_period in ilo_get_data).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum codes returned (default 200)
offsetNoCodes to skip, for pagination (default 0)
searchNoCase-insensitive filter on code id or label
dataflowYesDataflow id the dimension belongs to
dimensionYesDimension id from ilo_get_indicator_metadata (e.g. "REF_AREA", "SEX")
provenance_modeNoProvenance verbosity: 'concise' (default — source, url, vintage, retrieval date, citation, license) or 'detailed' (full canonical block with dataset, dimension key and notices)

Output Schema

ParametersJSON Schema
NameRequiredDescription
offsetYes
valuesYes
showingYes
codelistYes
dataflowYes
has_moreYes
dimensionYes
provenanceYes
attributionYes
next_offsetNo
total_codesYes

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered. The description adds real behavioral scope beyond them: codelists are shared across dataflows, results exclude statistical values, and codes do not indicate which have data. It stops short of describing pagination defaults or the raw return shape, so a 4 rather than 5.

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-loaded with purpose, then usage, then exclusions, in a compact block with no filler sentences. It is dense and runs long in a single paragraph, which slightly reduces scanability, but each clause carries information.

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?

With an output schema present and annotations covering safety, the description only needed to supply scope and exclusions — which it does: shared codelists, absence of data-availability info, and the time-dimension carve-out. Nothing an agent needs to call it correctly 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 description coverage is 100%, so limit/offset/search/dataflow/dimension/provenance_mode are already documented in the schema; baseline 3 applies. The description adds the intent of `search` (name-to-code resolution) and implies paging, but no syntax or format detail 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?

States a specific verb and resource ('Valid codes (id + label) of one dimension of an ILOSTAT dataflow') and grounds it with concrete examples (REF_AREA ISO 3166-1 alpha-3, X-codes, SEX_T/SEX_M/SEX_F, AGE). An agent can distinguish this from ilo_get_data and search without opening a schema.

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?

Explicitly routes the agent: use `search` to resolve a name to a code instead of paging, and use this to build ilo_get_data filters. It also names an exclusion ('not applicable to the time dimension — filter it via start_period/end_period in ilo_get_data'), which is exactly the when-not guidance the dimension calls for.

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

ilo_search_indicatorsSearch ILOSTAT indicatorsA
Read-onlyIdempotent
Inspect

Search the ILOSTAT catalogue of ~1,200 indicator dataflows by keywords in the name or id (e.g. "unemployment rate sex age"). All terms must match (AND, case-insensitive), so start with 2–3 English words and drop terms if you get 0 results. Everyday and US wording is resolved to the ILO's own (labor→labour, wages/salary→earnings, informality→informal, gender→sex, productivity→output per worker); when that happens the response says so in vocabulary_notes. Results are ranked by ILO relevance weight, not by match count. Reading the id tells you the shape: suffix _RT = rate/ratio, NB = number (usually thousands); dataflows whose second token starts with 2 (e.g. DF_UNE_2EAP…) are ILO modelled estimates with full country/year coverage, the others are reported national data. Returns dataflow ids to use with ilo_get_data / ilo_get_indicator_metadata. Searches the local catalogue only — it does not return statistical values (use ilo_get_data), does not search dimension codes such as countries (use ilo_list_dimension_values) and does not cover non-ILO sources.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum results (default 20)
queryYesKeywords, matched against dataflow name and id (AND between terms)
offsetNoResults to skip, for pagination (default 0)
provenance_modeNoProvenance verbosity: 'concise' (default — source, url, vintage, retrieval date, citation, license) or 'detailed' (full canonical block with dataset, dimension key and notices)

Output Schema

ParametersJSON Schema
NameRequiredDescription
hintNo
offsetYes
showingYes
has_moreYes
indicatorsYes
provenanceYes
attributionYes
next_offsetNo
total_matchesYes
vocabulary_notesNo

TDQS

A4.9/5.0
Behavior5/5

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

While annotations already establish readOnly/idempotent/non-destructive behavior, the description goes well beyond them by disclosing AND semantics, case-insensitivity, synonym resolution, relevance ranking, id-shape conventions (_RT, _NB, 2-token modelled estimates), and vocabulary_notes behavior. No contradiction with annotations exists.

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 long but every sentence earns its place: purpose, query strategy, vocabulary behavior, ranking, id interpretation, and exclusions are all covered without redundancy. The core purpose is front-loaded before the detailed guidance.

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 output schema exists and the tool is a read-only search, the description covers everything an agent needs: what it searches, how to construct queries, how results are ordered, how to interpret ids, and which sibling tools to use for adjacent tasks. Nothing important is missing.

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, but the description adds meaning beyond the schema: it explains query semantics with examples, vocabulary mapping, ranking behavior, and how to interpret result ids. It doesn't add much about limit/offset/provenance_mode, but those are already fully described in 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 opens with a specific verb and resource: 'Search the ILOSTAT catalogue of ~1,200 indicator dataflows by keywords in the name or id.' It also differentiates itself from siblings by explicitly stating what it does not do: no statistical values, no dimension-code search, no non-ILO sources.

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?

Usage guidance is explicit and actionable: start with 2–3 English words, drop terms on zero results, and use alternatives for other needs (ilo_get_data for values, ilo_list_dimension_values for countries). It also names sibling tools directly, so an agent knows exactly when to choose this tool.

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. 6 tool updatesv0.6.0
    • Addedfetch
    • Changedilo_get_data8 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / filters / description
        Previous value: -"Dimension id → code or list of codes (from ilo_list_dimension_values). REF_AREA is required (up to 30 area codes)."New value: +"Dimension id → code or list of codes (from ilo_list_dimension_values). REF_AREA is required (up to 30 area codes); any other dimension is optional and, left out, returns all of its categories."
      • addedInput schema / properties / filters / properties
        Added value: +{
        +  "REF_AREA": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "items": {
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "type": "array"
        +      }
        +    ],
        +    "description": "Area codes — REQUIRED, at most 30 per call (e.g. [\"BRA\",\"ARG\"]). Without them the ILO gateway times out (HTTP 504). Discover codes with ilo_list_dimension_values (dimension REF_AREA)."
        +  }
        +}
      • removedInput schema / properties / filters / propertyNames
        Removed value: -{
        -  "type": "string"
        -}
      • addedInput schema / properties / filters / required
        Added value: +[
        +  "REF_AREA"
        +]
      • changedInput schema / required
        Previous value: -[
        -  "dataflow"
        -]New value: +[
        +  "dataflow",
        +  "filters"
        +]
      • removedOutput schema / properties / dataflow / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / dataflow / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedilo_get_indicator_metadata9 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • removedOutput schema / properties / data_vintage / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / data_vintage / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / dimensions / items / properties / codelist / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / dimensions / items / properties / codelist / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / time_dimension / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / time_dimension / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedilo_list_dimension_values3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • removedOutput schema / properties / values / items / properties / name / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / values / items / properties / name / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedilo_search_indicators3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedOutput schema / properties / hint
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / vocabulary_notes
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Addedsearch
  2. 4 tool updatesv0.1.0
    • First observedilo_get_data
    • First observedilo_get_indicator_metadata
    • First observedilo_list_dimension_values
    • First observedilo_search_indicators

TDQS

A4.5/5.0

Scored across 6 tools

Disambiguation4/5

The data tools (ilo_search_indicators, ilo_get_indicator_metadata, ilo_list_dimension_values, ilo_get_data) are clearly separated by function. The generic search and fetch tools are distinct from each other, but search and ilo_search_indicators both search the same catalog, creating mild overlap; their descriptions do clarify that one serves document retrieval and the other serves dataflow discovery.

Naming Consistency3/5

The four ilo_* tools follow a consistent verb-based pattern with underscores, but the unprefixed generic tools search and fetch break the convention. The mixed prefixing is explainable but inconsistent across the set.

Tool Count5/5

Six tools is a well-scoped size for the server's purpose: discovery, metadata inspection, dimension lookup, and data retrieval each have a dedicated tool. No tool feels redundant or unnecessary for the stated domain.

Completeness5/5

The tool set covers the full workflow needed to query ILOSTAT data: search for indicators, inspect metadata, list valid dimension codes, and retrieve data values. The search/fetch pair also enables document-level research, so there are no obvious dead ends in the intended use cases.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers