Senado BR MCP

Datos abiertos del Senado Federal de Brasil a través de MCP — 90 herramientas en el proceso legislativo, administración del Senado (gastos de CEAPS, nómina, contratos) y el portal e-Cidadania. Cloudflare Workers, Streamable HTTP, sin autenticación. Respuestas en pt-BR.

Documentación

Servidor MCP Senado Brasil

Cloudflare Workers MCP Tools CI MCP Registry LobeHub LightNow capabilities senado-br-mcp-cloudflare MCP server smithery badge GitHub stars GitHub Sponsors License: MIT Status

🇧🇷 Leia em Português

Un servidor MCP público y alojado que brinda a los asistentes de IA acceso en vivo y estructurado a los datos abiertos del Senado brasileño — sin instalación, sin cuenta, sin clave API. Apunta tu cliente MCP al endpoint alojado y comienza a preguntar sobre senadores, proyectos de ley, votaciones, gastos y más. Se ejecuta en Cloudflare Workers sobre Streamable HTTP.

Expone 69 herramientas, 4 prompts y 5 recursos en dos dominios:

  • Legislativo — senadores; proyectos de ley y su tramitación; votaciones; comisiones; sesiones plenarias, resultados y vetos presidenciales; orientación de votación de bloques partidarios; discursos y transcripciones estenográficas; bloques y liderazgos; legislación federal; y participación ciudadana a través del portal e-Cidadania.
  • Administrativo — gastos de la cuota parlamentaria CEAPS; auxilio vivienda; servidores públicos y nómina; horas extras; pasantes; contratos de compras y licitaciones; personal tercerizado; fondos de caja menor; y ejecución presupuestaria.

Los datos provienen de tres fuentes oficiales — la API de datos abiertos legislativos, la API de datos abiertos administrativos y el portal e-Cidadania. Todas las respuestas de las herramientas están en portugués (pt-BR). Consulta CHANGELOG.md para el historial de versiones.

Vélo en acción

Apunta un cliente al endpoint y pregunta en lenguaje natural — inglés o portugués:

  • "¿Cómo votaron los senadores de São Paulo en las votaciones plenarias más recientes?" → senado_search_votacoes
  • "Muestra el avance legislativo de la PEC 45/2019 (una propuesta de enmienda constitucional)." → senado_buscar_materias + senado_obter_materia
  • "¿Cuánto se gastó en la asignación parlamentaria CEAPS en 2024, desglosado por tipo de gasto?" → senado_ceaps

Las respuestas llegan en vivo desde las APIs oficiales de datos abiertos del Senado — cifras exactas con procedencia, no números adivinados a partir de datos de entrenamiento.

Úsalo (alojado — sin configuración)

Este es un servidor remoto, alojado y de acceso abierto. Para usarlo, apunta cualquier cliente MCP al endpoint Streamable HTTP — sin instalación, sin cuenta, sin clave API, sin configuración:

https://senado.sidneybissoli.com/mcp

Superficie de app OpenAI / ChatGPT

Para el envío y la revisión del SDK de OpenAI Apps, el Worker también expone una superficie MCP curada:

https://senado.sidneybissoli.com/mcp/openai-app-v2

Este endpoint mantiene intencionalmente intacto el servidor MCP público completo en /mcp, pero limita el descubrimiento de herramientas a 27 herramientas de alta señal orientadas a la intención para uso en la app ChatGPT. /mcp/openai-app sigue disponible como alias heredado, pero las nuevas configuraciones de la app ChatGPT deben usar /mcp/openai-app-v2 para que los clientes obtengan el esquema de herramientas actual. Las herramientas siguen llamando a los mismos manejadores y devuelven el mismo sobre de procedencia; solo la superficie anunciada es más reducida. Cualquier listado de la app ChatGPT debe presentar esto como una app independiente de investigación de datos abiertos, no como un conector oficial del Senado, OpenAI o ChatGPT.

Para ChatGPT Apps, esas 27 herramientas también anuncian una plantilla compartida de UI de MCP Apps en ui://senado-br-mcp/openai-app-dashboard-v2.html. El widget autocontenido renderiza el structuredContent devuelto como un panel compacto con métricas, registros principales y fuente/procedencia, sin agregar otra herramienta de datos visible para el modelo.

URLs legales públicas para revisión de la app:

  • Política de privacidad: https://senado.sidneybissoli.com/privacy
  • Términos de uso: https://senado.sidneybissoli.com/terms

ChatGPT (Deep Research)

La investigación profunda de ChatGPT (y el conocimiento de la empresa, y los flujos de trabajo de investigación sobre la Responses API) solo usa un servidor MCP que expone exactamente search y fetch — este servidor lo hace, además de las herramientas senado_*, en la superficie completa /mcp (no en el perfil de app curado). Apunta el conector al endpoint alojado, sin clave requerida:

https://senado.sidneybissoli.com/mcp

search clasifica la consulta entre los senadores en ejercicio y las comisiones activas del Senado y del Congreso Nacional y devuelve { id, title, url } (sen:<código> / com:<código>); fetch devuelve el documento como Markdown legible — la biografía y los mandatos del senador, o el resumen y la mesa directiva de la comisión — con la página pública canónica (el perfil del senador en www25.senado.leg.br o la página de la comisión en legis.senado.leg.br), que es lo que ChatGPT cita. Ambos llevan el mismo bloque de procedencia que todas las demás herramientas, en structuredContent y _meta (el canal de texto es el JSON del contrato). En el modo desarrollador de ChatGPT (Configuración → Seguridad e inicio de sesión → Modo desarrollador) cualquier herramienta es invocable — las herramientas senado_* siguen siendo las que se deben usar para datos.

Instalación (cualquier cliente)

Para clientes que lanzan servidores MCP como comando — y para configuración con un solo comando — usa el puente mcp-remote. Sin compilación, sin configuración, sin clave:

npx -y mcp-remote https://senado.sidneybissoli.com/mcp

Todo lo que está debajo de Arquitectura (Requisitos previos, Configuración, Despliegue) es solo para autoalojar opcionalmente tu propia instancia — no es necesario para usar este servidor público.

Ejecutar localmente (npx · stdio)

¿Prefieres no enrutar consultas a través de un host de terceros (por ejemplo, una política de redacción)? El mismo servidor también se ejecuta como proceso stdio local que habla directamente con las APIs oficiales del gobierno — mismas 69 herramientas, mismo sobre de procedencia, sin Cloudflare en el medio. Este es el canal npm/stdio, publicado como senado-br-mcp.

Apunta un cliente basado en comandos (Claude Desktop/Code, etc.) al paquete — npm lo descarga y ejecuta, sin clonar ni compilar:

{
  "mcpServers": {
    "senado-br": {
      "command": "npx",
      "args": ["-y", "senado-br-mcp"]
    }
  }
}

Para ejecutarlo directamente o modificarlo, usa el checkout del código fuente:

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)

Paridad con el servidor alojado: las herramientas legislativas y administrativas son idénticas (mismas APIs upstream, mismo límite/caché/procedencia) — localmente el caché L1 de Cloudflare es un no-op, pero el caché L0 en memoria sigue funcionando, por lo que los resultados son los mismos. La única diferencia son las herramientas de lista/corpus de e-Cidadania: sin D1 recurren a un scraping en vivo de los ~5 REST highlights, marcado mediante meta.fonte / possivelDesatualizacao; las herramientas de detalle (obter_*) son idénticas. Los registros van a stderr — stdout lleva solo el flujo de protocolo JSON-RPC.

