@comando.one/mcp-server 0.4.0 → 0.5.1
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 +6 -2
- package/dist/index.js +248 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Além deste pacote stdio, existe um **endpoint MCP remoto (streaming)** em `http
|
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
Ambos expõem o **mesmo conjunto de ferramentas** (
|
|
42
|
+
Ambos expõem o **mesmo conjunto de ferramentas** (131 curadas + `lookups` + `comando_request` = cobertura total da API).
|
|
43
43
|
|
|
44
44
|
## Variáveis de ambiente
|
|
45
45
|
|
|
@@ -51,10 +51,14 @@ Ambos expõem o **mesmo conjunto de ferramentas** (50 curadas + `lookups` + `com
|
|
|
51
51
|
|
|
52
52
|
## Como funciona
|
|
53
53
|
|
|
54
|
-
- **
|
|
54
|
+
- **131 tools curadas** (gerados a partir do OpenAPI canônico, zero drift) cobrindo as operações de maior valor — `customers_list`, `invoices_create`/`invoices_delete`, `charges_create`, `nfse_emit`, `payouts_create`, `contracts_pause`/`contracts_resume`, `service_categories_create`, `reports_aging_actions`/`reports_cashflow_forecast`, `audit_timeline`, `documents_analyze` (lê boleto/guia/NF anexada e extrai valor, vencimento e emitente), `cost_centers_create`, etc.
|
|
55
55
|
- **`comando_request`** — escape hatch genérico (`method`, `path`, `query`, `body`) que cobre 100% dos endpoints restantes.
|
|
56
56
|
- **`lookups`** — catálogos read-only (centros de custo, condições/métodos de pagamento, naturezas, contas bancárias).
|
|
57
57
|
- **`whoami`** — identidade, empresas acessíveis e scopes da chave.
|
|
58
|
+
- **Nomes em português** — cada tool viaja com `title` (e `annotations.title`) vindo do
|
|
59
|
+
`summary` da OpenAPI, então o cliente mostra "Listar clientes" em vez de "Customers list".
|
|
60
|
+
O servidor também se identifica com `title` ("Comando.One"), `description`, `websiteUrl` e
|
|
61
|
+
`icons` (SEP-973). Clientes que ainda não leem esses campos caem no nome técnico sem quebrar.
|
|
58
62
|
|
|
59
63
|
### Segurança
|
|
60
64
|
|
package/dist/index.js
CHANGED
|
@@ -143,6 +143,8 @@ var MANIFEST = [
|
|
|
143
143
|
{ operationId: "getInvoice", tool: "invoices_get" },
|
|
144
144
|
{ operationId: "createInvoice", tool: "invoices_create", write: true },
|
|
145
145
|
{ operationId: "cancelInvoice", tool: "invoices_cancel", write: true, destructive: true },
|
|
146
|
+
{ operationId: "sendInvoiceSecondCopy", tool: "invoices_send", write: true },
|
|
147
|
+
{ operationId: "generateContractInvoices", tool: "contracts_generate_invoices", write: true },
|
|
146
148
|
// ----- Cobranças -----
|
|
147
149
|
{ operationId: "listCharges", tool: "charges_list" },
|
|
148
150
|
{ operationId: "getCharge", tool: "charges_get" },
|
|
@@ -194,6 +196,7 @@ var MANIFEST = [
|
|
|
194
196
|
{ operationId: "releaseSplitItem", tool: "split_release_item", write: true },
|
|
195
197
|
// Auditoria
|
|
196
198
|
{ operationId: "analyzeDocument", tool: "documents_analyze", write: true },
|
|
199
|
+
{ operationId: "listDocuments", tool: "documents_search" },
|
|
197
200
|
{ operationId: "getAuditTimeline", tool: "audit_timeline" },
|
|
198
201
|
// Categorias de serviço
|
|
199
202
|
{ operationId: "listServiceCategories", tool: "service_categories_list" },
|
|
@@ -367,7 +370,7 @@ var SCHEMAS = {
|
|
|
367
370
|
email: { type: ["string", "null"] },
|
|
368
371
|
phone: { type: ["string", "null"] },
|
|
369
372
|
document: { type: ["string", "null"], description: "CPF ou CNPJ" },
|
|
370
|
-
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"] },
|
|
373
|
+
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"], description: "Natureza JUR\xCDDICA do cadastro, n\xE3o a categoria de atividade: fisica = pessoa f\xEDsica (CPF); juridica = pessoa jur\xEDdica (CNPJ), o que inclui empresas, \xF3rg\xE3os p\xFAblicos, prefeituras e a Receita Federal; estrangeira = sem CNPJ/CPF. Na d\xFAvida, OMITA o campo \u2014 o padr\xE3o j\xE1 cobre o caso comum." },
|
|
371
374
|
company_name: { type: ["string", "null"] },
|
|
372
375
|
trade_name: { type: ["string", "null"] },
|
|
373
376
|
status: { type: "string" },
|
|
@@ -383,7 +386,7 @@ var SCHEMAS = {
|
|
|
383
386
|
email: { type: "string" },
|
|
384
387
|
phone: { type: "string" },
|
|
385
388
|
document: { type: "string" },
|
|
386
|
-
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"], default: "fisica" },
|
|
389
|
+
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"], default: "fisica", description: "Natureza JUR\xCDDICA do cadastro, n\xE3o a categoria de atividade: fisica = pessoa f\xEDsica (CPF); juridica = pessoa jur\xEDdica (CNPJ), o que inclui empresas, \xF3rg\xE3os p\xFAblicos, prefeituras e a Receita Federal; estrangeira = sem CNPJ/CPF. Na d\xFAvida, OMITA o campo \u2014 o padr\xE3o j\xE1 cobre o caso comum." },
|
|
387
390
|
company_name: { type: "string" },
|
|
388
391
|
trade_name: { type: "string" },
|
|
389
392
|
status: { type: "string", default: "ativo" }
|
|
@@ -396,7 +399,7 @@ var SCHEMAS = {
|
|
|
396
399
|
email: { type: ["string", "null"] },
|
|
397
400
|
phone: { type: ["string", "null"] },
|
|
398
401
|
document: { type: ["string", "null"] },
|
|
399
|
-
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"] },
|
|
402
|
+
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"], description: "Natureza JUR\xCDDICA do cadastro, n\xE3o a categoria de atividade: fisica = pessoa f\xEDsica (CPF); juridica = pessoa jur\xEDdica (CNPJ), o que inclui empresas, \xF3rg\xE3os p\xFAblicos, prefeituras e a Receita Federal; estrangeira = sem CNPJ/CPF. Na d\xFAvida, OMITA o campo \u2014 o padr\xE3o j\xE1 cobre o caso comum." },
|
|
400
403
|
company_name: { type: ["string", "null"] },
|
|
401
404
|
trade_name: { type: ["string", "null"] },
|
|
402
405
|
status: { type: "string" }
|
|
@@ -685,7 +688,7 @@ var SCHEMAS = {
|
|
|
685
688
|
email: { type: ["string", "null"] },
|
|
686
689
|
phone: { type: ["string", "null"] },
|
|
687
690
|
document: { type: ["string", "null"], description: "CPF ou CNPJ" },
|
|
688
|
-
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"] },
|
|
691
|
+
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"], description: "Natureza JUR\xCDDICA do cadastro, n\xE3o a categoria de atividade: fisica = pessoa f\xEDsica (CPF); juridica = pessoa jur\xEDdica (CNPJ), o que inclui empresas, \xF3rg\xE3os p\xFAblicos, prefeituras e a Receita Federal; estrangeira = sem CNPJ/CPF. Na d\xFAvida, OMITA o campo \u2014 o padr\xE3o j\xE1 cobre o caso comum." },
|
|
689
692
|
company_name: { type: ["string", "null"] },
|
|
690
693
|
trade_name: { type: ["string", "null"] },
|
|
691
694
|
state_registration: { type: ["string", "null"] },
|
|
@@ -710,7 +713,7 @@ var SCHEMAS = {
|
|
|
710
713
|
email: { type: "string" },
|
|
711
714
|
phone: { type: "string" },
|
|
712
715
|
document: { type: "string" },
|
|
713
|
-
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"], default: "juridica" },
|
|
716
|
+
type: { type: "string", enum: ["fisica", "juridica", "estrangeira"], default: "juridica", description: "Natureza JUR\xCDDICA do cadastro, n\xE3o a categoria de atividade: fisica = pessoa f\xEDsica (CPF); juridica = pessoa jur\xEDdica (CNPJ), o que inclui empresas, \xF3rg\xE3os p\xFAblicos, prefeituras e a Receita Federal; estrangeira = sem CNPJ/CPF. Na d\xFAvida, OMITA o campo \u2014 o padr\xE3o j\xE1 cobre o caso comum." },
|
|
714
717
|
company_name: { type: "string" },
|
|
715
718
|
trade_name: { type: "string" },
|
|
716
719
|
state_registration: { type: "string" },
|
|
@@ -780,7 +783,12 @@ var SCHEMAS = {
|
|
|
780
783
|
status: { type: "string", enum: ["pendente", "pago", "cancelado"], default: "pendente" },
|
|
781
784
|
bank_account_id: { type: "string", format: "uuid" },
|
|
782
785
|
payment_method_id: { type: "string", format: "uuid" },
|
|
783
|
-
notes: { type: "string" }
|
|
786
|
+
notes: { type: "string" },
|
|
787
|
+
attachment_ids: {
|
|
788
|
+
type: "array",
|
|
789
|
+
items: { type: "string", format: "uuid" },
|
|
790
|
+
description: "Ids de anexos j\xE1 enviados que devem ser vinculados \xE0 despesa criada. \xC9 o fluxo 'lance esse imposto e anexe o PDF' numa chamada s\xF3."
|
|
791
|
+
}
|
|
784
792
|
}
|
|
785
793
|
},
|
|
786
794
|
PurchaseInvoice: {
|
|
@@ -861,7 +869,12 @@ var SCHEMAS = {
|
|
|
861
869
|
title: { type: "string", description: "Descri\xE7\xE3o da fatura; vira o nome do item quando 'items' n\xE3o \xE9 informado." },
|
|
862
870
|
digitable_line: { type: "string", description: "Atalho: grava o boleto na parcela \xFAnica criada por 'due_date'." },
|
|
863
871
|
pix_key: { type: "string", description: "Atalho: grava a chave Pix na parcela \xFAnica." },
|
|
864
|
-
notes: { type: "string" }
|
|
872
|
+
notes: { type: "string" },
|
|
873
|
+
attachment_ids: {
|
|
874
|
+
type: "array",
|
|
875
|
+
items: { type: "string", format: "uuid" },
|
|
876
|
+
description: "Ids de anexos j\xE1 enviados que devem ser vinculados \xE0 fatura criada. \xC9 o fluxo 'lance esse imposto e anexe o PDF' numa chamada s\xF3."
|
|
877
|
+
}
|
|
865
878
|
}
|
|
866
879
|
},
|
|
867
880
|
Charge: {
|
|
@@ -872,7 +885,7 @@ var SCHEMAS = {
|
|
|
872
885
|
status: { type: "string", enum: ["pending", "paid", "cancelled", "expired", "failed"] },
|
|
873
886
|
status_raw: { type: "string", description: "Status bruto do provider" },
|
|
874
887
|
method: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"] },
|
|
875
|
-
provider: { type: "string", enum: ["inter", "c6bank", "pix_offline", "pagarme"], description: "Provedor resolvido. 'pix_offline' = Pix est\xE1tico (BR Code local). 'pagarme' = Pix server-side ou cart\xE3o (method=credit_card retorna 'checkout.url' = link da p\xE1gina de pagamento)." },
|
|
888
|
+
provider: { type: "string", enum: ["inter", "c6bank", "pix_offline", "pagarme", "cora"], description: "Provedor resolvido. 'pix_offline' = Pix est\xE1tico (BR Code local). 'pagarme' = Pix server-side ou cart\xE3o (method=credit_card retorna 'checkout.url' = link da p\xE1gina de pagamento). 'cora' = boleto ou Pix emitidos de forma s\xEDncrona (o boleto j\xE1 volta com 'pdf_url')." },
|
|
876
889
|
invoice_id: { type: ["string", "null"], format: "uuid" },
|
|
877
890
|
customer_id: { type: ["string", "null"], format: "uuid" },
|
|
878
891
|
amount: { type: ["number", "null"] },
|
|
@@ -889,7 +902,7 @@ var SCHEMAS = {
|
|
|
889
902
|
required: ["method"],
|
|
890
903
|
properties: {
|
|
891
904
|
method: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"], description: "Canal de pagamento" },
|
|
892
|
-
provider: { type: "string", enum: ["inter", "c6bank", "pix_offline", "pagarme"], description: "Opcional. Desambigua quando a empresa tem mais de um provedor no mesmo canal (ex.: Pix Inter x Pix Pagar.me). Se omitido, usa o provedor ativo do canal." },
|
|
905
|
+
provider: { type: "string", enum: ["inter", "c6bank", "pix_offline", "pagarme", "cora"], description: "Opcional. Desambigua quando a empresa tem mais de um provedor no mesmo canal (ex.: Pix Inter x Pix Pagar.me x Pix Cora). Se omitido, usa o provedor ativo do canal." },
|
|
893
906
|
invoice_id: { type: "string", format: "uuid", description: "Fatura existente (opcional)" },
|
|
894
907
|
customer_id: { type: "string", format: "uuid", description: "Obrigat\xF3rio se invoice_id omitido" },
|
|
895
908
|
amount: { type: "number", description: "Obrigat\xF3rio se invoice_id omitido" },
|
|
@@ -1977,6 +1990,9 @@ var OPENAPI_SPEC = {
|
|
|
1977
1990
|
{ name: "payment_status", in: "query", schema: { type: "string", enum: ["pendente", "parcial", "pago", "vencido"] } },
|
|
1978
1991
|
{ name: "customer_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
1979
1992
|
{ name: "due_date_from", in: "query", schema: { type: "string", format: "date" }, description: "Vencimento a partir de (YYYY-MM-DD)" },
|
|
1993
|
+
{ name: "overdue", in: "query", schema: { type: "string", enum: ["true", "false"] }, description: "true = vencidas de VERDADE (vencimento passado e n\xE3o pagas). N\xE3o confunda com payment_status=vencido: esse campo \xE9 agregado e 'parcial' ganha de 'vencido', ent\xE3o uma fatura com parcela paga e parcela vencida N\xC3O aparece l\xE1. Para cobran\xE7a, use este filtro." },
|
|
1994
|
+
{ name: "sort_by", in: "query", description: "Coluna de ordena\xE7\xE3o. Use com sort_order para responder 'as maiores' ou 'as mais recentes'.", schema: { type: "string", enum: ["amount", "due_date", "created_at", "updated_at", "invoice_number"] } },
|
|
1995
|
+
{ name: "sort_order", in: "query", description: "Dire\xE7\xE3o da ordena\xE7\xE3o. Padr\xE3o: desc quando sort_by \xE9 informado.", schema: { type: "string", enum: ["asc", "desc"] } },
|
|
1980
1996
|
{ name: "due_date_to", in: "query", schema: { type: "string", format: "date" }, description: "Vencimento at\xE9 (YYYY-MM-DD)" }
|
|
1981
1997
|
],
|
|
1982
1998
|
responses: {
|
|
@@ -2016,6 +2032,84 @@ var OPENAPI_SPEC = {
|
|
|
2016
2032
|
responses: { "204": { description: "Exclu\xEDda" }, "404": errorResponse("Fatura n\xE3o encontrada"), "409": errorResponse("H\xE1 registros vinculados que impedem a exclus\xE3o"), ...COMMON_ERRORS }
|
|
2017
2033
|
}
|
|
2018
2034
|
},
|
|
2035
|
+
"/contracts/{id}/generate-invoices": {
|
|
2036
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
|
|
2037
|
+
post: {
|
|
2038
|
+
tags: ["Contratos"],
|
|
2039
|
+
summary: "Gerar as faturas devidas do contrato",
|
|
2040
|
+
operationId: "generateContractInvoices",
|
|
2041
|
+
description: "Gera fatura do contrato. Por padr\xE3o (mode=extra) cria uma fatura AVULSA fora do ciclo: n\xE3o avan\xE7a o agendamento, ent\xE3o chamar duas vezes gera DUAS faturas. Use mode=cycle para antecipar a fatura do ciclo corrente \u2014 \xE9 esse modo que avan\xE7a next_generation_date e evita duplicar a compet\xEAncia. mode=skip pula o ciclo sem gerar nada. Contrato cancelado ou suspenso \xE9 recusado.",
|
|
2042
|
+
requestBody: { required: false, content: { "application/json": { schema: { type: "object", properties: { mode: { type: "string", enum: ["extra", "cycle", "skip"], default: "extra", description: "extra = avulsa (repet\xEDvel) \xB7 cycle = fatura do ciclo, avan\xE7a o agendamento \xB7 skip = s\xF3 avan\xE7a" } } } } } },
|
|
2043
|
+
security: [{ ApiKeyAuth: ["invoices:create"] }],
|
|
2044
|
+
responses: {
|
|
2045
|
+
"200": {
|
|
2046
|
+
description: "Gera\xE7\xE3o executada",
|
|
2047
|
+
content: {
|
|
2048
|
+
"application/json": {
|
|
2049
|
+
schema: {
|
|
2050
|
+
type: "object",
|
|
2051
|
+
properties: {
|
|
2052
|
+
contract_id: { type: "string", format: "uuid" },
|
|
2053
|
+
created: { type: "integer", description: "Quantas faturas nasceram nesta chamada." }
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
},
|
|
2059
|
+
...COMMON_ERRORS
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
},
|
|
2063
|
+
"/invoices/{id}/send": {
|
|
2064
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
|
|
2065
|
+
post: {
|
|
2066
|
+
tags: ["Faturas"],
|
|
2067
|
+
summary: "Enviar segunda via da fatura ao cliente",
|
|
2068
|
+
operationId: "sendInvoiceSecondCopy",
|
|
2069
|
+
description: "Envia a segunda via por e-mail. Sem 'to', usa o e-mail cadastrado do cliente. Os anexos da fatura v\xE3o junto por padr\xE3o. Registra a tentativa na fila de e-mails antes de enviar, ent\xE3o um envio que falha deixa rastro.",
|
|
2070
|
+
security: [{ ApiKeyAuth: ["invoices:send"] }],
|
|
2071
|
+
requestBody: {
|
|
2072
|
+
required: false,
|
|
2073
|
+
content: {
|
|
2074
|
+
"application/json": {
|
|
2075
|
+
schema: {
|
|
2076
|
+
type: "object",
|
|
2077
|
+
properties: {
|
|
2078
|
+
to: {
|
|
2079
|
+
description: "Destinat\xE1rio(s). Aceita string separada por v\xEDrgula ou lista. Omitido, usa o e-mail do cliente.",
|
|
2080
|
+
oneOf: [{ type: "string" }, { type: "array", items: { type: "string", format: "email" } }]
|
|
2081
|
+
},
|
|
2082
|
+
subject: { type: "string", description: "Assunto. Padr\xE3o: 'Segunda via da fatura <numero>'." },
|
|
2083
|
+
body_html: { type: "string", description: "Corpo em HTML. Padr\xE3o: mensagem curta com valor e vencimento." },
|
|
2084
|
+
include_attachments: { type: "boolean", default: true, description: "Anexa os arquivos da fatura." }
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
},
|
|
2090
|
+
responses: {
|
|
2091
|
+
"200": {
|
|
2092
|
+
description: "Segunda via enviada",
|
|
2093
|
+
content: {
|
|
2094
|
+
"application/json": {
|
|
2095
|
+
schema: {
|
|
2096
|
+
type: "object",
|
|
2097
|
+
properties: {
|
|
2098
|
+
invoice_id: { type: "string", format: "uuid" },
|
|
2099
|
+
schedule_id: { type: "string", format: "uuid" },
|
|
2100
|
+
recipients: { type: "array", items: { type: "string" } },
|
|
2101
|
+
subject: { type: "string" },
|
|
2102
|
+
attachments: { type: "integer" },
|
|
2103
|
+
sent_at: { type: "string", format: "date-time" }
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
},
|
|
2109
|
+
...COMMON_ERRORS
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
},
|
|
2019
2113
|
"/invoices/{id}/cancel": {
|
|
2020
2114
|
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string", format: "uuid" } }],
|
|
2021
2115
|
patch: {
|
|
@@ -2241,6 +2335,52 @@ var OPENAPI_SPEC = {
|
|
|
2241
2335
|
responses: { "200": paginatedResponse("#/components/schemas/ServiceUnit"), ...COMMON_ERRORS }
|
|
2242
2336
|
}
|
|
2243
2337
|
},
|
|
2338
|
+
"/documents": {
|
|
2339
|
+
get: {
|
|
2340
|
+
tags: ["Documentos"],
|
|
2341
|
+
summary: "Procurar anexos j\xE1 enviados",
|
|
2342
|
+
operationId: "listDocuments",
|
|
2343
|
+
description: "Busca anexos da empresa por nome do arquivo e/ou entidade a que est\xE3o ligados. Ordenado do mais recente para o mais antigo \u2014 \xE9 o que 'aquele boleto que mandei' quer dizer na pr\xE1tica.",
|
|
2344
|
+
security: [{ ApiKeyAuth: ["documents:read"] }],
|
|
2345
|
+
parameters: [
|
|
2346
|
+
...PAGINATION_PARAMS,
|
|
2347
|
+
{ name: "search", in: "query", schema: { type: "string" }, description: "Trecho do nome do arquivo." },
|
|
2348
|
+
{ name: "entity_type", in: "query", schema: { type: "string", enum: ["invoice", "purchase_invoice", "expense", "proposal", "contract", "customer", "supplier", "payment", "supplier_payment", "agent_message"] } },
|
|
2349
|
+
{ name: "entity_id", in: "query", schema: { type: "string", format: "uuid" }, description: "Anexos de um registro espec\xEDfico." }
|
|
2350
|
+
],
|
|
2351
|
+
responses: {
|
|
2352
|
+
"200": {
|
|
2353
|
+
description: "Anexos encontrados",
|
|
2354
|
+
content: {
|
|
2355
|
+
"application/json": {
|
|
2356
|
+
schema: {
|
|
2357
|
+
type: "object",
|
|
2358
|
+
properties: {
|
|
2359
|
+
data: {
|
|
2360
|
+
type: "array",
|
|
2361
|
+
items: {
|
|
2362
|
+
type: "object",
|
|
2363
|
+
properties: {
|
|
2364
|
+
id: { type: "string", format: "uuid" },
|
|
2365
|
+
entity_type: { type: "string" },
|
|
2366
|
+
entity_id: { type: "string", format: "uuid", nullable: true },
|
|
2367
|
+
file_name: { type: "string" },
|
|
2368
|
+
file_path: { type: "string" },
|
|
2369
|
+
file_size: { type: "integer" },
|
|
2370
|
+
mime_type: { type: "string", nullable: true },
|
|
2371
|
+
created_at: { type: "string", format: "date-time" }
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
},
|
|
2380
|
+
...COMMON_ERRORS
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
},
|
|
2244
2384
|
"/documents/analyze": {
|
|
2245
2385
|
post: {
|
|
2246
2386
|
tags: ["Documentos"],
|
|
@@ -2325,7 +2465,7 @@ var OPENAPI_SPEC = {
|
|
|
2325
2465
|
summary: "Listar categorias de servi\xE7o",
|
|
2326
2466
|
operationId: "listServiceCategories",
|
|
2327
2467
|
security: [{ ApiKeyAuth: ["services:read"] }],
|
|
2328
|
-
parameters: [...PAGINATION_PARAMS, { name: "search", in: "query", schema: { type: "string" }, description: "Filtro por nome (ilike)" }],
|
|
2468
|
+
parameters: [...PAGINATION_PARAMS, { name: "search", in: "query", schema: { type: "string" }, description: "Filtro por nome (ilike)" }, { name: "query", in: "query", schema: { type: "string" }, description: "Apelido de 'search' \u2014 o c\xF3digo j\xE1 aceitava os dois nomes; agora est\xE1 documentado." }],
|
|
2329
2469
|
responses: { "200": paginatedResponse("#/components/schemas/ServiceCategory"), ...COMMON_ERRORS }
|
|
2330
2470
|
},
|
|
2331
2471
|
post: {
|
|
@@ -2370,14 +2510,33 @@ var OPENAPI_SPEC = {
|
|
|
2370
2510
|
{ name: "min_overdue_days", in: "query", schema: { type: "integer", minimum: 1, maximum: 365, default: 1 } },
|
|
2371
2511
|
{ name: "include_shared", in: "query", schema: { type: "boolean", default: true }, description: "Incluir clientes compartilhados" },
|
|
2372
2512
|
{ name: "customer_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
2373
|
-
{ name: "search", in: "query", schema: { type: "string" } }
|
|
2513
|
+
{ name: "search", in: "query", schema: { type: "string" } },
|
|
2514
|
+
{ name: "company_id", in: "query", schema: { type: "string", format: "uuid" }, description: "Restringe a UMA empresa: a sua, ou a dona de um cliente compartilhado. Aplicado SOBRE o escopo permitido \u2014 nunca amplia acesso." },
|
|
2515
|
+
{ name: "query", in: "query", schema: { type: "string" }, description: "Apelido de 'search' \u2014 o c\xF3digo j\xE1 aceitava os dois nomes; agora est\xE1 documentado." }
|
|
2374
2516
|
],
|
|
2375
2517
|
responses: { "200": { description: "Faturas em atraso + a\xE7\xF5es recomendadas", content: { "application/json": { schema: { type: "object", properties: {
|
|
2376
2518
|
count: { type: "integer" },
|
|
2377
2519
|
limit: { type: "integer" },
|
|
2378
2520
|
min_overdue_days: { type: "integer" },
|
|
2379
|
-
total_overdue_amount: { type: "number" },
|
|
2380
|
-
|
|
2521
|
+
total_overdue_amount: { type: "number", description: "Soma do SALDO em aberto (valor da fatura menos o que j\xE1 foi pago) \u2014 o que ainda d\xE1 para cobrar." },
|
|
2522
|
+
total_invoiced_amount: { type: "number", description: "Soma do valor cheio das mesmas faturas, ignorando pagamentos parciais." },
|
|
2523
|
+
actions: { type: "array", items: { type: "object", properties: {
|
|
2524
|
+
invoice_id: { type: "string", format: "uuid" },
|
|
2525
|
+
company_id: { type: "string", format: "uuid", description: "Empresa DONA da fatura. Com clientes compartilhados a lista mistura empresas; sem este campo n\xE3o d\xE1 para saber de quem \xE9 cada linha." },
|
|
2526
|
+
company_name: { type: "string", nullable: true },
|
|
2527
|
+
invoice_number: { type: "string", nullable: true },
|
|
2528
|
+
title: { type: "string", nullable: true },
|
|
2529
|
+
customer_id: { type: "string", format: "uuid" },
|
|
2530
|
+
customer_name: { type: "string", nullable: true },
|
|
2531
|
+
amount: { type: "number", description: "Valor cheio da fatura." },
|
|
2532
|
+
paid_amount: { type: "number", description: "Quanto j\xE1 foi pago nesta fatura." },
|
|
2533
|
+
outstanding_amount: { type: "number", description: "Saldo devedor \u2014 \xE9 este o valor a cobrar." },
|
|
2534
|
+
due_date: { type: "string", format: "date", nullable: true },
|
|
2535
|
+
payment_status: { type: "string" },
|
|
2536
|
+
status: { type: "string" },
|
|
2537
|
+
days_overdue: { type: "integer" },
|
|
2538
|
+
recommended_action: { type: "string" }
|
|
2539
|
+
} } }
|
|
2381
2540
|
} } } } }, ...COMMON_ERRORS }
|
|
2382
2541
|
}
|
|
2383
2542
|
},
|
|
@@ -2591,7 +2750,9 @@ var OPENAPI_SPEC = {
|
|
|
2591
2750
|
{ name: "supplier_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
2592
2751
|
{ name: "category_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
2593
2752
|
{ name: "expense_date_from", in: "query", schema: { type: "string", format: "date" } },
|
|
2594
|
-
{ name: "expense_date_to", in: "query", schema: { type: "string", format: "date" } }
|
|
2753
|
+
{ name: "expense_date_to", in: "query", schema: { type: "string", format: "date" } },
|
|
2754
|
+
{ name: "sort_by", in: "query", description: "Coluna de ordena\xE7\xE3o. Use com sort_order para responder 'as maiores' ou 'as mais recentes'.", schema: { type: "string", enum: ["amount", "expense_date", "due_date", "created_at", "updated_at"] } },
|
|
2755
|
+
{ name: "sort_order", in: "query", description: "Dire\xE7\xE3o da ordena\xE7\xE3o. Padr\xE3o: desc quando sort_by \xE9 informado.", schema: { type: "string", enum: ["asc", "desc"] } }
|
|
2595
2756
|
],
|
|
2596
2757
|
responses: { "200": paginatedResponse("#/components/schemas/Expense"), ...COMMON_ERRORS }
|
|
2597
2758
|
},
|
|
@@ -2645,7 +2806,10 @@ var OPENAPI_SPEC = {
|
|
|
2645
2806
|
{ name: "supplier_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
2646
2807
|
{ name: "invoice_number", in: "query", schema: { type: "string" } },
|
|
2647
2808
|
{ name: "due_date_from", in: "query", schema: { type: "string", format: "date" } },
|
|
2648
|
-
{ name: "due_date_to", in: "query", schema: { type: "string", format: "date" } }
|
|
2809
|
+
{ name: "due_date_to", in: "query", schema: { type: "string", format: "date" } },
|
|
2810
|
+
{ name: "overdue", in: "query", schema: { type: "string", enum: ["true", "false"] }, description: "true = contas a pagar com parcela vencida e n\xE3o paga. O vencimento mora nas parcelas, ent\xE3o o status agregado da fatura n\xE3o responde isso." },
|
|
2811
|
+
{ name: "sort_by", in: "query", description: "Coluna de ordena\xE7\xE3o. Use com sort_order para responder 'as maiores' ou 'as mais recentes'.", schema: { type: "string", enum: ["amount", "issue_date", "created_at", "updated_at", "invoice_number"] } },
|
|
2812
|
+
{ name: "sort_order", in: "query", description: "Dire\xE7\xE3o da ordena\xE7\xE3o. Padr\xE3o: desc quando sort_by \xE9 informado.", schema: { type: "string", enum: ["asc", "desc"] } }
|
|
2649
2813
|
],
|
|
2650
2814
|
responses: { "200": paginatedResponse("#/components/schemas/PurchaseInvoice"), ...COMMON_ERRORS }
|
|
2651
2815
|
},
|
|
@@ -2700,7 +2864,9 @@ var OPENAPI_SPEC = {
|
|
|
2700
2864
|
{ name: "status", in: "query", schema: { type: "string", enum: ["pending", "paid", "cancelled", "expired", "failed"] } },
|
|
2701
2865
|
{ name: "method", in: "query", schema: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"] } },
|
|
2702
2866
|
{ name: "customer_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
2703
|
-
{ name: "invoice_id", in: "query", schema: { type: "string", format: "uuid" } }
|
|
2867
|
+
{ name: "invoice_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
2868
|
+
{ name: "sort_by", in: "query", description: "Coluna de ordena\xE7\xE3o. Use com sort_order para responder 'as maiores' ou 'as mais recentes'.", schema: { type: "string", enum: ["amount", "due_date", "created_at", "paid_at"] } },
|
|
2869
|
+
{ name: "sort_order", in: "query", description: "Dire\xE7\xE3o da ordena\xE7\xE3o. Padr\xE3o: desc quando sort_by \xE9 informado.", schema: { type: "string", enum: ["asc", "desc"] } }
|
|
2704
2870
|
],
|
|
2705
2871
|
responses: { "200": paginatedResponse("#/components/schemas/Charge"), ...COMMON_ERRORS }
|
|
2706
2872
|
},
|
|
@@ -3143,7 +3309,8 @@ var OPENAPI_SPEC = {
|
|
|
3143
3309
|
...PAGINATION_PARAMS,
|
|
3144
3310
|
{ name: "active", in: "query", schema: { type: "string", enum: ["true", "false"] } },
|
|
3145
3311
|
{ name: "provider", in: "query", schema: { type: "string", enum: ["inter", "c6bank"] } },
|
|
3146
|
-
{ name: "channel", in: "query", schema: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"] } }
|
|
3312
|
+
{ name: "channel", in: "query", schema: { type: "string", enum: ["pix", "boleto", "checkout", "credit_card"] } },
|
|
3313
|
+
{ name: "all", in: "query", description: "true lista TODAS as formas cadastradas; por padr\xE3o s\xF3 as utiliz\xE1veis (manuais ou de provider com integra\xE7\xE3o ativa).", schema: { type: "string", enum: ["true", "false"] } }
|
|
3147
3314
|
],
|
|
3148
3315
|
responses: { "200": paginatedResponse("#/components/schemas/PaymentMethod"), ...COMMON_ERRORS }
|
|
3149
3316
|
}
|
|
@@ -3201,6 +3368,7 @@ var API_MODULES = [
|
|
|
3201
3368
|
{ key: "read", label: "Listar e visualizar", description: "Consultar faturas e cobran\xE7as" },
|
|
3202
3369
|
{ key: "create", label: "Criar cobran\xE7a", description: "Gerar boletos, Pix e cobran\xE7as" },
|
|
3203
3370
|
{ key: "cancel", label: "Cancelar cobran\xE7a", description: "Cancelar cobran\xE7as em aberto" },
|
|
3371
|
+
{ key: "send", label: "Enviar ao cliente", description: "Enviar segunda via da fatura por e-mail ao cliente" },
|
|
3204
3372
|
{ key: "delete", label: "Excluir fatura", description: "Excluir faturas permanentemente (itens e cobran\xE7as vinculadas)" }
|
|
3205
3373
|
]
|
|
3206
3374
|
},
|
|
@@ -3433,7 +3601,6 @@ function describeOperation(operationId) {
|
|
|
3433
3601
|
scopes: extractScopes(operation),
|
|
3434
3602
|
inputSchema,
|
|
3435
3603
|
summary: operation.summary,
|
|
3436
|
-
description: operation.description,
|
|
3437
3604
|
description: operation.description
|
|
3438
3605
|
};
|
|
3439
3606
|
}
|
|
@@ -3558,6 +3725,9 @@ function buildCuratedTools(api, heldScopes) {
|
|
|
3558
3725
|
const description = `${prefix}${desc.summary ?? entry.operationId}.${scopeNote}`;
|
|
3559
3726
|
tools.push({
|
|
3560
3727
|
name: entry.tool,
|
|
3728
|
+
// O `summary` da OpenAPI já é escrito em português — é ele que vira o rótulo no
|
|
3729
|
+
// cliente. Sem isso o Claude Desktop humaniza o nome técnico ("Customers list").
|
|
3730
|
+
title: desc.summary?.trim() || void 0,
|
|
3561
3731
|
description,
|
|
3562
3732
|
inputSchema: asInputSchema(inputSchema),
|
|
3563
3733
|
handler: async (args) => {
|
|
@@ -3593,9 +3763,31 @@ function buildCuratedTools(api, heldScopes) {
|
|
|
3593
3763
|
|
|
3594
3764
|
// src/tools/request.ts
|
|
3595
3765
|
var METHODS = ["GET", "POST", "PATCH", "PUT", "DELETE"];
|
|
3766
|
+
var ROTAS_DESTRUTIVAS = (() => {
|
|
3767
|
+
const out = [];
|
|
3768
|
+
for (const entry of MANIFEST) {
|
|
3769
|
+
if (!entry.destructive) continue;
|
|
3770
|
+
let desc;
|
|
3771
|
+
try {
|
|
3772
|
+
desc = describeOperation(entry.operationId);
|
|
3773
|
+
} catch {
|
|
3774
|
+
continue;
|
|
3775
|
+
}
|
|
3776
|
+
const padrao = desc.pathTemplate.split("/").map(
|
|
3777
|
+
(seg) => seg.startsWith("{") && seg.endsWith("}") ? "[^/]+" : seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
3778
|
+
).join("/");
|
|
3779
|
+
out.push({ method: desc.method.toUpperCase(), re: new RegExp(`^${padrao}/?$`) });
|
|
3780
|
+
}
|
|
3781
|
+
return out;
|
|
3782
|
+
})();
|
|
3783
|
+
function ehRotaDestrutiva(method, path) {
|
|
3784
|
+
const semQuery = path.split("?")[0];
|
|
3785
|
+
return ROTAS_DESTRUTIVAS.some((r) => r.method === method.toUpperCase() && r.re.test(semQuery));
|
|
3786
|
+
}
|
|
3596
3787
|
function buildRequestTool(api) {
|
|
3597
3788
|
return {
|
|
3598
3789
|
name: "comando_request",
|
|
3790
|
+
title: "Chamada livre \xE0 API",
|
|
3599
3791
|
description: "Chamada gen\xE9rica \xE0 API do Comando.One (cobre qualquer endpoint /v1/*). Use quando n\xE3o houver uma tool espec\xEDfica. Ex.: method=GET, path=/webhooks/deliveries. Os scopes da chave s\xE3o validados pelo servidor.",
|
|
3600
3792
|
inputSchema: {
|
|
3601
3793
|
type: "object",
|
|
@@ -3615,7 +3807,7 @@ function buildRequestTool(api) {
|
|
|
3615
3807
|
company_id: { type: "string", description: "Opcional: UUID da empresa (header X-Company-Id)." },
|
|
3616
3808
|
idempotency_key: { type: "string", description: "Opcional: chave de idempot\xEAncia (POST)." },
|
|
3617
3809
|
dry_run: { type: "boolean", description: "Se true, n\xE3o executa \u2014 s\xF3 mostra o que seria enviado." },
|
|
3618
|
-
confirm: { type: "boolean", description: "Obrigat\xF3rio para DELETE
|
|
3810
|
+
confirm: { type: "boolean", description: "Obrigat\xF3rio para DELETE e para qualquer rota destrutiva (cancelar, estornar, pagar, reverter)." }
|
|
3619
3811
|
}
|
|
3620
3812
|
},
|
|
3621
3813
|
handler: async (args) => {
|
|
@@ -3624,13 +3816,13 @@ function buildRequestTool(api) {
|
|
|
3624
3816
|
if (!METHODS.includes(method)) {
|
|
3625
3817
|
return fail(`M\xE9todo inv\xE1lido: ${args.method}. Use um de: ${METHODS.join(", ")}.`);
|
|
3626
3818
|
}
|
|
3627
|
-
|
|
3819
|
+
let path = String(args.path ?? "");
|
|
3820
|
+
if (!path.startsWith("/")) return fail("path deve come\xE7ar com / (ex.: /customers).");
|
|
3821
|
+
if ((method === "DELETE" || ehRotaDestrutiva(method, path)) && args.confirm !== true && args.dry_run !== true) {
|
|
3628
3822
|
return fail(
|
|
3629
3823
|
"A\xE7\xE3o destrutiva bloqueada. Passe confirm: true para executar, ou dry_run: true para pr\xE9-visualizar."
|
|
3630
3824
|
);
|
|
3631
3825
|
}
|
|
3632
|
-
let path = String(args.path ?? "");
|
|
3633
|
-
if (!path.startsWith("/")) return fail("path deve come\xE7ar com / (ex.: /customers).");
|
|
3634
3826
|
const queryArg = coerceObjectArg(args.query);
|
|
3635
3827
|
if (queryArg) {
|
|
3636
3828
|
const u = new URLSearchParams();
|
|
@@ -3670,6 +3862,7 @@ var KINDS = {
|
|
|
3670
3862
|
function buildLookupsTool(api) {
|
|
3671
3863
|
return {
|
|
3672
3864
|
name: "lookups",
|
|
3865
|
+
title: "Consultar cat\xE1logos",
|
|
3673
3866
|
description: "Consulta cat\xE1logos read-only do ERP: centros de custo, condi\xE7\xF5es/m\xE9todos de pagamento, unidades de servi\xE7o, naturezas financeiras e contas banc\xE1rias.",
|
|
3674
3867
|
inputSchema: {
|
|
3675
3868
|
type: "object",
|
|
@@ -3710,6 +3903,7 @@ function buildLookupsTool(api) {
|
|
|
3710
3903
|
function buildWhoamiTool(api) {
|
|
3711
3904
|
return {
|
|
3712
3905
|
name: "whoami",
|
|
3906
|
+
title: "Identidade da chave",
|
|
3713
3907
|
description: "Retorna a identidade da chave de API: empresa atual, empresas acess\xEDveis, scopes concedidos e se \xE9 multi-empresa.",
|
|
3714
3908
|
inputSchema: { type: "object", properties: {} },
|
|
3715
3909
|
handler: async () => {
|
|
@@ -3722,6 +3916,20 @@ function buildWhoamiTool(api) {
|
|
|
3722
3916
|
};
|
|
3723
3917
|
}
|
|
3724
3918
|
|
|
3919
|
+
// src/branding.ts
|
|
3920
|
+
var MCP_SERVER_NAME = "comando-one";
|
|
3921
|
+
var MCP_SERVER_TITLE = "Comando.One";
|
|
3922
|
+
var MCP_SERVER_VERSION = "0.5.0";
|
|
3923
|
+
var MCP_SERVER_DESCRIPTION = "ERP das empresas de servi\xE7o brasileiras: clientes, propostas, contratos, faturas, cobran\xE7as Pix e boleto, NFS-e, contas a pagar e financeiro.";
|
|
3924
|
+
var MCP_SERVER_WEBSITE = "https://comando.one";
|
|
3925
|
+
var MCP_SERVER_ICONS = [
|
|
3926
|
+
{
|
|
3927
|
+
src: "data:image/png;base64,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",
|
|
3928
|
+
mimeType: "image/png",
|
|
3929
|
+
sizes: ["96x96"]
|
|
3930
|
+
}
|
|
3931
|
+
];
|
|
3932
|
+
|
|
3725
3933
|
// src/index.ts
|
|
3726
3934
|
function loadDotEnv() {
|
|
3727
3935
|
try {
|
|
@@ -3774,11 +3982,27 @@ async function main() {
|
|
|
3774
3982
|
`
|
|
3775
3983
|
);
|
|
3776
3984
|
const server = new Server(
|
|
3777
|
-
{
|
|
3985
|
+
{
|
|
3986
|
+
name: MCP_SERVER_NAME,
|
|
3987
|
+
// `title` é o nome que o app mostra; `icons` é a marca no lugar da inicial genérica.
|
|
3988
|
+
title: MCP_SERVER_TITLE,
|
|
3989
|
+
version: MCP_SERVER_VERSION,
|
|
3990
|
+
description: MCP_SERVER_DESCRIPTION,
|
|
3991
|
+
websiteUrl: MCP_SERVER_WEBSITE,
|
|
3992
|
+
icons: MCP_SERVER_ICONS
|
|
3993
|
+
},
|
|
3778
3994
|
{ capabilities: { tools: {} } }
|
|
3779
3995
|
);
|
|
3780
3996
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
3781
|
-
|
|
3997
|
+
// `title` e `annotations.title` juntos: revisões mais novas do protocolo leem o
|
|
3998
|
+
// primeiro, as anteriores leem o segundo. Sem nenhum dos dois o cliente cai no nome
|
|
3999
|
+
// técnico em inglês.
|
|
4000
|
+
tools: tools.map((t) => ({
|
|
4001
|
+
name: t.name,
|
|
4002
|
+
...t.title ? { title: t.title, annotations: { title: t.title } } : {},
|
|
4003
|
+
description: t.description,
|
|
4004
|
+
inputSchema: t.inputSchema
|
|
4005
|
+
}))
|
|
3782
4006
|
}));
|
|
3783
4007
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
3784
4008
|
const tool = byName.get(req.params.name);
|
package/package.json
CHANGED