sapiens-mcp 1.26.2 → 1.26.4
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 +48 -42
- package/dist/tools/instagram.js +98 -0
- package/dist/tools/video.js +13 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { article, articleSchema } from "./tools/article.js";
|
|
|
13
13
|
import { quotePop, quotePopSchema } from "./tools/quotePop.js";
|
|
14
14
|
import { search, searchSchema } from "./tools/search.js";
|
|
15
15
|
import { studios, studiosSchema } from "./tools/studios.js";
|
|
16
|
+
import { instagram, instagramSchema } from "./tools/instagram.js";
|
|
16
17
|
import { persona, personaSchema } from "./tools/persona.js";
|
|
17
18
|
import { helen, helenSchema } from "./tools/helen.js";
|
|
18
19
|
import { musicator, musicatorSchema } from "./tools/musicator.js";
|
|
@@ -148,6 +149,11 @@ const TOOLS = {
|
|
|
148
149
|
schema: forumSchema,
|
|
149
150
|
handler: forum,
|
|
150
151
|
},
|
|
152
|
+
sapiens_instagram: {
|
|
153
|
+
description: "Auto-DM do Instagram da casa (o 'ManyChat próprio') — ADMIN-ONLY (dono). Quem manda DM ou comenta keyword num post do @sapiensinteticos recebe resposta automática; aqui você OPERA esse motor. Sub-actions: 'rules' (lista regras: keyword, resposta, variações, eco público, escopo por post, disparos), 'rule_upsert' (cria/edita regra; ruleId presente = edita; keyword+reply obrigatórios fora do fallback; replyVariants/echoVariants rodam em round-robin pra não repetir; mediaId escopa a regra num post; isFallback responde DM sem keyword 1x/24h por pessoa), 'rule_delete' (apaga por ruleId), 'inbox' (conversas recentes; cada uma com canReply = janela de 24h da Meta aberta ou não), 'thread' (mensagens de uma conversa por igUserId), 'send' (responde na mão pela janela de 24h; fora dela a Meta recusa). Comentário só dispara regra de KEYWORD (fallback nunca), com eco público opcional ('te respondi no direct!'). Limites da API: não dá pra iniciar conversa, só reagir; janela de 24h pra responder DM.",
|
|
154
|
+
schema: instagramSchema,
|
|
155
|
+
handler: instagram,
|
|
156
|
+
},
|
|
151
157
|
sapiens_aula: {
|
|
152
158
|
description: "Aula (deck da Mentoria OPS, servido em /aulas/<slug>) — ADMIN-ONLY (aula é conteúdo de mentor, não de aluno; aluno leva 'restrito ao dono'). Cria e edita aula direto no Convex, sem o script migrate-aulas-to-convex.mjs. Sub-actions: 'list' (slug/título/data/slideCount/voiceWarnings/url), 'get' (1 aula completa por slug, pra editar local), 'upsert' (cria se não existe, senão patch; por slug kebab-case). O `aula` do upsert é o objeto completo: title (obrig) + slides[] (≥1) + subtitle/data/duration/tag/mentorAgenda opcionais. Slides são { type, ...campos }: cover, cover-image/section-image/content-image (imageUrl), agenda (items[]), content (body markdown/HTML + list[]/listType), two-col (cols[]), quote, callout (tone tip|warn|note), comic (panels[]), pause, close (items[]). O servidor re-linta a voz e grava voiceWarnings (1ª pessoa, anti-corporate, SEM travessão). A rota /aulas/<slug> serve sob demanda; slug novo aparece sem rebuild.",
|
|
153
159
|
schema: aulaSchema,
|
|
@@ -179,48 +185,48 @@ const TOOLS = {
|
|
|
179
185
|
// É a "skill que anda junto com o pacote": escrevo uma vez, vale pra todos os clients,
|
|
180
186
|
// sem instalar nada. Cobre os tropeços reais (fluxo do musicator, model no vídeo, o
|
|
181
187
|
// disjuntor anti-loop). Mantém curto de propósito: viaja em todo handshake.
|
|
182
|
-
const SAPIENS_INSTRUCTIONS = `Você opera o Sapiens Sintéticos (sapiensinteticos.com) NA CONTA de um usuário logado. Cada tool age de verdade na conta dele e muitas COBRAM Sinapses (o crédito da casa). Aja como operador, não no chute.
|
|
183
|
-
|
|
184
|
-
REGRA DE OURO:
|
|
185
|
-
- PRIMEIRO CONTATO ou "o que você faz?"/"como começo?"/"o que dá pra fazer?": chame sapiens_meta action=start e MOSTRE o resultado na sua voz. Sem login, ele ensina a conectar; logado, traz saldo + primeiros poderes com exemplos. É a porta de entrada: não despeje a lista dos 27 tools, deixe o start guiar.
|
|
186
|
-
- LOGO APÓS UM LOGIN BEM-SUCEDIDO (action=login retornou ok): chame action=start na sequência e mostre a porta de entrada. O recém-chegado não sabe o que pedir; não o deixe na tela em branco, guie a primeira jogada sem ele precisar perguntar.
|
|
187
|
-
- Se um tool voltar erro de validação ("exige X", "falta Y"), LEIA o erro e refaça a chamada COM o que falta. NUNCA repita igual a chamada que falhou: 3 falhas seguidas no mesmo tool fazem o cliente marcar o servidor como "unreachable" por ~56s (disjuntor anti-loop). Aí parece que "o MCP caiu", quando foi só argumento faltando.
|
|
188
|
-
- Antes de gerar algo caro (imagem/música/vídeo), cheque saldo: sapiens_meta action=credits (ou subscription). Saldo baixo, avise o usuário antes.
|
|
189
|
-
- "sessionToken expirado" = refaça login: sapiens_meta action=login com o código de sapiensinteticos.com/conectar-claude.
|
|
190
|
-
- sapiens_meta action=formats devolve os schemas por formato; action=whoami diz tier (user/admin) + saldo.
|
|
191
|
-
|
|
192
|
-
FLUXOS QUE NÃO PODEM ERRAR:
|
|
193
|
-
|
|
194
|
-
Música (sapiens_musicator) é fluxo de 4 passos, EM ORDEM:
|
|
195
|
-
1. create exige title (≥3) + context (≥20 chars, o tema/ângulo) + direction (gênero/mood). Custo 0, devolve trackId.
|
|
196
|
-
2. lyrics passe trackId + context pra GRAVAR a letra na track (300 Sinapses). NUNCA chame lyrics sem title+context.
|
|
197
|
-
3. render passe o trackId pronto pra sintetizar o áudio (3000 Sinapses, assíncrono, 3/min).
|
|
198
|
-
4. get passe o trackId e fique polando o status até 'ready' (ou 'failed').
|
|
199
|
-
Pular pro lyrics/render sem create, ou sem os campos, sempre falha.
|
|
200
|
-
|
|
201
|
-
Vídeo (sapiens_video) action=create EXIGE 'model': sapiens-video-seedance | kling | wan | kling-motion | lite | fast | quality | omni. Sem model, falha de cara. O 'omni' (Gemini Omni)
|
|
202
|
-
|
|
203
|
-
Imagem (sapiens_image) action=generate: prompt + model + aspectRatio. Referência via referenceImageUrls (galeria/Acervo/personagens) e/ou sourceImageIds. templateSlug aplica um super-prompt travado da casa.
|
|
204
|
-
|
|
205
|
-
SEU STUDIO vs geração BASE (não confunda, é o ponto): o usuário tem UM "Meu Studio", único, que o servidor resolve pela SESSÃO. Você NUNCA passa id de studio: é sempre o studio dele. É a identidade configurada dele: marca + personagem-operador + por ferramenta os presets e a "vibe" (o estilo afinado).
|
|
206
|
-
- Criar SEGUINDO o studio (na cara dele): sapiens_image com useStudio=true. O servidor acha o studio e aplica marca + personagem + vibe + presets sozinho (o que você passar explícito vence). O retorno traz studioApplied=true. Use quando ele diz "no meu studio", "na minha marca", "do meu jeito", "como sempre".
|
|
207
|
-
- Geração AVULSA (Sapiens base, sem a identidade dele): sapiens_image SEM useStudio (studioApplied=false). Pra teste solto ou pedido fora da identidade. Não misture: ou é studio, ou é base.
|
|
208
|
-
- Antes de criar no studio, cheque com sapiens_studios action=mine (nível, marca, operador, ferramentas, a vibe da imagem). Se você pediu useStudio e voltar studioApplied=false, o user não tem studio montado: avise e aponte /dashboard/studio. Gerar no studio faz ele evoluir de nível.
|
|
209
|
-
- EMANCIPAÇÃO (Nível 3, o passo grande): quando o membro quer a casa PRÓPRIA dele (site/produto próprio, FORA do Sapiens), use sapiens_studios action=emancipar. Ele devolve o blueprint pra VOCÊ construir na infra DO MEMBRO (Vercel + Convex + domínio dele), começando pela Fundação e seguindo um módulo por vez (action=module module=<slug>). Confirme cada passo, nunca hospede no Sapiens, siga o gosto dele. É complexo: conduza com calma.
|
|
210
|
-
|
|
211
|
-
Tirinha / Comic (sapiens_pipeline format=tirinha + sapiens_image): fluxo de 2 FASES, decida o MODO antes de gerar pixel.
|
|
212
|
-
FASE 1 (roteiro): monte 3-6 painéis, cada um com a CENA visual e a FALA/legenda SEPARADAS. Salve em sapiens_pipeline create_production format=tirinha. O texto dos balões mora no payload (campos dialogue/caption), NUNCA dentro da imagem.
|
|
213
|
-
FASE 2 (imagem), escolha UM dos dois modos (pergunte ao user, ou decida pelo caso):
|
|
214
|
-
MODO A, tira inteira numa imagem só: UMA chamada sapiens_image com prompt em grade (descreva "Painel 1 (cima-esq): ...; Painel 2 (cima-dir): ...", peça grade NxM com calhas brancas finas, MESMO personagem/estilo/luz em todos os quadros). Mais barato, estilo mais travado, menos controle quadro a quadro.
|
|
215
|
-
MODO B, painel a painel (N imagens): UMA sapiens_image por painel, com character-lock passando o painel anterior + a ref da Helen em referenceImageUrls. Mais controle e consistência de enquadramento, custa N gerações.
|
|
216
|
-
REGRA DE OURO da tirinha: a imagem sai SEM texto (o estilo da casa é no-text e modelo de imagem erra letra). A fala vai SEPARADA como legenda: manda a imagem com a fala embaixo (ex no Telegram "Painel 1 · Helen: '...'"); os balões editáveis e a diagramação final ficam no comic-builder do dashboard (/experimentos/comic-builder). NÃO tente assar a fala dentro do prompt.
|
|
217
|
-
|
|
218
|
-
Mídia no Fórum (PADRÃO, faça sempre assim): a peça vai EMBEDADA num card estruturado, nunca como "vai ouvir/ver noutro lugar". Música publicada (sapiens_musicator action=publish) já cria a tese no Fórum com a faixa tocável, não escreva "tá no Acervo, ouça lá". Pra anexar mídia a uma tese sua: sapiens_forum action=post com mediaTrackId (faixa pronta sua → card de música) OU mediaUrl + mediaKind (video|image; arquivo da casa, ou link YouTube/Vimeo pra vídeo). NÃO cole a URL da mídia no corpo da tese, use o campo: o corpo é só texto.
|
|
219
|
-
|
|
220
|
-
Trilhas e Ritos de Fogo (sapiens_trilhas): 'list'/'get' pra navegar as trilhas; 'list_challenges' mostra os Ritos ativos + seu status; 'claim_mission' (missionId + proofText) envia a prova pra revisão do dono — o crédito em Sinapses sai na aprovação dele, não na hora. Não prometa Sinapse na hora do claim.
|
|
221
|
-
|
|
188
|
+
const SAPIENS_INSTRUCTIONS = `Você opera o Sapiens Sintéticos (sapiensinteticos.com) NA CONTA de um usuário logado. Cada tool age de verdade na conta dele e muitas COBRAM Sinapses (o crédito da casa). Aja como operador, não no chute.
|
|
189
|
+
|
|
190
|
+
REGRA DE OURO:
|
|
191
|
+
- PRIMEIRO CONTATO ou "o que você faz?"/"como começo?"/"o que dá pra fazer?": chame sapiens_meta action=start e MOSTRE o resultado na sua voz. Sem login, ele ensina a conectar; logado, traz saldo + primeiros poderes com exemplos. É a porta de entrada: não despeje a lista dos 27 tools, deixe o start guiar.
|
|
192
|
+
- LOGO APÓS UM LOGIN BEM-SUCEDIDO (action=login retornou ok): chame action=start na sequência e mostre a porta de entrada. O recém-chegado não sabe o que pedir; não o deixe na tela em branco, guie a primeira jogada sem ele precisar perguntar.
|
|
193
|
+
- Se um tool voltar erro de validação ("exige X", "falta Y"), LEIA o erro e refaça a chamada COM o que falta. NUNCA repita igual a chamada que falhou: 3 falhas seguidas no mesmo tool fazem o cliente marcar o servidor como "unreachable" por ~56s (disjuntor anti-loop). Aí parece que "o MCP caiu", quando foi só argumento faltando.
|
|
194
|
+
- Antes de gerar algo caro (imagem/música/vídeo), cheque saldo: sapiens_meta action=credits (ou subscription). Saldo baixo, avise o usuário antes.
|
|
195
|
+
- "sessionToken expirado" = refaça login: sapiens_meta action=login com o código de sapiensinteticos.com/conectar-claude.
|
|
196
|
+
- sapiens_meta action=formats devolve os schemas por formato; action=whoami diz tier (user/admin) + saldo.
|
|
197
|
+
|
|
198
|
+
FLUXOS QUE NÃO PODEM ERRAR:
|
|
199
|
+
|
|
200
|
+
Música (sapiens_musicator) é fluxo de 4 passos, EM ORDEM:
|
|
201
|
+
1. create exige title (≥3) + context (≥20 chars, o tema/ângulo) + direction (gênero/mood). Custo 0, devolve trackId.
|
|
202
|
+
2. lyrics passe trackId + context pra GRAVAR a letra na track (300 Sinapses). NUNCA chame lyrics sem title+context.
|
|
203
|
+
3. render passe o trackId pronto pra sintetizar o áudio (3000 Sinapses, assíncrono, 3/min).
|
|
204
|
+
4. get passe o trackId e fique polando o status até 'ready' (ou 'failed').
|
|
205
|
+
Pular pro lyrics/render sem create, ou sem os campos, sempre falha.
|
|
206
|
+
|
|
207
|
+
Vídeo (sapiens_video) action=create EXIGE 'model': sapiens-video-seedance | kling | wan | kling-motion | lite | fast | quality | omni. Sem model, falha de cara. O 'omni' (Gemini Omni) gera clipe de 10s 720p com áudio nativo a partir de TEXTO (não aceita imagem/vídeo do user, ignora duração/resolução) e EDITA os próprios vídeos: passe editOfImageId com o imageId de um vídeo Omni já gerado e o prompt vira instrução de edição sobre a MESMA cena (troca item/personagem, preserva câmera e ambiente; cada edição debita como geração nova). É o caminho pra variações com continuidade: gera a base uma vez, edita N vezes. Vídeo é o mais caro: confirme com o usuário antes. Vitrine dos demos (sem custo): sapiens_video action=demos lista seus demo films com slug; action=showcase (slug + showcase=true/false + showcaseTag + showcaseOrder) cura o mini-cinema da /conectar-claude. FILMES DA CASA (Estúdio de Vídeo, tela /experimentos/films): são OUTRA coisa, três kinds na tabela videoSpecs: demo (UI clonada + câmera), aula-tour (telas reais + narração) e essay (fita-ensaio abstrata: partícula/tinta vira símbolo, com a logo explodindo no fim; narração da casa OPCIONAL, sai em 16:9 ou 9:16 vertical, e o filme final é limpo, sem rótulos de produção). Eles NÃO são gerados por este MCP: o user monta o spec na tela e um agente local (Claude Code, skill /film) produz o mp4 no repo da casa. Se o user pedir 'fita-ensaio' ou 'demo film' aqui, aponte pra tela e pro agente local.
|
|
208
|
+
|
|
209
|
+
Imagem (sapiens_image) action=generate: prompt + model + aspectRatio. Referência via referenceImageUrls (galeria/Acervo/personagens) e/ou sourceImageIds. templateSlug aplica um super-prompt travado da casa.
|
|
210
|
+
|
|
211
|
+
SEU STUDIO vs geração BASE (não confunda, é o ponto): o usuário tem UM "Meu Studio", único, que o servidor resolve pela SESSÃO. Você NUNCA passa id de studio: é sempre o studio dele. É a identidade configurada dele: marca + personagem-operador + por ferramenta os presets e a "vibe" (o estilo afinado).
|
|
212
|
+
- Criar SEGUINDO o studio (na cara dele): sapiens_image com useStudio=true. O servidor acha o studio e aplica marca + personagem + vibe + presets sozinho (o que você passar explícito vence). O retorno traz studioApplied=true. Use quando ele diz "no meu studio", "na minha marca", "do meu jeito", "como sempre".
|
|
213
|
+
- Geração AVULSA (Sapiens base, sem a identidade dele): sapiens_image SEM useStudio (studioApplied=false). Pra teste solto ou pedido fora da identidade. Não misture: ou é studio, ou é base.
|
|
214
|
+
- Antes de criar no studio, cheque com sapiens_studios action=mine (nível, marca, operador, ferramentas, a vibe da imagem). Se você pediu useStudio e voltar studioApplied=false, o user não tem studio montado: avise e aponte /dashboard/studio. Gerar no studio faz ele evoluir de nível.
|
|
215
|
+
- EMANCIPAÇÃO (Nível 3, o passo grande): quando o membro quer a casa PRÓPRIA dele (site/produto próprio, FORA do Sapiens), use sapiens_studios action=emancipar. Ele devolve o blueprint pra VOCÊ construir na infra DO MEMBRO (Vercel + Convex + domínio dele), começando pela Fundação e seguindo um módulo por vez (action=module module=<slug>). Confirme cada passo, nunca hospede no Sapiens, siga o gosto dele. É complexo: conduza com calma.
|
|
216
|
+
|
|
217
|
+
Tirinha / Comic (sapiens_pipeline format=tirinha + sapiens_image): fluxo de 2 FASES, decida o MODO antes de gerar pixel.
|
|
218
|
+
FASE 1 (roteiro): monte 3-6 painéis, cada um com a CENA visual e a FALA/legenda SEPARADAS. Salve em sapiens_pipeline create_production format=tirinha. O texto dos balões mora no payload (campos dialogue/caption), NUNCA dentro da imagem.
|
|
219
|
+
FASE 2 (imagem), escolha UM dos dois modos (pergunte ao user, ou decida pelo caso):
|
|
220
|
+
MODO A, tira inteira numa imagem só: UMA chamada sapiens_image com prompt em grade (descreva "Painel 1 (cima-esq): ...; Painel 2 (cima-dir): ...", peça grade NxM com calhas brancas finas, MESMO personagem/estilo/luz em todos os quadros). Mais barato, estilo mais travado, menos controle quadro a quadro.
|
|
221
|
+
MODO B, painel a painel (N imagens): UMA sapiens_image por painel, com character-lock passando o painel anterior + a ref da Helen em referenceImageUrls. Mais controle e consistência de enquadramento, custa N gerações.
|
|
222
|
+
REGRA DE OURO da tirinha: a imagem sai SEM texto (o estilo da casa é no-text e modelo de imagem erra letra). A fala vai SEPARADA como legenda: manda a imagem com a fala embaixo (ex no Telegram "Painel 1 · Helen: '...'"); os balões editáveis e a diagramação final ficam no comic-builder do dashboard (/experimentos/comic-builder). NÃO tente assar a fala dentro do prompt.
|
|
223
|
+
|
|
224
|
+
Mídia no Fórum (PADRÃO, faça sempre assim): a peça vai EMBEDADA num card estruturado, nunca como "vai ouvir/ver noutro lugar". Música publicada (sapiens_musicator action=publish) já cria a tese no Fórum com a faixa tocável, não escreva "tá no Acervo, ouça lá". Pra anexar mídia a uma tese sua: sapiens_forum action=post com mediaTrackId (faixa pronta sua → card de música) OU mediaUrl + mediaKind (video|image; arquivo da casa, ou link YouTube/Vimeo pra vídeo). NÃO cole a URL da mídia no corpo da tese, use o campo: o corpo é só texto.
|
|
225
|
+
|
|
226
|
+
Trilhas e Ritos de Fogo (sapiens_trilhas): 'list'/'get' pra navegar as trilhas; 'list_challenges' mostra os Ritos ativos + seu status; 'claim_mission' (missionId + proofText) envia a prova pra revisão do dono — o crédito em Sinapses sai na aprovação dele, não na hora. Não prometa Sinapse na hora do claim.
|
|
227
|
+
|
|
222
228
|
Voz da casa: 1ª pessoa, direto, anti-corporate, sem travessão. Pra bom entendedor, meia palavra basta.`;
|
|
223
|
-
const server = new Server({ name: "mcp-sapiens", version: "1.26.
|
|
229
|
+
const server = new Server({ name: "mcp-sapiens", version: "1.26.4" }, { capabilities: { tools: {} }, instructions: SAPIENS_INSTRUCTIONS });
|
|
224
230
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
225
231
|
tools: Object.entries(TOOLS).map(([name, t]) => ({
|
|
226
232
|
name,
|
|
@@ -253,4 +259,4 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
253
259
|
});
|
|
254
260
|
const transport = new StdioServerTransport();
|
|
255
261
|
await server.connect(transport);
|
|
256
|
-
console.error("mcp-sapiens v1.26.
|
|
262
|
+
console.error("mcp-sapiens v1.26.4 rodando via stdio (27 tools)");
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexAction, convexMutation, convexQuery, getSessionToken } from "../convexClient.js";
|
|
3
|
+
/**
|
|
4
|
+
* sapiens_instagram — o "ManyChat da casa" via MCP. ADMIN-ONLY (requireMcpAdmin
|
|
5
|
+
* no Convex): opera o auto-DM do Instagram da casa (regras de resposta
|
|
6
|
+
* automática, inbox das conversas, resposta manual pela janela de 24h).
|
|
7
|
+
* Espelha a UI /dashboard/admin/instagram; backend em convex/instagramDm.ts.
|
|
8
|
+
*
|
|
9
|
+
* Sub-actions:
|
|
10
|
+
* - rules: lista as regras (keyword, variações, escopo por post, disparos)
|
|
11
|
+
* - rule_upsert: cria/edita regra (ruleId presente = edita)
|
|
12
|
+
* - rule_delete: apaga regra por ruleId
|
|
13
|
+
* - inbox: threads recentes com a janela de 24h de cada (canReply)
|
|
14
|
+
* - thread: mensagens de uma conversa (igUserId do inbox)
|
|
15
|
+
* - send: responde uma conversa na mão (só com a janela aberta)
|
|
16
|
+
*/
|
|
17
|
+
export const instagramSchema = z.object({
|
|
18
|
+
action: z.enum(["rules", "rule_upsert", "rule_delete", "inbox", "thread", "send"]),
|
|
19
|
+
ruleId: z.string().optional().describe("Id da regra (rule_upsert pra editar, rule_delete)."),
|
|
20
|
+
keyword: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Keyword da regra (substring case-insensitive no texto da DM/comentário). Obrigatória em regra não-fallback."),
|
|
24
|
+
reply: z.string().optional().describe("Resposta na DM (obrigatória no rule_upsert)."),
|
|
25
|
+
replyVariants: z
|
|
26
|
+
.array(z.string())
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Variações da resposta; presentes, rodam em round-robin no lugar da reply."),
|
|
29
|
+
commentEcho: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Eco público no comentário depois da DM ('te respondi no direct!'). Só p/ comentário."),
|
|
33
|
+
echoVariants: z.array(z.string()).optional().describe("Variações do eco público (round-robin)."),
|
|
34
|
+
mediaId: z
|
|
35
|
+
.string()
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("Escopo por post: id de mídia do Instagram; a regra só casa comentário DESSE post."),
|
|
38
|
+
isFallback: z
|
|
39
|
+
.boolean()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("Fallback: responde DM sem keyword (1x/24h por pessoa). Nunca dispara em comentário."),
|
|
42
|
+
active: z.boolean().optional().describe("Regra ativa (default true)."),
|
|
43
|
+
priority: z.number().optional().describe("Menor casa primeiro (default 100)."),
|
|
44
|
+
igUserId: z.string().optional().describe("IGSID da contraparte (vem do inbox). Pra thread e send."),
|
|
45
|
+
text: z.string().optional().describe("Texto da resposta manual (send)."),
|
|
46
|
+
limit: z.number().optional().describe("Máx de itens (inbox default 30, thread default 40)."),
|
|
47
|
+
});
|
|
48
|
+
function need(value, name) {
|
|
49
|
+
if (value === undefined || value === null) {
|
|
50
|
+
throw new Error(`Faltando arg "${name}" pra essa action.`);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
export async function instagram(args) {
|
|
55
|
+
const sessionToken = getSessionToken();
|
|
56
|
+
switch (args.action) {
|
|
57
|
+
case "rules":
|
|
58
|
+
return await convexQuery("instagramDm:mcpListRules", { sessionToken });
|
|
59
|
+
case "rule_upsert": {
|
|
60
|
+
const reply = need(args.reply, "reply");
|
|
61
|
+
return await convexMutation("instagramDm:mcpUpsertRule", {
|
|
62
|
+
sessionToken,
|
|
63
|
+
ruleId: args.ruleId,
|
|
64
|
+
keyword: args.keyword,
|
|
65
|
+
reply,
|
|
66
|
+
replyVariants: args.replyVariants,
|
|
67
|
+
commentEcho: args.commentEcho,
|
|
68
|
+
echoVariants: args.echoVariants,
|
|
69
|
+
mediaId: args.mediaId,
|
|
70
|
+
isFallback: args.isFallback,
|
|
71
|
+
active: args.active,
|
|
72
|
+
priority: args.priority,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
case "rule_delete":
|
|
76
|
+
return await convexMutation("instagramDm:mcpRemoveRule", {
|
|
77
|
+
sessionToken,
|
|
78
|
+
ruleId: need(args.ruleId, "ruleId"),
|
|
79
|
+
});
|
|
80
|
+
case "inbox":
|
|
81
|
+
return await convexQuery("instagramDm:mcpListThreads", {
|
|
82
|
+
sessionToken,
|
|
83
|
+
limit: args.limit,
|
|
84
|
+
});
|
|
85
|
+
case "thread":
|
|
86
|
+
return await convexQuery("instagramDm:mcpThreadMessages", {
|
|
87
|
+
sessionToken,
|
|
88
|
+
igUserId: need(args.igUserId, "igUserId"),
|
|
89
|
+
limit: args.limit,
|
|
90
|
+
});
|
|
91
|
+
case "send":
|
|
92
|
+
return await convexAction("instagramDm:mcpSendDm", {
|
|
93
|
+
sessionToken,
|
|
94
|
+
igUserId: need(args.igUserId, "igUserId"),
|
|
95
|
+
text: need(args.text, "text"),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
package/dist/tools/video.js
CHANGED
|
@@ -24,7 +24,9 @@ import { convexAction, convexQuery, convexMutation, getSessionToken } from "../c
|
|
|
24
24
|
* cortes, blocking) como cena nova; personagem via role 'start'
|
|
25
25
|
* - sapiens-video-lite/fast/quality Veo 3.1 (2000/5000/25000 sinapses)
|
|
26
26
|
* - sapiens-video-omni Gemini Omni — texto -> vídeo 10s 720p com áudio nativo embutido.
|
|
27
|
-
*
|
|
27
|
+
* t2v + EDIÇÃO conversacional: `editOfImageId` aponta um vídeo Omni
|
|
28
|
+
* seu e o prompt edita a MESMA cena (troca item/personagem preservando
|
|
29
|
+
* o resto). Não aceita mídia do user (ignora references/durationSec/resolution).
|
|
28
30
|
*
|
|
29
31
|
* Custo: server-side por config (duração x resolução [x áudio]). i2v/motion usam
|
|
30
32
|
* `references` em base64 (role 'start' = imagem inicial, 'end' = frame final,
|
|
@@ -71,7 +73,7 @@ export const videoSchema = z.object({
|
|
|
71
73
|
"'sapiens-video-kling-motion' (motion transfer, precisa pessoa na imagem E no vídeo de movimento), " +
|
|
72
74
|
"'sapiens-video-shot-mimic' (recria o plano do vídeo de referência com seu personagem: mesma câmera, mesmos cortes; 'driving' = previs/clipe do plano, 'start' = personagem), " +
|
|
73
75
|
"'sapiens-video-lite/fast/quality' (Veo 3.1), " +
|
|
74
|
-
"'sapiens-video-omni' (Gemini Omni: texto -> vídeo 10s 720p com áudio nativo;
|
|
76
|
+
"'sapiens-video-omni' (Gemini Omni: texto -> vídeo 10s 720p com áudio nativo; t2v + EDIÇÃO conversacional via editOfImageId; não aceita imagem/vídeo do user, ignora duração/resolução)."),
|
|
75
77
|
durationSec: z
|
|
76
78
|
.number()
|
|
77
79
|
.optional()
|
|
@@ -85,6 +87,14 @@ export const videoSchema = z.object({
|
|
|
85
87
|
.boolean()
|
|
86
88
|
.optional()
|
|
87
89
|
.describe("action=create: liga áudio. Seedance = on por default; Kling 'sound' = +50%. WAN é áudio nativo sempre."),
|
|
90
|
+
editOfImageId: z
|
|
91
|
+
.string()
|
|
92
|
+
.optional()
|
|
93
|
+
.describe("action=create model=sapiens-video-omni: EDIÇÃO conversacional ('Nano Banana de vídeo'). " +
|
|
94
|
+
"Passe o imageId de um vídeo Omni SEU já gerado e o prompt vira instrução de edição sobre a MESMA cena " +
|
|
95
|
+
"(ex: 'troca o urso polar por um Papai Noel com um presente'), preservando câmera, ambiente e timing. " +
|
|
96
|
+
"Cada edição debita como uma geração Omni nova e devolve um vídeo novo (que também pode ser editado). " +
|
|
97
|
+
"Só funciona em vídeo gerado pelo Omni (não edita vídeo seu/upload)."),
|
|
88
98
|
// --- action=generate (legado) ---
|
|
89
99
|
imageId: z
|
|
90
100
|
.string()
|
|
@@ -168,6 +178,7 @@ export async function video(args) {
|
|
|
168
178
|
startImageUrl: args.startImageUrl,
|
|
169
179
|
endImageId: args.endImageId,
|
|
170
180
|
endImageUrl: args.endImageUrl,
|
|
181
|
+
editOfImageId: args.editOfImageId,
|
|
171
182
|
});
|
|
172
183
|
}
|
|
173
184
|
if (args.action === "generate") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.4",
|
|
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": {
|