Agent Skill (opcional)

Este repositorio incluye un Agent Skill de Claude en .claude/skills/senado-br/ que enseña a Claude cuándo recurrir a este servidor y cómo usar bien sus 69 herramientas — un mapa temático de herramientas, playbooks de pregunta común→herramienta, el contrato de procedencia y errores comunes (fechas, el puente codigoMateria, el listado de conjunto abierto de e-Cidadania, paginación). Apunta de vuelta a los recursos senado://catalogo / senado://guia del propio servidor en lugar de duplicarlos.

Claude Code lo descubre automáticamente cuando trabajas en este repositorio. Para usarlo en otro lugar, copia .claude/skills/senado-br/ en tu ~/.claude/skills/, o comprime la carpeta y súbela en claude.ai (Configuración → Funciones). El skill asume que el servidor MCP senado-br está conectado (alojado o mediante npx).

Arquitectura

  • Runtime: Cloudflare Workers (ESM)
  • Transporte: Streamable HTTP (especificación MCP 2025-03-26) mediante createMcpHandler de agents/mcp
  • Protocolo: MCP sobre JSON-RPC — /mcp maneja el servidor público completo; /mcp/openai-app-v2 expone un perfil curado de 27 herramientas más un widget compartido de MCP Apps para revisión/envío de apps de OpenAI (/mcp/openai-app sigue como alias heredado)
  • SDK: @modelcontextprotocol/server 2.x (instancias McpServer por solicitud; el @modelcontextprotocol/sdk v1 sigue solo como par de agents, en tiempo de desarrollo)
  • Validación: esquemas Zod para todas las entradas de herramientas
  • Caché: 2 capas (memoria L0 + API de caché L1) con clave SHA-256
  • Almacén e-Cidadania: base de datos D1 actualizada por un Cron Trigger (cada 2 h) — las herramientas de lista leen de D1 con respaldo de scraping en vivo y una bandera de obsolescencia; las herramientas de detalle se mantienen en vivo con escritura directa (consulta e-Cidadania)
  • Límite de velocidad: Token bucket — global (8 req/s) + por cliente (2 req/s)
  • Límite upstream: Máximo 6 solicitudes concurrentes, presupuesto de 10 s por viaje, reintento en 429/5xx/error de red con retroceso exponencial y Retry-After (fetch compartido de cartera @sbissoli/mcp-upstream); la procedencia de cada respuesta lleva los diagnósticos medidos de retrieval (viajes, intentos, anomalías)
  • Autenticación: Token Bearer opcional (configura el secreto API_KEY; acceso abierto cuando no está configurado). Comparación en tiempo constante.
  • Observabilidad: Registro JSON estructurado + contadores en memoria en /metrics; telemetría de llamadas por herramienta (selección, tasa de error, caché-vs-en-vivo) en Cloudflare Analytics Engine, sin PII
  • Disponibilidad: Se ejecuta en la propia red global de Cloudflare detrás de un dominio personalizado — sin host de terceros que pueda desaparecer. Los /health y /status públicos (versión + id/marca de tiempo del último despliegue) hacen verificables el tiempo de actividad y la compilación actual; la insignia de estado arriba hace ping al endpoint en vivo
  • Pruebas: pruebas unitarias Vitest para parsers, helpers, caché, límite y autenticación

Autoalojamiento (opcional)

No es necesario para usar el servidor — ya está alojado en https://senado.sidneybissoli.com/mcp (acceso abierto). Sigue esta sección solo si quieres ejecutar tu propia instancia privada.

Requisitos previos

Configuración

1. Instalar dependencias

npm install

2. Crear espacio de nombres 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

Reemplaza el ID de espacio de nombres KV de marcador de posición:

[[kv_namespaces]]
binding = "CACHE_KV"
id = "YOUR_KV_NAMESPACE_ID_HERE"

Opcionalmente configura ALLOWED_ORIGIN para restringir CORS:

[vars]
ALLOWED_ORIGIN = "https://your-app.example.com"

La canalización de e-Cidadania necesita una base de datos D1 y un Cron Trigger (ambos ya declarados en wrangler.toml — reemplaza el ID de la base de datos):

[[d1_databases]]
binding = "ECIDADANIA_DB"
database_name = "senado-ecidadania"
database_id = "YOUR_D1_DATABASE_ID_HERE"

[triggers]
crons = ["0 */2 * * *"]

Crea la base de datos (pega el ID devuelto arriba) y aplica el esquema:

npx wrangler d1 create senado-ecidadania
npx wrangler d1 migrations apply senado-ecidadania --remote

Las herramientas de lista recurren al scraping en vivo cuando D1 está vacío, por lo que el servidor funciona antes de la primera ejecución del Cron.

4. (Opcional) Habilitar autenticación

wrangler secret put API_KEY
# Clients must then send: Authorization: Bearer <key>
# When API_KEY is not set, the server is open access.

5. Desarrollo local

npm run dev
# Dev server runs locally on port 8787 (local only).
# The public MCP endpoint is https://senado.sidneybissoli.com/mcp

6. Pruebas y verificación de tipos

npm test             # run all tests once
npm run test:watch   # watch mode
npm run typecheck    # tsc --noEmit

7. Despliegue

npm run deploy
# Serves at https://senado.sidneybissoli.com (custom domain) and
# https://senado-br-mcp.sidneybissoli.workers.dev (workers.dev fallback)

Endpoints

RutaMétodosDescripción
/GETPágina de inicio (pt-BR) — identifica el cliente detrás del User-Agent saliente: qué es el servicio, postura de carga, contacto (siempre público)
/mcpPOST, GET, DELETE, OPTIONSEndpoint MCP Streamable HTTP (gestionado por createMcpHandler)
/healthGETVerificación de salud — devuelve ok (siempre público)
/statusGETJSON: status, version y metadatos del último despliegue (deploy.id/tag/timestamp) — disponibilidad + compilación actual, sin necesidad de handshake MCP (siempre público)
/metricsGETContadores JSON: solicitudes, llamadas a herramientas, aciertos/fallos de caché, llamadas/reintentos/errores upstream, fallos de autenticación (siempre público)

Ejemplos de solicitudes MCP

Todas las solicitudes van a POST /mcp con formato JSON-RPC 2.0.

Listar herramientas disponibles

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}

Llamar a una herramienta — Listar senadores de SP

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "senado_listar_senadores",
    "arguments": {
      "uf": "SP",
      "emExercicio": true
    }
  }
}

Llamar a una herramienta — Buscar proyectos de ley por palabra clave

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "senado_buscar_materias",
    "arguments": {
      "palavraChave": "inteligência artificial",
      "tramitando": true
    }
  }
}

Llamar a una herramienta — Obtener votaciones plenarias recientes

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "senado_search_votacoes",
    "arguments": {
      "dias": 7
    }
  }
}

Llamar a una herramienta — Ideas ciudadanas más populares

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "senado_ecidadania_listar_ideias",
    "arguments": {
      "ordenarPor": "apoios",
      "ordem": "desc",
      "status": "aberta"
    }
  }
}

Endpoints de API upstream

El servidor consume dos clases de endpoints upstream de la API del Senado:

Endpoints heredados (sufijo .json, respuestas PascalCase)

