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
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
- Un clic (LobeHub): abre la página del servidor y haz clic en Instalar.
- URL remota nativa (Claude Desktop/Code y otros clientes Streamable-HTTP): consulta Conectando clientes 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
createMcpHandlerdeagents/mcp - Protocolo: MCP sobre JSON-RPC —
/mcpmaneja el servidor público completo;/mcp/openai-app-v2expone 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-appsigue como alias heredado) - SDK:
@modelcontextprotocol/server2.x (instancias McpServer por solicitud; el@modelcontextprotocol/sdkv1 sigue solo como par deagents, 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 deretrieval(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
/healthy/statuspú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
- Node.js 22+ (
engines.node) - CLI de Wrangler v4+
- Cuenta de Cloudflare
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
| Ruta | Métodos | Descripción |
|---|---|---|
/ | GET | Pá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) |
/mcp | POST, GET, DELETE, OPTIONS | Endpoint MCP Streamable HTTP (gestionado por createMcpHandler) |
/health | GET | Verificación de salud — devuelve ok (siempre público) |
/status | GET | JSON: status, version y metadatos del último despliegue (deploy.id/tag/timestamp) — disponibilidad + compilación actual, sin necesidad de handshake MCP (siempre público) |
/metrics | GET | Contadores 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 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 vía llamada 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 (+ 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}/requerimentos | senado_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/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 plano, obtenido directamente) |
/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)
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 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 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 upstream | Usado 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/senadores | senado_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/licitacoes | senado_licitacoes |
/api/v1/contratacoes/terceirizados | senado_terceirizados |
/api/v1/contratacoes/empresas | senado_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.json | senado_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ónMIN(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 acervoconsultas_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 comook-metricapara 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 paracomentarios, 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_historysolo cuando elcontent_hashde 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) paraautoria/relator; estos son inmutables, por lo que solo se obtienen las filas aún no enriquecidas.eventos— audiências/eventos del listado HTMLprincipalaudiencia?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/horacanónicos +comissaoNomeCompleto/local/descricao/pauta/convidados/videoUrl) y su fragmento de comentarios AJAX (recuento canónico + una filaecidadania_comentariospor comentario, comparado con los hashes almacenados y emitido comoout-eventos-comentarios-*.sql).ideias— ideias legislativas (~113.7k) desdepesquisaideia?situacao=N&p=M, rastreadas por cubo desituacao(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íaingest: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 enecidadania_detalhe_cursory 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:
- 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. - Estado desde
/processo, no desde HTML. Una consulta se ejecuta desde la presentación hasta el final de la tramitación, por lo questatuses una función del asunto: abierta ⟺ elcodigoMateriaestá en el conjunto/processotramitando=S, derivado de JSON robusto (nunca extraído). Cada consulta entra comoaberta(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 aencerrada. Los conjuntosencerrada/todascrecen con el tiempo; las consultas cerradas antes de la primera ingesta no se capturan (fuera de alcance). Las herramientas de listado/análisis usanstatus: abertapor defecto. - Dos cadencias reconciliadas (un contrato de escritura compartido). El trabajo reutiliza
contentHash+ el constructorConsultaResumo+classifyRundesrc/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 comook-metrica, omitiendo la línea baseclassifyRundel corpus). La frescura del corpus (possivelDesatualizacao) se calcula desde la última ejecución destatus='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
| Capa | Almacenamiento | Alcance | Rango TTL | Propósito |
|---|---|---|---|---|
| L0 | En memoria Map | Por aislado | 30-300s | Ultra rápido, elimina solicitudes redundantes dentro de un aislado de Worker |
| L1 | API de caché de Cloudflare (caches.default) | Por colo (PoP) | 60-600s | Compartido entre solicitudes en la misma ubicación perimetral |
| L2 | KV (opcional) | Global | Variable | Reservado para datos raros y de baja escritura |
Categorías de caché
| Categoría | TTL L0 | TTL L1 | Usado para |
|---|---|---|---|
| STATIC | 300s | 600s | Tipos de legislación, referencia estática |
| SEMI_STATIC | 120s | 300s | Lista de partidos, lista de UF, detalles de comités |
| DYNAMIC | 30s | 60s | Agendas, votos recientes, listas de reuniones |
| ON_DEMAND | 30s | 120s | Bú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:
- Hash de parámetros — El nombre de la herramienta + los parámetros ordenados se procesan con SHA-256
- Clave GET sintética — Se construye una URL sintética
https://senado-br-mcp.internal/__cache/{tool}/{hash} - Coincidencia/put de la API de caché — La URL GET sintética se usa con
caches.default.match()ycaches.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):
| Campo | Significado |
|---|---|
source | Nombre oficial de la fuente (p. ej. Senado Federal — Dados Abertos (Legislativo)) |
source_url | URL canónica del endpoint/ítem consultado (p. ej. …/processo/{id}) |
data_vintage | Añada/competencia de los datos (p. ej. 2024-03-15, 2019) — denominado reference_period antes de v3.5.0 |
retrieved_at | ISO-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é |
citation | Cadena de cita lista para usar (legible por humanos) |
license | Té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 suschemaVersion). - Diccionario de variables y procedencia de campos —
docs/dataset-dictionary.md(generado desdesrc/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 ensrc/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) | Granularidad | Variables clave | Fuente(s) |
|---|---|---|---|
consultas | 1 consulta pública (matéria) | materia, ementa, votosSim/votosNao/totalVotos, percentual*, autoriaⁿ, relatorⁿ, status, url, firstSeenAt | Listado pesquisamateria + detalle (visualizacaomateria)ⁿ + /processo?tramitando=S para estado |
ideias | 1 idea legislativa (~113,7 mil) | titulo, apoios, status, dataPublicacaoⁿ, autorUfⁿ, descricaoⁿ, plConvertidoⁿ, url, firstSeenAt | Listado pesquisaideia + detalle (visualizacaoideia) mediante un relleno reanudableⁿ |
eventos | 1 evento interactivo (audiência) | titulo, dataᶜ, horaᶜ, comissao, comissaoNomeCompletoⁿ, localⁿ, descricaoⁿ, pautaⁿ, convidadosⁿ, videoUrlⁿ, comentariosᶜ, status, url, firstSeenAt | Listado principalaudiencia + detalle (visualizacaoaudiencia)ⁿ + fragmento AJAX de comentariosᶜ |
eventos_comentariosⁿ | 1 comentario (nivel de comentario) | 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) |
ⁿ = 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/horaahora provienen de la página de detalle (canónica — el estudio A3 encontró que el listado divergía un 57% enhora), más seis nuevos campos de detalle (comissaoNomeCompleto,local,descricao,pauta,convidados,videoUrl).comentariosahora es el recuento AJAX canónico (el recuento del listado era0-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) yconsultas(autoria,relator) — anteriormente siemprenullpor 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.mdpara 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)
| Herramienta | Descripción |
|---|---|
senado_tabelas_referencia | Tablas de referencia vía enum tabela: tipos-materia, partidos, ufs, legislatura-actual, tipos-norma, tipos-uso-palabra |
Grupo A — Senadores (5 herramientas)
| Herramienta | Descripción |
|---|---|
senado_listar_senadores | Lista senadores en ejercicio/por legislatura, con filtros nome (búsqueda parcial sin acento), uf y partido |
senado_obter_senador | Detalle 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_historico | Historial funcional vía enum tipo: licencias, comisiones, cargos, historial-académico, afiliaciones, profesiones |
senado_senadores_afastados | Senadores actualmente apartados (fuera de ejercicio) |
Grupo B — Proyectos/Materias (2 herramientas, backend v3)
| Herramienta | Descripció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)
| Herramienta | Descripció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_detalhe | Aspecto de un proceso vía enum secao: enmiendas, relatorías o plazos |
senado_autores_atuais | Parlamentarios autores de procesos en tramitación, ordenados por producción |
senado_tabelas_processo | 12 tablas de referencia (siglas, asuntos, clases, tipos-*) vía enum tabela |
Grupo D — Votaciones (3 herramientas)
| Herramienta | Descripció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)
| Herramienta | Descripción |
|---|---|
senado_listar_comissoes | Lista comisiones (colegiados) activas, filtráveis por tipo |
senado_obter_comissao | Datos de una comisión vía enum secao: resumen (mesa/totales) o miembros (composición). Resuelve sigla a código internamente. |
senado_reunioes_comissao | Reuniones de una comisión en un período (maneja intervalos entre años) |
senado_agenda_comissoes | Agenda de reuniones de todas las comisiones en una fecha |
senado_reuniao_comissao | Detalle completo de una reunión: partes, ítems, invitados, resultados, enlaces pauta/acta |
senado_requerimentos_cpi | Requerimientos protocolizados en una CPI en actividad, paginados (upstream suele venir vacío incluso para CPIs activas; retorno vacío trae aviso) |
senado_distribuicao_materias | Estadísticas de carga por senador en una comisión: autoría o relatoría |
Grupo F — Plenario (7 herramientas)
| Herramienta | Descripción |
|---|---|
senado_agenda_plenario | Agenda del plenario — por día, mes o Congreso (escopo dia/mes/cn) |
senado_resultado_plenario | Resultados de sesión: ítems deliberados, opiniones, resultados (SF/CN/mes) |
senado_orientacao_bancada | Instrucciones de voto de liderazgos partidarios por votación, con totales |
senado_vetos | Vetos presidenciales por año o estado de tramitación |
senado_resultado_veto | Resultados nominales de votación de vetos (por veto, proyecto vetado o dispositivo) |
senado_encontro_plenario | Detalle de sesión legislativa, ítems de agenda, resultados o resumen |
senado_tabelas_plenario | Tipos de sesión, tipos de asistencia, lista de legislaturas |
Grupo G — e-Cidadania (9 herramientas)
| Herramienta | Descripción |
|---|---|
senado_ecidadania_listar_consultas | Consultas públicas (conjunto completo de las abiertas — materias en tramitación) con votación sí/no; filtro status (padrón aberta) |
senado_ecidadania_obter_consulta | Detalle de una consulta: votos, autor, relator, comentarios |
senado_ecidadania_consultas_analise | Analiza el conjunto completo de consultas abiertas vía modo (consenso/polarizada); status padrón aberta |
senado_ecidadania_listar_ideias | Ideas legislativas de ciudadanos; ranking de las más apoyadas vía ordenarPor: apoios |
senado_ecidadania_obter_ideia | Detalle de una idea: texto, apoyos, estado de conversión en proyecto |
senado_ecidadania_listar_eventos | Eventos interactivos (audiencias, sabatinas, lives); ranking de los más comentados vía ordenarPor |
senado_ecidadania_obter_evento | Detalle de un evento: pauta, invitados, enlace de video |
senado_ecidadania_sugerir_tema_enquete | Sugiere temas para encuesta mensual a partir de criterios configurables |
senado_ecidadania_consultas_votos | Acervo 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)
| Herramienta | Descripción |
|---|---|
senado_discursos_senador | Pronunciamientos de un senador vía enum tipo: discursos (propios) o apartes (intervenciones) |
senado_discursos_plenario | Todos los discursos en plenario en un intervalo de fechas |
senado_discurso_texto | Texto integral de un pronunciamiento/discurso específico |
Grupo J — Bloques y Liderazgos (4 herramientas)
| Herramienta | Descripción |
|---|---|
senado_listar_blocos | Bloques parlamentarios del Senado y sus partidos miembros |
senado_obter_bloco | Detalles de un bloque parlamentario específico |
senado_liderancas | Liderazgos del Senado/Cámara/Congreso (líderes, vice-líderes) con el bloque/partido liderado, filtráveis |
senado_mesa | Miembros de la Mesa Directiva vía enum casa: senado (Mesa del SF) o congreso (Mesa del CN) |
Grupo K — Presupuesto (1 herramienta)
| Herramienta | Descripción |
|---|---|
senado_orcamento_parlamentar | Enmiendas 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)
| Herramienta | Descripción |
|---|---|
senado_buscar_legislacao | Busca normas jurídicas federales por tipo, número, año o fecha (al menos uno obligatorio) |
senado_obter_legislacao | Detalles de una norma jurídica federal específica |
Grupo M — Votación en Comisiones (1 herramienta)
| Herramienta | Descripción |
|---|---|
senado_votacao_comissao | Votaciones en comisiones vía enum por: comision, senador o materia; período opcional |
Grupo N — Taquigrafía (2 herramientas)
| Herramienta | Descripción |
|---|---|
senado_notas_taquigraficas | Transcripciones oficiales de sesiones plenarias o reuniones de comisión — modo resumen con extractos, modo texto completo paginado en bloques, filtro de orador |
senado_videos_taquigrafia | Unidades de video/audio por sesión o reunión, con orador y enlaces de medios |
Grupo O — Senadores/Administrativo (2 herramientas)
| Herramienta | Descripción |
|---|---|
senado_ceaps | Gastos 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_admin | Datos administrativos de los senadores vía enum tipo: auxilio-moradia, escritorios-apoyo o jubilados |
Grupo P — Servidores / Gestión de Personas (4 herramientas)
| Herramienta | Descripción |
|---|---|
senado_servidores | Servidores públicos por situación (activo/efectivo/comisionado/inactivo), filtrable por nombre, unidad, cargo |
senado_remuneracoes_servidores | Nó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_extras | Pagos 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_tabelas | Tablas 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)
| Herramienta | Descripción |
|---|---|
senado_contratos | Contratos 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_licitacoes | Licitaciones por número o texto del objeto |
senado_terceirizados | Colaboradores externalizados por nombre, empresa o unidad |
senado_empresas_contratadas | Empresas que contratan con el Senado (requiere filtro nombre/CNPJ) |
senado_contratacoes_lista | Actas de registro de precios, notas de compromiso, aprendices jóvenes |
Grupo R — Fondo Rotatorio (1 herramienta)
| Herramienta | Descripción |
|---|---|
senado_suprimento_fundos | Anticipos 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)
| Herramienta | Descripción |
|---|---|
senado_execucao_orcamentaria | Ejecució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.
| Herramienta | Descripción |
|---|---|
senado_estrutura_organizacional | Organigrama 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.
| Herramienta | Descripción |
|---|---|
search | Clasifica 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. |
fetch | Devuelve 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:
| Prompt | Args | Qué guía |
|---|---|---|
senado_gastos_senador | senador, ano | Resuelve al senador y agrega/detalla gastos CEAPS. |
senado_tramitacao_materia | sigla, numero, ano | Obtiene situación actual + historial de tramitación de la materia. |
senado_votos_senador | senador, 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:
| URI | Tipo | Contenido |
|---|---|---|
senado://guia | markdown | Visión general y qué herramienta usar por objetivo. |
senado://catalogo | markdown | Las 69 herramientas agrupadas por dominio. |
senado://glossario | markdown | Siglas y términos del Senado (PEC, CEAPS, CCJ, RCN…). |
senado://tabelas/tipos-materia | json | Tipos de proposición (sigla/nombre/descripción). |
senado://tabelas/ufs | json | Las 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
| Variable | Requerida | Predeterminada | Descripción |
|---|---|---|---|
SENADO_BASE_URL | No | https://legis.senado.leg.br/dadosabertos | URL base de la API legislativa |
SENADO_ADM_BASE_URL | No | https://adm.senado.gov.br/adm-dadosabertos | URL base de la API administrativa |
ALLOWED_ORIGIN | No | * | Origen permitido para CORS |
API_KEY | No (secreta) | — | Cuando se define, requiere Authorization: Bearer <key> en todas las solicitudes excepto /health, /metrics y preflight CORS |
CACHE_KV | Sí (vinculante) | — | Espacio de nombres KV para caché L2 |
ECIDADANIA_DB | Sí (vinculante) | — | Base de datos D1 para el pipeline de e-Cidadania (persistencia de listas + historial) |
ECIDADANIA_CORPUS_STALE_MAX_MIN | No | 14400 | Ventana 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_PCT | No | 80 | Piso 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_TOKEN | No (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_ID | No (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_ANALYTICS | No (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).