@productmaker/mcp 0.13.0 → 0.15.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 +15 -10
- package/dist/stdio.js +15 -10
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -479,7 +479,7 @@ var VideoTierEnum = z.enum([
|
|
|
479
479
|
]);
|
|
480
480
|
function resolveVideoTier(tier) {
|
|
481
481
|
if (!tier) return void 0;
|
|
482
|
-
return tier === "basic" ? "
|
|
482
|
+
return tier === "basic" ? "single_call" : "standard";
|
|
483
483
|
}
|
|
484
484
|
__name(resolveVideoTier, "resolveVideoTier");
|
|
485
485
|
var VideoResolutionEnum = z.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(),
|
|
@@ -1260,11 +1262,11 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
1260
1262
|
"options.videoStyle": resolved?.videoStyle,
|
|
1261
1263
|
"options.narrativeStyle": resolved?.narrativeStyle,
|
|
1262
1264
|
"options.videoTier": wireTier,
|
|
1263
|
-
// Resolution is meaningful ONLY for the basic/
|
|
1264
|
-
// other tier the backend derives it. Forward it ONLY for
|
|
1265
|
-
// MCP never presents a "user choice where there is none" (the web
|
|
1266
|
-
// no resolution knob for standard) — for non-
|
|
1267
|
-
"options.videoResolution": wireTier === "
|
|
1265
|
+
// Resolution is meaningful ONLY for the basic/single_call tier; for every
|
|
1266
|
+
// other tier the backend derives it. Forward it ONLY for single_call so
|
|
1267
|
+
// the MCP never presents a "user choice where there is none" (the web
|
|
1268
|
+
// has no resolution knob for standard) — for non-single_call it's dropped.
|
|
1269
|
+
"options.videoResolution": wireTier === "single_call" ? input.videoResolution : void 0,
|
|
1268
1270
|
"options.multiAngleVideos": input.multiAngleVideos,
|
|
1269
1271
|
"options.angleNarratives": input.angleNarratives,
|
|
1270
1272
|
"options.selectedOutputs": input.outputs,
|
|
@@ -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
|
}
|
|
@@ -1491,7 +1496,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
1491
1496
|
wirePayload.narrativeStyle = resolved.narrativeStyle;
|
|
1492
1497
|
}
|
|
1493
1498
|
if (wireTier !== void 0) wirePayload.videoTier = wireTier;
|
|
1494
|
-
if (wireTier === "
|
|
1499
|
+
if (wireTier === "single_call" && input.videoResolution) wirePayload.videoResolution = input.videoResolution;
|
|
1495
1500
|
return await submitCreative(api, {
|
|
1496
1501
|
path: "/v1/creatives/videos",
|
|
1497
1502
|
estimatedSeconds: 300,
|
package/dist/stdio.js
CHANGED
|
@@ -476,7 +476,7 @@ var VideoTierEnum = z.enum([
|
|
|
476
476
|
]);
|
|
477
477
|
function resolveVideoTier(tier) {
|
|
478
478
|
if (!tier) return void 0;
|
|
479
|
-
return tier === "basic" ? "
|
|
479
|
+
return tier === "basic" ? "single_call" : "standard";
|
|
480
480
|
}
|
|
481
481
|
__name(resolveVideoTier, "resolveVideoTier");
|
|
482
482
|
var VideoResolutionEnum = z.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(),
|
|
@@ -1216,11 +1218,11 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
1216
1218
|
"options.videoStyle": resolved?.videoStyle,
|
|
1217
1219
|
"options.narrativeStyle": resolved?.narrativeStyle,
|
|
1218
1220
|
"options.videoTier": wireTier,
|
|
1219
|
-
// Resolution is meaningful ONLY for the basic/
|
|
1220
|
-
// other tier the backend derives it. Forward it ONLY for
|
|
1221
|
-
// MCP never presents a "user choice where there is none" (the web
|
|
1222
|
-
// no resolution knob for standard) — for non-
|
|
1223
|
-
"options.videoResolution": wireTier === "
|
|
1221
|
+
// Resolution is meaningful ONLY for the basic/single_call tier; for every
|
|
1222
|
+
// other tier the backend derives it. Forward it ONLY for single_call so
|
|
1223
|
+
// the MCP never presents a "user choice where there is none" (the web
|
|
1224
|
+
// has no resolution knob for standard) — for non-single_call it's dropped.
|
|
1225
|
+
"options.videoResolution": wireTier === "single_call" ? input.videoResolution : void 0,
|
|
1224
1226
|
"options.multiAngleVideos": input.multiAngleVideos,
|
|
1225
1227
|
"options.angleNarratives": input.angleNarratives,
|
|
1226
1228
|
"options.selectedOutputs": input.outputs,
|
|
@@ -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
|
}
|
|
@@ -1447,7 +1452,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
1447
1452
|
wirePayload.narrativeStyle = resolved.narrativeStyle;
|
|
1448
1453
|
}
|
|
1449
1454
|
if (wireTier !== void 0) wirePayload.videoTier = wireTier;
|
|
1450
|
-
if (wireTier === "
|
|
1455
|
+
if (wireTier === "single_call" && input.videoResolution) wirePayload.videoResolution = input.videoResolution;
|
|
1451
1456
|
return await submitCreative(api, {
|
|
1452
1457
|
path: "/v1/creatives/videos",
|
|
1453
1458
|
estimatedSeconds: 300,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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.",
|