@comando.one/mcp-server 0.5.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/dist/index.js +30 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2038,7 +2038,8 @@ var OPENAPI_SPEC = {
|
|
|
2038
2038
|
tags: ["Contratos"],
|
|
2039
2039
|
summary: "Gerar as faturas devidas do contrato",
|
|
2040
2040
|
operationId: "generateContractInvoices",
|
|
2041
|
-
description: "Gera
|
|
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" } } } } } },
|
|
2042
2043
|
security: [{ ApiKeyAuth: ["invoices:create"] }],
|
|
2043
2044
|
responses: {
|
|
2044
2045
|
"200": {
|
|
@@ -2510,6 +2511,7 @@ var OPENAPI_SPEC = {
|
|
|
2510
2511
|
{ name: "include_shared", in: "query", schema: { type: "boolean", default: true }, description: "Incluir clientes compartilhados" },
|
|
2511
2512
|
{ name: "customer_id", in: "query", schema: { type: "string", format: "uuid" } },
|
|
2512
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." },
|
|
2513
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." }
|
|
2514
2516
|
],
|
|
2515
2517
|
responses: { "200": { description: "Faturas em atraso + a\xE7\xF5es recomendadas", content: { "application/json": { schema: { type: "object", properties: {
|
|
@@ -2520,6 +2522,8 @@ var OPENAPI_SPEC = {
|
|
|
2520
2522
|
total_invoiced_amount: { type: "number", description: "Soma do valor cheio das mesmas faturas, ignorando pagamentos parciais." },
|
|
2521
2523
|
actions: { type: "array", items: { type: "object", properties: {
|
|
2522
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 },
|
|
2523
2527
|
invoice_number: { type: "string", nullable: true },
|
|
2524
2528
|
title: { type: "string", nullable: true },
|
|
2525
2529
|
customer_id: { type: "string", format: "uuid" },
|
|
@@ -3759,6 +3763,27 @@ function buildCuratedTools(api, heldScopes) {
|
|
|
3759
3763
|
|
|
3760
3764
|
// src/tools/request.ts
|
|
3761
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
|
+
}
|
|
3762
3787
|
function buildRequestTool(api) {
|
|
3763
3788
|
return {
|
|
3764
3789
|
name: "comando_request",
|
|
@@ -3782,7 +3807,7 @@ function buildRequestTool(api) {
|
|
|
3782
3807
|
company_id: { type: "string", description: "Opcional: UUID da empresa (header X-Company-Id)." },
|
|
3783
3808
|
idempotency_key: { type: "string", description: "Opcional: chave de idempot\xEAncia (POST)." },
|
|
3784
3809
|
dry_run: { type: "boolean", description: "Se true, n\xE3o executa \u2014 s\xF3 mostra o que seria enviado." },
|
|
3785
|
-
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)." }
|
|
3786
3811
|
}
|
|
3787
3812
|
},
|
|
3788
3813
|
handler: async (args) => {
|
|
@@ -3791,13 +3816,13 @@ function buildRequestTool(api) {
|
|
|
3791
3816
|
if (!METHODS.includes(method)) {
|
|
3792
3817
|
return fail(`M\xE9todo inv\xE1lido: ${args.method}. Use um de: ${METHODS.join(", ")}.`);
|
|
3793
3818
|
}
|
|
3794
|
-
|
|
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) {
|
|
3795
3822
|
return fail(
|
|
3796
3823
|
"A\xE7\xE3o destrutiva bloqueada. Passe confirm: true para executar, ou dry_run: true para pr\xE9-visualizar."
|
|
3797
3824
|
);
|
|
3798
3825
|
}
|
|
3799
|
-
let path = String(args.path ?? "");
|
|
3800
|
-
if (!path.startsWith("/")) return fail("path deve come\xE7ar com / (ex.: /customers).");
|
|
3801
3826
|
const queryArg = coerceObjectArg(args.query);
|
|
3802
3827
|
if (queryArg) {
|
|
3803
3828
|
const u = new URLSearchParams();
|
package/package.json
CHANGED