内容
# 参议院巴西 MCP 服务器



[](https://registry.modelcontextprotocol.io)
[](https://lobehub.com/mcp/sidneybissoli-senado-br-mcp-cloudflare)
[](https://smithery.ai/servers/sidneybissoli/senado-br-mcp-cloudflare)
[](https://glama.ai/mcp/servers/SidneyBissoli/senado-br-mcp-cloudflare)
[](https://github.com/SidneyBissoli/senado-br-mcp-cloudflare)
[](https://github.com/sponsors/SidneyBissoli)
[](LICENSE)
[](https://senado.sidneybissoli.com/status)
🇧🇷 [阅读中文版本](README.pt-BR.md)
一个 **公开、托管** 的 MCP 服务器,为 AI 助手提供巴西参议院公开数据的实时结构化访问 - **无需安装,无需账户,无需 API 密钥**。只需将您的 MCP 客户端指向托管端点,即可开始询问有关参议员、法案、投票、支出等信息。它在 Cloudflare Workers 上通过 Streamable HTTP 运行。
它公开了 **66 种工具**、**4 种提示**和 **5 种资源**,涵盖两个领域:
- **立法** - 参议员;法案及其进展;投票;委员会;全体会议、结果和总统否决;党团投票导向;演讲和速记记录;集团和领导层;联邦立法;以及通过 e-Cidadania 门户的公民参与。
- **行政** - CEAPS 议会配额支出;住房津贴;公务员和工资单;加班费;实习生;采购合同和招标;外包人员;小额现金基金;预算执行。
数据来自三个官方来源 - 立法开放数据 API、行政开放数据 API 和 e-Cidadania 门户。所有工具响应均为葡萄牙语(pt-BR)。有关发布历史,请参见 [CHANGELOG.md](CHANGELOG.md)。
## 实际操作
将客户端指向端点并用普通语言提问 - 英语或葡萄牙语:
- *"São Paulo 的参议员在最近的全体投票中如何投票?"* → `senado_search_votacoes`
- *"显示 PEC 45/2019(宪法修正案提案)的立法进展。"* → `senado_buscar_materias` + `senado_obter_materia`
- *"2024 年 CEAPS 议会津贴支出多少,按支出类型细分?"* → `senado_ceaps`
答案来自参议院官方开放数据 API - 准确的数字和出处,而不是从训练数据中猜测的数字。
## 使用(托管 - 无需设置)
这是一个 **远程、托管、开放访问** 的服务器。要使用它,只需将任何 MCP 客户端指向 Streamable HTTP 端点 - **无需安装,无需账户,无需 API 密钥,无需配置**:
```
https://senado.sidneybissoli.com/mcp
```
### OpenAI / ChatGPT 应用界面
对于 OpenAI Apps SDK 提交和审查,Worker 还公开了一个精选的 MCP 界面:
```
https://senado.sidneybissoli.com/mcp/openai-app-v2
```
此端点故意在 `/mcp` 处保留完整的公共 MCP 服务器,但在 `/mcp/openai-app` 处提供了一个有限的 25 种工具配置文件,供 ChatGPT 应用使用。`/mcp/openai-app` 仍然作为旧别名存在,但新的 ChatGPT 应用配置应使用 `/mcp/openai-app-v2`,以便客户端获取当前工具模式。工具仍然调用相同的处理程序并返回相同的出处信封;仅公开的界面更窄。任何 ChatGPT 应用列表都应将此作为独立的开放数据研究应用,而不是官方参议院、OpenAI 或 ChatGPT 连接器。
对于 ChatGPT 应用,这 25 种工具还提供了一个共享的 MCP 应用 UI 模板,位于 `ui://senado-br-mcp/openai-app-dashboard-v2.html`。自包含的小部件渲染返回的 `structuredContent`,作为一个紧凑的仪表板,包含指标、主要记录和来源/出处,而不添加另一个模型可见的数据工具。
应用审查的公共合法 URL:
- 隐私政策:`https://senado.sidneybissoli.com/privacy`
- 使用条款:`https://senado.sidneybissoli.com/terms`
### 安装(任意客户端)
对于以命令方式启动 MCP 服务器的客户端 - 以及一键设置 - 请使用 [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) 桥。**无需构建,无需配置,无需密钥:**
```bash
npx -y mcp-remote https://senado.sidneybissoli.com/mcp
```
- **一键式(LobeHub):** 打开 [服务器页面](https://lobehub.com/mcp/sidneybissoli-senado-br-mcp-cloudflare) 并点击 **安装**。
- **原生远程 URL**(Claude Desktop/Code 和其他 Streamable-HTTP 客户端):请参阅 [连接 MCP 客户端](#connecting-mcp-clients)。
以下所有内容 *架构*(先决条件、设置、部署)仅适用于**可选的自行托管实例** - 使用此公共服务器**不需要**。
## 本地运行(npx · stdio)
不愿通过第三方主机路由查询(例如新闻编辑室政策)?**相同的服务器**也作为一个**本地_stdio 进程**运行,直接与官方政府 API 通信 - 相同的 66 种工具,相同的出处信封,没有 Cloudflare 参与。这是通过 npm/stdio 渠道发布的,作为 [`senado-br-mcp`](https://www.npmjs.com/package/senado-br-mcp)。
将基于命令的客户端(Claude Desktop/Code 等)指向该软件包 - npm 获取并运行它,无需克隆或构建:
```json
{
"mcpServers": {
"senado-br": {
"command": "npx",
"args": ["-y", "senado-br-mcp"]
}
}
}
```
要直接运行或修改它,请使用源码克隆:
```bash
git clone https://github.com/SidneyBissoli/senado-br-mcp-cloudflare
cd senado-br-mcp-cloudflare
npm install
npm run build
node dist/cli.js # 通过 stdio 提供 MCP(Ctrl+C 停止)
```
**与托管服务器的对等性:** 立法和行政工具是 **相同的**(相同的上游 API,相同的节流/缓存/出处)- 在本地,L1 Cloudflare 缓存是 no-op,但 L0 内存缓存仍然有效,因此结果相同。**唯一**的区别是 e-Cidadania 列表/语料库工具:没有 D1,它们会回退到 ~5 个 REST 高亮的实时抓取,并带有 `meta.fonte` / `possivelDesatualizacao` 标志;详细工具(`obter_*`)是相同的。日志记录到 **stderr** - stdout 仅携带 JSON-RPC 协议流。
## 代理技能(可选)
此存储库在 [.claude/skills/senado-br/](.claude/skills/senado-br/SKILL.md) 处捆绑了一个 Claude [代理技能](https://platform.claude.com/docs/en/docs/agents-and-tools/agent-skills/overview),它教 Claude **何时** 调用此服务器以及 **如何** 良好地使用其 66 种工具 - 一个主题工具地图、常见的问答→工具演练、 出处合同和陷阱(日期、`codigoMateria` 桥、e-Cidadania 的开放集列表、分页)。它指向服务器自己的 `senado://catalogo` / `senado://guia` 资源,而不是复制它们。
Claude Code 在此存储库中自动发现它。要在其他地方使用它,请将 `.claude/skills/senado-br/` 复制到您的 `~/.claude/skills/` 中,或压缩文件夹并在 claude.ai 上上传(设置 → 功能)。技能假设 `senado-br` MCP 服务器已连接(托管或通过 npx)。
## 架构
- **运行时:** Cloudflare Workers(ESM)
- **传输:** Streamable HTTP(MCP 规范 2025-03-26)通过 `createMcpHandler` 来自 `agents/mcp`
- **协议:** MCP 覆盖 JSON-RPC - `/mcp` 处理完整的公共服务器;`/mcp/openai-app-v2` 公开精选的 25 种工具配置文件以及 OpenAI 应用审查/提交的共享 MCP 应用小部件(`/mcp/openai-app` 仍然作为旧别名存在)
- **SDK:** `@modelcontextprotocol/sdk` 1.26.0+(每个请求的 McpServer 实例)
- **验证:** 所有工具输入的 Zod 模式
- **缓存:** 2 层(L0 内存 + L1 缓存 API)并使用 SHA-256 密钥
- **e-Cidadania 存储:** D1 数据库每 2 小时刷新一次 - 列表工具从 D1 读取并带有实时抓取的回退和过时标志;详细工具保持实时并带有直写(请参阅 [e-Cidadania](#e-cidadania-d1-backed-cron-refreshed))
- **速率限制:** 令牌桶 - 全局(8 req/s)+ 每个客户端(2 req/s)
- **上游节流:** 最多 6 个并发请求,10 秒超时,带有指数退火重试
- **身份验证:** 可选的 Bearer 令牌(设置 `API_KEY` 密钥;当未设置时,开放访问)。恒定时间比较。
- **可观察性:** 结构化 JSON 日志记录 + `/metrics` 处的内存计数器;每个工具的调用遥测(选择、错误率、缓存与实时)在 Cloudflare Analytics Engine 中,无 PII
- **活动:** 在 Cloudflare 自己的全球网络上运行,背后有自定义域名 - 没有第三方主机可以关闭。公共 `/health` 和 `/status`(版本 + 部署 ID/时间戳)使正常运行时间和当前构建版本可验证;**状态**徽章以上 ping 实时端点
## 自托管(可选)
> **不需要使用服务器** - 它已经托管在 `https://senado.sidneybissoli.com/mcp`
> (开放访问)。如果您想运行您自己的**私有实例**,请遵循此部分。
### 先决条件
- Node.js 18+
- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) v4+
- Cloudflare 账户
### 设置
#### 1. 安装依赖项
```bash
npm install
```
#### 2. 创建 KV 命名空间
```bash
# 创建 KV 命名空间
wrangler kv namespace create CACHE_KV
# 注意输出的 ID,例如:
# { binding = "CACHE_KV", id = "abc123..." }
```
#### 3. 配置 wrangler.toml
替换占位符 KV 命名空间 ID:
```toml
[[kv_namespaces]]
binding = "CACHE_KV"
id = "您的 KV 命名空间 ID_HERE"
```
可选地设置 `ALLOWED_ORIGIN` 以限制 CORS:
```toml
[vars]
ALLOWED_ORIGIN = "https://your-app.example.com"
```
e-Cidadania 流水线需要一个 **D1 数据库** 和一个 **Cron Trigger**(两者都已在 `wrangler.toml` 中声明 - 替换数据库 ID):
```toml
[[d1_databases]]
binding = "ECIDADANIA_DB"
database_name = "senado-ecidadania"
database_id = "您的 D1 数据库 ID_HERE"
[triggers]
crons = ["0 */2 * * *"]
```
创建数据库(粘贴返回的 ID 上方)并应用模式:
```bash
npx wrangler d1 create senado-ecidadania
npx wrangler d1 migrations apply senado-ecidadania --remote
```
列表工具在 D1 为空时回退到实时抓取,因此服务器在第一次 Cron 运行之前有效。
#### 4. (可选)启用身份验证
```bash
wrangler secret put API_KEY
# 客户端必须发送:Authorization: Bearer <key>
# 当 API_KEY 未设置时,服务器是开放访问的。
```
#### 5. 本地开发
```bash
npm run dev
# 开发服务器在端口 8787 上运行(仅本地)。
# 公共 MCP 端点是 https://senado.sidneybissoli.com/mcp
```
#### 6. 测试和类型检查
```bash
npm test # 运行所有测试一次
npm run test:watch # 监视模式
npm run typecheck ```bash
npm run typecheck # tsc --noEmit
```
#### 7. 部署
```bash
npm run deploy
# 在 https://senado.sidneybissoli.com (自定义域名)和
# https://senado-br-mcp.sidneybissoli.workers.dev (workers.dev 备用地址) 上提供服务
```
## 端点
| 路径 | 方法 | 描述 |
|------|---------|-------------|
| `/mcp` | POST, GET, DELETE, OPTIONS | MCP Streamable HTTP 端点(由 `createMcpHandler` 管理) |
| `/health` | GET | 健康检查 - 返回 `ok`(始终公开) |
| `/status` | GET | JSON: `status`, `version`, 和部署后的元数据(`deploy.id`/`tag`/`timestamp`)- 活动 + 当前构建,无需 MCP 握手(始终公开) |
| `/metrics` | GET | JSON 计数器:请求,工具调用,缓存命中/未命中,上游调用/重试/错误,身份验证失败(始终公开) |
## MCP 请求示例
所有请求都发送到 `POST /mcp`,采用 JSON-RPC 2.0 格式。
### 列出可用工具
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
```
### 调用工具 - 列出圣保罗州参议员
```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "senado_listar_senadores",
"arguments": {
"uf": "SP",
"emExercicio": true
}
}
}
```
### 调用工具 - 按关键词搜索法案
```json
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "senado_buscar_materias",
"arguments": {
"palavraChave": "人工智能",
"tramitando": true
}
}
}
```
### 调用工具 - 获取最近的全体会议投票
```json
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "senado_search_votacoes",
"arguments": {
"dias": 7
}
}
}
```
### 调用工具 - 最受公民欢迎的想法
```json
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "senado_ecidadania_listar_ideias",
"arguments": {
"ordenarPor": "apoios",
"ordem": "desc",
"status": "aberta"
}
}
}
```
## 上游 API 端点
服务器从参议院 API 消耗两类上游端点:
### 旧版端点(`.json`后缀,PascalCase响应)
用于 A 组、E、F、H、I、J、K、L、M、N 组。`.json`后缀由 `upstream.ts` 自动追加。上游中没有一个被标记为已弃用。
| 上游路径 | 被以下工具使用 |
|---------------|---------|
| `/senador/lista/atual` | `senado_listar_senadores` |
| `/senador/lista/legislatura/{legislatura}` | `senado_listar_senadores` (参数 `legislatura`) |
| `/senador/{codigo}` | `senado_obter_senador` |
| `/senador/{codigo}/licencas`, `/comissoes`, `/cargos`, `/historicoAcademico`, `/filiacoes`, `/profissao` | `senado_senador_historico` (`tipo` 枚举) |
| `/senador/afastados` | `senado_senadores_afastados` |
| `/senador/{codigo}/apartes` | `senado_discursos_senador` (`tipo=apartes`) |
| `/comissao/lista/colegiados` | `senado_listar_comissoes` (+ sigla-to-code 解析) |
| `/comissao/{codigo}` | `senado_obter_comissao` (`secao=resumo`; 数字代码,而非 sigla) |
| `/composicao/comissao/{codigo}` | `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` (空主体 = 无请求) |
| `/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_taquigraficas` |
| `/senador/{codigo}/discursos` | `senado_discursos_senador` |
| `/plenario/lista/discursos/{dataInicio}/{dataFim}` | `senado_discursos_plenario` |
| `/discurso/texto-integral/{codigo}` | `senado_discurso_texto` (纯文本,直接获取) |
| `/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` |
### v3 接口(扁平JSON数组/对象,驼峰命名)
由Group B、C、D使用。日期必须为**ISO格式**(`YYYY-MM-DD`)—— 工具接受`YYYYMMDD`并进行转换。`codigoMateria`查询参数连接了遗留的matéria代码到v3流程。
| 上游路径 | 使用者 |
|---------------|---------|
| `/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`(rapporteur) |
| `/processo/prazo` | `senado_processo_detalhe`(`secao=prazos`) |
| `/processo/{siglas,assuntos,classes,destinos,entes,tipos-*}` | `senado_tabelas_processo`(12个参考表) |
### 管理API(adm.senado.gov.br/adm-dadosabertos,扁平蛇形JSON)
由Group O、P、Q、R通过`admFetch`使用(无`.json`后缀;HTTP 404视为空集合)。基准URL可通过`SENADO_ADM_BASE_URL`配置。
| 上游路径 | 使用者 |
|---------------|---------|
| `/api/v1/senadores/despesas_ceaps/{ano}` | `senado_ceaps`(~10 MB/年,缓存 + 聚合在Worker内) |
| `/api/v1/senadores/{auxilio-moradia,escritorios,aposentados}` | `senado_senadores_admin`(`tipo`枚举) |
| `/api/v1/servidores/servidores/{ativos,efetivos,comissionados,inativos}` | `senado_servidores` |
| `/api/v1/servidores/remuneracoes/{ano}/{mes}` | `senado_remuneracoes_servidores`(~5.5 MB/月) |
| `/api/v1/servidores/horas-extras/{ano}/{mes}` | `senado_horas_extras` |
| `/api/v1/servidores/quantitativos/*`,`/previsao-aposentadoria`,`/api/v1/senadores/quantitativos/senadores` | `senado_pessoal_tabelas`(数量) |
| `/api/v1/servidores/{estagiarios,pensionistas,lotacoes,cargos}` | `senado_pessoal_tabelas`(名单) |
| `/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,需要过滤) |
| `/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`(每日JSON馈送,巴西十进制字符串规范化) |
### e-Cidadania(D1支持,Cron刷新)
e-Cidadania **列表** 数据保存在 **D1数据库**(`ecidadania_current/_history/_scrape_runs`,按`entidade`区分)并从中读取,而不是每次调用都进行爬取。**三个节奏** 将数据写入其中:
- **每日离线GitHub Action** 拥有三个实时实体(`consultas`、`eventos`、`ideias`;见下文)的**完整语料库** —— 真实数据的源头。每日(而非每周),因为首次发现的系列`MIN(scraped_at)`是唯一可衡量的进入节奏信号,而每个跳过的日子都会永久缩短它(ROADMAP第2阶段,决定D3);
- **每周完整性检查Action**(`.github/workflows/verify-consultas-votos.yml`)用于冻结的`consultas_votos`档案 —— 它重新哈希CSV,如果不变,则记录一个`ok`运行行 **不** 重新应用约15k次更新;如果它与注册的旧版本有差异,则作业失败以提醒(见下文);
- Worker内的 **Cron触发器**(`0 */2 * * *`,`src/scraper/pipeline.ts → refreshEcidadania`)仅执行 **有针对性的指标拼接** 约5个REST亮点,每个实时实体(`restcolecaomaismateria/ideia/audiencia` —— votos/comentários/apoios),记录为`ok-metrica`,因此它永远不会重新破坏语料库基线,也不会触及长尾。
两个写入者通过规范的`buildXResumo`生成器 + 共享的`contentHash`构建有效载荷,因此它们的行是字节相同的。每次写入:
- **插入** `ecidadania_current`(每项一行 —— 工具读取的内容),
- **追加** `ecidadania_history`仅当项目的`content_hash`发生变化时(时间序列准备),
- 在`ecidadania_scrape_runs`中记录每次运行。
**异常守卫**(`src/scraper/anomaly.ts`,`classifyRun`)确保失败或异常的语料库运行(零行,或少于`ECIDADANIA_CORPUS_MIN_PCT`%的上一次良好运行) **绝不会** 覆盖上一次良好状态。
**列表/分析工具**(`listar_*`、`consultas_analise`、`sugerir_tema_enquete`、`consultas_votos`)从D1通过`resolveList`(`src/scraper/store.ts`)读取:优先使用D1。因为现在每个实体都是一个完整的语料库,所以过时的语料库会从D1中 **标记**(`possivelDesatualizacao: true`)而不是崩溃到约5项实时亮点(原始覆盖漏洞);实时爬取仅在D1为空(冷启动,在第一次每周运行之前)保留。过时使用`ECIDADANIA_CORPUS_STALE_MAX_MIN`(~10天)。每个列表响应都带有附加的`meta`(`fonte`、`lastScrapedAt`、`possivelDesatualizacao`),因此调用者始终看到数据真实的年龄,并且永远不会在不知不觉中获取过时数据。
**详细信息工具**(`obter_*`)保持 **实时**(使用CSS类目标正则表达式的HTML爬取)并将它们丰富的数据通过`ecidadania_detalhe`写入 **fire-and-forget**(由`content_hash`去重),因此详细信息历史记录会累积,而不会为响应增加延迟。
#### 完整语料库摄入(离线)
三个实时e-Cidadania语料库由 **每日** Action(`.github/workflows/ingest-ecidadania.yml`)拥有,每个语料库都有自己的`scripts/ingest-ecidadania/index-*.ts`协调器,发出批处理`out-*.sql`,应用步骤批量加载:
- **`consultas`** —— 开放咨询(详细见下文)。
- **`eventos`** —— 来自`principalaudiencia?p=N` HTML列表的audiências/eventos;状态直接来自列表块(无`/processo`桥接)。
- **`ideias`** —— 来自`pesquisaideia?situacao=N&p=M`的ideias legislativas(~150k),按`situacao`桶爬取(列表中没有内联状态)并以~10k语句批次发出。
第四个实体,**`consultas_votos`**,是一个单独的 **历史** 档案,由~33 MB Arquimedes CSV(`Proposições-com-votos.csv`)解析的按UF划分的投票记录,聚合为每个事项的一条记录,并带有`votosPorUf`分解。CSV的“dados atualizados até”时间戳成为出处`reference_period`;它被排除在行哈希(`consultaVotoCore`)之外,因此这些冻结投票的时间戳更新不会改变历史记录。`STATUS ATUAL`统一为"Descontinuado",因此存档,不是开放咨询的迁移。通过`senado_ecidadania_consultas_votos`提供出处,指向CSV(`ECIDADANIA_ARQUIMEDES`)。由于它是 **冻结的单 vintage档案**(无时间序列 —— ROADMAP第2阶段,决定D1),因此 **排除** 在每日作业之外,而是进行 **每周完整性检查** Action(`.github/workflows/verify-consultas-votos.yml`,`INGEST_CONSULTAS_VOTOS_VERIFY=1`):它下载并重新哈希CSV与注册的旧版本;如果相同,它记录一个`ok`运行行并且不应用任何更改;如果它有差异(任何事项哈希更改或计数移动),它记录一个`anomalo`运行行并且作业 **失败**,因此“冻结档案”前提永远不会在不知不觉中被覆盖 —— 重新摄入合法的新vintage是一个明确的`force`调度(`INGEST_FORCE=1`)。
`consultas`作业是参考实现:
`consultas`涵盖 **所有开放咨询** 的完整集 —— 当前正在处理的事项 (~7.7k),而不仅仅是约5个亮点。确认在第一次运行:`pesquisamateria`列表 **仅限于正在处理的事项**,因此已关闭的历史咨询 **不会** 被此源捕获(超出范围)。三个确定的设计决策:
1. **解耦摄入。** 开放集由 **离线TypeScript作业**(`scripts/ingest-ecidadania/`,由每日GitHub Action运行 —— `.github/workflows/ingest-ecidadania.yml`)获取,该作业分页HTML列表(`pesquisamateria?p=1..N`,唯一的全覆盖源)以获取id + 票数计数并 **批量加载D1**;Worker仅读取。脆弱的长时间爬取被保留在请求/Cron路径之外。
2. **来自`/processo`的状态,而不是HTML。** 咨询从演示到结束,因此`status`是事项的一个函数:**aberta ⟺ `codigoMateria`在`/processo` `tramitando=S`集中**,源自强大的JSON(从未爬取)。每个咨询都作为`aberta`进入(列表仅产生正在处理的事项);在每次 **完整** 运行后,作业重新从`/processo`成员资格(不是列表缺失,它可能是短暂的)重新推导所有存储行的状态,因此某个事项离开处理后会翻转为`encerrada`。因此`encerrada`/`todas`集会随着时间增长;咨询在 **之前** 结束的咨询 **不会** 被捕获(超出范围)。列表/分析工具默认为`status: aberta`。
3. **两个协调一致的节奏(共享的编写器合约)。** 作业 **重用** `contentHash` + `ConsultaResumo`生成器 + `classifyRun`来自`src/scraper/`,因此其行与Cron的字节相同。每日作业拥有长尾; **2h Cron** 通过 **有针对性的指标拼接** (记录为`ok-metrica`,绕过语料库`classifyRun`基线)保持约5个热点/开放亮点新鲜(记录为`ok-metrica`)。语料库新鲜度(`possivelDesatualizacao`)从上一次`status='ok'`运行计算,并使用更大的窗口(`ECIDADANIA_CORPUS_STALE_MAX_MIN`),而过时的咨询语料库会从D1中标记而不是崩溃回到实时亮点。
写入负载的保护措施:不完整的爬取(任何页面失败)或不完整的`/processo`状态宇宙只会写入一个`erro`运行行;即使是完整的爬取也会被 **灾难性底线`(`ECIDADANIA_CORPUS_MIN_PCT`,默认为上一次良好语料库的80%)拒绝,以防止损坏的页面覆盖 -- 可使用`--force` / `INGEST_FORCE=1`合法的大型缩减。使用Action或手动运行:
```bash
CLOUDFLARE_API_TOKEN=… npm run ingest:ecidadania # 编写 scripts/ingest-ecidadania/out.sql
npx wrangler d1 execute senado-ecidadania --remote --file=scripts/ingest-ecidadania/out.sql
```## 缓存
### 层架构
| 层 | 存储 | 范围 | TTL范围 | 目的 |
|-------|---------|-------|-----------|---------|
| **L0** | 内存`Map` | 每个隔离 | 30-300秒 | 超快,消除Worker隔离内的冗余请求 |
| **L1** | Cloudflare Cache API(`caches.default`) | 每个colo(PoP) | 60-600秒 | 在同一个边缘位置跨请求共享 |
| **L2** | KV(可选) | 全球 | 可变 | 预留用于罕见的低写入数据 |
### 缓存类别
| 类别 | L0 TTL | L1 TTL | 用于 |
|----------|--------|--------|----------|
| **STATIC** | 300秒 | 600秒 | 立法类型,静态引用 |
| **SEMI_STATIC** | 120秒 | 300秒 | 党列表,UF列表,委员会详细信息 |
| **DYNAMIC** | 30秒 | 60秒 | 日程,最近的投票,会议列表 |
| **ON_DEMAND** | 30秒 | 120秒 | 特定账单/参议员/投票查找 |
### POST缓存方法
MCP使用POST进行所有`tools/call`请求。缓存POST响应不是Cache API原生支持的,因为它需要GET请求。解决方案:
1. **哈希参数** - 工具名称 + 排序参数被哈希为SHA-256
2. **合成GET密钥** - 合成URL `https://senado-br-mcp.internal/__cache/{tool}/{hash}`被构造
3. **Cache API匹配/放置** - 合成GET URL与`caches.default.match()`和|`caches.default.put()`一起使用,允许标准的Cache API操作在POST来源的数据上进行
此缓存发生在**工具级别**(在每个工具的回调内部),而不是在MCP传输级别。
### C 组 — 流程 (5 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_search_processos` ⊕ | 搜索立法流程(作为事项搜索的补充) |
| `senado_obter_processo` ⊕ | 特定立法流程的完整详情 |
| `senado_processo_detalhe` | 通过 `secao` 枚举的流程方面:修正案、报告或截止日期 |
| `senado_autores_atuais` | 按生产力排序的当前流程作者 |
| `senado_tabelas_processo` | 12 个参考表(缩写、主题、类别、类型-*)通过 `tabela` 枚举 |
### D 组 — 投票 (3 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_obter_votacao` ⊕ | 投票详情与命名投票。接受 `codigoVotacao`(plenário 会议的 `codigoSessao`)。 |
| `senado_votos_materia` ⊕ | 事项投票(通过 v3 `/votacao?codigoMateria`),可选命名投票 |
| `senado_search_votacoes` ⊕ | 按 `天`、`期间`、`流程`、`事项` 或 `参议员` 灵活搜索plenário投票 |
### E 组 — 委员会 (7 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_listar_comissoes` | 活动委员会列表,按类型可过滤 |
| `senado_obter_comissao` | 通过 `secao` 枚举的委员会数据:摘要(主席/总数)或成员(组成)。内部解决缩写为代码。 |
| `senado_reunioes_comissao` | 委员会在某个期间的会议(处理年之间的间隔) |
| `senado_agenda_comissoes` | 某日所有委员会的会议议程 |
| `senado_reuniao_comissao` | 会议详情:各方、事项、嘉宾、结果、议程/会议链接 |
| `senado_requerimentos_cpi` | 提交给活动中的 CPI 的请求,分页 |
| `senado_distribuicao_materias` | 参议员在委员会中的工作量统计:作者或报告人 |
### F 组 — 全体会议 (7 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_agenda_plenario` | 全体会议日程 - 按日、月或国会(范围:日/月/CN) |
| `senado_resultado_plenario` | 会议结果:审议事项、意见、结果(SF/CN/月) |
| `senado_orientacao_bancada` | 按投票的党派领导指示,附人数统计 |
| `senado_vetos` | 按年份或审议状态的总统否决 |
| `senado_resultado_veto` | 否决投票结果(按否决、否决法案或设备) |
| `senado_encontro_plenario` | 立法会议详情、议程事项、结果或摘要 |
| `senado_tabelas_plenario` | 会议类型、出席类型、立法机构列表 |
### G 组 — 电子公民 (9 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_ecidadania_listar_consultas` | 公共咨询(**开放**的提案审议流程的完整集),带有是/否投票;`状态` 过滤器(默认为 `开放`) |
| `senado_ecidadania_obter_consulta` | 咨询详情:投票、作者、报告人、评论 |
| `senado_ecidadania_consultas_analise` | 通过 `模式`(共识/两极分化);`状态` 默认为 `开放`,分析所有 **开放** 的咨询 |
| `senado_ecidadania_listar_ideias` | 公民的立法想法;通过 `ordenarPor: apoios` 支持度最高的排名 |
| `senado_ecidadania_obter_ideia` | 想法详情:文本、支持、转换为提案的状态 |
| `senado_ecidadania_listar_eventos` | 交互式活动(听证会、座谈会、直播);通过 `ordenarPor` 评论最多的排名 |
| `senado_ecidadania_obter_evento` | 活动详情:议程、嘉宾、视频链接 |
| `senado_ecidadania_sugerir_tema_enquete` | 根据可配置的标准建议每月调查主题 |
| `senado_ecidadania_consultas_votos` | 带 **按 UF 分割**(CSV 阿基米德)的历史投票档案;按 `total`/`sim`/`nao`、`uf`/`materia` 过滤 |
### I 组 — 发言 (3 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_discursos_senador` | 通过 `tipo` 枚举的参议员发言:发言(自己的)或插话(干预) |
| `senado_discursos_plenario` | 某日期范围内的全体会议发言 |
| `senado_discurso_texto` | 特定发言/讲话的全文 |
### J 组 — 集团和领导层 (4 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_listar_blocos` | 参议院的议会集团及其成员党派 |
| `senado_obter_bloco` | 特定议会集团的详情 |
| `senado_liderancas` | 参议院/国会领导层(领导人、副领导人),可过滤 |
| `senado_mesa` | 通过 `casa` 枚举的董事会成员:参议院(参议院董事会)或国会(国会董事会) |
### K 组 — 预算 (1 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_orcamento_parlamentar` | 通过 `tipo` 枚举的预算修正案数据:修正案(批次)或函件(支持函件) |
### L 组 — 联邦法律 (2 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_buscar_legislacao` | 按类型、编号、年份或日期(至少一个必填)搜索联邦法律规范 |
| `senado_obter_legislacao` | 特定联邦法律规范的详情 |
### M 组 — 委员会投票 (1 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_votacao_comissao` | 通过 `por` 枚举的委员会投票:委员会、参议员或事项;可选期间 |
### N 组 — 速记 (2 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_notas_taquigraficas` | 全体会议或委员会会议的官方记录 - 摘要模式带摘录、分页全文模式带分块、发言者过滤 |
| `senado_videos_taquigrafia` | 每个会议或集会的视频/音频单元,带有发言者和媒体链接 |
### O 组 — 参议员/行政 (2 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_ceaps` | 按年份统计的参议员 CEAPS 议会配额支出 - 按参议员、支出类型、月份或供应商聚合或详细列项;按参议员/月份/类型/供应商过滤 |
| `senado_senadores_admin` | 通过 `tipo` 枚举的参议员行政数据:住房补贴、支持办公室或退休人员 |
### P 组 — 公务员/人事管理 (4 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_servidores` | 按状态(在职/有效/委任/离职)的公务员,可按姓名、单位、职位过滤 |
| `senado_remuneracoes_servidores` | 月度工资单 - 按工资类型或个人构成汇总,附计算的毛额 |
| `senado_horas_extras` | 按月统计的加班费,附总额 |
| `senado_pessoal_tabelas` | 通过 `tabela` 枚举的人员表格:数量(人员、职位-职能、退休预测、参议员)和列表(实习生、养老金领取者、地点、职位) |
### Q 组 — 合同 (6 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_contratos` | 带服务器端过滤的合同:供应商、 CNPJ、年份、编号、对象、劳动 |
| `senado_contratacao_detalhe` | 合同/ ATA/拨款的项目、付款、担保、修正案或激活 |
| `senado_licitacoes` | 按编号或对象文本的招标 |
| `senado_terceirizados` | 按姓名、公司或单位的外部合作者 |
| `senado_empresas_contratadas` | 与参议院签订合同的公司(需要名称/CNPJ过滤器) |
| `senado_contratacoes_lista` | 价格注册 ATA、承诺笔记、青年学徒 |
### R 组 — 基金供应 (1 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_suprimento_fundos` | 按年份统计的小额现金垫款:收款人、授予行为、承诺、流动、卡交易 |
### S 组 — 参议院预算 (1 个工具)
| 工具 | 描述 |
|------|-------------|
| `senado_execucao_orcamentaria` | 自 2013 年以来的预算执行(分配、承诺/结算/支付)和自 2012 年以来的自有收入(预测 vs. 收集)- 按年份、行动、支出组、来源或收入来源汇总 |
**总计:66 个工具**
### 提示 (4)
可重用的 pt-BR 工作流模板(MCP `prompts` 功能),定义在 `src/prompts.ts` 中:
| 提示 | 参数 | 它指导什么 |
| --- | --- | --- |
| `senado_gastos_senador` | `senador`, `ano` | 解析参议员并聚合/详细列出 CEAPS 支出。 |
| `senado_tramitacao_materia` | `sigla`, `numero`, `ano` | 获取事项的当前情况 + 流转历史。 |
| `senado_votos_senador` | `senador`, `periodo?` | 列出参议员在该期间的命名投票。 |
| `senado_panorama_ecidadania` | — | 整合咨询(共识/两极分化)、想法和热门活动。 |
### 资源 (5)
静态上下文文档/表格(MCP `resources` 功能),定义在 `src/resources.ts` 中:
| URI | 类型 | 内容 |
| --- | --- | --- |
| `senado://guia` | markdown | 目标的总体视图和每种工具的使用指南。 |
| `senado://catalogo` | markdown | 按领域分组的 66 种工具。 |
| `senado://glossario` | markdown | 参议院的缩写和术语(PEC、CEAPS、CCJ、RCN ...)。 |
| `senado://tabelas/tipos-materia` | json | 提案类型(缩写/名称/描述)。 |
| `senado://tabelas/ufs` | json | 27 个联邦单位。 |
## 项目结构
```
src/
├── index.ts # Worker 入口点(fetch 处理程序 + 调度/Cron 处理程序)
├── server.ts # McpServer 工厂(为每个请求创建实例)
├── auth.ts # 可选的 Bearer token 身份验证(恒定时间比较)
├── metrics.ts # 内存计数器,在 /metrics 处提供
├── types.ts # 环境、缓存类别、安全常数
├── cache/
│ ├── l0-memory.ts # 带 TTL + LRU 逐出的内存映射缓存
│ ├── l1-cache-api.ts # Cloudflare Cache API 包装器(合成 GET 键)
│ └── manager.ts # 缓存协调器(L0 → L1 → 上游)
├── throttle/
│ ├── token-bucket.ts # 令牌桶速率限制器(全局 + 每个客户端)
│ └── upstream.ts # 上游获取,带并发限制、重试、超时
├── scraper/
│ ├── ecidadania.ts # 隔离的 e-Cidadania 抓取器(REST 列表 + 正则表达式 HTML 详情;buildConsultaResumo)
│ ├── pipeline.ts # 2 小时 Cron:有针对性的高亮指标拼接(consultas/eventos/ideias);由 Worker 作业拥有
│ ├── anomaly.ts # 运行分类(异常运行从不覆盖当前)
│ └── store.ts # D1 读取(解析列表 + 实体过时性,lastGoodRunAt)+ 详细写入
├── instrument.ts # 每个工具的调用遥测(内存 + 分析引擎)
├── utils/
│ ├── logger.ts # 结构化 JSON 日志记录
│ └── validation.ts # toolResult、toolError、errorFrom、buildParams、ensureArray 帮助函数
└── tools/
├── referencia.ts # H 组 — 1 个参考/元数据工具
├── senadores.ts # A 组 — 5 个参议员工具
├── materias.ts # B 组 — 2 个法案/事项工具(v3 后端)
├── processos.ts # C 组 — 5 个流程工具
├── votacoes.ts # D 组 — 3 个投票工具
├── comissoes.ts # E 组 — 7 个委员会工具
├── plenario.ts # F 组 — 7 个全体会议工具
├── ecidadania.ts # G 组 — 8 个 e-Cidadania 工具(从 D1 读取;参见抓取器)
├── discursos.ts # I 组 — 3 个演讲工具
├── composicao.ts # J 组 — 4 个集团/领导工具
├── orcamento.ts # K 组 — 1 个预算工具
├── legislacao.ts # L 组 — 2 个联邦法律工具
├── votacao-comissao.ts # M 组 — 1 个委员会投票工具
├── taquigrafia.ts # N 组 — 2 个速记记录工具
├── senadores-admin.ts # O 组 — 2 个行政参议员工具(CEAPS、住房)
├── servidores.ts # P 组 — 4 个人员工具
├── contratacoes.ts # Q 组 — 6 个采购工具
├── supridos.ts # R 组 — 1 个小额现金工具
└── orcamento-senado.ts # S 组 — 1 个预算执行工具
脚本/
└── ingest-ecidadania/ # 离线 Worker 全 corpus 咨询数据摄入(通过 `npm run ingest:ecidadania` 运行)
├── index.ts # 协调器:爬取 → 状态(/processo)→ 标准化 → 保护 → out.sql
├── listing.ts # 纯列表解析器(parseConsultaListingPage,findLastPage)
├── status.ts # tramitando=S 集来自 /processo → aberta/encerrada(deriveStatus)
├── restatus.ts # 停滞修复:通过 /processo 成员资格重新统计存储的行(关闭僵尸)
├── http.ts # 有礼貌的获取(重试/回退)用于无人值守的爬取
├── d1.ts # D1 预读(现有元数据、有效载荷、最后好的行)通过 wrangler
├── verify.ts # consultas_votos 每周完整性检查判决(verifyAcervoIntegrity)
└── sql.ts # out.sql 生成(镜像 SQL.upsert/SQL.history;重用 SyncRecord)
.github/workflows/ # ingest-ecidadania.yml(每日 D1 corpus 加载),verify-consultas-votos.yml
# (每周冻结-acervo 完整性检查),publish-mcp.yml(registry),
# usage-report.yml(每月分析报告),deprecate-registry.yml
# (所有固定到当前 Node 24 操作符版本 — 参见每个 YAML 了解确切版本)
migrations/ # D1 模式(0001 表,0002 索引)用于 e-Cidadania 管道
tests/ # Vitest 单元测试镜像 src/(解析器、缓存、限流、身份验证、抓取器、
# 管道/异常/存储,以及 e-Cidadania 合同测试)
```
## 环境变量
| 变量 | 必需 | 默认值 | 描述 |
|----------|----------|---------|-------------|
| `SENADO_BASE_URL` | 否 | `https://legis.senado.leg.br/dadosabertos` | 立法 API 基本 URL |
| `SENADO_ADM_BASE_URL` | 否 | `https://adm.senado.gov.br/adm-dadosabertos` | 行政 API 基本 URL |
| `ALLOWED_ORIGIN` | 否 | `*` | CORS 允许的来源 |
| `API_KEY` | 否(秘密) | — | 设置后,所有请求(除 `/health`、`/metrics` 和 CORS 预检外)都需要 `Authorization: Bearer <key>` |
| `CACHE_KV` | 是(绑定) | — | L2 缓存的 KV 命名空间 |
| `ECIDADANIA_DB` | 是(绑定) | — | e-Cidadania 管道的 D1 数据库(列表持久性和历史记录) |
| `ECIDADANIA_CORPUS_STALE_MAX_MIN` | 否 | `14400` | 离线 Worker 全体 corpora 的过期窗口(分钟,~10d)- 提供标记的,绝不崩溃到高亮 |
| `ECIDADANIA_CORPUS_MIN_PCT` | 否 | `80` | 离线 Worker corpus 作业的灾难性下限:低于此百分比的完整爬取/解析将被拒绝 |
| `CLOUDFLARE_API_TOKEN` | 否(秘密) | — | GitHub Actions 秘密(D1 编辑范围)用于 corpus 抓取/完整性检查作业;不由 Worker 使用 |
| `CLOUDFLARE_ACCOUNT_ID` | 否(Actions var) | — | GitHub Actions 存储库变量,因此 wrangler 跳过 `/memberships` 帐户自动发现(D1 范围令牌无法读取它);与 `CLOUDFLARE_API_TOKEN` 在抓取作业中一起必需 |
| `SENADO_ANALYTICS` | 否(绑定) | — | 每个工具调用遥测的分析引擎数据集 |
## 连接 MCP 客户端
这是一个**远程**服务器(可流式传输的 HTTP,无需安装,开放访问)- 任意 MCP 客户端指向
`https://senado.sidneybissoli.com/mcp`。除了 66 种工具外,它还公开了**提示**(预制的 pt-BR
工作流程:`senado_gastos_senador`、`senado_tramitacao_materia`、`senado_votos_senador`、
`senado_panorama_ecidadania`)和**资源**(`senado://guia`、`senado://catalogo`,
`senado://glossario`, `senado://tabelas/tipos-materia`, `senado://tabelas/ufs`).
### 一键式(LobeHub)
从 LobeHub 市场安装 - 打开
[服务器页面](https://lobehub.com/mcp/sidneybissoli-senado-br-mcp-cloudflare) 并点击 **安装**
(它预先填写了远程端点,无需配置)。
### Claude 桌面版/Claude 代码
将以下内容添加到您的 MCP 配置中:
```json
{
"mcpServers": {
"senado-br": {
"url": "https://senado.sidneybissoli.com/mcp"
}
}
}
```
对于基于命令的客户端(或任何没有本机远程支持的客户端),请使用 `mcp-remote` 桥接器:
```json
{
"mcpServers": {
"senado-br": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://senado.sidneybissoli.com/mcp"]
}
}
}
```
### MCP 检验
```bash
npx @modelcontextprotocol/inspector https://senado.sidneybissoli.com/mcp
```
## 许可证
麻省理工学院
## 致谢
图标:*“巴西国会大厦日出”* - 巴西国会大厦的照片,根据知识共享许可协议使用。 (如果你是作者,请开启一个问题,以便我们添加完整的署名/许可链接。)
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器