@productmaker/mcp 8.13.1 → 9.0.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/README.md +2 -2
- package/dist/http.js +139 -122
- package/dist/stdio.js +139 -122
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -137,7 +137,7 @@ separate release step.
|
|
|
137
137
|
| `get_task_status` | Check task progress (optional `waitSeconds` for near-sync polling) |
|
|
138
138
|
| `list_tasks` | List recent tasks |
|
|
139
139
|
| `edit_task_draft` | Edit angle / pain point / persona before generation |
|
|
140
|
-
| `create_service_video` |
|
|
140
|
+
| `create_service_video` | **Hidden from the MCP since 9.0.0** (owner decision 2026-10-08, still on WhatsApp): use `create_animated_video` for a service video. |
|
|
141
141
|
| `create_animated_video` | Animated _service_ video ("Video animado", motion graphics: text, shapes and the site's visual identity, music, no presenter) from its landing page URL. Choose `format` (vertical/square/horizontal), `durationSec` (10/15/30/45/60), `language` (es/en/pt) and optional `notes`. **Paid action** — flat price by duration (listed in the tool description, refunded on failure); takes minutes in a queue. Follow it with `get_task_status` (stage, queue position, render %, activity, preview, final MP4). In closed testing: other accounts get `FEATURE_NOT_AVAILABLE` |
|
|
142
142
|
| `generate_video_creative` | Standalone UGC video creative |
|
|
143
143
|
| `generate_free_video` | One free-form video from an exact prompt/script, optionally with a reference image (async: returns a `taskId`) |
|
|
@@ -390,7 +390,7 @@ Release metadata synchronized with per-store Meta controls. MCP tool inputs, res
|
|
|
390
390
|
|
|
391
391
|
### 8.3.0 — Idempotencia de tools pagadas + refresh OAuth
|
|
392
392
|
|
|
393
|
-
- Tools pagadas (`create_product_task`, `
|
|
393
|
+
- Tools pagadas (`create_product_task`, `create_animated_video` (sin `notes` en la llave), `generate_video_creative`, `generate_free_video`, `generate_image_creatives`, `generate_landing`, `create_creative_variant`): envían un `Idempotency-Key` derivado de los argumentos semánticos (ventana de 15 min). Un reintento con los mismos argumentos devuelve la misma tarea (`replayed: true`) sin segundo cargo; una tarea en `error` sí se reintenta.
|
|
394
394
|
- OAuth alojado: se anuncia `offline_access` + grant `refresh_token`; un token a punto de expirar responde `401` + `WWW-Authenticate` para que el host refresque en silencio (`MCP_SUBJECT_TOKEN_REAUTH_WINDOW_MS`, por defecto 180000; `0` lo desactiva).
|
|
395
395
|
|
|
396
396
|
### 8.2.0 — Fase 3 (modelos)
|
package/dist/http.js
CHANGED
|
@@ -15274,44 +15274,58 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
15274
15274
|
"product"
|
|
15275
15275
|
]
|
|
15276
15276
|
),
|
|
15277
|
-
defineCapability(
|
|
15277
|
+
defineCapability(
|
|
15278
|
+
"create_service_video",
|
|
15279
|
+
"c3d81a4f698e01658fa04ebb613a91c8ba43320d21cacda522e72d198036eb21",
|
|
15278
15280
|
"credit_consuming",
|
|
15279
|
-
"
|
|
15280
|
-
|
|
15281
|
-
|
|
15282
|
-
"
|
|
15283
|
-
]
|
|
15284
|
-
|
|
15285
|
-
"
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
"
|
|
15289
|
-
|
|
15290
|
-
|
|
15291
|
-
"
|
|
15292
|
-
|
|
15293
|
-
|
|
15294
|
-
"
|
|
15295
|
-
|
|
15296
|
-
|
|
15297
|
-
"
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
"
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
"
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15281
|
+
"creative",
|
|
15282
|
+
[
|
|
15283
|
+
"credit_consuming",
|
|
15284
|
+
"state_change"
|
|
15285
|
+
],
|
|
15286
|
+
[
|
|
15287
|
+
slot("service_landing", true, [
|
|
15288
|
+
"landingUrl"
|
|
15289
|
+
]),
|
|
15290
|
+
slot("locale", true, [
|
|
15291
|
+
"language"
|
|
15292
|
+
]),
|
|
15293
|
+
slot("service_context", false, [
|
|
15294
|
+
"additionalContext"
|
|
15295
|
+
]),
|
|
15296
|
+
slot("voice", false, [
|
|
15297
|
+
"voiceId"
|
|
15298
|
+
]),
|
|
15299
|
+
slot("brand", false, [
|
|
15300
|
+
"brandId"
|
|
15301
|
+
]),
|
|
15302
|
+
slot("review_mode", false, [
|
|
15303
|
+
"reviewMode"
|
|
15304
|
+
]),
|
|
15305
|
+
slot("video_preset", false, [
|
|
15306
|
+
"videoPreset"
|
|
15307
|
+
]),
|
|
15308
|
+
// MCP-only for now: WhatsApp's service flow keeps the economy default.
|
|
15309
|
+
slot("video_quality", false, [
|
|
15310
|
+
"videoQuality"
|
|
15311
|
+
], []),
|
|
15312
|
+
slot("video_resolution", false, [
|
|
15313
|
+
"videoResolution"
|
|
15314
|
+
], [])
|
|
15315
|
+
],
|
|
15316
|
+
[
|
|
15317
|
+
"service_context"
|
|
15318
|
+
],
|
|
15319
|
+
[
|
|
15320
|
+
"task",
|
|
15321
|
+
"video"
|
|
15322
|
+
],
|
|
15323
|
+
// Owner decision 2026-10-08: the presenter service video is hidden from the
|
|
15324
|
+
// MCP for now — dropshipping sellers ordered it for products and cancelled.
|
|
15325
|
+
// MCP clients get `create_animated_video` instead. Flip back to
|
|
15326
|
+
// SHARED_CHANNEL_EXPOSURE to restore it.
|
|
15327
|
+
WHATSAPP_ONLY_CHANNEL_EXPOSURE
|
|
15328
|
+
),
|
|
15315
15329
|
defineCapability("edit_image_creative", "50eca473829328dfb63b9cbae03a9835b79c510e29528563e09b7eb3e5e9bca4", "credit_consuming", "creative", [
|
|
15316
15330
|
"credit_consuming",
|
|
15317
15331
|
"state_change"
|
|
@@ -19789,7 +19803,7 @@ var ApiClient = class {
|
|
|
19789
19803
|
};
|
|
19790
19804
|
|
|
19791
19805
|
// src/index.ts
|
|
19792
|
-
var MCP_VERSION = "
|
|
19806
|
+
var MCP_VERSION = "9.0.0";
|
|
19793
19807
|
|
|
19794
19808
|
// src/meta-upload-app.ts
|
|
19795
19809
|
import { readFileSync } from "fs";
|
|
@@ -22338,7 +22352,7 @@ function renderAnimatedVideoStatus(result) {
|
|
|
22338
22352
|
__name(renderAnimatedVideoStatus, "renderAnimatedVideoStatus");
|
|
22339
22353
|
function registerAnimatedVideoTools(server, api) {
|
|
22340
22354
|
server.registerTool("create_animated_video", {
|
|
22341
|
-
description: guidance.summary + ` Hace un video animado (motion graphics) de un SERVICIO a partir del enlace de su p\xE1gina: textos, formas y la identidad visual del sitio, con m\xFAsica y efectos, sin presentador ni voz en off. Esta acci\xF3n consume cr\xE9ditos: confirma formato, duraci\xF3n, idioma y precio con el usuario antes de llamarla. Precio fijo por duraci\xF3n: ${describeAnimatedVideoPrices()}; si falla, se devuelve. Tarda varios minutos, m\xE1s si hay otros videos en la cola. Devuelve un taskId: sigue el avance con get_task_status (etapa, posici\xF3n en la cola, % de render, lo que va haciendo y vista previa) hasta done, que trae el enlace del MP4, o error, que trae el motivo.
|
|
22355
|
+
description: guidance.summary + ` Hace un video animado (motion graphics) de un SERVICIO a partir del enlace de su p\xE1gina: textos, formas y la identidad visual del sitio, con m\xFAsica y efectos, sin presentador ni voz en off. Esta acci\xF3n consume cr\xE9ditos: confirma formato, duraci\xF3n, idioma y precio con el usuario antes de llamarla. Precio fijo por duraci\xF3n: ${describeAnimatedVideoPrices()}; si falla, se devuelve. Tarda varios minutos, m\xE1s si hay otros videos en la cola. Devuelve un taskId: sigue el avance con get_task_status (etapa, posici\xF3n en la cola, % de render, lo que va haciendo y vista previa) hasta done, que trae el enlace del MP4, o error, que trae el motivo. Es el \xFAnico video de servicio disponible por ahora: no ofrezcas un video con presentador. Puede no estar disponible para todas las cuentas: si responde que la funci\xF3n no est\xE1 disponible, dilo y no ofrezcas alternativas pagadas.`,
|
|
22342
22356
|
inputSchema: CreateAnimatedVideoInput.shape,
|
|
22343
22357
|
annotations: CREATES_PAID_OPEN_WORLD
|
|
22344
22358
|
}, async (input) => {
|
|
@@ -22443,7 +22457,7 @@ function renderCreateProductTaskAvoidWhenForMcp(fragment) {
|
|
|
22443
22457
|
__name(renderCreateProductTaskAvoidWhenForMcp, "renderCreateProductTaskAvoidWhenForMcp");
|
|
22444
22458
|
var createProductTaskDefaultDescription = renderCreateProductTaskDefaultForMcp(createProductTaskGuidance.defaults[0]);
|
|
22445
22459
|
var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenForMcp(createProductTaskGuidance.avoidWhen[0]);
|
|
22446
|
-
var
|
|
22460
|
+
var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
|
|
22447
22461
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
22448
22462
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
22449
22463
|
var CreateProductTaskInput = z87.object({
|
|
@@ -22878,7 +22892,7 @@ async function fetchAnimatedVideoResult(api, taskId, signal, serviceMode = void
|
|
|
22878
22892
|
}
|
|
22879
22893
|
}
|
|
22880
22894
|
__name(fetchAnimatedVideoResult, "fetchAnimatedVideoResult");
|
|
22881
|
-
function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http" } = {}) {
|
|
22895
|
+
function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http", serviceVideo = CREATE_SERVICE_VIDEO_ON_MCP } = {}) {
|
|
22882
22896
|
server.registerTool("create_product_task", {
|
|
22883
22897
|
description: createProductTaskGuidance.summary + ` ${createProductTaskDefaultDescription} \xDAsala cuando el usuario pide todo o varios outputs, no creando tareas individuales. Usa images para solicitudes directas. Usa projectId \xFAnicamente si el usuario pidi\xF3 expl\xEDcitamente continuar el proyecto guiado que acaba de costear; nunca busques, infieras ni menciones proyectos previos.
|
|
22884
22898
|
|
|
@@ -23001,97 +23015,100 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
23001
23015
|
throw translateError(e);
|
|
23002
23016
|
}
|
|
23003
23017
|
});
|
|
23004
|
-
|
|
23005
|
-
|
|
23006
|
-
|
|
23007
|
-
|
|
23008
|
-
|
|
23009
|
-
|
|
23010
|
-
|
|
23011
|
-
|
|
23012
|
-
|
|
23013
|
-
|
|
23014
|
-
|
|
23015
|
-
|
|
23016
|
-
|
|
23017
|
-
|
|
23018
|
-
|
|
23019
|
-
|
|
23020
|
-
|
|
23021
|
-
|
|
23022
|
-
|
|
23023
|
-
|
|
23024
|
-
|
|
23025
|
-
|
|
23026
|
-
|
|
23027
|
-
|
|
23028
|
-
|
|
23029
|
-
|
|
23030
|
-
|
|
23031
|
-
|
|
23032
|
-
|
|
23033
|
-
|
|
23034
|
-
|
|
23035
|
-
|
|
23036
|
-
|
|
23037
|
-
|
|
23038
|
-
|
|
23039
|
-
|
|
23040
|
-
|
|
23041
|
-
|
|
23042
|
-
|
|
23043
|
-
|
|
23044
|
-
|
|
23045
|
-
|
|
23046
|
-
|
|
23047
|
-
|
|
23048
|
-
|
|
23049
|
-
|
|
23050
|
-
|
|
23051
|
-
|
|
23052
|
-
|
|
23053
|
-
if (
|
|
23054
|
-
|
|
23055
|
-
|
|
23056
|
-
|
|
23057
|
-
|
|
23018
|
+
if (serviceVideo) {
|
|
23019
|
+
const createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
23020
|
+
server.registerTool("create_service_video", {
|
|
23021
|
+
description: createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.",
|
|
23022
|
+
inputSchema: CreateServiceVideoInput.shape,
|
|
23023
|
+
annotations: CREATES_PAID_OPEN_WORLD
|
|
23024
|
+
}, async (input) => {
|
|
23025
|
+
try {
|
|
23026
|
+
if (input.videoQuality === "medium" && input.videoResolution === "720p") {
|
|
23027
|
+
throw mcp(McpErrorCode.INVALID_INPUT, 'videoResolution "720p" no est\xE1 disponible con videoQuality "medium" en videos de servicio (Medio = 768P). Usa "480p" o elige "economy"/"pro".');
|
|
23028
|
+
}
|
|
23029
|
+
await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
|
|
23030
|
+
const created = await api.postJson("/v2/ingest", {
|
|
23031
|
+
taskType: "service",
|
|
23032
|
+
serviceLandingUrl: input.landingUrl,
|
|
23033
|
+
...input.additionalContext ? {
|
|
23034
|
+
additionalContext: input.additionalContext
|
|
23035
|
+
} : {},
|
|
23036
|
+
lang: input.language,
|
|
23037
|
+
...input.voiceId ? {
|
|
23038
|
+
voiceId: input.voiceId
|
|
23039
|
+
} : {},
|
|
23040
|
+
videoPreset: input.videoPreset,
|
|
23041
|
+
videoQuality: input.videoQuality,
|
|
23042
|
+
videoResolution: input.videoResolution,
|
|
23043
|
+
reviewMode: input.reviewMode,
|
|
23044
|
+
...input.brandId ? {
|
|
23045
|
+
brandId: input.brandId
|
|
23046
|
+
} : {},
|
|
23047
|
+
media: {
|
|
23048
|
+
assets: []
|
|
23049
|
+
},
|
|
23050
|
+
appDemoVideos: []
|
|
23051
|
+
}, {
|
|
23052
|
+
// The 2026-09-25 incident: four retries of this exact tool created
|
|
23053
|
+
// four charged service tasks because the host rephrased
|
|
23054
|
+
// `additionalContext` and flipped the landing between `/` and
|
|
23055
|
+
// `/es`. The derived key is stable across both rewrites (see
|
|
23056
|
+
// request-key.ts).
|
|
23057
|
+
idempotencyKey: derivePaidRequestKey({
|
|
23058
|
+
fingerprint: api.fingerprint(),
|
|
23059
|
+
tool: "create_service_video",
|
|
23060
|
+
input,
|
|
23061
|
+
nowMs: Date.now()
|
|
23062
|
+
})
|
|
23063
|
+
});
|
|
23064
|
+
const angles = await api.postJson(`/v1/tasks/${encodeURIComponent(created.taskId)}/service-angles`, {});
|
|
23065
|
+
const first = angles[0];
|
|
23066
|
+
const replayed = created.replayed === true;
|
|
23067
|
+
if (input.reviewMode === "automatic") {
|
|
23068
|
+
if (!first) throw new Error("ProductMaker no pudo crear un concepto para este servicio.");
|
|
23069
|
+
if (!(replayed && created.status !== "queued")) {
|
|
23070
|
+
await api.postJson(`/v1/tasks/${encodeURIComponent(created.taskId)}/service-angles/select`, {
|
|
23071
|
+
angleIds: [
|
|
23072
|
+
first.id
|
|
23073
|
+
]
|
|
23074
|
+
});
|
|
23075
|
+
}
|
|
23076
|
+
return asText({
|
|
23077
|
+
taskId: created.taskId,
|
|
23078
|
+
status: replayed ? created.status ?? "processing" : "processing",
|
|
23079
|
+
...replayed ? {
|
|
23080
|
+
replayed: true
|
|
23081
|
+
} : {},
|
|
23082
|
+
reviewMode: input.reviewMode,
|
|
23083
|
+
selectedConcept: first
|
|
23084
|
+
});
|
|
23085
|
+
}
|
|
23086
|
+
if (replayed && created.status !== "queued") {
|
|
23087
|
+
return asText({
|
|
23088
|
+
taskId: created.taskId,
|
|
23089
|
+
status: created.status,
|
|
23090
|
+
replayed: true,
|
|
23091
|
+
reviewMode: input.reviewMode,
|
|
23092
|
+
angles
|
|
23058
23093
|
});
|
|
23059
23094
|
}
|
|
23060
23095
|
return asText({
|
|
23061
23096
|
taskId: created.taskId,
|
|
23062
|
-
status:
|
|
23097
|
+
status: "waiting_for_user",
|
|
23063
23098
|
...replayed ? {
|
|
23064
23099
|
replayed: true
|
|
23065
23100
|
} : {},
|
|
23066
23101
|
reviewMode: input.reviewMode,
|
|
23067
|
-
|
|
23068
|
-
|
|
23069
|
-
|
|
23070
|
-
|
|
23071
|
-
return asText({
|
|
23072
|
-
taskId: created.taskId,
|
|
23073
|
-
status: created.status,
|
|
23074
|
-
replayed: true,
|
|
23075
|
-
reviewMode: input.reviewMode,
|
|
23076
|
-
angles
|
|
23102
|
+
pendingUserAction: {
|
|
23103
|
+
kind: "service_angle_approval",
|
|
23104
|
+
angles
|
|
23105
|
+
}
|
|
23077
23106
|
});
|
|
23107
|
+
} catch (e) {
|
|
23108
|
+
throw translateError(e);
|
|
23078
23109
|
}
|
|
23079
|
-
|
|
23080
|
-
|
|
23081
|
-
status: "waiting_for_user",
|
|
23082
|
-
...replayed ? {
|
|
23083
|
-
replayed: true
|
|
23084
|
-
} : {},
|
|
23085
|
-
reviewMode: input.reviewMode,
|
|
23086
|
-
pendingUserAction: {
|
|
23087
|
-
kind: "service_angle_approval",
|
|
23088
|
-
angles
|
|
23089
|
-
}
|
|
23090
|
-
});
|
|
23091
|
-
} catch (e) {
|
|
23092
|
-
throw translateError(e);
|
|
23093
|
-
}
|
|
23094
|
-
});
|
|
23110
|
+
});
|
|
23111
|
+
}
|
|
23095
23112
|
server.registerTool("verify_landing_commerce", {
|
|
23096
23113
|
description: getProductMakerCapabilityModelGuidance("verify_landing_commerce").summary + " Verifica una correcci\xF3n manual de precios, tachados o packs de una landing editable existente. Solo relee Shopify y los recibos externos; no cambia precios, inventario, SKU ni compra una edici\xF3n. Pasa taskId y editId de la edici\xF3n ya conocida; nunca inventes IDs ni pidas repetir el cambio. Devuelve el estado can\xF3nico por proveedor: conserva el aviso pendiente hasta confirmar los valores reales. Solo despu\xE9s de confirmar todos los valores, el servidor puede volver a habilitar la compra. Web guardada no demuestra publicaci\xF3n p\xFAblica ni checkout; muestra las correcciones y enlaces pendientes sin c\xF3digos t\xE9cnicos. La disponibilidad del editor conserva sus permisos actuales.",
|
|
23097
23114
|
inputSchema: {
|
package/dist/stdio.js
CHANGED
|
@@ -15296,44 +15296,58 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
15296
15296
|
"product"
|
|
15297
15297
|
]
|
|
15298
15298
|
),
|
|
15299
|
-
defineCapability(
|
|
15299
|
+
defineCapability(
|
|
15300
|
+
"create_service_video",
|
|
15301
|
+
"c3d81a4f698e01658fa04ebb613a91c8ba43320d21cacda522e72d198036eb21",
|
|
15300
15302
|
"credit_consuming",
|
|
15301
|
-
"
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
"
|
|
15305
|
-
]
|
|
15306
|
-
|
|
15307
|
-
"
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
"
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
"
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
"
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
"
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
"
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
|
|
15329
|
-
"
|
|
15330
|
-
|
|
15331
|
-
|
|
15332
|
-
|
|
15333
|
-
|
|
15334
|
-
|
|
15335
|
-
|
|
15336
|
-
|
|
15303
|
+
"creative",
|
|
15304
|
+
[
|
|
15305
|
+
"credit_consuming",
|
|
15306
|
+
"state_change"
|
|
15307
|
+
],
|
|
15308
|
+
[
|
|
15309
|
+
slot("service_landing", true, [
|
|
15310
|
+
"landingUrl"
|
|
15311
|
+
]),
|
|
15312
|
+
slot("locale", true, [
|
|
15313
|
+
"language"
|
|
15314
|
+
]),
|
|
15315
|
+
slot("service_context", false, [
|
|
15316
|
+
"additionalContext"
|
|
15317
|
+
]),
|
|
15318
|
+
slot("voice", false, [
|
|
15319
|
+
"voiceId"
|
|
15320
|
+
]),
|
|
15321
|
+
slot("brand", false, [
|
|
15322
|
+
"brandId"
|
|
15323
|
+
]),
|
|
15324
|
+
slot("review_mode", false, [
|
|
15325
|
+
"reviewMode"
|
|
15326
|
+
]),
|
|
15327
|
+
slot("video_preset", false, [
|
|
15328
|
+
"videoPreset"
|
|
15329
|
+
]),
|
|
15330
|
+
// MCP-only for now: WhatsApp's service flow keeps the economy default.
|
|
15331
|
+
slot("video_quality", false, [
|
|
15332
|
+
"videoQuality"
|
|
15333
|
+
], []),
|
|
15334
|
+
slot("video_resolution", false, [
|
|
15335
|
+
"videoResolution"
|
|
15336
|
+
], [])
|
|
15337
|
+
],
|
|
15338
|
+
[
|
|
15339
|
+
"service_context"
|
|
15340
|
+
],
|
|
15341
|
+
[
|
|
15342
|
+
"task",
|
|
15343
|
+
"video"
|
|
15344
|
+
],
|
|
15345
|
+
// Owner decision 2026-10-08: the presenter service video is hidden from the
|
|
15346
|
+
// MCP for now — dropshipping sellers ordered it for products and cancelled.
|
|
15347
|
+
// MCP clients get `create_animated_video` instead. Flip back to
|
|
15348
|
+
// SHARED_CHANNEL_EXPOSURE to restore it.
|
|
15349
|
+
WHATSAPP_ONLY_CHANNEL_EXPOSURE
|
|
15350
|
+
),
|
|
15337
15351
|
defineCapability("edit_image_creative", "50eca473829328dfb63b9cbae03a9835b79c510e29528563e09b7eb3e5e9bca4", "credit_consuming", "creative", [
|
|
15338
15352
|
"credit_consuming",
|
|
15339
15353
|
"state_change"
|
|
@@ -18121,7 +18135,7 @@ var ApiClient = class {
|
|
|
18121
18135
|
};
|
|
18122
18136
|
|
|
18123
18137
|
// src/index.ts
|
|
18124
|
-
var MCP_VERSION = "
|
|
18138
|
+
var MCP_VERSION = "9.0.0";
|
|
18125
18139
|
|
|
18126
18140
|
// src/meta-upload-app.ts
|
|
18127
18141
|
import { readFileSync } from "fs";
|
|
@@ -20723,7 +20737,7 @@ function renderAnimatedVideoStatus(result) {
|
|
|
20723
20737
|
__name(renderAnimatedVideoStatus, "renderAnimatedVideoStatus");
|
|
20724
20738
|
function registerAnimatedVideoTools(server, api) {
|
|
20725
20739
|
server.registerTool("create_animated_video", {
|
|
20726
|
-
description: guidance.summary + ` Hace un video animado (motion graphics) de un SERVICIO a partir del enlace de su p\xE1gina: textos, formas y la identidad visual del sitio, con m\xFAsica y efectos, sin presentador ni voz en off. Esta acci\xF3n consume cr\xE9ditos: confirma formato, duraci\xF3n, idioma y precio con el usuario antes de llamarla. Precio fijo por duraci\xF3n: ${describeAnimatedVideoPrices()}; si falla, se devuelve. Tarda varios minutos, m\xE1s si hay otros videos en la cola. Devuelve un taskId: sigue el avance con get_task_status (etapa, posici\xF3n en la cola, % de render, lo que va haciendo y vista previa) hasta done, que trae el enlace del MP4, o error, que trae el motivo.
|
|
20740
|
+
description: guidance.summary + ` Hace un video animado (motion graphics) de un SERVICIO a partir del enlace de su p\xE1gina: textos, formas y la identidad visual del sitio, con m\xFAsica y efectos, sin presentador ni voz en off. Esta acci\xF3n consume cr\xE9ditos: confirma formato, duraci\xF3n, idioma y precio con el usuario antes de llamarla. Precio fijo por duraci\xF3n: ${describeAnimatedVideoPrices()}; si falla, se devuelve. Tarda varios minutos, m\xE1s si hay otros videos en la cola. Devuelve un taskId: sigue el avance con get_task_status (etapa, posici\xF3n en la cola, % de render, lo que va haciendo y vista previa) hasta done, que trae el enlace del MP4, o error, que trae el motivo. Es el \xFAnico video de servicio disponible por ahora: no ofrezcas un video con presentador. Puede no estar disponible para todas las cuentas: si responde que la funci\xF3n no est\xE1 disponible, dilo y no ofrezcas alternativas pagadas.`,
|
|
20727
20741
|
inputSchema: CreateAnimatedVideoInput.shape,
|
|
20728
20742
|
annotations: CREATES_PAID_OPEN_WORLD
|
|
20729
20743
|
}, async (input) => {
|
|
@@ -20828,7 +20842,7 @@ function renderCreateProductTaskAvoidWhenForMcp(fragment) {
|
|
|
20828
20842
|
__name(renderCreateProductTaskAvoidWhenForMcp, "renderCreateProductTaskAvoidWhenForMcp");
|
|
20829
20843
|
var createProductTaskDefaultDescription = renderCreateProductTaskDefaultForMcp(createProductTaskGuidance.defaults[0]);
|
|
20830
20844
|
var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenForMcp(createProductTaskGuidance.avoidWhen[0]);
|
|
20831
|
-
var
|
|
20845
|
+
var CREATE_SERVICE_VIDEO_ON_MCP = PRODUCTMAKER_MCP_CAPABILITY_NAMES.includes("create_service_video");
|
|
20832
20846
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
20833
20847
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
20834
20848
|
var CreateProductTaskInput = z86.object({
|
|
@@ -21263,7 +21277,7 @@ async function fetchAnimatedVideoResult(api, taskId, signal, serviceMode = void
|
|
|
21263
21277
|
}
|
|
21264
21278
|
}
|
|
21265
21279
|
__name(fetchAnimatedVideoResult, "fetchAnimatedVideoResult");
|
|
21266
|
-
function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http" } = {}) {
|
|
21280
|
+
function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http", serviceVideo = CREATE_SERVICE_VIDEO_ON_MCP } = {}) {
|
|
21267
21281
|
server.registerTool("create_product_task", {
|
|
21268
21282
|
description: createProductTaskGuidance.summary + ` ${createProductTaskDefaultDescription} \xDAsala cuando el usuario pide todo o varios outputs, no creando tareas individuales. Usa images para solicitudes directas. Usa projectId \xFAnicamente si el usuario pidi\xF3 expl\xEDcitamente continuar el proyecto guiado que acaba de costear; nunca busques, infieras ni menciones proyectos previos.
|
|
21269
21283
|
|
|
@@ -21386,97 +21400,100 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
21386
21400
|
throw translateError(e);
|
|
21387
21401
|
}
|
|
21388
21402
|
});
|
|
21389
|
-
|
|
21390
|
-
|
|
21391
|
-
|
|
21392
|
-
|
|
21393
|
-
|
|
21394
|
-
|
|
21395
|
-
|
|
21396
|
-
|
|
21397
|
-
|
|
21398
|
-
|
|
21399
|
-
|
|
21400
|
-
|
|
21401
|
-
|
|
21402
|
-
|
|
21403
|
-
|
|
21404
|
-
|
|
21405
|
-
|
|
21406
|
-
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
|
|
21410
|
-
|
|
21411
|
-
|
|
21412
|
-
|
|
21413
|
-
|
|
21414
|
-
|
|
21415
|
-
|
|
21416
|
-
|
|
21417
|
-
|
|
21418
|
-
|
|
21419
|
-
|
|
21420
|
-
|
|
21421
|
-
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
|
|
21428
|
-
|
|
21429
|
-
|
|
21430
|
-
|
|
21431
|
-
|
|
21432
|
-
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
|
|
21436
|
-
|
|
21437
|
-
|
|
21438
|
-
if (
|
|
21439
|
-
|
|
21440
|
-
|
|
21441
|
-
|
|
21442
|
-
|
|
21403
|
+
if (serviceVideo) {
|
|
21404
|
+
const createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
21405
|
+
server.registerTool("create_service_video", {
|
|
21406
|
+
description: createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.",
|
|
21407
|
+
inputSchema: CreateServiceVideoInput.shape,
|
|
21408
|
+
annotations: CREATES_PAID_OPEN_WORLD
|
|
21409
|
+
}, async (input) => {
|
|
21410
|
+
try {
|
|
21411
|
+
if (input.videoQuality === "medium" && input.videoResolution === "720p") {
|
|
21412
|
+
throw mcp(McpErrorCode.INVALID_INPUT, 'videoResolution "720p" no est\xE1 disponible con videoQuality "medium" en videos de servicio (Medio = 768P). Usa "480p" o elige "economy"/"pro".');
|
|
21413
|
+
}
|
|
21414
|
+
await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
|
|
21415
|
+
const created = await api.postJson("/v2/ingest", {
|
|
21416
|
+
taskType: "service",
|
|
21417
|
+
serviceLandingUrl: input.landingUrl,
|
|
21418
|
+
...input.additionalContext ? {
|
|
21419
|
+
additionalContext: input.additionalContext
|
|
21420
|
+
} : {},
|
|
21421
|
+
lang: input.language,
|
|
21422
|
+
...input.voiceId ? {
|
|
21423
|
+
voiceId: input.voiceId
|
|
21424
|
+
} : {},
|
|
21425
|
+
videoPreset: input.videoPreset,
|
|
21426
|
+
videoQuality: input.videoQuality,
|
|
21427
|
+
videoResolution: input.videoResolution,
|
|
21428
|
+
reviewMode: input.reviewMode,
|
|
21429
|
+
...input.brandId ? {
|
|
21430
|
+
brandId: input.brandId
|
|
21431
|
+
} : {},
|
|
21432
|
+
media: {
|
|
21433
|
+
assets: []
|
|
21434
|
+
},
|
|
21435
|
+
appDemoVideos: []
|
|
21436
|
+
}, {
|
|
21437
|
+
// The 2026-09-25 incident: four retries of this exact tool created
|
|
21438
|
+
// four charged service tasks because the host rephrased
|
|
21439
|
+
// `additionalContext` and flipped the landing between `/` and
|
|
21440
|
+
// `/es`. The derived key is stable across both rewrites (see
|
|
21441
|
+
// request-key.ts).
|
|
21442
|
+
idempotencyKey: derivePaidRequestKey({
|
|
21443
|
+
fingerprint: api.fingerprint(),
|
|
21444
|
+
tool: "create_service_video",
|
|
21445
|
+
input,
|
|
21446
|
+
nowMs: Date.now()
|
|
21447
|
+
})
|
|
21448
|
+
});
|
|
21449
|
+
const angles = await api.postJson(`/v1/tasks/${encodeURIComponent(created.taskId)}/service-angles`, {});
|
|
21450
|
+
const first = angles[0];
|
|
21451
|
+
const replayed = created.replayed === true;
|
|
21452
|
+
if (input.reviewMode === "automatic") {
|
|
21453
|
+
if (!first) throw new Error("ProductMaker no pudo crear un concepto para este servicio.");
|
|
21454
|
+
if (!(replayed && created.status !== "queued")) {
|
|
21455
|
+
await api.postJson(`/v1/tasks/${encodeURIComponent(created.taskId)}/service-angles/select`, {
|
|
21456
|
+
angleIds: [
|
|
21457
|
+
first.id
|
|
21458
|
+
]
|
|
21459
|
+
});
|
|
21460
|
+
}
|
|
21461
|
+
return asText({
|
|
21462
|
+
taskId: created.taskId,
|
|
21463
|
+
status: replayed ? created.status ?? "processing" : "processing",
|
|
21464
|
+
...replayed ? {
|
|
21465
|
+
replayed: true
|
|
21466
|
+
} : {},
|
|
21467
|
+
reviewMode: input.reviewMode,
|
|
21468
|
+
selectedConcept: first
|
|
21469
|
+
});
|
|
21470
|
+
}
|
|
21471
|
+
if (replayed && created.status !== "queued") {
|
|
21472
|
+
return asText({
|
|
21473
|
+
taskId: created.taskId,
|
|
21474
|
+
status: created.status,
|
|
21475
|
+
replayed: true,
|
|
21476
|
+
reviewMode: input.reviewMode,
|
|
21477
|
+
angles
|
|
21443
21478
|
});
|
|
21444
21479
|
}
|
|
21445
21480
|
return asText({
|
|
21446
21481
|
taskId: created.taskId,
|
|
21447
|
-
status:
|
|
21482
|
+
status: "waiting_for_user",
|
|
21448
21483
|
...replayed ? {
|
|
21449
21484
|
replayed: true
|
|
21450
21485
|
} : {},
|
|
21451
21486
|
reviewMode: input.reviewMode,
|
|
21452
|
-
|
|
21453
|
-
|
|
21454
|
-
|
|
21455
|
-
|
|
21456
|
-
return asText({
|
|
21457
|
-
taskId: created.taskId,
|
|
21458
|
-
status: created.status,
|
|
21459
|
-
replayed: true,
|
|
21460
|
-
reviewMode: input.reviewMode,
|
|
21461
|
-
angles
|
|
21487
|
+
pendingUserAction: {
|
|
21488
|
+
kind: "service_angle_approval",
|
|
21489
|
+
angles
|
|
21490
|
+
}
|
|
21462
21491
|
});
|
|
21492
|
+
} catch (e) {
|
|
21493
|
+
throw translateError(e);
|
|
21463
21494
|
}
|
|
21464
|
-
|
|
21465
|
-
|
|
21466
|
-
status: "waiting_for_user",
|
|
21467
|
-
...replayed ? {
|
|
21468
|
-
replayed: true
|
|
21469
|
-
} : {},
|
|
21470
|
-
reviewMode: input.reviewMode,
|
|
21471
|
-
pendingUserAction: {
|
|
21472
|
-
kind: "service_angle_approval",
|
|
21473
|
-
angles
|
|
21474
|
-
}
|
|
21475
|
-
});
|
|
21476
|
-
} catch (e) {
|
|
21477
|
-
throw translateError(e);
|
|
21478
|
-
}
|
|
21479
|
-
});
|
|
21495
|
+
});
|
|
21496
|
+
}
|
|
21480
21497
|
server.registerTool("verify_landing_commerce", {
|
|
21481
21498
|
description: getProductMakerCapabilityModelGuidance("verify_landing_commerce").summary + " Verifica una correcci\xF3n manual de precios, tachados o packs de una landing editable existente. Solo relee Shopify y los recibos externos; no cambia precios, inventario, SKU ni compra una edici\xF3n. Pasa taskId y editId de la edici\xF3n ya conocida; nunca inventes IDs ni pidas repetir el cambio. Devuelve el estado can\xF3nico por proveedor: conserva el aviso pendiente hasta confirmar los valores reales. Solo despu\xE9s de confirmar todos los valores, el servidor puede volver a habilitar la compra. Web guardada no demuestra publicaci\xF3n p\xFAblica ni checkout; muestra las correcciones y enlaces pendientes sin c\xF3digos t\xE9cnicos. La disponibilidad del editor conserva sus permisos actuales.",
|
|
21482
21499
|
inputSchema: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "ProductMaker MCP server — cost products, generate landing pages, UGC videos, and ad creatives, and publish to Shopify, Meta Ads, and TikTok Ads.",
|