brasil-data-mcp 0.2.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 +14 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +414 -104
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
[](https://glama.ai/mcp/servers/alanpcf/brasil-data-mcp)
|
|
9
9
|
|
|
10
|
-
> MCP server que expõe dados públicos brasileiros (CNPJ, CEP, bancos, feriados, DDD, ISBN, taxas econômicas, corretoras CVM) 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).
|
|
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).
|
|
11
11
|
>
|
|
12
|
-
> _MCP server exposing Brazilian public data (CNPJ, CEP, banks, holidays, area codes, ISBN, economic rates, CVM brokers) as tools for Claude Desktop, Claude Code, Cursor, Windsurf and any MCP-compatible client. Ships with MCP prompts for guided workflows._
|
|
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._
|
|
13
13
|
|
|
14
14
|
Powered by [BrasilAPI](https://brasilapi.com.br) — sem chave, sem auth, dados oficiais.
|
|
15
15
|
|
|
@@ -27,10 +27,13 @@ Conecte seu cliente de IA aos dados públicos brasileiros sem escrever uma linha
|
|
|
27
27
|
- _"Me dá o livro do ISBN 9788532530802."_
|
|
28
28
|
- _"Qual a SELIC hoje?"_
|
|
29
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?"_
|
|
30
33
|
|
|
31
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.
|
|
32
35
|
|
|
33
|
-
### Tools disponíveis (
|
|
36
|
+
### Tools disponíveis (15)
|
|
34
37
|
|
|
35
38
|
| Tool | O que faz |
|
|
36
39
|
| ---------------------- | ---------------------------------------------------------------------------------- |
|
|
@@ -44,6 +47,11 @@ O Claude (ou outro cliente MCP) chama a tool, retorna o JSON estruturado, e voc
|
|
|
44
47
|
| `consultar_taxa` | Valor atual de taxa econômica (SELIC, CDI, IPCA) em % ao ano |
|
|
45
48
|
| `listar_taxas` | Panorama com todas as taxas econômicas vigentes |
|
|
46
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) |
|
|
47
55
|
|
|
48
56
|
### Prompts disponíveis (2)
|
|
49
57
|
|
|
@@ -60,7 +68,7 @@ Prompts MCP são **workflows guiados** que aparecem como atalho no Claude Deskto
|
|
|
60
68
|
|
|
61
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).
|
|
62
70
|
|
|
63
|
-
|
|
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.
|
|
64
72
|
|
|
65
73
|
---
|
|
66
74
|
|
|
@@ -145,6 +153,7 @@ Pra apontar seu cliente MCP pro build local em vez do pacote do npm:
|
|
|
145
153
|
- [x] **Fase 2** — `consultar_cep`, `consultar_banco`, `listar_bancos`, `consultar_feriados` + testes Vitest
|
|
146
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)
|
|
147
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
|
|
148
157
|
- [ ] **Próximo** — FIPE (aguardando upstream estabilizar, [BrasilAPI#805](https://github.com/BrasilAPI/BrasilAPI/issues/805)); Trusted Publishing (npm OIDC); mais prompts conforme demanda
|
|
149
158
|
|
|
150
159
|
---
|
|
@@ -163,7 +172,7 @@ Se você é dev brasileiro e usa LLM no dia a dia, esse server é pra você.
|
|
|
163
172
|
|
|
164
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`.
|
|
165
174
|
|
|
166
|
-
Guia detalhado em
|
|
175
|
+
Guia detalhado em [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
167
176
|
|
|
168
177
|
---
|
|
169
178
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ 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
|
|
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
12
|
* 3. Registra prompts (workflows) via registerPrompt.
|
|
@@ -15,9 +15,9 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
15
15
|
* REGRA CRÍTICA: nunca escrever em stdout fora do protocolo. Logs em stderr
|
|
16
16
|
* via console.error. console.log corrompe o canal MCP.
|
|
17
17
|
*
|
|
18
|
-
* REGISTRY: adicionar tool nova = uma
|
|
19
|
-
*
|
|
20
|
-
* 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.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
declare function createServer(): McpServer;
|
package/dist/index.js
CHANGED
|
@@ -85,12 +85,27 @@ function panoramaEconomicoHandler() {
|
|
|
85
85
|
// src/tools/banco.ts
|
|
86
86
|
import { z as z2 } from "zod";
|
|
87
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();
|
|
102
|
+
|
|
88
103
|
// src/clients/brasilapi.ts
|
|
89
104
|
var BASE_URL = "https://brasilapi.com.br/api";
|
|
90
105
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
91
106
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
92
107
|
var MAX_RETRIES = 3;
|
|
93
|
-
var USER_AGENT =
|
|
108
|
+
var USER_AGENT = `brasil-data-mcp/${VERSION} (+https://github.com/alanpcf/brasil-data-mcp)`;
|
|
94
109
|
var BrasilApiError = class extends Error {
|
|
95
110
|
constructor(message, status, path, body) {
|
|
96
111
|
super(message);
|
|
@@ -308,10 +323,174 @@ async function listarBancosHandler(_input) {
|
|
|
308
323
|
}
|
|
309
324
|
}
|
|
310
325
|
|
|
311
|
-
// src/tools/
|
|
326
|
+
// src/tools/cambio.ts
|
|
312
327
|
import { z as z3 } from "zod";
|
|
313
|
-
var
|
|
314
|
-
|
|
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
|
+
|
|
490
|
+
// src/tools/cep.ts
|
|
491
|
+
import { z as z4 } from "zod";
|
|
492
|
+
var consultarCepSchema = z4.object({
|
|
493
|
+
cep: z4.string().describe(
|
|
315
494
|
"CEP brasileiro com ou sem h\xEDfen. Aceita '01310-100' ou '01310100'. Deve ter 8 d\xEDgitos."
|
|
316
495
|
)
|
|
317
496
|
});
|
|
@@ -371,7 +550,7 @@ async function consultarCepHandler(input) {
|
|
|
371
550
|
}
|
|
372
551
|
|
|
373
552
|
// src/tools/cnpj.ts
|
|
374
|
-
import { z as
|
|
553
|
+
import { z as z5 } from "zod";
|
|
375
554
|
|
|
376
555
|
// src/utils/cnpj.ts
|
|
377
556
|
function limparCnpj(s) {
|
|
@@ -384,8 +563,8 @@ function validarCnpj(s) {
|
|
|
384
563
|
}
|
|
385
564
|
|
|
386
565
|
// src/tools/cnpj.ts
|
|
387
|
-
var consultarCnpjSchema =
|
|
388
|
-
cnpj:
|
|
566
|
+
var consultarCnpjSchema = z5.object({
|
|
567
|
+
cnpj: z5.string().describe(
|
|
389
568
|
"CNPJ da empresa, com ou sem m\xE1scara. Aceita '12.345.678/0001-90' ou '12345678000190'. Deve ter 14 d\xEDgitos."
|
|
390
569
|
)
|
|
391
570
|
});
|
|
@@ -449,9 +628,9 @@ async function consultarCnpjHandler(input) {
|
|
|
449
628
|
}
|
|
450
629
|
|
|
451
630
|
// src/tools/corretoras.ts
|
|
452
|
-
import { z as
|
|
453
|
-
var consultarCorretoraSchema =
|
|
454
|
-
cnpj:
|
|
631
|
+
import { z as z6 } from "zod";
|
|
632
|
+
var consultarCorretoraSchema = z6.object({
|
|
633
|
+
cnpj: z6.string().describe(
|
|
455
634
|
"CNPJ da corretora, com ou sem m\xE1scara. 14 d\xEDgitos. Ex: '02.332.886/0011-78' (XP Investimentos)."
|
|
456
635
|
)
|
|
457
636
|
});
|
|
@@ -505,9 +684,9 @@ async function consultarCorretoraHandler(input) {
|
|
|
505
684
|
}
|
|
506
685
|
|
|
507
686
|
// src/tools/ddd.ts
|
|
508
|
-
import { z as
|
|
509
|
-
var consultarDddSchema =
|
|
510
|
-
ddd:
|
|
687
|
+
import { z as z7 } from "zod";
|
|
688
|
+
var consultarDddSchema = z7.object({
|
|
689
|
+
ddd: z7.union([z7.string(), z7.number()]).describe(
|
|
511
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)."
|
|
512
691
|
)
|
|
513
692
|
});
|
|
@@ -563,10 +742,76 @@ async function consultarDddHandler(input) {
|
|
|
563
742
|
}
|
|
564
743
|
}
|
|
565
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
|
+
|
|
566
811
|
// src/tools/feriados.ts
|
|
567
|
-
import { z as
|
|
568
|
-
var consultarFeriadosSchema =
|
|
569
|
-
ano:
|
|
812
|
+
import { z as z9 } from "zod";
|
|
813
|
+
var consultarFeriadosSchema = z9.object({
|
|
814
|
+
ano: z9.number().int().describe(
|
|
570
815
|
"Ano dos feriados, 4 d\xEDgitos. Faixa aceita: 1900 a 2199. Ex: 2026."
|
|
571
816
|
)
|
|
572
817
|
});
|
|
@@ -619,10 +864,128 @@ async function consultarFeriadosHandler(input) {
|
|
|
619
864
|
}
|
|
620
865
|
}
|
|
621
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
|
+
|
|
622
985
|
// src/tools/isbn.ts
|
|
623
|
-
import { z as
|
|
624
|
-
var consultarIsbnSchema =
|
|
625
|
-
codigo:
|
|
986
|
+
import { z as z11 } from "zod";
|
|
987
|
+
var consultarIsbnSchema = z11.object({
|
|
988
|
+
codigo: z11.string().describe(
|
|
626
989
|
"ISBN do livro, 10 ou 13 d\xEDgitos. Aceita com ou sem h\xEDfens. Ex: '978-85-325-3080-2' ou '9788532530802'."
|
|
627
990
|
)
|
|
628
991
|
});
|
|
@@ -682,10 +1045,10 @@ async function consultarIsbnHandler(input) {
|
|
|
682
1045
|
}
|
|
683
1046
|
|
|
684
1047
|
// src/tools/taxas.ts
|
|
685
|
-
import { z as
|
|
1048
|
+
import { z as z12 } from "zod";
|
|
686
1049
|
var TTL_TAXAS_MS = 60 * 60 * 1e3;
|
|
687
|
-
var consultarTaxaSchema =
|
|
688
|
-
sigla:
|
|
1050
|
+
var consultarTaxaSchema = z12.object({
|
|
1051
|
+
sigla: z12.string().describe(
|
|
689
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)."
|
|
690
1053
|
)
|
|
691
1054
|
});
|
|
@@ -741,7 +1104,7 @@ async function consultarTaxaHandler(input) {
|
|
|
741
1104
|
};
|
|
742
1105
|
}
|
|
743
1106
|
}
|
|
744
|
-
var listarTaxasSchema =
|
|
1107
|
+
var listarTaxasSchema = z12.object({});
|
|
745
1108
|
var listarTaxasTool = {
|
|
746
1109
|
name: "listar_taxas",
|
|
747
1110
|
description: [
|
|
@@ -780,7 +1143,6 @@ async function listarTaxasHandler(_input) {
|
|
|
780
1143
|
}
|
|
781
1144
|
|
|
782
1145
|
// src/index.ts
|
|
783
|
-
var VERSION = "0.2.0";
|
|
784
1146
|
function wrapHandler(toolName, handler) {
|
|
785
1147
|
return async (input) => {
|
|
786
1148
|
try {
|
|
@@ -799,91 +1161,39 @@ function wrapHandler(toolName, handler) {
|
|
|
799
1161
|
}
|
|
800
1162
|
};
|
|
801
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
|
+
];
|
|
802
1182
|
function createServer() {
|
|
803
1183
|
const server = new McpServer({
|
|
804
1184
|
name: "brasil-data-mcp",
|
|
805
1185
|
version: VERSION
|
|
806
1186
|
});
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
{
|
|
818
|
-
description: consultarCepTool.description,
|
|
819
|
-
inputSchema: consultarCepSchema.shape
|
|
820
|
-
},
|
|
821
|
-
wrapHandler(consultarCepTool.name, consultarCepHandler)
|
|
822
|
-
);
|
|
823
|
-
server.registerTool(
|
|
824
|
-
consultarBancoTool.name,
|
|
825
|
-
{
|
|
826
|
-
description: consultarBancoTool.description,
|
|
827
|
-
inputSchema: consultarBancoSchema.shape
|
|
828
|
-
},
|
|
829
|
-
wrapHandler(consultarBancoTool.name, consultarBancoHandler)
|
|
830
|
-
);
|
|
831
|
-
server.registerTool(
|
|
832
|
-
listarBancosTool.name,
|
|
833
|
-
{
|
|
834
|
-
description: listarBancosTool.description,
|
|
835
|
-
inputSchema: listarBancosSchema.shape
|
|
836
|
-
},
|
|
837
|
-
wrapHandler(listarBancosTool.name, listarBancosHandler)
|
|
838
|
-
);
|
|
839
|
-
server.registerTool(
|
|
840
|
-
consultarFeriadosTool.name,
|
|
841
|
-
{
|
|
842
|
-
description: consultarFeriadosTool.description,
|
|
843
|
-
inputSchema: consultarFeriadosSchema.shape
|
|
844
|
-
},
|
|
845
|
-
wrapHandler(consultarFeriadosTool.name, consultarFeriadosHandler)
|
|
846
|
-
);
|
|
847
|
-
server.registerTool(
|
|
848
|
-
consultarDddTool.name,
|
|
849
|
-
{
|
|
850
|
-
description: consultarDddTool.description,
|
|
851
|
-
inputSchema: consultarDddSchema.shape
|
|
852
|
-
},
|
|
853
|
-
wrapHandler(consultarDddTool.name, consultarDddHandler)
|
|
854
|
-
);
|
|
855
|
-
server.registerTool(
|
|
856
|
-
consultarIsbnTool.name,
|
|
857
|
-
{
|
|
858
|
-
description: consultarIsbnTool.description,
|
|
859
|
-
inputSchema: consultarIsbnSchema.shape
|
|
860
|
-
},
|
|
861
|
-
wrapHandler(consultarIsbnTool.name, consultarIsbnHandler)
|
|
862
|
-
);
|
|
863
|
-
server.registerTool(
|
|
864
|
-
consultarTaxaTool.name,
|
|
865
|
-
{
|
|
866
|
-
description: consultarTaxaTool.description,
|
|
867
|
-
inputSchema: consultarTaxaSchema.shape
|
|
868
|
-
},
|
|
869
|
-
wrapHandler(consultarTaxaTool.name, consultarTaxaHandler)
|
|
870
|
-
);
|
|
871
|
-
server.registerTool(
|
|
872
|
-
listarTaxasTool.name,
|
|
873
|
-
{
|
|
874
|
-
description: listarTaxasTool.description,
|
|
875
|
-
inputSchema: listarTaxasSchema.shape
|
|
876
|
-
},
|
|
877
|
-
wrapHandler(listarTaxasTool.name, listarTaxasHandler)
|
|
878
|
-
);
|
|
879
|
-
server.registerTool(
|
|
880
|
-
consultarCorretoraTool.name,
|
|
881
|
-
{
|
|
882
|
-
description: consultarCorretoraTool.description,
|
|
883
|
-
inputSchema: consultarCorretoraSchema.shape
|
|
884
|
-
},
|
|
885
|
-
wrapHandler(consultarCorretoraTool.name, consultarCorretoraHandler)
|
|
886
|
-
);
|
|
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
|
+
}
|
|
887
1197
|
server.registerPrompt(
|
|
888
1198
|
analiseCnpjPrompt.name,
|
|
889
1199
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brasil-data-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server providing access to Brazilian public data (CNPJ, CEP, banks, holidays, DDD, ISBN, economic rates, CVM brokers) via BrasilAPI. Ships with MCP prompts for guided workflows. 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",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"selic",
|
|
16
16
|
"cdi",
|
|
17
17
|
"ipca",
|
|
18
|
+
"cambio",
|
|
19
|
+
"ibge",
|
|
20
|
+
"registro-br",
|
|
18
21
|
"cvm",
|
|
19
22
|
"brasilapi",
|
|
20
23
|
"ai-tools"
|