sapiens-mcp 1.62.0 → 1.62.2

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 CHANGED
@@ -75,7 +75,7 @@ export const TOOLS = {
75
75
  handler: repertorio,
76
76
  },
77
77
  sapiens_gallery: {
78
- description: "Browse, publicação e upload das imagens do user. 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; publicado NÃO despublica, não existe unpublish), upload (traz pra galeria uma peça gerada FORA da casa, por sourceUrl https, filePath local ou base64; ADMIN por ora), ingest (peça que a CASA dirigiu e um motor externo só renderizou: entra NATIVA na timeline, publica e vai pra comunidade, com custo 0 em Sinapses e o custo real guardado em externalCost; carrega o prompt inteiro, as referências da casa (referenceImageIds) e o personagem (characterId), e é idempotente por sourceUrl, então re-ingerir corrige a ficha em vez de duplicar; ADMIN), refs (acopla peças da casa como REFERÊNCIA numa peça que já existe, de upload ou de ingest; ADMIN, e só na própria peça). 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. IMPORTANTE sobre upload: a peça entra PRIVADA e continua privada — o servidor recusa publicar e recusa compartilhar na comunidade, porque ela é do usuário e a responsabilidade é dele. O caminho pra ela virar coisa pública é usar como referência numa geração daqui e publicar o resultado. O refs escreve só proveniência (de que ficha/folha a peça nasceu): não promove nada, e um upload continua sem publicar depois de ganhar referência.",
78
+ description: "Browse, publicação e upload das imagens do user. 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; publicado NÃO despublica, não existe unpublish), upload (traz pra galeria uma peça gerada FORA da casa, por sourceUrl https, filePath local ou base64; ADMIN por ora), ingest (peça que a CASA dirigiu e um motor externo só renderizou: entra NATIVA na timeline, publica e vai pra comunidade, com custo 0 em Sinapses e o custo real guardado em externalCost; carrega o prompt inteiro, as referências da casa (referenceImageIds) e o personagem (characterId), e é idempotente por sourceUrl, então re-ingerir corrige a ficha em vez de duplicar; ADMIN), refs (acopla peças da casa como REFERÊNCIA numa peça que já existe, de upload ou de ingest; ADMIN, e só na própria peça), cast (QUEM ESTÁ EM CENA numa peça que já existe, quando é mais de uma criatura: characterIds em ordem, o protagonista primeiro, e a peça passa a contar na ficha de todos eles em vez de sumir da segunda; qualquer membro, na própria peça). 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. IMPORTANTE sobre upload: a peça entra PRIVADA e continua privada — o servidor recusa publicar e recusa compartilhar na comunidade, porque ela é do usuário e a responsabilidade é dele. O caminho pra ela virar coisa pública é usar como referência numa geração daqui e publicar o resultado. O refs escreve só proveniência (de que ficha/folha a peça nasceu): não promove nada, e um upload continua sem publicar depois de ganhar referência.",
79
79
  schema: gallerySchema,
80
80
  handler: gallery,
81
81
  },
@@ -145,7 +145,7 @@ export const TOOLS = {
145
145
  handler: brand,
146
146
  },
