bcb-br-mcp 1.10.1 → 1.12.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 +51 -8
- package/README.pt-BR.md +123 -8
- package/dist/call-shape.d.ts +68 -0
- package/dist/call-shape.d.ts.map +1 -0
- package/dist/call-shape.js +138 -0
- package/dist/call-shape.js.map +1 -0
- package/dist/catalog.d.ts +6 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +16 -8
- package/dist/catalog.js.map +1 -1
- package/dist/deep-research.d.ts +55 -0
- package/dist/deep-research.d.ts.map +1 -0
- package/dist/deep-research.js +255 -0
- package/dist/deep-research.js.map +1 -0
- package/dist/register.d.ts +9 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +9 -5
- package/dist/register.js.map +1 -1
- package/dist/stats.d.ts +14 -8
- package/dist/stats.d.ts.map +1 -1
- package/dist/stats.js +9 -0
- package/dist/stats.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +37 -5
- package/dist/tools.js.map +1 -1
- package/dist/vocabulario.d.ts +80 -0
- package/dist/vocabulario.d.ts.map +1 -0
- package/dist/vocabulario.js +142 -0
- package/dist/vocabulario.js.map +1 -0
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Banco Central do Brasil (BCB) — SGS Time Series MCP Server
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/bcb-br-mcp)
|
|
4
4
|
[](https://www.npmjs.com/package/bcb-br-mcp)
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
[Leia em Português](README.pt-BR.md)
|
|
15
15
|
|
|
16
|
-
MCP (Model Context Protocol) server for the **Brazilian Central Bank** (Banco Central do Brasil, **BCB**) time series
|
|
16
|
+
MCP (Model Context Protocol) server for the **Brazilian Central Bank** (Banco Central do Brasil, **BCB**): **SGS** time series (SGS/BCB), the **Focus** market-expectations survey (served over the **Olinda** OData API) and **PTAX** exchange rates.
|
|
17
17
|
|
|
18
18
|
Query economic and financial indicators such as **Selic** (interest rate), **IPCA** (inflation), **exchange rates**, **GDP**, and more, directly from AI assistants like Claude.
|
|
19
19
|
|
|
20
20
|
> If you find this project useful, please consider giving it a [star on GitHub](https://github.com/SidneyBissoli/bcb-br-mcp). It helps others discover the project!
|
|
21
21
|
|
|
22
|
-
**Capabilities:**
|
|
22
|
+
**Capabilities:** 17 tools (skills) · 3 resources · 3 prompts — everything an MCP client needs to query the Brazilian Central Bank: SGS/BCB time series, the **Focus** market-expectations survey and **PTAX** exchange rates.
|
|
23
23
|
|
|
24
24
|
## See it in action
|
|
25
25
|
|
|
@@ -54,6 +54,8 @@ The answers come live from the Brazilian Central Bank's SGS API — exact figure
|
|
|
54
54
|
- **Focus survey** - Market expectations (mean, median, std. deviation, min, max, respondents) for IPCA, GDP, FX and more, by monthly/quarterly/annual horizon or rolling 12/24-month inflation, plus Selic by Copom meeting
|
|
55
55
|
- **PTAX exchange rates** - Official closing quotes for any currency the BCB publishes, single day or date range
|
|
56
56
|
|
|
57
|
+
📖 **Article (in Portuguese):** [Séries do Banco Central: como consultar o SGS, a Focus e a PTAX sem cair nas armadilhas](docs/artigo-sgs-series-do-banco-central.pt-BR.md) — the three API limits measured live, level vs. rate series, the Focus scopes, and what the ODbL requires. Also published on the site, in Portuguese and English: [sidneybissoli.com](https://sidneybissoli.com/en/blog/posts/series-banco-central/).
|
|
58
|
+
|
|
57
59
|
## Available Tools
|
|
58
60
|
|
|
59
61
|
| Tool | Description |
|
|
@@ -62,7 +64,7 @@ The answers come live from the Brazilian Central Bank's SGS API — exact figure
|
|
|
62
64
|
| `bcb_serie_ultimos` | Get the last N values of a series (any N — the upstream cap of 20 is worked around) |
|
|
63
65
|
| `bcb_serie_metadados` | Get series metadata (name, frequency, category, last value) |
|
|
64
66
|
| `bcb_series_populares` | List popular series grouped by category |
|
|
65
|
-
| `bcb_buscar_serie` | Search series by name or description (accent-insensitive) |
|
|
67
|
+
| `bcb_buscar_serie` | Search series by name or description (accent-insensitive, AND between words; everyday words resolved to the BCB's wording, and the response says so) |
|
|
66
68
|
| `bcb_indicadores_atuais` | Latest values: Selic, IPCA, USD/BRL, IBC-Br |
|
|
67
69
|
| `bcb_variacao` | Percentage variation of one series over a period: level change for level series, **compounded accumulation** for series that are already period-on-period rates (IPCA, IGP-M, INPC…); `analise.metodo` says which |
|
|
68
70
|
| `bcb_comparar` | Compare 2 to 5 series over the same period with ranking (same level/compounding rule per series, declared in `metodo`) |
|
|
@@ -71,6 +73,8 @@ The answers come live from the Brazilian Central Bank's SGS API — exact figure
|
|
|
71
73
|
| `bcb_focus_referencias` | Which indicators and reference dates the Focus survey actually publishes, **broken down per scope** (the five horizons plus `selic`, whose axis is the Copom meeting) — the indicator set differs by scope (9 monthly vs 26 annual) |
|
|
72
74
|
| `bcb_cambio_cotacao` | PTAX quote for a currency (USD by default), single day or date range |
|
|
73
75
|
| `bcb_cambio_moedas` | Currencies with quotes published by the BCB |
|
|
76
|
+
| `search` | OpenAI Deep Research contract: searches the series catalog (curated + open data portal index) and returns `{ id, title, url }` — see [ChatGPT (Deep Research)](#chatgpt-deep-research) |
|
|
77
|
+
| `fetch` | OpenAI Deep Research contract: returns one series as a readable document with its canonical public URL |
|
|
74
78
|
|
|
75
79
|
## Resources
|
|
76
80
|
|
|
@@ -146,6 +150,16 @@ npm install -g bcb-br-mcp
|
|
|
146
150
|
}
|
|
147
151
|
```
|
|
148
152
|
|
|
153
|
+
### ChatGPT (Deep Research)
|
|
154
|
+
|
|
155
|
+
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 `bcb_*` tools. Point the connector at the hosted endpoint, no key required:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
https://bcb.sidneybissoli.com/mcp
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`search` ranks the query against the series catalog — the 135 curated series plus the thousands indexed from the Open Data Portal — and returns `{ id, title, url }` (ids are `sgs:<code>`); `fetch` returns the series as readable Markdown (name, category, frequency, unit, latest value) with the canonical public URL, which is what ChatGPT cites: the dataset page on dadosabertos.bcb.gov.br when the series has one, otherwise the public SGS query for its latest observations (the SGS has no per-series page). Both carry the same provenance block as every other tool. In ChatGPT's developer mode (Settings → Security and login → Developer mode) any tool is callable — the `bcb_*` tools remain the ones to use for data.
|
|
162
|
+
|
|
149
163
|
## Usage Examples
|
|
150
164
|
|
|
151
165
|
### Get the current Selic rate
|
|
@@ -407,6 +421,22 @@ The SGS database contains over 18,000 time series. To find codes for other serie
|
|
|
407
421
|
3. Note the series code
|
|
408
422
|
4. Use that code with this server's tools
|
|
409
423
|
|
|
424
|
+
## Ask in your words, not the BCB's
|
|
425
|
+
|
|
426
|
+
`bcb_buscar_serie` matches your words, all of them (AND), against the curated catalogue (135 series: name and category) and the dataset slugs of the BCB open-data portal (3,579 series identified by code). Accents were already ignored; the word was not. Measured over both layers on 2026-09-16, fixed since 1.12.0: the everyday word is expanded to the BCB's own, and the response says so in `notasVocabulario`; zero results come with a way out.
|
|
427
|
+
|
|
428
|
+
| you ask | hits before (curated / portal) | the BCB writes | hits |
|
|
429
|
+
| --- | ---: | --- | ---: |
|
|
430
|
+
| `déficit`, `superávit` | 0 / 0 | resultado primário, resultado nominal | 1 / 26, 0 / 22 |
|
|
431
|
+
| `calote` | 0 / 0 | inadimplência | 6 / 484 |
|
|
432
|
+
| `juros básicos` | 0 / 0 | Selic | 5 / 7 |
|
|
433
|
+
| `desemprego` | 0 / 0 | desocupação | 1 / 0 |
|
|
434
|
+
| `arrecadação`, `gasto` | 0 / 0 | receita, despesa | 2 / 8, 0 / 8 |
|
|
435
|
+
| `investimento estrangeiro` | 0 / 0 | investimento direto | 1 / 12 |
|
|
436
|
+
| `conta corrente` | 0 / 0 | transações correntes | 1 / 5 |
|
|
437
|
+
|
|
438
|
+
Only measured pairs enter the table (`src/vocabulario.ts`): the word you ask with absent from both layers, the BCB's word present. What the BCB does not publish under any of these names stays out and still returns zero — `salário mínimo`, `ibovespa`, `bitcoin`, `meta de inflação` — because an alias for a series that does not exist promises what the source does not have; and `empréstimo` is not mapped to `crédito` on purpose (the portal already answers it with 45 datasets; the mapping would drown them in 2,000). The same table feeds the Deep Research `search` index.
|
|
439
|
+
|
|
410
440
|
## Technical Details
|
|
411
441
|
|
|
412
442
|
### Robustness
|
|
@@ -443,9 +473,9 @@ rounded (to 4 decimals).
|
|
|
443
473
|
|
|
444
474
|
### Smart Search
|
|
445
475
|
|
|
446
|
-
`bcb_buscar_serie` searches two layers: the curated
|
|
447
|
-
|
|
448
|
-
accent- and case-insensitive, and several terms are combined with AND:
|
|
476
|
+
`bcb_buscar_serie` searches two layers: the curated catalog of 135 verified series (which ranks first, with
|
|
477
|
+
the source of the name declared) and the index of the BCB Open Data Portal, with thousands of series
|
|
478
|
+
identified by code. Terms are accent- and case-insensitive, and several terms are combined with AND:
|
|
449
479
|
|
|
450
480
|
- `"inflacao"` → finds "Inflação"
|
|
451
481
|
- `"cambio"` → finds "Câmbio"
|
|
@@ -592,7 +622,20 @@ Contributions are welcome! Please:
|
|
|
592
622
|
|
|
593
623
|
## License
|
|
594
624
|
|
|
595
|
-
|
|
625
|
+
**Two licences, and they are not the same thing.**
|
|
626
|
+
|
|
627
|
+
- **Code:** MIT — see [LICENSE](LICENSE).
|
|
628
|
+
- **Data:** from the Banco Central do Brasil, under the **Open Data Commons Open
|
|
629
|
+
Database License (ODbL) v1.0** — https://opendatacommons.org/licenses/odbl/1-0/.
|
|
630
|
+
Not CC0, not CC BY, not public domain: the ODbL requires **attribution**, has a
|
|
631
|
+
**share-alike** clause on derived databases, and an **anti-DRM** clause.
|
|
632
|
+
|
|
633
|
+
Every successful response carries a provenance block with the source, the query URL, the data vintage, the
|
|
634
|
+
real extraction instant and the licence. Exchange-rate answers pass the BCB disclaimer through verbatim, and
|
|
635
|
+
non-USD parities are qualified as information-agency data (Refinitiv) redistributed by the BCB — not as data
|
|
636
|
+
compiled by the Central Bank.
|
|
637
|
+
|
|
638
|
+
Details and obligations in [NOTICE.md](NOTICE.md). Privacy: no user data is logged, by either channel — see [PRIVACY.md](PRIVACY.md).
|
|
596
639
|
|
|
597
640
|
## Author
|
|
598
641
|
|
package/README.pt-BR.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Banco Central do Brasil (BCB)
|
|
1
|
+
# Banco Central do Brasil (BCB) — SGS Time Series MCP Server
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/bcb-br-mcp)
|
|
4
4
|
[](https://www.npmjs.com/package/bcb-br-mcp)
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
|
|
13
13
|
[Read in English](README.md)
|
|
14
14
|
|
|
15
|
-
Servidor MCP (Model Context Protocol)
|
|
15
|
+
Servidor MCP (Model Context Protocol) do **Banco Central do Brasil** (**BCB**): séries temporais do **SGS** (SGS/BCB), a pesquisa de expectativas de mercado **Focus** (servida pela API OData **Olinda**) e as cotações de câmbio **PTAX**.
|
|
16
16
|
|
|
17
17
|
Permite consultar indicadores econômicos e financeiros como **Selic**, **IPCA**, **câmbio**, **PIB**, entre outros, diretamente em assistentes de IA como Claude.
|
|
18
18
|
|
|
19
19
|
> Se você achou este projeto útil, considere dar uma [estrela no GitHub](https://github.com/SidneyBissoli/bcb-br-mcp). Isso ajuda outras pessoas a descobrirem o projeto!
|
|
20
20
|
|
|
21
|
-
**Capacidades:**
|
|
21
|
+
**Capacidades:** 17 ferramentas (skills) · 3 recursos · 3 prompts — tudo o que um cliente MCP precisa para consultar o Banco Central do Brasil: séries temporais do SGS/BCB, a pesquisa de expectativas de mercado **Focus** e as cotações de câmbio **PTAX**.
|
|
22
22
|
|
|
23
23
|
## Veja na prática
|
|
24
24
|
|
|
@@ -27,6 +27,9 @@ Pergunte ao seu assistente, em português:
|
|
|
27
27
|
- *"Qual a taxa Selic atual?"* → `bcb_indicadores_atuais`
|
|
28
28
|
- *"Mostre o IPCA mês a mês em 2024."* → `bcb_serie_valores`
|
|
29
29
|
- *"Qual foi a variação do dólar nos últimos 12 meses?"* → `bcb_variacao`
|
|
30
|
+
- *"O que o mercado espera do IPCA em 2027?"* → `bcb_focus_expectativas`
|
|
31
|
+
- *"Qual a Selic esperada na próxima reunião do Copom?"* → `bcb_focus_selic`
|
|
32
|
+
- *"Qual foi a PTAX de fechamento do euro na sexta?"* → `bcb_cambio_cotacao`
|
|
30
33
|
|
|
31
34
|
As respostas vêm ao vivo da API SGS do Banco Central — valores exatos com procedência, não números chutados do treino.
|
|
32
35
|
|
|
@@ -47,6 +50,10 @@ As respostas vêm ao vivo da API SGS do Banco Central — valores exatos com pro
|
|
|
47
50
|
- **Cálculo de variação** - Variação percentual entre períodos com estatísticas
|
|
48
51
|
- **Comparação de séries** - Compara múltiplas séries no mesmo período, com aviso
|
|
49
52
|
quando as periodicidades diferem
|
|
53
|
+
- **Pesquisa Focus** - Expectativas de mercado (média, mediana, desvio-padrão, mínimo, máximo, número de respondentes) para IPCA, PIB, câmbio e outros, por horizonte mensal/trimestral/anual ou inflação acumulada em 12/24 meses, mais a Selic por reunião do Copom
|
|
54
|
+
- **Câmbio PTAX** - Cotações oficiais de fechamento para qualquer moeda que o BCB publique, em um dia ou num intervalo de datas
|
|
55
|
+
|
|
56
|
+
📖 **Artigo:** [Séries do Banco Central: como consultar o SGS, a Focus e a PTAX sem cair nas armadilhas](docs/artigo-sgs-series-do-banco-central.pt-BR.md) — os três limites da API medidos ao vivo, a diferença entre série de nível e série de taxa, os escopos da Focus e o que a ODbL exige. Também publicado no site: [sidneybissoli.com](https://sidneybissoli.com/blog/posts/series-banco-central/).
|
|
50
57
|
|
|
51
58
|
## Ferramentas Disponíveis
|
|
52
59
|
|
|
@@ -56,10 +63,17 @@ As respostas vêm ao vivo da API SGS do Banco Central — valores exatos com pro
|
|
|
56
63
|
| `bcb_serie_ultimos` | Obtém os últimos N valores de uma série (qualquer N — o teto de 20 da origem é contornado) |
|
|
57
64
|
| `bcb_serie_metadados` | Retorna nome, periodicidade, categoria e último valor de uma série |
|
|
58
65
|
| `bcb_series_populares` | Lista séries populares agrupadas por categoria |
|
|
59
|
-
| `bcb_buscar_serie` | Busca séries por nome ou descrição (aceita termos sem acento) |
|
|
66
|
+
| `bcb_buscar_serie` | Busca séries por nome ou descrição (aceita termos sem acento, AND entre palavras; a palavra de todo dia é traduzida para a do BCB, e a resposta diz que traduziu) |
|
|
60
67
|
| `bcb_indicadores_atuais` | Valores mais recentes: Selic, IPCA, Dólar, IBC-Br |
|
|
61
68
|
| `bcb_variacao` | Variação percentual de UMA série no período: entre as pontas para série de nível, **acumulado por encadeamento** para série que já é variação por período (IPCA, IGP-M, INPC…); `analise.metodo` diz qual |
|
|
62
69
|
| `bcb_comparar` | Compara 2 a 5 séries no mesmo período com ranking (mesma regra nível/encadeamento por série, declarada em `metodo`) |
|
|
70
|
+
| `bcb_focus_expectativas` | Expectativas da pesquisa Focus para um indicador, com o horizonte como parâmetro (mensal, trimestral, anual, inflação acumulada em 12m/24m); marcador `top5` |
|
|
71
|
+
| `bcb_focus_selic` | Expectativas Focus para a taxa Selic, por reunião do Copom (formato R1/2026) |
|
|
72
|
+
| `bcb_focus_referencias` | Quais indicadores e datas de referência a Focus de fato publica, **discriminados por escopo** (os cinco horizontes mais `selic`, cujo eixo é a reunião do Copom) — o conjunto de indicadores muda com o escopo (9 no mensal contra 26 no anual) |
|
|
73
|
+
| `bcb_cambio_cotacao` | Cotação PTAX de uma moeda (dólar por padrão), num dia ou num intervalo de datas |
|
|
74
|
+
| `bcb_cambio_moedas` | Moedas com cotação publicada pelo BCB |
|
|
75
|
+
| `search` | Contrato Deep Research da OpenAI: busca no catálogo de séries (curado + índice do portal de dados abertos) e devolve `{ id, title, url }` — ver [ChatGPT (Deep Research)](#chatgpt-deep-research) |
|
|
76
|
+
| `fetch` | Contrato Deep Research da OpenAI: devolve uma série como documento legível com a sua URL pública canônica |
|
|
63
77
|
|
|
64
78
|
## Recursos
|
|
65
79
|
|
|
@@ -92,9 +106,14 @@ Acesse [bcb-br-mcp no Smithery](https://smithery.ai/servers/sidneybissoli/bcb-br
|
|
|
92
106
|
Use o endpoint HTTP diretamente, sem instalar nada:
|
|
93
107
|
|
|
94
108
|
```
|
|
95
|
-
https://bcb.sidneybissoli.
|
|
109
|
+
https://bcb.sidneybissoli.com/mcp
|
|
96
110
|
```
|
|
97
111
|
|
|
112
|
+
O hostname antigo `https://bcb.sidneybissoli.workers.dev` continua funcionando, e a
|
|
113
|
+
rota antiga `POST /` também — cliente configurado antes de o endpoint mudar para
|
|
114
|
+
`/mcp` é reescrito de forma transparente, então nada que funcionava parou. Config
|
|
115
|
+
nova deve usar a URL acima.
|
|
116
|
+
|
|
98
117
|
### Via npx (Claude Desktop)
|
|
99
118
|
|
|
100
119
|
Adicione ao arquivo de configuração do Claude Desktop:
|
|
@@ -130,6 +149,16 @@ npm install -g bcb-br-mcp
|
|
|
130
149
|
}
|
|
131
150
|
```
|
|
132
151
|
|
|
152
|
+
### ChatGPT (Deep Research)
|
|
153
|
+
|
|
154
|
+
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 as duas, além das `bcb_*`. Aponte o conector para o endpoint hospedado, sem chave:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
https://bcb.sidneybissoli.com/mcp
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`search` ranqueia a consulta contra o catálogo de séries — as 135 curadas mais os milhares indexados do Portal de Dados Abertos — e devolve `{ id, title, url }` (os ids são `sgs:<código>`); `fetch` devolve a série em Markdown legível (nome, categoria, periodicidade, unidade, último valor) com a URL pública canônica, que é o que o ChatGPT cita: a página do dataset em dadosabertos.bcb.gov.br quando a série tem uma, senão a consulta pública do SGS às últimas observações dela (o SGS não tem página por série). As duas carregam o mesmo bloco de proveniência das demais ferramentas. No modo desenvolvedor do ChatGPT (Configurações → Segurança e login → Modo desenvolvedor) qualquer ferramenta pode ser chamada — para dados, as `bcb_*` continuam sendo as certas.
|
|
161
|
+
|
|
133
162
|
## Exemplos de Uso
|
|
134
163
|
|
|
135
164
|
### Consultar a Selic atual
|
|
@@ -391,6 +420,22 @@ O SGS possui mais de 18.000 séries temporais. Para encontrar o código de outra
|
|
|
391
420
|
3. Anote o código da série
|
|
392
421
|
4. Use esse código nas ferramentas deste servidor
|
|
393
422
|
|
|
423
|
+
## Pergunte com as suas palavras, não com as do BCB
|
|
424
|
+
|
|
425
|
+
`bcb_buscar_serie` casa as suas palavras, todas (AND), contra o catálogo curado (135 séries: nome e categoria) e os slugs dos datasets do Portal de Dados Abertos do BCB (3.579 séries identificadas por código). O acento já era ignorado; a palavra, não. Medido nas duas camadas em 16/09/2026 e consertado na 1.12.0: a palavra de todo dia é expandida para a do BCB, e a resposta diz isso em `notasVocabulario`; zero resultado vem com a saída.
|
|
426
|
+
|
|
427
|
+
| você pergunta | achava (curado / portal) | o BCB escreve | acha |
|
|
428
|
+
| --- | ---: | --- | ---: |
|
|
429
|
+
| `déficit`, `superávit` | 0 / 0 | resultado primário, resultado nominal | 1 / 26, 0 / 22 |
|
|
430
|
+
| `calote` | 0 / 0 | inadimplência | 6 / 484 |
|
|
431
|
+
| `juros básicos` | 0 / 0 | Selic | 5 / 7 |
|
|
432
|
+
| `desemprego` | 0 / 0 | desocupação | 1 / 0 |
|
|
433
|
+
| `arrecadação`, `gasto` | 0 / 0 | receita, despesa | 2 / 8, 0 / 8 |
|
|
434
|
+
| `investimento estrangeiro` | 0 / 0 | investimento direto | 1 / 12 |
|
|
435
|
+
| `conta corrente` | 0 / 0 | transações correntes | 1 / 5 |
|
|
436
|
+
|
|
437
|
+
Só entra par **medido** (`src/vocabulario.ts`): a palavra perguntada ausente das duas camadas, a palavra do BCB presente. O que o BCB não publica com nenhum desses nomes fica de fora e segue devolvendo zero — `salário mínimo`, `ibovespa`, `bitcoin`, `meta de inflação` — porque apelido para série inexistente promete o que a fonte não tem; e `empréstimo` não é mapeado para `crédito` de propósito (o portal já responde por ele com 45 datasets; o mapeamento os afogaria em 2 mil). A mesma tabela alimenta o índice de `search` (Deep Research).
|
|
438
|
+
|
|
394
439
|
## Características Técnicas
|
|
395
440
|
|
|
396
441
|
### Robustez
|
|
@@ -427,11 +472,48 @@ Valor publicado pelo BCB sai sempre verbatim; só o que é calculado é arredond
|
|
|
427
472
|
|
|
428
473
|
### Busca Inteligente
|
|
429
474
|
|
|
430
|
-
|
|
475
|
+
`bcb_buscar_serie` procura em duas camadas: o catálogo curado de 135 séries verificadas (que aparece primeiro,
|
|
476
|
+
com a origem do nome declarada) e o índice do Portal de Dados Abertos do BCB, com milhares de séries
|
|
477
|
+
identificadas por código. Os termos ignoram acento e caixa, e vários termos são combinados com E:
|
|
431
478
|
|
|
432
479
|
- `"inflacao"` → encontra "Inflação"
|
|
433
480
|
- `"cambio"` → encontra "Câmbio"
|
|
434
|
-
- `"
|
|
481
|
+
- `"ipca servicos"` → os dois termos precisam bater
|
|
482
|
+
|
|
483
|
+
O índice do portal é servido de um cache de 24 horas, renovado pela primeira busca depois que ele vence (uma
|
|
484
|
+
requisição ao portal, só metadados — códigos e nomes de série, nunca observações). Toda resposta carrega
|
|
485
|
+
`catalogo.cobertura`: o índice **não** é o SGS inteiro, então não achar uma série aqui não prova que ela não
|
|
486
|
+
existe.
|
|
487
|
+
|
|
488
|
+
### Fonte dos dados e licença
|
|
489
|
+
|
|
490
|
+
Dados obtidos do Banco Central do Brasil (SGS / Olinda-Expectativas / PTAX), publicados sob a
|
|
491
|
+
**Open Data Commons Open Database License (ODbL) v1.0** — https://opendatacommons.org/licenses/odbl/1-0/.
|
|
492
|
+
Reconferido contra a fonte em 2026-08-13: 4.259 dos 4.260 conjuntos do portal declaram
|
|
493
|
+
`license_id: "odc-odbl"`. Isso **não** é CC0, CC BY nem domínio público — a ODbL traz cláusulas de
|
|
494
|
+
atribuição, de compartilhamento nos mesmos termos (para bases derivadas) e contra DRM. As respostas de
|
|
495
|
+
câmbio repassam verbatim o próprio aviso de responsabilidade do BCB; as paridades entre moedas **não** são
|
|
496
|
+
apuradas pelo BCB — vêm de agência de informação (Refinitiv) e são redistribuídas por ele, e as ferramentas
|
|
497
|
+
dizem isso.
|
|
498
|
+
|
|
499
|
+
O código do servidor é MIT; os dados não são. Ver [NOTICE.md](NOTICE.md). Privacidade: nenhum dado de
|
|
500
|
+
usuário é registrado, por nenhum dos canais — ver [PRIVACY.md](PRIVACY.md).
|
|
501
|
+
|
|
502
|
+
### Bloco de proveniência
|
|
503
|
+
|
|
504
|
+
Toda resposta bem-sucedida carrega um bloco de proveniência (contrato do portfólio v1.0) em dois canais:
|
|
505
|
+
`structuredContent.provenance` + `attribution` (visível ao modelo) e um espelho em `_meta` sob
|
|
506
|
+
`br.com.sidneybissoli.bcb/*` (fora de banda, custo zero em tokens). Cada bloco nomeia a fonte, a URL canônica
|
|
507
|
+
que reproduz a consulta, a vintage do dado, o instante **real** da extração na origem e a licença.
|
|
508
|
+
|
|
509
|
+
Dois detalhes fáceis de errar, e que aqui estão tratados:
|
|
510
|
+
|
|
511
|
+
- **`retrieved_at` é o instante real da extração, não "agora".** O índice do portal é servido de um cache de
|
|
512
|
+
24 horas, então busca respondida do cache informa o instante em que o índice foi de fato buscado — que pode
|
|
513
|
+
ser de um dia atrás, e é a data juridicamente relevante.
|
|
514
|
+
- **Um bloco por proveniência, nunca fundidos.** `bcb_buscar_serie` separa o índice do portal do BCB do
|
|
515
|
+
catálogo curado do próprio servidor; `bcb_serie_metadados` separa a leitura ao vivo do SGS do catálogo;
|
|
516
|
+
`bcb_cambio_cotacao` separa as cotações de dólar apuradas pelo BCB das paridades vindas de agência.
|
|
435
517
|
|
|
436
518
|
## Desenvolvimento
|
|
437
519
|
|
|
@@ -453,12 +535,18 @@ npm install
|
|
|
453
535
|
npm run build
|
|
454
536
|
```
|
|
455
537
|
|
|
456
|
-
### Teste local
|
|
538
|
+
### Teste local (stdio)
|
|
457
539
|
|
|
458
540
|
```bash
|
|
459
541
|
npm run dev
|
|
460
542
|
```
|
|
461
543
|
|
|
544
|
+
### Teste local (worker HTTP)
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
npm run dev:worker
|
|
548
|
+
```
|
|
549
|
+
|
|
462
550
|
Ou use o MCP Inspector:
|
|
463
551
|
|
|
464
552
|
```bash
|
|
@@ -476,6 +564,33 @@ Este servidor utiliza a API pública do Banco Central do Brasil:
|
|
|
476
564
|
|
|
477
565
|
## Changelog
|
|
478
566
|
|
|
567
|
+
### v1.4.1
|
|
568
|
+
|
|
569
|
+
- `bcb_focus_referencias`: o parâmetro passou a ser `escopo`, não `horizonte`, e o
|
|
570
|
+
vetor da resposta é `escopos`. Os escopos são os cinco horizontes de
|
|
571
|
+
`bcb_focus_expectativas` **mais `selic`** — e `selic` não é horizonte: o eixo dele
|
|
572
|
+
é a reunião do Copom. Cada bloco nomeia a `tool` que o consome. O nome anterior
|
|
573
|
+
dava a entender que `selic` era um horizonte consultável de
|
|
574
|
+
`bcb_focus_expectativas`, e não é. Nunca foi publicado no npm com o nome antigo.
|
|
575
|
+
|
|
576
|
+
### v1.4.0
|
|
577
|
+
|
|
578
|
+
- **Três APIs sob um contrato só, de 8 para 13 ferramentas.** A pesquisa de
|
|
579
|
+
expectativas de mercado Focus (`bcb_focus_expectativas`, `bcb_focus_selic`,
|
|
580
|
+
`bcb_focus_referencias`) e o câmbio PTAX (`bcb_cambio_cotacao`,
|
|
581
|
+
`bcb_cambio_moedas`), consolidados por parâmetro em vez de espelhar os ~18
|
|
582
|
+
recursos OData da origem.
|
|
583
|
+
- **Busca de verdade.** `bcb_buscar_serie` passou a consultar o índice do Portal de
|
|
584
|
+
Dados Abertos (3.500+ séries, cache de 24 horas, só metadados) por cima do
|
|
585
|
+
catálogo curado, e a declarar a cobertura do índice em vez de afirmar que uma
|
|
586
|
+
série não existe.
|
|
587
|
+
- Cada nome de campo da Focus e da PTAX foi conferido contra a API ao vivo,
|
|
588
|
+
inclusive o recurso Top 5 da Selic, que publica os campos numa caixa diferente
|
|
589
|
+
dos outros doze.
|
|
590
|
+
- Obrigações da ODbL entregues junto com as ferramentas de câmbio: o aviso do BCB
|
|
591
|
+
é repassado verbatim, e as paridades que não envolvem o dólar são qualificadas
|
|
592
|
+
como dado de terceiro (Refinitiv) redistribuído pelo BCB.
|
|
593
|
+
|
|
479
594
|
### v1.2.0
|
|
480
595
|
|
|
481
596
|
- Endpoint HTTP via Cloudflare Workers (`https://bcb.sidneybissoli.workers.dev`)
|
|
@@ -0,0 +1,68 @@
|
|
|
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, uma delas aqui:
|
|
6
|
+
* `bcb_focus_expectativas`, com 42 erros em 116 chamadas. Diagnosticar custou vinte
|
|
7
|
+
* minutos de chamadas manuais porque a telemetria dizia QUE falhou e não DIZIA
|
|
8
|
+
* por quê. No senado, onde o mesmo campo foi ligado primeiro, uma linha
|
|
9
|
+
* respondeu o que a sonda levou meia hora para achar. Atenção a um limite que
|
|
10
|
+
* vale aqui também: erro de validação de esquema NÃO chega a esta camada — o
|
|
11
|
+
* SDK o responde antes do handler, e a chamada não é contada nem como chamada
|
|
12
|
+
* nem como erro.
|
|
13
|
+
*
|
|
14
|
+
* Por que não gravar os argumentos. O dado que este servidor serve é público; a
|
|
15
|
+
* PERGUNTA não é: o registro já guarda país e organização de rede, e parte dos
|
|
16
|
+
* parâmetros é texto livre (`indicador`, `busca`), onde cabe qualquer coisa que a
|
|
17
|
+
* 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
|
+
/** Vocabulário FECHADO. Nada aqui carrega valor vindo do usuário. */
|
|
26
|
+
export type ErrorClass =
|
|
27
|
+
/** Regra de contrato checada no código (o esquema não a expressa): parâmetro que falta, combinação proibida. */
|
|
28
|
+
"contrato"
|
|
29
|
+
/** A fonte respondeu, e respondeu que não existe: 404, vazio, sem registros. */
|
|
30
|
+
| "nao_encontrado"
|
|
31
|
+
/** A fonte falhou ou demorou: 5xx, timeout, payload grande demais. */
|
|
32
|
+
| "fonte"
|
|
33
|
+
/** Falhou por outro motivo — se esta classe crescer, é sinal de que falta uma classe. */
|
|
34
|
+
| "outro";
|
|
35
|
+
/**
|
|
36
|
+
* Classifica pela mensagem de erro, que é NOSSA. A ordem importa: "não
|
|
37
|
+
* encontrado" e "vazio" são mais específicos que "erro da fonte", e um 404
|
|
38
|
+
* casaria com os dois.
|
|
39
|
+
*
|
|
40
|
+
* O vocabulário foi ampliado depois de passar o classificador por TODAS as
|
|
41
|
+
* mensagens de erro do bcb e do senado (a varredura virou a guarda em
|
|
42
|
+
* `call-shape.test.ts`): 13 de 18 aqui e 12 de 18 lá caíam em `outro`, ou
|
|
43
|
+
* seja, a telemetria não responderia nada nestes dois servidores. As famílias
|
|
44
|
+
* que faltavam eram "Informe X ou Y", "só existe para", "desconhecido",
|
|
45
|
+
* "recusada", "não retornou dados" e "não publica" — nenhuma exótica; a versão
|
|
46
|
+
* inicial foi escrita a partir das mensagens do senado que eu já tinha lido.
|
|
47
|
+
*/
|
|
48
|
+
export declare function classifyError(message: string): ErrorClass;
|
|
49
|
+
/**
|
|
50
|
+
* Nomes dos parâmetros que a chamada trouxe, em ordem, separados por vírgula.
|
|
51
|
+
* Só os nomes de PRIMEIRO nível e só quando o argumento é objeto simples — o
|
|
52
|
+
* conteúdo nunca entra. Cortado em 200 caracteres porque blob do Analytics
|
|
53
|
+
* Engine tem teto de tamanho e um nome de parâmetro longo não vale a linha.
|
|
54
|
+
*/
|
|
55
|
+
export declare function paramNames(args: unknown): string;
|
|
56
|
+
/**
|
|
57
|
+
* Texto de erro de um resultado de tool, para classificar. Vazio quando não há.
|
|
58
|
+
*
|
|
59
|
+
* Lê o CAMPO `error` do envelope, não o payload serializado inteiro. O envelope
|
|
60
|
+
* padrão é `{ error, retryable, hint }`, e o `hint` de erro não recuperável
|
|
61
|
+
* termina com "a fonte oficial pode estar indisponível" — texto de formulário,
|
|
62
|
+
* igual em todos. Classificando o payload inteiro, esse "indisponível"
|
|
63
|
+
* arrastava TODO erro não recuperável para a classe `fonte`. Visto na produção
|
|
64
|
+
* do senado em 10/09/2026: a mensagem "Não existe reunião com o código X",
|
|
65
|
+
* que é `nao_encontrado` por definição, foi gravada como `fonte`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function errorText(result: unknown): string;
|
|
68
|
+
//# sourceMappingURL=call-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-shape.d.ts","sourceRoot":"","sources":["../src/call-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,qEAAqE;AACrE,MAAM,MAAM,UAAU;AACpB,gHAAgH;AAC9G,UAAU;AACZ,gFAAgF;GAC9E,gBAAgB;AAClB,sEAAsE;GACpE,OAAO;AACT,yFAAyF;GACvF,OAAO,CAAC;AAEZ;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAmEzD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAOhD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAcjD"}
|
|
@@ -0,0 +1,138 @@
|
|
|
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, uma delas aqui:
|
|
6
|
+
* `bcb_focus_expectativas`, com 42 erros em 116 chamadas. Diagnosticar custou vinte
|
|
7
|
+
* minutos de chamadas manuais porque a telemetria dizia QUE falhou e não DIZIA
|
|
8
|
+
* por quê. No senado, onde o mesmo campo foi ligado primeiro, uma linha
|
|
9
|
+
* respondeu o que a sonda levou meia hora para achar. Atenção a um limite que
|
|
10
|
+
* vale aqui também: erro de validação de esquema NÃO chega a esta camada — o
|
|
11
|
+
* SDK o responde antes do handler, e a chamada não é contada nem como chamada
|
|
12
|
+
* nem como erro.
|
|
13
|
+
*
|
|
14
|
+
* Por que não gravar os argumentos. O dado que este servidor serve é público; a
|
|
15
|
+
* PERGUNTA não é: o registro já guarda país e organização de rede, e parte dos
|
|
16
|
+
* parâmetros é texto livre (`indicador`, `busca`), onde cabe qualquer coisa que a
|
|
17
|
+
* 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
|
+
//# sourceMappingURL=call-shape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-shape.js","sourceRoot":"","sources":["../src/call-shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAaH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAChC,mEAAmE;IACnE,yEAAyE;IACzE,uEAAuE;IACvE,uEAAuE;IACvE,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,4EAA4E;IAC5E,6EAA6E;IAC7E,wEAAwE;IACxE,YAAY;IACZ,MAAM,iBAAiB,GACrB,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,oCAAoC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrF,IACE,iBAAiB;QACjB,wJAAwJ,CAAC,IAAI,CAC3J,CAAC,CACF;QACD,wEAAwE;QACxE,4EAA4E;QAC5E,4EAA4E;QAC5E,qEAAqE;QACrE,2EAA2E;QAC3E,sEAAsE;QACtE,+GAA+G,CAAC,IAAI,CAClH,CAAC,CACF,EACD,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IACE,gOAAgO,CAAC,IAAI,CACnO,CAAC,CACF;QACD,4EAA4E;QAC5E,oEAAoE;QACpE,oEAAoE,CAAC,IAAI,CAAC,CAAC,CAAC,EAC5E,CAAC;QACD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,4EAA4E;IAC5E,0EAA0E;IAC1E,6EAA6E;IAC7E,6EAA6E;IAC7E,4EAA4E;IAC5E,sEAAsE;IACtE,uCAAuC;IACvC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,UAAU,CAAC;IAC7C,6EAA6E;IAC7E,2EAA2E;IAC3E,mEAAmE;IACnE,6EAA6E;IAC7E,8EAA8E;IAC9E,2EAA2E;IAC3E,8EAA8E;IAC9E,uEAAuE;IACvE,IACE,kQAAkQ,CAAC,IAAI,CACrQ,CAAC,CACF,EACD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAA4B,CAAC;SACpD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAA6B,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;SAC9D,IAAI,EAAE,CAAC;IACV,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,MAAe;IACvC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,CAAC,GAAG,MAA0F,CAAC;IACrG,MAAM,WAAW,GAAG,CAAC,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC/C,IAAI,OAAO,WAAW,KAAK,QAAQ;QAAE,OAAO,WAAW,CAAC;IACxD,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAwB,CAAC;QAC/C,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;IAC9E,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/catalog.d.ts
CHANGED
|
@@ -105,9 +105,15 @@ export interface SerieEncontrada {
|
|
|
105
105
|
* série está nele, ela vem primeiro e com o nome bom, porque foi revisada à
|
|
106
106
|
* mão; o índice do portal entra depois, ordenado do slug mais curto (mais
|
|
107
107
|
* específico) para o mais longo, com desempate estável pelo código.
|
|
108
|
+
*
|
|
109
|
+
* Cada termo vira um OR das grafias que o BCB usa para ele (src/vocabulario.ts):
|
|
110
|
+
* quem escreve "deficit" ou "calote" casa "resultado primario" e
|
|
111
|
+
* "inadimplencia" em vez de receber zero calado; stopwords ("taxa DE juros")
|
|
112
|
+
* ficam fora do AND. O `notas` devolvido diz quando houve tradução.
|
|
108
113
|
*/
|
|
109
114
|
export declare function buscarSeries(termo: string, curadoria: SeriePopular[], entradas: EntradaCatalogo[] | null, limite: number): {
|
|
110
115
|
total: number;
|
|
111
116
|
series: SerieEncontrada[];
|
|
117
|
+
notas: string[];
|
|
112
118
|
};
|
|
113
119
|
//# sourceMappingURL=catalog.d.ts.map
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAGrB,eAAO,MAAM,iBAAiB,8DAA8D,CAAC;AAC7F,eAAO,MAAM,iBAAiB,4CAA4C,CAAC;AAE3E,gEAAgE;AAChE,eAAO,MAAM,eAAe,QAAsB,CAAC;AAEnD,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,iDAAiD;AACjD,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAkBvG;AAwBD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyCvG;AAID,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+EAA+E;IAC/E,MAAM,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,YAAY,EAAE,EACzB,QAAQ,EAAE,eAAe,EAAE,GAAG,IAAI,EAClC,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CA6B/D"}
|