brasil-data-mcp 0.1.0 → 0.3.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
@@ -1,12 +1,15 @@
1
1
  # brasil-data-mcp
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/brasil-data-mcp.svg)](https://www.npmjs.com/package/brasil-data-mcp)
4
+ [![npm downloads](https://img.shields.io/npm/dm/brasil-data-mcp.svg)](https://www.npmjs.com/package/brasil-data-mcp)
5
+ [![CI](https://github.com/alanpcf/brasil-data-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/alanpcf/brasil-data-mcp/actions/workflows/ci.yml)
4
6
  [![license](https://img.shields.io/npm/l/brasil-data-mcp.svg)](./LICENSE)
5
7
  [![node](https://img.shields.io/node/v/brasil-data-mcp.svg)](https://nodejs.org)
8
+ [![Glama MCP server](https://glama.ai/mcp/servers/alanpcf/brasil-data-mcp/badges/score.svg)](https://glama.ai/mcp/servers/alanpcf/brasil-data-mcp)
6
9
 
7
- > MCP server que expõe dados públicos brasileiros (CNPJ, CEP, bancos, feriados) como tools pra Claude Desktop, Claude Code, Cursor, Windsurf e qualquer cliente compatível com [Model Context Protocol](https://modelcontextprotocol.io).
10
+ > MCP server que expõe dados públicos brasileiros (CNPJ, CEP, bancos, feriados, DDD, ISBN, taxas econômicas, câmbio, corretoras CVM, estados e municípios IBGE, domínios .br) como tools pra Claude Desktop, Claude Code, Cursor, Windsurf e qualquer cliente compatível com [Model Context Protocol](https://modelcontextprotocol.io). Inclui também **prompts MCP** (workflows guiados).
8
11
  >
9
- > _MCP server exposing Brazilian public data (CNPJ, CEP, banks, holidays) as tools for Claude Desktop, Claude Code, Cursor, Windsurf and any MCP-compatible client._
12
+ > _MCP server exposing Brazilian public data (CNPJ, CEP, banks, holidays, area codes, ISBN, economic rates, exchange rates, CVM brokers, IBGE states/municipalities, .br domains) as tools for Claude Desktop, Claude Code, Cursor, Windsurf and any MCP-compatible client. Ships with MCP prompts for guided workflows._
10
13
 
11
14
  Powered by [BrasilAPI](https://brasilapi.com.br) — sem chave, sem auth, dados oficiais.
12
15
 
@@ -20,26 +23,52 @@ Conecte seu cliente de IA aos dados públicos brasileiros sem escrever uma linha
20
23
  - _"Esse CEP 01310-100 é em qual cidade?"_
21
24
  - _"Quem é o banco com código 341?"_
22
25
  - _"Quais os feriados nacionais de 2026?"_
26
+ - _"Quais cidades têm DDD 41?"_
27
+ - _"Me dá o livro do ISBN 9788532530802."_
28
+ - _"Qual a SELIC hoje?"_
29
+ - _"A corretora de CNPJ 02.332.886/0011-78 ainda tá ativa?"_
30
+ - _"Quanto fechou o dólar sexta-feira?"_
31
+ - _"Quais os municípios do Acre?"_
32
+ - _"meuprojeto.com.br tá disponível?"_
23
33
 
24
34
  O Claude (ou outro cliente MCP) chama a tool, retorna o JSON estruturado, e você lê a resposta em português direto na conversa.
25
35
 
26
- ### Tools disponíveis
27
-
28
- | Tool | O que faz |
29
- | --------------------- | ------------------------------------------------------------------------------- |
30
- | `consultar_cnpj` | Dados cadastrais de empresa: razão social, situação, endereço, sócios, CNAE |
31
- | `consultar_cep` | Endereço completo a partir de CEP (logradouro, bairro, cidade, UF, coordenadas) |
32
- | `consultar_banco` | Nome e ISPB de banco brasileiro pelo código COMPE (ex: 341 = Itaú, 260 = Nubank) |
33
- | `listar_bancos` | Lista completa de bancos brasileiros cadastrados no BACEN (~250 instituições) |
34
- | `consultar_feriados` | Feriados nacionais de um ano (datas, nome, tipo) — inclui Carnaval e Páscoa |
36
+ ### Tools disponíveis (15)
37
+
38
+ | Tool | O que faz |
39
+ | ---------------------- | ---------------------------------------------------------------------------------- |
40
+ | `consultar_cnpj` | Dados cadastrais de empresa: razão social, situação, endereço, sócios, CNAE |
41
+ | `consultar_cep` | Endereço completo a partir de CEP (logradouro, bairro, cidade, UF, coordenadas) |
42
+ | `consultar_banco` | Nome e ISPB de banco brasileiro pelo código COMPE (ex: 341 = Itaú, 260 = Nubank) |
43
+ | `listar_bancos` | Lista completa de bancos brasileiros cadastrados no BACEN (~250 instituições) |
44
+ | `consultar_feriados` | Feriados nacionais de um ano (datas, nome, tipo) — inclui Carnaval e Páscoa |
45
+ | `consultar_ddd` | Estado e cidades atendidas por um código DDD (ex: 11 = SP capital + região metro) |
46
+ | `consultar_isbn` | Metadados de livro pelo ISBN-10/13 (título, autor, editora, ano, idioma, páginas) |
47
+ | `consultar_taxa` | Valor atual de taxa econômica (SELIC, CDI, IPCA) em % ao ano |
48
+ | `listar_taxas` | Panorama com todas as taxas econômicas vigentes |
49
+ | `consultar_corretora` | Dados cadastrais de corretora de valores autorizada pela CVM (status, endereço) |
50
+ | `consultar_cambio` | Cotação de câmbio (USD, EUR, +8 moedas) em BRL por data — boletins PTAX/BACEN |
51
+ | `listar_moedas` | Moedas estrangeiras com cotação disponível (símbolo, nome, tipo) |
52
+ | `listar_estados` | As 27 UFs com código IBGE, nome, região e capital |
53
+ | `consultar_municipios` | Municípios de uma UF com nome e código IBGE de 7 dígitos |
54
+ | `consultar_dominio_br` | Disponibilidade/status de domínio .br no registro.br (DNS, expiração, sugestões) |
55
+
56
+ ### Prompts disponíveis (2)
57
+
58
+ Prompts MCP são **workflows guiados** que aparecem como atalho no Claude Desktop. Você seleciona, preenche o argumento e o LLM segue o roteiro pré-definido (chama tools, interpreta, responde).
59
+
60
+ | Prompt | O que faz |
61
+ | -------------------- | ---------------------------------------------------------------------------------------- |
62
+ | `analise-cnpj` | Recebe um CNPJ, consulta na Receita e produz análise estruturada (setor, idade, porte) |
63
+ | `panorama-economico` | Combina taxas vigentes + próximos feriados nacionais em um snapshot conciso |
35
64
 
36
65
  ---
37
66
 
38
67
  ## 🇺🇸 EN — What is it?
39
68
 
40
- Plug your AI client into Brazilian public data with zero code. Ask in natural language and the LLM picks the right tool, calls it, and answers you with structured data from official sources (Receita Federal, ViaCEP, BACEN).
69
+ Plug your AI client into Brazilian public data with zero code. Ask in natural language and the LLM picks the right tool, calls it, and answers you with structured data from official sources (Receita Federal, ViaCEP, BACEN, CVM, BrasilAPI).
41
70
 
42
- Currently ships with `consultar_cnpj`. CEP, banks and holidays are landing next.
71
+ 15 tools covering CNPJ, CEP, banks, holidays, area codes (DDD), ISBN, economic rates (SELIC/CDI/IPCA), exchange rates (PTAX/BACEN), CVM brokers, IBGE states and municipalities, and .br domain availability — plus 2 MCP prompts (`analise-cnpj`, `panorama-economico`) for guided workflows.
43
72
 
44
73
  ---
45
74
 
@@ -122,8 +151,10 @@ Pra apontar seu cliente MCP pro build local em vez do pacote do npm:
122
151
 
123
152
  - [x] **Fase 1** — Esqueleto + cliente HTTP + `consultar_cnpj`
124
153
  - [x] **Fase 2** — `consultar_cep`, `consultar_banco`, `listar_bancos`, `consultar_feriados` + testes Vitest
125
- - [ ] **Fase 3** — CI (GitHub Actions), CONTRIBUTING.md, cobertura > 80%, publicação no npm
126
- - [ ] **Fase 4** — FIPE, DDD, ISBN, taxas (SELIC/CDI/IPCA), CVM, MCP prompts pra workflows
154
+ - [x] **Fase 3** — CI (GitHub Actions), `CONTRIBUTING.md`, cobertura 94%/85%, publicação no [npm](https://www.npmjs.com/package/brasil-data-mcp), listagem no [Glama](https://glama.ai/mcp/servers/alanpcf/brasil-data-mcp)
155
+ - [x] **Fase 4 (v0.2.0)** — `consultar_ddd`, `consultar_isbn`, `consultar_taxa` + `listar_taxas`, `consultar_corretora` (CVM) + MCP prompts (`analise-cnpj`, `panorama-economico`)
156
+ - [x] **Fase 5 (v0.3.0)** — `consultar_cambio` + `listar_moedas` (PTAX/BACEN), `listar_estados` + `consultar_municipios` (IBGE), `consultar_dominio_br` (registro.br); versão single-source; registry declarativo de tools; testes do caminho de retry
157
+ - [ ] **Próximo** — FIPE (aguardando upstream estabilizar, [BrasilAPI#805](https://github.com/BrasilAPI/BrasilAPI/issues/805)); Trusted Publishing (npm OIDC); mais prompts conforme demanda
127
158
 
128
159
  ---
129
160
 
@@ -141,7 +172,7 @@ Se você é dev brasileiro e usa LLM no dia a dia, esse server é pra você.
141
172
 
142
173
  Issues e PRs muito bem-vindos. Pra adicionar uma tool nova, siga o padrão de `src/tools/cnpj.ts` (schema Zod + descrição + handler) e registre em `src/index.ts`.
143
174
 
144
- Guia detalhado em `CONTRIBUTING.md` _(em breve)_.
175
+ Guia detalhado em [CONTRIBUTING.md](./CONTRIBUTING.md).
145
176
 
146
177
  ---
147
178
 
package/dist/index.d.ts CHANGED
@@ -6,17 +6,18 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
6
  *
7
7
  * Boot:
8
8
  * 1. Cria um McpServer (high-level API do SDK 1.x).
9
- * 2. Registra cada tool via registerTool — o SDK deriva o JSON Schema do
9
+ * 2. Registra cada tool do array TOOLS — o SDK deriva o JSON Schema do
10
10
  * schema Zod, então atendemos "validação dupla" (Zod runtime + JSON
11
11
  * Schema na definição) com uma única declaração por tool.
12
- * 3. Conecta no StdioServerTransport e fica em loop atendendo requisições.
12
+ * 3. Registra prompts (workflows) via registerPrompt.
13
+ * 4. Conecta no StdioServerTransport e fica em loop atendendo requisições.
13
14
  *
14
15
  * REGRA CRÍTICA: nunca escrever em stdout fora do protocolo. Logs em stderr
15
16
  * via console.error. console.log corrompe o canal MCP.
16
17
  *
17
- * REGISTRY: adicionar tool nova = uma chamada de registerTool. O helper
18
- * wrapHandler aplica o try/catch defensivo padronizado (bug numa tool não
19
- * derruba o server).
18
+ * REGISTRY: adicionar tool nova = uma entrada no array TOOLS. O loop de
19
+ * registro aplica o wrapHandler (try/catch defensivo padronizado bug numa
20
+ * tool não derruba o server) uniformemente, sem risco de esquecer.
20
21
  */
21
22
 
22
23
  declare function createServer(): McpServer;
package/dist/index.js CHANGED
@@ -4,15 +4,108 @@
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
 
7
- // src/tools/banco.ts
7
+ // src/prompts/analise-cnpj.ts
8
8
  import { z } from "zod";
9
+ var analiseCnpjArgsSchema = {
10
+ cnpj: z.string().describe(
11
+ "CNPJ da empresa a analisar (com ou sem m\xE1scara). Ex: 33.000.167/0001-01"
12
+ )
13
+ };
14
+ var analiseCnpjPrompt = {
15
+ name: "analise-cnpj",
16
+ title: "Analisar empresa por CNPJ",
17
+ description: "Workflow guiado: consulta os dados cadastrais do CNPJ na Receita Federal e produz uma an\xE1lise interpretada \u2014 setor de atua\xE7\xE3o (CNAE principal), idade da empresa, situa\xE7\xE3o cadastral, porte, quadro societ\xE1rio e observa\xE7\xF5es relevantes.",
18
+ argsSchema: analiseCnpjArgsSchema
19
+ };
20
+ function analiseCnpjHandler(args) {
21
+ const cnpj = args.cnpj.trim();
22
+ return {
23
+ messages: [
24
+ {
25
+ role: "user",
26
+ content: {
27
+ type: "text",
28
+ text: [
29
+ `Fa\xE7a uma an\xE1lise completa da empresa de CNPJ ${cnpj}.`,
30
+ "",
31
+ "Passos:",
32
+ `1. Chame a tool consultar_cnpj com o CNPJ ${cnpj}.`,
33
+ "2. Com base nos dados retornados, produza uma an\xE1lise estruturada cobrindo:",
34
+ " - **Identifica\xE7\xE3o**: raz\xE3o social, nome fantasia.",
35
+ " - **Situa\xE7\xE3o cadastral**: ativa/baixada/suspensa, motivo se aplic\xE1vel, data.",
36
+ " - **Idade**: anos desde a abertura (calcule a partir da data de in\xEDcio).",
37
+ " - **Porte**: MEI/ME/EPP/Demais, capital social.",
38
+ " - **Atividade**: CNAE principal traduzido em linguagem simples + secund\xE1rios relevantes.",
39
+ " - **Localiza\xE7\xE3o**: cidade/UF.",
40
+ " - **Quadro societ\xE1rio (QSA)**: n\xFAmero de s\xF3cios, principais.",
41
+ " - **Observa\xE7\xF5es**: empresa Simples Nacional? MEI? Algo que chame aten\xE7\xE3o (situa\xE7\xE3o irregular, idade incomum, atividade restrita)?",
42
+ "",
43
+ "Seja objetivo. N\xE3o recomende decis\xF5es de neg\xF3cio \u2014 s\xF3 apresente os fatos extra\xEDdos."
44
+ ].join("\n")
45
+ }
46
+ }
47
+ ]
48
+ };
49
+ }
50
+
51
+ // src/prompts/panorama-economico.ts
52
+ var panoramaEconomicoPrompt = {
53
+ name: "panorama-economico",
54
+ title: "Panorama econ\xF4mico e de feriados",
55
+ description: "Workflow guiado: lista as taxas econ\xF4micas atuais (SELIC, CDI, IPCA) e os feriados nacionais do ano corrente, e produz um resumo conciso \xFAtil pra planejamento de curto prazo (pr\xF3ximos feriados, juros vigentes)."
56
+ // argsSchema omitido = prompt sem argumentos.
57
+ };
58
+ function panoramaEconomicoHandler() {
59
+ const anoCorrente = (/* @__PURE__ */ new Date()).getFullYear();
60
+ return {
61
+ messages: [
62
+ {
63
+ role: "user",
64
+ content: {
65
+ type: "text",
66
+ text: [
67
+ "Monte um panorama econ\xF4mico e de calend\xE1rio do Brasil no momento.",
68
+ "",
69
+ "Passos:",
70
+ "1. Chame a tool listar_taxas pra obter SELIC, CDI e IPCA atuais.",
71
+ `2. Chame a tool consultar_feriados com ano=${anoCorrente}.`,
72
+ "3. Produza um resumo curto cobrindo:",
73
+ " - **Taxas vigentes**: SELIC, CDI, IPCA (% ao ano), com uma frase de contexto cada (ex: 'SELIC \xE9 a taxa b\xE1sica de juros').",
74
+ " - **Pr\xF3ximos feriados**: a partir de hoje, liste os 3-5 pr\xF3ximos feriados nacionais com data e dia da semana.",
75
+ " - **Pontes em vista**: aponte feriados que caem em ter\xE7a/quinta (potencial emenda).",
76
+ "",
77
+ "Seja conciso. N\xE3o d\xEA recomenda\xE7\xE3o de investimento."
78
+ ].join("\n")
79
+ }
80
+ }
81
+ ]
82
+ };
83
+ }
84
+
85
+ // src/tools/banco.ts
86
+ import { z as z2 } from "zod";
87
+
88
+ // src/version.ts
89
+ import { readFileSync } from "fs";
90
+ function lerVersao() {
91
+ try {
92
+ const raw = readFileSync(
93
+ new URL("../package.json", import.meta.url),
94
+ "utf-8"
95
+ );
96
+ return JSON.parse(raw).version ?? "0.0.0";
97
+ } catch {
98
+ return "0.0.0";
99
+ }
100
+ }
101
+ var VERSION = lerVersao();
9
102
 
10
103
  // src/clients/brasilapi.ts
11
104
  var BASE_URL = "https://brasilapi.com.br/api";
12
105
  var DEFAULT_TIMEOUT_MS = 1e4;
13
106
  var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
14
107
  var MAX_RETRIES = 3;
15
- var USER_AGENT = "brasil-data-mcp/0.1.0 (+https://github.com/alanpcf/brasil-data-mcp)";
108
+ var USER_AGENT = `brasil-data-mcp/${VERSION} (+https://github.com/alanpcf/brasil-data-mcp)`;
16
109
  var BrasilApiError = class extends Error {
17
110
  constructor(message, status, path, body) {
18
111
  super(message);
@@ -136,8 +229,8 @@ function traduzirErroBrasilApi(err, mapa) {
136
229
  }
137
230
 
138
231
  // src/tools/banco.ts
139
- var consultarBancoSchema = z.object({
140
- codigo: z.union([z.string(), z.number()]).describe(
232
+ var consultarBancoSchema = z2.object({
233
+ codigo: z2.union([z2.string(), z2.number()]).describe(
141
234
  "C\xF3digo COMPE/Febraban do banco (1 a 4 d\xEDgitos). Aceita string ou n\xFAmero. Ex: 341 (Ita\xFA), 260 (Nubank), 237 (Bradesco)."
142
235
  )
143
236
  });
@@ -192,7 +285,7 @@ async function consultarBancoHandler(input) {
192
285
  };
193
286
  }
194
287
  }
195
- var listarBancosSchema = z.object({});
288
+ var listarBancosSchema = z2.object({});
196
289
  var listarBancosTool = {
197
290
  name: "listar_bancos",
198
291
  description: [
@@ -230,10 +323,174 @@ async function listarBancosHandler(_input) {
230
323
  }
231
324
  }
232
325
 
326
+ // src/tools/cambio.ts
327
+ import { z as z3 } from "zod";
328
+ var MOEDAS_VALIDAS = /* @__PURE__ */ new Set([
329
+ "AUD",
330
+ "CAD",
331
+ "CHF",
332
+ "DKK",
333
+ "EUR",
334
+ "GBP",
335
+ "JPY",
336
+ "NOK",
337
+ "SEK",
338
+ "USD"
339
+ ]);
340
+ function hojeSaoPaulo() {
341
+ return new Intl.DateTimeFormat("en-CA", {
342
+ timeZone: "America/Sao_Paulo"
343
+ }).format(/* @__PURE__ */ new Date());
344
+ }
345
+ function diaAnterior(iso) {
346
+ const d = /* @__PURE__ */ new Date(`${iso}T12:00:00Z`);
347
+ d.setUTCDate(d.getUTCDate() - 1);
348
+ return d.toISOString().slice(0, 10);
349
+ }
350
+ function normalizarData(entrada) {
351
+ const s = entrada.trim();
352
+ let iso;
353
+ const brasileira = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(s);
354
+ if (brasileira) {
355
+ iso = `${brasileira[3]}-${brasileira[2]}-${brasileira[1]}`;
356
+ } else if (/^\d{4}-\d{2}-\d{2}$/.test(s)) {
357
+ iso = s;
358
+ } else {
359
+ return null;
360
+ }
361
+ const d = /* @__PURE__ */ new Date(`${iso}T12:00:00Z`);
362
+ if (Number.isNaN(d.getTime()) || d.toISOString().slice(0, 10) !== iso) {
363
+ return null;
364
+ }
365
+ return iso;
366
+ }
367
+ var consultarCambioSchema = z3.object({
368
+ moeda: z3.string().describe(
369
+ "C\xF3digo da moeda (ISO 4217), case-insensitive. Aceitas: USD, EUR, GBP, JPY, CHF, CAD, AUD, DKK, NOK, SEK. Ex: 'USD'."
370
+ ),
371
+ data: z3.string().optional().describe(
372
+ "Data da cota\xE7\xE3o no formato YYYY-MM-DD (aceita tamb\xE9m DD/MM/YYYY). Se omitida, usa ontem (fuso de Bras\xEDlia) \u2014 a fonte n\xE3o exp\xF5e o dia corrente. Em data sem preg\xE3o (fim de semana, feriado) a API retorna as cota\xE7\xF5es do \xFAltimo dia \xFAtil anterior."
373
+ )
374
+ });
375
+ var consultarCambioTool = {
376
+ name: "consultar_cambio",
377
+ description: [
378
+ "Consulta a cota\xE7\xE3o de c\xE2mbio oficial de uma moeda estrangeira em rela\xE7\xE3o ao Real (BRL) numa data, via boletins PTAX do Banco Central (BrasilAPI).",
379
+ "",
380
+ "Retorna em JSON os boletins do dia (ABERTURA, INTERMEDI\xC1RIO, FECHAMENTO) com cota\xE7\xE3o de compra e venda em BRL, paridade e data_hora_cotacao. A fonte N\xC3O exp\xF5e o dia corrente: com data omitida a tool consulta ontem (a cota\xE7\xE3o mais recente dispon\xEDvel), e em data sem preg\xE3o a API retorna os boletins do \xFAltimo dia \xFAtil anterior.",
381
+ "",
382
+ "Use quando o usu\xE1rio perguntar 'quanto t\xE1 o d\xF3lar?' (retorna a cota\xE7\xE3o mais recente, do dia \xFAtil anterior), 'cota\xE7\xE3o do euro em 26/06', 'quanto fechou a libra sexta-feira' \u2014 qualquer pergunta sobre valor de moeda estrangeira em reais.",
383
+ "",
384
+ "N\xC3O use para: criptomoedas (n\xE3o est\xE1 nesta API), BRL (\xE9 a moeda base), s\xE9rie hist\xF3rica (uma data por chamada), ou moedas fora das 10 suportadas \u2014 pra descobrir as moedas dispon\xEDveis use listar_moedas."
385
+ ].join(" "),
386
+ inputSchema: consultarCambioSchema
387
+ };
388
+ async function consultarCambioHandler(input) {
389
+ const moeda = input.moeda.trim().toUpperCase();
390
+ if (!MOEDAS_VALIDAS.has(moeda)) {
391
+ return {
392
+ content: [
393
+ {
394
+ type: "text",
395
+ text: `Moeda n\xE3o suportada: '${input.moeda}'. Use uma de: ${[...MOEDAS_VALIDAS].join(", ")}.`
396
+ }
397
+ ],
398
+ isError: true
399
+ };
400
+ }
401
+ const hoje = hojeSaoPaulo();
402
+ const ontem = diaAnterior(hoje);
403
+ let data;
404
+ if (input.data === void 0) {
405
+ data = ontem;
406
+ } else {
407
+ const normalizada = normalizarData(input.data);
408
+ if (normalizada === null) {
409
+ return {
410
+ content: [
411
+ {
412
+ type: "text",
413
+ text: `Data inv\xE1lida: '${input.data}'. Use o formato YYYY-MM-DD (ex: ${ontem}) ou DD/MM/YYYY.`
414
+ }
415
+ ],
416
+ isError: true
417
+ };
418
+ }
419
+ data = normalizada;
420
+ }
421
+ if (data >= hoje) {
422
+ return {
423
+ content: [
424
+ {
425
+ type: "text",
426
+ text: `A fonte n\xE3o fornece cota\xE7\xE3o do dia corrente nem de datas futuras ('${data}'). A cota\xE7\xE3o mais recente dispon\xEDvel \xE9 a de ${ontem} \u2014 omita 'data' pra us\xE1-la.`
427
+ }
428
+ ],
429
+ isError: true
430
+ };
431
+ }
432
+ try {
433
+ const dados = await brasilApi.get(
434
+ `/cambio/v1/cotacao/${moeda}/${data}`
435
+ );
436
+ return {
437
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
438
+ };
439
+ } catch (err) {
440
+ return {
441
+ content: [
442
+ {
443
+ type: "text",
444
+ text: traduzirErroBrasilApi(err, {
445
+ notFound: `Cota\xE7\xE3o de ${moeda} n\xE3o encontrada para ${data}.`,
446
+ contextoErro: "Erro ao consultar c\xE2mbio"
447
+ })
448
+ }
449
+ ],
450
+ isError: true
451
+ };
452
+ }
453
+ }
454
+ var listarMoedasSchema = z3.object({});
455
+ var listarMoedasTool = {
456
+ name: "listar_moedas",
457
+ description: [
458
+ "Lista as moedas estrangeiras com cota\xE7\xE3o dispon\xEDvel na BrasilAPI (boletins PTAX/BACEN).",
459
+ "",
460
+ "Retorna em JSON um array com s\xEDmbolo (ISO 4217), nome e tipo de cada moeda \u2014 10 moedas: USD, EUR, GBP, JPY, CHF, CAD, AUD, DKK, NOK, SEK.",
461
+ "",
462
+ "Use quando o usu\xE1rio quiser saber quais moedas t\xEAm cota\xE7\xE3o dispon\xEDvel ou n\xE3o souber o c\xF3digo da moeda.",
463
+ "",
464
+ "N\xC3O use para obter a cota\xE7\xE3o em si \u2014 use consultar_cambio."
465
+ ].join(" "),
466
+ inputSchema: listarMoedasSchema
467
+ };
468
+ async function listarMoedasHandler(_input) {
469
+ try {
470
+ const dados = await brasilApi.get("/cambio/v1/moedas");
471
+ return {
472
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
473
+ };
474
+ } catch (err) {
475
+ return {
476
+ content: [
477
+ {
478
+ type: "text",
479
+ text: traduzirErroBrasilApi(err, {
480
+ notFound: "Lista de moedas n\xE3o dispon\xEDvel no momento.",
481
+ contextoErro: "Erro ao listar moedas"
482
+ })
483
+ }
484
+ ],
485
+ isError: true
486
+ };
487
+ }
488
+ }
489
+
233
490
  // src/tools/cep.ts
234
- import { z as z2 } from "zod";
235
- var consultarCepSchema = z2.object({
236
- cep: z2.string().describe(
491
+ import { z as z4 } from "zod";
492
+ var consultarCepSchema = z4.object({
493
+ cep: z4.string().describe(
237
494
  "CEP brasileiro com ou sem h\xEDfen. Aceita '01310-100' ou '01310100'. Deve ter 8 d\xEDgitos."
238
495
  )
239
496
  });
@@ -293,9 +550,21 @@ async function consultarCepHandler(input) {
293
550
  }
294
551
 
295
552
  // src/tools/cnpj.ts
296
- import { z as z3 } from "zod";
297
- var consultarCnpjSchema = z3.object({
298
- cnpj: z3.string().describe(
553
+ import { z as z5 } from "zod";
554
+
555
+ // src/utils/cnpj.ts
556
+ function limparCnpj(s) {
557
+ return s.replace(/\D/g, "");
558
+ }
559
+ function validarCnpj(s) {
560
+ if (!/^\d{14}$/.test(s)) return false;
561
+ if (/^(\d)\1{13}$/.test(s)) return false;
562
+ return true;
563
+ }
564
+
565
+ // src/tools/cnpj.ts
566
+ var consultarCnpjSchema = z5.object({
567
+ cnpj: z5.string().describe(
299
568
  "CNPJ da empresa, com ou sem m\xE1scara. Aceita '12.345.678/0001-90' ou '12345678000190'. Deve ter 14 d\xEDgitos."
300
569
  )
301
570
  });
@@ -317,14 +586,6 @@ var consultarCnpjTool = {
317
586
  ].join(" "),
318
587
  inputSchema: consultarCnpjSchema
319
588
  };
320
- function limparCnpj(s) {
321
- return s.replace(/\D/g, "");
322
- }
323
- function validarCnpj(s) {
324
- if (!/^\d{14}$/.test(s)) return false;
325
- if (/^(\d)\1{13}$/.test(s)) return false;
326
- return true;
327
- }
328
589
  async function consultarCnpjHandler(input) {
329
590
  const cnpjLimpo = limparCnpj(input.cnpj);
330
591
  if (!validarCnpj(cnpjLimpo)) {
@@ -366,10 +627,191 @@ async function consultarCnpjHandler(input) {
366
627
  }
367
628
  }
368
629
 
630
+ // src/tools/corretoras.ts
631
+ import { z as z6 } from "zod";
632
+ var consultarCorretoraSchema = z6.object({
633
+ cnpj: z6.string().describe(
634
+ "CNPJ da corretora, com ou sem m\xE1scara. 14 d\xEDgitos. Ex: '02.332.886/0011-78' (XP Investimentos)."
635
+ )
636
+ });
637
+ var consultarCorretoraTool = {
638
+ name: "consultar_corretora",
639
+ description: [
640
+ "Consulta dados cadastrais de uma corretora de valores autorizada pela CVM (Comiss\xE3o de Valores Mobili\xE1rios) via BrasilAPI.",
641
+ "",
642
+ "Retorna em JSON: CNPJ, nome social, nome comercial, status (em funcionamento, cancelada, etc), endere\xE7o completo, e-mail, telefone, data de in\xEDcio e patrim\xF4nio quando dispon\xEDvel.",
643
+ "",
644
+ "Use quando o usu\xE1rio fornecer um CNPJ e quiser saber se \xE9 uma corretora autorizada pela CVM, ou puxar os dados cadastrais.",
645
+ "",
646
+ "N\xC3O use para: empresas em geral (use consultar_cnpj), corretoras de seguros (CVM s\xF3 regula valores mobili\xE1rios), ou buscar por nome (a API s\xF3 aceita CNPJ)."
647
+ ].join(" "),
648
+ inputSchema: consultarCorretoraSchema
649
+ };
650
+ async function consultarCorretoraHandler(input) {
651
+ const cnpjLimpo = limparCnpj(input.cnpj);
652
+ if (!validarCnpj(cnpjLimpo)) {
653
+ return {
654
+ content: [
655
+ {
656
+ type: "text",
657
+ text: `CNPJ inv\xE1lido: '${input.cnpj}'. Deve conter 14 d\xEDgitos (com ou sem m\xE1scara) e n\xE3o pode ser uma sequ\xEAncia repetida.`
658
+ }
659
+ ],
660
+ isError: true
661
+ };
662
+ }
663
+ try {
664
+ const dados = await brasilApi.get(
665
+ `/cvm/corretoras/v1/${cnpjLimpo}`
666
+ );
667
+ return {
668
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
669
+ };
670
+ } catch (err) {
671
+ return {
672
+ content: [
673
+ {
674
+ type: "text",
675
+ text: traduzirErroBrasilApi(err, {
676
+ notFound: `Corretora com CNPJ ${cnpjLimpo} n\xE3o encontrada no cadastro da CVM. Verifique se est\xE1 correto \u2014 s\xF3 corretoras de valores mobili\xE1rios autorizadas pela CVM aparecem aqui.`,
677
+ contextoErro: "Erro ao consultar corretora"
678
+ })
679
+ }
680
+ ],
681
+ isError: true
682
+ };
683
+ }
684
+ }
685
+
686
+ // src/tools/ddd.ts
687
+ import { z as z7 } from "zod";
688
+ var consultarDddSchema = z7.object({
689
+ ddd: z7.union([z7.string(), z7.number()]).describe(
690
+ "C\xF3digo DDD brasileiro (2 d\xEDgitos). Aceita string ou n\xFAmero. Ex: 11 (S\xE3o Paulo capital), 21 (Rio), 41 (Curitiba), 71 (Salvador)."
691
+ )
692
+ });
693
+ var consultarDddTool = {
694
+ name: "consultar_ddd",
695
+ description: [
696
+ "Lista as cidades atendidas por um c\xF3digo DDD brasileiro via BrasilAPI.",
697
+ "",
698
+ "Retorna em JSON: estado (UF) e lista de cidades que usam aquele DDD.",
699
+ "",
700
+ "Use quando o usu\xE1rio perguntar de onde \xE9 um DDD, quais cidades um DDD cobre, ou descobrir o estado de um n\xFAmero de telefone.",
701
+ "",
702
+ "N\xC3O use para: validar n\xFAmero de telefone completo, descobrir DDD a partir de cidade (a opera\xE7\xE3o s\xF3 \xE9 DDD \u2192 cidades), ou consultar DDDs internacionais."
703
+ ].join(" "),
704
+ inputSchema: consultarDddSchema
705
+ };
706
+ function normalizarDdd(ddd) {
707
+ const s = String(ddd).trim().replace(/\D/g, "");
708
+ if (!/^[1-9]\d$/.test(s)) return "";
709
+ return s;
710
+ }
711
+ async function consultarDddHandler(input) {
712
+ const ddd = normalizarDdd(input.ddd);
713
+ if (!ddd) {
714
+ return {
715
+ content: [
716
+ {
717
+ type: "text",
718
+ text: `DDD inv\xE1lido: '${input.ddd}'. Deve ter 2 d\xEDgitos, primeiro entre 1 e 9 (ex: 11, 21, 41).`
719
+ }
720
+ ],
721
+ isError: true
722
+ };
723
+ }
724
+ try {
725
+ const dados = await brasilApi.get(`/ddd/v1/${ddd}`);
726
+ return {
727
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
728
+ };
729
+ } catch (err) {
730
+ return {
731
+ content: [
732
+ {
733
+ type: "text",
734
+ text: traduzirErroBrasilApi(err, {
735
+ notFound: `DDD ${ddd} n\xE3o encontrado no plano de numera\xE7\xE3o brasileiro.`,
736
+ contextoErro: "Erro ao consultar DDD"
737
+ })
738
+ }
739
+ ],
740
+ isError: true
741
+ };
742
+ }
743
+ }
744
+
745
+ // src/tools/dominio.ts
746
+ import { z as z8 } from "zod";
747
+ function normalizarDominio(entrada) {
748
+ const semProtocolo = entrada.trim().toLowerCase().replace(/^https?:\/\//, "");
749
+ const semPath = semProtocolo.split("/")[0] ?? "";
750
+ return semPath.replace(/^www\./, "");
751
+ }
752
+ function validarDominioBr(dominio) {
753
+ return /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*\.br$/.test(
754
+ dominio
755
+ );
756
+ }
757
+ var consultarDominioBrSchema = z8.object({
758
+ dominio: z8.string().describe(
759
+ "Dom\xEDnio .br a verificar. Aceita URL completa ou dom\xEDnio puro \u2014 ser\xE1 normalizado (remove http(s)://, www. e caminho). Ex: 'exemplo.com.br' ou 'https://www.exemplo.com.br/pagina'."
760
+ )
761
+ });
762
+ var consultarDominioBrTool = {
763
+ name: "consultar_dominio_br",
764
+ description: [
765
+ "Consulta o status de registro de um dom\xEDnio .br direto na base do registro.br (via BrasilAPI).",
766
+ "",
767
+ "Retorna em JSON: status (AVAILABLE = dispon\xEDvel pra registro, REGISTERED = j\xE1 registrado), fqdn, hosts (servidores DNS) e expires-at quando registrado, e suggestions de extens\xF5es quando dispon\xEDvel. O resultado nunca \xE9 cacheado \u2014 \xE9 sempre o status atual.",
768
+ "",
769
+ "Use quando o usu\xE1rio perguntar 'o dom\xEDnio X.com.br t\xE1 livre?', 'quando expira Y.org.br?', 'quem responde pelo DNS de Z.br?'.",
770
+ "",
771
+ "N\xC3O use para: dom\xEDnios internacionais .com/.net/gTLDs (a base \xE9 s\xF3 .br), dados de titular/whois completo (a API n\xE3o exp\xF5e), ou hospedagem/conte\xFAdo do site."
772
+ ].join(" "),
773
+ inputSchema: consultarDominioBrSchema
774
+ };
775
+ async function consultarDominioBrHandler(input) {
776
+ const dominio = normalizarDominio(input.dominio);
777
+ if (!validarDominioBr(dominio)) {
778
+ return {
779
+ content: [
780
+ {
781
+ type: "text",
782
+ text: `Dom\xEDnio inv\xE1lido: '${input.dominio}'. Esta tool s\xF3 consulta dom\xEDnios .br (registro.br). Ex: 'exemplo.com.br'.`
783
+ }
784
+ ],
785
+ isError: true
786
+ };
787
+ }
788
+ try {
789
+ const dados = await brasilApi.get(`/registrobr/v1/${dominio}`, {
790
+ ttlMs: 0
791
+ });
792
+ return {
793
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
794
+ };
795
+ } catch (err) {
796
+ return {
797
+ content: [
798
+ {
799
+ type: "text",
800
+ text: traduzirErroBrasilApi(err, {
801
+ notFound: `Dom\xEDnio ${dominio} n\xE3o encontrado na base do registro.br.`,
802
+ contextoErro: "Erro ao consultar dom\xEDnio"
803
+ })
804
+ }
805
+ ],
806
+ isError: true
807
+ };
808
+ }
809
+ }
810
+
369
811
  // src/tools/feriados.ts
370
- import { z as z4 } from "zod";
371
- var consultarFeriadosSchema = z4.object({
372
- ano: z4.number().int().describe(
812
+ import { z as z9 } from "zod";
813
+ var consultarFeriadosSchema = z9.object({
814
+ ano: z9.number().int().describe(
373
815
  "Ano dos feriados, 4 d\xEDgitos. Faixa aceita: 1900 a 2199. Ex: 2026."
374
816
  )
375
817
  });
@@ -422,8 +864,285 @@ async function consultarFeriadosHandler(input) {
422
864
  }
423
865
  }
424
866
 
867
+ // src/tools/ibge.ts
868
+ import { z as z10 } from "zod";
869
+ var UFS_VALIDAS = /* @__PURE__ */ new Set([
870
+ "AC",
871
+ "AL",
872
+ "AP",
873
+ "AM",
874
+ "BA",
875
+ "CE",
876
+ "DF",
877
+ "ES",
878
+ "GO",
879
+ "MA",
880
+ "MT",
881
+ "MS",
882
+ "MG",
883
+ "PA",
884
+ "PB",
885
+ "PR",
886
+ "PE",
887
+ "PI",
888
+ "RJ",
889
+ "RN",
890
+ "RS",
891
+ "RO",
892
+ "RR",
893
+ "SC",
894
+ "SP",
895
+ "SE",
896
+ "TO"
897
+ ]);
898
+ var listarEstadosSchema = z10.object({});
899
+ var listarEstadosTool = {
900
+ name: "listar_estados",
901
+ description: [
902
+ "Lista as 27 unidades federativas do Brasil (26 estados + DF) com dados do IBGE, via BrasilAPI.",
903
+ "",
904
+ "Retorna em JSON um array com id (c\xF3digo IBGE), sigla, nome, regi\xE3o (Norte/Nordeste/Centro-Oeste/Sudeste/Sul) e capital de cada UF.",
905
+ "",
906
+ "Use quando o usu\xE1rio precisar do c\xF3digo IBGE de um estado, agrupar estados por regi\xE3o, validar siglas de UF ou saber a capital.",
907
+ "",
908
+ "N\xC3O use para: munic\xEDpios (use consultar_municipios), dados demogr\xE1ficos ou populacionais (n\xE3o est\xE3o nesta API)."
909
+ ].join(" "),
910
+ inputSchema: listarEstadosSchema
911
+ };
912
+ async function listarEstadosHandler(_input) {
913
+ try {
914
+ const dados = await brasilApi.get("/ibge/uf/v1");
915
+ return {
916
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
917
+ };
918
+ } catch (err) {
919
+ return {
920
+ content: [
921
+ {
922
+ type: "text",
923
+ text: traduzirErroBrasilApi(err, {
924
+ notFound: "Lista de estados n\xE3o dispon\xEDvel no momento.",
925
+ contextoErro: "Erro ao listar estados"
926
+ })
927
+ }
928
+ ],
929
+ isError: true
930
+ };
931
+ }
932
+ }
933
+ var consultarMunicipiosSchema = z10.object({
934
+ uf: z10.string().describe(
935
+ "Sigla da unidade federativa, 2 letras, case-insensitive. Ex: 'SP', 'rj', 'DF'."
936
+ )
937
+ });
938
+ var consultarMunicipiosTool = {
939
+ name: "consultar_municipios",
940
+ description: [
941
+ "Lista todos os munic\xEDpios de uma UF brasileira com nome e c\xF3digo IBGE de 7 d\xEDgitos, via BrasilAPI.",
942
+ "",
943
+ "Retorna em JSON um array de {nome, codigo_ibge}. Aten\xE7\xE3o: estados grandes retornam listas longas (SP tem 645 munic\xEDpios, ~30KB) \u2014 prefira usar s\xF3 quando precisar da lista ou do c\xF3digo de um munic\xEDpio.",
944
+ "",
945
+ "Use quando o usu\xE1rio precisar do c\xF3digo IBGE de um munic\xEDpio ou listar as cidades de um estado.",
946
+ "",
947
+ "N\xC3O use para: buscar um munic\xEDpio por nome no pa\xEDs inteiro (a API s\xF3 filtra por UF \u2014 se souber o estado, consulte-o), endere\xE7os/CEP (use consultar_cep), ou dados populacionais."
948
+ ].join(" "),
949
+ inputSchema: consultarMunicipiosSchema
950
+ };
951
+ async function consultarMunicipiosHandler(input) {
952
+ const uf = input.uf.trim().toUpperCase();
953
+ if (!UFS_VALIDAS.has(uf)) {
954
+ return {
955
+ content: [
956
+ {
957
+ type: "text",
958
+ text: `UF inv\xE1lida: '${input.uf}'. Use uma sigla de estado brasileiro, ex: SP, RJ, MG.`
959
+ }
960
+ ],
961
+ isError: true
962
+ };
963
+ }
964
+ try {
965
+ const dados = await brasilApi.get(`/ibge/municipios/v1/${uf}`);
966
+ return {
967
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
968
+ };
969
+ } catch (err) {
970
+ return {
971
+ content: [
972
+ {
973
+ type: "text",
974
+ text: traduzirErroBrasilApi(err, {
975
+ notFound: `Munic\xEDpios da UF ${uf} n\xE3o encontrados.`,
976
+ contextoErro: "Erro ao consultar munic\xEDpios"
977
+ })
978
+ }
979
+ ],
980
+ isError: true
981
+ };
982
+ }
983
+ }
984
+
985
+ // src/tools/isbn.ts
986
+ import { z as z11 } from "zod";
987
+ var consultarIsbnSchema = z11.object({
988
+ codigo: z11.string().describe(
989
+ "ISBN do livro, 10 ou 13 d\xEDgitos. Aceita com ou sem h\xEDfens. Ex: '978-85-325-3080-2' ou '9788532530802'."
990
+ )
991
+ });
992
+ var consultarIsbnTool = {
993
+ name: "consultar_isbn",
994
+ description: [
995
+ "Consulta metadados de um livro pelo ISBN via BrasilAPI (agrega CBL, Mercado Editorial, Open Library e Google Books).",
996
+ "",
997
+ "Retorna em JSON: t\xEDtulo, subt\xEDtulo, autores, editora, ano, idioma, n\xFAmero de p\xE1ginas, assunto/categoria, sinopse (quando dispon\xEDvel) e fonte do dado.",
998
+ "",
999
+ "Use quando o usu\xE1rio fornecer um ISBN e quiser saber sobre o livro (t\xEDtulo, autor, editora, ano).",
1000
+ "",
1001
+ "N\xC3O use para: buscar livro por t\xEDtulo ou autor (a opera\xE7\xE3o \xE9 s\xF3 ISBN \u2192 metadados), validar formato sem consultar (rejeite local se n\xE3o bater 10/13 d\xEDgitos), ou consultar pre\xE7o/disponibilidade. Aceita ISBN-10 e ISBN-13, com ou sem h\xEDfens."
1002
+ ].join(" "),
1003
+ inputSchema: consultarIsbnSchema
1004
+ };
1005
+ function limparIsbn(s) {
1006
+ return s.replace(/[\s-]/g, "").toUpperCase();
1007
+ }
1008
+ function validarIsbn(s) {
1009
+ if (/^\d{9}[\dX]$/.test(s)) return true;
1010
+ if (/^\d{13}$/.test(s)) return true;
1011
+ return false;
1012
+ }
1013
+ async function consultarIsbnHandler(input) {
1014
+ const isbnLimpo = limparIsbn(input.codigo);
1015
+ if (!validarIsbn(isbnLimpo)) {
1016
+ return {
1017
+ content: [
1018
+ {
1019
+ type: "text",
1020
+ text: `ISBN inv\xE1lido: '${input.codigo}'. Deve ter 10 d\xEDgitos (\xFAltimo pode ser 'X') ou 13 d\xEDgitos. Aceita com ou sem h\xEDfens.`
1021
+ }
1022
+ ],
1023
+ isError: true
1024
+ };
1025
+ }
1026
+ try {
1027
+ const dados = await brasilApi.get(`/isbn/v1/${isbnLimpo}`);
1028
+ return {
1029
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
1030
+ };
1031
+ } catch (err) {
1032
+ return {
1033
+ content: [
1034
+ {
1035
+ type: "text",
1036
+ text: traduzirErroBrasilApi(err, {
1037
+ notFound: `ISBN ${isbnLimpo} n\xE3o encontrado nos provedores agregados (CBL, Mercado Editorial, Open Library, Google Books).`,
1038
+ contextoErro: "Erro ao consultar ISBN"
1039
+ })
1040
+ }
1041
+ ],
1042
+ isError: true
1043
+ };
1044
+ }
1045
+ }
1046
+
1047
+ // src/tools/taxas.ts
1048
+ import { z as z12 } from "zod";
1049
+ var TTL_TAXAS_MS = 60 * 60 * 1e3;
1050
+ var consultarTaxaSchema = z12.object({
1051
+ sigla: z12.string().describe(
1052
+ "Sigla da taxa, case-insensitive. Aceita: 'Selic' (taxa b\xE1sica de juros), 'CDI' (Certificado de Dep\xF3sito Interbanc\xE1rio), 'IPCA' (infla\xE7\xE3o oficial)."
1053
+ )
1054
+ });
1055
+ var consultarTaxaTool = {
1056
+ name: "consultar_taxa",
1057
+ description: [
1058
+ "Consulta o valor atual de uma taxa econ\xF4mica brasileira (SELIC, CDI, IPCA) via BrasilAPI.",
1059
+ "",
1060
+ "Retorna em JSON: nome da taxa e valor atual (% ao ano).",
1061
+ "",
1062
+ "Use quando o usu\xE1rio perguntar 'qual a SELIC hoje?', 'CDI atual?', 'infla\xE7\xE3o do IPCA?' \u2014 qualquer pergunta sobre o valor corrente de uma taxa espec\xEDfica.",
1063
+ "",
1064
+ "N\xC3O use para: s\xE9rie hist\xF3rica (a API devolve s\xF3 o \xFAltimo valor), outras taxas al\xE9m de SELIC/CDI/IPCA, ou consultar d\xF3lar/bolsa (n\xE3o est\xE1 nesta API). Pra panorama com todas as 3 taxas use listar_taxas."
1065
+ ].join(" "),
1066
+ inputSchema: consultarTaxaSchema
1067
+ };
1068
+ var SIGLAS_VALIDAS = /* @__PURE__ */ new Set(["SELIC", "CDI", "IPCA"]);
1069
+ function normalizarSigla(sigla) {
1070
+ return sigla.trim().toUpperCase();
1071
+ }
1072
+ async function consultarTaxaHandler(input) {
1073
+ const sigla = normalizarSigla(input.sigla);
1074
+ if (!SIGLAS_VALIDAS.has(sigla)) {
1075
+ return {
1076
+ content: [
1077
+ {
1078
+ type: "text",
1079
+ text: `Sigla inv\xE1lida: '${input.sigla}'. Use uma de: SELIC, CDI, IPCA.`
1080
+ }
1081
+ ],
1082
+ isError: true
1083
+ };
1084
+ }
1085
+ try {
1086
+ const dados = await brasilApi.get(`/taxas/v1/${sigla}`, {
1087
+ ttlMs: TTL_TAXAS_MS
1088
+ });
1089
+ return {
1090
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
1091
+ };
1092
+ } catch (err) {
1093
+ return {
1094
+ content: [
1095
+ {
1096
+ type: "text",
1097
+ text: traduzirErroBrasilApi(err, {
1098
+ notFound: `Taxa ${sigla} n\xE3o encontrada na BrasilAPI.`,
1099
+ contextoErro: "Erro ao consultar taxa"
1100
+ })
1101
+ }
1102
+ ],
1103
+ isError: true
1104
+ };
1105
+ }
1106
+ }
1107
+ var listarTaxasSchema = z12.object({});
1108
+ var listarTaxasTool = {
1109
+ name: "listar_taxas",
1110
+ description: [
1111
+ "Lista TODAS as taxas econ\xF4micas brasileiras dispon\xEDveis na BrasilAPI (SELIC, CDI, IPCA) com seus valores atuais.",
1112
+ "",
1113
+ "Retorna em JSON um array com nome e valor (% ao ano) de cada taxa.",
1114
+ "",
1115
+ "Use quando o usu\xE1rio quiser um panorama econ\xF4mico, comparar SELIC vs CDI vs IPCA, ou n\xE3o souber a sigla espec\xEDfica.",
1116
+ "",
1117
+ "N\xC3O use quando o usu\xE1rio j\xE1 sabe qual taxa quer \u2014 use consultar_taxa que \xE9 semanticamente mais direto. Hoje s\xE3o s\xF3 3 taxas; o payload \xE9 pequeno."
1118
+ ].join(" "),
1119
+ inputSchema: listarTaxasSchema
1120
+ };
1121
+ async function listarTaxasHandler(_input) {
1122
+ try {
1123
+ const dados = await brasilApi.get("/taxas/v1", {
1124
+ ttlMs: TTL_TAXAS_MS
1125
+ });
1126
+ return {
1127
+ content: [{ type: "text", text: JSON.stringify(dados, null, 2) }]
1128
+ };
1129
+ } catch (err) {
1130
+ return {
1131
+ content: [
1132
+ {
1133
+ type: "text",
1134
+ text: traduzirErroBrasilApi(err, {
1135
+ notFound: "Lista de taxas n\xE3o dispon\xEDvel no momento.",
1136
+ contextoErro: "Erro ao listar taxas"
1137
+ })
1138
+ }
1139
+ ],
1140
+ isError: true
1141
+ };
1142
+ }
1143
+ }
1144
+
425
1145
  // src/index.ts
426
- var VERSION = "0.1.0";
427
1146
  function wrapHandler(toolName, handler) {
428
1147
  return async (input) => {
429
1148
  try {
@@ -442,50 +1161,55 @@ function wrapHandler(toolName, handler) {
442
1161
  }
443
1162
  };
444
1163
  }
1164
+ var TOOLS = [
1165
+ { tool: consultarCnpjTool, handler: consultarCnpjHandler },
1166
+ { tool: consultarCepTool, handler: consultarCepHandler },
1167
+ { tool: consultarBancoTool, handler: consultarBancoHandler },
1168
+ { tool: listarBancosTool, handler: listarBancosHandler },
1169
+ { tool: consultarFeriadosTool, handler: consultarFeriadosHandler },
1170
+ { tool: consultarDddTool, handler: consultarDddHandler },
1171
+ { tool: consultarIsbnTool, handler: consultarIsbnHandler },
1172
+ { tool: consultarTaxaTool, handler: consultarTaxaHandler },
1173
+ { tool: listarTaxasTool, handler: listarTaxasHandler },
1174
+ { tool: consultarCorretoraTool, handler: consultarCorretoraHandler },
1175
+ // Fase 5 (v0.3.0):
1176
+ { tool: consultarCambioTool, handler: consultarCambioHandler },
1177
+ { tool: listarMoedasTool, handler: listarMoedasHandler },
1178
+ { tool: listarEstadosTool, handler: listarEstadosHandler },
1179
+ { tool: consultarMunicipiosTool, handler: consultarMunicipiosHandler },
1180
+ { tool: consultarDominioBrTool, handler: consultarDominioBrHandler }
1181
+ ];
445
1182
  function createServer() {
446
1183
  const server = new McpServer({
447
1184
  name: "brasil-data-mcp",
448
1185
  version: VERSION
449
1186
  });
450
- server.registerTool(
451
- consultarCnpjTool.name,
452
- {
453
- description: consultarCnpjTool.description,
454
- inputSchema: consultarCnpjSchema.shape
455
- },
456
- wrapHandler(consultarCnpjTool.name, consultarCnpjHandler)
457
- );
458
- server.registerTool(
459
- consultarCepTool.name,
460
- {
461
- description: consultarCepTool.description,
462
- inputSchema: consultarCepSchema.shape
463
- },
464
- wrapHandler(consultarCepTool.name, consultarCepHandler)
465
- );
466
- server.registerTool(
467
- consultarBancoTool.name,
468
- {
469
- description: consultarBancoTool.description,
470
- inputSchema: consultarBancoSchema.shape
471
- },
472
- wrapHandler(consultarBancoTool.name, consultarBancoHandler)
473
- );
474
- server.registerTool(
475
- listarBancosTool.name,
1187
+ for (const { tool, handler } of TOOLS) {
1188
+ server.registerTool(
1189
+ tool.name,
1190
+ {
1191
+ description: tool.description,
1192
+ inputSchema: tool.inputSchema.shape
1193
+ },
1194
+ wrapHandler(tool.name, handler)
1195
+ );
1196
+ }
1197
+ server.registerPrompt(
1198
+ analiseCnpjPrompt.name,
476
1199
  {
477
- description: listarBancosTool.description,
478
- inputSchema: listarBancosSchema.shape
1200
+ title: analiseCnpjPrompt.title,
1201
+ description: analiseCnpjPrompt.description,
1202
+ argsSchema: analiseCnpjArgsSchema
479
1203
  },
480
- wrapHandler(listarBancosTool.name, listarBancosHandler)
1204
+ analiseCnpjHandler
481
1205
  );
482
- server.registerTool(
483
- consultarFeriadosTool.name,
1206
+ server.registerPrompt(
1207
+ panoramaEconomicoPrompt.name,
484
1208
  {
485
- description: consultarFeriadosTool.description,
486
- inputSchema: consultarFeriadosSchema.shape
1209
+ title: panoramaEconomicoPrompt.title,
1210
+ description: panoramaEconomicoPrompt.description
487
1211
  },
488
- wrapHandler(consultarFeriadosTool.name, consultarFeriadosHandler)
1212
+ panoramaEconomicoHandler
489
1213
  );
490
1214
  return server;
491
1215
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "brasil-data-mcp",
3
- "version": "0.1.0",
4
- "description": "MCP server providing access to Brazilian public data (CNPJ, CEP, banks, holidays) via BrasilAPI. For use with Claude Desktop, Claude Code, Cursor, and other MCP-compatible clients.",
3
+ "version": "0.3.0",
4
+ "description": "MCP server providing access to Brazilian public data (CNPJ, CEP, banks, holidays, DDD, ISBN, economic rates, exchange rates, CVM brokers, IBGE states/municipalities, .br domains) via BrasilAPI. Ships with MCP prompts for guided workflows. For use with Claude Desktop, Claude Code, Cursor, and other MCP-compatible clients.",
5
5
  "keywords": [
6
6
  "mcp",
7
7
  "model-context-protocol",
@@ -10,6 +10,15 @@
10
10
  "brazil",
11
11
  "cnpj",
12
12
  "cep",
13
+ "ddd",
14
+ "isbn",
15
+ "selic",
16
+ "cdi",
17
+ "ipca",
18
+ "cambio",
19
+ "ibge",
20
+ "registro-br",
21
+ "cvm",
13
22
  "brasilapi",
14
23
  "ai-tools"
15
24
  ],