@productmaker/mcp 1.5.0 → 1.6.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/http.js CHANGED
@@ -113,7 +113,7 @@ var ApiClient = class {
113
113
  };
114
114
 
115
115
  // src/index.ts
116
- var MCP_VERSION = "1.5.0";
116
+ var MCP_VERSION = "1.6.0";
117
117
 
118
118
  // src/tools/tasks.ts
119
119
  import { z as z2 } from "zod";
@@ -1216,7 +1216,18 @@ var PendingActionPayload = z2.discriminatedUnion("kind", [
1216
1216
  z2.object({
1217
1217
  kind: z2.literal("product_reference_confirmation"),
1218
1218
  userChoice: ProductReferenceUserChoiceEnum,
1219
- confirmedProductNames: z2.array(z2.string().min(1).max(120)).min(2).max(8).optional()
1219
+ confirmedProductNames: z2.array(z2.string().min(1).max(120)).min(2).max(8).optional(),
1220
+ // SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
1221
+ // reachable via MCP. Valid ONLY together with userChoice='variants' (same
1222
+ // product in several colors): renders one shot per color and stitches them,
1223
+ // so every variant color is shown off. Ignored for any other userChoice.
1224
+ // We deliberately do NOT expose the raw `standard` tier on the MCP video
1225
+ // knobs (VideoTierEnum stays {basic}) because a general tier dial with no
1226
+ // cost surface caused a prod over-spend incident (2026-07-04); this flag is
1227
+ // safe because multi-scene IS the intended render for a color variant set,
1228
+ // not a blind quality upsell. Maps to `videoTier: 'standard'` on the
1229
+ // confirm call; the backend re-gates it (variants + variant_set only).
1230
+ useMultiSceneShowcase: z2.boolean().optional().describe('Opcional (SOLO con userChoice="variants"). true = render Multiescena: una toma por color, mostrando todas las variantes, hasta 30s. Se factura POR ESCENA (m\xE1s caro que el render normal de una sola toma) \u2014 AV\xCDSALE del mayor costo al usuario antes de activarlo. Omitir = render est\xE1ndar de una sola toma. Se ignora si userChoice no es "variants".')
1220
1231
  }),
1221
1232
  z2.object({
1222
1233
  kind: z2.literal("angle_review_approval"),
@@ -1234,6 +1245,10 @@ var ResolvePendingActionInput = z2.object({
1234
1245
  taskId: z2.string().min(1),
1235
1246
  action: PendingActionPayload
1236
1247
  }).strict();
1248
+ function resolveVariantConfirmVideoTier(action) {
1249
+ return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
1250
+ }
1251
+ __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
1237
1252
  var StatusForResolveSchema = z2.object({
1238
1253
  pendingUserAction: z2.object({
1239
1254
  kind: z2.string(),
@@ -1368,7 +1383,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
1368
1383
  throw translateError(e);
1369
1384
  }
1370
1385
  });
1371
- server.tool("resolve_pending_action", 'Resuelve una acci\xF3n que el pipeline est\xE1 esperando del usuario. La llamas cuando `get_task_status` devuelve `pendingUserAction` (sin esto la tarea NUNCA avanza por m\xE1s que esperes). El `action.kind` que mandas DEBE coincidir con el `pendingUserAction.kind` que viste en el status \u2014 es el contrato de simetr\xEDa que mantiene este tool como \xFAnica superficie de resoluci\xF3n de gates.\n\nKINDS soportados hoy:\n\n\u2022 `product_reference_confirmation` \u2014 el clasificador no est\xE1 seguro si las fotos son variantes del mismo producto o productos distintos. Payload: `userChoice` \u2208 { "same_product" (mismo producto, fotos son s\xF3lo \xE1ngulos distintos), "variants" (mismo producto, distintos colores/tallas/sabores), "combo_distinct" (son 2 productos distintos vendidos juntos como combo \u2014 marca la tarea como combo), "different_products" (productos distintos y el usuario quiere generar s\xF3lo uno \u2014 el backend bloquea hasta que selecciones im\xE1genes de un solo producto; normalmente NO es la respuesta correcta para destrabar) }. PREG\xDANTALE al usuario antes de invocar \u2014 `pendingUserAction.targetProductLabel` y `reason` te dan contexto para formularle la pregunta en lenguaje natural. Usa SOLO valores presentes en `pendingUserAction.options`. Si el status trae `proposedProductNames` (lista propuesta de nombres), el combo es INCIERTO: mu\xE9strale los nombres al usuario y, si confirma que son productos distintos, manda `userChoice: "combo_distinct"` JUNTO CON `confirmedProductNames` (la lista confirmada o editada, 2-8 nombres) para separarlo en productos distintos; si el usuario dice que es un solo producto, manda `userChoice: "same_product"` (sin `confirmedProductNames`).\n\n\u2022 `angle_review_approval` \u2014 el usuario opto por `pauseForAngleReview: true` al crear el creativo (en `generate_image_creatives`, `generate_video_creative` o `generate_landing`). La IA ya gener\xF3 el \xE1ngulo + pain points + benefits + features y la tarea est\xE1 pausada esperando que el usuario apruebe o edite antes de renderizar. Lee `customAngleDraft`, `painPointsDraft`, `benefitsDraft`, `featuresDraft` del `pendingUserAction` para mostr\xE1rselos al usuario en lenguaje natural ("la IA propuso este \xE1ngulo: ... \xBFlo apruebas o cambias algo?"). Payload (TODOS opcionales \u2014 sin nada = aprobar tal cual; con campos = aprobar con ediciones): `customAngle` (override del \xE1ngulo), `painPoints`, `benefits`, `features` (array de 1-10 bullets). Llamar sin ning\xFAn campo es v\xE1lido y aprueba el draft sin cambios.\n\nFuturos kinds (no implementados a\xFAn) se agregar\xE1n como nuevas variantes del `action` discriminated union \u2014 el flujo "lee kind del status \u2192 manda mismo kind aqu\xED" sigue igual.', ResolvePendingActionInput.shape, async (input) => {
1386
+ server.tool("resolve_pending_action", 'Resuelve una acci\xF3n que el pipeline est\xE1 esperando del usuario. La llamas cuando `get_task_status` devuelve `pendingUserAction` (sin esto la tarea NUNCA avanza por m\xE1s que esperes). El `action.kind` que mandas DEBE coincidir con el `pendingUserAction.kind` que viste en el status \u2014 es el contrato de simetr\xEDa que mantiene este tool como \xFAnica superficie de resoluci\xF3n de gates.\n\nKINDS soportados hoy:\n\n\u2022 `product_reference_confirmation` \u2014 el clasificador no est\xE1 seguro si las fotos son variantes del mismo producto o productos distintos. Payload: `userChoice` \u2208 { "same_product" (mismo producto, fotos son s\xF3lo \xE1ngulos distintos), "variants" (mismo producto, distintos colores/tallas/sabores), "combo_distinct" (son 2 productos distintos vendidos juntos como combo \u2014 marca la tarea como combo), "different_products" (productos distintos y el usuario quiere generar s\xF3lo uno \u2014 el backend bloquea hasta que selecciones im\xE1genes de un solo producto; normalmente NO es la respuesta correcta para destrabar) }. PREG\xDANTALE al usuario antes de invocar \u2014 `pendingUserAction.targetProductLabel` y `reason` te dan contexto para formularle la pregunta en lenguaje natural. Usa SOLO valores presentes en `pendingUserAction.options`. Si el status trae `proposedProductNames` (lista propuesta de nombres), el combo es INCIERTO: mu\xE9strale los nombres al usuario y, si confirma que son productos distintos, manda `userChoice: "combo_distinct"` JUNTO CON `confirmedProductNames` (la lista confirmada o editada, 2-8 nombres) para separarlo en productos distintos; si el usuario dice que es un solo producto, manda `userChoice: "same_product"` (sin `confirmedProductNames`). Cuando el producto son VARIANTES DE COLOR (mismo producto, distintos colores) puedes ofrecer un video "Multiescena" que muestra una toma por color: manda `userChoice: "variants"` JUNTO CON `useMultiSceneShowcase: true`. AVISA al usuario que ese modo se factura por escena (m\xE1s caro que el render normal de una sola toma) antes de activarlo; si prefiere el render normal, manda solo `userChoice: "variants"` sin el flag.\n\n\u2022 `angle_review_approval` \u2014 el usuario opto por `pauseForAngleReview: true` al crear el creativo (en `generate_image_creatives`, `generate_video_creative` o `generate_landing`). La IA ya gener\xF3 el \xE1ngulo + pain points + benefits + features y la tarea est\xE1 pausada esperando que el usuario apruebe o edite antes de renderizar. Lee `customAngleDraft`, `painPointsDraft`, `benefitsDraft`, `featuresDraft` del `pendingUserAction` para mostr\xE1rselos al usuario en lenguaje natural ("la IA propuso este \xE1ngulo: ... \xBFlo apruebas o cambias algo?"). Payload (TODOS opcionales \u2014 sin nada = aprobar tal cual; con campos = aprobar con ediciones): `customAngle` (override del \xE1ngulo), `painPoints`, `benefits`, `features` (array de 1-10 bullets). Llamar sin ning\xFAn campo es v\xE1lido y aprueba el draft sin cambios.\n\nFuturos kinds (no implementados a\xFAn) se agregar\xE1n como nuevas variantes del `action` discriminated union \u2014 el flujo "lee kind del status \u2192 manda mismo kind aqu\xED" sigue igual.', ResolvePendingActionInput.shape, async (input) => {
1372
1387
  try {
1373
1388
  const raw = await api.getJson(`/v1/status/${encodeURIComponent(input.taskId)}`);
1374
1389
  const status = StatusForResolveSchema.parse(raw);
@@ -1397,6 +1412,12 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
1397
1412
  },
1398
1413
  ...input.action.confirmedProductNames ? {
1399
1414
  confirmedProductNames: input.action.confirmedProductNames
1415
+ } : {},
1416
+ // Multi-scene color showcase → upgrade to STANDARD. Gated to the
1417
+ // variants choice client-side so the wire body stays coherent; the
1418
+ // backend re-gates on variant_set grouping.
1419
+ ...resolveVariantConfirmVideoTier(input.action) === "standard" ? {
1420
+ videoTier: "standard"
1400
1421
  } : {}
1401
1422
  });
1402
1423
  return asText(r);
package/dist/stdio.js CHANGED
@@ -110,7 +110,7 @@ var ApiClient = class {
110
110
  };
111
111
 
112
112
  // src/index.ts
113
- var MCP_VERSION = "1.5.0";
113
+ var MCP_VERSION = "1.6.0";
114
114
 
115
115
  // src/tools/tasks.ts
116
116
  import { z as z2 } from "zod";
@@ -1172,7 +1172,18 @@ var PendingActionPayload = z2.discriminatedUnion("kind", [
1172
1172
  z2.object({
1173
1173
  kind: z2.literal("product_reference_confirmation"),
1174
1174
  userChoice: ProductReferenceUserChoiceEnum,
1175
- confirmedProductNames: z2.array(z2.string().min(1).max(120)).min(2).max(8).optional()
1175
+ confirmedProductNames: z2.array(z2.string().min(1).max(120)).min(2).max(8).optional(),
1176
+ // SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
1177
+ // reachable via MCP. Valid ONLY together with userChoice='variants' (same
1178
+ // product in several colors): renders one shot per color and stitches them,
1179
+ // so every variant color is shown off. Ignored for any other userChoice.
1180
+ // We deliberately do NOT expose the raw `standard` tier on the MCP video
1181
+ // knobs (VideoTierEnum stays {basic}) because a general tier dial with no
1182
+ // cost surface caused a prod over-spend incident (2026-07-04); this flag is
1183
+ // safe because multi-scene IS the intended render for a color variant set,
1184
+ // not a blind quality upsell. Maps to `videoTier: 'standard'` on the
1185
+ // confirm call; the backend re-gates it (variants + variant_set only).
1186
+ useMultiSceneShowcase: z2.boolean().optional().describe('Opcional (SOLO con userChoice="variants"). true = render Multiescena: una toma por color, mostrando todas las variantes, hasta 30s. Se factura POR ESCENA (m\xE1s caro que el render normal de una sola toma) \u2014 AV\xCDSALE del mayor costo al usuario antes de activarlo. Omitir = render est\xE1ndar de una sola toma. Se ignora si userChoice no es "variants".')
1176
1187
  }),
1177
1188
  z2.object({
1178
1189
  kind: z2.literal("angle_review_approval"),
@@ -1190,6 +1201,10 @@ var ResolvePendingActionInput = z2.object({
1190
1201
  taskId: z2.string().min(1),
1191
1202
  action: PendingActionPayload
1192
1203
  }).strict();
1204
+ function resolveVariantConfirmVideoTier(action) {
1205
+ return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
1206
+ }
1207
+ __name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
1193
1208
  var StatusForResolveSchema = z2.object({
1194
1209
  pendingUserAction: z2.object({
1195
1210
  kind: z2.string(),
@@ -1324,7 +1339,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
1324
1339
  throw translateError(e);
1325
1340
  }
1326
1341
  });
1327
- server.tool("resolve_pending_action", 'Resuelve una acci\xF3n que el pipeline est\xE1 esperando del usuario. La llamas cuando `get_task_status` devuelve `pendingUserAction` (sin esto la tarea NUNCA avanza por m\xE1s que esperes). El `action.kind` que mandas DEBE coincidir con el `pendingUserAction.kind` que viste en el status \u2014 es el contrato de simetr\xEDa que mantiene este tool como \xFAnica superficie de resoluci\xF3n de gates.\n\nKINDS soportados hoy:\n\n\u2022 `product_reference_confirmation` \u2014 el clasificador no est\xE1 seguro si las fotos son variantes del mismo producto o productos distintos. Payload: `userChoice` \u2208 { "same_product" (mismo producto, fotos son s\xF3lo \xE1ngulos distintos), "variants" (mismo producto, distintos colores/tallas/sabores), "combo_distinct" (son 2 productos distintos vendidos juntos como combo \u2014 marca la tarea como combo), "different_products" (productos distintos y el usuario quiere generar s\xF3lo uno \u2014 el backend bloquea hasta que selecciones im\xE1genes de un solo producto; normalmente NO es la respuesta correcta para destrabar) }. PREG\xDANTALE al usuario antes de invocar \u2014 `pendingUserAction.targetProductLabel` y `reason` te dan contexto para formularle la pregunta en lenguaje natural. Usa SOLO valores presentes en `pendingUserAction.options`. Si el status trae `proposedProductNames` (lista propuesta de nombres), el combo es INCIERTO: mu\xE9strale los nombres al usuario y, si confirma que son productos distintos, manda `userChoice: "combo_distinct"` JUNTO CON `confirmedProductNames` (la lista confirmada o editada, 2-8 nombres) para separarlo en productos distintos; si el usuario dice que es un solo producto, manda `userChoice: "same_product"` (sin `confirmedProductNames`).\n\n\u2022 `angle_review_approval` \u2014 el usuario opto por `pauseForAngleReview: true` al crear el creativo (en `generate_image_creatives`, `generate_video_creative` o `generate_landing`). La IA ya gener\xF3 el \xE1ngulo + pain points + benefits + features y la tarea est\xE1 pausada esperando que el usuario apruebe o edite antes de renderizar. Lee `customAngleDraft`, `painPointsDraft`, `benefitsDraft`, `featuresDraft` del `pendingUserAction` para mostr\xE1rselos al usuario en lenguaje natural ("la IA propuso este \xE1ngulo: ... \xBFlo apruebas o cambias algo?"). Payload (TODOS opcionales \u2014 sin nada = aprobar tal cual; con campos = aprobar con ediciones): `customAngle` (override del \xE1ngulo), `painPoints`, `benefits`, `features` (array de 1-10 bullets). Llamar sin ning\xFAn campo es v\xE1lido y aprueba el draft sin cambios.\n\nFuturos kinds (no implementados a\xFAn) se agregar\xE1n como nuevas variantes del `action` discriminated union \u2014 el flujo "lee kind del status \u2192 manda mismo kind aqu\xED" sigue igual.', ResolvePendingActionInput.shape, async (input) => {
1342
+ server.tool("resolve_pending_action", 'Resuelve una acci\xF3n que el pipeline est\xE1 esperando del usuario. La llamas cuando `get_task_status` devuelve `pendingUserAction` (sin esto la tarea NUNCA avanza por m\xE1s que esperes). El `action.kind` que mandas DEBE coincidir con el `pendingUserAction.kind` que viste en el status \u2014 es el contrato de simetr\xEDa que mantiene este tool como \xFAnica superficie de resoluci\xF3n de gates.\n\nKINDS soportados hoy:\n\n\u2022 `product_reference_confirmation` \u2014 el clasificador no est\xE1 seguro si las fotos son variantes del mismo producto o productos distintos. Payload: `userChoice` \u2208 { "same_product" (mismo producto, fotos son s\xF3lo \xE1ngulos distintos), "variants" (mismo producto, distintos colores/tallas/sabores), "combo_distinct" (son 2 productos distintos vendidos juntos como combo \u2014 marca la tarea como combo), "different_products" (productos distintos y el usuario quiere generar s\xF3lo uno \u2014 el backend bloquea hasta que selecciones im\xE1genes de un solo producto; normalmente NO es la respuesta correcta para destrabar) }. PREG\xDANTALE al usuario antes de invocar \u2014 `pendingUserAction.targetProductLabel` y `reason` te dan contexto para formularle la pregunta en lenguaje natural. Usa SOLO valores presentes en `pendingUserAction.options`. Si el status trae `proposedProductNames` (lista propuesta de nombres), el combo es INCIERTO: mu\xE9strale los nombres al usuario y, si confirma que son productos distintos, manda `userChoice: "combo_distinct"` JUNTO CON `confirmedProductNames` (la lista confirmada o editada, 2-8 nombres) para separarlo en productos distintos; si el usuario dice que es un solo producto, manda `userChoice: "same_product"` (sin `confirmedProductNames`). Cuando el producto son VARIANTES DE COLOR (mismo producto, distintos colores) puedes ofrecer un video "Multiescena" que muestra una toma por color: manda `userChoice: "variants"` JUNTO CON `useMultiSceneShowcase: true`. AVISA al usuario que ese modo se factura por escena (m\xE1s caro que el render normal de una sola toma) antes de activarlo; si prefiere el render normal, manda solo `userChoice: "variants"` sin el flag.\n\n\u2022 `angle_review_approval` \u2014 el usuario opto por `pauseForAngleReview: true` al crear el creativo (en `generate_image_creatives`, `generate_video_creative` o `generate_landing`). La IA ya gener\xF3 el \xE1ngulo + pain points + benefits + features y la tarea est\xE1 pausada esperando que el usuario apruebe o edite antes de renderizar. Lee `customAngleDraft`, `painPointsDraft`, `benefitsDraft`, `featuresDraft` del `pendingUserAction` para mostr\xE1rselos al usuario en lenguaje natural ("la IA propuso este \xE1ngulo: ... \xBFlo apruebas o cambias algo?"). Payload (TODOS opcionales \u2014 sin nada = aprobar tal cual; con campos = aprobar con ediciones): `customAngle` (override del \xE1ngulo), `painPoints`, `benefits`, `features` (array de 1-10 bullets). Llamar sin ning\xFAn campo es v\xE1lido y aprueba el draft sin cambios.\n\nFuturos kinds (no implementados a\xFAn) se agregar\xE1n como nuevas variantes del `action` discriminated union \u2014 el flujo "lee kind del status \u2192 manda mismo kind aqu\xED" sigue igual.', ResolvePendingActionInput.shape, async (input) => {
1328
1343
  try {
1329
1344
  const raw = await api.getJson(`/v1/status/${encodeURIComponent(input.taskId)}`);
1330
1345
  const status = StatusForResolveSchema.parse(raw);
@@ -1353,6 +1368,12 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
1353
1368
  },
1354
1369
  ...input.action.confirmedProductNames ? {
1355
1370
  confirmedProductNames: input.action.confirmedProductNames
1371
+ } : {},
1372
+ // Multi-scene color showcase → upgrade to STANDARD. Gated to the
1373
+ // variants choice client-side so the wire body stays coherent; the
1374
+ // backend re-gates on variant_set grouping.
1375
+ ...resolveVariantConfirmVideoTier(input.action) === "standard" ? {
1376
+ videoTier: "standard"
1356
1377
  } : {}
1357
1378
  });
1358
1379
  return asText(r);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@productmaker/mcp",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "description": "Product Maker MCP server — connect Claude Desktop, Claude Code, ChatGPT, or Gemini to Product Maker AI to generate dropshipping landing pages, UGC videos, and ad creatives, and publish to Shopify and Meta Ads from your AI assistant.",
@@ -60,7 +60,7 @@
60
60
  "msw": "^2.4.0",
61
61
  "tsup": "^8.3.0",
62
62
  "tsx": "^4.16.0",
63
- "typescript": "^5.4.5",
63
+ "typescript": "^7.0.2",
64
64
  "vitest": "^2.1.9",
65
65
  "@packages/types": "0.1.0"
66
66
  },