@productmaker/mcp 0.14.0 → 0.15.1
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 +10 -5
- package/dist/stdio.js +10 -5
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -1174,7 +1174,7 @@ var CreateProductTaskInput = z2.object({
|
|
|
1174
1174
|
offer: z2.string().optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
|
|
1175
1175
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla (en la web es el \xFAnico dropdown). Default "auto" (la IA escoge tras analizar el producto). Opciones: "auto", "ugc_dynamic" (UGC testimonial), "ugc_unboxing_chaos" (unboxing agresivo), "ugc_curiosity_reveal" (hook con producto oculto), "ugc_listicle_3" (3 razones, ideal 30s), "ugc_skeptic_confession" (esc\xE9ptico\u2192conversi\xF3n, ideal 30s), "ugc_demo_review" (demo en uso), "problem_solution" (problema\u2192producto\u2192CTA), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla), "product_showcase" (solo producto, sin actor), "wearable_showcase" (ropa/accesorios puestos). Si el usuario pide algo fuera de esta lista (ej. "estilo anime"), p\xEDdele una opci\xF3n v\xE1lida.'),
|
|
1176
1176
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video (en la web la etiqueta es "\xBFCalidad de video?", 2 opciones \u2014 sin escalera de calidad, son ESTILOS distintos). "basic" = "Realista" (RECOMENDADO por la web): render de 15s con audio nativo, el m\xE1s natural \u2014 S\xD3LO v\xE1lido si la duraci\xF3n del video es 15s. "standard" = "Multiescena": m\xFAltiples tomas, hasta 30s. Si el usuario no menciona estilo, OMITE este campo y el backend usa su default. Para duraci\xF3n 30s s\xF3lo aplica "standard" (Realista est\xE1 vetada).'),
|
|
1177
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "
|
|
1177
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez (~el doble de precio). Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p para basic).'),
|
|
1178
1178
|
multiAngleVideos: z2.boolean().optional().describe("Opcional. Si true, genera m\xFAltiples \xE1ngulos de venta en paralelo (3-5 videos). Si false/omitido, genera 1 video del \xE1ngulo principal. Default false."),
|
|
1179
1179
|
angleNarratives: NarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional, override avanzado). Usa los mismos identificadores de narrativa que videoPreset (ej. "animated_problem_pixar", "review", "ugc_skeptic_confession"). angleNarratives[i] fuerza la narrativa del \xE1ngulo en la posici\xF3n i; si la lista es m\xE1s corta que la cantidad de \xE1ngulos, las posiciones restantes las elige la IA. Requiere multiAngleVideos:true para que haya varios \xE1ngulos. Si se omite, todas las narrativas se auto-seleccionan seg\xFAn el producto.'),
|
|
1180
1180
|
outputs: z2.array(z2.enum([
|
|
@@ -1210,7 +1210,8 @@ var EditTaskDraftInput = z2.object({
|
|
|
1210
1210
|
var PendingActionPayload = z2.discriminatedUnion("kind", [
|
|
1211
1211
|
z2.object({
|
|
1212
1212
|
kind: z2.literal("product_reference_confirmation"),
|
|
1213
|
-
userChoice: ProductReferenceUserChoiceEnum
|
|
1213
|
+
userChoice: ProductReferenceUserChoiceEnum,
|
|
1214
|
+
confirmedProductNames: z2.array(z2.string().min(1).max(120)).min(2).max(8).optional()
|
|
1214
1215
|
}),
|
|
1215
1216
|
z2.object({
|
|
1216
1217
|
kind: z2.literal("angle_review_approval"),
|
|
@@ -1233,6 +1234,7 @@ var StatusForResolveSchema = z2.object({
|
|
|
1233
1234
|
kind: z2.string(),
|
|
1234
1235
|
candidateGrouping: z2.string().optional(),
|
|
1235
1236
|
selectedImageUrls: z2.array(z2.string()).optional(),
|
|
1237
|
+
proposedProductNames: z2.array(z2.string()).optional(),
|
|
1236
1238
|
customAngleDraft: z2.string().optional(),
|
|
1237
1239
|
painPointsDraft: z2.string().optional(),
|
|
1238
1240
|
benefitsDraft: z2.string().optional(),
|
|
@@ -1340,7 +1342,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
1340
1342
|
throw translateError(e);
|
|
1341
1343
|
}
|
|
1342
1344
|
});
|
|
1343
|
-
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
|
|
1345
|
+
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) => {
|
|
1344
1346
|
try {
|
|
1345
1347
|
const raw = await api.getJson(`/v1/status/${encodeURIComponent(input.taskId)}`);
|
|
1346
1348
|
const status = StatusForResolveSchema.parse(raw);
|
|
@@ -1366,7 +1368,10 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
1366
1368
|
// we send the matching MCP-mirror value so the wire body
|
|
1367
1369
|
// is internally coherent if the server skips overwrite.
|
|
1368
1370
|
selectedImageUrlsHash: buildSelectedImageUrlsHash(selectedImageUrls)
|
|
1369
|
-
}
|
|
1371
|
+
},
|
|
1372
|
+
...input.action.confirmedProductNames ? {
|
|
1373
|
+
confirmedProductNames: input.action.confirmedProductNames
|
|
1374
|
+
} : {}
|
|
1370
1375
|
});
|
|
1371
1376
|
return asText(r);
|
|
1372
1377
|
}
|
|
@@ -1425,7 +1430,7 @@ var VideoInput = z3.object({
|
|
|
1425
1430
|
durationSeconds: z3.number().int().min(5).max(60).optional().describe("Opcional. Duraci\xF3n del video en segundos (5-60). Default 15s. Para hooks cortos usa 8, para storytelling usa 30."),
|
|
1426
1431
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla (en la web es el \xFAnico dropdown). Default "auto" (la IA escoge tras analizar el producto). Opciones: "auto", "ugc_dynamic" (UGC cl\xE1sico testimonial multi-hook), "ugc_unboxing_chaos" (unboxing agresivo), "ugc_curiosity_reveal" (hook con producto oculto), "ugc_listicle_3" (3 razones numeradas, recomendado 30s), "ugc_skeptic_confession" (esc\xE9ptico\u2192conversi\xF3n, recomendado 30s), "ugc_demo_review" (demo en uso a lo largo de d\xEDas), "problem_solution" (problema\u2192producto\u2192CTA), "pixar_problem" (problema animado 3D estilo Pixar), "pixar_sassy" (producto que habla con personalidad), "product_showcase" (sin actor, solo producto), "wearable_showcase" (ropa/accesorios puestos).'),
|
|
1427
1432
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video (en la web la etiqueta es "\xBFCalidad de video?", 2 opciones \u2014 sin escalera de calidad, son ESTILOS distintos). "basic" = "Realista" (RECOMENDADO por la web): render de 15s con audio nativo, el m\xE1s natural \u2014 S\xD3LO v\xE1lido cuando durationSeconds \u2264 15 (el handler lo valida). "standard" = "Multiescena": m\xFAltiples tomas, hasta 30s. Si la duraci\xF3n es 30s, s\xF3lo aplica "standard". Si el usuario no menciona estilo, OMITE este campo y el backend usa su default.'),
|
|
1428
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); el tier "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "
|
|
1433
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); el tier "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez (~el doble de precio). Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p para basic).'),
|
|
1429
1434
|
features: z3.array(z3.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
1430
1435
|
price: CreativeRefs.price,
|
|
1431
1436
|
offer: CreativeRefs.offer,
|
package/dist/stdio.js
CHANGED
|
@@ -1130,7 +1130,7 @@ var CreateProductTaskInput = z2.object({
|
|
|
1130
1130
|
offer: z2.string().optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
|
|
1131
1131
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla (en la web es el \xFAnico dropdown). Default "auto" (la IA escoge tras analizar el producto). Opciones: "auto", "ugc_dynamic" (UGC testimonial), "ugc_unboxing_chaos" (unboxing agresivo), "ugc_curiosity_reveal" (hook con producto oculto), "ugc_listicle_3" (3 razones, ideal 30s), "ugc_skeptic_confession" (esc\xE9ptico\u2192conversi\xF3n, ideal 30s), "ugc_demo_review" (demo en uso), "problem_solution" (problema\u2192producto\u2192CTA), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla), "product_showcase" (solo producto, sin actor), "wearable_showcase" (ropa/accesorios puestos). Si el usuario pide algo fuera de esta lista (ej. "estilo anime"), p\xEDdele una opci\xF3n v\xE1lida.'),
|
|
1132
1132
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video (en la web la etiqueta es "\xBFCalidad de video?", 2 opciones \u2014 sin escalera de calidad, son ESTILOS distintos). "basic" = "Realista" (RECOMENDADO por la web): render de 15s con audio nativo, el m\xE1s natural \u2014 S\xD3LO v\xE1lido si la duraci\xF3n del video es 15s. "standard" = "Multiescena": m\xFAltiples tomas, hasta 30s. Si el usuario no menciona estilo, OMITE este campo y el backend usa su default. Para duraci\xF3n 30s s\xF3lo aplica "standard" (Realista est\xE1 vetada).'),
|
|
1133
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "
|
|
1133
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez (~el doble de precio). Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p para basic).'),
|
|
1134
1134
|
multiAngleVideos: z2.boolean().optional().describe("Opcional. Si true, genera m\xFAltiples \xE1ngulos de venta en paralelo (3-5 videos). Si false/omitido, genera 1 video del \xE1ngulo principal. Default false."),
|
|
1135
1135
|
angleNarratives: NarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional, override avanzado). Usa los mismos identificadores de narrativa que videoPreset (ej. "animated_problem_pixar", "review", "ugc_skeptic_confession"). angleNarratives[i] fuerza la narrativa del \xE1ngulo en la posici\xF3n i; si la lista es m\xE1s corta que la cantidad de \xE1ngulos, las posiciones restantes las elige la IA. Requiere multiAngleVideos:true para que haya varios \xE1ngulos. Si se omite, todas las narrativas se auto-seleccionan seg\xFAn el producto.'),
|
|
1136
1136
|
outputs: z2.array(z2.enum([
|
|
@@ -1166,7 +1166,8 @@ var EditTaskDraftInput = z2.object({
|
|
|
1166
1166
|
var PendingActionPayload = z2.discriminatedUnion("kind", [
|
|
1167
1167
|
z2.object({
|
|
1168
1168
|
kind: z2.literal("product_reference_confirmation"),
|
|
1169
|
-
userChoice: ProductReferenceUserChoiceEnum
|
|
1169
|
+
userChoice: ProductReferenceUserChoiceEnum,
|
|
1170
|
+
confirmedProductNames: z2.array(z2.string().min(1).max(120)).min(2).max(8).optional()
|
|
1170
1171
|
}),
|
|
1171
1172
|
z2.object({
|
|
1172
1173
|
kind: z2.literal("angle_review_approval"),
|
|
@@ -1189,6 +1190,7 @@ var StatusForResolveSchema = z2.object({
|
|
|
1189
1190
|
kind: z2.string(),
|
|
1190
1191
|
candidateGrouping: z2.string().optional(),
|
|
1191
1192
|
selectedImageUrls: z2.array(z2.string()).optional(),
|
|
1193
|
+
proposedProductNames: z2.array(z2.string()).optional(),
|
|
1192
1194
|
customAngleDraft: z2.string().optional(),
|
|
1193
1195
|
painPointsDraft: z2.string().optional(),
|
|
1194
1196
|
benefitsDraft: z2.string().optional(),
|
|
@@ -1296,7 +1298,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
1296
1298
|
throw translateError(e);
|
|
1297
1299
|
}
|
|
1298
1300
|
});
|
|
1299
|
-
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
|
|
1301
|
+
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) => {
|
|
1300
1302
|
try {
|
|
1301
1303
|
const raw = await api.getJson(`/v1/status/${encodeURIComponent(input.taskId)}`);
|
|
1302
1304
|
const status = StatusForResolveSchema.parse(raw);
|
|
@@ -1322,7 +1324,10 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
1322
1324
|
// we send the matching MCP-mirror value so the wire body
|
|
1323
1325
|
// is internally coherent if the server skips overwrite.
|
|
1324
1326
|
selectedImageUrlsHash: buildSelectedImageUrlsHash(selectedImageUrls)
|
|
1325
|
-
}
|
|
1327
|
+
},
|
|
1328
|
+
...input.action.confirmedProductNames ? {
|
|
1329
|
+
confirmedProductNames: input.action.confirmedProductNames
|
|
1330
|
+
} : {}
|
|
1326
1331
|
});
|
|
1327
1332
|
return asText(r);
|
|
1328
1333
|
}
|
|
@@ -1381,7 +1386,7 @@ var VideoInput = z3.object({
|
|
|
1381
1386
|
durationSeconds: z3.number().int().min(5).max(60).optional().describe("Opcional. Duraci\xF3n del video en segundos (5-60). Default 15s. Para hooks cortos usa 8, para storytelling usa 30."),
|
|
1382
1387
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla (en la web es el \xFAnico dropdown). Default "auto" (la IA escoge tras analizar el producto). Opciones: "auto", "ugc_dynamic" (UGC cl\xE1sico testimonial multi-hook), "ugc_unboxing_chaos" (unboxing agresivo), "ugc_curiosity_reveal" (hook con producto oculto), "ugc_listicle_3" (3 razones numeradas, recomendado 30s), "ugc_skeptic_confession" (esc\xE9ptico\u2192conversi\xF3n, recomendado 30s), "ugc_demo_review" (demo en uso a lo largo de d\xEDas), "problem_solution" (problema\u2192producto\u2192CTA), "pixar_problem" (problema animado 3D estilo Pixar), "pixar_sassy" (producto que habla con personalidad), "product_showcase" (sin actor, solo producto), "wearable_showcase" (ropa/accesorios puestos).'),
|
|
1383
1388
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video (en la web la etiqueta es "\xBFCalidad de video?", 2 opciones \u2014 sin escalera de calidad, son ESTILOS distintos). "basic" = "Realista" (RECOMENDADO por la web): render de 15s con audio nativo, el m\xE1s natural \u2014 S\xD3LO v\xE1lido cuando durationSeconds \u2264 15 (el handler lo valida). "standard" = "Multiescena": m\xFAltiples tomas, hasta 30s. Si la duraci\xF3n es 30s, s\xF3lo aplica "standard". Si el usuario no menciona estilo, OMITE este campo y el backend usa su default.'),
|
|
1384
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); el tier "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "
|
|
1389
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render \u2014 aplica S\xD3LO al tier "basic" (Realista); el tier "standard" la deriva solo. En la web se pregunta "\xBFResoluci\xF3n del video?" tras elegir "basic". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez (~el doble de precio). Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p para basic).'),
|
|
1385
1390
|
features: z3.array(z3.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
1386
1391
|
price: CreativeRefs.price,
|
|
1387
1392
|
offer: CreativeRefs.offer,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
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.",
|