beplus-mcp 0.12.0 → 0.14.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 +108 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -189,7 +189,18 @@ var BeplusClient = class {
|
|
|
189
189
|
return this.request("POST", "/analyze-media", { body, timeoutMs: 3e5 });
|
|
190
190
|
}
|
|
191
191
|
searchCalls(query) {
|
|
192
|
-
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
|
+
});
|
|
193
204
|
}
|
|
194
205
|
getCall(id) {
|
|
195
206
|
return this.request("GET", `/calls/${id}`);
|
|
@@ -204,6 +215,10 @@ var TEAM_GATING_NOTE = " \u26A0\uFE0F DESTINO DA GERA\xC7\xC3O: toda imagem/v\xE
|
|
|
204
215
|
function isTeamGatingError(msg) {
|
|
205
216
|
return !!msg && /cliente e um projeto|selecione um cliente|sem cliente vinculado|antes de gerar/i.test(msg);
|
|
206
217
|
}
|
|
218
|
+
function isBudgetBlockedError(msg) {
|
|
219
|
+
return !!msg && /budget/i.test(msg);
|
|
220
|
+
}
|
|
221
|
+
var BUDGET_BLOCKED_GUIDANCE = "\u{1F4A1} O pote deste projeto/cliente acabou. Um admin pode recarregar em Admin \u2192 IA Lab \u2192 Projetos/Clientes. Alternativa: trocar o projeto ativo com `set_active_project`.";
|
|
207
222
|
async function buildPickProjectMessage(client) {
|
|
208
223
|
let clientsTxt = " (n\xE3o foi poss\xEDvel listar clientes)";
|
|
209
224
|
let projectsTxt = " (n\xE3o foi poss\xEDvel listar projetos)";
|
|
@@ -371,6 +386,35 @@ function logError(...args) {
|
|
|
371
386
|
}
|
|
372
387
|
|
|
373
388
|
// src/format.ts
|
|
389
|
+
function fmtResetDate(iso) {
|
|
390
|
+
const [, m, d] = iso.split("-");
|
|
391
|
+
return d && m ? `${d}/${m}` : iso;
|
|
392
|
+
}
|
|
393
|
+
function weeklyAllowanceLine(wa) {
|
|
394
|
+
if (!wa || !wa.enabled) return "";
|
|
395
|
+
if (wa.unlimited) return "\u267E\uFE0F Limite semanal: ilimitado (sua conta \xE9 isenta).";
|
|
396
|
+
const pct = wa.percentUsed;
|
|
397
|
+
const icon = pct >= 100 ? "\u{1F6D1}" : pct >= wa.warnThresholdPercent ? "\u26A0\uFE0F" : "\u{1F4CA}";
|
|
398
|
+
let line = `${icon} Limite semanal: ${pct}% usado \xB7 ${wa.remaining} de ${wa.quota} restantes`;
|
|
399
|
+
if (pct >= 100) {
|
|
400
|
+
line += `
|
|
401
|
+
\u{1F6D1} Limite semanal atingido \u2014 reseta em ${fmtResetDate(wa.periodEnd)}.`;
|
|
402
|
+
} else if (pct >= wa.warnThresholdPercent) {
|
|
403
|
+
line += `
|
|
404
|
+
\u26A0\uFE0F Seu limite semanal est\xE1 acabando \u2014 reseta em ${fmtResetDate(wa.periodEnd)}.`;
|
|
405
|
+
}
|
|
406
|
+
return line;
|
|
407
|
+
}
|
|
408
|
+
function budgetLine(b) {
|
|
409
|
+
if (!b || !b.enabled) return "";
|
|
410
|
+
const scope = b.scope === "client" ? "cliente" : "projeto";
|
|
411
|
+
const pct = b.percentUsed;
|
|
412
|
+
const exhausted = pct >= 100 || b.remainingDiamonds <= 0;
|
|
413
|
+
const icon = exhausted ? "\u{1F6D1}" : pct >= 80 ? "\u26A0\uFE0F" : "\u{1F9FE}";
|
|
414
|
+
let line = `${icon} Budget do ${scope}: ${b.remainingDiamonds} de ${b.quotaDiamonds}\u{1F48E} restantes (${pct}% usado)`;
|
|
415
|
+
if (exhausted) line += " \u2014 pe\xE7a a um admin para recarregar";
|
|
416
|
+
return line;
|
|
417
|
+
}
|
|
374
418
|
function textResult(s) {
|
|
375
419
|
return { content: [{ type: "text", text: s }] };
|
|
376
420
|
}
|
|
@@ -393,11 +437,20 @@ function costFooter(start, cfg) {
|
|
|
393
437
|
footer = `\u26A0 Custo alto (${start.diamond_cost} \u{1F48E})
|
|
394
438
|
${footer}`;
|
|
395
439
|
}
|
|
440
|
+
const budget = budgetLine(start.budget);
|
|
396
441
|
if (start.project_code) {
|
|
397
|
-
|
|
442
|
+
let proj = `\u{1F4C1} Projeto: ${start.project_code}${start.project_name ? ` \u2014 ${start.project_name}` : ""}`;
|
|
443
|
+
if (budget) proj = `${proj}
|
|
444
|
+
${budget}`;
|
|
398
445
|
footer = footer ? `${proj}
|
|
399
446
|
${footer}` : proj;
|
|
447
|
+
} else if (budget) {
|
|
448
|
+
footer = footer ? `${budget}
|
|
449
|
+
${footer}` : budget;
|
|
400
450
|
}
|
|
451
|
+
const wa = weeklyAllowanceLine(start.weekly_allowance);
|
|
452
|
+
if (wa) footer = footer ? `${footer}
|
|
453
|
+
${wa}` : wa;
|
|
401
454
|
return footer;
|
|
402
455
|
}
|
|
403
456
|
function outputUrls(status) {
|
|
@@ -631,6 +684,10 @@ ${footer}` }, ...blocks]
|
|
|
631
684
|
} catch (e) {
|
|
632
685
|
const msg = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "";
|
|
633
686
|
if (isTeamGatingError(msg)) return errorResult(await buildPickProjectMessage(client));
|
|
687
|
+
if (isBudgetBlockedError(msg)) {
|
|
688
|
+
return errorResult(`${apiErrorToUserMessage(e)}
|
|
689
|
+
${BUDGET_BLOCKED_GUIDANCE}`);
|
|
690
|
+
}
|
|
634
691
|
return errorResult(apiErrorToUserMessage(e));
|
|
635
692
|
}
|
|
636
693
|
}
|
|
@@ -688,6 +745,10 @@ ${footer}` }, ...blocks] };
|
|
|
688
745
|
} catch (e) {
|
|
689
746
|
const msg = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "";
|
|
690
747
|
if (isTeamGatingError(msg)) return errorResult(await buildPickProjectMessage(client));
|
|
748
|
+
if (isBudgetBlockedError(msg)) {
|
|
749
|
+
return errorResult(`${apiErrorToUserMessage(e)}
|
|
750
|
+
${BUDGET_BLOCKED_GUIDANCE}`);
|
|
751
|
+
}
|
|
691
752
|
return errorResult(apiErrorToUserMessage(e));
|
|
692
753
|
}
|
|
693
754
|
}
|
|
@@ -780,6 +841,10 @@ ${footer}`);
|
|
|
780
841
|
} catch (e) {
|
|
781
842
|
const msg = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "";
|
|
782
843
|
if (isTeamGatingError(msg)) return errorResult(await buildPickProjectMessage(client));
|
|
844
|
+
if (isBudgetBlockedError(msg)) {
|
|
845
|
+
return errorResult(`${apiErrorToUserMessage(e)}
|
|
846
|
+
${BUDGET_BLOCKED_GUIDANCE}`);
|
|
847
|
+
}
|
|
783
848
|
return errorResult(apiErrorToUserMessage(e));
|
|
784
849
|
}
|
|
785
850
|
}
|
|
@@ -956,14 +1021,22 @@ function registerAudioTools(server, client, cfg) {
|
|
|
956
1021
|
if (res.diamonds_refunded) parts.push(`Estorno: ${res.diamonds_refunded} \u{1F48E}`);
|
|
957
1022
|
const projLine = res.project_code ? `
|
|
958
1023
|
\u{1F4C1} Projeto: ${res.project_code}${res.project_name ? ` \u2014 ${res.project_name}` : ""}` : "";
|
|
1024
|
+
const wa = weeklyAllowanceLine(res.weekly_allowance);
|
|
1025
|
+
const budget = budgetLine(res.budget);
|
|
959
1026
|
return textResult(
|
|
960
1027
|
`\u2705 \xC1udio gerado (${res.model}, voz ${res.voice}, ${res.duration_sec.toFixed(1)}s).
|
|
961
1028
|
${res.url}
|
|
962
|
-
${parts.join(" \xB7 ")}${projLine}`
|
|
1029
|
+
${parts.join(" \xB7 ")}${projLine}` + (budget ? `
|
|
1030
|
+
${budget}` : "") + (wa ? `
|
|
1031
|
+
${wa}` : "")
|
|
963
1032
|
);
|
|
964
1033
|
} catch (e) {
|
|
965
1034
|
const msg = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "";
|
|
966
1035
|
if (isTeamGatingError(msg)) return errorResult(await buildPickProjectMessage(client));
|
|
1036
|
+
if (isBudgetBlockedError(msg)) {
|
|
1037
|
+
return errorResult(`${apiErrorToUserMessage(e)}
|
|
1038
|
+
${BUDGET_BLOCKED_GUIDANCE}`);
|
|
1039
|
+
}
|
|
967
1040
|
return errorResult(apiErrorToUserMessage(e));
|
|
968
1041
|
}
|
|
969
1042
|
}
|
|
@@ -1047,6 +1120,10 @@ ${footer}`);
|
|
|
1047
1120
|
} catch (e) {
|
|
1048
1121
|
const msg = e instanceof ApiError ? e.message : e instanceof Error ? e.message : "";
|
|
1049
1122
|
if (isTeamGatingError(msg)) return errorResult(await buildPickProjectMessage(client));
|
|
1123
|
+
if (isBudgetBlockedError(msg)) {
|
|
1124
|
+
return errorResult(`${apiErrorToUserMessage(e)}
|
|
1125
|
+
${BUDGET_BLOCKED_GUIDANCE}`);
|
|
1126
|
+
}
|
|
1050
1127
|
return errorResult(apiErrorToUserMessage(e));
|
|
1051
1128
|
}
|
|
1052
1129
|
}
|
|
@@ -1066,9 +1143,13 @@ function registerAccountTools(server, client, _cfg) {
|
|
|
1066
1143
|
async () => {
|
|
1067
1144
|
try {
|
|
1068
1145
|
const me = await client.me();
|
|
1146
|
+
const wa = weeklyAllowanceLine(me.weekly_allowance);
|
|
1147
|
+
const budget = budgetLine(me.budget);
|
|
1069
1148
|
return textResult(
|
|
1070
1149
|
`\u{1F464} ${me.name ?? "(sem nome)"} <${me.email ?? "sem email"}>
|
|
1071
|
-
Saldo: ${me.diamonds} \u{1F48E} \xB7 auth: ${me.authType}`
|
|
1150
|
+
Saldo: ${me.diamonds} \u{1F48E} \xB7 auth: ${me.authType}` + (wa ? `
|
|
1151
|
+
${wa}` : "") + (budget ? `
|
|
1152
|
+
${budget}` : "")
|
|
1072
1153
|
);
|
|
1073
1154
|
} catch (e) {
|
|
1074
1155
|
return errorResult(apiErrorToUserMessage(e));
|
|
@@ -1079,13 +1160,19 @@ Saldo: ${me.diamonds} \u{1F48E} \xB7 auth: ${me.authType}`
|
|
|
1079
1160
|
"get_balance",
|
|
1080
1161
|
{
|
|
1081
1162
|
title: "Saldo de diamantes",
|
|
1082
|
-
description: "Mostra o saldo atual de diamantes da
|
|
1163
|
+
description: "Mostra o saldo atual de diamantes e, para membros da equipe, o cr\xE9dito semanal (% usado, quanto resta e quando reseta).",
|
|
1083
1164
|
inputSchema: {}
|
|
1084
1165
|
},
|
|
1085
1166
|
async () => {
|
|
1086
1167
|
try {
|
|
1087
1168
|
const b = await client.balance();
|
|
1088
|
-
|
|
1169
|
+
const wa = weeklyAllowanceLine(b.weekly_allowance);
|
|
1170
|
+
const budget = budgetLine(b.budget);
|
|
1171
|
+
return textResult(
|
|
1172
|
+
`Saldo: ${b.diamonds} \u{1F48E}` + (wa ? `
|
|
1173
|
+
${wa}` : "") + (budget ? `
|
|
1174
|
+
${budget}` : "")
|
|
1175
|
+
);
|
|
1089
1176
|
} catch (e) {
|
|
1090
1177
|
return errorResult(apiErrorToUserMessage(e));
|
|
1091
1178
|
}
|
|
@@ -1203,7 +1290,8 @@ function projectLine(p, active) {
|
|
|
1203
1290
|
const marker = active ? "\u25CF " : "\u25CB ";
|
|
1204
1291
|
const counts = `${p.generation_count ?? 0} gera\xE7\xF5es`;
|
|
1205
1292
|
const owner = p.client_name ? ` \xB7 cliente: ${p.client_name}` : "";
|
|
1206
|
-
|
|
1293
|
+
const budget = p.budget?.enabled ? ` \xB7 budget ${p.budget.remainingDiamonds}/${p.budget.quotaDiamonds}\u{1F48E}` : "";
|
|
1294
|
+
return `${marker}${p.code} \u2014 ${p.name} (${counts}${owner})${budget}`;
|
|
1207
1295
|
}
|
|
1208
1296
|
function registerProjectTools(server, client, _cfg) {
|
|
1209
1297
|
server.registerTool(
|
|
@@ -1223,7 +1311,10 @@ function registerProjectTools(server, client, _cfg) {
|
|
|
1223
1311
|
}
|
|
1224
1312
|
const lines = projects.map((p) => projectLine(p, !!p.is_active_for_user));
|
|
1225
1313
|
const active = projects.find((p) => p.is_active_for_user);
|
|
1226
|
-
|
|
1314
|
+
let header = active ? `Projeto ativo: ${active.code} \u2014 ${active.name}` : "Nenhum projeto ativo (gera\xE7\xF5es ficam sem projeto).";
|
|
1315
|
+
const activeBudget = budgetLine(active?.budget);
|
|
1316
|
+
if (activeBudget) header += `
|
|
1317
|
+
${activeBudget}`;
|
|
1227
1318
|
return textResult(`${header}
|
|
1228
1319
|
|
|
1229
1320
|
${lines.join("\n")}`);
|
|
@@ -1274,7 +1365,9 @@ ${lines.join("\n")}`);
|
|
|
1274
1365
|
try {
|
|
1275
1366
|
const { project: active } = await client.setActiveProject(project ?? null);
|
|
1276
1367
|
if (!active) return textResult("\u2705 Projeto ativo removido \u2014 novas gera\xE7\xF5es ficar\xE3o sem projeto.");
|
|
1277
|
-
|
|
1368
|
+
const budget = budgetLine(active.budget);
|
|
1369
|
+
return textResult(`\u2705 Projeto ativo: ${active.code} \u2014 ${active.name}.` + (budget ? `
|
|
1370
|
+
${budget}` : ""));
|
|
1278
1371
|
} catch (e) {
|
|
1279
1372
|
return errorResult(apiErrorToUserMessage(e));
|
|
1280
1373
|
}
|
|
@@ -1373,12 +1466,13 @@ function fmtDate(iso) {
|
|
|
1373
1466
|
return iso ? iso.slice(0, 10) : "";
|
|
1374
1467
|
}
|
|
1375
1468
|
function callLine(c) {
|
|
1469
|
+
const company = c.company_name ? ` \xB7 ${c.company_name}` : "";
|
|
1376
1470
|
const proj = c.project_name ? ` \xB7 ${c.client_name ? c.client_name + " / " : ""}${c.project_name}` : "";
|
|
1377
1471
|
const who = c.speakers.length ? ` \xB7 ${c.speakers.join(", ")}` : c.participant_count ? ` \xB7 ${c.participant_count} falantes` : "";
|
|
1378
1472
|
const vis = VIS_LABEL[c.visibility] ?? c.visibility;
|
|
1379
1473
|
const flag = c.status !== "ready" ? ` [${c.status}]` : "";
|
|
1380
1474
|
return `\u2022 ${c.title ?? "(sem t\xEDtulo)"}${flag}
|
|
1381
|
-
${fmtDate(c.date)} \xB7 ${fmtDuration(c.duration_sec)} \xB7 ${vis}${proj}${who}
|
|
1475
|
+
${fmtDate(c.date)} \xB7 ${fmtDuration(c.duration_sec)} \xB7 ${vis}${company}${proj}${who}
|
|
1382
1476
|
id: ${c.id}`;
|
|
1383
1477
|
}
|
|
1384
1478
|
function renderCall(c) {
|
|
@@ -1388,6 +1482,7 @@ function renderCall(c) {
|
|
|
1388
1482
|
if (c.date) meta.push(fmtDate(c.date));
|
|
1389
1483
|
meta.push(fmtDuration(c.duration_sec));
|
|
1390
1484
|
meta.push(VIS_LABEL[c.visibility] ?? c.visibility);
|
|
1485
|
+
if (c.company_name) meta.push(c.company_name);
|
|
1391
1486
|
if (c.project_name) meta.push(`${c.client_name ? c.client_name + " / " : ""}${c.project_name}`);
|
|
1392
1487
|
if (c.status !== "ready") meta.push(`status: ${c.status}`);
|
|
1393
1488
|
lines.push(meta.join(" \xB7 "));
|
|
@@ -1418,13 +1513,15 @@ function registerCallTools(server, client, _cfg) {
|
|
|
1418
1513
|
"search_calls",
|
|
1419
1514
|
{
|
|
1420
1515
|
title: "Buscar calls",
|
|
1421
|
-
description:
|
|
1516
|
+
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.',
|
|
1422
1517
|
inputSchema: {
|
|
1423
1518
|
query: z8.string().max(200).optional().describe("Texto livre \u2014 casa t\xEDtulo, projeto, cliente ou falante."),
|
|
1424
1519
|
project: z8.string().max(64).optional().describe('Projeto: code (ex.: "CONTEUDO-INS"), uuid ou parte do nome.'),
|
|
1425
1520
|
client: z8.string().max(128).optional().describe("Cliente: code ou parte do nome."),
|
|
1521
|
+
company: z8.string().max(128).optional().describe('Empresa/equipe do dono da call (ex.: "BePlus"). Filtra por parte do nome.'),
|
|
1426
1522
|
visibility: z8.enum(["team", "private", "workspace", "link"]).optional().describe("Privacidade: team (equipe), private (privada), workspace (projeto) ou link."),
|
|
1427
1523
|
speaker: z8.string().max(128).optional().describe("Nome do falante."),
|
|
1524
|
+
mine: z8.boolean().optional().describe('true = s\xF3 as calls que EU gravei (sou o dono). Use pra "minhas grava\xE7\xF5es".'),
|
|
1428
1525
|
limit: z8.number().int().min(1).max(50).optional().describe("M\xE1ximo de resultados (padr\xE3o 20).")
|
|
1429
1526
|
}
|
|
1430
1527
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beplus-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.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": {
|