@brazil-mcp/cnpj 1.0.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 +75 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/brasil-api.d.ts +11 -0
- package/dist/providers/brasil-api.js +69 -0
- package/dist/providers/brasil-api.js.map +1 -0
- package/dist/providers/index.d.ts +19 -0
- package/dist/providers/index.js +56 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/receita-ws.d.ts +12 -0
- package/dist/providers/receita-ws.js +66 -0
- package/dist/providers/receita-ws.js.map +1 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.js +57 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/format.d.ts +17 -0
- package/dist/tools/format.js +94 -0
- package/dist/tools/format.js.map +1 -0
- package/dist/tools/handlers.d.ts +14 -0
- package/dist/tools/handlers.js +77 -0
- package/dist/tools/handlers.js.map +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cache.d.ts +19 -0
- package/dist/utils/cache.js +53 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/cnpj.d.ts +21 -0
- package/dist/utils/cnpj.js +66 -0
- package/dist/utils/cnpj.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +88 -0
- package/dist/utils/rate-limiter.js +263 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# 🇧🇷 CNPJ MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server para consulta de CNPJ, sĂłcios e atividades de empresas brasileiras.
|
|
4
|
+
|
|
5
|
+
Parte do [Brazil MCP Bundle](https://github.com/acaua/brazil-mcp) — ferramentas brasileiras para Claude Code, Cursor e qualquer cliente MCP.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Instalação
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Claude Code
|
|
13
|
+
claude mcp add cnpj -- npx @brazil-mcp/cnpj
|
|
14
|
+
|
|
15
|
+
# claude_desktop_config.json / Cursor / VS Code
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"cnpj": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["@brazil-mcp/cnpj"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Tools DisponĂveis
|
|
27
|
+
|
|
28
|
+
| Tool | Descrição |
|
|
29
|
+
|------|-----------|
|
|
30
|
+
| `cnpj_lookup` | Dados completos da empresa (razão social, endereço, capital social, sócios, CNAEs) |
|
|
31
|
+
| `cnpj_validate` | Valida dĂgitos verificadores (local, sem API) |
|
|
32
|
+
| `cnpj_partners` | Lista de sócios (QSA) com qualificação |
|
|
33
|
+
| `cnpj_activities` | Atividades econômicas (CNAE principal e secundárias) |
|
|
34
|
+
| `cnpj_address` | Endereço completo registrado na Receita Federal |
|
|
35
|
+
|
|
36
|
+
## Exemplos de Uso
|
|
37
|
+
|
|
38
|
+
No Claude Code ou Cursor, simplesmente peça:
|
|
39
|
+
|
|
40
|
+
- *"Quem sĂŁo os sĂłcios do CNPJ 33.000.167/0001-01?"*
|
|
41
|
+
- *"Valide o CNPJ 12345678000195"*
|
|
42
|
+
- *"Qual o endereço da empresa com CNPJ 33000167000101?"*
|
|
43
|
+
- *"Liste as atividades econĂ´micas do CNPJ 33.000.167/0001-01"*
|
|
44
|
+
|
|
45
|
+
## APIs Utilizadas
|
|
46
|
+
|
|
47
|
+
- [BrasilAPI](https://brasilapi.com.br/) (principal — gratuita, sem auth)
|
|
48
|
+
- [ReceitaWS](https://receitaws.com.br/) (fallback — gratuita, 3 req/min)
|
|
49
|
+
|
|
50
|
+
Cache em memĂłria com TTL de 24h para reduzir chamadas.
|
|
51
|
+
|
|
52
|
+
## Desenvolvimento
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install
|
|
56
|
+
npm run dev # Roda em modo dev
|
|
57
|
+
npm test # Testes unitários
|
|
58
|
+
npm run test:integration # Testes com APIs reais
|
|
59
|
+
npm run build # Compila TypeScript
|
|
60
|
+
npm run inspect # Abre MCP Inspector
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Licença
|
|
64
|
+
|
|
65
|
+
MIT
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
# 🇧🇷 CNPJ MCP Server (English)
|
|
70
|
+
|
|
71
|
+
MCP server for querying Brazilian company data (CNPJ), partners, and economic activities.
|
|
72
|
+
|
|
73
|
+
Part of the [Brazil MCP Bundle](https://github.com/acaua/brazil-mcp) — Brazilian business tools for Claude Code, Cursor, and any MCP client.
|
|
74
|
+
|
|
75
|
+
All tool responses are in Portuguese (Brazilian data from Receita Federal).
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { createServer } from "./server.js";
|
|
4
|
+
async function main() {
|
|
5
|
+
const { server } = createServer();
|
|
6
|
+
const transport = new StdioServerTransport();
|
|
7
|
+
await server.connect(transport);
|
|
8
|
+
console.error("[cnpj-mcp] Server iniciado via stdio");
|
|
9
|
+
}
|
|
10
|
+
main().catch((err) => {
|
|
11
|
+
console.error("[cnpj-mcp] Erro fatal:", err);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;AACxD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CnpjData, CnpjProvider } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Provider que consulta a BrasilAPI (gratuita, sem autenticação).
|
|
4
|
+
* Docs: https://brasilapi.com.br/docs#tag/CNPJ
|
|
5
|
+
*/
|
|
6
|
+
export declare class BrasilApiProvider implements CnpjProvider {
|
|
7
|
+
name: string;
|
|
8
|
+
private baseUrl;
|
|
9
|
+
fetchCnpj(cnpj: string): Promise<CnpjData>;
|
|
10
|
+
private normalize;
|
|
11
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider que consulta a BrasilAPI (gratuita, sem autenticação).
|
|
3
|
+
* Docs: https://brasilapi.com.br/docs#tag/CNPJ
|
|
4
|
+
*/
|
|
5
|
+
export class BrasilApiProvider {
|
|
6
|
+
name = "BrasilAPI";
|
|
7
|
+
baseUrl = "https://brasilapi.com.br/api/cnpj/v1";
|
|
8
|
+
async fetchCnpj(cnpj) {
|
|
9
|
+
const url = `${this.baseUrl}/${cnpj}`;
|
|
10
|
+
const response = await fetch(url, {
|
|
11
|
+
headers: { Accept: "application/json" },
|
|
12
|
+
signal: AbortSignal.timeout(10_000),
|
|
13
|
+
});
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
const status = response.status;
|
|
16
|
+
if (status === 404) {
|
|
17
|
+
throw new Error(`CNPJ ${cnpj} nĂŁo encontrado na base da Receita Federal.`);
|
|
18
|
+
}
|
|
19
|
+
if (status === 429) {
|
|
20
|
+
throw new Error("Rate limit atingido na BrasilAPI. Tente novamente em alguns segundos.");
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`BrasilAPI retornou status ${status}`);
|
|
23
|
+
}
|
|
24
|
+
const raw = await response.json();
|
|
25
|
+
return this.normalize(raw);
|
|
26
|
+
}
|
|
27
|
+
normalize(raw) {
|
|
28
|
+
const socios = (raw.qsa || []).map((s) => ({
|
|
29
|
+
nome: s.nome_socio || s.nome || "",
|
|
30
|
+
qualificacao: s.qualificacao_socio || s.qual || "",
|
|
31
|
+
data_entrada: s.data_entrada_sociedade || "",
|
|
32
|
+
cpf_cnpj: s.cnpj_cpf_do_socio || "",
|
|
33
|
+
faixa_etaria: s.faixa_etaria || "",
|
|
34
|
+
}));
|
|
35
|
+
const atividadePrincipal = {
|
|
36
|
+
codigo: String(raw.cnae_fiscal || ""),
|
|
37
|
+
descricao: raw.cnae_fiscal_descricao || "",
|
|
38
|
+
};
|
|
39
|
+
const atividadesSecundarias = (raw.cnaes_secundarios || []).map((a) => ({
|
|
40
|
+
codigo: String(a.codigo || ""),
|
|
41
|
+
descricao: a.descricao || "",
|
|
42
|
+
}));
|
|
43
|
+
return {
|
|
44
|
+
cnpj: raw.cnpj || "",
|
|
45
|
+
razao_social: raw.razao_social || "",
|
|
46
|
+
nome_fantasia: raw.nome_fantasia || "",
|
|
47
|
+
situacao_cadastral: raw.descricao_situacao_cadastral || "",
|
|
48
|
+
data_situacao_cadastral: raw.data_situacao_cadastral || "",
|
|
49
|
+
data_abertura: raw.data_inicio_atividade || "",
|
|
50
|
+
natureza_juridica: raw.natureza_juridica || "",
|
|
51
|
+
capital_social: raw.capital_social || 0,
|
|
52
|
+
porte: raw.porte || raw.descricao_porte || "",
|
|
53
|
+
tipo: raw.descricao_tipo_de_logradouro || "",
|
|
54
|
+
logradouro: raw.logradouro || "",
|
|
55
|
+
numero: raw.numero || "",
|
|
56
|
+
complemento: raw.complemento || "",
|
|
57
|
+
bairro: raw.bairro || "",
|
|
58
|
+
municipio: raw.municipio || "",
|
|
59
|
+
uf: raw.uf || "",
|
|
60
|
+
cep: raw.cep || "",
|
|
61
|
+
telefone: raw.ddd_telefone_1 || "",
|
|
62
|
+
email: raw.email || "",
|
|
63
|
+
atividade_principal: atividadePrincipal,
|
|
64
|
+
atividades_secundarias: atividadesSecundarias,
|
|
65
|
+
socios,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=brasil-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brasil-api.js","sourceRoot":"","sources":["../../src/providers/brasil-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CnpjData, CnpjProvider } from "../types.js";
|
|
2
|
+
import { MemoryCache } from "../utils/cache.js";
|
|
3
|
+
/**
|
|
4
|
+
* Orquestrador de providers CNPJ com fallback automático e cache.
|
|
5
|
+
*
|
|
6
|
+
* Fluxo:
|
|
7
|
+
* 1. Verifica cache (TTL 24h)
|
|
8
|
+
* 2. Tenta BrasilAPI (principal)
|
|
9
|
+
* 3. Se falhar, tenta ReceitaWS (fallback)
|
|
10
|
+
* 4. Se ambos falharem, retorna erro descritivo
|
|
11
|
+
*/
|
|
12
|
+
export declare class CnpjService {
|
|
13
|
+
private providers;
|
|
14
|
+
private cache;
|
|
15
|
+
constructor(providers?: CnpjProvider[], cache?: MemoryCache<CnpjData>);
|
|
16
|
+
lookup(cnpj: string): Promise<CnpjData>;
|
|
17
|
+
clearCache(): void;
|
|
18
|
+
get cacheSize(): number;
|
|
19
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { MemoryCache } from "../utils/cache.js";
|
|
2
|
+
import { BrasilApiProvider } from "./brasil-api.js";
|
|
3
|
+
import { ReceitaWsProvider } from "./receita-ws.js";
|
|
4
|
+
/**
|
|
5
|
+
* Orquestrador de providers CNPJ com fallback automático e cache.
|
|
6
|
+
*
|
|
7
|
+
* Fluxo:
|
|
8
|
+
* 1. Verifica cache (TTL 24h)
|
|
9
|
+
* 2. Tenta BrasilAPI (principal)
|
|
10
|
+
* 3. Se falhar, tenta ReceitaWS (fallback)
|
|
11
|
+
* 4. Se ambos falharem, retorna erro descritivo
|
|
12
|
+
*/
|
|
13
|
+
export class CnpjService {
|
|
14
|
+
providers;
|
|
15
|
+
cache;
|
|
16
|
+
constructor(providers, cache) {
|
|
17
|
+
this.providers = providers ?? [
|
|
18
|
+
new BrasilApiProvider(),
|
|
19
|
+
new ReceitaWsProvider(),
|
|
20
|
+
];
|
|
21
|
+
this.cache = cache ?? new MemoryCache(86_400_000); // 24h
|
|
22
|
+
}
|
|
23
|
+
async lookup(cnpj) {
|
|
24
|
+
// 1. Verifica cache
|
|
25
|
+
const cached = this.cache.get(cnpj);
|
|
26
|
+
if (cached) {
|
|
27
|
+
console.error(`[cnpj-mcp] Cache hit para ${cnpj}`);
|
|
28
|
+
return cached;
|
|
29
|
+
}
|
|
30
|
+
// 2. Tenta cada provider em ordem
|
|
31
|
+
const errors = [];
|
|
32
|
+
for (const provider of this.providers) {
|
|
33
|
+
try {
|
|
34
|
+
console.error(`[cnpj-mcp] Consultando ${provider.name} para ${cnpj}`);
|
|
35
|
+
const data = await provider.fetchCnpj(cnpj);
|
|
36
|
+
this.cache.set(cnpj, data);
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
41
|
+
console.error(`[cnpj-mcp] ${provider.name} falhou: ${message}`);
|
|
42
|
+
errors.push(`${provider.name}: ${message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// 3. Todos falharam
|
|
46
|
+
throw new Error(`NĂŁo foi possĂvel consultar o CNPJ ${cnpj}. ` +
|
|
47
|
+
`Erros: ${errors.join(" | ")}`);
|
|
48
|
+
}
|
|
49
|
+
clearCache() {
|
|
50
|
+
this.cache.clear();
|
|
51
|
+
}
|
|
52
|
+
get cacheSize() {
|
|
53
|
+
return this.cache.size;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAW;IACd,SAAS,CAAiB;IAC1B,KAAK,CAAwB;IAErC,YACE,SAA0B,EAC1B,KAA6B;QAE7B,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI;YAC5B,IAAI,iBAAiB,EAAE;YACvB,IAAI,iBAAiB,EAAE;SACxB,CAAC;QACF,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,IAAI,WAAW,CAAW,UAAU,CAAC,CAAC,CAAC,MAAM;IACrE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,oBAAoB;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;YACnD,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,kCAAkC;QAClC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,OAAO,CAAC,KAAK,CAAC,0BAA0B,QAAQ,CAAC,IAAI,SAAS,IAAI,EAAE,CAAC,CAAC;gBACtE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC5C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC3B,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,OAAO,CAAC,KAAK,CAAC,cAAc,QAAQ,CAAC,IAAI,YAAY,OAAO,EAAE,CAAC,CAAC;gBAChE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,IAAI;YAC3C,UAAU,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACjC,CAAC;IACJ,CAAC;IAED,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CnpjData, CnpjProvider } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Provider que consulta a ReceitaWS (gratuita, limite 3 req/min).
|
|
4
|
+
* Usado como fallback quando BrasilAPI está indisponĂvel.
|
|
5
|
+
* Docs: https://receitaws.com.br/api
|
|
6
|
+
*/
|
|
7
|
+
export declare class ReceitaWsProvider implements CnpjProvider {
|
|
8
|
+
name: string;
|
|
9
|
+
private baseUrl;
|
|
10
|
+
fetchCnpj(cnpj: string): Promise<CnpjData>;
|
|
11
|
+
private normalize;
|
|
12
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider que consulta a ReceitaWS (gratuita, limite 3 req/min).
|
|
3
|
+
* Usado como fallback quando BrasilAPI está indisponĂvel.
|
|
4
|
+
* Docs: https://receitaws.com.br/api
|
|
5
|
+
*/
|
|
6
|
+
export class ReceitaWsProvider {
|
|
7
|
+
name = "ReceitaWS";
|
|
8
|
+
baseUrl = "https://receitaws.com.br/v1/cnpj";
|
|
9
|
+
async fetchCnpj(cnpj) {
|
|
10
|
+
const url = `${this.baseUrl}/${cnpj}`;
|
|
11
|
+
const response = await fetch(url, {
|
|
12
|
+
headers: { Accept: "application/json" },
|
|
13
|
+
signal: AbortSignal.timeout(15_000), // ReceitaWS Ă© mais lenta
|
|
14
|
+
});
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
throw new Error(`ReceitaWS retornou status ${response.status}`);
|
|
17
|
+
}
|
|
18
|
+
const raw = await response.json();
|
|
19
|
+
if (raw.status === "ERROR") {
|
|
20
|
+
throw new Error(raw.message || "Erro ao consultar ReceitaWS");
|
|
21
|
+
}
|
|
22
|
+
return this.normalize(raw);
|
|
23
|
+
}
|
|
24
|
+
normalize(raw) {
|
|
25
|
+
const socios = (raw.qsa || []).map((s) => ({
|
|
26
|
+
nome: s.nome || "",
|
|
27
|
+
qualificacao: s.qual || "",
|
|
28
|
+
data_entrada: "",
|
|
29
|
+
cpf_cnpj: "",
|
|
30
|
+
faixa_etaria: "",
|
|
31
|
+
}));
|
|
32
|
+
const parseActivity = (a) => ({
|
|
33
|
+
codigo: a.code || "",
|
|
34
|
+
descricao: a.text || "",
|
|
35
|
+
});
|
|
36
|
+
const atividadePrincipal = raw.atividade_principal?.length > 0
|
|
37
|
+
? parseActivity(raw.atividade_principal[0])
|
|
38
|
+
: { codigo: "", descricao: "" };
|
|
39
|
+
const atividadesSecundarias = (raw.atividades_secundarias || []).map(parseActivity);
|
|
40
|
+
return {
|
|
41
|
+
cnpj: (raw.cnpj || "").replace(/[^\d]/g, ""),
|
|
42
|
+
razao_social: raw.nome || "",
|
|
43
|
+
nome_fantasia: raw.fantasia || "",
|
|
44
|
+
situacao_cadastral: raw.situacao || "",
|
|
45
|
+
data_situacao_cadastral: raw.data_situacao || "",
|
|
46
|
+
data_abertura: raw.abertura || "",
|
|
47
|
+
natureza_juridica: raw.natureza_juridica || "",
|
|
48
|
+
capital_social: parseFloat(raw.capital_social || "0"),
|
|
49
|
+
porte: raw.porte || "",
|
|
50
|
+
tipo: raw.tipo || "",
|
|
51
|
+
logradouro: raw.logradouro || "",
|
|
52
|
+
numero: raw.numero || "",
|
|
53
|
+
complemento: raw.complemento || "",
|
|
54
|
+
bairro: raw.bairro || "",
|
|
55
|
+
municipio: raw.municipio || "",
|
|
56
|
+
uf: raw.uf || "",
|
|
57
|
+
cep: (raw.cep || "").replace(/[^\d]/g, ""),
|
|
58
|
+
telefone: raw.telefone || "",
|
|
59
|
+
email: raw.email || "",
|
|
60
|
+
atividade_principal: atividadePrincipal,
|
|
61
|
+
atividades_secundarias: atividadesSecundarias,
|
|
62
|
+
socios,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=receita-ws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receita-ws.js","sourceRoot":"","sources":["../../src/providers/receita-ws.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { CnpjService } from "./providers/index.js";
|
|
3
|
+
import { DailyRateLimiter } from "./utils/rate-limiter.js";
|
|
4
|
+
/**
|
|
5
|
+
* Cria e configura o MCP Server com todas as tools.
|
|
6
|
+
* No tier free, aplica rate limit de 50 calls/dia nas tools que consultam API.
|
|
7
|
+
* cnpj_validate nĂŁo consome quota (Ă© local).
|
|
8
|
+
*/
|
|
9
|
+
export declare function createServer(opts?: {
|
|
10
|
+
service?: CnpjService;
|
|
11
|
+
rateLimiter?: DailyRateLimiter | null;
|
|
12
|
+
}): {
|
|
13
|
+
server: McpServer;
|
|
14
|
+
cnpjService: CnpjService;
|
|
15
|
+
rateLimiter: DailyRateLimiter | null;
|
|
16
|
+
};
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { CnpjService } from "./providers/index.js";
|
|
4
|
+
import { handleCnpjLookup, handleCnpjValidate, handleCnpjPartners, handleCnpjActivities, handleCnpjAddress, } from "./tools/handlers.js";
|
|
5
|
+
import { DailyRateLimiter, rateLimitMessage } from "./utils/rate-limiter.js";
|
|
6
|
+
/**
|
|
7
|
+
* Cria e configura o MCP Server com todas as tools.
|
|
8
|
+
* No tier free, aplica rate limit de 50 calls/dia nas tools que consultam API.
|
|
9
|
+
* cnpj_validate nĂŁo consome quota (Ă© local).
|
|
10
|
+
*/
|
|
11
|
+
export function createServer(opts) {
|
|
12
|
+
const cnpjService = opts?.service ?? new CnpjService();
|
|
13
|
+
// null = sem rate limit (modo pro). undefined = cria default (modo free).
|
|
14
|
+
const limiter = opts?.rateLimiter === null
|
|
15
|
+
? null
|
|
16
|
+
: opts?.rateLimiter ?? new DailyRateLimiter(50);
|
|
17
|
+
const server = new McpServer({
|
|
18
|
+
name: "cnpj-mcp",
|
|
19
|
+
version: "1.0.0",
|
|
20
|
+
description: "Consulta CNPJ, sĂłcios e atividades de empresas brasileiras via Receita Federal. " +
|
|
21
|
+
"Plano gratuito: 50 consultas/dia. Ilimitado com @brazil-mcp/bundle-pro.",
|
|
22
|
+
});
|
|
23
|
+
function withLimit(fn, toolLabel) {
|
|
24
|
+
if (limiter && !limiter.tryConsume()) {
|
|
25
|
+
return Promise.resolve({
|
|
26
|
+
content: [{ type: "text", text: rateLimitMessage(toolLabel, limiter.limit) }],
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return fn();
|
|
30
|
+
}
|
|
31
|
+
// ─── Tools ────────────────────────────────────────────
|
|
32
|
+
server.registerTool("cnpj_lookup", {
|
|
33
|
+
description: "Consulta dados completos de uma empresa brasileira pelo CNPJ. " +
|
|
34
|
+
"Retorna razão social, nome fantasia, endereço, capital social, sócios e CNAEs.",
|
|
35
|
+
inputSchema: {
|
|
36
|
+
cnpj: z.string().describe("CNPJ da empresa (com ou sem formatação)"),
|
|
37
|
+
},
|
|
38
|
+
}, async ({ cnpj }) => withLimit(() => handleCnpjLookup(cnpj, cnpjService), "CNPJ"));
|
|
39
|
+
server.registerTool("cnpj_validate", {
|
|
40
|
+
description: "Valida dĂgitos verificadores de um CNPJ (local, sem API, sem consumir quota).",
|
|
41
|
+
inputSchema: { cnpj: z.string().describe("CNPJ para validar") },
|
|
42
|
+
}, async ({ cnpj }) => handleCnpjValidate(cnpj)); // sem rate limit — é local
|
|
43
|
+
server.registerTool("cnpj_partners", {
|
|
44
|
+
description: "Lista sĂłcios (QSA) de uma empresa pelo CNPJ.",
|
|
45
|
+
inputSchema: { cnpj: z.string().describe("CNPJ da empresa") },
|
|
46
|
+
}, async ({ cnpj }) => withLimit(() => handleCnpjPartners(cnpj, cnpjService), "CNPJ"));
|
|
47
|
+
server.registerTool("cnpj_activities", {
|
|
48
|
+
description: "Retorna CNAEs (atividades econĂ´micas) de uma empresa pelo CNPJ.",
|
|
49
|
+
inputSchema: { cnpj: z.string().describe("CNPJ da empresa") },
|
|
50
|
+
}, async ({ cnpj }) => withLimit(() => handleCnpjActivities(cnpj, cnpjService), "CNPJ"));
|
|
51
|
+
server.registerTool("cnpj_address", {
|
|
52
|
+
description: "Retorna endereço registrado na Receita Federal para um CNPJ.",
|
|
53
|
+
inputSchema: { cnpj: z.string().describe("CNPJ da empresa") },
|
|
54
|
+
}, async ({ cnpj }) => withLimit(() => handleCnpjAddress(cnpj, cnpjService), "CNPJ"));
|
|
55
|
+
return { server, cnpjService, rateLimiter: limiter };
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CnpjData } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Formata os dados de uma empresa em relatĂłrio textual legĂvel.
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatCompanyReport(data: CnpjData): string;
|
|
6
|
+
/**
|
|
7
|
+
* Formata a lista de sĂłcios de uma empresa.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatPartnersList(razaoSocial: string, cnpj: string, socios: CnpjData["socios"]): string;
|
|
10
|
+
/**
|
|
11
|
+
* Formata as atividades econĂ´micas de uma empresa.
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatActivities(razaoSocial: string, cnpj: string, principal: CnpjData["atividade_principal"], secundarias: CnpjData["atividades_secundarias"]): string;
|
|
14
|
+
/**
|
|
15
|
+
* Formata o endereço de uma empresa.
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatAddress(data: CnpjData): string;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { formatCnpj } from "../utils/cnpj.js";
|
|
2
|
+
/**
|
|
3
|
+
* Formata os dados de uma empresa em relatĂłrio textual legĂvel.
|
|
4
|
+
*/
|
|
5
|
+
export function formatCompanyReport(data) {
|
|
6
|
+
const lines = [
|
|
7
|
+
`Empresa: ${data.razao_social}`,
|
|
8
|
+
data.nome_fantasia ? `Nome Fantasia: ${data.nome_fantasia}` : "",
|
|
9
|
+
`CNPJ: ${formatCnpj(data.cnpj)}`,
|
|
10
|
+
`Situação: ${data.situacao_cadastral}`,
|
|
11
|
+
`Data Abertura: ${data.data_abertura}`,
|
|
12
|
+
`Natureza JurĂdica: ${data.natureza_juridica}`,
|
|
13
|
+
`Capital Social: R$ ${data.capital_social.toLocaleString("pt-BR", { minimumFractionDigits: 2 })}`,
|
|
14
|
+
data.porte ? `Porte: ${data.porte}` : "",
|
|
15
|
+
"",
|
|
16
|
+
"Endereço:",
|
|
17
|
+
` ${[data.logradouro, data.numero ? `nÂş ${data.numero}` : "", data.complemento].filter(Boolean).join(", ")}`,
|
|
18
|
+
` ${data.bairro} - ${data.municipio}/${data.uf}`,
|
|
19
|
+
` CEP: ${data.cep}`,
|
|
20
|
+
"",
|
|
21
|
+
data.telefone ? `Telefone: ${data.telefone}` : "",
|
|
22
|
+
data.email ? `E-mail: ${data.email}` : "",
|
|
23
|
+
"",
|
|
24
|
+
`Atividade Principal: ${data.atividade_principal.codigo} - ${data.atividade_principal.descricao}`,
|
|
25
|
+
];
|
|
26
|
+
if (data.atividades_secundarias.length > 0) {
|
|
27
|
+
lines.push(`Atividades Secundárias (${data.atividades_secundarias.length}):`, ...data.atividades_secundarias.map((a) => ` ${a.codigo} - ${a.descricao}`));
|
|
28
|
+
}
|
|
29
|
+
if (data.socios.length > 0) {
|
|
30
|
+
lines.push("", `SĂłcios (${data.socios.length}):`, ...data.socios.map((s) => ` - ${s.nome}${s.qualificacao ? ` (${s.qualificacao})` : ""}`));
|
|
31
|
+
}
|
|
32
|
+
return lines.filter((l) => l !== "").join("\n");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Formata a lista de sĂłcios de uma empresa.
|
|
36
|
+
*/
|
|
37
|
+
export function formatPartnersList(razaoSocial, cnpj, socios) {
|
|
38
|
+
const lines = [
|
|
39
|
+
`SĂłcios de ${razaoSocial} (${formatCnpj(cnpj)}):`,
|
|
40
|
+
"",
|
|
41
|
+
...socios.map((s, i) => {
|
|
42
|
+
const parts = [`${i + 1}. ${s.nome}`];
|
|
43
|
+
if (s.qualificacao)
|
|
44
|
+
parts.push(` Qualificação: ${s.qualificacao}`);
|
|
45
|
+
if (s.data_entrada)
|
|
46
|
+
parts.push(` Entrada: ${s.data_entrada}`);
|
|
47
|
+
return parts.join("\n");
|
|
48
|
+
}),
|
|
49
|
+
];
|
|
50
|
+
return lines.join("\n");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Formata as atividades econĂ´micas de uma empresa.
|
|
54
|
+
*/
|
|
55
|
+
export function formatActivities(razaoSocial, cnpj, principal, secundarias) {
|
|
56
|
+
const lines = [
|
|
57
|
+
`Atividades econĂ´micas de ${razaoSocial} (${formatCnpj(cnpj)}):`,
|
|
58
|
+
"",
|
|
59
|
+
`Atividade Principal:`,
|
|
60
|
+
` ${principal.codigo} - ${principal.descricao}`,
|
|
61
|
+
];
|
|
62
|
+
if (secundarias.length > 0) {
|
|
63
|
+
lines.push("", "Atividades Secundárias:");
|
|
64
|
+
secundarias.forEach((a) => {
|
|
65
|
+
lines.push(` ${a.codigo} - ${a.descricao}`);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return lines.join("\n");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Formata o endereço de uma empresa.
|
|
72
|
+
*/
|
|
73
|
+
export function formatAddress(data) {
|
|
74
|
+
const addressParts = [
|
|
75
|
+
data.logradouro,
|
|
76
|
+
data.numero ? `nÂş ${data.numero}` : "",
|
|
77
|
+
data.complemento,
|
|
78
|
+
]
|
|
79
|
+
.filter(Boolean)
|
|
80
|
+
.join(", ");
|
|
81
|
+
const lines = [
|
|
82
|
+
`Endereço de ${data.razao_social} (${formatCnpj(data.cnpj)}):`,
|
|
83
|
+
"",
|
|
84
|
+
addressParts,
|
|
85
|
+
`${data.bairro} - ${data.municipio}/${data.uf}`,
|
|
86
|
+
`CEP: ${data.cep}`,
|
|
87
|
+
];
|
|
88
|
+
if (data.telefone)
|
|
89
|
+
lines.push(`Telefone: ${data.telefone}`);
|
|
90
|
+
if (data.email)
|
|
91
|
+
lines.push(`E-mail: ${data.email}`);
|
|
92
|
+
return lines.join("\n");
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/tools/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CnpjService } from "../providers/index.js";
|
|
2
|
+
/** Tipo padrĂŁo de retorno dos handlers MCP. */
|
|
3
|
+
export interface ToolResult {
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
content: Array<{
|
|
6
|
+
type: "text";
|
|
7
|
+
text: string;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
export declare function handleCnpjLookup(cnpj: string, service: CnpjService): Promise<ToolResult>;
|
|
11
|
+
export declare function handleCnpjValidate(cnpj: string): Promise<ToolResult>;
|
|
12
|
+
export declare function handleCnpjPartners(cnpj: string, service: CnpjService): Promise<ToolResult>;
|
|
13
|
+
export declare function handleCnpjActivities(cnpj: string, service: CnpjService): Promise<ToolResult>;
|
|
14
|
+
export declare function handleCnpjAddress(cnpj: string, service: CnpjService): Promise<ToolResult>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { cleanCnpj, formatCnpj, isValidCnpj } from "../utils/cnpj.js";
|
|
2
|
+
import { formatCompanyReport, formatPartnersList, formatActivities, formatAddress, } from "./format.js";
|
|
3
|
+
function textResult(text) {
|
|
4
|
+
return { content: [{ type: "text", text }] };
|
|
5
|
+
}
|
|
6
|
+
function errorResult(prefix, err) {
|
|
7
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8
|
+
return textResult(`❌ ${prefix}: ${message}`);
|
|
9
|
+
}
|
|
10
|
+
// ─── cnpj_lookup ──────────────────────────────────────────
|
|
11
|
+
export async function handleCnpjLookup(cnpj, service) {
|
|
12
|
+
const clean = cleanCnpj(cnpj);
|
|
13
|
+
if (!isValidCnpj(clean)) {
|
|
14
|
+
return textResult(`❌ CNPJ inválido: ${cnpj}. Verifique se todos os dĂgitos estĂŁo corretos.`);
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const data = await service.lookup(clean);
|
|
18
|
+
return textResult(formatCompanyReport(data));
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
return errorResult("Erro ao consultar CNPJ", err);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ─── cnpj_validate ────────────────────────────────────────
|
|
25
|
+
export async function handleCnpjValidate(cnpj) {
|
|
26
|
+
const clean = cleanCnpj(cnpj);
|
|
27
|
+
const valid = isValidCnpj(clean);
|
|
28
|
+
return textResult(valid
|
|
29
|
+
? `âś… CNPJ ${formatCnpj(clean)} Ă© válido (dĂgitos verificadores corretos).`
|
|
30
|
+
: `❌ CNPJ ${cnpj} Ă© inválido. Os dĂgitos verificadores nĂŁo conferem.`);
|
|
31
|
+
}
|
|
32
|
+
// ─── cnpj_partners ────────────────────────────────────────
|
|
33
|
+
export async function handleCnpjPartners(cnpj, service) {
|
|
34
|
+
const clean = cleanCnpj(cnpj);
|
|
35
|
+
if (!isValidCnpj(clean)) {
|
|
36
|
+
return textResult(`❌ CNPJ inválido: ${cnpj}`);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const data = await service.lookup(clean);
|
|
40
|
+
if (!data.socios || data.socios.length === 0) {
|
|
41
|
+
return textResult(`Nenhum sĂłcio encontrado para ${formatCnpj(clean)} (${data.razao_social}).`);
|
|
42
|
+
}
|
|
43
|
+
return textResult(formatPartnersList(data.razao_social, clean, data.socios));
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
return errorResult("Erro", err);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ─── cnpj_activities ──────────────────────────────────────
|
|
50
|
+
export async function handleCnpjActivities(cnpj, service) {
|
|
51
|
+
const clean = cleanCnpj(cnpj);
|
|
52
|
+
if (!isValidCnpj(clean)) {
|
|
53
|
+
return textResult(`❌ CNPJ inválido: ${cnpj}`);
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const data = await service.lookup(clean);
|
|
57
|
+
return textResult(formatActivities(data.razao_social, clean, data.atividade_principal, data.atividades_secundarias));
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
return errorResult("Erro", err);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// ─── cnpj_address ─────────────────────────────────────────
|
|
64
|
+
export async function handleCnpjAddress(cnpj, service) {
|
|
65
|
+
const clean = cleanCnpj(cnpj);
|
|
66
|
+
if (!isValidCnpj(clean)) {
|
|
67
|
+
return textResult(`❌ CNPJ inválido: ${cnpj}`);
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const data = await service.lookup(clean);
|
|
71
|
+
return textResult(formatAddress(data));
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
return errorResult("Erro", err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=handlers.js.map
|