Usado pelos Grupos A, E, F, H, I, J, K, L, M, N. El sufijo .json se añade automáticamente mediante upstream.ts. Ninguno de estos está marcado como obsoleto en el upstream.

Ruta upstreamUsado por
/senador/lista/atualsenado_listar_senadores
/senador/lista/legislatura/{legislatura}senado_listar_senadores (parámetro legislatura)
/senador/{codigo} (+ /mandatos)senado_obter_senador (biografia + mandatos vía llamada extra)
/senador/{codigo}/licencas, /comissoes, /cargos, /historicoAcademico, /filiacoes, /profissaosenado_senador_historico (enum tipo)
/senador/afastadossenado_senadores_afastados
/senador/{codigo}/apartessenado_discursos_senador (tipo=apartes)
/comissao/lista/colegiadossenado_listar_comissoes (+ resolución sigla-a-código)
/comissao/{codigo}senado_obter_comissao (secao=resumo; código numérico, no 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}/requerimentossenado_requerimentos_cpi (el upstream suele estar vacío incluso para CPIs activas — un resultado vacío lleva un 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/legislaturassenado_tabelas_plenario
/materia/vetos/{ano}, /vetos/aposrcn, /vetos/antesrcn, /vetos/encerradossenado_vetos
/taquigrafia/notas/{sessao|reuniao}/{id}senado_notas_taquigraficas
/taquigrafia/videos/{sessao|reuniao}/{id}senado_videos_taquigrafia
/senador/{codigo}/discursossenado_discursos_senador
/plenario/lista/discursos/{dataInicio}/{dataFim}senado_discursos_plenario
/discurso/texto-integral/{codigo}senado_discurso_texto (texto plano, obtenido directamente)
/senador/lista/tiposUsoPalavrasenado_tabelas_referencia (tabela=tipos-uso-palavra)
/composicao/lista/blocossenado_listar_blocos
/composicao/bloco/{codigo}senado_obter_bloco
/composicao/liderancasenado_liderancas
/composicao/mesaSFsenado_mesa (casa=senado)
/composicao/mesaCNsenado_mesa (casa=congresso)
/orcamento/listasenado_orcamento_parlamentar (tipo=emendas)
/orcamento/oficiossenado_orcamento_parlamentar (tipo=oficios)
/legislacao/listasenado_buscar_legislacao
/legislacao/{codigo}senado_obter_legislacao
/legislacao/tiposNormasenado_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/atualsenado_autores_atuais

Endpoints v3 (arrays/objetos JSON planos, camelCase)

Usado por los Grupos B, C, D. Las fechas deben estar en formato ISO (YYYY-MM-DD) — las herramientas aceptan YYYYMMDD y convierten. El parámetro de consulta codigoMateria conecta los códigos legacy de matéria con los procesos v3.

Ruta upstreamUsado por
/votacaosenado_obter_votacao, senado_search_votacoes, senado_votos_materia, senado_votacoes_senador
/processosenado_search_processos, senado_buscar_materias
/processo/{id}senado_obter_processo, senado_obter_materia (secao=detalhe/tramitacao)
/processo/documentosenado_obter_materia (secao=textos)
/processo/emendasenado_processo_detalhe (secao=emendas)
/processo/relatoriasenado_processo_detalhe (secao=relatorias), senado_obter_materia (relator)
/processo/prazosenado_processo_detalhe (secao=prazos)
/processo/{siglas,assuntos,classes,destinos,entes,tipos-*}senado_tabelas_processo (12 tablas de referencia)

API administrativa (adm.senado.gov.br/adm-dadosabertos, JSON plano snake_case)

Usado por los Grupos O, P, Q, R vía admFetch (sin sufijo .json; HTTP 404 se trata como colección vacía). La URL base es configurable mediante SENADO_ADM_BASE_URL.

Ruta upstreamUsado por
/api/v1/senadores/despesas_ceaps/{ano}senado_ceaps (~10 MB/año, en caché + agregado en el 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/mes)
/api/v1/servidores/horas-extras/{ano}/{mes}senado_horas_extras
/api/v1/servidores/quantitativos/*, /previsao-aposentadoria, /api/v1/senadores/quantitativos/senadoressenado_pessoal_tabelas (cuantitativos)
/api/v1/servidores/{estagiarios,pensionistas,lotacoes,cargos}senado_pessoal_tabelas (listas nominales)
/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/licitacoessenado_licitacoes
/api/v1/contratacoes/terceirizadossenado_terceirizados
/api/v1/contratacoes/empresassenado_empresas_contratadas (~13 MB, requiere 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.jsonsenado_execucao_orcamentaria (feeds JSON diarios, cadenas decimales brasileñas normalizadas)

e-Cidadania (respaldado por D1, actualizado por Cron)

Los datos de lista de e-Cidadania se persisten en una base de datos D1 (ecidadania_current/_history/_scrape_runs, discriminados por entidade; además de ecidadania_comentarios para el nivel de comentarios de audiência y ecidadania_detalhe_cursor para el relleno reanudable de detalles — añadidos en el esquema v2) y se leen desde allí en lugar de extraerse en cada llamada. Tres cadencias escriben en ella:

  • una GitHub Action diaria fuera del Worker posee el corpus completo de las tres entidades vivas (consultas, eventos, ideias; ver más abajo) — la fuente de verdad. Diaria (no semanal) porque la serie de primera aparición MIN(scraped_at) es la única señal medible del ritmo de entrada y cada día omitido la acorta permanentemente (ROADMAP Etapa 2, decisión D3);
  • una Action de ingesta semanal (.github/workflows/verify-consultas-votos.yml — nombre de archivo histórico) para el acervo consultas_votos: el Senado republica el CSV de Arquimedes periódicamente (confirmado el 2026-07-20), por lo que la ejecución semanal re-ingiere la versión actual bajo las mismas protecciones de anomalías que los otros corpus (ver más abajo);
  • un Cron Trigger dentro del Worker (0 */2 * * *, src/scraper/pipeline.ts → refreshEcidadania) realiza solo un empalme de métricas dirigido de los ~5 destacados REST por entidad viva (restcolecaomaismateria/ideia/audiencia — votos/comentarios/apoyos), registrado como ok-metrica para que nunca vuelva a romper la línea base del corpus ni toque la cola larga. En v2, el empalme de eventos preserva el recuento canónico de comentarios del corpus (el rastreo diario es la fuente de verdad para comentarios, por lo que el empalme no puede hacerlo oscilar contra el recuento REST degradado).

Ambos escritores construyen cargas útiles mediante los constructores canónicos buildXResumo + contentHash compartido, por lo que sus filas son byte-idénticas. Cada escritura:

  • hace upsert de ecidadania_current (una fila por elemento — lo que leen las herramientas),
  • añade ecidadania_history solo cuando el content_hash de un elemento cambia (listo para series temporales),
  • registra cada ejecución en ecidadania_scrape_runs.

Una protección de anomalías (src/scraper/anomaly.ts, classifyRun) garantiza que una ejecución fallida o anómala del corpus (cero filas, o menos del ECIDADANIA_CORPUS_MIN_PCT% de la última ejecución buena) nunca sobrescriba el último estado bueno.

