senado-br-mcp 3.6.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  ![Cloudflare Workers](https://img.shields.io/badge/Cloudflare%20Workers-F38020?logo=cloudflare&logoColor=white)
4
4
  ![MCP](https://img.shields.io/badge/MCP-Streamable%20HTTP-1f6feb)
5
- ![Tools](https://img.shields.io/badge/tools-67-2ea44f)
5
+ ![Tools](https://img.shields.io/badge/tools-69-2ea44f)
6
6
  [![CI](https://github.com/SidneyBissoli/senado-br-mcp-cloudflare/actions/workflows/ci.yml/badge.svg)](https://github.com/SidneyBissoli/senado-br-mcp-cloudflare/actions/workflows/ci.yml)
7
7
  [![MCP Registry](https://img.shields.io/badge/MCP-Registry-blue)](https://registry.modelcontextprotocol.io)
8
8
  [![LobeHub](https://lobehub.com/badge/mcp/sidneybissoli-senado-br-mcp-cloudflare)](https://lobehub.com/mcp/sidneybissoli-senado-br-mcp-cloudflare)
9
- [![smithery badge](https://smithery.ai/badge/sidneybissoli/senado-br-mcp-cloudflare)](https://smithery.ai/servers/sidneybissoli/senado-br-mcp-cloudflare)
9
+ [![LightNow capabilities](https://lightnow.ai/badge/io.github.SidneyBissoli/senado-br-mcp-cloudflare)](https://lightnow.ai/servers/io.github.SidneyBissoli/senado-br-mcp-cloudflare)
10
10
  [![senado-br-mcp-cloudflare MCP server](https://glama.ai/mcp/servers/SidneyBissoli/senado-br-mcp-cloudflare/badges/score.svg)](https://glama.ai/mcp/servers/SidneyBissoli/senado-br-mcp-cloudflare)
11
11
  [![GitHub stars](https://img.shields.io/github/stars/SidneyBissoli/senado-br-mcp-cloudflare?style=flat&logo=github)](https://github.com/SidneyBissoli/senado-br-mcp-cloudflare)
12
12
  [![GitHub Sponsors](https://img.shields.io/github/sponsors/SidneyBissoli?logo=githubsponsors&label=Sponsor&color=db61a2)](https://github.com/sponsors/SidneyBissoli)
@@ -17,7 +17,7 @@
17
17
 
18
18
  A **public, hosted** MCP server that gives AI assistants live, structured access to **Brazilian Senate open data** — **no installation, no account, no API key**. Point your MCP client at the hosted endpoint and start asking about senators, bills, votes, expenses, and more. It runs on Cloudflare Workers over Streamable HTTP.
19
19
 
20
- It exposes **67 tools**, **4 prompts**, and **5 resources** across two domains:
20
+ It exposes **69 tools**, **4 prompts**, and **5 resources** across two domains:
21
21
 
22
22
  - **Legislative** — senators; bills and their tramitation; votes; committees; plenary sessions, results and presidential vetoes; party-bloc voting orientation; speeches and stenographic transcripts; blocs and leadership; federal legislation; and citizen participation via the e-Cidadania portal.
23
23
  - **Administrative** — CEAPS parliamentary-quota expenses; housing allowance; civil servants and payroll; overtime; interns; procurement contracts and biddings; outsourced staff; petty-cash funds; and budget execution.
@@ -68,6 +68,16 @@ Public legal URLs for app review:
68
68
  - Privacy policy: `https://senado.sidneybissoli.com/privacy`
69
69
  - Terms of use: `https://senado.sidneybissoli.com/terms`
70
70
 
71
+ ### ChatGPT (Deep Research)
72
+
73
+ ChatGPT deep research (and company knowledge, and research workflows over the Responses API) only uses an MCP server that exposes exactly `search` and `fetch` — this server does, on top of the `senado_*` tools, on the full `/mcp` surface (not on the curated app profile). Point the connector at the hosted endpoint, no key required:
74
+
75
+ ```
76
+ https://senado.sidneybissoli.com/mcp
77
+ ```
78
+
79
+ `search` ranks the query against the senators in office and the active committees of the Senate and the National Congress and returns `{ id, title, url }` (`sen:<código>` / `com:<código>`); `fetch` returns the document as readable Markdown — the senator's biography and mandates, or the committee's summary and board — with the canonical public page (the senator's profile on www25.senado.leg.br or the committee page on legis.senado.leg.br), which is what ChatGPT cites. Both carry the same provenance block as every other tool, in `structuredContent` and `_meta` (the text channel is the contract's JSON). In ChatGPT's developer mode (Settings → Security and login → Developer mode) any tool is callable — the `senado_*` tools remain the ones to use for data.
80
+
71
81
  ### Install (any client)
72
82
 
73
83
  For clients that launch MCP servers as a command — and for one-command setup — use the
@@ -87,7 +97,7 @@ own instance** — it is **not** required to use this public server.
87
97
 
88
98
  Prefer not to route queries through a third-party host (e.g. a newsroom policy)? The **same server**
89
99
  also runs as a **local stdio process** that talks **directly to the official government APIs** — same
90
- 67 tools, same provenance envelope, no Cloudflare in the loop. This is the npm/stdio channel, published
100
+ 69 tools, same provenance envelope, no Cloudflare in the loop. This is the npm/stdio channel, published
91
101
  as [`senado-br-mcp`](https://www.npmjs.com/package/senado-br-mcp).
92
102
 
93
103
  Point a command-based client (Claude Desktop/Code, etc.) at the package — npm fetches and runs it,
@@ -125,7 +135,7 @@ list/corpus tools: without D1 they fall back to a live scrape of the ~5 REST hig
125
135
 
126
136
  This repo bundles a Claude [Agent Skill](https://platform.claude.com/docs/en/docs/agents-and-tools/agent-skills/overview)
127
137
  at [`.claude/skills/senado-br/`](.claude/skills/senado-br/SKILL.md) that teaches Claude **when** to reach for
128
- this server and **how** to use its 67 tools well — a themed tool map, common question→tool playbooks, the
138
+ this server and **how** to use its 69 tools well — a themed tool map, common question→tool playbooks, the
129
139
  provenance contract, and gotchas (dates, the `codigoMateria` bridge, e-Cidadania's open-set listing, pagination).
130
140
  It points back to the server's own `senado://catalogo` / `senado://guia` resources rather than duplicating them.
131
141
 
@@ -138,7 +148,7 @@ Claude Code auto-discovers it when you work in this repo. To use it elsewhere, c
138
148
  - **Runtime:** Cloudflare Workers (ESM)
139
149
  - **Transport:** Streamable HTTP (MCP spec 2025-03-26) via `createMcpHandler` from `agents/mcp`
140
150
  - **Protocol:** MCP over JSON-RPC — `/mcp` handles the full public server; `/mcp/openai-app-v2` exposes a curated 27-tool profile plus a shared MCP Apps widget for OpenAI app review/submission (`/mcp/openai-app` remains as a legacy alias)
141
- - **SDK:** `@modelcontextprotocol/sdk` 1.26.0+ (per-request McpServer instances)
151
+ - **SDK:** `@modelcontextprotocol/server` 2.x (per-request McpServer instances; the v1 `@modelcontextprotocol/sdk` remains only as a peer of `agents`, dev-time)
142
152
  - **Validation:** Zod schemas for all tool inputs
143
153
  - **Caching:** 2-layer (L0 memory + L1 Cache API) with SHA-256 keying
144
154
  - **e-Cidadania store:** D1 database refreshed by a Cron Trigger (every 2h) — list tools read from D1 with a live-scrape fallback and a staleness flag; detail tools stay live with write-through (see [e-Cidadania](#e-cidadania-d1-backed-cron-refreshed))
@@ -156,7 +166,7 @@ Claude Code auto-discovers it when you work in this repo. To use it elsewhere, c
156
166
 
157
167
  ### Prerequisites
158
168
 
159
- - Node.js 20+
169
+ - Node.js 22+ (`engines.node`)
160
170
  - [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) v4+
161
171
  - Cloudflare account
162
172
 
@@ -535,7 +545,7 @@ In addition to the `provenance` envelope, `structuredContent` carries a top-leve
535
545
 
536
546
  `retrieved_at` fidelity is provided by the cache layer (`cachedFetchWithMeta`), which persists the fetch timestamp alongside the value, so it reflects the real upstream extraction even on a cache hit. Two exceptions report an honest live timestamp instead: the e-Cidadania **list** tools (read from D1) use the corpus's `lastScrapedAt` — the true age of the stored data — while e-Cidadania **detail** tools, scraped live, use the fetch time and a level-3 canonical item URL. The only path that falls back to the build-time default is the in-code static reference catalog (`senado_tabelas_referencia` `tipos-materia`), which has no upstream extraction instant.
537
547
 
538
- Coverage is **universal**: all 67 tools carry the envelope (verify with `grep -c 'resultWithProvenance(' src/tools/*.ts`). The **⊕** marks in the inventory below denote the original pilot tools (votes, bills, processes); the envelope now extends to every tool, so the marks are historical.
548
+ Coverage is **universal**: all 69 tools carry the envelope — the 67 `senado_*` tools via `resultWithProvenance(` (verify with `grep -c 'resultWithProvenance(' src/tools/*.ts`) and the two Deep Research tools via `provenanceExtras` (same block, in `structuredContent`/`_meta`, since their text channel is the contract's JSON). The **⊕** marks in the inventory below denote the original pilot tools (votes, bills, processes); the envelope now extends to every tool, so the marks are historical.
539
549
 
540
550
  ## Citable dataset (e-Cidadania participation)
541
551
 
@@ -739,7 +749,16 @@ Reads a bundled snapshot of the Senate's organizational tree (crawled from the i
739
749
  |------|-------------|
740
750
  | `senado_estrutura_organizacional` | Organizational chart (organograma) resolved for a `unidade` (sigla like `DGER` or name): returns its `caminho` (ancestors) and every subordinate unit (`subordinadas[]` — secretarias, coordenações, serviços, núcleos — with `nivel`). Pairs with `senado_servidores`'s `subordinadasA` filter, which counts/lists all servants under a whole directorate (a servant sits in a leaf serviço, so filtering `lotacao` by the parent sigla returns 0). |
741
751
 
742
- **Total: 67 tools**
752
+ ### Group U — Deep Research (2 tools)
753
+
754
+ The [OpenAI Deep Research contract](#chatgpt-deep-research): the only two tools without the `senado_` prefix, because the names are fixed by the contract. Registered through the same shim as the others (read-only annotations, permissive `outputSchema`, per-tool telemetry) and served on `/mcp` only — the curated ChatGPT app profile does not include them. The index (senators in office + active committees, ~300 documents) is built on first use from the same two list endpoints the `senado_listar_*` tools read, and kept for 24 h.
755
+
756
+ | Tool | Description |
757
+ |------|-------------|
758
+ | `search` | Ranks the query (natural language or keywords, pt/en, accent-insensitive) against senators in office and active committees; returns up to 10 `{ id, title, url }` — `sen:<código>` with the public profile URL, `com:<código>` with the public committee page. Provenance of both lists in `structuredContent`/`_meta`. |
759
+ | `fetch` | Returns the document for an id from `search` as `{ id, title, text, url, metadata }`: the senator's biography and mandates (same read as `senado_obter_senador`) or the committee's summary and board (same read as `senado_obter_comissao`), as Markdown, with that read's provenance. Unknown id → error. |
760
+
761
+ **Total: 69 tools**
743
762
 
744
763
  ### Prompts (4)
745
764
 
@@ -759,7 +778,7 @@ Static context documents/tables (MCP `resources` capability), defined in `src/re
759
778
  | URI | Type | Content |
760
779
  | --- | --- | --- |
761
780
  | `senado://guia` | markdown | Visão geral e qual ferramenta usar por objetivo. |
762
- | `senado://catalogo` | markdown | As 67 ferramentas agrupadas por domínio. |
781
+ | `senado://catalogo` | markdown | As 69 ferramentas agrupadas por domínio. |
763
782
  | `senado://glossario` | markdown | Siglas e termos do Senado (PEC, CEAPS, CCJ, RCN…). |
764
783
  | `senado://tabelas/tipos-materia` | json | Tipos de proposição (sigla/nome/descrição). |
765
784
  | `senado://tabelas/ufs` | json | As 27 unidades federativas. |
@@ -848,7 +867,7 @@ tests/ # Vitest unit tests mirroring src/ (parsers, cache, th
848
867
  ## Connecting MCP Clients
849
868
 
850
869
  This is a **remote** server (Streamable HTTP, no install, open access) — point any MCP client at
851
- `https://senado.sidneybissoli.com/mcp`. Besides 67 tools, it exposes **prompts** (ready-made pt-BR
870
+ `https://senado.sidneybissoli.com/mcp`. Besides 69 tools, it exposes **prompts** (ready-made pt-BR
852
871
  workflows: `senado_gastos_senador`, `senado_tramitacao_materia`, `senado_votos_senador`,
853
872
  `senado_panorama_ecidadania`) and **resources** (`senado://guia`, `senado://catalogo`,
854
873
  `senado://glossario`, `senado://tabelas/tipos-materia`, `senado://tabelas/ufs`).
package/README.pt-BR.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![Cloudflare Workers](https://img.shields.io/badge/Cloudflare%20Workers-F38020?logo=cloudflare&logoColor=white)
4
4
  ![MCP](https://img.shields.io/badge/MCP-Streamable%20HTTP-1f6feb)
5
- ![Tools](https://img.shields.io/badge/tools-67-2ea44f)
5
+ ![Tools](https://img.shields.io/badge/tools-69-2ea44f)
6
6
  [![CI](https://github.com/SidneyBissoli/senado-br-mcp-cloudflare/actions/workflows/ci.yml/badge.svg)](https://github.com/SidneyBissoli/senado-br-mcp-cloudflare/actions/workflows/ci.yml)
7
7
  [![MCP Registry](https://img.shields.io/badge/MCP-Registry-blue)](https://registry.modelcontextprotocol.io)
8
8
  [![LobeHub](https://lobehub.com/badge/mcp/sidneybissoli-senado-br-mcp-cloudflare)](https://lobehub.com/mcp/sidneybissoli-senado-br-mcp-cloudflare)
@@ -16,7 +16,7 @@
16
16
 
17
17
  Um servidor MCP **público e hospedado** que dá aos assistentes de IA acesso ao vivo e estruturado aos **dados abertos do Senado Federal do Brasil** — **sem instalação, sem conta, sem chave de API**. Aponte o seu cliente MCP para o endpoint hospedado e comece a perguntar sobre senadores, matérias, votações, despesas e muito mais. Roda em Cloudflare Workers via Streamable HTTP.
18
18
 
19
- Expõe **67 ferramentas**, **4 prompts** e **5 recursos** em dois domínios:
19
+ Expõe **69 ferramentas**, **4 prompts** e **5 recursos** em dois domínios:
20
20
 
21
21
  - **Legislativo** — senadores; matérias e sua tramitação; votações; comissões; sessões plenárias, resultados e vetos presidenciais; orientação de bancada nas votações; discursos e notas taquigráficas; blocos e lideranças; legislação federal; e participação cidadã pelo portal e-Cidadania.
22
22
  - **Administrativo** — despesas da cota parlamentar (CEAPS); auxílio-moradia; servidores e remunerações; horas extras; estagiários; contratos e licitações; terceirizados; suprimento de fundos; e execução orçamentária.
@@ -50,7 +50,7 @@ Para submissao e revisao pelo OpenAI Apps SDK, o Worker tambem expoe uma superfi
50
50
  https://senado.sidneybissoli.com/mcp/openai-app-v2
51
51
  ```
52
52
 
53
- Esse endpoint preserva o servidor MCP publico completo em `/mcp`, mas limita a descoberta a 25
53
+ Esse endpoint preserva o servidor MCP publico completo em `/mcp`, mas limita a descoberta a 27
54
54
  ferramentas de alto sinal, organizadas por intencao de usuario, para uso como app do ChatGPT.
55
55
  `/mcp/openai-app` continua disponivel como alias legado, mas novas configuracoes do app no ChatGPT
56
56
  devem usar `/mcp/openai-app-v2` para forcar a leitura do schema atual das ferramentas. As ferramentas
@@ -58,7 +58,7 @@ continuam chamando os mesmos handlers e retornando o mesmo envelope de provenien
58
58
  anunciada fica mais estreita. Qualquer listagem de ChatGPT App deve apresentar isto como um app
59
59
  independente de pesquisa em dados abertos, nao como conector oficial do Senado, da OpenAI ou do ChatGPT.
60
60
 
61
- Para ChatGPT Apps, essas 25 ferramentas tambem anunciam um template UI compartilhado do MCP Apps em
61
+ Para ChatGPT Apps, essas 27 ferramentas tambem anunciam um template UI compartilhado do MCP Apps em
62
62
  `ui://senado-br-mcp/openai-app-dashboard-v2.html`. O widget e autocontido e renderiza o
63
63
  `structuredContent` retornado como painel compacto com metricas, registros principais e fonte/proveniencia,
64
64
  sem adicionar outra ferramenta de dados visivel ao modelo.
@@ -68,6 +68,16 @@ URLs publicas legais para revisao do app:
68
68
  - Politica de privacidade: `https://senado.sidneybissoli.com/privacy`
69
69
  - Termos de uso: `https://senado.sidneybissoli.com/terms`
70
70
 
71
+ ### ChatGPT (Deep Research)
72
+
73
+ O deep research do ChatGPT (e o company knowledge, e os workflows de pesquisa da API Responses) só usa um servidor MCP que exponha exatamente `search` e `fetch` — este servidor expõe, além das ferramentas `senado_*`, na superfície completa `/mcp` (não no perfil curado do app). Aponte o conector para o endpoint hospedado, sem chave:
74
+
75
+ ```
76
+ https://senado.sidneybissoli.com/mcp
77
+ ```
78
+
79
+ `search` ranqueia a consulta contra os senadores em exercício e as comissões ativas do Senado e do Congresso Nacional e devolve `{ id, title, url }` (`sen:<código>` / `com:<código>`); `fetch` devolve o documento em Markdown legível — a biografia e os mandatos do senador, ou o resumo e a mesa da comissão — com a página pública canônica (o perfil do senador em www25.senado.leg.br ou a página da comissão em legis.senado.leg.br), que é o que o ChatGPT cita. As duas carregam o mesmo bloco de proveniência das outras ferramentas, em `structuredContent` e `_meta` (o canal de texto é o JSON do contrato). No modo desenvolvedor do ChatGPT (Settings → Security and login → Developer mode) qualquer ferramenta é chamável — as `senado_*` continuam sendo as ferramentas para dados.
80
+
71
81
  ### Instalação (qualquer cliente)
72
82
 
73
83
  Para clientes que iniciam servidores MCP como um comando — e para uma configuração de um único comando — use a
@@ -87,7 +97,7 @@ própria instância** — **não** é necessário para usar este servidor públi
87
97
 
88
98
  Prefere não rotear suas consultas por um servidor de terceiros (ex.: política de uma redação)? O **mesmo
89
99
  servidor** também roda como um **processo local stdio** que bate **direto nas APIs oficiais do governo** —
90
- as mesmas 67 ferramentas, o mesmo envelope de proveniência, sem Cloudflare no caminho. É o canal npm/stdio,
100
+ as mesmas 69 ferramentas, o mesmo envelope de proveniência, sem Cloudflare no caminho. É o canal npm/stdio,
91
101
  publicado como [`senado-br-mcp`](https://www.npmjs.com/package/senado-br-mcp).
92
102
 
93
103
  Aponte um cliente baseado em comando (Claude Desktop/Code, etc.) para o pacote — o npm baixa e executa,
@@ -125,7 +135,7 @@ Os logs vão para o **stderr** — o stdout carrega apenas o fluxo do protocolo
125
135
 
126
136
  Este repositório inclui uma [Agent Skill](https://platform.claude.com/docs/en/docs/agents-and-tools/agent-skills/overview)
127
137
  do Claude em [`.claude/skills/senado-br/`](.claude/skills/senado-br/SKILL.md) que ensina o Claude **quando**
128
- recorrer a este servidor e **como** usar bem as 67 ferramentas — um mapa de ferramentas por tema, playbooks de
138
+ recorrer a este servidor e **como** usar bem as 69 ferramentas — um mapa de ferramentas por tema, playbooks de
129
139
  pergunta→ferramenta, o contrato de proveniência e os gotchas (datas, a ponte `codigoMateria`, a listagem
130
140
  só-abertas do e-Cidadania, paginação). Ela aponta para os recursos `senado://catalogo` / `senado://guia` do
131
141
  próprio servidor em vez de duplicá-los.
@@ -138,8 +148,8 @@ O Claude Code a descobre automaticamente ao trabalhar neste repositório. Para u
138
148
 
139
149
  - **Runtime:** Cloudflare Workers (ESM)
140
150
  - **Transporte:** Streamable HTTP (spec MCP 2025-03-26) via `createMcpHandler` de `agents/mcp`
141
- - **Protocolo:** MCP sobre JSON-RPC — `/mcp` serve o catalogo publico completo; `/mcp/openai-app-v2` expoe um perfil curado de 25 ferramentas mais um widget MCP Apps compartilhado para revisao/submissao como app OpenAI (`/mcp/openai-app` permanece como alias legado)
142
- - **SDK:** `@modelcontextprotocol/sdk` 1.26.0+ (instâncias de McpServer por requisição)
151
+ - **Protocolo:** MCP sobre JSON-RPC — `/mcp` serve o catalogo publico completo; `/mcp/openai-app-v2` expoe um perfil curado de 27 ferramentas mais um widget MCP Apps compartilhado para revisao/submissao como app OpenAI (`/mcp/openai-app` permanece como alias legado)
152
+ - **SDK:** `@modelcontextprotocol/server` 2.x (instâncias de McpServer por requisição; o `@modelcontextprotocol/sdk` v1 fica só como peer do `agents`, em tempo de dev)
143
153
  - **Validação:** schemas Zod para todas as entradas das ferramentas
144
154
  - **Cache:** 2 camadas (L0 memória + L1 Cache API) com chaveamento SHA-256
145
155
  - **Store do e-Cidadania:** banco D1 atualizado por um Cron Trigger (a cada 2h) — as ferramentas de listagem leem do D1 com fallback de scraping ao vivo e flag de desatualização; as de detalhe ficam ao vivo com write-through (veja [e-Cidadania](#e-cidadania-em-d1-atualizado-por-cron))
@@ -156,7 +166,7 @@ O Claude Code a descobre automaticamente ao trabalhar neste repositório. Para u
156
166
 
157
167
  ### Pré-requisitos
158
168
 
159
- - Node.js 20+
169
+ - Node.js 22+ (`engines.node`)
160
170
  - [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) v4+
161
171
  - Conta Cloudflare
162
172
 
@@ -507,6 +517,37 @@ Campos do bloco `concise` (por resposta — uma ferramenta, uma fonte): `source`
507
517
 
508
518
  A cobertura abrange as quatro fontes upstream: **Dados Abertos Legislativo** (`legis.senado.leg.br`), **Dados Abertos Administrativo** (`adm.senado.gov.br`), **Execução Orçamentária** (feed Arquimedes/Financeiro em `senado.gov.br`) e **Portal e-Cidadania** (`www12.senado.leg.br/ecidadania`). Nas listas do e-Cidadania (lidas do D1) o `retrieved_at` é o `lastScrapedAt` do corpus — a idade real do dado; nos detalhes (raspados ao vivo) é o instante da chamada, com a URL canônica do item. A fidelidade do `retrieved_at` vem da camada de cache (`cachedFetchWithMeta`), que persiste o timestamp junto ao valor.
509
519
 
520
+ ## Conjunto de dados citável (participação no e-Cidadania)
521
+
522
+ Além do servidor ao vivo, este projeto publica um **conjunto de dados congelado, versionado e citável** da camada de participação do e-Cidadania (consultas públicas, ideias legislativas, eventos interativos + seus comentários, votos históricos por estado) — a camada que o pacote R `congressbr` nunca cobriu. Cada valor carrega um envelope de procedência por campo (`{ value, sourceEndpoint, sourceField, retrievedAt, license, schemaVersion }`); a licença dos dados (Dados Abertos do Senado Federal) é mantida **separada** da licença do código (MIT).
523
+
524
+ - **Como citar** — [`CITATION.cff`](CITATION.cff) (conjunto de dados; cite o DOI da versão do snapshot que você usou, e o DOI de conceito para o conjunto através das versões).
525
+ - **O que vai em cada release** — [`CHANGELOG-dataset.md`](CHANGELOG-dataset.md) (cumulativo, só acrescenta; amarra cada release ao seu `schemaVersion`).
526
+ - **Dicionário de variáveis e procedência de campo** — [`docs/dataset-dictionary.md`](docs/dataset-dictionary.md) (gerado de `src/dataset/schema.ts`, a fonte única de verdade).
527
+ - **Licença dos dados** — [`LICENSE-DATA.md`](LICENSE-DATA.md).
528
+ - **Como cortar uma release** (congelar → checksums → GitHub Release → DOI no Zenodo) — [`docs/release-runbook.md`](docs/release-runbook.md); a maquinaria está em `src/dataset/`, `scripts/build-dataset/` e `.github/workflows/release-dataset.yml`.
529
+
530
+ ### Inventário — schema v2 (`schemaVersion` `2.0.0`)
531
+
532
+ Cada release entrega um recurso NDJSON por entidade (um `HarmonizedRecord` por linha: identidade + um envelope de procedência por campo), mais um manifesto `datapackage.json` e uma cópia do dicionário. Cinco recursos:
533
+
534
+ | Recurso (`*.ndjson`) | Grão | Variáveis principais | Fonte(s) |
535
+ |---|---|---|---|
536
+ | `consultas` | 1 consulta pública (matéria) | `materia`, `ementa`, `votosSim`/`votosNao`/`totalVotos`, `percentual*`, **`autoria`ⁿ**, **`relator`ⁿ**, `status`, `url`, `firstSeenAt` | listagem `pesquisamateria` + **detalhe** (`visualizacaomateria`)ⁿ + `/processo?tramitando=S` para o status |
537
+ | `ideias` | 1 ideia legislativa (~113,7 mil) | `titulo`, `apoios`, `status`, **`dataPublicacao`ⁿ**, **`autorUf`ⁿ**, **`descricao`ⁿ**, **`plConvertido`ⁿ**, `url`, `firstSeenAt` | listagem `pesquisaideia` + **detalhe** (`visualizacaoideia`) por um backfill retomávelⁿ |
538
+ | `eventos` | 1 evento interativo (audiência) | `titulo`, **`data`ᶜ**, **`hora`ᶜ**, `comissao`, **`comissaoNomeCompleto`ⁿ**, **`local`ⁿ**, **`descricao`ⁿ**, **`pauta`ⁿ**, **`convidados`ⁿ**, **`videoUrl`ⁿ**, **`comentarios`ᶜ**, `status`, `url`, `firstSeenAt` | listagem `principalaudiencia` + **detalhe** (`visualizacaoaudiencia`)ⁿ + **fragmento AJAX de comentários**ᶜ |
539
+ | **`eventos_comentarios`ⁿ** | 1 comentário (nível de comentário) | `eventoId`, `comentarioId`, `uf`, `texto`, `data`, `hora`, `momentoVideoUrl`, `convidadoAssociado` | fragmento AJAX `ajaxcolecaocomentarioaudiencia?audienciaId=` |
540
+ | `consultas_votos` | 1 matéria (acervo histórico) | `materia`, `ementa`, `autoria`, `votosSim`/`votosNao`/`totalVotos`, `votosPorUf`, `status`, `url`, `referencePeriod` | CSV do Arquimedes `Proposições-com-votos.csv` (reingerido semanalmente) |
541
+
542
+ **ⁿ = novo ou reaberto na v2 · ᶜ = fonte corrigida para a canônica na v2.** O que a v2 (`2.0.0`) mudou — a ingestão saiu de **só listagem** para **listagem + detalhe (+ comentários por AJAX nos eventos)**:
543
+
544
+ - **Eventos corrigidos e enriquecidos.** `data`/`hora` agora vêm da página de detalhe (a canônica — o [estudo A3](docs/estudo-a3-reconciliacao-eventos.md) achou a listagem divergente em 57% dos casos no `hora`), mais seis campos novos de detalhe (`comissaoNomeCompleto`, `local`, `descricao`, `pauta`, `convidados`, `videoUrl`). `comentarios` passou a ser a **contagem canônica do AJAX** (a contagem da listagem era `0` espúrio em 82% dos eventos, capturando só ~6,7% do engajamento).
545
+ - **Recurso novo em nível de comentário**, `eventos_comentarios` — uma linha por comentário de audiência, o sinal de participação que ninguém mais publica versionado.
546
+ - **Campos que só existem no detalhe foram reabertos** para `ideias` (`dataPublicacao`, `autorUf`, `descricao`, `plConvertido`) e `consultas` (`autoria`, `relator`) — antes sempre `null` por decisão de projeto.
547
+ - **Postura de privacidade pela origem do dado.** Conteúdo de cidadão (comentários de audiência, autores de ideia) guarda **apenas a UF — nunca o nome**, descartado já no parser; agente público (autoria/relatoria de consulta, convidados de evento) guarda o nome (público pela função). O racional campo a campo está em `docs/schema-v2-inventario.md` (alvo aprovado).
548
+
549
+ O NDJSON congelado **não** é commitado (é construído sob demanda a partir do corpus soberano no D1); uma release marcada `dataset-v*` anexa o tarball + `SHA256SUMS` + `release.json` e os arquiva no Zenodo.
550
+
510
551
  ## Inventário de ferramentas
511
552
 
512
553
  ### Grupo H — Referência/Metadados (1 ferramenta)
@@ -670,7 +711,24 @@ A cobertura abrange as quatro fontes upstream: **Dados Abertos Legislativo** (`l
670
711
  |------|-------------|
671
712
  | `senado_execucao_orcamentaria` | Execução orçamentária desde 2013 (dotação, empenhado/liquidado/pago) e receitas próprias desde 2012 (previsto vs. arrecadado) — agregadas por ano, ação, grupo de despesa, fonte ou origem de receita; `estatisticas=true` devolve a distribuição do conjunto (min/máx/média/mediana/percentis) + ranking top/bottom, ou um ranking de grupos por soma do `campo` via `agruparPor`, com `campo` (padrão pago / arrecadada) e `topN` |
672
713
 
673
- **Total: 67 ferramentas**
714
+ ### Grupo T — Estrutura Organizacional (1 ferramenta)
715
+
716
+ Lê um retrato embutido da árvore organizacional do Senado (varrida do portal institucional até o nível de serviço por `npm run ingest:estrutura`), porque a API de dados abertos só publica unidades até Secretaria e nunca liga uma unidade-folha ao pai dela. Unidades que o portal lista apenas por nome, sem página própria (os núcleos da CONLEG/CONORF), são capturadas como nós sintéticos a partir da listagem indentada da página. Órgãos do Congresso onde o cadastro de servidores registra lotações (CMO, CPCMS, CMMC) vêm de um complemento curado (`src/estrutura/complemento-cn.ts`, fonte pública: congressonacional.leg.br) sob uma raiz **Congresso Nacional** (`CN`) separada — nunca sob a árvore do Senado, de modo que `subordinadasA: "DGER"` os exclui e `subordinadasA: "CN"` os conta. Servidores registrados sob as pseudo-unidades situacionais "Servidores Afastados/em Trânsito - SF" são reportados à parte, como `afastadosOuEmTransito`, por `senado_servidores`.
717
+
718
+ | Ferramenta | Descrição |
719
+ |------|-------------|
720
+ | `senado_estrutura_organizacional` | Organograma resolvido para uma `unidade` (sigla como `DGER` ou nome): devolve o `caminho` (ancestrais) e todas as unidades subordinadas (`subordinadas[]` — secretarias, coordenações, serviços, núcleos — com `nivel`). Faz par com o filtro `subordinadasA` de `senado_servidores`, que conta/lista todos os servidores sob uma diretoria inteira (o servidor fica num serviço-folha, então filtrar `lotacao` pela sigla do pai devolve 0). |
721
+
722
+ ### Grupo U — Deep Research (2 ferramentas)
723
+
724
+ O [contrato Deep Research da OpenAI](#chatgpt-deep-research): as únicas duas ferramentas sem o prefixo `senado_`, porque os nomes são fixados pelo contrato. Registradas pelo mesmo shim das outras (annotations somente-leitura, `outputSchema` permissivo, telemetria por ferramenta) e servidas só em `/mcp` — o perfil curado do app do ChatGPT não as inclui. O índice (senadores em exercício + comissões ativas, ~300 documentos) é construído no primeiro uso a partir dos mesmos dois endpoints de lista que as ferramentas `senado_listar_*` leem, e mantido por 24 h.
725
+
726
+ | Ferramenta | Descrição |
727
+ |------|-------------|
728
+ | `search` | Ranqueia a consulta (linguagem natural ou palavras-chave, pt/en, sem distinguir acentos) contra senadores em exercício e comissões ativas; devolve até 10 `{ id, title, url }` — `sen:<código>` com a URL do perfil público, `com:<código>` com a página pública da comissão. Proveniência das duas listas em `structuredContent`/`_meta`. |
729
+ | `fetch` | Devolve o documento de um id vindo de `search` como `{ id, title, text, url, metadata }`: a biografia e os mandatos do senador (a mesma leitura de `senado_obter_senador`) ou o resumo e a mesa da comissão (a mesma leitura de `senado_obter_comissao`), em Markdown, com a proveniência dessa leitura. Id desconhecido → erro. |
730
+
731
+ **Total: 69 ferramentas**
674
732
 
675
733
  ### Prompts (4)
676
734
 
@@ -690,7 +748,7 @@ Documentos/tabelas de contexto estáticos (capacidade MCP `resources`), definido
690
748
  | URI | Tipo | Conteúdo |
691
749
  | --- | --- | --- |
692
750
  | `senado://guia` | markdown | Visão geral e qual ferramenta usar por objetivo. |
693
- | `senado://catalogo` | markdown | As 67 ferramentas agrupadas por domínio. |
751
+ | `senado://catalogo` | markdown | As 69 ferramentas agrupadas por domínio. |
694
752
  | `senado://glossario` | markdown | Siglas e termos do Senado (PEC, CEAPS, CCJ, RCN…). |
695
753
  | `senado://tabelas/tipos-materia` | json | Tipos de proposição (sigla/nome/descrição). |
696
754
  | `senado://tabelas/ufs` | json | As 27 unidades federativas. |
@@ -774,7 +832,7 @@ tests/ # Testes unitários Vitest espelhando src/ (parsers, c
774
832
  ## Conectando clientes MCP
775
833
 
776
834
  Este é um servidor **remoto** (Streamable HTTP, sem instalação, acesso aberto) — aponte qualquer cliente MCP para
777
- `https://senado.sidneybissoli.com/mcp`. Além das 67 ferramentas, ele expõe **prompts** (workflows prontos em pt-BR:
835
+ `https://senado.sidneybissoli.com/mcp`. Além das 69 ferramentas, ele expõe **prompts** (workflows prontos em pt-BR:
778
836
  `senado_gastos_senador`, `senado_tramitacao_materia`, `senado_votos_senador`,
779
837
  `senado_panorama_ecidadania`) e **recursos** (`senado://guia`, `senado://catalogo`,
780
838
  `senado://glossario`, `senado://tabelas/tipos-materia`, `senado://tabelas/ufs`).
@@ -1,6 +1,11 @@
1
1
  export const DEFAULT_MCP_ROUTE = "/mcp";
2
2
  export const OPENAI_APP_LEGACY_MCP_ROUTE = "/mcp/openai-app";
3
3
  export const OPENAI_APP_MCP_ROUTE = "/mcp/openai-app-v2";
4
+ // Rota privada do dono: mesma superficie COMPLETA da rota publica, outro
5
+ // endereco, e a telemetria a marca como uso proprio (ver src/instrument.ts).
6
+ // Precisa ser reconhecida aqui, senao handlerRouteForPath cai no fallback e
7
+ // o handler e montado numa rota diferente da que a requisicao pediu.
8
+ export const SELF_MCP_ROUTE = "/mcp/uso-proprio";
4
9
  export const OPENAI_APP_WIDGET_URI = "ui://senado-br-mcp/openai-app-dashboard-v2.html";
5
10
  export const OPENAI_APP_WIDGET_DOMAIN = "https://senado.sidneybissoli.com";
6
11
  const OPENAI_APP_MCP_ROUTES = new Set([OPENAI_APP_LEGACY_MCP_ROUTE, OPENAI_APP_MCP_ROUTE]);
@@ -89,7 +94,9 @@ export function mcpRouteForProfile(profile) {
89
94
  }
90
95
  export function handlerRouteForPath(pathname, profile) {
91
96
  const normalized = normalizeMcpRoute(pathname);
92
- if (OPENAI_APP_MCP_ROUTES.has(normalized) || normalized === DEFAULT_MCP_ROUTE) {
97
+ if (OPENAI_APP_MCP_ROUTES.has(normalized) ||
98
+ normalized === DEFAULT_MCP_ROUTE ||
99
+ normalized === SELF_MCP_ROUTE) {
93
100
  return pathname;
94
101
  }
95
102
  return mcpRouteForProfile(profile);
@@ -0,0 +1,168 @@
1
+ /**
2
+ * A FORMA da chamada, nunca o conteúdo dela.
3
+ *
4
+ * Por que existe. Em 10/09/2026 o painel do portfólio passou a medir erro por
5
+ * chamada e apontou cinco ferramentas quebradas, a pior delas
6
+ * `senado_reuniao_comissao`, com 74 erros em 74 chamadas. Diagnosticar custou
7
+ * vinte minutos de chamadas manuais porque a telemetria dizia QUE falhou e não
8
+ * DIZIA por quê — e a primeira hipótese (o agente escolheu a ferramenta errada,
9
+ * confundindo o singular com o plural `senado_reunioes_comissao`) estava
10
+ * ERRADA: erro de validação de esquema nem chega aqui, o SDK o responde antes
11
+ * do callback. As 74 falhas eram códigos bem-formados que não existem.
12
+ *
13
+ * Por que não gravar os argumentos. O dado que este servidor serve é público; a
14
+ * PERGUNTA não é. `senado_ceaps` com o id de um senador, repetido, é alguém
15
+ * investigando aquele senador, e o registro já guarda país e organização de
16
+ * rede. Parte dos parâmetros é texto livre (`palavraChave`), onde cabe qualquer
17
+ * coisa que a pessoa digitou. E ligar isso mudaria o que o serviço coleta sem
18
+ * mudar o que a página pública diz que ele coleta.
19
+ *
20
+ * O meio-termo: NOMES de parâmetro (que são o esquema publicado, não dado de
21
+ * ninguém) e a CLASSE do erro (vocabulário fechado, derivado da nossa própria
22
+ * mensagem). Isso separa "chamou sem o parâmetro obrigatório" de "chamou certo
23
+ * com um valor que não existe" — que é a bifurcação do conserto.
24
+ */
25
+ /**
26
+ * Classifica pela mensagem de erro, que é NOSSA. A ordem importa: "não
27
+ * encontrado" e "vazio" são mais específicos que "erro da fonte", e um 404
28
+ * casaria com os dois.
29
+ *
30
+ * O vocabulário foi ampliado depois de passar o classificador por TODAS as
31
+ * mensagens de erro do bcb e do senado (a varredura virou a guarda em
32
+ * `call-shape.test.ts`): 13 de 18 aqui e 12 de 18 lá caíam em `outro`, ou
33
+ * seja, a telemetria não responderia nada nestes dois servidores. As famílias
34
+ * que faltavam eram "Informe X ou Y", "só existe para", "desconhecido",
35
+ * "recusada", "não retornou dados" e "não publica" — nenhuma exótica; a versão
36
+ * inicial foi escrita a partir das mensagens do senado que eu já tinha lido.
37
+ */
38
+ export function classifyError(message) {
39
+ const m = message.toLowerCase();
40
+ // A fronteira de palavra vai só no INÍCIO. Os padrões são RADICAIS
41
+ // ("vazi", "obrigatóri", "indisponív") justamente porque a flexão muda o
42
+ // fim: `\bvazi\b` não casa "vazia", e foi assim que "Resposta upstream
43
+ // vazia" caiu em `fonte` na primeira versão — a palavra que casava era
44
+ // "upstream". Ordem também importa: "não encontrado" é mais específico que
45
+ // "erro da fonte", e a mensagem real do senado tem sinal das duas famílias.
46
+ // "desconhecido"/"unknown" só é sinal de contrato quando qualifica um VALOR
47
+ // que o chamador passou ("Índice de preços desconhecido: X. Aceitos: ...",
48
+ // "Unknown dimension(s) for dataflow X"). "Erro desconhecido ao consultar o
49
+ // calendário do IBGE" e "Unknown error" são o oposto — são justamente o caso
50
+ // sem classe — e a primeira versão desta ampliação os classificava como
51
+ // contrato.
52
+ const valorDesconhecido = /\b(desconhecid|unknown)/.test(m) && !/\b(erro desconhecid|unknown error)/.test(m);
53
+ if (valorDesconhecido ||
54
+ /\b(obrigatóri|obrigatori|exige|requer|required|inválid|invalid|validation error|não aceita|nao aceita|no máximo|no maximo|só existe|so existe|recusad)/.test(m) ||
55
+ // Inglês, das mensagens do ilo, do uis e do medical. `empty query` fica
56
+ // AQUI e não em nao_encontrado: consulta vazia é parâmetro que falta. Era o
57
+ // radical `empty` solto que a classificava errado — ele existia para "empty
58
+ // response", que é outra coisa, e agora está escrito por extenso lá.
59
+ // "narrow it/the query" e "maximum N per call" são instruções ao chamador:
60
+ // a resposta não veio porque a chamada precisa mudar, que é contrato.
61
+ /\b(empty query|not part of|too broad|too many|maximum|narrow (it|the|your)|has no codelist|has no enumerated)/.test(m)) {
62
+ return "contrato";
63
+ }
64
+ if (/\b(não encontrad|nao encontrad|não existe|nao existe|does ?n[o']t exist|not.?found|inexistent|vazi|empty response|empty result|returned empty|sem registros|não retornou dados|nao retornou dados|não publica|nao publica|404)/.test(m) ||
65
+ // "Nenhum evento encontrado", "nenhuma reunião", "nenhum registro": a forma
66
+ // varia com o substantivo de cada servidor, então case pelo padrão.
67
+ /\bnenhum[ao]?s?\b[\s\S]{0,40}\b(encontrad|resultado|registro|dado)/.test(m)) {
68
+ return "nao_encontrado";
69
+ }
70
+ // "Informe X ou Y" é a mensagem canônica de parâmetro que falta — dez delas
71
+ // no senado, com e sem qualificador na frente ("Para por=senador, informe
72
+ // 'codigoSenador'"). Fica DEPOIS de "não encontrado" de propósito: é o sinal
73
+ // mais fraco dos dois, e um "informe um código válido" fechando uma mensagem
74
+ // de não encontrado não pode sequestrar a classe. Hoje nenhuma mensagem dos
75
+ // quatro servidores casa com as duas famílias — a ordem existe para a
76
+ // mensagem que alguém escrever amanhã.
77
+ if (/\binforme\b/.test(m))
78
+ return "contrato";
79
+ // `\b5\d\d\b` e não `5\d\d`: sem a fronteira final, qualquer número com um 5
80
+ // seguido de dois dígitos casava — um código de reunião "591234" citado na
81
+ // mensagem virava "erro 5xx". A intenção sempre foi o status HTTP.
82
+ // A fonte falhou ou demorou. As quatro últimas vieram da fábrica de erros do
83
+ // ibge, onde caíam em `outro`: ela nomeia a falha de infraestrutura em vez de
84
+ // usar as palavras genéricas ("Tempo de resposta excedido", não "timeout";
85
+ // "Serviço em manutenção"; "Erro de conexão"). `erro interno do servidor` vai
86
+ // com o complemento, porque "erro interno" sozinho pode ser bug nosso.
87
+ if (/\b(timeout|tempo esgotado|tempo de resposta excedid|excedeu o tempo|indisponív|indisponiv|manutenç|manutenc|erro de conexão|erro de conexao|erro interno do servidor|internal server error|upstream|\b5\d\d\b|payload|too large|grande demais|limite de tamanho)/.test(m)) {
88
+ return "fonte";
89
+ }
90
+ return "outro";
91
+ }
92
+ /**
93
+ * Nomes dos parâmetros que a chamada trouxe, em ordem, separados por vírgula.
94
+ * Só os nomes de PRIMEIRO nível e só quando o argumento é objeto simples — o
95
+ * conteúdo nunca entra. Cortado em 200 caracteres porque blob do Analytics
96
+ * Engine tem teto de tamanho e um nome de parâmetro longo não vale a linha.
97
+ */
98
+ export function paramNames(args) {
99
+ const a = Array.isArray(args) ? args[0] : args;
100
+ if (!a || typeof a !== "object" || Array.isArray(a))
101
+ return "";
102
+ const nomes = Object.keys(a)
103
+ .filter((k) => a[k] !== undefined)
104
+ .sort();
105
+ return nomes.join(",").slice(0, 200);
106
+ }
107
+ /**
108
+ * Texto de erro de um resultado de tool, para classificar. Vazio quando não há.
109
+ *
110
+ * Lê o CAMPO `error` do envelope, não o payload serializado inteiro. O envelope
111
+ * padrão é `{ error, retryable, hint }`, e o `hint` de erro não recuperável
112
+ * termina com "a fonte oficial pode estar indisponível" — texto de formulário,
113
+ * igual em todos. Classificando o payload inteiro, esse "indisponível"
114
+ * arrastava TODO erro não recuperável para a classe `fonte`. Visto na produção
115
+ * do senado em 10/09/2026: a mensagem "Não existe reunião com o código X",
116
+ * que é `nao_encontrado` por definição, foi gravada como `fonte`.
117
+ */
118
+ export function errorText(result) {
119
+ if (!result || typeof result !== "object")
120
+ return "";
121
+ const r = result;
122
+ const estruturado = r.structuredContent?.error;
123
+ if (typeof estruturado === "string")
124
+ return estruturado;
125
+ const t = Array.isArray(r.content) ? r.content[0]?.text : undefined;
126
+ if (typeof t !== "string")
127
+ return "";
128
+ try {
129
+ const j = JSON.parse(t);
130
+ if (typeof j.error === "string")
131
+ return j.error;
132
+ }
133
+ catch {
134
+ // Não é o envelope JSON — vale o texto cru (é o caso de outros servidores).
135
+ }
136
+ return t;
137
+ }
138
+ /**
139
+ * Classifica uma exceção que ESCAPOU do handler, tendo o objeto do erro em mãos
140
+ * e não só a mensagem.
141
+ *
142
+ * Por que existe. Em 22/09/2026 o `ibge_cnae` respondia
143
+ * `Cannot read properties of undefined (reading 'divisao')` a um código de
144
+ * classe válido — um `TypeError` nosso, nascido de um `[]` da fonte que
145
+ * atravessou a camada de rede. Nenhum padrão de `classifyError` casa com essa
146
+ * frase, então ela caía em `outro`, que já era 13 dos 23 erros da ferramenta na
147
+ * semana. O comentário de `outro` avisava desde o início: *se esta classe
148
+ * crescer, é sinal de que falta uma classe*. Faltava esta. O conserto nasceu no
149
+ * `ibge-br-mcp` 5.1.2 e é o mesmo em toda a frota, porque a classe é a mesma.
150
+ *
151
+ * O sinal é o TIPO, não a frase, e é por isso que esta função existe separada
152
+ * de `classifyError`: `TypeError`, `RangeError`, `ReferenceError` e
153
+ * `SyntaxError` são erros de programa. A fonte não os produz — nós os
154
+ * produzimos ao supor a forma do que ela respondeu. Classificá-los por
155
+ * mensagem seria caçar o texto do motor de JS, que muda entre versões de Node.
156
+ *
157
+ * `classifyError` fica INTACTA: ela recebe mensagem e continua sendo o caminho
158
+ * do erro que NÓS escrevemos.
159
+ */
160
+ export function classifyThrown(error) {
161
+ if (error instanceof TypeError ||
162
+ error instanceof RangeError ||
163
+ error instanceof ReferenceError ||
164
+ error instanceof SyntaxError) {
165
+ return "defeito";
166
+ }
167
+ return classifyError(error instanceof Error ? error.message : String(error));
168
+ }
@@ -1,7 +1,7 @@
1
1
  export const ESTRUTURA_ORGANIZACIONAL = {
2
- "extraidoEm": "2026-08-01T08:10:35.063Z",
2
+ "extraidoEm": "2026-09-01T10:56:16.383Z",
3
3
  "fonteUrl": "https://www12.senado.leg.br/institucional/estrutura/orgaosenado",
4
- "total": 824,
4
+ "total": 823,
5
5
  "orgaos": [
6
6
  {
7
7
  "cod": -2072346465,
@@ -1947,12 +1947,6 @@ export const ESTRUTURA_ORGANIZACIONAL = {
1947
1947
  "nome": "Ouvidoria do Senado Federal",
1948
1948
  "codSuperior": null
1949
1949
  },
1950
- {
1951
- "cod": 9426,
1952
- "sigla": null,
1953
- "nome": "Assessoria Técnica da Strans",
1954
- "codSuperior": 8852
1955
- },
1956
1950
  {
1957
1951
  "cod": 9430,
1958
1952
  "sigla": null,
@@ -2217,12 +2211,6 @@ export const ESTRUTURA_ORGANIZACIONAL = {
2217
2211
  "nome": "Serviço de Atendimento Eletrônico",
2218
2212
  "codSuperior": 9600
2219
2213
  },
2220
- {
2221
- "cod": 9596,
2222
- "sigla": null,
2223
- "nome": "Serviço de Manutenção Eletromecânica",
2224
- "codSuperior": 10741
2225
- },
2226
2214
  {
2227
2215
  "cod": 9600,
2228
2216
  "sigla": null,
@@ -2457,12 +2445,6 @@ export const ESTRUTURA_ORGANIZACIONAL = {
2457
2445
  "nome": "Serviço de Pesquisa e Análise",
2458
2446
  "codSuperior": 9807
2459
2447
  },
2460
- {
2461
- "cod": 9810,
2462
- "sigla": null,
2463
- "nome": "Observatório da Mulher Contra a Violência",
2464
- "codSuperior": 9807
2465
- },
2466
2448
  {
2467
2449
  "cod": 9868,
2468
2450
  "sigla": "IFI",
@@ -4785,18 +4767,6 @@ export const ESTRUTURA_ORGANIZACIONAL = {
4785
4767
  "nome": "Serviço de Suporte aos Sistemas de Saúde",
4786
4768
  "codSuperior": 10620
4787
4769
  },
4788
- {
4789
- "cod": 10801,
4790
- "sigla": "GSBBONET",
4791
- "nome": "Gabinete do Senador Bruno Bonetti",
4792
- "codSuperior": 108
4793
- },
4794
- {
4795
- "cod": 10803,
4796
- "sigla": null,
4797
- "nome": "Escritório de Apoio Nº 01 do Senador Bruno Bonetti",
4798
- "codSuperior": 10801
4799
- },
4800
4770
  {
4801
4771
  "cod": 10806,
4802
4772
  "sigla": "GSRACIOL",
@@ -4946,6 +4916,30 @@ export const ESTRUTURA_ORGANIZACIONAL = {
4946
4916
  "sigla": null,
4947
4917
  "nome": "Coordenação do Observatório da Mulher Contra a Violência",
4948
4918
  "codSuperior": 8852
4919
+ },
4920
+ {
4921
+ "cod": 10860,
4922
+ "sigla": "GSLPEREI",
4923
+ "nome": "Gabinete da Senadora Lourdinha Pereira",
4924
+ "codSuperior": 108
4925
+ },
4926
+ {
4927
+ "cod": 10861,
4928
+ "sigla": null,
4929
+ "nome": "Escritório de Apoio Nº 01 da Senadora Lourdinha Pereira",
4930
+ "codSuperior": 10860
4931
+ },
4932
+ {
4933
+ "cod": 10862,
4934
+ "sigla": "GSSREGIN",
4935
+ "nome": "Gabinete do Senador Sargento Reginauro",
4936
+ "codSuperior": 108
4937
+ },
4938
+ {
4939
+ "cod": 10863,
4940
+ "sigla": null,
4941
+ "nome": "Escritório de Apoio Nº 01 do Senador Sargento Reginauro",
4942
+ "codSuperior": 10862
4949
4943
  }
4950
4944
  ]
4951
4945
  };