sapiens-mcp 1.0.0 → 1.1.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.
@@ -77,6 +77,10 @@ function readPluginSessionToken() {
77
77
  // URL do Convex de produção do Sapiens. É valor público (NEXT_PUBLIC_*), então
78
78
  // vem embutido como default pra instalação via npm funcionar sem configurar nada.
79
79
  // Override por env (CONVEX_URL) continua valendo pra dev/staging.
80
+ //
81
+ // CONVEX-URL-MIGRATION: artefato DISTRIBUÍDO (pacote npm `sapiens-mcp`, já
82
+ // publicado). No corte EU->US, trocar o literal aqui, bump de versão e
83
+ // `npm publish`. Quem instalou precisa atualizar. Ver docs/infra/migracao-convex-eu-us.md
80
84
  const DEFAULT_CONVEX_URL = "https://oceanic-bass-791.convex.cloud";
81
85
  let _client = null;
82
86
  export function getConvex() {
@@ -33,6 +33,14 @@ export const imageSchema = z.object({
33
33
  .array(z.string())
34
34
  .optional()
35
35
  .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 ou gpt-image-2-*)."),
36
+ brandSlug: z
37
+ .string()
38
+ .optional()
39
+ .describe("Slug do brand (design system) pra aplicar estilo visual. Fonte única: tabela `brands` (ex: 'sapiens', 'solarpunk', 'editorial-duotone', 'brutalista-mono'). Default: nenhum (prompt cru). Vale em action=generate (mode=create) e request_generation."),
40
+ brandMark: z
41
+ .enum(["persona", "logo", "none"])
42
+ .optional()
43
+ .describe("Marca na imagem do brand: 'persona' (personagem do brand via character sheets, ex: Helen), 'logo' (carimba a logo no canto), 'none' (só o estilo). Default 'none'. Só aplica se brandSlug setado e o brand oferecer a marca."),
36
44
  mode: z
37
45
  .enum(["create", "edit", "variation"])
38
46
  .optional()
@@ -97,6 +105,8 @@ export async function image(args) {
97
105
  negativePrompt: args.negativePrompt,
98
106
  aspectRatio: args.aspectRatio ?? "16:9",
99
107
  size: args.size ?? "1K",
108
+ brandSlug: args.brandSlug,
109
+ brandMark: args.brandMark,
100
110
  }));
101
111
  }
102
112
  // Edit/variation usam desktopMcp.generateImageOnline (suporta sourceImageId
