sapiens-mcp 1.36.0 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/registry.js +3 -3
- package/dist/tools/character.js +63 -1
- package/dist/tools/profile.js +53 -0
- package/dist/tools/repertorio.js +4 -18
- package/package.json +1 -1
package/dist/registry.js
CHANGED
|
@@ -53,7 +53,7 @@ export const TOOLS = {
|
|
|
53
53
|
handler: meta,
|
|
54
54
|
},
|
|
55
55
|
sapiens_repertorio: {
|
|
56
|
-
description: "Acervo pessoal de filme/série/anime/jogo/livro/música (Repertório, o segundo cérebro do user). Reads: list (filtros mediaType/status), search (texto em title/genres/tags), get (detalhe),
|
|
56
|
+
description: "Acervo pessoal de filme/série/anime/jogo/livro/música (Repertório, o segundo cérebro do user). Reads: list (filtros mediaType/status), search (texto em title/genres/tags), get (detalhe), popArticles, resolve (busca capa/ano/id nos providers server-side: OMDb/IGDB-Twitch/AniList/Google Books/iTunes). Mutations (qualquer logado, mexem no PRÓPRIO acervo): add_item, update_item (status/rating/tags/note/isPublic), remove_item. CAPTURA ONE-SHOT travada na lista de providers: quando o user fala natural ('acabei de ver Duna 2, nota 9', 'tô jogando Hollow Knight', 'li tal livro'), (1) infira mediaType e status (assisti/zerei/li=completed, quero=backlog, tô jogando/vendo=active, dropei=dropped) e rating se citado; (2) chame action=resolve {mediaType, query}, escolha o candidato certo e faça add_item passando SÓ o source + externalId DELE + os campos pessoais (status/rating/tags/note). O servidor re-resolve no provider e grava título/capa/ano canônicos — você NÃO manda título/capa nem inventa externalId. (3) Se o resolve não achar (lista vazia/providerKeyMissing), NÃO dá pra adicionar: diga ao user que não encontrou nos providers (não fabrique entry manual). Upsert/dedup por (userId, source, externalId). Só pergunte se ambíguo entre candidatos. FERRAMENTAS DE IA (Repertório de Ferramentas): fluxo separado (vêm do catálogo aitag, não dos providers de mídia). action=search_tools {query} acha a ferramenta no catálogo e devolve o toolId; action=add_tool {toolId, favorite?, rating?, note?} grava como mediaType 'tool' (estar no acervo já é 'usei'; favorite=true liga a estrela). Use quando o user fala 'adiciona o Midjourney/Cursor no meu repertório de ferramentas' ou 'uso tal ferramenta de IA'. Cada ferramenta aponta pra página dela no aitag.",
|
|
57
57
|
schema: repertorioSchema,
|
|
58
58
|
handler: repertorio,
|
|
59
59
|
},
|
|
@@ -133,12 +133,12 @@ export const TOOLS = {
|
|
|
133
133
|
handler: brand,
|
|
134
134
|
},
|
|
135
135
|
sapiens_character: {
|
|
136
|
-
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.",
|
|
136
|
+
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). 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). 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.",
|
|
137
137
|
schema: characterSchema,
|
|
138
138
|
handler: character,
|
|
139
139
|
},
|
|
140
140
|
sapiens_profile: {
|
|
141
|
-
description: "O 'tudo junto' do perfil do user (/u/<username>),
|
|
141
|
+
description: "O 'tudo junto' do perfil do user (/u/<username>), user-tier. Agrega o que mora no perfil mas estava fora do MCP: identidade + nível/XP + saldo, badges (conquistas) e golden tools (favoritos do aitag). Sub-actions de LEITURA: get (card completo: identidade + nível + saldo + badges + golden tools), badges (só as conquistas, lista cheia), golden_tools (só os favoritos do aitag, lista cheia), notifications (suas notificações recentes do sino + contagem de não-lidas), mark_read (marca uma notificationId ou TODAS as não-lidas como lidas). Sub-actions de ESCRITA (mexem na SUA conta; identidade sempre da sessão): follow/unfollow (seguir/deixar de seguir outro user por followingId=users:_id, descoberto via sapiens_community participants/search_users), update_bio (edita a sua bio), update_username (troca o seu @; inválido/tomado volta {success:false,error}). As partes grandes do perfil NÃO são duplicadas aqui, têm tool própria: imagens geradas/publicadas=sapiens_gallery, repertório (filmes/séries/jogos/livros/música)=sapiens_repertorio, personagens=sapiens_character, persona/arquétipo MBTI=sapiens_persona action=my_profile, saldo detalhado por bucket=sapiens_meta action=subscription. Monta a partir de queries já em prod (sem custo).",
|
|
142
142
|
schema: profileSchema,
|
|
143
143
|
handler: profile,
|
|
144
144
|
},
|
package/dist/tools/character.js
CHANGED
|
@@ -21,6 +21,10 @@ import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js
|
|
|
21
21
|
* - set_card: edita a alma (systemPrompt), título e/ou nome do próprio.
|
|
22
22
|
* - activate: publica (sai de draft). Exige ≥1 imagem.
|
|
23
23
|
* - set_visibility: público (entra no Explorar, ganha slug) ou privado.
|
|
24
|
+
* - remove_image: tira UMA imagem do próprio personagem (por url).
|
|
25
|
+
* - set_main_image: define a principal (por url, entre as que já existem).
|
|
26
|
+
* - reorder_images: reordena as imagens (posição 0 = principal).
|
|
27
|
+
* - delete: apaga o próprio personagem (permanente).
|
|
24
28
|
*
|
|
25
29
|
* Fluxo típico de criação: create → add_image (1+) → set_card (opcional) →
|
|
26
30
|
* activate → set_visibility isPublic=true.
|
|
@@ -35,6 +39,10 @@ export const characterSchema = z.object({
|
|
|
35
39
|
"set_card",
|
|
36
40
|
"activate",
|
|
37
41
|
"set_visibility",
|
|
42
|
+
"remove_image",
|
|
43
|
+
"set_main_image",
|
|
44
|
+
"reorder_images",
|
|
45
|
+
"delete",
|
|
38
46
|
]),
|
|
39
47
|
characterId: z
|
|
40
48
|
.string()
|
|
@@ -63,7 +71,11 @@ export const characterSchema = z.object({
|
|
|
63
71
|
.describe("Pra create/set_card: a 'alma' do personagem (personalidade, jeito de falar, contexto). Usado no chat e como guia de geração."),
|
|
64
72
|
imageUrl: httpUrl()
|
|
65
73
|
.optional()
|
|
66
|
-
.describe("Pra add_image: URL pública da imagem (Bunny CDN / Convex storage). Use a `url` que sapiens_image/sapiens_gallery devolvem."),
|
|
74
|
+
.describe("Pra add_image: URL pública da imagem (Bunny CDN / Convex storage). Use a `url` que sapiens_image/sapiens_gallery devolvem. Pra remove_image/set_main_image: a url da imagem JÁ no personagem (pegue via action=get, campo imageUrls)."),
|
|
75
|
+
orderedUrls: z
|
|
76
|
+
.array(z.string())
|
|
77
|
+
.optional()
|
|
78
|
+
.describe("Pra reorder_images: as urls das imagens do personagem na nova ordem (posição 0 = principal). url ausente vai pro fim, nenhuma se perde. Pegue as urls atuais via action=get."),
|
|
67
79
|
sourceImageId: z
|
|
68
80
|
.string()
|
|
69
81
|
.optional()
|
|
@@ -188,4 +200,54 @@ export async function character(args) {
|
|
|
188
200
|
isPublic: args.isPublic,
|
|
189
201
|
});
|
|
190
202
|
}
|
|
203
|
+
// -------- remove_image: tira UMA imagem (por url) --------
|
|
204
|
+
if (args.action === "remove_image") {
|
|
205
|
+
if (!args.characterId)
|
|
206
|
+
throw new Error("action=remove_image exige characterId.");
|
|
207
|
+
if (!args.imageUrl)
|
|
208
|
+
throw new Error("action=remove_image exige imageUrl (a url da imagem no personagem; veja em action=get).");
|
|
209
|
+
const sessionToken = getSessionToken();
|
|
210
|
+
return await convexMutation("influencers:mcpRemoveCharacterImage", {
|
|
211
|
+
sessionToken,
|
|
212
|
+
characterId: args.characterId,
|
|
213
|
+
imageUrl: args.imageUrl,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// -------- set_main_image: define a principal (por url) --------
|
|
217
|
+
if (args.action === "set_main_image") {
|
|
218
|
+
if (!args.characterId)
|
|
219
|
+
throw new Error("action=set_main_image exige characterId.");
|
|
220
|
+
if (!args.imageUrl)
|
|
221
|
+
throw new Error("action=set_main_image exige imageUrl (uma das imagens já no personagem; veja em action=get).");
|
|
222
|
+
const sessionToken = getSessionToken();
|
|
223
|
+
return await convexMutation("influencers:mcpSetCharacterMainImage", {
|
|
224
|
+
sessionToken,
|
|
225
|
+
characterId: args.characterId,
|
|
226
|
+
imageUrl: args.imageUrl,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
// -------- reorder_images: nova ordem (posição 0 = principal) --------
|
|
230
|
+
if (args.action === "reorder_images") {
|
|
231
|
+
if (!args.characterId)
|
|
232
|
+
throw new Error("action=reorder_images exige characterId.");
|
|
233
|
+
if (!args.orderedUrls || args.orderedUrls.length === 0) {
|
|
234
|
+
throw new Error("action=reorder_images exige orderedUrls (as urls na nova ordem; veja em action=get).");
|
|
235
|
+
}
|
|
236
|
+
const sessionToken = getSessionToken();
|
|
237
|
+
return await convexMutation("influencers:mcpReorderCharacterImages", {
|
|
238
|
+
sessionToken,
|
|
239
|
+
characterId: args.characterId,
|
|
240
|
+
orderedUrls: args.orderedUrls,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
// -------- delete: apaga o próprio personagem (permanente) --------
|
|
244
|
+
if (args.action === "delete") {
|
|
245
|
+
if (!args.characterId)
|
|
246
|
+
throw new Error("action=delete exige characterId.");
|
|
247
|
+
const sessionToken = getSessionToken();
|
|
248
|
+
return await convexMutation("influencers:mcpDeleteCharacter", {
|
|
249
|
+
sessionToken,
|
|
250
|
+
characterId: args.characterId,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
191
253
|
}
|
package/dist/tools/profile.js
CHANGED
|
@@ -22,6 +22,9 @@ import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js
|
|
|
22
22
|
* - golden_tools: só os favoritos do aitag (lista cheia).
|
|
23
23
|
* - notifications: suas notificações recentes (sino) + contagem de não-lidas.
|
|
24
24
|
* - mark_read: marca uma (notificationId) ou TODAS as suas não-lidas como lidas.
|
|
25
|
+
* - follow/unfollow: segue/deixa de seguir outro usuário (followingId).
|
|
26
|
+
* - update_bio: edita a SUA bio.
|
|
27
|
+
* - update_username: troca o SEU @username.
|
|
25
28
|
*/
|
|
26
29
|
export const profileSchema = z.object({
|
|
27
30
|
action: z.enum([
|
|
@@ -30,6 +33,10 @@ export const profileSchema = z.object({
|
|
|
30
33
|
"golden_tools",
|
|
31
34
|
"notifications",
|
|
32
35
|
"mark_read",
|
|
36
|
+
"follow",
|
|
37
|
+
"unfollow",
|
|
38
|
+
"update_bio",
|
|
39
|
+
"update_username",
|
|
33
40
|
]),
|
|
34
41
|
limit: z
|
|
35
42
|
.number()
|
|
@@ -39,6 +46,18 @@ export const profileSchema = z.object({
|
|
|
39
46
|
.string()
|
|
40
47
|
.optional()
|
|
41
48
|
.describe("Pra mark_read: o id de UMA notificação (vem de action=notifications). Omita pra marcar TODAS as não-lidas."),
|
|
49
|
+
followingId: z
|
|
50
|
+
.string()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe("Pra follow/unfollow: users:_id de QUEM seguir/deixar de seguir. Você (o seguidor) é sempre o dono da sessão. Descubra o id via sapiens_community participants/search_users ou sapiens_search."),
|
|
53
|
+
bio: z
|
|
54
|
+
.string()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Pra update_bio: o novo texto da sua bio (perfil /u/<username>)."),
|
|
57
|
+
newUsername: z
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe("Pra update_username: o novo @ (3-20 chars, alfanumérico + underscore). Já em uso ou inválido volta {success:false,error}."),
|
|
42
61
|
});
|
|
43
62
|
const APP = "https://sapiensinteticos.com";
|
|
44
63
|
async function resolveUser(sessionToken) {
|
|
@@ -92,6 +111,40 @@ export async function profile(args) {
|
|
|
92
111
|
: `Marquei ${res.updated} notificação(ões) como lida(s).`,
|
|
93
112
|
};
|
|
94
113
|
}
|
|
114
|
+
// Escritas do perfil (autenticam pelo sessionToken; identidade sempre do
|
|
115
|
+
// token, o cliente só escolhe alvo/valor). Despacham antes do resolveUser.
|
|
116
|
+
if (args.action === "follow" || args.action === "unfollow") {
|
|
117
|
+
if (!args.followingId?.trim()) {
|
|
118
|
+
throw new Error(`action=${args.action} exige followingId (users:_id de quem seguir). Descubra via sapiens_community participants/search_users.`);
|
|
119
|
+
}
|
|
120
|
+
const fn = args.action === "follow" ? "users:mcpFollowUser" : "users:mcpUnfollowUser";
|
|
121
|
+
const res = await convexMutation(fn, {
|
|
122
|
+
sessionToken,
|
|
123
|
+
followingId: args.followingId.trim(),
|
|
124
|
+
});
|
|
125
|
+
return { ...res, action: args.action };
|
|
126
|
+
}
|
|
127
|
+
if (args.action === "update_bio") {
|
|
128
|
+
if (typeof args.bio !== "string") {
|
|
129
|
+
throw new Error("action=update_bio exige bio (o novo texto do perfil).");
|
|
130
|
+
}
|
|
131
|
+
const res = await convexMutation("users:mcpUpdateBio", {
|
|
132
|
+
sessionToken,
|
|
133
|
+
bio: args.bio,
|
|
134
|
+
});
|
|
135
|
+
return { ...res, note: "Bio atualizada." };
|
|
136
|
+
}
|
|
137
|
+
if (args.action === "update_username") {
|
|
138
|
+
if (!args.newUsername?.trim()) {
|
|
139
|
+
throw new Error("action=update_username exige newUsername (3-20 chars).");
|
|
140
|
+
}
|
|
141
|
+
const res = await convexMutation("users:mcpUpdateUsername", {
|
|
142
|
+
sessionToken,
|
|
143
|
+
newUsername: args.newUsername.trim(),
|
|
144
|
+
});
|
|
145
|
+
// doUpdateUsername devolve {success:false,error} quando inválido/tomado.
|
|
146
|
+
return res;
|
|
147
|
+
}
|
|
95
148
|
const user = await resolveUser(sessionToken);
|
|
96
149
|
const userId = user._id;
|
|
97
150
|
if (args.action === "badges") {
|
package/dist/tools/repertorio.js
CHANGED
|
@@ -4,8 +4,10 @@ import { need } from "../schema.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Acesso ao Repertório do Sapiens (acervo pessoal de filme/série/anime/jogo/livro/música).
|
|
6
6
|
*
|
|
7
|
-
* Reads (v1.0): list, search, get,
|
|
8
|
-
* só vê items públicos (isPublic !== false).
|
|
7
|
+
* Reads (v1.0): list, search, get, popArticles. Sem auth necessária —
|
|
8
|
+
* só vê items públicos (isPublic !== false). (A action `lists` saiu em jul/2026:
|
|
9
|
+
* as listas curadas foram removidas do produto em 2026-06-22, e a query
|
|
10
|
+
* repertorio:listLists não existe mais no backend.)
|
|
9
11
|
*
|
|
10
12
|
* Mutations (v1.1+): add_item, update_item, remove_item. Usam sessionToken
|
|
11
13
|
* e valem pra QUALQUER conta logada (`requireMcpUser`) — cada um mexe no
|
|
@@ -36,7 +38,6 @@ export const repertorioSchema = z.object({
|
|
|
36
38
|
"list",
|
|
37
39
|
"search",
|
|
38
40
|
"get",
|
|
39
|
-
"lists",
|
|
40
41
|
"popArticles",
|
|
41
42
|
"resolve",
|
|
42
43
|
"add_item",
|
|
@@ -197,21 +198,6 @@ export async function repertorio(args) {
|
|
|
197
198
|
if (!args.userId) {
|
|
198
199
|
throw new Error(`action=${args.action} exige userId. Use sapiens_meta action=whoami pra descobrir o user atual.`);
|
|
199
200
|
}
|
|
200
|
-
if (args.action === "lists") {
|
|
201
|
-
const lists = await convexQuery("repertorio:listLists", {
|
|
202
|
-
userId: args.userId,
|
|
203
|
-
});
|
|
204
|
-
return {
|
|
205
|
-
count: Array.isArray(lists) ? lists.length : 0,
|
|
206
|
-
lists: (lists || []).map((l) => ({
|
|
207
|
-
_id: l._id,
|
|
208
|
-
name: l.name,
|
|
209
|
-
slug: l.slug,
|
|
210
|
-
description: l.description,
|
|
211
|
-
isPublic: l.isPublic,
|
|
212
|
-
})),
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
201
|
if (args.action === "get") {
|
|
216
202
|
const item = await convexQuery("repertorio:getById", {
|
|
217
203
|
itemId: need(args.itemId, "itemId"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.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": {
|