sapiens-mcp 1.11.1 → 1.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/LICENSE +21 -0
- package/dist/index.js +9 -3
- package/dist/tools/character.js +191 -0
- package/dist/tools/gallery.js +15 -2
- package/dist/tools/image.js +5 -2
- package/dist/tools/meta.js +15 -15
- package/dist/tools/pipeline.js +11 -5
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Borderless (Sapiens Sintéticos)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ 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
23
|
import { brand, brandSchema } from "./tools/brand.js";
|
|
24
|
+
import { character, characterSchema } from "./tools/character.js";
|
|
24
25
|
import { describeConvexError } from "./convexClient.js";
|
|
25
26
|
const TOOLS = {
|
|
26
27
|
sapiens_pipeline: {
|
|
@@ -44,7 +45,7 @@ const TOOLS = {
|
|
|
44
45
|
handler: repertorio,
|
|
45
46
|
},
|
|
46
47
|
sapiens_gallery: {
|
|
47
|
-
description: "Browse das imagens geradas pelo user (nanoBanana). Sub-actions: list (últimas N imagens, com prompt/model/url), get (1 imagem com metadados, opcionalmente base64). Use pra reusar imagem como referência (passe o imageId em sapiens_image mode=edit ou mode=variation)
|
|
48
|
+
description: "Browse e publicação das imagens geradas pelo user (nanoBanana). Sub-actions: list (últimas N imagens, com prompt/model/url + isPublic), get (1 imagem com metadados, opcionalmente base64), publish (torna a PRÓPRIA imagem pública: entra na galeria pública + feed Pinterest, e ganha página indexável /imagem/<id> se o modelo não for degen — devolve publicPageUrl), unpublish (volta a privada). Use list/get pra reusar imagem como referência (passe o imageId em sapiens_image mode=edit ou mode=variation) ou pra mostrar pro user o que ele já tem; publish quando o user quer divulgar a imagem dele.",
|
|
48
49
|
schema: gallerySchema,
|
|
49
50
|
handler: gallery,
|
|
50
51
|
},
|
|
@@ -113,8 +114,13 @@ const TOOLS = {
|
|
|
113
114
|
schema: brandSchema,
|
|
114
115
|
handler: brand,
|
|
115
116
|
},
|
|
117
|
+
sapiens_character: {
|
|
118
|
+
description: "Personagens (character sheets) do Sapiens — a tabela `influencers`: personagem reutilizável com imagens (pra character-lock em geração) + alma (systemPrompt), tudo amarrado à conta do dono do token (sem admin). Sub-actions: list_public (catálogo global de personagens públicos do Explorar; cada um traz mainImageUrl/imageUrls usáveis direto como referenceImageUrls em sapiens_image; sem custo, sem login), get (detalhe de 1 por characterId — público+ativo qualquer um vê, draft/privado só o dono; systemPrompt só volta pro dono), list_mine (os personagens do próprio user, inclui drafts/privados), create (cria rascunho na conta: name + gender + opcional title/systemPrompt), add_image (adiciona imagem ao próprio personagem via imageUrl público OU sourceImageId da galeria; 1ª vira principal), set_card (edita alma/título/nome do próprio), activate (publica, sai de draft, exige ≥1 imagem), set_visibility (isPublic true=Explorar+slug / false=privado). Fluxo de criação: create → add_image (1+) → set_card (opcional) → activate → set_visibility isPublic=true. Pra usar um personagem público como referência numa geração, pegue mainImageUrl em list_public/get e passe em sapiens_image referenceImageUrls.",
|
|
119
|
+
schema: characterSchema,
|
|
120
|
+
handler: character,
|
|
121
|
+
},
|
|
116
122
|
};
|
|
117
|
-
const server = new Server({ name: "mcp-sapiens", version: "1.
|
|
123
|
+
const server = new Server({ name: "mcp-sapiens", version: "1.13.0" }, { capabilities: { tools: {} } });
|
|
118
124
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
119
125
|
tools: Object.entries(TOOLS).map(([name, t]) => ({
|
|
120
126
|
name,
|
|
@@ -147,4 +153,4 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
147
153
|
});
|
|
148
154
|
const transport = new StdioServerTransport();
|
|
149
155
|
await server.connect(transport);
|
|
150
|
-
console.error("mcp-sapiens v1.
|
|
156
|
+
console.error("mcp-sapiens v1.13.0 rodando via stdio (19 tools)");
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js";
|
|
3
|
+
/**
|
|
4
|
+
* sapiens_character — personagens (character sheets) do Sapiens.
|
|
5
|
+
*
|
|
6
|
+
* "Character" aqui é a tabela `influencers`: personagem reutilizável com
|
|
7
|
+
* imagens (pra character-lock em geração) + alma (systemPrompt). Tudo amarrado
|
|
8
|
+
* à conta do dono do sessionToken. Sem nada de admin.
|
|
9
|
+
*
|
|
10
|
+
* Sub-actions:
|
|
11
|
+
* - list_public: catálogo global de personagens públicos (Explorar). Cada um
|
|
12
|
+
* traz mainImageUrl/imageUrls usáveis como referência em
|
|
13
|
+
* sapiens_image (referenceImageUrls). Sem custo.
|
|
14
|
+
* - get: detalhe de 1 personagem por id. Público+ativo: qualquer um.
|
|
15
|
+
* Draft/privado: só o dono. systemPrompt só volta pro dono.
|
|
16
|
+
* - list_mine: os personagens do próprio user (inclui drafts/privados).
|
|
17
|
+
* - create: cria um personagem (rascunho) na conta. name + gender.
|
|
18
|
+
* - add_image: adiciona imagem ao próprio personagem (imageUrl direto ou
|
|
19
|
+
* sourceImageId da galeria). 1ª imagem vira a principal.
|
|
20
|
+
* - set_card: edita a alma (systemPrompt), título e/ou nome do próprio.
|
|
21
|
+
* - activate: publica (sai de draft). Exige ≥1 imagem.
|
|
22
|
+
* - set_visibility: público (entra no Explorar, ganha slug) ou privado.
|
|
23
|
+
*
|
|
24
|
+
* Fluxo típico de criação: create → add_image (1+) → set_card (opcional) →
|
|
25
|
+
* activate → set_visibility isPublic=true.
|
|
26
|
+
*/
|
|
27
|
+
export const characterSchema = z.object({
|
|
28
|
+
action: z.enum([
|
|
29
|
+
"list_public",
|
|
30
|
+
"get",
|
|
31
|
+
"list_mine",
|
|
32
|
+
"create",
|
|
33
|
+
"add_image",
|
|
34
|
+
"set_card",
|
|
35
|
+
"activate",
|
|
36
|
+
"set_visibility",
|
|
37
|
+
]),
|
|
38
|
+
characterId: z
|
|
39
|
+
.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("ID do personagem (influencers:_id). Obrigatório em get/add_image/set_card/activate/set_visibility. Descubra via list_public ou list_mine."),
|
|
42
|
+
limit: z
|
|
43
|
+
.number()
|
|
44
|
+
.int()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Pra list_public: quantos retornar (default 40, max 100)."),
|
|
47
|
+
name: z
|
|
48
|
+
.string()
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Pra create (obrigatório) ou set_card (renomear): nome do personagem."),
|
|
51
|
+
gender: z
|
|
52
|
+
.string()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("Pra create: 'masculino' | 'feminino' | 'nao-binario'. Default 'nao-binario'."),
|
|
55
|
+
title: z
|
|
56
|
+
.string()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Pra create/set_card: subtítulo curto (ex: 'A guia do Sapiens')."),
|
|
59
|
+
systemPrompt: z
|
|
60
|
+
.string()
|
|
61
|
+
.optional()
|
|
62
|
+
.describe("Pra create/set_card: a 'alma' do personagem (personalidade, jeito de falar, contexto). Usado no chat e como guia de geração."),
|
|
63
|
+
imageUrl: z
|
|
64
|
+
.string()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe("Pra add_image: URL pública da imagem (Bunny CDN / Convex storage). Use a `url` que sapiens_image/sapiens_gallery devolvem."),
|
|
67
|
+
sourceImageId: z
|
|
68
|
+
.string()
|
|
69
|
+
.optional()
|
|
70
|
+
.describe("Pra add_image: alternativa ao imageUrl — ID de imagem da SUA galeria (generatedImages:_id, via sapiens_gallery action=list). O backend resolve a url e confere que é sua."),
|
|
71
|
+
isMain: z
|
|
72
|
+
.boolean()
|
|
73
|
+
.optional()
|
|
74
|
+
.describe("Pra add_image: marca esta como a imagem principal (avatar). 1ª imagem já vira main sozinha."),
|
|
75
|
+
isPublic: z
|
|
76
|
+
.boolean()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe("Pra set_visibility: true = público no Explorar (gera slug), false = privado."),
|
|
79
|
+
});
|
|
80
|
+
export async function character(args) {
|
|
81
|
+
// -------- list_public: catálogo global (sessionToken opcional, marca `mine`) --------
|
|
82
|
+
if (args.action === "list_public") {
|
|
83
|
+
let sessionToken;
|
|
84
|
+
try {
|
|
85
|
+
sessionToken = getSessionToken();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
sessionToken = undefined; // catálogo público funciona sem login
|
|
89
|
+
}
|
|
90
|
+
return await convexQuery("influencers:mcpListPublicCharacters", {
|
|
91
|
+
sessionToken,
|
|
92
|
+
limit: args.limit,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// -------- get: detalhe de 1 personagem --------
|
|
96
|
+
if (args.action === "get") {
|
|
97
|
+
if (!args.characterId) {
|
|
98
|
+
throw new Error("action=get exige characterId (pegue via list_public ou list_mine).");
|
|
99
|
+
}
|
|
100
|
+
let sessionToken;
|
|
101
|
+
try {
|
|
102
|
+
sessionToken = getSessionToken();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
sessionToken = undefined;
|
|
106
|
+
}
|
|
107
|
+
const res = await convexQuery("influencers:mcpGetCharacter", {
|
|
108
|
+
sessionToken,
|
|
109
|
+
characterId: args.characterId,
|
|
110
|
+
});
|
|
111
|
+
if (!res) {
|
|
112
|
+
throw new Error(`Personagem "${args.characterId}" não encontrado (ou é privado de outro user).`);
|
|
113
|
+
}
|
|
114
|
+
return res;
|
|
115
|
+
}
|
|
116
|
+
// -------- list_mine: personagens do próprio user (inclui drafts) --------
|
|
117
|
+
if (args.action === "list_mine") {
|
|
118
|
+
const sessionToken = getSessionToken();
|
|
119
|
+
return await convexQuery("influencers:mcpListMyCharacters", { sessionToken });
|
|
120
|
+
}
|
|
121
|
+
// -------- create: novo rascunho na conta --------
|
|
122
|
+
if (args.action === "create") {
|
|
123
|
+
if (!args.name || !args.name.trim()) {
|
|
124
|
+
throw new Error("action=create exige 'name'.");
|
|
125
|
+
}
|
|
126
|
+
const sessionToken = getSessionToken();
|
|
127
|
+
return await convexMutation("influencers:mcpCreateCharacter", {
|
|
128
|
+
sessionToken,
|
|
129
|
+
name: args.name,
|
|
130
|
+
gender: args.gender,
|
|
131
|
+
title: args.title,
|
|
132
|
+
systemPrompt: args.systemPrompt,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// -------- add_image: imagem no próprio personagem --------
|
|
136
|
+
if (args.action === "add_image") {
|
|
137
|
+
if (!args.characterId)
|
|
138
|
+
throw new Error("action=add_image exige characterId.");
|
|
139
|
+
if (!args.imageUrl && !args.sourceImageId) {
|
|
140
|
+
throw new Error("action=add_image exige 'imageUrl' ou 'sourceImageId'.");
|
|
141
|
+
}
|
|
142
|
+
const sessionToken = getSessionToken();
|
|
143
|
+
return await convexMutation("influencers:mcpAddCharacterImage", {
|
|
144
|
+
sessionToken,
|
|
145
|
+
characterId: args.characterId,
|
|
146
|
+
imageUrl: args.imageUrl,
|
|
147
|
+
sourceImageId: args.sourceImageId,
|
|
148
|
+
isMain: args.isMain,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
// -------- set_card: alma/título/nome do próprio personagem --------
|
|
152
|
+
if (args.action === "set_card") {
|
|
153
|
+
if (!args.characterId)
|
|
154
|
+
throw new Error("action=set_card exige characterId.");
|
|
155
|
+
if (args.systemPrompt === undefined && args.title === undefined && args.name === undefined) {
|
|
156
|
+
throw new Error("action=set_card precisa de pelo menos um: systemPrompt, title ou name.");
|
|
157
|
+
}
|
|
158
|
+
const sessionToken = getSessionToken();
|
|
159
|
+
return await convexMutation("influencers:mcpSetCharacterCard", {
|
|
160
|
+
sessionToken,
|
|
161
|
+
characterId: args.characterId,
|
|
162
|
+
systemPrompt: args.systemPrompt,
|
|
163
|
+
title: args.title,
|
|
164
|
+
name: args.name,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
// -------- activate: publica (sai de draft, exige ≥1 imagem) --------
|
|
168
|
+
if (args.action === "activate") {
|
|
169
|
+
if (!args.characterId)
|
|
170
|
+
throw new Error("action=activate exige characterId.");
|
|
171
|
+
const sessionToken = getSessionToken();
|
|
172
|
+
return await convexMutation("influencers:mcpActivateCharacter", {
|
|
173
|
+
sessionToken,
|
|
174
|
+
characterId: args.characterId,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// -------- set_visibility: público (Explorar) ou privado --------
|
|
178
|
+
if (args.action === "set_visibility") {
|
|
179
|
+
if (!args.characterId)
|
|
180
|
+
throw new Error("action=set_visibility exige characterId.");
|
|
181
|
+
if (args.isPublic === undefined) {
|
|
182
|
+
throw new Error("action=set_visibility exige isPublic (true=público, false=privado).");
|
|
183
|
+
}
|
|
184
|
+
const sessionToken = getSessionToken();
|
|
185
|
+
return await convexMutation("influencers:mcpSetCharacterVisibility", {
|
|
186
|
+
sessionToken,
|
|
187
|
+
characterId: args.characterId,
|
|
188
|
+
isPublic: args.isPublic,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
package/dist/tools/gallery.js
CHANGED
|
@@ -8,9 +8,10 @@ import { convexAction, getSessionToken } from "../convexClient.js";
|
|
|
8
8
|
* - Listar imagens recentes do user (pra reusar como referenceImage)
|
|
9
9
|
* - Pegar bytes de uma imagem pra mostrar inline no Claude
|
|
10
10
|
* - Descobrir imageId pra passar como sourceImageId em sapiens_image edit/variation
|
|
11
|
+
* - Publicar/despublicar a própria imagem (galeria pública + feed Pinterest)
|
|
11
12
|
*/
|
|
12
13
|
export const gallerySchema = z.object({
|
|
13
|
-
action: z.enum(["list", "get"]),
|
|
14
|
+
action: z.enum(["list", "get", "publish", "unpublish"]),
|
|
14
15
|
limit: z
|
|
15
16
|
.number()
|
|
16
17
|
.int()
|
|
@@ -25,7 +26,7 @@ export const gallerySchema = z.object({
|
|
|
25
26
|
imageId: z
|
|
26
27
|
.string()
|
|
27
28
|
.optional()
|
|
28
|
-
.describe("generatedImages:_id (obrigatório pra action=get)"),
|
|
29
|
+
.describe("generatedImages:_id (obrigatório pra action=get/publish/unpublish)"),
|
|
29
30
|
includeBase64: z
|
|
30
31
|
.boolean()
|
|
31
32
|
.optional()
|
|
@@ -54,4 +55,16 @@ export async function gallery(args) {
|
|
|
54
55
|
includeBase64: args.includeBase64 ?? false,
|
|
55
56
|
});
|
|
56
57
|
}
|
|
58
|
+
// publish/unpublish: liga/desliga isPublic na própria imagem. Public = entra
|
|
59
|
+
// na galeria pública + feed Pinterest (e /imagem/<id> se não for degen).
|
|
60
|
+
if (args.action === "publish" || args.action === "unpublish") {
|
|
61
|
+
if (!args.imageId) {
|
|
62
|
+
throw new Error(`action=${args.action} exige imageId. Use action=list pra descobrir.`);
|
|
63
|
+
}
|
|
64
|
+
return await convexAction("desktopMcp:gallerySetPublic", {
|
|
65
|
+
sessionToken,
|
|
66
|
+
imageId: args.imageId,
|
|
67
|
+
isPublic: args.action === "publish",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
57
70
|
}
|
package/dist/tools/image.js
CHANGED
|
@@ -8,6 +8,9 @@ const MODELS = [
|
|
|
8
8
|
"nano-banana-2", // gemini-3.1-flash-image-preview (V2, Flash 3.1) · 450 + adder · COM refs · DEFAULT
|
|
9
9
|
"gpt-image-2-low", // Azure gpt-image-2 quality=low · 250
|
|
10
10
|
"gpt-image-2-high", // Azure gpt-image-2 quality=high · 800
|
|
11
|
+
// xAI Grok Imagine. Moderação frouxa (+18), aceita refs (img2img) + aspect.
|
|
12
|
+
"grok-2-image", // grok-imagine-image · 450 + adder 2K · COM refs
|
|
13
|
+
"grok-2-image-quality", // grok-imagine-image-quality, mais fiel pra character lock · 900 + adder 2K · COM refs
|
|
11
14
|
// Degen (uncensored, gate +18 na galeria). WaveSpeed = rápido (6-25s):
|
|
12
15
|
"wavespeed-chroma", // Chroma uncensored fotorrealista · 600
|
|
13
16
|
"wavespeed-flux2", // Flux.2 Klein 9B · 600
|
|
@@ -24,7 +27,7 @@ export const imageSchema = z.object({
|
|
|
24
27
|
model: z
|
|
25
28
|
.enum(MODELS)
|
|
26
29
|
.optional()
|
|
27
|
-
.describe("Default 'nano-banana-2' (Flash 3.1 com refs). 'nano-banana-max' (Pro 3) = qualidade alta. 'gpt-image-2-low/high' = Azure. DEGEN (uncensored, gate +18): 'wavespeed-chroma' (fotorrealista rápido), 'wavespeed-flux2' (Flux.2 Klein), 'wavespeed-flux-nsfw' (flux+LoRA NSFW) = WaveSpeed rápido; 'civitai-wai-illustrious'/'civitai-nova-anime-xl' (anime), 'civitai-pony-v6' (Pony V6 XL, base nº1) = Civitai sdcpp rápido."),
|
|
30
|
+
.describe("Default 'nano-banana-2' (Flash 3.1 com refs). 'nano-banana-max' (Pro 3) = qualidade alta. 'gpt-image-2-low/high' = Azure. 'grok-2-image'/'grok-2-image-quality' = xAI Grok Imagine (moderação frouxa +18, aceita refs e aspect; quality é mais fiel pra character lock). DEGEN (uncensored, gate +18): 'wavespeed-chroma' (fotorrealista rápido), 'wavespeed-flux2' (Flux.2 Klein), 'wavespeed-flux-nsfw' (flux+LoRA NSFW) = WaveSpeed rápido; 'civitai-wai-illustrious'/'civitai-nova-anime-xl' (anime), 'civitai-pony-v6' (Pony V6 XL, base nº1) = Civitai sdcpp rápido."),
|
|
28
31
|
aspectRatio: z
|
|
29
32
|
.enum(["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"])
|
|
30
33
|
.optional()
|
|
@@ -41,7 +44,7 @@ export const imageSchema = z.object({
|
|
|
41
44
|
referenceImageUrls: z
|
|
42
45
|
.array(z.string())
|
|
43
46
|
.optional()
|
|
44
|
-
.describe("URLs públicas (Convex storage / Bunny CDN / Wikimedia) usadas como reference images. Trava character/style entre múltiplas gerações. Requer model com supportsReferences=true (nano-banana-2
|
|
47
|
+
.describe("URLs públicas (Convex storage / Bunny CDN / Wikimedia) usadas como reference images. Trava character/style entre múltiplas gerações. Requer model com supportsReferences=true (nano-banana-2, gpt-image-2-* ou grok-2-image*)."),
|
|
45
48
|
brandSlug: z
|
|
46
49
|
.string()
|
|
47
50
|
.optional()
|
package/dist/tools/meta.js
CHANGED
|
@@ -74,11 +74,11 @@ const FORMAT_GUIDE = {
|
|
|
74
74
|
},
|
|
75
75
|
},
|
|
76
76
|
cena_visual: {
|
|
77
|
-
description: "
|
|
77
|
+
description: "Vídeo curto programático via Hyperframes (movimento + texto entram por código).",
|
|
78
78
|
payloadHint: {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
concept: "string (ideia da cena)",
|
|
80
|
+
scenes: [{ text: "string", motion: "string", durationMs: "number" }],
|
|
81
|
+
durationMs: "number total opcional",
|
|
82
82
|
},
|
|
83
83
|
},
|
|
84
84
|
video_yt: {
|
|
@@ -89,20 +89,20 @@ const FORMAT_GUIDE = {
|
|
|
89
89
|
scenes: [{ visual: "string", voiceover: "string", duration: "number" }],
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
|
-
|
|
93
|
-
description: "
|
|
94
|
-
payloadHint: { text: "string", hashtags: ["string"] },
|
|
95
|
-
},
|
|
96
|
-
post_twitter: {
|
|
97
|
-
description: "Post Twitter/X (single ou thread).",
|
|
92
|
+
mega_grafico: {
|
|
93
|
+
description: "Pôster blueprint denso multi-seção (estilo Pop Chart), texto fiel via gpt-image-2. Tem runner próprio: propose_mega_grafico_plan / run_mega_grafico_full.",
|
|
98
94
|
payloadHint: {
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
title: "string",
|
|
96
|
+
sections: [{ heading: "string", items: ["string"] }],
|
|
97
|
+
withHelen: "boolean (1 painel com a Helen interagindo com o tema)",
|
|
101
98
|
},
|
|
102
99
|
},
|
|
103
|
-
|
|
104
|
-
description: "
|
|
105
|
-
payloadHint: {
|
|
100
|
+
aula: {
|
|
101
|
+
description: "Aula em slides (deck navegável no site /aulas) destilada do source: framework nomeado + analogia.",
|
|
102
|
+
payloadHint: {
|
|
103
|
+
title: "string",
|
|
104
|
+
slides: [{ title: "string", body: "string", note: "string opcional" }],
|
|
105
|
+
},
|
|
106
106
|
},
|
|
107
107
|
};
|
|
108
108
|
export async function meta(args) {
|
package/dist/tools/pipeline.js
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { convexAction, convexMutation, convexQuery, getSessionToken, } from "../convexClient.js";
|
|
3
|
+
// Espelho canônico dos formatos do app (peças surface:'format' em PIECES,
|
|
4
|
+
// apps/sapiens/src/features/content-pipeline/registry.jsx). Mantido em sync por
|
|
5
|
+
// lint: `npm run audit:mcp-format-parity` falha o CI se divergir. Ao adicionar
|
|
6
|
+
// ou remover formato, mexa nos dois lados.
|
|
3
7
|
const FORMATS = [
|
|
4
8
|
"tirinha",
|
|
5
9
|
"carrossel_ig",
|
|
6
10
|
"post_social",
|
|
7
|
-
"musica",
|
|
8
11
|
"mega_grafico",
|
|
9
|
-
"post_linkedin",
|
|
10
|
-
"post_twitter",
|
|
11
|
-
"post_threads",
|
|
12
12
|
"shorts_yt",
|
|
13
13
|
"cena_visual",
|
|
14
14
|
"video_yt",
|
|
15
|
+
"musica",
|
|
16
|
+
"aula",
|
|
15
17
|
];
|
|
18
|
+
// Formatos legados: fora do FORMAT_GUIDE (não advertidos), mas ainda aceitos na
|
|
19
|
+
// validação pra editar productions antigas sem quebrar.
|
|
20
|
+
const LEGACY_FORMATS = ["post_linkedin", "post_twitter", "post_threads"];
|
|
21
|
+
const ACCEPTED_FORMATS = [...FORMATS, ...LEGACY_FORMATS];
|
|
16
22
|
const STATUSES = ["draft", "ready", "finalized"];
|
|
17
23
|
export const pipelineSchema = z.object({
|
|
18
24
|
action: z.enum([
|
|
@@ -75,7 +81,7 @@ export const pipelineSchema = z.object({
|
|
|
75
81
|
publishableId: z.string().optional(),
|
|
76
82
|
articleId: z.string().optional(),
|
|
77
83
|
// create / add
|
|
78
|
-
format: z.enum(
|
|
84
|
+
format: z.enum(ACCEPTED_FORMATS).optional(),
|
|
79
85
|
payload: z.any().optional().describe("Payload livre por formato"),
|
|
80
86
|
status: z.enum(STATUSES).optional(),
|
|
81
87
|
notes: z.string().optional(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
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": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=18"
|
|
15
15
|
},
|
|
16
|
-
"homepage": "https://sapiensinteticos.com/conectar-claude",
|
|
16
|
+
"homepage": "https://www.sapiensinteticos.com/conectar-claude",
|
|
17
17
|
"keywords": [
|
|
18
18
|
"mcp",
|
|
19
19
|
"model-context-protocol",
|