beplus-mcp 0.11.0 → 0.13.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/dist/index.js +113 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -157,7 +157,15 @@ var BeplusClient = class {
|
|
|
157
157
|
return this.request("DELETE", `/generations/${id}`);
|
|
158
158
|
}
|
|
159
159
|
listGenerations(query) {
|
|
160
|
-
return this.request("GET", "/generations", {
|
|
160
|
+
return this.request("GET", "/generations", {
|
|
161
|
+
query: {
|
|
162
|
+
limit: query.limit,
|
|
163
|
+
offset: query.offset,
|
|
164
|
+
// Only send when true — the backend treats truthy as "constrain".
|
|
165
|
+
favorite: query.favorite ? "true" : void 0,
|
|
166
|
+
approved: query.approved ? "true" : void 0
|
|
167
|
+
}
|
|
168
|
+
});
|
|
161
169
|
}
|
|
162
170
|
tts(body) {
|
|
163
171
|
return this.request("POST", "/tts", { body, timeoutMs: 9e4 });
|
|
@@ -181,7 +189,18 @@ var BeplusClient = class {
|
|
|
181
189
|
return this.request("POST", "/analyze-media", { body, timeoutMs: 3e5 });
|
|
182
190
|
}
|
|
183
191
|
searchCalls(query) {
|
|
184
|
-
return this.request("GET", "/calls", {
|
|
192
|
+
return this.request("GET", "/calls", {
|
|
193
|
+
query: {
|
|
194
|
+
query: query.query,
|
|
195
|
+
project: query.project,
|
|
196
|
+
client: query.client,
|
|
197
|
+
company: query.company,
|
|
198
|
+
visibility: query.visibility,
|
|
199
|
+
speaker: query.speaker,
|
|
200
|
+
mine: query.mine ? "true" : void 0,
|
|
201
|
+
limit: query.limit
|
|
202
|
+
}
|
|
203
|
+
});
|
|
185
204
|
}
|
|
186
205
|
getCall(id) {
|
|
187
206
|
return this.request("GET", `/calls/${id}`);
|
|
@@ -363,6 +382,25 @@ function logError(...args) {
|
|
|
363
382
|
}
|
|
364
383
|
|
|
365
384
|
// src/format.ts
|
|
385
|
+
function fmtResetDate(iso) {
|
|
386
|
+
const [, m, d] = iso.split("-");
|
|
387
|
+
return d && m ? `${d}/${m}` : iso;
|
|
388
|
+
}
|
|
389
|
+
function weeklyAllowanceLine(wa) {
|
|
390
|
+
if (!wa || !wa.enabled) return "";
|
|
391
|
+
if (wa.unlimited) return "\u267E\uFE0F Limite semanal: ilimitado (sua conta \xE9 isenta).";
|
|
392
|
+
const pct = wa.percentUsed;
|
|
393
|
+
const icon = pct >= 100 ? "\u{1F6D1}" : pct >= wa.warnThresholdPercent ? "\u26A0\uFE0F" : "\u{1F4CA}";
|
|
394
|
+
let line = `${icon} Limite semanal: ${pct}% usado \xB7 ${wa.remaining} de ${wa.quota} restantes`;
|
|
395
|
+
if (pct >= 100) {
|
|
396
|
+
line += `
|
|
397
|
+
\u{1F6D1} Limite semanal atingido \u2014 reseta em ${fmtResetDate(wa.periodEnd)}.`;
|
|
398
|
+
} else if (pct >= wa.warnThresholdPercent) {
|
|
399
|
+
line += `
|
|
400
|
+
\u26A0\uFE0F Seu limite semanal est\xE1 acabando \u2014 reseta em ${fmtResetDate(wa.periodEnd)}.`;
|
|
401
|
+
}
|
|
402
|
+
return line;
|
|
403
|
+
}
|
|
366
404
|
function textResult(s) {
|
|
367
405
|
return { content: [{ type: "text", text: s }] };
|
|
368
406
|
}
|
|
@@ -390,6 +428,9 @@ ${footer}`;
|
|
|
390
428
|
footer = footer ? `${proj}
|
|
391
429
|
${footer}` : proj;
|
|
392
430
|
}
|
|
431
|
+
const wa = weeklyAllowanceLine(start.weekly_allowance);
|
|
432
|
+
if (wa) footer = footer ? `${footer}
|
|
433
|
+
${wa}` : wa;
|
|
393
434
|
return footer;
|
|
394
435
|
}
|
|
395
436
|
function outputUrls(status) {
|
|
@@ -497,6 +538,22 @@ var DEFAULTS = {
|
|
|
497
538
|
// src/tools/generation.ts
|
|
498
539
|
var IMAGE_BUDGET_MS = 9e4;
|
|
499
540
|
var VIDEO_BUDGET_MS = 12e4;
|
|
541
|
+
function flagsLine(g) {
|
|
542
|
+
const parts = [
|
|
543
|
+
g.is_favorite ? "\u2B50 like" : null,
|
|
544
|
+
g.is_approved_plan ? "\u2714\uFE0F aprovado" : null
|
|
545
|
+
].filter(Boolean);
|
|
546
|
+
return parts.length ? `
|
|
547
|
+
${parts.join(" \xB7 ")}` : "";
|
|
548
|
+
}
|
|
549
|
+
function firstOutputUrl(output) {
|
|
550
|
+
if (!output) return null;
|
|
551
|
+
const o = output;
|
|
552
|
+
if (Array.isArray(o) && typeof o[0] === "string") return o[0];
|
|
553
|
+
if (Array.isArray(o.urls) && typeof o.urls[0] === "string") return o.urls[0];
|
|
554
|
+
if (typeof o.url === "string") return o.url;
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
500
557
|
function registerGenerationTools(server, client, cfg) {
|
|
501
558
|
server.registerTool(
|
|
502
559
|
"generate_image",
|
|
@@ -777,7 +834,7 @@ ${footer}`);
|
|
|
777
834
|
const blocks = await buildImageBlocks(urls, cfg);
|
|
778
835
|
const list = urls.map((u, i) => `${i + 1}. ${u}`).join("\n") || "(sem URLs)";
|
|
779
836
|
return { content: [{ type: "text", text: `\u2705 Pronto.
|
|
780
|
-
${list}` }, ...blocks] };
|
|
837
|
+
${list}${flagsLine(status)}` }, ...blocks] };
|
|
781
838
|
}
|
|
782
839
|
if (status.status === "failed") {
|
|
783
840
|
return errorResult(`Gera\xE7\xE3o falhou: ${status.error_message || "erro desconhecido"}.`);
|
|
@@ -790,6 +847,43 @@ ${list}` }, ...blocks] };
|
|
|
790
847
|
}
|
|
791
848
|
}
|
|
792
849
|
);
|
|
850
|
+
server.registerTool(
|
|
851
|
+
"list_generations",
|
|
852
|
+
{
|
|
853
|
+
title: "Listar gera\xE7\xF5es",
|
|
854
|
+
description: 'Lista as suas gera\xE7\xF5es (imagens/v\xEDdeos) mais recentes, com os flags de favorito ("like") e de plano aprovado. Use os filtros favorite=true / approved=true para ver s\xF3 as favoritadas ou s\xF3 as aprovadas. Retorna id, modelo, tipo, status, data, um trecho do prompt e (quando h\xE1) a URL.',
|
|
855
|
+
inputSchema: {
|
|
856
|
+
limit: z.number().int().min(1).max(100).optional().describe("Quantas trazer (padr\xE3o 20, m\xE1x 100)."),
|
|
857
|
+
offset: z.number().int().min(0).optional().describe("Deslocamento para paginar (padr\xE3o 0)."),
|
|
858
|
+
favorite: z.boolean().optional().describe('S\xF3 as favoritadas ("like"). Padr\xE3o: todas.'),
|
|
859
|
+
approved: z.boolean().optional().describe("S\xF3 as com plano aprovado. Padr\xE3o: todas.")
|
|
860
|
+
}
|
|
861
|
+
},
|
|
862
|
+
async ({ limit, offset, favorite, approved }) => {
|
|
863
|
+
try {
|
|
864
|
+
const { generations } = await client.listGenerations({ limit, offset, favorite, approved });
|
|
865
|
+
if (!generations.length) {
|
|
866
|
+
const scope = favorite && approved ? " (favoritadas + aprovadas)" : favorite ? " favoritadas" : approved ? " aprovadas" : "";
|
|
867
|
+
return textResult(`Nenhuma gera\xE7\xE3o${scope} encontrada.`);
|
|
868
|
+
}
|
|
869
|
+
const lines = generations.map((g, i) => {
|
|
870
|
+
const type = g.generation_type || "image";
|
|
871
|
+
const when = g.created_at ? new Date(g.created_at).toISOString().slice(0, 10) : "\u2014";
|
|
872
|
+
const prompt = (g.prompt || "").replace(/\s+/g, " ").slice(0, 80);
|
|
873
|
+
const url = firstOutputUrl(g.output);
|
|
874
|
+
const marks = [g.is_favorite ? "\u2B50" : null, g.is_approved_plan ? "\u2714\uFE0F" : null].filter(Boolean).join(" ");
|
|
875
|
+
const marksSuffix = marks ? ` ${marks}` : "";
|
|
876
|
+
return `${i + 1}. ${type} \xB7 ${g.status} \xB7 ${when} \xB7 ${g.model}${marksSuffix}
|
|
877
|
+
${g.id}
|
|
878
|
+
"${prompt}"${url ? `
|
|
879
|
+
${url}` : ""}`;
|
|
880
|
+
});
|
|
881
|
+
return textResult(lines.join("\n\n"));
|
|
882
|
+
} catch (e) {
|
|
883
|
+
return errorResult(apiErrorToUserMessage(e));
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
);
|
|
793
887
|
server.registerTool(
|
|
794
888
|
"cancel_generation",
|
|
795
889
|
{
|
|
@@ -895,10 +989,12 @@ function registerAudioTools(server, client, cfg) {
|
|
|
895
989
|
if (res.diamonds_refunded) parts.push(`Estorno: ${res.diamonds_refunded} \u{1F48E}`);
|
|
896
990
|
const projLine = res.project_code ? `
|
|
897
991
|
\u{1F4C1} Projeto: ${res.project_code}${res.project_name ? ` \u2014 ${res.project_name}` : ""}` : "";
|
|
992
|
+
const wa = weeklyAllowanceLine(res.weekly_allowance);
|
|
898
993
|
return textResult(
|
|
899
994
|
`\u2705 \xC1udio gerado (${res.model}, voz ${res.voice}, ${res.duration_sec.toFixed(1)}s).
|
|
900
995
|
${res.url}
|
|
901
|
-
${parts.join(" \xB7 ")}${projLine}`
|
|
996
|
+
${parts.join(" \xB7 ")}${projLine}` + (wa ? `
|
|
997
|
+
${wa}` : "")
|
|
902
998
|
);
|
|
903
999
|
} catch (e) {
|
|
904
1000
|
const msg = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "";
|
|
@@ -1005,9 +1101,11 @@ function registerAccountTools(server, client, _cfg) {
|
|
|
1005
1101
|
async () => {
|
|
1006
1102
|
try {
|
|
1007
1103
|
const me = await client.me();
|
|
1104
|
+
const wa = weeklyAllowanceLine(me.weekly_allowance);
|
|
1008
1105
|
return textResult(
|
|
1009
1106
|
`\u{1F464} ${me.name ?? "(sem nome)"} <${me.email ?? "sem email"}>
|
|
1010
|
-
Saldo: ${me.diamonds} \u{1F48E} \xB7 auth: ${me.authType}`
|
|
1107
|
+
Saldo: ${me.diamonds} \u{1F48E} \xB7 auth: ${me.authType}` + (wa ? `
|
|
1108
|
+
${wa}` : "")
|
|
1011
1109
|
);
|
|
1012
1110
|
} catch (e) {
|
|
1013
1111
|
return errorResult(apiErrorToUserMessage(e));
|
|
@@ -1018,13 +1116,15 @@ Saldo: ${me.diamonds} \u{1F48E} \xB7 auth: ${me.authType}`
|
|
|
1018
1116
|
"get_balance",
|
|
1019
1117
|
{
|
|
1020
1118
|
title: "Saldo de diamantes",
|
|
1021
|
-
description: "Mostra o saldo atual de diamantes da
|
|
1119
|
+
description: "Mostra o saldo atual de diamantes e, para membros da equipe, o cr\xE9dito semanal (% usado, quanto resta e quando reseta).",
|
|
1022
1120
|
inputSchema: {}
|
|
1023
1121
|
},
|
|
1024
1122
|
async () => {
|
|
1025
1123
|
try {
|
|
1026
1124
|
const b = await client.balance();
|
|
1027
|
-
|
|
1125
|
+
const wa = weeklyAllowanceLine(b.weekly_allowance);
|
|
1126
|
+
return textResult(`Saldo: ${b.diamonds} \u{1F48E}` + (wa ? `
|
|
1127
|
+
${wa}` : ""));
|
|
1028
1128
|
} catch (e) {
|
|
1029
1129
|
return errorResult(apiErrorToUserMessage(e));
|
|
1030
1130
|
}
|
|
@@ -1312,12 +1412,13 @@ function fmtDate(iso) {
|
|
|
1312
1412
|
return iso ? iso.slice(0, 10) : "";
|
|
1313
1413
|
}
|
|
1314
1414
|
function callLine(c) {
|
|
1415
|
+
const company = c.company_name ? ` \xB7 ${c.company_name}` : "";
|
|
1315
1416
|
const proj = c.project_name ? ` \xB7 ${c.client_name ? c.client_name + " / " : ""}${c.project_name}` : "";
|
|
1316
1417
|
const who = c.speakers.length ? ` \xB7 ${c.speakers.join(", ")}` : c.participant_count ? ` \xB7 ${c.participant_count} falantes` : "";
|
|
1317
1418
|
const vis = VIS_LABEL[c.visibility] ?? c.visibility;
|
|
1318
1419
|
const flag = c.status !== "ready" ? ` [${c.status}]` : "";
|
|
1319
1420
|
return `\u2022 ${c.title ?? "(sem t\xEDtulo)"}${flag}
|
|
1320
|
-
${fmtDate(c.date)} \xB7 ${fmtDuration(c.duration_sec)} \xB7 ${vis}${proj}${who}
|
|
1421
|
+
${fmtDate(c.date)} \xB7 ${fmtDuration(c.duration_sec)} \xB7 ${vis}${company}${proj}${who}
|
|
1321
1422
|
id: ${c.id}`;
|
|
1322
1423
|
}
|
|
1323
1424
|
function renderCall(c) {
|
|
@@ -1327,6 +1428,7 @@ function renderCall(c) {
|
|
|
1327
1428
|
if (c.date) meta.push(fmtDate(c.date));
|
|
1328
1429
|
meta.push(fmtDuration(c.duration_sec));
|
|
1329
1430
|
meta.push(VIS_LABEL[c.visibility] ?? c.visibility);
|
|
1431
|
+
if (c.company_name) meta.push(c.company_name);
|
|
1330
1432
|
if (c.project_name) meta.push(`${c.client_name ? c.client_name + " / " : ""}${c.project_name}`);
|
|
1331
1433
|
if (c.status !== "ready") meta.push(`status: ${c.status}`);
|
|
1332
1434
|
lines.push(meta.join(" \xB7 "));
|
|
@@ -1357,13 +1459,15 @@ function registerCallTools(server, client, _cfg) {
|
|
|
1357
1459
|
"search_calls",
|
|
1358
1460
|
{
|
|
1359
1461
|
title: "Buscar calls",
|
|
1360
|
-
description:
|
|
1462
|
+
description: 'Busca nas calls (reuni\xF5es gravadas e transcritas) vis\xEDveis pra conta \u2014 suas, da equipe e compartilhadas. Todos os filtros s\xE3o opcionais e combin\xE1veis: `query` (texto no t\xEDtulo/projeto/cliente/falante), `project` (code/uuid/nome), `client` (code/nome), `company` (empresa/equipe do dono, ex.: "BePlus"), `visibility` (team|private|workspace|link), `speaker` (nome do falante), `mine` (s\xF3 as que EU gravei). Retorna uma lista resumida \u2014 use get_call com o id pra ler a transcri\xE7\xE3o completa.',
|
|
1361
1463
|
inputSchema: {
|
|
1362
1464
|
query: z8.string().max(200).optional().describe("Texto livre \u2014 casa t\xEDtulo, projeto, cliente ou falante."),
|
|
1363
1465
|
project: z8.string().max(64).optional().describe('Projeto: code (ex.: "CONTEUDO-INS"), uuid ou parte do nome.'),
|
|
1364
1466
|
client: z8.string().max(128).optional().describe("Cliente: code ou parte do nome."),
|
|
1467
|
+
company: z8.string().max(128).optional().describe('Empresa/equipe do dono da call (ex.: "BePlus"). Filtra por parte do nome.'),
|
|
1365
1468
|
visibility: z8.enum(["team", "private", "workspace", "link"]).optional().describe("Privacidade: team (equipe), private (privada), workspace (projeto) ou link."),
|
|
1366
1469
|
speaker: z8.string().max(128).optional().describe("Nome do falante."),
|
|
1470
|
+
mine: z8.boolean().optional().describe('true = s\xF3 as calls que EU gravei (sou o dono). Use pra "minhas grava\xE7\xF5es".'),
|
|
1367
1471
|
limit: z8.number().int().min(1).max(50).optional().describe("M\xE1ximo de resultados (padr\xE3o 20).")
|
|
1368
1472
|
}
|
|
1369
1473
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beplus-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Conector MCP da equipe BePlus — gere imagens/vídeos/áudio e consulte calls, projetos e clientes pela sua conta BePlus (diamantes, limites e histórico aplicados pela plataforma).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|