sapiens-mcp 1.52.0 → 1.53.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/registry.js +1 -1
- package/dist/tools/brand.js +32 -5
- package/dist/tools/stockAudio.js +72 -3
- package/package.json +1 -1
package/dist/registry.js
CHANGED
|
@@ -128,7 +128,7 @@ export const TOOLS = {
|
|
|
128
128
|
handler: video,
|
|
129
129
|
},
|
|
130
130
|
sapiens_stock_audio: {
|
|
131
|
-
description: "Banco de som da casa: trilha pronta E efeito sonoro (tabela stockAudio). Sub-actions de leitura (públicas, sem auth): categories (lista os moods/usos), list (busca com filtros mood/albumSlug/durationMax/search; kind='sfx' traz os EFEITOS: whoosh, clique, impacto, ambiência, foley — devolve {count, items} com title/url/durationSeconds/tags), get (1 item por audioId). Use pra puxar trilha/efeito pronto: pega a `url` e usa direto no ffmpeg. Não achou o efeito? generate (COBRA Sinapses, exige login) cria um novo por texto: prompt + durationSeconds (1-15, default 5) + provider ('mirelo' padrão 35 Sinapses/s mín 70 | 'elevenlabs' premium 60/s mín 120) + promptInfluence opcional (0..1, só elevenlabs: fidelidade ao texto, default 0.3), assíncrono — acompanhe com generation-status (generationId) até 'ready' (audioUrl; o efeito também entra no acervo kind=sfx) ou 'failed' (Sinapses reembolsadas). Efeito é CURTO (1-15s): música/trilha nova é no sapiens_musicator. Mood disponíveis: calmo, intenso, narrativo, épico, sombrio.",
|
|
131
|
+
description: "Banco de som da casa: trilha pronta E efeito sonoro (tabela stockAudio). Sub-actions de leitura (públicas, sem auth): categories (lista os moods/usos), list (busca com filtros mood/albumSlug/durationMax/search; kind='sfx' traz os EFEITOS: whoosh, clique, impacto, ambiência, foley — devolve {count, items} com title/url/durationSeconds/tags), get (1 item por audioId). Use pra puxar trilha/efeito pronto: pega a `url` e usa direto no ffmpeg. Não achou o efeito? generate (COBRA Sinapses, exige login) cria um novo por texto: prompt + durationSeconds (1-15, default 5) + provider ('mirelo' padrão 35 Sinapses/s mín 70 | 'elevenlabs' premium 60/s mín 120) + promptInfluence opcional (0..1, só elevenlabs: fidelidade ao texto, default 0.3), assíncrono — acompanhe com generation-status (generationId) até 'ready' (audioUrl; o efeito também entra no acervo kind=sfx) ou 'failed' (Sinapses reembolsadas). Efeito é CURTO (1-15s): música/trilha nova é no sapiens_musicator. Mood disponíveis: calmo, intenso, narrativo, épico, sombrio. Precisa de VOZ junto com trilha e efeito (anúncio, vinheta, cena de filme, podcast)? scene (COBRA Sinapses, exige login) cria a CENA INTEIRA num passe só, já batida, sem montar em pedaços e mixar depois: scenePrompt (a direção da cena, quem fala, com que timbre, o que toca atrás, a fala entre aspas) + durationSeconds (3-120, default 15) + loudnessRate/pitchRate/speechRate opcionais + withSubtitles opcional (traz o tempo de cada palavra), 11 Sinapses/s, assíncrono — acompanhe com scene-status (sceneId) até 'ready' (audioUrl + realDurationSeconds) ou 'failed' (Sinapses reembolsadas). A cena fica com o AUTOR e não entra no acervo compartilhado, porque carrega a voz e o roteiro de quem pediu.",
|
|
132
132
|
schema: stockAudioSchema,
|
|
133
133
|
handler: stockAudio,
|
|
134
134
|
},
|
package/dist/tools/brand.js
CHANGED
|
@@ -15,7 +15,10 @@ import { convexAction, convexQuery, convexMutation, getSessionToken, } from "../
|
|
|
15
15
|
* - generate: cria um design system NOVO a partir de descrição em texto livre
|
|
16
16
|
* (Gemini monta paleta+tipografia+voz+imageStyle e já nasce com
|
|
17
17
|
* card premium gpt-image-2). Cobra ~950 Sinapses (texto + card),
|
|
18
|
-
* reembolsa se falhar. Identidade vem do sessionToken.
|
|
18
|
+
* reembolsa se falhar. Identidade vem do sessionToken. Pode
|
|
19
|
+
* partir do briefing de um brand JÁ SEU (fromSlug) e aplicar uma
|
|
20
|
+
* torção (twist): é assim que se desenha várias direções pro
|
|
21
|
+
* mesmo projeto sem redigitar o briefing a cada uma.
|
|
19
22
|
* - refine: ajusta um brand custom existente por feedback em texto livre
|
|
20
23
|
* ("fundo mais escuro", "voz menos professoral"). ~75 Sinapses.
|
|
21
24
|
* - reroll: regenera SÓ uma peça (voice | palette | imageStyle) numa direção
|
|
@@ -69,6 +72,14 @@ export const brandSchema = z.object({
|
|
|
69
72
|
.string()
|
|
70
73
|
.optional()
|
|
71
74
|
.describe("Pra action=generate: nome sugerido pro brand (opcional, ≤40 chars). Sem isso o Gemini sugere um."),
|
|
75
|
+
fromSlug: z
|
|
76
|
+
.string()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe("Pra action=generate: slug de um brand SEU cujo briefing vira a base da variação (o brand original não é tocado, nasce um novo). Com isso, `description` fica opcional. Só funciona em brand que guarda briefing (os criados a partir de ago/2026); veja em action=get, campo `brief`."),
|
|
79
|
+
twist: z
|
|
80
|
+
.string()
|
|
81
|
+
.optional()
|
|
82
|
+
.describe("Pra action=generate: a torção aplicada sobre o briefing ('mais bruto', 'mais editorial', 'paleta clara'). Combina com fromSlug (variação de um brand seu) ou com description (torção sobre o briefing que você acabou de escrever). ≤400 chars."),
|
|
72
83
|
feedback: z
|
|
73
84
|
.string()
|
|
74
85
|
.optional()
|
|
@@ -113,19 +124,32 @@ export async function brand(args) {
|
|
|
113
124
|
if (!b) {
|
|
114
125
|
throw new Error(`Brand "${args.slug}" não encontrado (ou é custom de outro user). Veja os seus em action=list.`);
|
|
115
126
|
}
|
|
116
|
-
return
|
|
127
|
+
return {
|
|
128
|
+
...b,
|
|
129
|
+
// O briefing só vem em brand seu (ou oficial) e só existe nos criados a
|
|
130
|
+
// partir de ago/2026. Quando existe, é o atalho pra desenhar variações.
|
|
131
|
+
briefNote: b.brief?.text
|
|
132
|
+
? `Esse brand guarda o briefing que gerou ele. Pra desenhar outra direção a partir dele: action=generate fromSlug=${b.slug} twist='mais bruto' (não toca neste aqui, nasce um brand novo).`
|
|
133
|
+
: "Esse brand não guarda o briefing (nasceu antes disso existir), então variação por fromSlug não funciona nele. Pra criar um parecido, escreva a description na mão.",
|
|
134
|
+
};
|
|
117
135
|
}
|
|
118
136
|
// -------- generate: cria design system novo (cobra Sinapses) --------
|
|
119
137
|
if (args.action === "generate") {
|
|
120
138
|
const description = (args.description || "").trim();
|
|
121
|
-
|
|
139
|
+
const fromSlug = args.fromSlug?.trim();
|
|
140
|
+
// Com fromSlug o briefing vem do brand de origem (o servidor lê e confere a
|
|
141
|
+
// posse), então a description deixa de ser obrigatória.
|
|
142
|
+
if (!fromSlug && description.length < 30) {
|
|
122
143
|
throw new Error("action=generate exige description com pelo menos 30 chars (vibe, cores, voz, referências). " +
|
|
123
|
-
"Quanto mais rico, melhor o brand. Converse com o user e monte a descrição antes de chamar."
|
|
144
|
+
"Quanto mais rico, melhor o brand. Converse com o user e monte a descrição antes de chamar. " +
|
|
145
|
+
"Pra variar um brand que já é dele, use fromSlug=<slug> (+ twist='mais bruto').");
|
|
124
146
|
}
|
|
125
147
|
const res = await convexAction("customBrandsActions:mcpGenerateBrand", {
|
|
126
148
|
sessionToken,
|
|
127
149
|
description,
|
|
128
150
|
name: args.name?.trim() || undefined,
|
|
151
|
+
fromSlug: fromSlug || undefined,
|
|
152
|
+
twist: args.twist?.trim() || undefined,
|
|
129
153
|
});
|
|
130
154
|
return {
|
|
131
155
|
...res,
|
|
@@ -138,7 +162,10 @@ export async function brand(args) {
|
|
|
138
162
|
res.slug +
|
|
139
163
|
" feedback='...'. Regenerar uma peça: action=reroll slug=" +
|
|
140
164
|
res.slug +
|
|
141
|
-
" piece=voice|palette|imageStyle."
|
|
165
|
+
" piece=voice|palette|imageStyle. Outra direção do MESMO briefing: " +
|
|
166
|
+
"action=generate fromSlug=" +
|
|
167
|
+
res.slug +
|
|
168
|
+
" twist='mais bruto'.",
|
|
142
169
|
};
|
|
143
170
|
}
|
|
144
171
|
// -------- refine: ajusta brand custom existente (cobra Sinapses) --------
|
package/dist/tools/stockAudio.js
CHANGED
|
@@ -17,10 +17,12 @@ import { convexQuery, convexAction, getSessionToken } from "../convexClient.js";
|
|
|
17
17
|
*/
|
|
18
18
|
export const stockAudioSchema = z.object({
|
|
19
19
|
action: z
|
|
20
|
-
.enum(["list", "get", "categories", "generate", "generation-status"])
|
|
20
|
+
.enum(["list", "get", "categories", "generate", "generation-status", "scene", "scene-status"])
|
|
21
21
|
.describe("list = busca faixas/efeitos; get = 1 item por id; categories = moods/usos; " +
|
|
22
22
|
"generate = cria efeito sonoro novo (COBRA Sinapses, assíncrono); " +
|
|
23
|
-
"generation-status = status de uma geração (até ready/failed)
|
|
23
|
+
"generation-status = status de uma geração (até ready/failed); " +
|
|
24
|
+
"scene = cria uma CENA de áudio completa, voz + trilha + efeito + ambiência num passe só " +
|
|
25
|
+
"(COBRA Sinapses, assíncrono); scene-status = status de uma cena (até ready/failed)."),
|
|
24
26
|
limit: z
|
|
25
27
|
.number()
|
|
26
28
|
.int()
|
|
@@ -63,7 +65,9 @@ export const stockAudioSchema = z.object({
|
|
|
63
65
|
durationSeconds: z
|
|
64
66
|
.number()
|
|
65
67
|
.optional()
|
|
66
|
-
.describe("
|
|
68
|
+
.describe("Duração alvo em segundos. action=generate: 1 a 15, default 5. action=scene: 3 a 120, default 15. " +
|
|
69
|
+
"O custo escala por segundo nos dois. Na CENA a duração não é parâmetro do modelo, ela sai da " +
|
|
70
|
+
"direção escrita: o alvo entra no pedido como instrução e o preço é acertado pela duração que voltou."),
|
|
67
71
|
provider: z
|
|
68
72
|
.enum(["mirelo", "elevenlabs"])
|
|
69
73
|
.optional()
|
|
@@ -78,6 +82,46 @@ export const stockAudioSchema = z.object({
|
|
|
78
82
|
.string()
|
|
79
83
|
.optional()
|
|
80
84
|
.describe("action=generation-status: o generationId que o generate devolveu."),
|
|
85
|
+
// --- action=scene (cena de áudio completa, Seed Audio 1.0) ---
|
|
86
|
+
scenePrompt: z
|
|
87
|
+
.string()
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("action=scene: a DIREÇÃO da cena inteira, não só a fala. Diga quem fala, com que timbre e " +
|
|
90
|
+
"humor, em que idioma, o que toca atrás e o que se ouve no fundo, e ponha a fala entre aspas. " +
|
|
91
|
+
"Ex: 'Voz masculina adulta, calma e um pouco rouca, em português do Brasil. Estúdio à noite, " +
|
|
92
|
+
"um teclado bem baixo atrás. Ela fala: Sapiens Sintéticos, o Lab onde a sua ideia vira peça " +
|
|
93
|
+
"pronta.' Mín. 10 chars, máx. 2.000. Escreva como quem dirige, não como quem preenche campo: " +
|
|
94
|
+
"o modelo entende cena inteira e é daí que sai a qualidade."),
|
|
95
|
+
loudnessRate: z
|
|
96
|
+
.number()
|
|
97
|
+
.int()
|
|
98
|
+
.min(-50)
|
|
99
|
+
.max(100)
|
|
100
|
+
.optional()
|
|
101
|
+
.describe("action=scene: volume. -50 = metade, 100 = dobro. Default 0 (natural do modelo)."),
|
|
102
|
+
pitchRate: z
|
|
103
|
+
.number()
|
|
104
|
+
.int()
|
|
105
|
+
.min(-12)
|
|
106
|
+
.max(12)
|
|
107
|
+
.optional()
|
|
108
|
+
.describe("action=scene: tom da voz. Default 0 (natural do modelo)."),
|
|
109
|
+
speechRate: z
|
|
110
|
+
.number()
|
|
111
|
+
.int()
|
|
112
|
+
.min(-50)
|
|
113
|
+
.max(100)
|
|
114
|
+
.optional()
|
|
115
|
+
.describe("action=scene: velocidade da fala. -50 = metade, 100 = dobro. Default 0."),
|
|
116
|
+
withSubtitles: z
|
|
117
|
+
.boolean()
|
|
118
|
+
.optional()
|
|
119
|
+
.describe("action=scene: guarda a legenda com o tempo de cada palavra, pra casar texto com a fala " +
|
|
120
|
+
"sem transcrever depois. Default false."),
|
|
121
|
+
sceneId: z
|
|
122
|
+
.string()
|
|
123
|
+
.optional()
|
|
124
|
+
.describe("action=scene-status: o sceneId que o scene devolveu."),
|
|
81
125
|
});
|
|
82
126
|
export async function stockAudio(args) {
|
|
83
127
|
if (args.action === "categories") {
|
|
@@ -102,6 +146,31 @@ export async function stockAudio(args) {
|
|
|
102
146
|
promptInfluence: args.promptInfluence,
|
|
103
147
|
});
|
|
104
148
|
}
|
|
149
|
+
if (args.action === "scene") {
|
|
150
|
+
if (!args.scenePrompt || args.scenePrompt.trim().length < 10) {
|
|
151
|
+
throw new Error("action=scene exige scenePrompt (mín. 10 chars dirigindo a cena: quem fala, como, o que se ouve atrás).");
|
|
152
|
+
}
|
|
153
|
+
const sessionToken = getSessionToken();
|
|
154
|
+
return await convexAction("mcpExtrasActions:mcpAudioSceneGenerate", {
|
|
155
|
+
sessionToken,
|
|
156
|
+
scenePrompt: args.scenePrompt,
|
|
157
|
+
durationSeconds: args.durationSeconds,
|
|
158
|
+
loudnessRate: args.loudnessRate,
|
|
159
|
+
pitchRate: args.pitchRate,
|
|
160
|
+
speechRate: args.speechRate,
|
|
161
|
+
withSubtitles: args.withSubtitles,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (args.action === "scene-status") {
|
|
165
|
+
if (!args.sceneId) {
|
|
166
|
+
throw new Error("action=scene-status exige sceneId (o que o scene devolveu).");
|
|
167
|
+
}
|
|
168
|
+
const sessionToken = getSessionToken();
|
|
169
|
+
return await convexQuery("mcpExtras:mcpAudioSceneStatus", {
|
|
170
|
+
sessionToken,
|
|
171
|
+
sceneId: args.sceneId,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
105
174
|
if (args.action === "generation-status") {
|
|
106
175
|
if (!args.generationId) {
|
|
107
176
|
throw new Error("action=generation-status exige generationId (o que o generate devolveu).");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.53.0",
|
|
4
4
|
"mcpName": "com.sapiensinteticos/sapiens",
|
|
5
5
|
"description": "MCP server pra operar o Sapiens Sintéticos (sapiensinteticos.com) pelo Claude Code: gerar imagem, escrever artigo, voz, música e mais, na sua conta. Login pelo código de sapiensinteticos.com/conectar-claude.",
|
|
6
6
|
"type": "module",
|