@@ -108,9 +118,7 @@ export async function image(args) {
108
118
  if ((args.mode === "edit" || args.mode === "variation") && !args.sourceImageId) {
109
119
  throw new Error(`mode='${args.mode}' exige sourceImageId. Use sapiens_gallery action=list pra descobrir.`);
110
120
  }
111
- // Quando há referenceImageUrls (URLs externas) e mode=create, ainda usamos
112
- // o pipelineMcpImage (que aceita URLs). Pra modos edit/variation usamos
113
- // desktopMcp (que aceita sourceImageId interno).
121
+ // Edit/variation (sourceImageId interno): desktopMcp (USER-TIER). Brand opcional.
114
122
  if (args.sourceImageId) {
115
123
  const result = await convexAction("desktopMcp:generateImageOnline", {
116
124
  sessionToken,
@@ -121,6 +129,8 @@ export async function image(args) {
121
129
  negativePrompt: args.negativePrompt,
122
130
  mode: args.mode ?? "edit",
123
131
  sourceImageId: args.sourceImageId,
132
+ brandSlug: args.brandSlug,
133
+ brandMark: args.brandMark,
124
134
  });
125
135
  return {
126
136
  imageId: result?.imageId,
@@ -130,16 +140,41 @@ export async function image(args) {
130
140
  // chama sapiens_gallery action=get com includeBase64=true.
131
141
  };
132
142
  }
133
- // Fluxo legacy: pipelineMcpImage com referenceImageUrls (externas) ou puro.
134
- const result = await convexAction("pipelineMcpImage:mcpGenerateImage", {
143
+ // Create COM referências externas (URLs): pipelineMcpImage (aceita URLs).
144
+ // Admin-only por enquanto. O caso comum (sem refs externas) cai no caminho
145
+ // user-tier abaixo; a persona do brand NÃO precisa de refs externas (são
146
+ // buscadas server-side a partir do próprio brand).
147
+ if (args.referenceImageUrls && args.referenceImageUrls.length > 0) {
148
+ return await convexAction("pipelineMcpImage:mcpGenerateImage", {
149
+ sessionToken,
150
+ prompt: args.prompt,
151
+ model: args.model ?? "nano-banana-2",
152
+ aspectRatio: args.aspectRatio,
153
+ size: args.size,
154
+ styleId: args.styleId,
155
+ negativePrompt: args.negativePrompt,
156
+ referenceImageUrls: args.referenceImageUrls,
157
+ brandSlug: args.brandSlug,
158
+ brandMark: args.brandMark,
159
+ });
160
+ }
161
+ // Create do zero (sem refs externas): desktopMcp (USER-TIER) com mode=create.
162
+ // Caminho do usuário comum. O brand (estilo + persona via refs server-side
163
+ // + logo) aplica dentro do generateImageAction, igual ao gerador web.
164
+ const result = await convexAction("desktopMcp:generateImageOnline", {
135
165
  sessionToken,
136
166
  prompt: args.prompt,
137
- model: args.model ?? "nano-banana-2",
138
167
  aspectRatio: args.aspectRatio,
139
168
  size: args.size,
140
- styleId: args.styleId,
169
+ model: args.model ?? "nano-banana-2",
141
170
  negativePrompt: args.negativePrompt,
142
- referenceImageUrls: args.referenceImageUrls,
171
+ mode: "create",
172
+ brandSlug: args.brandSlug,
173
+ brandMark: args.brandMark,
143
174
  });
144
- return result;
175
+ return {
176
+ imageId: result?.imageId,
177
+ url: result?.url,
178
+ mimeType: result?.mimeType,
179
+ };
145
180
  }
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { convexMutation, convexQuery, getSessionToken, } from "../convexClient.js";
3
3
  /**
4
- * Acesso ao Repertório do Sapiens (acervo pessoal de filme/série/anime/jogo).
4
+ * Acesso ao Repertório do Sapiens (acervo pessoal de filme/série/anime/jogo/livro/música).
5
5
  *
6
6
  * Reads (v1.0): list, search, get, lists, popArticles. Sem auth necessária —
7
7
  * só vê items públicos (isPublic !== false).
@@ -13,7 +13,7 @@ import { convexMutation, convexQuery, getSessionToken, } from "../convexClient.j
13
13
  *
14
14
  * Action-based design (memoria: consolidar tools via args).
15
15
  */
16
- const mediaTypeEnum = z.enum(["movie", "series", "anime", "game"]);
16
+ const mediaTypeEnum = z.enum(["movie", "series", "anime", "game", "book", "music"]);
17
17
  const statusEnum = z.enum([
18
18
  "backlog",
19
19
  "active",
@@ -21,7 +21,7 @@ const statusEnum = z.enum([
21
21
  "paused",
22
22
  "dropped",
23
23
  ]);
24
- const sourceEnum = z.enum(["tmdb", "anilist", "rawg", "manual"]);
24
+ const sourceEnum = z.enum(["tmdb", "anilist", "rawg", "twitch", "googlebooks", "itunes", "manual"]);
25
25
  export const repertorioSchema = z.object({
26
26
  action: z.enum([
27
27
  "list",
@@ -64,6 +64,12 @@ export const repertorioSchema = z.object({
64
64
  runtimeMin: z.number().optional(),
65
65
  platforms: z.array(z.string()).optional(),
66
66
  studios: z.array(z.string()).optional(),
67
+ authors: z
68
+ .array(z.string())
69
+ .optional()
70
+ .describe("Autor(es) de livro ou artista(s) de álbum (source=itunes)."),
71
+ pageCount: z.number().optional(),
72
+ isbn: z.string().optional(),
67
73
  rating: z
68
74
  .number()
69
75
  .nullable()
@@ -121,6 +127,9 @@ export async function repertorio(args) {
121
127
  runtimeMin: args.runtimeMin,
122
128
  platforms: args.platforms,
123
129
  studios: args.studios,
130
+ authors: args.authors,
131
+ pageCount: args.pageCount,
132
+ isbn: args.isbn,
124
133
  status: args.status,
125
134
  rating: args.rating === null ? undefined : args.rating,
126
135
  tags: args.tags,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapiens-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.1.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": {