Las herramientas de lista / análisis (listar_*, consultas_analise, sugerir_tema_enquete, consultas_votos) leen desde D1 vía resolveList (src/scraper/store.ts): D1 primero. Como cada entidad es ahora un corpus completo, un corpus obsoleto se sirve desde D1 marcado (possivelDesatualizacao: true) en lugar de colapsar a los ~5 destacados en vivo (el bug original de cobertura); el raspado en vivo se reserva para un D1 vacío (arranque en frío, antes de la primera ejecución semanal). La obsolescencia usa ECIDADANIA_CORPUS_STALE_MAX_MIN (~10 días). Cada respuesta de lista lleva un meta aditivo (fonte, lastScrapedAt, possivelDesatualizacao) para que los llamadores siempre vean la edad real de los datos y nunca reciban datos obsoletos en silencio.

Las herramientas de detalle (obter_*) permanecen en vivo (HTML raspado con regex dirigido por clases CSS) para frescura, y escriben su carga útil más rica en ecidadania_detalhe fire-and-forget (deduplicado por content_hash), de modo que el historial de detalles se acumula sin añadir latencia a la respuesta.

Ingesta de corpus completo (fuera del Worker)

Los tres corpus vivos de e-Cidadania son propiedad de la Action diaria (.github/workflows/ingest-ecidadania.yml), cada uno con su propio orquestador scripts/ingest-ecidadania/index-*.ts que emite out-*.sql por lotes que el paso de aplicación carga en masa:

  • consultas — consultas abiertas (detalladas más abajo). En v2, cada materia rastreada también se enriquece desde su página de detalle (visualizacaomateria) para autoria/relator; estos son inmutables, por lo que solo se obtienen las filas aún no enriquecidas.
  • eventos — audiências/eventos del listado HTML principalaudiencia?p=N; el estado proviene directamente del bloque del listado (sin puente /processo). En v2, cada evento se enriquece desde su página de detalle (data/hora canónicos + comissaoNomeCompleto/local/descricao/pauta/convidados/videoUrl) y su fragmento de comentarios AJAX (recuento canónico + una fila ecidadania_comentarios por comentario, comparado con los hashes almacenados y emitido como out-eventos-comentarios-*.sql).
  • ideias — ideias legislativas (~113.7k) desde pesquisaideia?situacao=N&p=M, rastreadas por cubo de situacao (el listado no tiene estado en línea) y emitidas en lotes de ~10k declaraciones. En v2, el rastreo del listado preserva los campos de detalle inmutables, y un relleno reanudable separado (index-ideias-detalhe.ts, ejecutado vía ingest:ecidadania:ideias-detalhe) los completa un fragmento por ejecución — porque ~113.7k obtenciones de detalle no caben en una sola Action, persiste un cursor en ecidadania_detalhe_cursor y da la vuelta al final.

La cuarta entidad, consultas_votos, es un acervo histórico separado de votos por UF analizado desde el CSV de Arquimedes de ~33 MB (Proposições-com-votos.csv), agregado a un registro por matéria con un desglose votosPorUf. El sello "dados atualizados até" del CSV se convierte en la procedencia data_vintage; se excluye del hash de fila (consultaVotoCore) para que una re-ingesta con votos sin cambios no agite _history. STATUS ATUAL es uniformemente "Descontinuado", por lo tanto es archivístico, no una migración de las consultas abiertas. Servido por senado_ecidadania_consultas_votos con procedencia apuntando al CSV (ECIDADANIA_ARQUIMEDES). Está excluido del trabajo diario y es propiedad de su propia Action de ingesta semanal (.github/workflows/verify-consultas-votos.yml — el nombre de archivo mantiene el prefijo histórico verify-): el acervo se trató originalmente como una versión única congelada (ROADMAP Etapa 2, decisión D1) y la ejecución semanal solo lo verificaba, pero el 2026-07-20 el Senado republicó el CSV como una versión nueva (+43 matérias, 648 actualizadas), por lo que la ejecución programada ahora re-ingiere la versión actual bajo las protecciones de anomalías estándar (CSV vacío/truncado y el piso catastrófico aún fallan sin escribir; el despacho force anula el piso). El modo de verificación del script (INGEST_CONSULTAS_VOTOS_VERIFY=1 / --verify) sigue disponible como verificación de integridad bajo demanda.

El trabajo consultas es la implementación de referencia:

consultas cubre el conjunto completo de consultas ABIERTAS — cada materia actualmente en tramitación (~7.7k), no solo los ~5 destacados. Confirmado en la primera ejecución: el listado pesquisamateria es solo en-tramitación, por lo que las consultas cerradas/históricas no son capturadas por esta fuente (un relleno histórico previo a la ingesta está fuera de alcance). Tres decisiones de diseño establecidas:

  1. Ingestión desacoplada. El conjunto abierto se obtiene mediante un trabajo TypeScript fuera del Worker (scripts/ingest-ecidadania/, ejecutado por una GitHub Action diaria — .github/workflows/ingest-ecidadania.yml) que pagina el listado HTML (pesquisamateria?p=1..N, la única fuente de cobertura completa para consultas abiertas) para obtener ids y conteos de votos, y carga en bloque D1; el Worker solo lee. El rastreo frágil y largo se mantiene fuera de la ruta de solicitud/Cron.
  2. Estado desde /processo, no desde HTML. Una consulta se ejecuta desde la presentación hasta el final de la tramitación, por lo que status es una función del asunto: abierta ⟺ el codigoMateria está en el conjunto /processo tramitando=S, derivado de JSON robusto (nunca extraído). Cada consulta entra como aberta (el listado solo produce asuntos en tramitación); en cada ejecución completa, el trabajo vuelve a derivar el estado de todas las filas almacenadas mediante la pertenencia a /processo (no por ausencia en el listado, que puede ser transitoria), por lo que una consulta cuyo asunto sale de tramitación cambia a encerrada. Los conjuntos encerrada/todas crecen con el tiempo; las consultas cerradas antes de la primera ingesta no se capturan (fuera de alcance). Las herramientas de listado/análisis usan status: aberta por defecto.
  3. Dos cadencias reconciliadas (un contrato de escritura compartido). El trabajo reutiliza contentHash + el constructor ConsultaResumo + classifyRun de src/scraper/, por lo que sus filas son byte-idénticas a las del Cron. El trabajo diario gestiona la cola larga; el Cron de 2h mantiene frescos los ~5 puntos destacados abiertos/activos mediante una inserción de métrica dirigida (registrada como ok-metrica, omitiendo la línea base classifyRun del corpus). La frescura del corpus (possivelDesatualizacao) se calcula desde la última ejecución de status='ok' y usa una ventana más amplia (ECIDADANIA_CORPUS_STALE_MAX_MIN), y un corpus de consultas obsoleto se sirve desde D1 marcado en lugar de colapsar a los puntos destacados en vivo.

Guardas de escritura en la carga: un rastreo incompleto (cualquier página fallida) o un universo de estado /processo incompleto escribe solo una fila de ejecución erro; incluso un rastreo completo se rechaza mediante un piso catastrófico (ECIDADANIA_CORPUS_MIN_PCT, por defecto 80% del último corpus bueno) para protegerse contra una página degradada — se puede anular con --force / INGEST_FORCE=1 para una reducción grande legítima. Ejecutar diariamente mediante la Action, o 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

Caché

Arquitectura de capas

