ilo-mcp-server — servidor MCP provenance-first do ILOSTAT
Servidor MCP (Streamable HTTP) para o ILOSTAT,
a base estatística da Organização Internacional do Trabalho, hospedado em Cloudflare
Workers. Projeto ilostat (C:\dev\mcp\ilostat\roadmap.md), instanciado do template
da Fase 0 do portfólio (mcp-br-commons/templates/cloudflare-worker). A fonte UNESCO
UIS vive no servidor irmão uis-mcp-server (decisão do decisor, 07/08/2026: um
servidor por fonte — segregação estrutural CC BY / CC BY-SA e convenção de naming do
mcp-builder; tools com prefixo de serviço ilo_).
Produção: https://ilo.sidneybissoli.com (endpoint MCP em /mcp; padrão de
URLs do portfólio). O hostname ilo-mcp-server.sidneybissoli.workers.dev permanece
servido como secundário.
Tools
| Tool | O quê | Fonte |
|---|---|---|
ilo_search_indicators | busca ~1.210 dataflows por palavra-chave (paginação por offset) | catálogo em D1 (100% local) |
ilo_get_indicator_metadata | dimensões, codelists, vintage, defaults de um dataflow | estrutura em KV (miss → upstream) |
ilo_list_dimension_values | códigos válidos de uma dimensão (paginação por offset) | codelist em KV (miss → upstream) |
ilo_get_data | observações com filtros por dimensão e período | 1 chamada REST por consulta |
Toda resposta carrega o bloco de proveniência v1.0 (@sbissoli/mcp-provenance,
modos concise/detailed via parâmetro provenance_mode) nos três canais do
contrato: structuredContent, _meta namespaced (com.sidneybissoli.ilostat/*) e
rodapé de texto.
Decisões vinculantes (spike Sessão 04 + decisor, 07/08/2026)
- JSON só via header
Accept(application/vnd.sdmx.{structure,data}+json) —?format=é ignorado pelo endpoint e devolve XML. - Nunca emitir consulta irrestrita (
/all→ HTTP 504 do gateway em ~61 s).REF_AREAé obrigatório emilo_get_data, com teto de 30 áreas por chamada e erro pedagógico pedindo lotes/paginação por período. Sem fatiamento server-side no MVP; reavaliar pós-lançamento com dados do UsageTracker. - Codelists cacheadas POR CODELIST (
codelist:ILO:CL_AREA:1.0, TTL 7 dias) —CL_MEASURE/CL_AREAsão compartilhadas entre dataflows (~90% de economia de KV). Estrutura de dataflow em KV com TTL 24 h (é a fonte dodata_vintage). data_vintage= annotationLAST_UPDATEdo dataflow (dd/MM/yyyy→ ISO), servido da estrutura cacheada — consulta típica permanece 1 chamada REST.- Catálogo em D1, seed via
scripts/seed-catalog.mjs; oretrieved_atdo seed é gravado emcatalog_metae reportado na proveniência deilo_search_indicators(served_from_cache: true). retrieved_até sempre o instante REAL da extração no upstream, preservado junto ao valor cacheado — nunca o momento do build ou da resposta.- User-Agent identificável em toda chamada upstream (o gateway da OIT responde
500 a clientes sem UA reconhecível; o fetch do Node/undici é rejeitado mesmo com UA
— o seed usa
curl). - Idioma do servidor: inglês; fuso: UTC (persona internacional; dados da OIT são publicados em inglês).
Regra de derived (caso de fronteira — decisão do decisor, 07/08/2026)
Conversão de unidade e arredondamento não contam como derivação: derived=false
com nota documentando a conversão. derived=true fica reservado a transformação
real (agregação, taxa calculada pelo servidor, interpolação, harmonização), sempre
com derivation_note. Regra operativa: valor com o mesmo significado = não derivado;
valor calculado = derivado. O MVP não transforma nada — derived é sempre false.
Notices
notices reproduz os valores de OBS_STATUS (canal de status/disclaimer do SDMX,
ex.: "Break in series"), verbatim com contagem. Atributos técnicos por observação
(DECIMALS etc.) permanecem nas linhas (rows[].attributes).
Obrigações de licença (docs/02 do projeto)
- ILOSTAT: CC BY 4.0 (dados/metadados desde 03/05/2023;
verified_at2026-08-04). - Atribuição ILO em toda resposta (campo
citation):International Labour Organization, ILOSTAT, https://ilostat.ilo.org/data/, accessed <data>. - Não usar o logo da OIT. Landing declara "not endorsed by the ILO".
- Dados UIS (CC BY-SA) vivem no servidor irmão
uis-mcp-server— segregação estrutural: os dois regimes nunca coabitam um servidor.
Desenvolvimento
npm install
npm run typecheck && npm test # 62 testes offline (parsers, chave, tools, evals-fixtures)
npm run dev # http://localhost:8787/mcp
# Seed do catálogo (D1) — necessário antes do primeiro uso:
node scripts/seed-catalog.mjs # baixa via curl e gera 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 do MCP em produção (initialize → 4 tools → erros)
Refresh do seed (D1) — decisão da Sessão 07 (07/08/2026)
Estratégia: seed manual com gatilho definido; sem cron do Worker. Os dados de
ilo_get_data são sempre live (nunca envelhecem); o que o seed congela é só o
catálogo de busca (~1.210 dataflows, quase estático no upstream). A proveniência de
ilo_search_indicators expõe o retrieved_at REAL do seed, então a idade do
catálogo é sempre visível ao cliente — staleness explícita, não silenciosa.
- Gatilhos de re-seed: (a) trimestral; (b) imediato se um dataflow existente no upstream não aparecer na busca (sintoma de catálogo defasado). Procedimento: os 3 comandos de seed em "Desenvolvimento".
- Cron rejeitado por ora: cadência upstream baixa não justifica código/estado extra; reavaliar na Fase 3 (pós-submissão), com tráfego real — mesma janela da reavaliação dos tetos operacionais.
Evals
@sbissoli/mcp-evals: 24 fixtures próprias em evals/fixtures/queries.ts, validadas
offline em npm test. A rodada com modelo real (npm run eval) custa API — só
com decisão explícita (ANTHROPIC_API_KEY; sem a chave, sai 0 com instruções).
Rodada de 07/08/2026 (Sessão 07): top-1 100% (24/24) — evals/results/.
End-to-end (formato mcp-builder): 10 perguntas complexas com resposta única
verificável em evals/e2e/evaluation.xml, respostas validadas manualmente contra a
produção (evals/e2e/validacao-respostas.md). Rodada de 07/08/2026 (Sonnet):
9/10 string exata; 10/10 substantivo — evals/results/2026-08-07-e2e.md.
Harness:
fase0-insumos/mcp-builder-evaluation/evaluation.py -t http -u https://ilo.sidneybissoli.com/mcp
(exige as correções de compatibilidade descritas no registro de resultados).
Rotas
/ landing · /health liveness · /status versão+deploy · /metrics uso agregado ·
/mcp MCP Streamable HTTP. Auth Bearer opcional (wrangler secret put API_KEY);
rate limit token-bucket por IP.
Privacidade
Política de privacidade do serviço hospedado: PRIVACY.md.