@conflaro/mcp 1.9.0 → 1.11.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 +1 -1
- package/dist/index.js +37 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ faltou, sem erro de versão duplicada.
|
|
|
96
96
|
recusam quando divergem. O servidor lê a dele do `package.json`.
|
|
97
97
|
|
|
98
98
|
O npm publica por **Trusted Publisher** (OIDC): o vínculo é com
|
|
99
|
-
`conflaro/
|
|
99
|
+
`conflaro/app` + `mcp-publish.yml`, configurado nas Settings do pacote no
|
|
100
100
|
npmjs.com. Renomear o workflow quebra a publicação.
|
|
101
101
|
🔴 Pacote novo não aceita Trusted Publisher antes de existir: a 1ª versão do
|
|
102
102
|
`@conflaro/mcp` sai à mão (`npm publish` no terminal, com a passkey), que depois é apagado (ver o
|
package/dist/index.js
CHANGED
|
@@ -77,13 +77,24 @@ const server = new McpServer({ name: "conflaro", version });
|
|
|
77
77
|
// ── Empresa ────────────────────────────────────────────────────────────────
|
|
78
78
|
server.tool("get_company", "Mostra os dados da empresa dona da chave de API configurada (razão social, CNPJ, IE/IM, regime tributário, endereço).", {}, tool(() => api("GET", "/v1/company")));
|
|
79
79
|
// ── Documentos fiscais ─────────────────────────────────────────────────────
|
|
80
|
+
// Sem `companyId`: a empresa da chave. Com `companyId`: uma empresa da
|
|
81
|
+
// CARTEIRA do escritório (chave `ok_`) — escrever exige ainda que a empresa
|
|
82
|
+
// tenha liberado a emissão pelo contador.
|
|
83
|
+
const FD_COMPANY = z
|
|
84
|
+
.string()
|
|
85
|
+
.optional()
|
|
86
|
+
.describe("SÓ no modo contador (chave do escritório `ok_`): a empresa da carteira (id de list_portfolio_companies). Omita com a chave de uma empresa.");
|
|
87
|
+
const fdBase = (companyId) => companyId
|
|
88
|
+
? `/v1/accounting/companies/${encodeURIComponent(String(companyId))}/fiscal-documents`
|
|
89
|
+
: "/v1/fiscal-documents";
|
|
80
90
|
server.tool("list_fiscal_documents", "Lista os documentos fiscais (NF-e/NFC-e/NFS-e) da empresa, com paginação e filtros por status e tipo.", {
|
|
81
91
|
page: z.number().int().positive().optional().describe("Página (default 1)"),
|
|
82
92
|
pageSize: z.number().int().positive().max(100).optional().describe("Itens por página (default 20, máx 100)"),
|
|
83
93
|
status: z.string().optional().describe("Filtra por status (ex.: AUTHORIZED, DRAFT, REJECTED)"),
|
|
84
94
|
type: z.string().optional().describe("Filtra por tipo (NFE, NFCE, NFSE)"),
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
companyId: FD_COMPANY,
|
|
96
|
+
}, tool(({ companyId, ...query }) => api("GET", fdBase(companyId), { query })));
|
|
97
|
+
server.tool("get_fiscal_document", "Detalha um documento fiscal pelo id (status, número, chave de acesso, itens, etc.).", { id: z.string().describe("ID do documento fiscal"), companyId: FD_COMPANY }, tool((a) => api("GET", `${fdBase(a.companyId)}/${a.id}`)));
|
|
87
98
|
/**
|
|
88
99
|
* 🔴 Estes shapes são um RECORTE da API pública, não um espelho dela.
|
|
89
100
|
*
|
|
@@ -310,6 +321,7 @@ const itemShape = z.object({
|
|
|
310
321
|
}).passthrough();
|
|
311
322
|
server.tool("create_fiscal_document", "Cria um documento fiscal (rascunho). Use emit=true para já enfileirar a emissão. Impostos são resolvidos pela regra tributária quando não informados.", {
|
|
312
323
|
type: z.enum(["NFE", "NFCE", "NFSE"]).describe("Tipo do documento"),
|
|
324
|
+
companyId: FD_COMPANY,
|
|
313
325
|
clientId: z
|
|
314
326
|
.string()
|
|
315
327
|
.optional()
|
|
@@ -472,22 +484,24 @@ server.tool("create_fiscal_document", "Cria um documento fiscal (rascunho). Use
|
|
|
472
484
|
// `z.object` fechado, então campo não declarado seria DESCARTADO em
|
|
473
485
|
// silêncio — o pior desfecho, porque a nota sai sem ele e nada avisa.
|
|
474
486
|
// O declarado vence o `extra` quando os dois trazem a mesma chave.
|
|
475
|
-
const { extra, ...campos } = a;
|
|
487
|
+
const { extra, companyId, ...campos } = a;
|
|
476
488
|
const declarados = Object.fromEntries(Object.entries(campos).filter(([, v]) => v !== undefined));
|
|
477
|
-
return api("POST",
|
|
489
|
+
return api("POST", fdBase(companyId), {
|
|
478
490
|
body: { ...(extra ?? {}), ...declarados },
|
|
479
491
|
});
|
|
480
492
|
}));
|
|
481
|
-
server.tool("emit_fiscal_document", "Dispara a emissão (assíncrona) de um documento fiscal já criado. Acompanhe o status com get_fiscal_document.", { id: z.string().describe("ID do documento fiscal") }, tool((a) => api("POST",
|
|
493
|
+
server.tool("emit_fiscal_document", "Dispara a emissão (assíncrona) de um documento fiscal já criado. Acompanhe o status com get_fiscal_document.", { id: z.string().describe("ID do documento fiscal"), companyId: FD_COMPANY }, tool((a) => api("POST", `${fdBase(a.companyId)}/${a.id}/emit`)));
|
|
482
494
|
server.tool("cancel_fiscal_document", "Cancela um documento fiscal AUTORIZADO, com justificativa.", {
|
|
483
495
|
id: z.string().describe("ID do documento fiscal"),
|
|
484
496
|
reason: z.string().min(15).describe("Justificativa do cancelamento (mín. 15 caracteres)"),
|
|
485
|
-
|
|
497
|
+
companyId: FD_COMPANY,
|
|
498
|
+
}, tool((a) => api("POST", `${fdBase(a.companyId)}/${a.id}/cancel`, { body: { reason: a.reason } })));
|
|
486
499
|
server.tool("correct_fiscal_document", "Emite uma Carta de Correção (CC-e) para um documento fiscal autorizado.", {
|
|
487
500
|
id: z.string().describe("ID do documento fiscal"),
|
|
488
501
|
text: z.string().min(15).describe("Texto da correção (mín. 15 caracteres)"),
|
|
489
|
-
|
|
490
|
-
|
|
502
|
+
companyId: FD_COMPANY,
|
|
503
|
+
}, tool((a) => api("POST", `${fdBase(a.companyId)}/${a.id}/correction`, { body: { text: a.text } })));
|
|
504
|
+
server.tool("get_fiscal_document_xml", "Baixa o XML autorizado de um documento fiscal (retorna o XML como texto).", { id: z.string().describe("ID do documento fiscal"), companyId: FD_COMPANY }, tool((a) => api("GET", `${fdBase(a.companyId)}/${a.id}/xml`)));
|
|
491
505
|
// ── GNRE por operação (docs/plans/gnre.md §8) ──
|
|
492
506
|
server.tool("get_fiscal_document_gnre", "GNRE da nota (guia de recolhimento do DIFAL, FCP e ICMS-ST devidos a OUTRA UF): o que a NF-e autorizada exige (`assessment`, pelo XML), as guias geradas (status, valor, vencimento, `digitableLine` para pagar) e a cota do mês. `noGuideReason` explica quando NÃO há guia devida. Valores em string decimal.", { id: z.string().describe("ID do documento fiscal (NF-e)") }, tool((a) => api("GET", `/v1/fiscal-documents/${encodeURIComponent(String(a.id))}/gnre`)));
|
|
493
507
|
server.tool("generate_fiscal_document_gnre", "Gera (ou regera) as guias GNRE da nota no Portal GNRE — fala com o fisco, consome a cota do plano e cria obrigação de pagamento: confirme com o usuário antes. Idempotente (guia emitida não é refeita). O resultado sai em ≥ 30 s: depois consulte get_fiscal_document_gnre (ou refresh_fiscal_document_gnre). `blocked` = falta dado que só a pessoa resolve; o motivo fica na guia. Exige o módulo GNRE (403 `feature_not_enabled`).", { id: z.string().describe("ID do documento fiscal (NF-e autorizada)") }, tool((a) => api("POST", `/v1/fiscal-documents/${encodeURIComponent(String(a.id))}/gnre`)));
|
|
@@ -794,6 +808,14 @@ server.tool("get_simples_das_forecast", "Previsão do DAS do MÊS CORRENTE se o
|
|
|
794
808
|
: "/v1/simples/forecast";
|
|
795
809
|
return api("GET", path);
|
|
796
810
|
}));
|
|
811
|
+
server.tool("get_simples_monophasic_recovery", "PIS/COFINS monofásico que a empresa do Simples PODE ter pago a mais no DAS nos últimos 60 meses: revenda de NCM monofásico emitida sem o CST 04 de PIS, com o PIS/COFINS da alíquota efetiva do Anexo I de cada mês. É INDÍCIO a confirmar com o contador (só houve pagamento a mais se o PGDAS-D não segregou a receita) — diga isso. `monthsWithoutRate` ficou FORA do total. Escopo `simples:read`.", {
|
|
812
|
+
companyId: RD_COMPANY,
|
|
813
|
+
}, tool((a) => {
|
|
814
|
+
const path = a.companyId
|
|
815
|
+
? `/v1/accounting/companies/${encodeURIComponent(String(a.companyId))}/simples/monophasic-recovery`
|
|
816
|
+
: "/v1/simples/monophasic-recovery";
|
|
817
|
+
return api("GET", path);
|
|
818
|
+
}));
|
|
797
819
|
server.tool("get_product_tax_in_price", "Quanto do preço de um produto é imposto (empresa do Simples): alíquota efetiva do DAS do anexo do produto, imposto no preço, margem e o PREÇO MÍNIMO para a margem desejada. Valores em string decimal (\"40.00\"). `minimumPrice: null` = imposto + despesas + margem passam de 100%. Nada é gravado. Escopo `simples:read`.", {
|
|
798
820
|
productId: z.string().describe("Id do produto (list_products)"),
|
|
799
821
|
cost: z.string().describe("Custo unitário, decimal em string"),
|
|
@@ -814,6 +836,13 @@ server.tool("list_portfolio_companies", "MODO CONTADOR: as empresas-cliente com
|
|
|
814
836
|
page: z.number().int().positive().optional(),
|
|
815
837
|
pageSize: z.number().int().positive().max(100).optional(),
|
|
816
838
|
}, tool((a) => api("GET", "/v1/accounting/companies", { query: a })));
|
|
839
|
+
server.tool("list_portfolio_company_clients", "MODO CONTADOR: os clientes cadastrados numa empresa da carteira — o `clientId` para criar nota por ela (create_fiscal_document com `companyId`).", {
|
|
840
|
+
companyId: z.string().describe("Empresa da carteira (id de list_portfolio_companies)"),
|
|
841
|
+
search: z.string().optional().describe("Nome, documento, email ou nome fantasia"),
|
|
842
|
+
page: z.number().int().positive().optional(),
|
|
843
|
+
pageSize: z.number().int().positive().max(100).optional(),
|
|
844
|
+
}, tool(({ companyId, ...query }) => api("GET", `/v1/accounting/companies/${encodeURIComponent(String(companyId))}/clients`, { query })));
|
|
845
|
+
server.tool("get_portfolio_nfse_readiness", "MODO CONTADOR: a empresa da carteira consegue emitir NFS-e agora? (certificado, configuração do município, cota do plano) — sem criar nota. Use antes de propor uma NFS-e.", { companyId: z.string().describe("Empresa da carteira (id de list_portfolio_companies)") }, tool((a) => api("GET", `/v1/accounting/companies/${encodeURIComponent(String(a.companyId))}/nfse-readiness`)));
|
|
817
846
|
server.tool("list_closing_eligible_companies", "MODO CONTADOR: empresas da carteira com nota de PRODUÇÃO autorizada ou cancelada no mês (BRT) — as que o fechamento vai processar. Mês é 1–12.", {
|
|
818
847
|
year: z.number().int().describe("Ano (ex.: 2026)"),
|
|
819
848
|
month: z.number().int().min(1).max(12).describe("Mês, 1–12"),
|