CapaAlmacenamientoAlcanceRango TTLPropósito
L0En memoria MapPor aislado30-300sUltra rápido, elimina solicitudes redundantes dentro de un aislado de Worker
L1API de caché de Cloudflare (caches.default)Por colo (PoP)60-600sCompartido entre solicitudes en la misma ubicación perimetral
L2KV (opcional)GlobalVariableReservado para datos raros y de baja escritura

Categorías de caché

CategoríaTTL L0TTL L1Usado para
STATIC300s600sTipos de legislación, referencia estática
SEMI_STATIC120s300sLista de partidos, lista de UF, detalles de comités
DYNAMIC30s60sAgendas, votos recientes, listas de reuniones
ON_DEMAND30s120sBúsquedas específicas de proyectos/senadores/votos

Enfoque de caché para POST

MCP usa POST para todas las solicitudes tools/call. El almacenamiento en caché de respuestas POST no es compatible de forma nativa con la API de caché, que requiere solicitudes GET. La solución:

  1. Hash de parámetros — El nombre de la herramienta + los parámetros ordenados se procesan con SHA-256
  2. Clave GET sintética — Se construye una URL sintética https://senado-br-mcp.internal/__cache/{tool}/{hash}
  3. Coincidencia/put de la API de caché — La URL GET sintética se usa con caches.default.match() y caches.default.put(), lo que permite operaciones estándar de la API de caché en datos originados por POST

Este almacenamiento en caché ocurre a nivel de herramienta (dentro del callback de cada herramienta), no a nivel de transporte de MCP.

Procedencia

Cada herramienta adjunta un sobre de procedencia para que un resultado sea rastreable hasta su fuente oficial — la procedencia se trata como una parte de primera clase de la respuesta, no como un extra opcional (la audiencia son periodistas e investigadores de ciencia política, para quienes una cifra sin fuente es inutilizable). Desde v3.5.0, el sobre implementa el contrato de procedencia v1.0 de todo el portafolio (@sbissoli/mcp-provenance): el servidor construye y valida un modelo canónico completo por respuesta, y emite su proyección concise — un bloque fijo de 6 claves con null explícito para campos desconocidos. El bloque vive en structuredContent.provenance (analizable por clientes; tenga en cuenta que el esquema de salida por herramienta anunciado es permisivo, por lo que la validación del contrato ocurre en el lado del servidor en el momento de la compilación, en el paquete) y se refleja como un pie de página de fuente compacto en el contenido de texto para clientes que solo renderizan texto — el JSON de datos en sí no se duplica con el sobre, para mantener bajo el costo de tokens por respuesta.