147
147
  sapiens_character: {
148
- 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 form/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/lema em inglês/nome/forma do próprio), set_presence (escreve onde o personagem existe FORA da casa: redes sociais por handle, Fanvue, site e o email que responde por ele), activate (tira do rascunho e libera o personagem pra USAR nas gerações do dono; exige ≥1 imagem. NÃO torna público: quem publica é set_visibility, e ativar é gesto reversível e privado), set_visibility (isPublic true=Explorar+slug / false=privado). GESTÃO de imagem (por url, pegue as urls atuais em action=get campo imageUrls): remove_image (tira uma), set_main_image (define a principal), reorder_images (nova ordem via orderedUrls, posição 0=principal), e delete (apaga o personagem, permanente). FORMA (`form`, o que tipo de CORPO ele tem: human default, humanoid, animal (bicho real), creature (ser inventado), object, abstract): não é enfeite de cadastro, é o que a ficha, as figurinhas e o vídeo leem pra decidir se descrevem rosto e mãos ou silhueta e postura, e é ele que impede uma criatura de voltar desenhada como pessoa. Mande no create sempre que o personagem não for gente; personagem que já existe sem ele conserta com set_card form=creature. Ausente = human, que é o que a casa desenhava antes do campo existir. TRAÇO (`style`, em que TÉCNICA ele é feito: auto default, realista, anime, manhwa, 3d, custom): irmão da forma, e a divisão é limpa, a forma diz que CORPO é esse e o traço diz como ele é DESENHADO. As mesmas três peças leem daqui. No 'auto' a peça não afirma técnica nenhuma e as imagens de referência mandam; 'realista' é fotografia, 'anime' é cel shading com contorno de tinta, 'manhwa' é pintura de webtoon, '3d' é render com material e oclusão, 'custom' usa a linha escrita em `styleNote` (até 140 caracteres, ex: aquarela sobre papel texturizado). Mande sempre que o personagem tiver técnica definida: até ago/2026 a ficha cravava vocabulário de desenho e devolvia personagem fotográfico virado em ilustração. Conserto sem custo em quem já existe: set_card style=realista. PRESENÇA (set_presence, de graça): o ENDEREÇO do personagem, o que faltava pra ele existir fora da ficha. `socials` é {rede: handle} nas redes instagram, tiktok, youtube, x, threads, bluesky, twitch, spotify, fanvue, patreon, onlyfans, telegram; `websiteUrl` é o site dele e `email` é o email que responde POR ELE (não o do dono). É MERGE: mandar {fanvue:'helen'} não apaga o instagram, e pra apagar uma rede se manda ela vazia. O que volta em action=get são as duas formas, `presence` (o handle cru, que é o que se reedita) e `presenceLinks` (o link já montado, pra mostrar sem remontar URL na mão). Vale a pena preencher quando o personagem TEM conta de verdade: é o que separa uma ficha de um ser com endereço, e a página pública dele desenha isso. FICHA (generate_sheet, COBRA 450 Sinapses): desenha a página-pôster do personagem no traço das imagens que ele já tem (exige pelo menos uma), em duas orientações (arg `orientation`): 'portrait' (default) é a página de processo, pose, expressões, trocas de roupa e adereços soltos na folha; 'landscape' é a prancha larga, com a volta completa à esquerda, a figura grande no meio, poses à direita, estudos de silhueta, expressão e detalhe embaixo e um painel CHARACTER ID na ponta. A personalidade sai da alma (systemPrompt) e é ela que escolhe roupa e objeto, então personagem com alma escrita rende ficha melhor. Cada geração é um estilo NOVO e elas acumulam no personagem (campo sheetUrls em action=get), nenhuma apaga a anterior, e a ficha já entra na galeria dele como referência das próximas gerações. É geração síncrona: se voltar Timeout, cheque action=get antes de repetir, senão cobra duas vezes. STICKERS (generate_stickers, COBRA 550 Sinapses): desenha 5 stickers do personagem DE UMA VEZ. Uma folha só, em 2K, com as cinco figuras separadas sobre um fundo verde chroma, recortada por código em peças 512x512 transparentes abaixo de 100KB (o teto do WhatsApp). É por isso que sai o preço de UMA imagem em 2K e não de cinco: quem paga é a folha. As peças entram no pack do personagem (um por personagem, os lotes acumulam) e já ficam no picker de expressão do dono, no chat e no Fórum. Arg `moods`: até 5 humores do vocabulário comum por slug (kkkkk, amei, isso, hmm, chega, que, aff, bora, socorro, seinao, valeu, ainao, seila, ideia, calma, contatudo, perfeito, euavisei, naovourir, zzz, somaisum, sextou, merecido, quedia, tudobem); faltando, a casa completa com os mais usados. Arg `hint`: direcionamento curto do autor (roupa, adereço, clima), até 140 caracteres. Arg `stickerTier`: 'folha' (default) é esse lote de cinco, desenhado no Gemini 3.1 Flash; 'unica' (COBRA 900 Sinapses) desenha UM sticker por vez no Gemini 3 Pro, o motor mais fiel da casa, com a figura sozinha no quadro e o dobro de pixel por peça, e leva só o PRIMEIRO mood da lista. Pra encher o pack, folha; pra traço difícil ou a reação que vira a cara do personagem, a unica. Ao oferecer a escolha, diga o NOME DO MOTOR e o que ele troca: adjetivo vago de acabamento não informa nada a quem vai pagar. Os dois caem no MESMO pack e acumulam. Sem legenda queimada na imagem, de propósito: modelo erra acento em português, então o rótulo fica na row e serve de busca no picker. Exige pelo menos uma imagem no personagem (é dela que sai a cara) e é geração síncrona: se voltar Timeout, cheque sapiens_gallery antes de repetir. Quando a resposta vem com ok=false, a folha foi gerada e paga mas o corte falhou; ela está na galeria e o recorte de novo é de graça, pela web. Publicar o pack na vitrine e o carimbo da casa (que é o que põe no picker de todo mundo) são gestos da web, não desta tool. CHARACTER VIDEO (a ficha que anda): o personagem atravessa 6 mundos em 12s, trocando de roupa em cada um, com som gerado junto, e o último plano fecha a peça com ele parando e encarando a câmera. A peça volta FECHADA pelas duas portas (tela e agente), sem ninguém pedir: o personagem se apresenta no cartão de nome por cima do fim do último plano, com o LEMA em inglês embaixo (o campo `titleEn`, escrito uma vez em set_card), e só depois a casa assina. Quem não tem lema recebe o subtítulo que o roteiro inventou naquele take, e ele muda no take seguinte. O fecho é asset, não geração: zero Sinapse a mais, e é fail-open, então a resposta traz `closed` e `nameCard` dizendo o que entrou de verdade em vez de prometer um cartão que não está no arquivo. Pra colocar esse cartão num vídeo que JÁ existe, o caminho é a ficha do take na web (gaveta do fecho, 'Apresentação do personagem'), também sem custo. Exige FICHA gerada (é dela que saem a cara e o guarda-roupa), não só imagem. Duas actions, nesta ordem: plan_video (COBRA 50 Sinapses) devolve os 6 planos que a alma do personagem escolheu, com ambiente, ato, enquadramento e roupa. Cada plano vem nas duas línguas: em inglês (setting/act/wardrobe, que é o que vai pro motor) e em português (settingPt/actPt/wardrobePt). MOSTRE a versão em português pro autor, o público da casa é brasileiro e roteiro que ele lê de través não é roteiro aprovado; peça de novo quantas vezes ele quiser, porque trocar sai por 50 e o take errado sai por milhares. replan_shot (COBRA 15 Sinapses) reescreve UM plano e não toca nos outros cinco: os seis são cenas independentes, então quando o autor gosta de quatro e implica com um, troque só aquele em vez de sortear tudo de novo (mande os 6 planos em `shots`, o número em `shotIndex`, e o que ele quer diferente em `shotHint`; volta só o plano trocado, e é você que remonta o roteiro). Depois generate_video (COBRA) renderiza, com os planos aprovados no arg `shots` e o MOTOR no arg `videoTier`: 'draft' (5.400 Sinapses) é o Seedance 2.0 Mini, metade do preço, que tropeça em mão, pouca luz e câmera rápida, e 'final' (8.640 Sinapses) é o Seedance 2.0 Fast, que segura o que o Mini erra. A peça é a MESMA nos dois (mesmos 6 planos, 12s, 720p, com som), então ofereça pelo nome do motor e pelo que ele troca, nunca por adjetivo vago de acabamento. Vertical ou horizontal pelo arg `orientation`. Chamar generate_video SEM `shots` funciona, mas escreve um roteiro novo às cegas e cobra igual: não faça isso sem o autor ter visto o que vai receber. É geração síncrona e demorada: se voltar Timeout, cheque sapiens_gallery antes de repetir. Fluxo de criação: create → add_image (1+) → set_card (opcional) → activate. PARE AÍ. O personagem nasce e continua PRIVADO, e é assim que ele serve pro dono: dá pra gerar, referenciar e iterar sem ninguém ver. set_visibility isPublic=true é o gesto de PUBLICAR no Explorar, com slug público, e nÃO é passo de fluxo: só chame quando o dono pedir pra publicar aquele personagem, com essas palavras. Na dúvida, não publique e pergunte. Pra usar um personagem público como referência numa geração, pegue mainImageUrl em list_public/get e passe em sapiens_image referenceImageUrls.",
148
+ 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 form/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/lema em inglês/nome/nome por extenso/forma do próprio), set_presence (escreve onde o personagem existe FORA da casa: redes sociais por handle, Fanvue, site e o email dele, este último privado), activate (tira do rascunho e libera o personagem pra USAR nas gerações do dono; exige ≥1 imagem. NÃO torna público: quem publica é set_visibility, e ativar é gesto reversível e privado), set_visibility (isPublic true=Explorar+slug / false=privado). GESTÃO de imagem (por url, pegue as urls atuais em action=get campo imageUrls): remove_image (tira uma), set_main_image (define a principal), reorder_images (nova ordem via orderedUrls, posição 0=principal), e delete (apaga o personagem, permanente). FORMA (`form`, o que tipo de CORPO ele tem: human default, humanoid, animal (bicho real), creature (ser inventado), object, abstract): não é enfeite de cadastro, é o que a ficha, as figurinhas e o vídeo leem pra decidir se descrevem rosto e mãos ou silhueta e postura, e é ele que impede uma criatura de voltar desenhada como pessoa. Mande no create sempre que o personagem não for gente; personagem que já existe sem ele conserta com set_card form=creature. Ausente = human, que é o que a casa desenhava antes do campo existir. NOME E NOME POR EXTENSO (`name` e `fullName`): `name` é como o personagem é CHAMADO e é o que toda tela desenha; `fullName` é o nome inteiro, pra quem tem apelido ('Crow Girl' na tela, 'Kaia Crowe' por extenso). Um não substitui o outro, e o extenso não mexe no slug da página nem no cartão de nome do vídeo: batizar personagem que já existe não muda endereço publicado nem assinatura de peça que já saiu. Vem em action=get e list_mine no campo `fullName` (null = ainda sem nome por extenso). TRAÇO (`style`, em que TÉCNICA ele é feito: auto default, realista, anime, manhwa, 3d, custom): irmão da forma, e a divisão é limpa, a forma diz que CORPO é esse e o traço diz como ele é DESENHADO. As mesmas três peças leem daqui. No 'auto' a peça não afirma técnica nenhuma e as imagens de referência mandam; 'realista' é fotografia, 'anime' é cel shading com contorno de tinta, 'manhwa' é pintura de webtoon, '3d' é render com material e oclusão, 'custom' usa a linha escrita em `styleNote` (até 140 caracteres, ex: aquarela sobre papel texturizado). Mande sempre que o personagem tiver técnica definida: até ago/2026 a ficha cravava vocabulário de desenho e devolvia personagem fotográfico virado em ilustração. Conserto sem custo em quem já existe: set_card style=realista. PRESENÇA (set_presence, de graça): o ENDEREÇO do personagem, o que faltava pra ele existir fora da ficha. `socials` é {rede: handle} nas redes instagram, tiktok, youtube, x, threads, bluesky, twitch, spotify, fanvue, patreon, onlyfans, telegram; `websiteUrl` é o site dele e `email` é o email do personagem, o que cadastra e recupera as contas dele nas redes. As redes e o site são PÚBLICOS; o email é PRIVADO e fica só com o dono, mesmo com o personagem publicado, porque email é chave de conta e isca de spam, não canal de contato. Em action=get e list_public de personagem de OUTRA pessoa, o campo simplesmente não vem. É MERGE: mandar {fanvue:'helen'} não apaga o instagram, e pra apagar uma rede se manda ela vazia. O que volta em action=get são as duas formas, `presence` (o handle cru, que é o que se reedita) e `presenceLinks` (o link já montado, pra mostrar sem remontar URL na mão). Vale a pena preencher quando o personagem TEM conta de verdade: é o que separa uma ficha de um ser com endereço, e a página pública dele desenha as redes e o site (nunca o email). FICHA (generate_sheet, COBRA 450 Sinapses): desenha a página-pôster do personagem no traço das imagens que ele já tem (exige pelo menos uma), em duas orientações (arg `orientation`): 'portrait' (default) é a página de processo, pose, expressões, trocas de roupa e adereços soltos na folha; 'landscape' é a prancha larga, com a volta completa à esquerda, a figura grande no meio, poses à direita, estudos de silhueta, expressão e detalhe embaixo e um painel CHARACTER ID na ponta. A personalidade sai da alma (systemPrompt) e é ela que escolhe roupa e objeto, então personagem com alma escrita rende ficha melhor. Cada geração é um estilo NOVO e elas acumulam no personagem (campo sheetUrls em action=get), nenhuma apaga a anterior, e a ficha já entra na galeria dele como referência das próximas gerações. É geração síncrona: se voltar Timeout, cheque action=get antes de repetir, senão cobra duas vezes. STICKERS (generate_stickers, COBRA 550 Sinapses): desenha 5 stickers do personagem DE UMA VEZ. Uma folha só, em 2K, com as cinco figuras separadas sobre um fundo verde chroma, recortada por código em peças 512x512 transparentes abaixo de 100KB (o teto do WhatsApp). É por isso que sai o preço de UMA imagem em 2K e não de cinco: quem paga é a folha. As peças entram no pack do personagem (um por personagem, os lotes acumulam) e já ficam no picker de expressão do dono, no chat e no Fórum. Arg `moods`: até 5 humores do vocabulário comum por slug (kkkkk, amei, isso, hmm, chega, que, aff, bora, socorro, seinao, valeu, ainao, seila, ideia, calma, contatudo, perfeito, euavisei, naovourir, zzz, somaisum, sextou, merecido, quedia, tudobem); faltando, a casa completa com os mais usados. Arg `hint`: direcionamento curto do autor (roupa, adereço, clima), até 140 caracteres. Arg `stickerTier`: 'folha' (default) é esse lote de cinco, desenhado no Gemini 3.1 Flash; 'unica' (COBRA 900 Sinapses) desenha UM sticker por vez no Gemini 3 Pro, o motor mais fiel da casa, com a figura sozinha no quadro e o dobro de pixel por peça, e leva só o PRIMEIRO mood da lista. Pra encher o pack, folha; pra traço difícil ou a reação que vira a cara do personagem, a unica. Ao oferecer a escolha, diga o NOME DO MOTOR e o que ele troca: adjetivo vago de acabamento não informa nada a quem vai pagar. Os dois caem no MESMO pack e acumulam. Sem legenda queimada na imagem, de propósito: modelo erra acento em português, então o rótulo fica na row e serve de busca no picker. Exige pelo menos uma imagem no personagem (é dela que sai a cara) e é geração síncrona: se voltar Timeout, cheque sapiens_gallery antes de repetir. Quando a resposta vem com ok=false, a folha foi gerada e paga mas o corte falhou; ela está na galeria e o recorte de novo é de graça, pela web. Publicar o pack na vitrine e o carimbo da casa (que é o que põe no picker de todo mundo) são gestos da web, não desta tool. CHARACTER VIDEO (a ficha que anda): o personagem atravessa 6 mundos em 12s, trocando de roupa em cada um, com som gerado junto, e o último plano fecha a peça com ele parando e encarando a câmera. A peça volta FECHADA pelas duas portas (tela e agente), sem ninguém pedir: o personagem se apresenta no cartão de nome por cima do fim do último plano, com o LEMA em inglês embaixo (o campo `titleEn`, escrito uma vez em set_card), e só depois a casa assina. Quem não tem lema recebe o subtítulo que o roteiro inventou naquele take, e ele muda no take seguinte. O fecho é asset, não geração: zero Sinapse a mais, e é fail-open, então a resposta traz `closed` e `nameCard` dizendo o que entrou de verdade em vez de prometer um cartão que não está no arquivo. Pra colocar esse cartão num vídeo que JÁ existe, o caminho é a ficha do take na web (gaveta do fecho, 'Apresentação do personagem'), também sem custo. Exige FICHA gerada (é dela que saem a cara e o guarda-roupa), não só imagem. Duas actions, nesta ordem: plan_video (COBRA 50 Sinapses) devolve os 6 planos que a alma do personagem escolheu, com ambiente, ato, enquadramento e roupa. Cada plano vem nas duas línguas: em inglês (setting/act/wardrobe, que é o que vai pro motor) e em português (settingPt/actPt/wardrobePt). MOSTRE a versão em português pro autor, o público da casa é brasileiro e roteiro que ele lê de través não é roteiro aprovado; peça de novo quantas vezes ele quiser, porque trocar sai por 50 e o take errado sai por milhares. replan_shot (COBRA 15 Sinapses) reescreve UM plano e não toca nos outros cinco: os seis são cenas independentes, então quando o autor gosta de quatro e implica com um, troque só aquele em vez de sortear tudo de novo (mande os 6 planos em `shots`, o número em `shotIndex`, e o que ele quer diferente em `shotHint`; volta só o plano trocado, e é você que remonta o roteiro). Depois generate_video (COBRA) renderiza, com os planos aprovados no arg `shots` e o MOTOR no arg `videoTier`: 'draft' (5.400 Sinapses) é o Seedance 2.0 Mini, metade do preço, que tropeça em mão, pouca luz e câmera rápida, e 'final' (8.640 Sinapses) é o Seedance 2.0 Fast, que segura o que o Mini erra. A peça é a MESMA nos dois (mesmos 6 planos, 12s, 720p, com som), então ofereça pelo nome do motor e pelo que ele troca, nunca por adjetivo vago de acabamento. Vertical ou horizontal pelo arg `orientation`. Chamar generate_video SEM `shots` funciona, mas escreve um roteiro novo às cegas e cobra igual: não faça isso sem o autor ter visto o que vai receber. É geração síncrona e demorada: se voltar Timeout, cheque sapiens_gallery antes de repetir. Fluxo de criação: create → add_image (1+) → set_card (opcional) → activate. PARE AÍ. O personagem nasce e continua PRIVADO, e é assim que ele serve pro dono: dá pra gerar, referenciar e iterar sem ninguém ver. set_visibility isPublic=true é o gesto de PUBLICAR no Explorar, com slug público, e nÃO é passo de fluxo: só chame quando o dono pedir pra publicar aquele personagem, com essas palavras. Na dúvida, não publique e pergunte. Pra usar um personagem público como referência numa geração, pegue mainImageUrl em list_public/get e passe em sapiens_image referenceImageUrls.",
149
149
  schema: characterSchema,
