sapiens-mcp 1.10.0 → 1.11.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 +9 -3
- package/dist/tools/brand.js +190 -0
- package/dist/tools/studios.js +18 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import { shorts, shortsSchema } from "./tools/shorts.js";
|
|
|
20
20
|
import { video, videoSchema } from "./tools/video.js";
|
|
21
21
|
import { write, writeSchema } from "./tools/write.js";
|
|
22
22
|
import { stockAudio, stockAudioSchema } from "./tools/stockAudio.js";
|
|
23
|
+
import { brand, brandSchema } from "./tools/brand.js";
|
|
23
24
|
import { describeConvexError } from "./convexClient.js";
|
|
24
25
|
const TOOLS = {
|
|
25
26
|
sapiens_pipeline: {
|
|
@@ -73,7 +74,7 @@ const TOOLS = {
|
|
|
73
74
|
handler: search,
|
|
74
75
|
},
|
|
75
76
|
sapiens_studios: {
|
|
76
|
-
description: "Catálogo dos estúdios/experimentos Sapiens (v1.3, atualizado v1.4). Sub-actions: list (todos com URL+status+tags+mcpReady), get (detalhe de 1 slug), publishable_url (formata URL /articles/<slug>). Use quando user pergunta 'que estúdios existem'. Estúdios cobertos: helen-voice (v1.4 mcpReady), musicator (v1.4 mcpReady), persona-
|
|
77
|
+
description: "Catálogo dos estúdios/experimentos Sapiens (v1.3, atualizado v1.4). Sub-actions: list (todos com URL+status+tags+mcpReady), get (detalhe de 1 slug), publishable_url (formata URL /articles/<slug>). Use quando user pergunta 'que estúdios existem'. Estúdios cobertos: helen-voice (v1.4 mcpReady), musicator (v1.4 mcpReady), persona-sapiens (teste de autoconhecimento + arte, mcpReady), personagem-atlas (dossiê de personagem, UI-only), sapiens-shorts, sapiens-video, cena-visual, text-post-builder, carrosel-editorial, comunidade, repertorio.",
|
|
77
78
|
schema: studiosSchema,
|
|
78
79
|
handler: studios,
|
|
79
80
|
},
|
|
@@ -107,8 +108,13 @@ const TOOLS = {
|
|
|
107
108
|
schema: stockAudioSchema,
|
|
108
109
|
handler: stockAudio,
|
|
109
110
|
},
|
|
111
|
+
sapiens_brand: {
|
|
112
|
+
description: "Brand Sapiens (= Design System) — paleta + tipografia + voz + estilo de imagem + persona como FONTE ÚNICA de estilo (espelha o Estúdio de Brand do app). Sub-actions: list (oficiais curados + os custom do user, leve, grátis), get (1 brand completo por slug: voz + imageStyle + persona/logo; só oficial ou o próprio), generate (CRIA design system novo a partir de descrição em texto livre; Gemini monta tudo e já nasce com card premium gpt-image-2; ~950 Sinapses, reembolsa se falhar), refine (ajusta brand custom por feedback livre tipo 'fundo mais escuro'/'voz mais seca', ~75 Sinapses), reroll (regenera SÓ 1 peça voice|palette|imageStyle numa direção diferente, grátis), card ((re)gera o card premium, preço de catálogo do modelo), delete (apaga brand custom do próprio user). Qualquer conta logada; Sinapses saem do dono do sessionToken. Pra generate: converse com o user e monte uma description rica (vibe, cores, voz, públicos, refs; se ele colar amostra de texto dele, inclua pra a voz sair dali) ANTES de chamar. Confirme o custo (~950 Sinapses) antes de gerar.",
|
|
113
|
+
schema: brandSchema,
|
|
114
|
+
handler: brand,
|
|
115
|
+
},
|
|
110
116
|
};
|
|
111
|
-
const server = new Server({ name: "mcp-sapiens", version: "1.
|
|
117
|
+
const server = new Server({ name: "mcp-sapiens", version: "1.11.0" }, { capabilities: { tools: {} } });
|
|
112
118
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
113
119
|
tools: Object.entries(TOOLS).map(([name, t]) => ({
|
|
114
120
|
name,
|
|
@@ -141,4 +147,4 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
141
147
|
});
|
|
142
148
|
const transport = new StdioServerTransport();
|
|
143
149
|
await server.connect(transport);
|
|
144
|
-
console.error("mcp-sapiens v1.
|
|
150
|
+
console.error("mcp-sapiens v1.11.0 rodando via stdio (18 tools)");
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexAction, convexQuery, convexMutation, getSessionToken, } from "../convexClient.js";
|
|
3
|
+
/**
|
|
4
|
+
* Brand Sapiens (= Design System). Espelha o Estúdio de Brand do app: um Brand
|
|
5
|
+
* é a FONTE ÚNICA de estilo (paleta, tipografia, voz, estilo de imagem,
|
|
6
|
+
* persona). O conteúdo (Source) diz O QUÊ; o Brand diz o COMO. Depois de criado,
|
|
7
|
+
* o brand aparece em todos os seletores do app (pipeline, /escrever, vitrine) e
|
|
8
|
+
* pode virar o padrão da conta.
|
|
9
|
+
*
|
|
10
|
+
* Sub-actions:
|
|
11
|
+
* - list: oficiais (curados) + os custom do user, versão leve (paleta,
|
|
12
|
+
* tipografia, card). De graça.
|
|
13
|
+
* - get: um brand COMPLETO por slug (voz + imageStyle + persona/logo).
|
|
14
|
+
* Só oficial ou custom do próprio user. De graça.
|
|
15
|
+
* - generate: cria um design system NOVO a partir de descrição em texto livre
|
|
16
|
+
* (Gemini monta paleta+tipografia+voz+imageStyle e já nasce com
|
|
17
|
+
* card premium gpt-image-2). Cobra ~950 Sinapses (texto + card),
|
|
18
|
+
* reembolsa se falhar. Identidade vem do sessionToken.
|
|
19
|
+
* - refine: ajusta um brand custom existente por feedback em texto livre
|
|
20
|
+
* ("fundo mais escuro", "voz menos professoral"). ~75 Sinapses.
|
|
21
|
+
* - reroll: regenera SÓ uma peça (voice | palette | imageStyle) numa direção
|
|
22
|
+
* diferente, mantendo o resto. De graça (rate-limited).
|
|
23
|
+
* - card: (re)gera o card premium (gpt-image-2). Cobra o preço de catálogo
|
|
24
|
+
* do modelo (gpt-image-2-high default, ou gpt-image-2-low).
|
|
25
|
+
* - delete: apaga um brand custom do próprio user (oficiais são intocáveis).
|
|
26
|
+
*
|
|
27
|
+
* Auth: qualquer conta logada (sessionToken). As Sinapses saem do dono do token.
|
|
28
|
+
* NÃO mexe em brand de terceiro: custom é privado por dono.
|
|
29
|
+
*/
|
|
30
|
+
const APP = "https://sapiensinteticos.com";
|
|
31
|
+
export const brandSchema = z.object({
|
|
32
|
+
action: z.enum([
|
|
33
|
+
"list",
|
|
34
|
+
"get",
|
|
35
|
+
"generate",
|
|
36
|
+
"refine",
|
|
37
|
+
"reroll",
|
|
38
|
+
"card",
|
|
39
|
+
"delete",
|
|
40
|
+
]),
|
|
41
|
+
slug: z
|
|
42
|
+
.string()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("Slug do brand. Obrigatório em get/refine/reroll/card/delete. Pegue via action=list."),
|
|
45
|
+
description: z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("Pra action=generate: descrição em texto livre do brand (o que o projeto/pessoa é, vibe, cores, voz, referências). Mínimo 30 chars; quanto mais rico, melhor o design system. Se o user colou um texto de amostra dele, inclua aqui pra a voz sair dali."),
|
|
49
|
+
name: z
|
|
50
|
+
.string()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe("Pra action=generate: nome sugerido pro brand (opcional, ≤40 chars). Sem isso o Gemini sugere um."),
|
|
53
|
+
feedback: z
|
|
54
|
+
.string()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Pra action=refine: o que ajustar, em texto livre ('escurece o fundo', 'fonte do título mais bruta', 'voz mais seca'). 5..2000 chars."),
|
|
57
|
+
piece: z
|
|
58
|
+
.enum(["voice", "palette", "imageStyle"])
|
|
59
|
+
.optional()
|
|
60
|
+
.describe("Pra action=reroll: qual peça regenerar numa direção diferente."),
|
|
61
|
+
model: z
|
|
62
|
+
.enum(["gpt-image-2-high", "gpt-image-2-low"])
|
|
63
|
+
.optional()
|
|
64
|
+
.describe("Pra action=card: tier do card premium (default gpt-image-2-high)."),
|
|
65
|
+
});
|
|
66
|
+
export async function brand(args) {
|
|
67
|
+
const sessionToken = getSessionToken();
|
|
68
|
+
// -------- list: oficiais + custom do user (leve, grátis) --------
|
|
69
|
+
if (args.action === "list") {
|
|
70
|
+
const brands = await convexQuery("brands:mcpListBrands", { sessionToken });
|
|
71
|
+
return {
|
|
72
|
+
count: Array.isArray(brands) ? brands.length : 0,
|
|
73
|
+
brands: (brands || []).map((b) => ({
|
|
74
|
+
slug: b.slug,
|
|
75
|
+
name: b.name,
|
|
76
|
+
tagline: b.tagline ?? null,
|
|
77
|
+
palette: b.palette,
|
|
78
|
+
typography: b.typography ?? null,
|
|
79
|
+
cardUrl: b.card?.url ?? null,
|
|
80
|
+
persona: b.persona?.label ?? null,
|
|
81
|
+
})),
|
|
82
|
+
note: "Oficiais (curados) + os seus custom. Pra detalhe completo (voz + estilo " +
|
|
83
|
+
"de imagem): action=get slug=<slug>. Pra criar um novo: action=generate.",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// -------- get: brand completo por slug (grátis) --------
|
|
87
|
+
if (args.action === "get") {
|
|
88
|
+
if (!args.slug)
|
|
89
|
+
throw new Error("action=get exige slug (pegue via action=list).");
|
|
90
|
+
const b = await convexQuery("brands:mcpGetBrand", {
|
|
91
|
+
sessionToken,
|
|
92
|
+
slug: args.slug.trim(),
|
|
93
|
+
});
|
|
94
|
+
if (!b) {
|
|
95
|
+
throw new Error(`Brand "${args.slug}" não encontrado (ou é custom de outro user). Veja os seus em action=list.`);
|
|
96
|
+
}
|
|
97
|
+
return b;
|
|
98
|
+
}
|
|
99
|
+
// -------- generate: cria design system novo (cobra Sinapses) --------
|
|
100
|
+
if (args.action === "generate") {
|
|
101
|
+
const description = (args.description || "").trim();
|
|
102
|
+
if (description.length < 30) {
|
|
103
|
+
throw new Error("action=generate exige description com pelo menos 30 chars (vibe, cores, voz, referências). " +
|
|
104
|
+
"Quanto mais rico, melhor o brand. Converse com o user e monte a descrição antes de chamar.");
|
|
105
|
+
}
|
|
106
|
+
const res = await convexAction("customBrandsActions:mcpGenerateBrand", {
|
|
107
|
+
sessionToken,
|
|
108
|
+
description,
|
|
109
|
+
name: args.name?.trim() || undefined,
|
|
110
|
+
});
|
|
111
|
+
return {
|
|
112
|
+
...res,
|
|
113
|
+
cardNote: res.cardTier === "premium"
|
|
114
|
+
? "Card premium gerado (gpt-image-2)."
|
|
115
|
+
: "Card premium falhou, caiu no pôster SVG (grátis). Pra tentar de novo: action=card slug=" +
|
|
116
|
+
res.slug,
|
|
117
|
+
viewUrl: `${APP}/experimentos/brands`,
|
|
118
|
+
next: "Ajustar: action=refine slug=" +
|
|
119
|
+
res.slug +
|
|
120
|
+
" feedback='...'. Regenerar uma peça: action=reroll slug=" +
|
|
121
|
+
res.slug +
|
|
122
|
+
" piece=voice|palette|imageStyle.",
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// -------- refine: ajusta brand custom existente (cobra Sinapses) --------
|
|
126
|
+
if (args.action === "refine") {
|
|
127
|
+
if (!args.slug)
|
|
128
|
+
throw new Error("action=refine exige slug do brand custom.");
|
|
129
|
+
const feedback = (args.feedback || "").trim();
|
|
130
|
+
if (feedback.length < 5) {
|
|
131
|
+
throw new Error("action=refine exige feedback (ex: 'fundo mais escuro', 'voz mais seca').");
|
|
132
|
+
}
|
|
133
|
+
const res = await convexAction("customBrandsActions:mcpRefineBrand", {
|
|
134
|
+
sessionToken,
|
|
135
|
+
slug: args.slug.trim(),
|
|
136
|
+
feedback,
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
...res,
|
|
140
|
+
viewUrl: `${APP}/experimentos/brands`,
|
|
141
|
+
note: "Brand ajustado. Veja o resultado com action=get slug=" + res.slug,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// -------- reroll: regenera 1 peça numa direção diferente (grátis) --------
|
|
145
|
+
if (args.action === "reroll") {
|
|
146
|
+
if (!args.slug)
|
|
147
|
+
throw new Error("action=reroll exige slug do brand custom.");
|
|
148
|
+
if (!args.piece)
|
|
149
|
+
throw new Error("action=reroll exige piece: voice | palette | imageStyle.");
|
|
150
|
+
const res = await convexAction("customBrandsActions:mcpRerollBrandPiece", {
|
|
151
|
+
sessionToken,
|
|
152
|
+
slug: args.slug.trim(),
|
|
153
|
+
piece: args.piece,
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
...res,
|
|
157
|
+
note: "Peça '" +
|
|
158
|
+
args.piece +
|
|
159
|
+
"' regenerada (grátis). Não gostou? Roda de novo. Veja com action=get slug=" +
|
|
160
|
+
res.slug,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// -------- card: (re)gera o card premium (cobra Sinapses) --------
|
|
164
|
+
if (args.action === "card") {
|
|
165
|
+
if (!args.slug)
|
|
166
|
+
throw new Error("action=card exige slug do brand custom.");
|
|
167
|
+
const res = await convexAction("customBrandsActions:mcpGenerateBrandCard", {
|
|
168
|
+
sessionToken,
|
|
169
|
+
slug: args.slug.trim(),
|
|
170
|
+
model: args.model || undefined,
|
|
171
|
+
});
|
|
172
|
+
return {
|
|
173
|
+
...res,
|
|
174
|
+
note: `Card premium gerado (${res.cost} Sinapses). URL: ${res.url}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// -------- delete: apaga brand custom do próprio user --------
|
|
178
|
+
if (args.action === "delete") {
|
|
179
|
+
if (!args.slug)
|
|
180
|
+
throw new Error("action=delete exige slug do brand custom.");
|
|
181
|
+
const res = await convexMutation("brands:mcpDeleteBrand", {
|
|
182
|
+
sessionToken,
|
|
183
|
+
slug: args.slug.trim(),
|
|
184
|
+
});
|
|
185
|
+
return {
|
|
186
|
+
...res,
|
|
187
|
+
note: "Brand apagado. Sources/artigos que apontavam pra ele caem no fallback (sapiens).",
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
package/dist/tools/studios.js
CHANGED
|
@@ -8,7 +8,7 @@ import { z } from "zod";
|
|
|
8
8
|
* certo quando ele pede coisa que não está coberta no plugin v1.x.
|
|
9
9
|
*
|
|
10
10
|
* v1.4 vai adicionar wrappers session-token-auth pros estúdios que justificam
|
|
11
|
-
* (Helen Voice TTS, Musicator letras, Sapiens Shorts render, Persona
|
|
11
|
+
* (Helen Voice TTS, Musicator letras, Sapiens Shorts render, Persona Sapiens).
|
|
12
12
|
* Por hora skills usam Claude-side + dashboard URL.
|
|
13
13
|
*/
|
|
14
14
|
export const studiosSchema = z.object({
|
|
@@ -16,7 +16,7 @@ export const studiosSchema = z.object({
|
|
|
16
16
|
studio: z
|
|
17
17
|
.string()
|
|
18
18
|
.optional()
|
|
19
|
-
.describe("Pra action=get: slug do estúdio (ex 'helen-voice', 'musicator', 'persona-
|
|
19
|
+
.describe("Pra action=get: slug do estúdio (ex 'helen-voice', 'musicator', 'persona-sapiens', 'sapiens-shorts')."),
|
|
20
20
|
publishableId: z
|
|
21
21
|
.string()
|
|
22
22
|
.optional()
|
|
@@ -48,15 +48,24 @@ const STUDIOS = {
|
|
|
48
48
|
mcpReady: true,
|
|
49
49
|
mcpNote: "Coberto via sapiens_musicator (lyrics). Render do áudio continua UI-driven (precisa criar track + scheduler).",
|
|
50
50
|
},
|
|
51
|
-
"persona-
|
|
52
|
-
name: "Persona
|
|
53
|
-
description: "
|
|
54
|
-
url: `${APP}/experimentos/
|
|
51
|
+
"persona-sapiens": {
|
|
52
|
+
name: "Persona Sapiens",
|
|
53
|
+
description: "Teste de personalidade pra AUTOCONHECIMENTO (não é gerador de imagem): quiz que cruza MBTI com humores antigos, elementos e estilos. 48 perguntas Likert (~10 min), resultado com persona/animal cultural/sombra/espelho, salvo no perfil do user. Secundário: arte ilustrada dos 16 arquétipos MBTI (full-bleed, Sapiens style).",
|
|
54
|
+
url: `${APP}/experimentos/persona-sapiens`,
|
|
55
55
|
status: "stable",
|
|
56
|
-
tags: ["persona", "mbti", "
|
|
57
|
-
convex: "
|
|
56
|
+
tags: ["persona", "mbti", "quiz", "autoconhecimento", "perfil", "personalidade", "teste"],
|
|
57
|
+
convex: "personalityProfiles",
|
|
58
58
|
mcpReady: true,
|
|
59
|
-
mcpNote: "Coberto via sapiens_persona (generate + list_codes).",
|
|
59
|
+
mcpNote: "Coberto via sapiens_persona. PRIMÁRIO (de graça, qualquer logado): get_quiz + submit_quiz + my_profile — aplica o teste conversando e ALIMENTA o personalityProfile do user. SECUNDÁRIO: generate + list_codes (arte dos arquétipos, 450 Sinapses).",
|
|
60
|
+
},
|
|
61
|
+
"personagem-atlas": {
|
|
62
|
+
name: "Personagem-Atlas",
|
|
63
|
+
description: "Dossiê editorial premium de personagens sintéticos: 10 slides com tipografia refinada, paleta cromática e geração de conteúdo via IA. É construção de PERSONAGEM ficcional, não o teste de personalidade do user (esse é o persona-sapiens).",
|
|
64
|
+
url: `${APP}/experimentos/personagem-atlas`,
|
|
65
|
+
status: "stable",
|
|
66
|
+
tags: ["personagem", "dossie", "editorial", "slides", "atlas", "character"],
|
|
67
|
+
convex: "characterAtlas",
|
|
68
|
+
mcpReady: false,
|
|
60
69
|
},
|
|
61
70
|
"sapiens-shorts": {
|
|
62
71
|
name: "Sapiens Shorts (UGC / Reflexão)",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.1",
|
|
4
4
|
"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.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|