Senado BR MCP
Dados abertos do Senado Federal brasileiro via MCP — 90 ferramentas sobre o processo legislativo, administração do Senado (despesas do CEAPS, folha de pagamento, contratos) e o portal e-Cidadania. Cloudflare Workers, Streamable HTTP, sem autenticação. Respostas em pt-BR.
Documentação
Servidor MCP Senado Brasil
Um servidor MCP público e hospedado que oferece aos assistentes de IA acesso ao vivo e estruturado aos dados abertos do Senado Brasileiro — sem instalação, sem conta, sem chave de API. Aponte seu cliente MCP para o endpoint hospedado e comece a perguntar sobre senadores, projetos de lei, votações, despesas e muito mais. Ele roda em Cloudflare Workers sobre Streamable HTTP.
Ele expõe 69 ferramentas, 4 prompts e 5 recursos em dois domínios:
- Legislativo — senadores; projetos de lei e sua tramitação; votações; comissões; sessões plenárias, resultados e vetos presidenciais; orientação de votação de blocos partidários; discursos e notas taquigráficas; blocos e lideranças; legislação federal; e participação cidadã por meio do portal e-Cidadania.
- Administrativo — despesas da cota parlamentar CEAPS; auxílio-moradia; servidores e folha de pagamento; horas extras; estagiários; contratos de compras e licitações; terceirizados; fundos de caixa pequeno; e execução orçamentária.
Os dados vêm de três fontes oficiais — a API de dados abertos legislativos, a API de dados abertos administrativos e o portal e-Cidadania. Todas as respostas das ferramentas estão em português (pt-BR). Consulte CHANGELOG.md para o histórico de versões.
Veja em ação
Aponte um cliente para o endpoint e pergunte em linguagem natural — inglês ou português:
- "Como os senadores de São Paulo votaram nas votações em plenário mais recentes?" →
senado_search_votacoes - "Mostre o andamento legislativo da PEC 45/2019 (uma proposta de emenda constitucional)." →
senado_buscar_materias+senado_obter_materia - "Quanto foi gasto com a cota parlamentar CEAPS em 2024, discriminado por tipo de despesa?" →
senado_ceaps
As respostas vêm ao vivo das APIs oficiais de dados abertos do Senado — números exatos com procedência, não estimativas baseadas em dados de treinamento.
Use (hospedado — sem configuração)
Este é um servidor remoto, hospedado e de acesso aberto. Para usá-lo, aponte qualquer cliente MCP para o endpoint Streamable HTTP — sem instalação, sem conta, sem chave de API, sem configuração:
https://senado.sidneybissoli.com/mcp
Superfície de aplicativo OpenAI / ChatGPT
Para o SDK e a revisão de aplicativos OpenAI Apps, o Worker também expõe uma superfície MCP selecionada:
https://senado.sidneybissoli.com/mcp/openai-app-v2
Este endpoint mantém intencionalmente o servidor MCP público completo em /mcp, mas limita a descoberta de ferramentas a 27 ferramentas de alto sinal e orientadas a intenção para uso em aplicativos ChatGPT. /mcp/openai-app permanece disponível como um alias legado, mas novas configurações de aplicativos ChatGPT devem usar /mcp/openai-app-v2 para que os clientes busquem o esquema de ferramentas atual. As ferramentas ainda chamam os mesmos manipuladores e retornam o mesmo envelope de procedência; apenas a superfície anunciada é mais restrita. Qualquer listagem de aplicativo ChatGPT deve apresentar isso como um aplicativo independente de pesquisa de dados abertos, não como um conector oficial do Senado, OpenAI ou ChatGPT.
Para ChatGPT Apps, essas 27 ferramentas também anunciam um modelo de UI compartilhado de MCP Apps em ui://senado-br-mcp/openai-app-dashboard-v2.html. O widget autônomo renderiza o structuredContent retornado como um painel compacto com métricas, registros principais e fonte/procedência, sem adicionar outra ferramenta de dados visível ao modelo.
URLs legais públicas para revisão do aplicativo:
- Política de privacidade:
https://senado.sidneybissoli.com/privacy - Termos de uso:
https://senado.sidneybissoli.com/terms
ChatGPT (Deep Research)
O deep research do ChatGPT (e conhecimento da empresa, e fluxos de trabalho de pesquisa sobre a Responses API) só usa um servidor MCP que expõe exatamente search e fetch — este servidor expõe, além das senado_* ferramentas, na superfície completa /mcp (não no perfil de aplicativo selecionado). Aponte o conector para o endpoint hospedado, sem chave necessária:
https://senado.sidneybissoli.com/mcp
search classifica a consulta entre os senadores em exercício e as comissões ativas do Senado e do Congresso Nacional e retorna { id, title, url } (sen:<código> / com:<código>); fetch retorna o documento como Markdown legível — a biografia e os mandatos do senador, ou o resumo e a diretoria da comissão — com a página pública canônica (o perfil do senador em www25.senado.leg.br ou a página da comissão em legis.senado.leg.br), que é o que o ChatGPT cita. Ambos carregam o mesmo bloco de procedência de todas as outras ferramentas, em structuredContent e _meta (o canal de texto é o JSON do contrato). No modo de desenvolvedor do ChatGPT (Configurações → Segurança e login → Modo de desenvolvedor), qualquer ferramenta pode ser chamada — as ferramentas senado_* continuam sendo as recomendadas para dados.
Instalação (qualquer cliente)
Para clientes que iniciam servidores MCP como um comando — e para configuração em um único comando — use a ponte mcp-remote. Sem build, sem configuração, sem chave:
npx -y mcp-remote https://senado.sidneybissoli.com/mcp
- Um clique (LobeHub): abra a página do servidor e clique em Instalar.
- URL remota nativa (Claude Desktop/Code e outros clientes Streamable-HTTP): consulte Conectando Clientes MCP.
Tudo abaixo de Arquitetura (Pré-requisitos, Configuração, Deploy) é apenas para auto-hospedar opcionalmente sua própria instância — não é necessário para usar este servidor público.
Execute localmente (npx · stdio)
Prefere não rotear consultas por um host de terceiros (por exemplo, política de redação)? O mesmo servidor também roda como um processo stdio local que fala diretamente com as APIs oficiais do governo — mesmas 69 ferramentas, mesmo envelope de procedência, sem Cloudflare no caminho. Este é o canal npm/stdio, publicado como senado-br-mcp.
Aponte um cliente baseado em comando (Claude Desktop/Code, etc.) para o pacote — o npm baixa e executa, sem clone ou build:
{
"mcpServers": {
"senado-br": {
"command": "npx",
"args": ["-y", "senado-br-mcp"]
}
}
}
Para executar diretamente ou modificar, use o checkout do código-fonte:
git clone https://github.com/SidneyBissoli/senado-br-mcp-cloudflare
cd senado-br-mcp-cloudflare
npm install
npm run build
node dist/cli.js # serves MCP over stdio (Ctrl+C to stop)
Paridade com o servidor hospedado: as ferramentas legislativas e administrativas são idênticas (mesmas APIs upstream, mesmo throttle/cache/procedência) — localmente o cache L1 do Cloudflare é um no-op, mas o cache em memória L0 ainda funciona, então os resultados são os mesmos. A única diferença são as ferramentas de lista/corpus do e-Cidadania: sem D1, elas recorrem a um scrape ao vivo dos ~5 destaques REST, sinalizado via meta.fonte / possivelDesatualizacao; as ferramentas de detalhe (obter_*) são idênticas. Os logs vão para stderr — o stdout carrega apenas o fluxo de protocolo JSON-RPC.
Agent Skill (opcional)
Este repositório inclui um Claude Agent Skill em .claude/skills/senado-br/ que ensina ao Claude quando usar este servidor e como usar bem suas 69 ferramentas — um mapa de ferramentas temático, playbooks de pergunta→ferramenta comuns, o contrato de procedência e pegadinhas (datas, a ponte codigoMateria, a listagem de conjunto aberto do e-Cidadania, paginação). Ele aponta de volta para os recursos senado://catalogo / senado://guia do próprio servidor, em vez de duplicá-los.
O Claude Code o descobre automaticamente quando você trabalha neste repositório. Para usar em outro lugar, copie .claude/skills/senado-br/ para seu ~/.claude/skills/, ou compacte a pasta e envie no claude.ai (Configurações → Recursos). A skill assume que o servidor MCP senado-br está conectado (hospedado ou via npx).
Arquitetura
- Runtime: Cloudflare Workers (ESM)
- Transporte: Streamable HTTP (especificação MCP 2025-03-26) via
createMcpHandlerdeagents/mcp - Protocolo: MCP sobre JSON-RPC —
/mcpgerencia o servidor público completo;/mcp/openai-app-v2expõe um perfil selecionado de 27 ferramentas mais um widget compartilhado de MCP Apps para revisão/envio de aplicativos OpenAI (/mcp/openai-apppermanece como alias legado) - SDK:
@modelcontextprotocol/server2.x (instâncias McpServer por requisição; o@modelcontextprotocol/sdkv1 permanece apenas como par deagents, em tempo de desenvolvimento) - Validação: Esquemas Zod para todas as entradas de ferramentas
- Cache: 2 camadas (memória L0 + API de Cache L1) com chaveamento SHA-256
- Armazenamento e-Cidadania: banco de dados D1 atualizado por um Cron Trigger (a cada 2h) — ferramentas de lista leem do D1 com fallback de scrape ao vivo e sinalizador de desatualização; ferramentas de detalhe permanecem ao vivo com write-through (veja e-Cidadania)
- Limitação de taxa: Token bucket — global (8 req/s) + por cliente (2 req/s)
- Throttle upstream: Máximo de 6 requisições concorrentes, timeout de 10s, retry com backoff exponencial
- Autenticação: Token Bearer opcional (defina o segredo
API_KEY; acesso aberto quando não definido). Comparação em tempo constante. - Observabilidade: Logging JSON estruturado + contadores em memória em
/metrics; telemetria de chamadas por ferramenta (seleção, taxa de erro, cache-vs-ao-vivo) no Cloudflare Analytics Engine, sem PII - Disponibilidade: Roda na própria rede global do Cloudflare atrás de um domínio personalizado — sem host de terceiros que possa ficar offline.
/healthe/statuspúblicos (versão + id/timestamp do último deploy) tornam o uptime e o build atual verificáveis; o selo de status acima faz ping no endpoint ao vivo - Testes: Testes unitários Vitest para parsers, helpers, cache, throttle e autenticação
Auto-hospedagem (opcional)
Não é necessário para usar o servidor — ele já está hospedado em
https://senado.sidneybissoli.com/mcp(acesso aberto). Siga esta seção apenas se quiser executar sua própria instância privada.
Pré-requisitos
- Node.js 22+ (
engines.node) - Wrangler CLI v4+
- Conta Cloudflare
Configuração
1. Instalar dependências
npm install
2. Criar namespace KV
# Create the KV namespace
wrangler kv namespace create CACHE_KV
# Note the ID from the output, e.g.:
# { binding = "CACHE_KV", id = "abc123..." }
3. Configurar wrangler.toml
Substitua o ID do namespace KV de exemplo:
[[kv_namespaces]]
binding = "CACHE_KV"
id = "YOUR_KV_NAMESPACE_ID_HERE"
Opcionalmente, defina ALLOWED_ORIGIN para restringir CORS:
[vars]
ALLOWED_ORIGIN = "https://your-app.example.com"
O pipeline do e-Cidadania precisa de um banco de dados D1 e um Cron Trigger (ambos já declarados em wrangler.toml — substitua o ID do banco de dados):
[[d1_databases]]
binding = "ECIDADANIA_DB"
database_name = "senado-ecidadania"
database_id = "YOUR_D1_DATABASE_ID_HERE"
[triggers]
crons = ["0 */2 * * *"]
Crie o banco de dados (cole o ID retornado acima) e aplique o esquema:
npx wrangler d1 create senado-ecidadania
npx wrangler d1 migrations apply senado-ecidadania --remote
As ferramentas de lista recorrem ao scraping ao vivo quando o D1 está vazio, então o servidor funciona antes da primeira execução do Cron.
4. (Opcional) Ativar autenticação
wrangler secret put API_KEY
# Clients must then send: Authorization: Bearer <key>
# When API_KEY is not set, the server is open access.
5. Desenvolvimento local
npm run dev
# Dev server runs locally on port 8787 (local only).
# The public MCP endpoint is https://senado.sidneybissoli.com/mcp
6. Testes e verificação de tipos
npm test # run all tests once
npm run test:watch # watch mode
npm run typecheck # tsc --noEmit
7. Deploy
npm run deploy
# Serves at https://senado.sidneybissoli.com (custom domain) and
# https://senado-br-mcp.sidneybissoli.workers.dev (workers.dev fallback)
Endpoints
| Caminho | Métodos | Descrição |
|---|---|---|
/ | GET | Página inicial (pt-BR) — identifica o cliente por trás do User-Agent de saída: o que é o serviço, postura de carga, contato (sempre público) |
/mcp | POST, GET, DELETE, OPTIONS | Endpoint MCP Streamable HTTP (gerenciado por createMcpHandler) |
/health | GET | Verificação de saúde — retorna ok (sempre público) |
/status | GET | JSON: status, version e metadados do último deploy (deploy.id/tag/timestamp) — disponibilidade + build atual, sem necessidade de handshake MCP (sempre público) |
/metrics | GET | Contadores JSON: requisições, chamadas de ferramentas, acertos/erros de cache, chamadas/retries/erros upstream, falhas de autenticação (sempre público) |
Exemplos de Requisições MCP
Todas as requisições vão para POST /mcp com formato JSON-RPC 2.0.
Listar ferramentas disponíveis
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
Chamar uma ferramenta — Listar senadores de SP
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "senado_listar_senadores",
"arguments": {
"uf": "SP",
"emExercicio": true
}
}
}
Chamar uma ferramenta — Buscar projetos de lei por palavra-chave
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "senado_buscar_materias",
"arguments": {
"palavraChave": "inteligência artificial",
"tramitando": true
}
}
}
Chamar uma ferramenta — Obter votações recentes em plenário
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "senado_search_votacoes",
"arguments": {
"dias": 7
}
}
}
Chamar uma ferramenta — Ideias cidadãs mais populares
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "senado_ecidadania_listar_ideias",
"arguments": {
"ordenarPor": "apoios",
"ordem": "desc",
"status": "aberta"
}
}
}
Endpoints da API Upstream
O servidor consome duas classes de endpoints upstream da API do Senado:
Endpoints legados (sufixo .json, respostas PascalCase)
Usados pelos Grupos A, E, F, H, I, J, K, L, M, N. O sufixo .json é anexado automaticamente por upstream.ts. Nenhum deles está marcado como obsoleto upstream.
| Caminho upstream | Usado por |
|---|---|
/senador/lista/atual | senado_listar_senadores |
/senador/lista/legislatura/{legislatura} | senado_listar_senadores (parâmetro legislatura) |
/senador/{codigo} (+ /mandatos) | senado_obter_senador (biografia + mandatos via chamada extra) |
/senador/{codigo}/licencas, /comissoes, /cargos, /historicoAcademico, /filiacoes, /profissao | senado_senador_historico (enum tipo) |
/senador/afastados | senado_senadores_afastados |
/senador/{codigo}/apartes | senado_discursos_senador (tipo=apartes) |
/comissao/lista/colegiados | senado_listar_comissoes (+ resolução sigla-para-código) |
/comissao/{codigo} | senado_obter_comissao (secao=resumo; código numérico, não sigla) |
/composicao/comissao/{codigo} (+ ?ativas=S) | senado_obter_comissao (secao=membros) |
/comissao/agenda/{data} | senado_agenda_comissoes |
/comissao/agenda/{dataInicio}/{dataFim} | senado_reunioes_comissao |
/comissao/reuniao/{codigoReuniao} | senado_reuniao_comissao |
/comissao/cpi/{sigla}/requerimentos | senado_requerimentos_cpi (upstream frequentemente vazio mesmo para CPIs ativas — resultado vazio carrega um aviso) |
/materia/distribuicao/autoria, /distribuicao/relatoria/{sigla} | senado_distribuicao_materias |
/plenario/agenda/dia/{data}, /agenda/mes/{data}, /agenda/cn/... | senado_agenda_plenario |
/plenario/resultado/{data}, /resultado/cn/{data}, /resultado/mes/{data} | senado_resultado_plenario |
/plenario/resultado/veto/{codigo} (+ /materia/, /dispositivo/) | senado_resultado_veto |
/plenario/votacao/orientacaoBancada/{data} (+ período) | senado_orientacao_bancada |
/plenario/encontro/{codigo} (+ /pauta, /resultado, /resumo) | senado_encontro_plenario |
/plenario/tiposSessao, /lista/tiposComparecimento, /lista/legislaturas | senado_tabelas_plenario |
/materia/vetos/{ano}, /vetos/aposrcn, /vetos/antesrcn, /vetos/encerrados | senado_vetos |
/taquigrafia/notas/{sessao|reuniao}/{id} | senado_notas_taquigraficas |
/taquigrafia/videos/{sessao|reuniao}/{id} | senado_videos_taquigrafia |
/senador/{codigo}/discursos | senado_discursos_senador |
/plenario/lista/discursos/{dataInicio}/{dataFim} | senado_discursos_plenario |
/discurso/texto-integral/{codigo} | senado_discurso_texto (texto simples, buscado diretamente) |
/senador/lista/tiposUsoPalavra | senado_tabelas_referencia (tabela=tipos-uso-palavra) |
/composicao/lista/blocos | senado_listar_blocos |
/composicao/bloco/{codigo} | senado_obter_bloco |
/composicao/lideranca | senado_liderancas |
/composicao/mesaSF | senado_mesa (casa=senado) |
/composicao/mesaCN | senado_mesa (casa=congresso) |
/orcamento/lista | senado_orcamento_parlamentar (tipo=emendas) |
/orcamento/oficios | senado_orcamento_parlamentar (tipo=oficios) |
/legislacao/lista | senado_buscar_legislacao |
/legislacao/{codigo} | senado_obter_legislacao |
/legislacao/tiposNorma | senado_tabelas_referencia (tabela=tipos-norma) |
/votacaoComissao/comissao/{sigla} | senado_votacao_comissao (por=comissao) |
/votacaoComissao/parlamentar/{codigo} | senado_votacao_comissao (por=senador) |
/votacaoComissao/materia/{sigla}/{numero}/{ano} | senado_votacao_comissao (por=materia) |
/autor/lista/atual | senado_autores_atuais |
Endpoints v3 (arrays/objetos JSON planos, camelCase)
Usados pelos Grupos B, C, D. Datas devem estar em formato ISO (YYYY-MM-DD) — as ferramentas aceitam YYYYMMDD e convertem. O parâmetro de consulta codigoMateria faz a ponte entre códigos legados de matéria e processos v3.
| Caminho upstream | Usado por |
|---|---|
/votacao | senado_obter_votacao, senado_search_votacoes, senado_votos_materia, senado_votacoes_senador |
/processo | senado_search_processos, senado_buscar_materias |
/processo/{id} | senado_obter_processo, senado_obter_materia (secao=detalhe/tramitacao) |
/processo/documento | senado_obter_materia (secao=textos) |
/processo/emenda | senado_processo_detalhe (secao=emendas) |
/processo/relatoria | senado_processo_detalhe (secao=relatorias), senado_obter_materia (relator) |
/processo/prazo | senado_processo_detalhe (secao=prazos) |
/processo/{siglas,assuntos,classes,destinos,entes,tipos-*} | senado_tabelas_processo (12 tabelas de referência) |
API Administrativa (adm.senado.gov.br/adm-dadosabertos, JSON plano snake_case)
Usada pelos Grupos O, P, Q, R via admFetch (sem sufixo .json; HTTP 404 tratado como coleção vazia). URL base configurável via SENADO_ADM_BASE_URL.
| Caminho upstream | Usado por |
|---|---|
/api/v1/senadores/despesas_ceaps/{ano} | senado_ceaps (~10 MB/ano, cacheado + agregado no Worker) |
/api/v1/senadores/{auxilio-moradia,escritorios,aposentados} | senado_senadores_admin (enum tipo) |
/api/v1/servidores/servidores/{ativos,efetivos,comissionados,inativos} | senado_servidores |
/api/v1/servidores/remuneracoes/{ano}/{mes} | senado_remuneracoes_servidores (~5,5 MB/mês) |
/api/v1/servidores/horas-extras/{ano}/{mes} | senado_horas_extras |
/api/v1/servidores/quantitativos/*, /previsao-aposentadoria, /api/v1/senadores/quantitativos/senadores | senado_pessoal_tabelas (quantitativos) |
/api/v1/servidores/{estagiarios,pensionistas,lotacoes,cargos} | senado_pessoal_tabelas (listas nominais) |
/api/v1/contratacoes/contratos (+ /{id}/aditivos) | senado_contratos, senado_contratacao_detalhe |
/api/v1/contratacoes/{tipo}/{id}/{itens,pagamentos,garantias} | senado_contratacao_detalhe |
/api/v1/contratacoes/licitacoes | senado_licitacoes |
/api/v1/contratacoes/terceirizados | senado_terceirizados |
/api/v1/contratacoes/empresas | senado_empresas_contratadas (~13 MB, exige filtro) |
/api/v1/contratacoes/{atas_registro_preco,notas_empenho,menores_aprendizes} | senado_contratacoes_lista |
/api/v1/supridos/{ano} (+ atosConcessao, empenhos, movimentacoes, transacoes) | senado_suprimento_fundos |
senado.gov.br/bi-arqs/Arquimedes/Financeiro/{Despesa,Receitas}SenadoDadosAbertos.json | senado_execucao_orcamentaria (feeds JSON diários, strings decimais brasileiras normalizadas) |
e-Cidadania (baseado em D1, atualizado por Cron)
Os dados de lista do e-Cidadania são persistidos em um banco de dados D1 (ecidadania_current/_history/_scrape_runs, discriminados por entidade; além de ecidadania_comentarios para o nível de comentários da audiência e ecidadania_detalhe_cursor para o preenchimento retomável de detalhes — adicionados no schema v2) e lidos de lá em vez de serem raspados a cada chamada. Três cadências escrevem nele:
- uma GitHub Action diária fora do Worker é dona do corpus completo das três entidades ativas (
consultas,eventos,ideias; veja abaixo) — a fonte da verdade. Diária (não semanal) porque a série de primeira apariçãoMIN(scraped_at)é o único sinal mensurável do ritmo de entrada e cada dia pulado a encurta permanentemente (ROADMAP Etapa 2, decisão D3); - uma Action de ingestão semanal (
.github/workflows/verify-consultas-votos.yml— nome de arquivo histórico) para o acervoconsultas_votos: o Senado republica o CSV do Arquimedes periodicamente (confirmado em 20/07/2026), então a execução semanal re-ingere a safra atual sob as mesmas proteções de anomalia dos outros corpora (veja abaixo); - um Cron Trigger no Worker (
0 */2 * * *,src/scraper/pipeline.ts → refreshEcidadania) faz apenas um ajuste métrico direcionado dos ~5 destaques REST por entidade ativa (restcolecaomaismateria/ideia/audiencia— votos/comentários/apoios), registrado comook-metricapara nunca quebrar novamente a linha de base do corpus e nunca tocar na cauda longa. Na v2, o ajuste de eventos preserva a contagem canônica de comentários do corpus (o rastreamento diário é a fonte da verdade paracomentarios, então o ajuste não pode fazer ping-pong contra a contagem REST degradada).
Ambos os escritores constroem payloads através dos builders canônicos buildXResumo + contentHash compartilhado, então suas linhas são byte-idênticas. Cada escrita:
- faz upsert de
ecidadania_current(uma linha por item — o que as ferramentas leem), - anexa
ecidadania_historyapenas quando ocontent_hashde um item muda (pronto para séries temporais), - registra cada execução em
ecidadania_scrape_runs.
Uma proteção de anomalia (src/scraper/anomaly.ts, classifyRun) garante que uma execução de corpus falha ou anômala (zero linhas, ou menos de ECIDADANIA_CORPUS_MIN_PCT% da última execução boa) nunca sobrescreva o último estado bom.
As ferramentas de lista / análise (listar_*, consultas_analise, sugerir_tema_enquete, consultas_votos) leem do D1 via resolveList (src/scraper/store.ts): D1 primeiro. Como cada entidade agora é um corpus completo, um corpus desatualizado é servido do D1 sinalizado (possivelDesatualizacao: true) em vez de colapsar para os ~5 destaques ao vivo (o bug de cobertura original); a raspagem ao vivo é reservada para um D1 vazio (início a frio, antes da primeira execução semanal). Desatualização usa ECIDADANIA_CORPUS_STALE_MAX_MIN (~10 dias). Cada resposta de lista carrega um meta aditivo (fonte, lastScrapedAt, possivelDesatualizacao) para que os chamadores sempre vejam a idade real dos dados e nunca recebam dados desatualizados silenciosamente.
As ferramentas de detalhe (obter_*) permanecem ao vivo (HTML raspado com regex direcionado por classe CSS) para frescor, e escrevem seu payload mais rico em ecidadania_detalhe fire-and-forget (deduplicado por content_hash), para que o histórico de detalhes se acumule sem adicionar latência à resposta.
Ingestão de corpus completo (fora do Worker)
Os três corpora ativos do e-Cidadania são de propriedade da Action diária (.github/workflows/ingest-ecidadania.yml), cada um com seu próprio orquestrador scripts/ingest-ecidadania/index-*.ts emitindo out-*.sql em lote que a etapa de aplicação carrega em massa:
consultas— consultas abertas (detalhadas abaixo). Na v2, cada matéria rastreada também é enriquecida a partir de sua página de detalhe (visualizacaomateria) paraautoria/relator; esses campos são imutáveis, então apenas linhas ainda não enriquecidas são buscadas.eventos— audiências/eventos da listagem HTMLprincipalaudiencia?p=N; o status vem direto do bloco da listagem (sem ponte/processo). Na v2, cada evento é enriquecido a partir de sua página de detalhe (data/horacanônicos +comissaoNomeCompleto/local/descricao/pauta/convidados/videoUrl) e seu fragmento de comentários AJAX (contagem canônica + uma linhaecidadania_comentariospor comentário, comparada com os hashes armazenados e emitida comoout-eventos-comentarios-*.sql).ideias— ideias legislativas (~113,7 mil) depesquisaideia?situacao=N&p=M, rastreadas por bucket desituacao(a listagem não tem status inline) e emitidas em lotes de ~10 mil declarações. Na v2, o rastreamento da listagem preserva os campos imutáveis de detalhe, e um preenchimento retomável separado (index-ideias-detalhe.ts, executado viaingest:ecidadania:ideias-detalhe) os preenche um pedaço por execução — porque ~113,7 mil buscas de detalhe não cabem em uma Action, ele persiste um cursor emecidadania_detalhe_cursore dá a volta no final.
A quarta entidade, consultas_votos, é um acervo histórico separado de votos por UF analisado do CSV do Arquimedes de ~33 MB (Proposições-com-votos.csv), agregado em um registro por matéria com um detalhamento votosPorUf. O carimbo "dados atualizados até" do CSV se torna a proveniência data_vintage; ele é excluído do hash da linha (consultaVotoCore) para que uma re-ingestão com votos inalterados não agite _history. STATUS ATUAL é uniformemente "Descontinuado", portanto arquivístico, não uma migração das consultas abertas. Servido por senado_ecidadania_consultas_votos com proveniência apontando para o CSV (ECIDADANIA_ARQUIMEDES). Ele é excluído do job diário e pertence à sua própria Action de ingestão semanal (.github/workflows/verify-consultas-votos.yml — o nome do arquivo mantém o prefixo histórico verify-): o acervo foi originalmente tratado como uma safra única congelada (ROADMAP Etapa 2, decisão D1) e a execução semanal apenas o verificava, mas em 20/07/2026 o Senado republicou o CSV como uma safra nova (+43 matérias, 648 atualizadas), então a execução agendada agora re-ingere a safra atual sob as proteções padrão de anomalia (CSV vazio/truncado e o piso catastrófico ainda falham sem escrever; o despacho force substitui o piso). O modo de verificação do script (INGEST_CONSULTAS_VOTOS_VERIFY=1 / --verify) permanece disponível como uma verificação de integridade sob demanda.
O job consultas é a implementação de referência:
consultas cobre o conjunto completo de consultas ABERTAS — toda matéria atualmente em tramitação (~7,7 mil), não apenas os ~5 destaques. Confirmado na primeira execução: a listagem pesquisamateria é somente em tramitação, então consultas encerradas/históricas não são capturadas por esta fonte (um preenchimento histórico pré-ingestão está fora do escopo). Três decisões de design estabelecidas:
- Ingestão desacoplada. O conjunto aberto é adquirido por um job TypeScript fora do Worker (
scripts/ingest-ecidadania/, executado por uma GitHub Action diária —.github/workflows/ingest-ecidadania.yml) que pagina a listagem HTML (pesquisamateria?p=1..N, a única fonte de cobertura completa para consultas abertas) para ids e contagens de votos e carrega em massa o D1; o Worker apenas lê. O rastreamento frágil e longo é mantido fora do caminho de requisição/Cron. - Status a partir de
/processo, não do HTML. Uma consulta ocorre desde a apresentação até o fim da tramitação, entãostatusé uma função da matéria: aberta ⟺ acodigoMateriaestá no conjunto/processotramitando=S, derivado de JSON robusto (nunca raspado). Toda consulta entra comoaberta(a listagem só retorna matérias em tramitação); a cada execução completa, o job rederiva o status de todas as linhas armazenadas pela pertinência a/processo(não pela ausência na listagem, que pode ser transitória), então uma consulta cuja matéria sai da tramitação muda paraencerrada. Os conjuntosencerrada/todascrescem ao longo do tempo; consultas encerradas antes da primeira ingestão não são capturadas (fora do escopo). As ferramentas de listagem/análise usamstatus: abertapor padrão. - Duas cadências reconciliadas (um contrato de escrita compartilhado). O job reutiliza
contentHash+ o construtor deConsultaResumo+classifyRundesrc/scraper/, então suas linhas são byte-idênticas às do Cron. O job diário é dono da cauda longa; o Cron de 2h mantém os ~5 destaques quentes/abertos atualizados via um splice métrico direcionado (registrado comook-metrica, ignorando a linha de baseclassifyRundo corpus). A atualidade do corpus (possivelDesatualizacao) é calculada a partir da última execução destatus='ok'e usa uma janela maior (ECIDADANIA_CORPUS_STALE_MAX_MIN), e um corpus de consultas desatualizado é servido do D1 sinalizado, em vez de colapsar de volta aos destaques ao vivo.
Guardas de escrita no carregamento: um rastreamento incompleto (qualquer página falhou) ou um universo de status /processo incompleto escreve apenas uma linha de execução erro; até um rastreamento completo é rejeitado por um piso catastrófico (ECIDADANIA_CORPUS_MIN_PCT, padrão 80% do último corpus bom) para proteger contra uma página degradada — substituível com --force / INGEST_FORCE=1 para uma redução legítima grande. Execute diariamente via Action, ou manualmente:
CLOUDFLARE_API_TOKEN=… npm run ingest:ecidadania # writes scripts/ingest-ecidadania/out.sql
npx wrangler d1 execute senado-ecidadania --remote --file=scripts/ingest-ecidadania/out.sql
Cache
Arquitetura de camadas
| Camada | Armazenamento | Escopo | Faixa de TTL | Finalidade |
|---|---|---|---|---|
| L0 | Em memória Map | Por isolado | 30-300s | Ultra-rápido, elimina requisições redundantes dentro de um isolado do Worker |
| L1 | Cloudflare Cache API (caches.default) | Por colo (PoP) | 60-600s | Compartilhado entre requisições no mesmo local de borda |
| L2 | KV (opcional) | Global | Variável | Reservado para dados raros e de baixa escrita |
Categorias de cache
| Categoria | TTL L0 | TTL L1 | Usado para |
|---|---|---|---|
| STATIC | 300s | 600s | Tipos de legislação, referência estática |
| SEMI_STATIC | 120s | 300s | Lista de partidos, lista de UF, detalhes de comissões |
| DYNAMIC | 30s | 60s | Agendas, votações recentes, listas de reuniões |
| ON_DEMAND | 30s | 120s | Consultas específicas de projetos/senadores/votações |
Abordagem de cache para POST
O MCP usa POST para todas as requisições tools/call. O cache de respostas POST não é suportado nativamente pela Cache API, que exige requisições GET. A solução:
- Hash dos parâmetros — Nome da ferramenta + parâmetros ordenados são transformados em hash com SHA-256
- Chave GET sintética — Uma URL sintética
https://senado-br-mcp.internal/__cache/{tool}/{hash}é construída - Match/put da Cache API — A URL GET sintética é usada com
caches.default.match()ecaches.default.put(), permitindo operações padrão da Cache API em dados originados de POST
Esse cache acontece no nível da ferramenta (dentro do callback de cada ferramenta), não no nível de transporte do MCP.
Proveniência
Toda ferramenta anexa um envelope de proveniência para que um resultado seja rastreável até sua fonte oficial — a proveniência é tratada como parte de primeira classe da resposta, não como um extra opcional (o público são jornalistas e pesquisadores de ciência política, para quem um dado sem fonte é inutilizável). Desde a v3.5.0, o envelope implementa o contrato de proveniência v1.0 do portfólio (@sbissoli/mcp-provenance): o servidor constrói e valida um modelo canônico completo por resposta e emite sua projeção concise — um bloco fixo de 6 chaves com null explícito para campos desconhecidos. O bloco vive em structuredContent.provenance (analisável por clientes; note que o esquema de saída anunciado por ferramenta é permissivo, então a validação do contrato acontece no lado do servidor, no momento da construção, no pacote) e é espelhado como um rodapé de fonte compacto no conteúdo de texto para clientes que renderizam apenas texto — o JSON de dados em si não é duplicado com o envelope, para manter baixo o custo de tokens por resposta.
A cobertura abrange todas as quatro fontes upstream, cada uma com seu próprio source/citation/license (em src/utils/provenance.ts):
- Senado Federal — Dados Abertos (Legislativo) —
legis.senado.leg.br/dadosabertos - Senado Federal — Dados Abertos (Administrativo) —
adm.senado.gov.br/adm-dadosabertos - Senado Federal — Execução Orçamentária e Financeira — feed Arquimedes/Financeiro em
senado.gov.br - Senado Federal — Portal e-Cidadania —
www12.senado.leg.br/ecidadania
Campos do bloco concise (por resposta — uma ferramenta, uma fonte; chaves nesta ordem fixa, null quando a fonte não expõe o valor):
| Campo | Significado |
|---|---|
source | Nome oficial da fonte (ex.: Senado Federal — Dados Abertos (Legislativo)) |
source_url | URL canônica do endpoint/item consultado (ex.: …/processo/{id}) |
data_vintage | Vintage/competência dos dados (ex.: 2024-03-15, 2019) — chamado de reference_period antes da v3.5.0 |
retrieved_at | ISO-8601 da extração upstream — transportado pelo cache, então reflete quando os dados foram realmente buscados, não a construção ou o momento do cache-hit |
citation | String de citação pronta para uso (legível por humanos) |
license | Termos da fonte (Dados Abertos do Senado Federal) |
O modelo canônico por trás do bloco também carrega dataset.id (identificador de item/série, ex.: codigoMateria=137808), api_version e field_sources por campo; esses são validados em toda construção e informam attribution (abaixo), mas não fazem parte da projeção concise.
Além do envelope provenance, structuredContent carrega uma lista de attribution de nível superior — as URLs de fonte distintas por trás da resposta. Isso espelha a nomenclatura proposta em modelcontextprotocol#711 (onde attribution é uma lista de referências de fonte no nível da resposta), então o servidor permanece compatível com o futuro se esse RFC for aprovado; o objeto mais rico provenance permanece uma extensão própria deste servidor.
Espelhamento fora de banda em _meta. O mesmo provenance e attribution também são espelhados no _meta do resultado sob chaves com namespace (com.sidneybissoli.senado/provenance e com.sidneybissoli.senado/attribution). A especificação MCP mantém _meta para metadados sobre um resultado que não devem orientar o modelo, que é onde o trabalho ainda incipiente de confiança/atribuição do #711 (dividido em uma trilha de extensões experimentais, ainda não no núcleo) aponta; espelhar ali dá a consumidores de auditoria e UI a proveniência sem ler o canal de dados voltado ao modelo, sem custo de tokens para o modelo, enquanto structuredContent a mantém visível para que o modelo possa citar a fonte. O espelhamento sobrevive ao minimizador de perfil do app ChatGPT (que só remove structuredContent.meta).
Granularidade no nível de campo. A maioria das ferramentas é de fonte única, então um envelope basta. As poucas que mesclam fatias em uma resposta preenchem field_sources no modelo canônico — uma lista de { fields, source_url, data_vintage, retrieved_at, … } atribuindo campos de saída específicos à sua origem real. Exemplo: senado_obter_materia secao=detalhe funde /processo/{id} (a fonte de nível superior) com a ementa de /processo e a relator de /processo/relatoria, cada uma carregando seu próprio retrieved_at. No bloco concise emitido, o detalhe por campo é resumido via attribution, que sempre lista cada source_url subjacente distinto.
A fidelidade de retrieved_at é fornecida pela camada de cache (cachedFetchWithMeta), que persiste o timestamp da busca junto ao valor, então reflete a extração upstream real mesmo em um cache-hit. Duas exceções relatam um timestamp ao vivo honesto: as ferramentas de lista do e-Cidadania (lidas do D1) usam o lastScrapedAt do corpus — a idade real dos dados armazenados — enquanto as ferramentas de detalhe do e-Cidadania, raspadas ao vivo, usam o tempo da busca e uma URL de item canônica de nível 3. O único caminho que recai no padrão do tempo de construção é o catálogo de referência estática no código (senado_tabelas_referencia tipos-materia), que não tem instante de extração upstream.
A cobertura é universal: todas as 69 ferramentas carregam o envelope — as 67 ferramentas senado_* via resultWithProvenance( (verifique com grep -c 'resultWithProvenance(' src/tools/*.ts) e as duas ferramentas Deep Research via provenanceExtras (mesmo bloco, em structuredContent/_meta, já que seu canal de texto é o JSON do contrato). As marcas ⊕ no inventário abaixo denotam as ferramentas piloto originais (votações, projetos, processos); o envelope agora se estende a toda ferramenta, então as marcas são históricas.
Conjunto de dados citável (participação e-Cidadania)
Além do servidor ao vivo, este projeto publica um conjunto de dados congelado, versionado e citável da camada de participação do e-Cidadania (consultas públicas, ideias legislativas, eventos interativos + seus comentários, votações históricas por estado) — a camada que o pacote R congressbr nunca cobriu. Cada valor carrega um envelope de proveniência por campo ({ value, sourceEndpoint, sourceField, retrievedAt, license, schemaVersion }); a licença de dados (Dados Abertos do Senado Federal) é mantida separada da licença do código (MIT).
- Como citar —
CITATION.cff(conjunto de dados; cite o DOI de versão do snapshot que você usou, o DOI de conceito para o conjunto de dados entre versões). - O que há em cada release —
CHANGELOG-dataset.md(cumulativo, somente anexação; vincula cada release ao seuschemaVersion). - Dicionário de variáveis e proveniência de campos —
docs/dataset-dictionary.md(gerado a partir desrc/dataset/schema.ts, a fonte única da verdade). - Licença de dados —
LICENSE-DATA.md. - Cortando um release (congelamento → checksums → GitHub Release → DOI Zenodo) —
docs/release-runbook.md; maquinário emsrc/dataset/,scripts/build-dataset/e.github/workflows/release-dataset.yml.
Inventário — esquema v2 (schemaVersion 2.0.0)
Cada release entrega um recurso NDJSON por entidade (um HarmonizedRecord por linha: identidade + um envelope de proveniência por campo), além de um manifesto datapackage.json e uma cópia do dicionário. Cinco recursos:
Recurso (*.ndjson) | Granularidade | Variáveis-chave | Fonte(s) |
|---|---|---|---|
consultas | 1 consulta pública (matéria) | materia, ementa, votosSim/votosNao/totalVotos, percentual*, autoriaⁿ, relatorⁿ, status, url, firstSeenAt | Listagem pesquisamateria + detalhe (visualizacaomateria)ⁿ + /processo?tramitando=S para status |
ideias | 1 ideia legislativa (~113,7 mil) | titulo, apoios, status, dataPublicacaoⁿ, autorUfⁿ, descricaoⁿ, plConvertidoⁿ, url, firstSeenAt | Listagem pesquisaideia + detalhe (visualizacaoideia) via backfill retomávelⁿ |
eventos | 1 evento interativo (audiência) | titulo, dataᶜ, horaᶜ, comissao, comissaoNomeCompletoⁿ, localⁿ, descricaoⁿ, pautaⁿ, convidadosⁿ, videoUrlⁿ, comentariosᶜ, status, url, firstSeenAt | Listagem principalaudiencia + detalhe (visualizacaoaudiencia)ⁿ + fragmento AJAX de comentáriosᶜ |
eventos_comentariosⁿ | 1 comentário (nível de comentário) | eventoId, comentarioId, uf, texto, data, hora, momentoVideoUrl, convidadoAssociado | Fragmento AJAX ajaxcolecaocomentarioaudiencia?audienciaId= |
consultas_votos | 1 matéria (acervo histórico) | materia, ementa, autoria, votosSim/votosNao/totalVotos, votosPorUf, status, url, referencePeriod | CSV Arquimedes Proposições-com-votos.csv (re-ingerido semanalmente) |
ⁿ = novo/reaberto na v2 · ᶜ = fonte corrigida para a canônica na v2. O que a v2 (2.0.0) mudou — a ingestão passou de somente listagem para listagem + detalhe (+ comentários AJAX para eventos):
- Eventos corrigidos e enriquecidos.
data/horaagora vêm da página de detalhe (canônica — o estudo A3 constatou que a listagem divergia 57% emhora), além de seis novos campos de detalhe (comissaoNomeCompleto,local,descricao,pauta,convidados,videoUrl).comentariosagora é a contagem AJAX canônica (a contagem da listagem era0-espúria em 82% dos eventos, capturando apenas ~6,7% do engajamento). - Novo recurso em nível de comentário
eventos_comentarios— uma linha por comentário de audiência, o sinal de participação que ninguém mais publica com versionamento. - Campos somente de detalhe reabertos para
ideias(dataPublicacao,autorUf,descricao,plConvertido) econsultas(autoria,relator) — antes semprenullpor design. - Postura de privacidade por origem dos dados. Conteúdo de cidadãos (comentários de audiência, autores de ideias) mantém apenas UF — nunca o nome, descartado no parser; agentes públicos (autoria/relatoria de consulta, convidados de evento) mantêm o nome (público por função). Veja
docs/schema-v2-inventario.mdpara a justificativa campo a campo (alvo aprovado).
O NDJSON congelado não é commitado (construído sob demanda a partir do corpus soberano D1); um release dataset-v* com tag anexa o tarball + SHA256SUMS + release.json e os arquiva no Zenodo.
Inventário de Ferramentas
Grupo H — Referência/Metadados (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
senado_tabelas_referencia | Tabelas de referência via enum tabela: tipos-materia, partidos, ufs, legislatura-atual, tipos-norma, tipos-uso-palavra |
Grupo A — Senadores (5 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_listar_senadores | Lista senadores em exercício/por legislatura, com filtros nome (busca parcial sem acento), uf e partido |
senado_obter_senador | Detalhe biográfico de um senador: bio, mandatos, partido, contato |
senado_votacoes_senador ⊕ | Como um senador votou em cada matéria (via v3 /votacao) |
senado_senador_historico | Histórico funcional via enum tipo: licencas, comissoes, cargos, historico-academico, filiacoes, profissoes |
senado_senadores_afastados | Senadores atualmente afastados (fora de exercício) |
Grupo B — Proposições/Matérias (2 ferramentas, backend v3)
| Ferramenta | Descrição |
|---|---|
senado_buscar_materias ⊕ | Busca matérias por tipo, número, ano, palavra-chave, autor ou tramitação (via v3 /processo) |
senado_obter_materia ⊕ | Dados de uma matéria via enum secao: detalhe (situação/relator), tramitacao (histórico) ou textos (documentos) |
Grupo C — Processos (5 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_search_processos ⊕ | Busca processos legislativos (complementar à busca de matérias) |
senado_obter_processo ⊕ | Detalhes completos de um processo legislativo específico |
senado_processo_detalhe | Aspecto de um processo via enum secao: emendas, relatorias ou prazos |
senado_autores_atuais | Parlamentares autores de processos em tramitação, ordenados por produção |
senado_tabelas_processo | 12 tabelas de referência (siglas, assuntos, classes, tipos-*) via enum tabela |
Grupo D — Votações (3 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_obter_votacao ⊕ | Detalhes de uma votação com votos nominais. Aceita codigoVotacao (codigoSessao da sessão plenária). |
senado_votos_materia ⊕ | Votações de uma matéria (via v3 /votacao?codigoMateria), com votos nominais opcionais |
senado_search_votacoes ⊕ | Busca/listagem flexível de votações do plenário por dias, período, processo, matéria ou senador |
Grupo E — Comissões (7 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_listar_comissoes | Lista comissões (colegiados) ativas, filtráveis por tipo |
senado_obter_comissao | Dados de uma comissão via enum secao: resumo (mesa/totais) ou membros (composição). Resolve sigla para código internamente. |
senado_reunioes_comissao | Reuniões de uma comissão num período (lida com intervalos entre anos) |
senado_agenda_comissoes | Agenda de reuniões de todas as comissões numa data |
senado_reuniao_comissao | Detalhe completo de uma reunião: partes, itens, convidados, resultados, links pauta/ata |
senado_requerimentos_cpi | Requerimentos protocolados numa CPI em atividade, paginados (upstream costuma vir vazio mesmo para CPIs ativas; retorno vazio traz aviso) |
senado_distribuicao_materias | Estatísticas de carga por senador numa comissão: autoria ou relatoria |
Grupo F — Plenário (7 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_agenda_plenario | Agenda do plenário — por dia, mês ou Congresso (escopo dia/mes/cn) |
senado_resultado_plenario | Resultados de sessão: itens deliberados, pareceres, desfechos (SF/CN/mês) |
senado_orientacao_bancada | Orientações de lideranças partidárias por votação, com totais |
senado_vetos | Vetos presidenciais por ano ou status de tramitação |
senado_resultado_veto | Resultados nominais de votação de vetos (por veto, projeto vetado ou dispositivo) |
senado_encontro_plenario | Detalhe de sessão legislativa, itens de pauta, resultados ou resumo |
senado_tabelas_plenario | Tipos de sessão, tipos de presença, lista de legislaturas |
Grupo G — e-Cidadania (9 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_ecidadania_listar_consultas | Consultas públicas (conjunto completo das abertas — matérias em tramitação) com votação sim/não; filtro status (padrão aberta) |
senado_ecidadania_obter_consulta | Detalhe de uma consulta: votos, autor, relator, comentários |
senado_ecidadania_consultas_analise | Analisa o conjunto completo de consultas abertas via modo (consenso/polarizada); status padrão aberta |
senado_ecidadania_listar_ideias | Ideias legislativas de cidadãos; ranking das mais apoiadas via ordenarPor: apoios |
senado_ecidadania_obter_ideia | Detalhe de uma ideia: texto, apoios, status de conversão em projeto |
senado_ecidadania_listar_eventos | Eventos interativos (audiências, sabatinas, lives); ranking dos mais comentados via ordenarPor |
senado_ecidadania_obter_evento | Detalhe de um evento: pauta, convidados, link de vídeo |
senado_ecidadania_sugerir_tema_enquete | Sugere temas para enquete mensal a partir de critérios configuráveis |
senado_ecidadania_consultas_votos | Acervo histórico de votos das consultas com quebra por UF (CSV Arquimedes); ranking por total/sim/nao, filtro uf/materia |
Grupo I — Pronunciamentos (3 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_discursos_senador | Pronunciamentos de um senador via enum tipo: discursos (próprios) ou apartes (intervenções) |
senado_discursos_plenario | Todos os discursos em plenário num intervalo de datas |
senado_discurso_texto | Texto integral de um pronunciamento/discurso específico |
Grupo J — Blocos & Lideranças (4 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_listar_blocos | Blocos parlamentares do Senado e seus partidos membros |
senado_obter_bloco | Detalhes de um bloco parlamentar específico |
senado_liderancas | Lideranças do Senado/Câmara/Congresso (líderes, vice-líderes) com o bloco/partido liderado, filtráveis |
senado_mesa | Membros da Mesa Diretora via enum casa: senado (Mesa do SF) ou congresso (Mesa do CN) |
Grupo K — Orçamento (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
senado_orcamento_parlamentar | Emendas parlamentares ao orçamento via enum tipo: emendas (lotes por autor) ou oficios (indicação de destino — filtrável por ano da emenda, paginado, incluirEmendas opcional) |
Grupo L — Legislação Federal (2 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_buscar_legislacao | Busca normas jurídicas federais por tipo, número, ano ou data (ao menos um obrigatório) |
senado_obter_legislacao | Detalhes de uma norma jurídica federal específica |
Grupo M — Votação em Comissões (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
senado_votacao_comissao | Votações em comissões via enum por: comissao, senador ou materia; período opcional |
Grupo N — Taquigrafia (2 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_notas_taquigraficas | Transcrições oficiais de sessões plenárias ou reuniões de comissão — modo resumo com trechos, modo texto integral paginado em blocos, filtro por orador |
senado_videos_taquigrafia | Unidades de vídeo/áudio por sessão ou reunião, com orador e links de mídia |
Grupo O — Senadores/Administrativo (2 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_ceaps | Despesas da cota parlamentar CEAPS por ano — agregadas por senador, tipo de despesa, mês ou fornecedor, ou detalhe itemizado; estatisticas=true retorna estatísticas de distribuição do conjunto completo (min/máx/média/mediana/percentis) + ranking topo/base, ou ranking de grupo por gasto total via agruparPor (senador/tipo/mês/fornecedor) com topN; filtros por senador/mês/tipo/fornecedor |
senado_senadores_admin | Dados administrativos dos senadores via enum tipo: auxilio-moradia, escritorios-apoio ou aposentados |
Grupo P — Servidores / Gestão de Pessoas (4 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_servidores | Servidores públicos por situação (ativo/efetivo/comissionado/inativo), filtráveis por nome, unidade, cargo |
senado_remuneracoes_servidores | Folha de pagamento mensal — resumo por tipo de folha ou composição por pessoa com bruto calculado; estatisticas=true retorna estatísticas de toda a folha (mín/máx/média/mediana/percentis) + ranking topo/base, com campo, consolidarPorServidor, agruparPor e topN |
senado_horas_extras | Pagamentos de horas extras por mês com totais; estatisticas=true retorna estatísticas de distribuição do conjunto completo (mín/máx/média/mediana/percentis) + ranking topo/base, ou um ranking por servidor pelo valor somado via agruparPor (nome/competência), com topN |
senado_pessoal_tabelas | Tabelas de pessoal via enum tabela: quantitativos (pessoal, cargos-funcoes, previsao-aposentadoria, senadores) e listas (estagiarios, pensionistas, lotacoes, cargos) |
Grupo Q — Contratações (6 ferramentas)
| Ferramenta | Descrição |
|---|---|
senado_contratos | Contratos filtrados no Worker sobre a base completa (insensível a acentos): fornecedor, CNPJ, ano, número, objeto, mão de obra |
senado_contratacao_detalhe | Itens, pagamentos, garantias, aditivos ou ativações de um contrato/ata/empenho |
senado_licitacoes | Licitações por número ou texto do objeto |
senado_terceirizados | Colaboradores terceirizados por nome, empresa ou unidade |
senado_empresas_contratadas | Empresas que contratam com o Senado (exige filtro de nome/CNPJ) |
senado_contratacoes_lista | Atas de registro de preços, notas de empenho, jovens aprendizes |
Grupo R — Suprimento de Fundos (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
senado_suprimento_fundos | Adiantamentos de suprimento de fundos por ano: beneficiários, atos de concessão, empenhos, movimentações, transações com cartão; estatisticas=true (tipo transacoes/empenhos/atos-concessao) retorna estatísticas de distribuição do conjunto completo (mín/máx/média/mediana/percentis) + ranking topo/base, ou um ranking pelo valor somado via agruparPor (ex.: fornecedor), com campo e topN contextuais |
Grupo S — Orçamento do Senado (1 ferramenta)
| Ferramenta | Descrição |
|---|---|
senado_execucao_orcamentaria | Execução orçamentária desde 2013 (dotação, empenhado/liquidado/pago) e receitas próprias desde 2012 (previsão vs arrecadado) — agregadas por ano, ação, grupo de despesa, fonte ou origem da receita; estatisticas=true retorna estatísticas de distribuição do conjunto completo (mín/máx/média/mediana/percentis) + ranking topo/base, ou um ranking de grupo pelo campo somado via agruparPor, com campo (padrão pago / arrecadado) e topN |
Grupo T — Estrutura Organizacional (1 ferramenta)
Lê um snapshot empacotado da árvore organizacional do Senado (coletado do portal institucional até o nível de serviço por npm run ingest:estrutura), já que a API de dados abertos só publica unidades até o nível de Secretaria e nunca vincula uma unidade-folha ao seu pai. Unidades que o portal lista apenas por nome, sem página própria (os núcleos CONLEG/CONORF), são capturadas como nós sintéticos a partir da listagem indentada da página. Órgãos de âmbito do Congresso onde o registro de lotações registra servidores (CMO, CPCMS, CMMC) vêm de um complemento curado (src/estrutura/complemento-cn.ts, fonte pública: congressonacional.leg.br) sob uma raiz separada Congresso Nacional (CN) — nunca sob a árvore do Senado, então subordinadasA: "DGER" os exclui enquanto subordinadasA: "CN" os conta. Servidores registrados sob as pseudo-unidades situacionais "Servidores Afastados/em Trânsito - SF" são reportados separadamente como afastadosOuEmTransito por senado_servidores.
| Ferramenta | Descrição |
|---|---|
senado_estrutura_organizacional | Organograma resolvido para um unidade (sigla como DGER ou nome): retorna seus caminho (ancestrais) e todas as unidades subordinadas (subordinadas[] — secretarias, coordenações, serviços, núcleos — com nivel). Combina com o filtro subordinadasA de senado_servidores, que conta/lista todos os servidores sob uma diretoria inteira (um servidor está em um serviço-folha, então filtrar lotacao pela sigla do pai retorna 0). |
Grupo U — Deep Research (2 ferramentas)
O contrato OpenAI Deep Research: as únicas duas ferramentas sem o prefixo senado_, porque os nomes são fixados pelo contrato. Registradas pelo mesmo shim que as demais (anotações somente leitura, outputSchema permissivo, telemetria por ferramenta) e servidas apenas em /mcp — o perfil curado do app ChatGPT não as inclui. O índice (senadores em exercício + comissões ativas, ~300 documentos) é construído no primeiro uso a partir dos mesmos dois endpoints de lista que as ferramentas senado_listar_* leem, e mantido por 24 h.
| Ferramenta | Descrição |
|---|---|
search | Ranqueia a consulta (linguagem natural ou palavras-chave, pt/en, insensível a acentos) contra senadores em exercício e comissões ativas; retorna até 10 { id, title, url } — sen:<código> com a URL do perfil público, com:<código> com a página pública da comissão. Proveniência de ambas as listas em structuredContent/_meta. |
fetch | Retorna o documento para um id de search como { id, title, text, url, metadata }: a biografia e os mandatos do senador (mesma leitura de senado_obter_senador) ou o resumo e a mesa da comissão (mesma leitura de senado_obter_comissao), como Markdown, com a proveniência dessa leitura. Id desconhecido → erro. |
Total: 69 ferramentas
Prompts (4)
Modelos de fluxo de trabalho reutilizáveis em pt-BR (capacidade MCP prompts), definidos em src/prompts.ts:
| Prompt | Args | O que orienta |
|---|---|---|
senado_gastos_senador | senador, ano | Resolve o senador e agrega/detalha despesas CEAPS. |
senado_tramitacao_materia | sigla, numero, ano | Obtém situação atual + histórico de tramitação da matéria. |
senado_votos_senador | senador, periodo? | Lista os votos nominais do senador no período. |
senado_panorama_ecidadania | — | Consolida consultas (consenso/polarização), ideias e eventos populares. |
Recursos (5)
Documentos/tabelas de contexto estáticos (capacidade MCP resources), definidos em src/resources.ts:
| URI | Tipo | Conteúdo |
|---|---|---|
senado://guia | markdown | Visão geral e qual ferramenta usar por objetivo. |
senado://catalogo | markdown | As 69 ferramentas agrupadas por domínio. |
senado://glossario | markdown | Siglas e termos do Senado (PEC, CEAPS, CCJ, RCN…). |
senado://tabelas/tipos-materia | json | Tipos de proposição (sigla/nome/descrição). |
senado://tabelas/ufs | json | As 27 unidades federativas. |
Estrutura do Projeto
src/
├── index.ts # Worker entrypoint (fetch handler + scheduled/Cron handler)
├── server.ts # McpServer factory (creates per-request instance)
├── auth.ts # Optional Bearer token auth (constant-time compare)
├── metrics.ts # In-memory counters served at /metrics
├── types.ts # Env, cache categories, safeguard constants
├── cache/
│ ├── l0-memory.ts # In-memory Map cache with TTL + LRU eviction
│ ├── l1-cache-api.ts # Cloudflare Cache API wrapper (synthetic GET keys)
│ └── manager.ts # Cache orchestrator (L0 → L1 → upstream)
├── throttle/
│ ├── token-bucket.ts # Token bucket rate limiter (global + per-client)
│ └── upstream.ts # Upstream fetch with concurrency limit, retry, timeout
├── scraper/
│ ├── ecidadania.ts # Isolated e-Cidadania scraper (REST lists + regex HTML detail; buildConsultaResumo)
│ ├── pipeline.ts # 2h Cron: targeted highlight metric splice (consultas/eventos/ideias); corpora owned by the off-Worker jobs
│ ├── anomaly.ts # Run classification (anomalous run never overwrites current)
│ └── store.ts # D1 reads (resolveList + per-entity staleness, lastGoodRunAt) + detail write-through
├── instrument.ts # Per-tool call telemetry (in-memory + Analytics Engine)
├── utils/
│ ├── logger.ts # Structured JSON logging
│ └── validation.ts # toolResult, toolError, errorFrom, buildParams, ensureArray helpers
└── tools/
├── referencia.ts # Group H — 1 reference/metadata tool
├── senadores.ts # Group A — 5 senator tools
├── materias.ts # Group B — 2 bill/matter tools (v3 backend)
├── processos.ts # Group C — 5 process tools
├── votacoes.ts # Group D — 3 vote tools
├── comissoes.ts # Group E — 7 committee tools
├── plenario.ts # Group F — 7 plenary tools
├── ecidadania.ts # Group G — 8 e-Cidadania tools (read from D1; see scraper/)
├── discursos.ts # Group I — 3 speech tools
├── composicao.ts # Group J — 4 bloc/leadership tools
├── orcamento.ts # Group K — 1 budget tool
├── legislacao.ts # Group L — 2 federal law tools
├── votacao-comissao.ts # Group M — 1 committee voting tool
├── taquigrafia.ts # Group N — 2 stenographic record tools
├── senadores-admin.ts # Group O — 2 admin senator tools (CEAPS, housing)
├── servidores.ts # Group P — 4 personnel tools
├── contratacoes.ts # Group Q — 6 procurement tools
├── supridos.ts # Group R — 1 petty-cash tool
├── orcamento-senado.ts # Group S — 1 budget execution tool
└── estrutura.ts # Group T — 1 org-structure tool (reads src/data/ snapshot via src/estrutura/)
scripts/
└── ingest-ecidadania/ # Off-Worker full-corpus consultas ingestion (run via `npm run ingest:ecidadania`)
├── index.ts # Orchestrator: crawl → status (/processo) → normalize → guards → out.sql
├── listing.ts # Pure listing parser (parseConsultaListingPage, findLastPage)
├── status.ts # tramitando=S set from /processo → aberta/encerrada (deriveStatus)
├── restatus.ts # Linger fix: re-status stored rows by /processo membership (close zombies)
├── http.ts # Polite fetch (retry/backoff) for the unattended crawl
├── d1.ts # D1 pre-reads (existing meta, payloads, last good rows) via wrangler
├── verify.ts # consultas_votos on-demand integrity-check verdict (verifyAcervoIntegrity)
└── sql.ts # out.sql generation (mirrors SQL.upsert/SQL.history; reuses SyncRecord)
.github/workflows/ # ingest-ecidadania.yml (daily D1 corpus load), verify-consultas-votos.yml
# (weekly frozen-acervo integrity check), publish-mcp.yml (registry),
# usage-report.yml (monthly Analytics report), deprecate-registry.yml
# (all pinned to current Node 24 action majors — see each YAML for exact versions)
migrations/ # D1 schema (0001 tables, 0002 indexes, 0003 comment level + detail cursor) for the e-Cidadania pipeline
tests/ # Vitest unit tests mirroring src/ (parsers, cache, throttle, auth, scraper,
# pipeline/anomaly/store, listing/sql/highlights, plus e-Cidadania contract tests)
Variáveis de Ambiente
| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
SENADO_BASE_URL | Não | https://legis.senado.leg.br/dadosabertos | URL base da API legislativa |
SENADO_ADM_BASE_URL | Não | https://adm.senado.gov.br/adm-dadosabertos | URL base da API administrativa |
ALLOWED_ORIGIN | Não | * | Origem permitida para CORS |
API_KEY | Não (secreta) | — | Quando definida, exige Authorization: Bearer <key> em todas as requisições, exceto /health, /metrics e preflight de CORS |
CACHE_KV | Sim (binding) | — | Namespace KV para cache L2 |
ECIDADANIA_DB | Sim (binding) | — | Banco D1 para o pipeline do e-Cidadania (persistência de listas + histórico) |
ECIDADANIA_CORPUS_STALE_MAX_MIN | Não | 14400 | Janela de obsolescência (minutos, ~10d) para os corpora completos fora do Worker (todas as entidades do e-Cidadania) — servidos sinalizados, nunca reduzidos a destaques |
ECIDADANIA_CORPUS_MIN_PCT | Não | 80 | Piso catastrófico para os jobs de corpus fora do Worker: um crawl/parse completo abaixo desta % do último bom corpus é rejeitado |
CLOUDFLARE_API_TOKEN | Não (secreta) | — | Segredo do GitHub Actions (escopo de edição D1) para os jobs de ingestão/verificação de integridade do corpus; não usado pelo Worker |
CLOUDFLARE_ACCOUNT_ID | Não (var de Actions) | — | Variável de repositório do GitHub Actions para o wrangler pular a descoberta automática de conta /memberships (um token com escopo D1 não pode lê-la); exigida junto com CLOUDFLARE_API_TOKEN no job de ingestão |
SENADO_ANALYTICS | Não (binding) | — | Conjunto de dados do Analytics Engine para telemetria de chamadas por ferramenta |
Conectando Clientes MCP
Este é um servidor remoto (HTTP Streamable, sem instalação, acesso aberto) — aponte qualquer cliente MCP para
https://senado.sidneybissoli.com/mcp. Além de 69 ferramentas, expõe prompts (fluxos de trabalho prontos em pt-BR:
senado_gastos_senador, senado_tramitacao_materia, senado_votos_senador,
senado_panorama_ecidadania) e recursos (senado://guia, senado://catalogo,
senado://glossario, senado://tabelas/tipos-materia, senado://tabelas/ufs).
Um clique (LobeHub)
Instale pelo marketplace do LobeHub — abra a página do servidor e clique em Instalar (ela pré-preenche o endpoint remoto, sem necessidade de configuração).
Claude Desktop / Claude Code
Adicione à sua configuração MCP:
{
"mcpServers": {
"senado-br": {
"url": "https://senado.sidneybissoli.com/mcp"
}
}
}
Para clientes baseados em comando (ou qualquer cliente sem suporte nativo a remoto), use a ponte mcp-remote:
{
"mcpServers": {
"senado-br": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://senado.sidneybissoli.com/mcp"]
}
}
}
MCP Inspector
npx @modelcontextprotocol/inspector https://senado.sidneybissoli.com/mcp
Licença
MIT
Créditos
Ícone: "Amanhecer no Congresso Nacional" — fotografia do Congresso Nacional brasileiro, usada sob licença Creative Commons. (Se você é o autor, abra uma issue para adicionarmos a atribuição completa / o link da licença.)