150
150
  handler: character,
151
151
  },
@@ -20,7 +20,8 @@ import { convexQuery, convexMutation, convexAction, getSessionToken } from "../c
20
20
  * técnica definida (ver abaixo).
21
21
  * - add_image: adiciona imagem ao próprio personagem (imageUrl direto ou
22
22
  * sourceImageId da galeria). 1ª imagem vira a principal.
23
- * - set_card: edita a alma (systemPrompt), título, nome, `form` e/ou `style`.
23
+ * - set_card: edita a alma (systemPrompt), título, nome, nome por extenso,
24
+ * `form` e/ou `style`.
24
25
  * - set_presence: escreve onde ele existe FORA da casa (redes, Fanvue, site,
25
26
  * email). Merge: mandar uma rede não apaga as outras.
26
27
  * - activate: publica (sai de draft). Exige ≥1 imagem.
@@ -116,7 +117,16 @@ export const characterSchema = z.object({
116
117
  name: z
117
118
  .string()
118
119
  .optional()
119
- .describe("Pra create (obrigatório) ou set_card (renomear): nome do personagem."),
120
+ .describe("Pra create (obrigatório) ou set_card (renomear): nome do personagem. É o APELIDO, o nome pelo qual ele é conhecido, e é o que TODA tela desenha."),
121
+ fullName: z
122
+ .string()
123
+ .optional()
124
+ .describe("Pra create/set_card: o nome do personagem POR EXTENSO, quando o `name` " +
125
+ "é um apelido ('Crow Girl' é como ela é chamada, 'Kaia Crowe' é quem ela " +
126
+ "é). Os dois convivem: este NÃO substitui o name, não muda o slug da " +
127
+ "página nem o cartão de nome do vídeo, e aparece como a linha logo " +
128
+ "abaixo do nome na página do personagem. String vazia apaga. Até 80 " +
129
+ "caracteres. Ausente = personagem que se chama de um jeito só."),
120
130
  gender: z
121
131
  .string()
122
132
  .optional()
@@ -185,8 +195,10 @@ export const characterSchema = z.object({
185
195
  email: z
186
196
  .string()
187
197
  .optional()
188
- .describe("Pra set_presence: o email que responde POR ELE (não o do dono). Vira um " +
189
- "mailto na ficha e na página pública. String vazia apaga."),
198
+ .describe("Pra set_presence: o email do personagem, o que cadastra e recupera as " +
199
+ "contas dele nas redes. É PRIVADO: aparece na ficha, pro dono, e NÃO " +
200
+ "vai pra página pública nem quando o personagem é publicado (email " +
201
+ "exposto é chave de conta e isca de spam). String vazia apaga."),
190
202
  websiteUrl: z
191
203
  .string()
192
204
  .optional()
@@ -289,6 +301,7 @@ export async function character(args) {
289
301
  return await convexMutation("influencers:mcpCreateCharacter", {
290
302
  sessionToken,
291
303
  name: args.name,
304
+ fullName: args.fullName,
292
305
  gender: args.gender,
293
306
  form: args.form,
294
307
  style: args.style,
@@ -326,10 +339,11 @@ export async function character(args) {
326
339
  args.title === undefined &&
327
340
  args.titleEn === undefined &&
328
341
  args.name === undefined &&
342
+ args.fullName === undefined &&
329
343
  args.form === undefined &&
330
344
  args.style === undefined &&
331
345
  args.styleNote === undefined) {
332
- throw new Error("action=set_card precisa de pelo menos um: systemPrompt, title, titleEn, name, form, style ou styleNote.");
346
+ throw new Error("action=set_card precisa de pelo menos um: systemPrompt, title, titleEn, name, fullName, form, style ou styleNote.");
333
347
  }
334
348
  const sessionToken = getSessionToken();
335
349
  return await convexMutation("influencers:mcpSetCharacterCard", {
@@ -339,6 +353,7 @@ export async function character(args) {
339
353
  title: args.title,
340
354
  titleEn: args.titleEn,
341
355
  name: args.name,
356
+ fullName: args.fullName,
342
357
  form: args.form,
343
358
  style: args.style,
344
359
  styleNote: args.styleNote,
@@ -34,6 +34,7 @@ export const gallerySchema = z.object({
34
34
  "upload",
35
35
  "ingest",
36
36
  "refs",
37
+ "cast",
37
38
  ]),
38
39
  limit: z
39
40
  .number()
@@ -49,7 +50,7 @@ export const gallerySchema = z.object({
49
50
  imageId: z
50
51
  .string()
51
52
  .optional()
52
- .describe("generatedImages:_id (obrigatório pra action=get/publish/refs)"),
53
+ .describe("generatedImages:_id (obrigatório pra action=get/publish/refs/cast)"),
53
54
  includeBase64: z
54
55
  .boolean()
55
56
  .optional()
@@ -108,6 +109,10 @@ export const gallerySchema = z.object({
108
109
  .string()
109
110
  .optional()
110
111
  .describe("action=ingest: o personagem de quem é a peça (influencers:_id, ache com sapiens_character action=list_mine). A peça nasce ligada à ficha, igual ao que sai dos motores da casa: conta no personagem e resolve a miniatura dele. PODE OMITIR quando as referenceImageIds já são peças da casa feitas com aquele personagem (folha de storyboard, ficha): o servidor deduz o personagem da primeira ref que tem um. O que você diz aqui manda sobre o que ele deduz. Re-ingerir a mesma sourceUrl com characterId AMARRA uma peça que já entrou sem personagem, sem trocar o id. Aceita personagem seu ou público."),
112
+ characterIds: z
113
+ .union([z.array(z.string()), z.string()])
114
+ .optional()
115
+ .describe("QUEM ESTÁ EM CENA, quando é mais de uma criatura (action=ingest e action=cast). Em ordem de cena: o PRIMEIRO é o protagonista (é ele que a ficha e o cartão do vídeo mostram) e o resto vira elenco, então a peça conta na ficha de TODOS eles em vez de sumir da segunda. Teto de 6. Use quando a fita foi dirigida com duas folhas de personagem: sem isto, ela aparece só na ficha de um. Aceita lista ou os ids separados por vírgula, personagem seu ou público. Pra peça de uma criatura só continue usando characterId."),
111
116
  replace: z
112
117
  .boolean()
113
118
  .optional()
@@ -225,6 +230,20 @@ function normalizeRefIds(raw) {
225
230
  .filter(Boolean)
226
231
  .slice(0, 8);
227
232
  }
233
+ /**
234
+ * O mesmo tratamento pro elenco, com o teto de lá: seis em cena. Mesma tolerância
235
+ * a cliente que serializa lista como texto (ver normalizeRefIds), porque o erro
236
+ * é o mesmo e a cura também.
237
+ */
238
+ function normalizeCastIds(raw) {
239
+ if (!raw)
240
+ return [];
241
+ const lista = Array.isArray(raw) ? raw : raw.split(",");
242
+ return lista
243
+ .map((id) => id.trim().replace(/^["'[]+|["'\]]+$/g, ""))
244
+ .filter(Boolean)
245
+ .slice(0, 6);
246
+ }
228
247
  export async function gallery(args) {
229
248
  const sessionToken = getSessionToken();
230
249
  if (args.action === "list") {
@@ -296,12 +315,38 @@ export async function gallery(args) {
296
315
  size: args.size,
297
316
  referenceImageIds: normalizeRefIds(args.referenceImageIds),
298
317
  characterId: args.characterId,
318
+ characterIds: normalizeCastIds(args.characterIds).length
319
+ ? normalizeCastIds(args.characterIds)
320
+ : undefined,
299
321
  });
300
322
  return {
301
323
  ...result,
302
324
  aviso: "Peça NATIVA: entra na timeline, publica e vai pra comunidade como qualquer geração da casa. Custo em Sinapses é 0 e ela NÃO leva assinatura C2PA, porque o motor rodou fora. Use ingest só quando a receita (folha, personagem, prompt) foi da casa; peça achada pronta é action=upload.",
303
325
  };
304
326
  }
327
+ // cast: quem está EM CENA numa peça que já existe.
328
+ //
329
+ // Porta separada do ingest pelo mesmo motivo do refs: o elenco quase sempre se
330
+ // descobre depois. A fita sai do motor, o autor assiste e só então diz quem
331
+ // apareceu. Pedir isso no disparo é pedir na hora em que ninguém sabe ainda.
332
+ if (args.action === "cast") {
333
+ if (!args.imageId) {
334
+ throw new Error("action=cast exige imageId: a peça que recebe o elenco. Use action=list pra achar.");
335
+ }
336
+ const influencerIds = normalizeCastIds(args.characterIds);
337
+ if (!influencerIds.length) {
338
+ throw new Error("action=cast exige characterIds: quem está em cena, em ordem, o protagonista primeiro. Ache os ids com sapiens_character action=list_mine.");
339
+ }
340
+ const result = await convexMutation("imageCast:mcpSetImageCast", {
341
+ sessionToken,
342
+ imageId: args.imageId,
343
+ influencerIds,
344
+ });
345
+ return {
346
+ ...result,
347
+ aviso: "A peça agora conta na ficha de cada um em cena. O primeiro da lista é o protagonista: é o nome que a ficha e o cartão do vídeo mostram.",
348
+ };
349
+ }
305
350
  // refs: acopla peças da casa a uma peça que JÁ existe (upload ou ingest).
306
351
  // A ingestão aceita refs no nascimento, mas quem sobe raramente tem os ids em
307
352
  // mãos na hora; e o upload não tinha lugar nenhum pra dizer de onde veio a
@@ -40,6 +40,7 @@ const MODELS = [
40
40
  // off). SEM referência: o endpoint krea-2/turbo/lora é text-to-image puro.
41
41
  "fal-krea2-realism", // Krea-2 + LoRA realismo (gokaygokay) · txt2img
42
42
  "fal-krea2-realism-v2", // Krea-2 + LoRA realismo alt (RudySen), pro A/B · txt2img
43
+ "fal-krea2-nsfw", // Krea-2 + realismo + LoRA NSFW (uzumix) · Ousadia regulável · txt2img
43
44
  ];
44
45
  export const imageSchema = z.object({
45
46
  action: z.enum(["generate", "request_generation", "compose", "models"]),
@@ -50,7 +51,7 @@ export const imageSchema = z.object({
50
51
  model: z
51
52
  .enum(MODELS)
52
53
  .optional()
53
- .describe("Default 'nano-banana-2' (Flash 3.1 com refs). 'nano-banana-max' (Pro 3) = qualidade alta. 'gpt-image-2-low/high' = Azure. 'seedream-4-5'/'seedream-5-0'/'seedream-5-0-pro' = ByteDance 2K nativo, cinematográfico, aceita até 4 referências (o 5.0 é a geração nova, entende prompt complexo melhor; o 5.0-pro é o topo da linha). 'grok-2-image'/'grok-2-image-quality' = xAI Grok Imagine da geração anterior (moderação frouxa +18, aceita refs e aspect; quality é mais fiel pra character lock); 'grok-imagine-2' = Grok Imagine Image 2.0, a geração nova de ago/2026, que é a melhor da linha integrando desenho e foto na mesma peça. DEGEN (uncensored, gate +18): 'wavespeed-chroma' (fotorrealista rápido), 'wavespeed-flux2' (Flux.2 Klein), 'wavespeed-flux-nsfw' (flux+LoRA NSFW, Ousadia regulável via loraIntensity), 'wavespeed-klein-anime' (Flux.2 Klein + LoRA anime, inteligente+controlável), 'wavespeed-klein-anime-plus' (Klein anime +18, Ousadia regulável) = WaveSpeed rápido; 'civitai-wai-illustrious'/'civitai-nova-anime-xl' (anime), 'civitai-pony-v6' (Pony V6 XL, base nº1) = Civitai sdcpp rápido. 'fal-krea2-realism'/'fal-krea2-realism-v2' (Krea-2 Turbo 12B + LoRA de realismo, fal.ai, ~4s, fotorrealismo forte) = SÓ txt2img (não aceita referência)."),
54
+ .describe("Default 'nano-banana-2' (Flash 3.1 com refs). 'nano-banana-max' (Pro 3) = qualidade alta. 'gpt-image-2-low/high' = Azure. 'seedream-4-5'/'seedream-5-0'/'seedream-5-0-pro' = ByteDance 2K nativo, cinematográfico, aceita até 4 referências (o 5.0 é a geração nova, entende prompt complexo melhor; o 5.0-pro é o topo da linha). 'grok-2-image'/'grok-2-image-quality' = xAI Grok Imagine da geração anterior (moderação frouxa +18, aceita refs e aspect; quality é mais fiel pra character lock); 'grok-imagine-2' = Grok Imagine Image 2.0, a geração nova de ago/2026, que é a melhor da linha integrando desenho e foto na mesma peça. DEGEN (uncensored, gate +18): 'wavespeed-chroma' (fotorrealista rápido), 'wavespeed-flux2' (Flux.2 Klein), 'wavespeed-flux-nsfw' (flux+LoRA NSFW, Ousadia regulável via loraIntensity), 'wavespeed-klein-anime' (Flux.2 Klein + LoRA anime, inteligente+controlável), 'wavespeed-klein-anime-plus' (Klein anime +18, Ousadia regulável) = WaveSpeed rápido; 'civitai-wai-illustrious'/'civitai-nova-anime-xl' (anime), 'civitai-pony-v6' (Pony V6 XL, base nº1) = Civitai sdcpp rápido. 'fal-krea2-realism'/'fal-krea2-realism-v2' (Krea-2 Turbo 12B + LoRA de realismo, fal.ai, ~4s, fotorrealismo forte) e 'fal-krea2-nsfw' (a mesma base com LoRA NSFW por cima, +18, Ousadia regulável via loraIntensity) = SÓ txt2img (não aceita referência)."),
54
55
  aspectRatio: z
55
56
  .enum(["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"])
56
57
  .optional()
@@ -91,7 +92,7 @@ export const imageSchema = z.object({
91
92
  loraIntensity: z
92
93
  .enum(["suave", "medio", "forte"])
93
94
  .optional()
94
- .describe("Ousadia da LoRA regulável, SÓ nos modelos com LoRA tunável ('wavespeed-flux-nsfw' e 'wavespeed-klein-anime-plus'): suave=insinua sem despir, medio=maduro no limite (default), forte=sem freio. Ideal pra remixar personagem (ex: a Helen) preservando a identidade e regulando a liberdade. Ignorado nos demais modelos."),
95
+ .describe("Ousadia da LoRA regulável, SÓ nos modelos com LoRA tunável ('wavespeed-flux-nsfw', 'wavespeed-klein-anime-plus' e 'fal-krea2-nsfw'): suave=insinua sem despir, medio=maduro no limite (default), forte=sem freio. Ideal pra remixar personagem (ex: a Helen) preservando a identidade e regulando a liberdade. Ignorado nos demais modelos."),
95
96
  mode: z
96
97
  .enum(["create", "edit", "variation"])
97
98
  .optional()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapiens-mcp",
3
- "version": "1.62.0",
3
+ "version": "1.62.2",
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",