La cobertura abarca las cuatro fuentes upstream, cada una con su propio source/citation/license (en 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 en senado.gov.br
  • Senado Federal — Portal e-Cidadania — www12.senado.leg.br/ecidadania

Campos del bloque concise (por respuesta — una herramienta, una fuente; claves en este orden fijo, null cuando la fuente no expone el valor):

CampoSignificado
sourceNombre oficial de la fuente (p. ej. Senado Federal — Dados Abertos (Legislativo))
source_urlURL canónica del endpoint/ítem consultado (p. ej. …/processo/{id})
data_vintageAñada/competencia de los datos (p. ej. 2024-03-15, 2019) — denominado reference_period antes de v3.5.0
retrieved_atISO-8601 de la extracción upstream — se transporta a través de la caché, por lo que refleja cuándo se obtuvieron realmente los datos, no la compilación ni el momento de acierto de caché
citationCadena de cita lista para usar (legible por humanos)
licenseTérminos de la fuente (Dados Abertos do Senado Federal)

El modelo canónico detrás del bloque también transporta dataset.id (identificador de ítem/serie, p. ej. codigoMateria=137808), api_version y field_sources por campo; estos se validan en cada compilación e informan attribution (abajo), pero no forman parte de la proyección concise.

Además del sobre provenance, structuredContent transporta una lista attribution de nivel superior — las URL de fuente distintas detrás de la respuesta. Esto refleja la nomenclatura propuesta en modelcontextprotocol#711 (donde attribution es una lista de referencias de fuente a nivel de respuesta), por lo que el servidor permanece compatible hacia adelante si ese RFC se concreta; el objeto más rico provenance sigue siendo una extensión propia de este servidor.

Espejo fuera de banda en _meta. El mismo provenance y attribution también se reflejan en el _meta del resultado bajo claves con espacio de nombres (com.sidneybissoli.senado/provenance y com.sidneybissoli.senado/attribution). La especificación MCP mantiene _meta para metadatos sobre un resultado que no deben guiar al modelo, que es donde apunta el trabajo aún incipiente de confianza/atribución de #711 (dividido en una pista de extensiones experimentales, aún no en el núcleo); reflejarlo allí brinda a los consumidores de auditoría y UI la procedencia sin leer el canal de datos orientado al modelo, sin costo de tokens de modelo, mientras que structuredContent lo mantiene visible para que el modelo pueda citar la fuente. El espejo sobrevive al minimizador de perfil de la aplicación ChatGPT (que solo elimina structuredContent.meta).

Granularidad a nivel de campo. La mayoría de las herramientas son de una sola fuente, por lo que un sobre es suficiente. Las pocas que fusionan segmentos en una respuesta llenan field_sources en el modelo canónico — una lista de { fields, source_url, data_vintage, retrieved_at, … } que atribuye campos de salida específicos a su origen real. Ejemplo: senado_obter_materia secao=detalhe fusiona /processo/{id} (la fuente de nivel superior) con el ementa de /processo y el relator de /processo/relatoria, cada uno con su propio retrieved_at. En el bloque concise emitido, el detalle por campo se resume mediante attribution, que siempre lista cada source_url subyacente distinto.

La fidelidad de retrieved_at la proporciona la capa de caché (cachedFetchWithMeta), que persiste la marca de tiempo de obtención junto con el valor, por lo que refleja la extracción upstream real incluso en un acierto de caché. Dos excepciones informan una marca de tiempo en vivo honesta en su lugar: las herramientas de lista de e-Cidadania (leídas desde D1) usan el lastScrapedAt del corpus — la edad real de los datos almacenados — mientras que las herramientas de detalle de e-Cidadania, extraídas en vivo, usan el tiempo de obtención y una URL de ítem canónica de nivel 3. La única ruta que recurre al valor predeterminado de compilación es el catálogo de referencia estática en código (senado_tabelas_referencia tipos-materia), que no tiene un instante de extracción upstream.

La cobertura es universal: las 69 herramientas llevan el sobre — las 67 herramientas senado_* mediante resultWithProvenance( (verificar con grep -c 'resultWithProvenance(' src/tools/*.ts) y las dos herramientas de Deep Research mediante provenanceExtras (mismo bloque, en structuredContent/_meta, ya que su canal de texto es el JSON del contrato). Las marcas ⊕ en el inventario a continuación denotan las herramientas piloto originales (votos, proyectos, procesos); el sobre ahora se extiende a cada herramienta, por lo que las marcas son históricas.

Conjunto de datos citable (participación e-Cidadania)

Más allá del servidor en vivo, este proyecto publica un conjunto de datos congelado, versionado y citable de la capa de participación de e-Cidadania (consultas públicas, ideas legislativas, eventos interactivos + sus comentarios, votos históricos por estado) — la capa que el paquete R congressbr nunca cubrió. Cada valor lleva un sobre de procedencia por campo ({ value, sourceEndpoint, sourceField, retrievedAt, license, schemaVersion }); la licencia de datos (Dados Abertos do Senado Federal) se mantiene separada de la licencia de código (MIT).

  • Cómo citar — CITATION.cff (conjunto de datos; cite el DOI de versión de la instantánea que usó, el DOI de concepto para el conjunto de datos entre versiones).
  • Qué hay en cada versión — CHANGELOG-dataset.md (acumulativo, solo anexar; vincula cada versión a su schemaVersion).
  • Diccionario de variables y procedencia de campos — docs/dataset-dictionary.md (generado desde src/dataset/schema.ts, la única fuente de verdad).
  • Licencia de datos — LICENSE-DATA.md.
  • Cómo hacer una versión (congelar → sumas de verificación → GitHub Release → DOI de Zenodo) — docs/release-runbook.md; maquinaria en src/dataset/, scripts/build-dataset/ y .github/workflows/release-dataset.yml.

Inventario — esquema v2 (schemaVersion 2.0.0)

Cada versión incluye un recurso NDJSON por entidad (un HarmonizedRecord por línea: identidad + un sobre de procedencia por campo), más un manifiesto datapackage.json y una copia del diccionario. Cinco recursos:

Recurso (*.ndjson)GranularidadVariables claveFuente(s)
consultas1 consulta pública (matéria)materia, ementa, votosSim/votosNao/totalVotos, percentual*, autoriaⁿ, relatorⁿ, status, url, firstSeenAtListado pesquisamateria + detalle (visualizacaomateria)ⁿ + /processo?tramitando=S para estado
ideias1 idea legislativa (~113,7 mil)titulo, apoios, status, dataPublicacaoⁿ, autorUfⁿ, descricaoⁿ, plConvertidoⁿ, url, firstSeenAtListado pesquisaideia + detalle (visualizacaoideia) mediante un relleno reanudableⁿ
eventos1 evento interactivo (audiência)titulo, dataᶜ, horaᶜ, comissao, comissaoNomeCompletoⁿ, localⁿ, descricaoⁿ, pautaⁿ, convidadosⁿ, videoUrlⁿ, comentariosᶜ, status, url, firstSeenAtListado principalaudiencia + detalle (visualizacaoaudiencia)ⁿ + fragmento AJAX de comentariosᶜ
eventos_comentariosⁿ1 comentario (nivel de comentario)eventoId, comentarioId, uf, texto, data, hora, momentoVideoUrl, convidadoAssociadoFragmento AJAX ajaxcolecaocomentarioaudiencia?audienciaId=
consultas_votos1 matéria (acervo histórico)materia, ementa, autoria, votosSim/votosNao/totalVotos, votosPorUf, status, url, referencePeriodCSV Arquimedes Proposições-com-votos.csv (re-ingerido semanalmente)

ⁿ = nuevo/reabierto en v2 · ᶜ = fuente corregida a la canónica en v2. Lo que cambió en v2 (2.0.0) — la ingesta pasó de solo listado a listado + detalle (+ comentarios AJAX para eventos):

  • Eventos corregidos y enriquecidos. data/hora ahora provienen de la página de detalle (canónica — el estudio A3 encontró que el listado divergía un 57% en hora), más seis nuevos campos de detalle (comissaoNomeCompleto, local, descricao, pauta, convidados, videoUrl). comentarios ahora es el recuento AJAX canónico (el recuento del listado era 0-espurio en el 82% de los eventos, capturando solo ~6,7% de la participación).
  • Nuevo recurso a nivel de comentario eventos_comentarios — una fila por comentario de audiência, la señal de participación que nadie más publica versionada.
  • Campos solo de detalle reabiertos para ideias (dataPublicacao, autorUf, descricao, plConvertido) y consultas (autoria, relator) — anteriormente siempre null por diseño.
  • Postura de privacidad según origen de datos. El contenido ciudadano (comentarios de audiência, autores de ideas) mantiene solo UF — nunca el nombre, descartado en el analizador; los agentes públicos (autoría/relatoría de consulta, invitados a eventos) mantienen el nombre (público por función). Ver docs/schema-v2-inventario.md para la justificación campo por campo (objetivo aprobado).

El NDJSON congelado no está comprometido (construido bajo demanda desde el corpus soberano D1); una versión etiquetada dataset-v* adjunta el tarball + SHA256SUMS + release.json y los archiva en Zenodo.

Inventario de Herramientas

Grupo H — Referencia/Metadatos (1 herramienta)

HerramientaDescripción
senado_tabelas_referenciaTablas de referencia vía enum tabela: tipos-materia, partidos, ufs, legislatura-actual, tipos-norma, tipos-uso-palabra

Grupo A — Senadores (5 herramientas)

HerramientaDescripción
senado_listar_senadoresLista senadores en ejercicio/por legislatura, con filtros nome (búsqueda parcial sin acento), uf y partido
senado_obter_senadorDetalle biográfico de un senador: bio, mandatos, partido, contacto
senado_votacoes_senador ⊕Cómo votó un senador en cada matéria (vía v3 /votacao)
senado_senador_historicoHistorial funcional vía enum tipo: licencias, comisiones, cargos, historial-académico, afiliaciones, profesiones
senado_senadores_afastadosSenadores actualmente apartados (fuera de ejercicio)

Grupo B — Proyectos/Materias (2 herramientas, backend v3)

HerramientaDescripción
senado_buscar_materias ⊕Busca materias por tipo, número, año, palabra clave, autor o tramitación (vía v3 /processo)
senado_obter_materia ⊕Datos de una matéria vía enum secao: detalle (situación/relator), tramitación (historial) o textos (documentos)

Grupo C — Procesos (5 herramientas)

HerramientaDescripción
senado_search_processos ⊕Busca procesos legislativos (complementaria a la búsqueda de materias)
senado_obter_processo ⊕Detalles completos de un proceso legislativo específico
senado_processo_detalheAspecto de un proceso vía enum secao: enmiendas, relatorías o plazos
senado_autores_atuaisParlamentarios autores de procesos en tramitación, ordenados por producción
senado_tabelas_processo12 tablas de referencia (siglas, asuntos, clases, tipos-*) vía enum tabela

Grupo D — Votaciones (3 herramientas)

HerramientaDescripción
senado_obter_votacao ⊕Detalles de una votación con votos nominales. Acepta codigoVotacao (codigoSessao de la sesión plenaria).
senado_votos_materia ⊕Votaciones de una matéria (vía v3 /votacao?codigoMateria), con votos nominales opcionales
senado_search_votacoes ⊕Búsqueda/listado flexible de votaciones del plenario por dias, período, proceso, matéria o senador

Grupo E — Comisiones (7 herramientas)

HerramientaDescripción
senado_listar_comissoesLista comisiones (colegiados) activas, filtráveis por tipo
senado_obter_comissaoDatos de una comisión vía enum secao: resumen (mesa/totales) o miembros (composición). Resuelve sigla a código internamente.
senado_reunioes_comissaoReuniones de una comisión en un período (maneja intervalos entre años)
senado_agenda_comissoesAgenda de reuniones de todas las comisiones en una fecha
senado_reuniao_comissaoDetalle completo de una reunión: partes, ítems, invitados, resultados, enlaces pauta/acta
senado_requerimentos_cpiRequerimientos protocolizados en una CPI en actividad, paginados (upstream suele venir vacío incluso para CPIs activas; retorno vacío trae aviso)
senado_distribuicao_materiasEstadísticas de carga por senador en una comisión: autoría o relatoría

Grupo F — Plenario (7 herramientas)

HerramientaDescripción
senado_agenda_plenarioAgenda del plenario — por día, mes o Congreso (escopo dia/mes/cn)
senado_resultado_plenarioResultados de sesión: ítems deliberados, opiniones, resultados (SF/CN/mes)
senado_orientacao_bancadaInstrucciones de voto de liderazgos partidarios por votación, con totales
senado_vetosVetos presidenciales por año o estado de tramitación
senado_resultado_vetoResultados nominales de votación de vetos (por veto, proyecto vetado o dispositivo)
senado_encontro_plenarioDetalle de sesión legislativa, ítems de agenda, resultados o resumen
senado_tabelas_plenarioTipos de sesión, tipos de asistencia, lista de legislaturas

Grupo G — e-Cidadania (9 herramientas)

HerramientaDescripción
senado_ecidadania_listar_consultasConsultas públicas (conjunto completo de las abiertas — materias en tramitación) con votación sí/no; filtro status (padrón aberta)
senado_ecidadania_obter_consultaDetalle de una consulta: votos, autor, relator, comentarios
senado_ecidadania_consultas_analiseAnaliza el conjunto completo de consultas abiertas vía modo (consenso/polarizada); status padrón aberta
senado_ecidadania_listar_ideiasIdeas legislativas de ciudadanos; ranking de las más apoyadas vía ordenarPor: apoios
senado_ecidadania_obter_ideiaDetalle de una idea: texto, apoyos, estado de conversión en proyecto
senado_ecidadania_listar_eventosEventos interactivos (audiencias, sabatinas, lives); ranking de los más comentados vía ordenarPor
senado_ecidadania_obter_eventoDetalle de un evento: pauta, invitados, enlace de video
senado_ecidadania_sugerir_tema_enqueteSugiere temas para encuesta mensual a partir de criterios configurables
senado_ecidadania_consultas_votosAcervo histórico de votos de las consultas con desglose por UF (CSV Arquimedes); ranking por total/sim/nao, filtro uf/materia

Grupo I — Discursos (3 herramientas)

HerramientaDescripción
senado_discursos_senadorPronunciamientos de un senador vía enum tipo: discursos (propios) o apartes (intervenciones)
senado_discursos_plenarioTodos los discursos en plenario en un intervalo de fechas
senado_discurso_textoTexto integral de un pronunciamiento/discurso específico

Grupo J — Bloques y Liderazgos (4 herramientas)

HerramientaDescripción
senado_listar_blocosBloques parlamentarios del Senado y sus partidos miembros
senado_obter_blocoDetalles de un bloque parlamentario específico
senado_liderancasLiderazgos del Senado/Cámara/Congreso (líderes, vice-líderes) con el bloque/partido liderado, filtráveis
senado_mesaMiembros de la Mesa Directiva vía enum casa: senado (Mesa del SF) o congreso (Mesa del CN)

Grupo K — Presupuesto (1 herramienta)

HerramientaDescripción
senado_orcamento_parlamentarEnmiendas parlamentarias al presupuesto vía enum tipo: enmiendas (lotes por autor) u oficios (indicación de destino — filtrável por ano de la enmienda, paginado, incluirEmendas opcional)

Grupo L — Ley Federal (2 herramientas)

HerramientaDescripción
senado_buscar_legislacaoBusca normas jurídicas federales por tipo, número, año o fecha (al menos uno obligatorio)
senado_obter_legislacaoDetalles de una norma jurídica federal específica

Grupo M — Votación en Comisiones (1 herramienta)

HerramientaDescripción
senado_votacao_comissaoVotaciones en comisiones vía enum por: comision, senador o materia; período opcional

Grupo N — Taquigrafía (2 herramientas)

HerramientaDescripción
senado_notas_taquigraficasTranscripciones oficiales de sesiones plenarias o reuniones de comisión — modo resumen con extractos, modo texto completo paginado en bloques, filtro de orador
senado_videos_taquigrafiaUnidades de video/audio por sesión o reunión, con orador y enlaces de medios

Grupo O — Senadores/Administrativo (2 herramientas)

HerramientaDescripción
senado_ceapsGastos de cuota parlamentaria CEAPS por año — agregados por senador, tipo de gasto, mes o proveedor, o detalle itemizado; estatisticas=true devuelve estadísticas de distribución del conjunto completo (min/max/mean/mediana/percentiles) + ranking superior/inferior, o un ranking de grupo por gasto total vía agruparPor (senador/tipo/mes/proveedor) con topN; filtros por senador/mes/tipo/proveedor
senado_senadores_adminDatos administrativos de los senadores vía enum tipo: auxilio-moradia, escritorios-apoyo o jubilados

Grupo P — Servidores / Gestión de Personas (4 herramientas)

HerramientaDescripción
senado_servidoresServidores públicos por situación (activo/efectivo/comisionado/inactivo), filtrable por nombre, unidad, cargo
senado_remuneracoes_servidoresNómina mensual — resumen por tipo de nómina o composición por persona con bruto calculado; estatisticas=true devuelve estadísticas de toda la nómina (mín/máx/media/mediana/percentiles) + ranking superior/inferior, con campo, consolidarPorServidor, agruparPor y topN
senado_horas_extrasPagos de horas extras por mes con totales; estatisticas=true devuelve estadísticas de distribución del conjunto completo (mín/máx/media/mediana/percentiles) + ranking superior/inferior, o un ranking por servidor según valor sumado vía agruparPor (nombre/competência), con topN
senado_pessoal_tabelasTablas de personal vía enum tabela: cuantitativos (personal, cargos-funciones, previsión-jubilación, senadores) y listas (becarios, pensionistas, asignaciones, cargos)

Grupo Q — Contrataciones (6 herramientas)

HerramientaDescripción
senado_contratosContratos filtrados en-Worker sobre toda la base (insensible a acentos): proveedor, CNPJ, año, número, objeto, mano de obra
senado_contratacao_detalheÍtems, pagos, garantías, modificaciones o activaciones de un contrato/ata/empeño
senado_licitacoesLicitaciones por número o texto del objeto
senado_terceirizadosColaboradores externalizados por nombre, empresa o unidad
senado_empresas_contratadasEmpresas que contratan con el Senado (requiere filtro nombre/CNPJ)
senado_contratacoes_listaActas de registro de precios, notas de compromiso, aprendices jóvenes

Grupo R — Fondo Rotatorio (1 herramienta)

HerramientaDescripción
senado_suprimento_fundosAnticipos de caja chica por año: beneficiarios, actos de concesión, compromisos, movimientos, transacciones con tarjeta; estatisticas=true (tipo transacciones/empeños/actos-concesión) devuelve estadísticas de distribución del conjunto completo (mín/máx/media/mediana/percentiles) + ranking superior/inferior, o un ranking por valor sumado vía agruparPor (p. ej. proveedor), con campo y topN contextuales

Grupo S — Presupuesto del Senado (1 herramienta)

HerramientaDescripción
senado_execucao_orcamentariaEjecución presupuestaria desde 2013 (asignación, comprometido/liquidado/pagado) e ingresos propios desde 2012 (previsión vs recaudado) — agregado por año, acción, grupo de gasto, fuente u origen de ingreso; estatisticas=true devuelve estadísticas de distribución del conjunto completo (mín/máx/media/mediana/percentiles) + ranking superior/inferior, o un ranking de grupo por campo sumado vía agruparPor, con campo (pagado/recaudado por defecto) y topN

Grupo T — Estructura Organizacional (1 herramienta)

Lee una instantánea empaquetada del árbol organizativo del Senado (rastreada desde el portal institucional hasta el nivel de servicio por npm run ingest:estrutura), ya que la API de datos abiertos solo publica unidades hasta Secretaría y nunca vincula una unidad hoja con su padre. Las unidades que el portal lista solo por nombre, sin página propia (los núcleos CONLEG/CONORF), se capturan como nodos sintéticos a partir de la lista indentada de la página. Los órganos de ámbito congresual donde el registro de servidores registra asignaciones (CMO, CPCMS, CMMC) provienen de un complemento curado (src/estrutura/complemento-cn.ts, fuente pública: congressonacional.leg.br) bajo una raíz separada Congresso Nacional (CN) — nunca bajo el árbol del Senado, por lo que subordinadasA: "DGER" los excluye mientras subordinadasA: "CN" los cuenta. Los servidores registrados bajo las pseudo-unidades situacionales "Servidores Afastados/em Trânsito - SF" se reportan por separado como afastadosOuEmTransito por senado_servidores.

HerramientaDescripción
senado_estrutura_organizacionalOrganigrama resuelto para un unidade (sigla como DGER o nombre): devuelve su caminho (ancestros) y cada unidad subordinada (subordinadas[] — secretarías, coordinaciones, servicios, núcleos — con nivel). Se combina con el filtro subordinadasA de senado_servidores, que cuenta/lista todos los servidores bajo una dirección completa (un servidor se ubica en un servicio hoja, por lo que filtrar lotacao por la sigla del padre devuelve 0).

Grupo U — Investigación Profunda (2 herramientas)

El contrato OpenAI Deep Research: las únicas dos herramientas sin el prefijo senado_, porque los nombres están fijados por el contrato. Registradas a través del mismo shim que las demás (anotaciones de solo lectura, outputSchema permisivo, telemetría por herramienta) y servidas solo en /mcp — el perfil curado de la app ChatGPT no las incluye. El índice (senadores en ejercicio + comités activos, ~300 documentos) se construye en el primer uso a partir de los mismos dos endpoints de lista que leen las herramientas senado_listar_*, y se mantiene durante 24 h.

HerramientaDescripción
searchClasifica la consulta (lenguaje natural o palabras clave, pt/en, insensible a acentos) contra senadores en ejercicio y comités activos; devuelve hasta 10 { id, title, url } — sen:<código> con la URL del perfil público, com:<código> con la página pública del comité. Procedencia de ambas listas en structuredContent/_meta.
fetchDevuelve el documento para un id de search como { id, title, text, url, metadata }: la biografía y mandatos del senador (misma lectura que senado_obter_senador) o el resumen y la mesa del comité (misma lectura que senado_obter_comissao), como Markdown, con la procedencia de esa lectura. Id desconocido → error.

Total: 69 herramientas

Prompts (4)

Plantillas de flujo de trabajo reutilizables en pt-BR (capacidad MCP prompts), definidas en src/prompts.ts:

PromptArgsQué guía
senado_gastos_senadorsenador, anoResuelve al senador y agrega/detalla gastos CEAPS.
senado_tramitacao_materiasigla, numero, anoObtiene situación actual + historial de tramitación de la materia.
senado_votos_senadorsenador, periodo?Lista los votos nominales del senador en el período.
senado_panorama_ecidadania—Consolida consultas (consenso/polarización), ideas y eventos populares.

Recursos (5)

Documentos/tablas de contexto estáticos (capacidad MCP resources), definidos en src/resources.ts:

URITipoContenido
senado://guiamarkdownVisión general y qué herramienta usar por objetivo.
senado://catalogomarkdownLas 69 herramientas agrupadas por dominio.
senado://glossariomarkdownSiglas y términos del Senado (PEC, CEAPS, CCJ, RCN…).
senado://tabelas/tipos-materiajsonTipos de proposición (sigla/nombre/descripción).
senado://tabelas/ufsjsonLas 27 unidades federativas.

Estructura del Proyecto

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)

Variables de Entorno

VariableRequeridaPredeterminadaDescripción
SENADO_BASE_URLNohttps://legis.senado.leg.br/dadosabertosURL base de la API legislativa
SENADO_ADM_BASE_URLNohttps://adm.senado.gov.br/adm-dadosabertosURL base de la API administrativa
ALLOWED_ORIGINNo*Origen permitido para CORS
API_KEYNo (secreta)—Cuando se define, requiere Authorization: Bearer <key> en todas las solicitudes excepto /health, /metrics y preflight CORS
CACHE_KVSí (vinculante)—Espacio de nombres KV para caché L2
ECIDADANIA_DBSí (vinculante)—Base de datos D1 para el pipeline de e-Cidadania (persistencia de listas + historial)
ECIDADANIA_CORPUS_STALE_MAX_MINNo14400Ventana de obsolescencia (minutos, ~10d) para los corpus completos fuera del Worker (todas las entidades e-Cidadania) — servidos marcados, nunca colapsados a destacados
ECIDADANIA_CORPUS_MIN_PCTNo80Piso catastrófico para los trabajos de corpus fuera del Worker: un rastreo/parseo completo por debajo de este % del último corpus bueno se rechaza
CLOUDFLARE_API_TOKENNo (secreta)—Secreto de GitHub Actions (alcance de edición D1) para los trabajos de ingesta/verificación de integridad del corpus; no usado por el Worker
CLOUDFLARE_ACCOUNT_IDNo (variable de Actions)—Variable de repositorio de GitHub Actions para que wrangler omita el auto-descubrimiento de cuenta /memberships (un token con alcance D1 no puede leerlo); requerida junto con CLOUDFLARE_API_TOKEN en el trabajo de ingesta
SENADO_ANALYTICSNo (vinculante)—Conjunto de datos de Analytics Engine para telemetría de llamadas por herramienta

Conexión de Clientes MCP

Este es un servidor remoto (HTTP Streamable, sin instalación, acceso abierto) — apunte cualquier cliente MCP a https://senado.sidneybissoli.com/mcp. Además de 69 herramientas, expone prompts (flujos de trabajo listos en pt-BR: senado_gastos_senador, senado_tramitacao_materia, senado_votos_senador, senado_panorama_ecidadania) y recursos (senado://guia, senado://catalogo, senado://glossario, senado://tabelas/tipos-materia, senado://tabelas/ufs).

Un clic (LobeHub)

Instale desde el marketplace de LobeHub — abra la página del servidor y haga clic en Instalar (rellena previamente el endpoint remoto, sin configuración necesaria).

Claude Desktop / Claude Code

Agregue a su configuración de MCP:

{
  "mcpServers": {
    "senado-br": {
      "url": "https://senado.sidneybissoli.com/mcp"
    }
  }
}

Para clientes basados en comandos (o cualquier cliente sin soporte remoto nativo), use el puente 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

Licencia

MIT

Créditos

Icono: "Amanhecer no Congresso Nacional" — fotografía del Congreso Nacional brasileño, usada bajo licencia Creative Commons. (Si usted es el autor, abra un issue para que podamos agregar la atribución completa / el enlace de la licencia).