@productmaker/mcp 2.1.0 → 2.2.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 +120 -24
- package/dist/stdio.js +120 -24
- package/package.json +2 -2
package/dist/http.js
CHANGED
|
@@ -153,7 +153,7 @@ var ApiClient = class {
|
|
|
153
153
|
};
|
|
154
154
|
|
|
155
155
|
// src/index.ts
|
|
156
|
-
var MCP_VERSION = "2.
|
|
156
|
+
var MCP_VERSION = "2.2.0";
|
|
157
157
|
|
|
158
158
|
// src/tools/tasks.ts
|
|
159
159
|
import { z as z40 } from "zod";
|
|
@@ -1424,11 +1424,12 @@ var IngestOptions = z13.object({
|
|
|
1424
1424
|
* shorter than the generated angle count leaves the remaining positions
|
|
1425
1425
|
* auto-selected. Empty/omitted → all angles auto-select as before. */
|
|
1426
1426
|
angleNarratives: z13.array(NarrativeStyle).max(3).optional(),
|
|
1427
|
-
//
|
|
1428
|
-
//
|
|
1427
|
+
// 480p is the recommended default for every tier (flipped back 2026-07-30 — the
|
|
1428
|
+
// 720p premium is real but small, and users on the entry plan were defaulting
|
|
1429
|
+
// into it while burning half a month of credits on one video).
|
|
1429
1430
|
// This Zod default is what callers that omit the field (MCP/API) actually get,
|
|
1430
|
-
// so it must agree with resolveSingleCallAwareResolution's unset fallback (
|
|
1431
|
-
videoResolution: VideoResolution.default("
|
|
1431
|
+
// so it must agree with resolveSingleCallAwareResolution's unset fallback (480p).
|
|
1432
|
+
videoResolution: VideoResolution.default("480p"),
|
|
1432
1433
|
generateAdCopy: z13.boolean().default(true),
|
|
1433
1434
|
generateAiMusic: z13.boolean().optional(),
|
|
1434
1435
|
voiceId: VoiceId.optional(),
|
|
@@ -1543,9 +1544,9 @@ var IngestResumePayload = z13.object({
|
|
|
1543
1544
|
videoModel: VideoModel.default("veo"),
|
|
1544
1545
|
videoTier: VideoTier.optional(),
|
|
1545
1546
|
narrativeStyle: NarrativeStyle.default("review"),
|
|
1546
|
-
//
|
|
1547
|
-
// with IngestOptions.videoResolution and resolveSingleCallAwareResolution.
|
|
1548
|
-
videoResolution: VideoResolution.default("
|
|
1547
|
+
// 480p is the recommended default for every tier (flipped back 2026-07-30) — keep in
|
|
1548
|
+
// sync with IngestOptions.videoResolution and resolveSingleCallAwareResolution.
|
|
1549
|
+
videoResolution: VideoResolution.default("480p"),
|
|
1549
1550
|
pauseForVideoScriptReview: z13.boolean().optional(),
|
|
1550
1551
|
generateAiMusic: z13.boolean().optional(),
|
|
1551
1552
|
scriptNotes: z13.string().max(2e3).optional(),
|
|
@@ -5004,16 +5005,37 @@ var DEFAULT_PRICING = {
|
|
|
5004
5005
|
ourCostCents: 0.15,
|
|
5005
5006
|
userPriceCents: 0.3
|
|
5006
5007
|
},
|
|
5007
|
-
// Video QA —
|
|
5008
|
-
//
|
|
5009
|
-
//
|
|
5010
|
-
// (
|
|
5011
|
-
//
|
|
5012
|
-
//
|
|
5008
|
+
// Video QA — anatomy. THREE keys, and they do NOT share a unit. Getting this wrong
|
|
5009
|
+
// over-charges by ~42x, which is exactly what a first pass at the 2026-07-30 change did.
|
|
5010
|
+
//
|
|
5011
|
+
// (a) The arm-scan's per-FRAME counting sweep. STILL LIVE on the whole-video concat path
|
|
5012
|
+
// (`scanClipArms` at apps/api/src/workers/core/video-concat-core.ts), which bills
|
|
5013
|
+
// units:1 PER SAMPLED FRAME, up to ARM_SCAN_FRAME_CEILING. Rate must stay per-frame.
|
|
5014
|
+
// Sized above the 30d prod average (10303 rows => 0.132c user/frame).
|
|
5013
5015
|
"openrouter:video-anatomy-arm-scan": {
|
|
5014
5016
|
ourCostCents: 0.1,
|
|
5015
5017
|
userPriceCents: 0.2
|
|
5016
5018
|
},
|
|
5019
|
+
// (b) The frame JUDGE that replaced the sweep on the `analyzeVideoClipDJ` path: ALL frames
|
|
5020
|
+
// in ONE multi-image call, so a unit is one call. MEASURED, not estimated —
|
|
5021
|
+
// usage.cost on a real 16-frame judgement at 768px is $0.0417 => 4.17c our. The table is
|
|
5022
|
+
// the FALLBACK used when OpenRouter omits usage.cost, so it must sit at or above that.
|
|
5023
|
+
// Billed PER FRAME (units = frames in the call), like the sweep and for the same reason:
|
|
5024
|
+
// the cost scales with IMAGES and QA_FRAME_JUDGE_FRAMES is env-overridable, so a per-CALL
|
|
5025
|
+
// unit would freeze the fallback charge and the credit-gate quote at the cap the rate
|
|
5026
|
+
// happened to be measured at. Measured $0.0417 over 16 frames => 0.26c/frame; priced at
|
|
5027
|
+
// 0.32c for headroom (n=1 on one clip, and the 1.9k reasoning-token share moves with
|
|
5028
|
+
// QA_DETECTOR_EFFORT). Re-derive from 30d of BillingEntry once this key has volume.
|
|
5029
|
+
"openrouter:video-qa-anatomy-frame-judge": {
|
|
5030
|
+
ourCostCents: 0.32,
|
|
5031
|
+
userPriceCents: 0.64
|
|
5032
|
+
},
|
|
5033
|
+
// (c) Tracing confirmation of a frames-only finding: 3 stills + a 3s 480p slice, one call,
|
|
5034
|
+
// no 16-image prompt — materially cheaper than the judgement it verifies.
|
|
5035
|
+
"openrouter:video-qa-anatomy-tracing-confirm": {
|
|
5036
|
+
ourCostCents: 1.5,
|
|
5037
|
+
userPriceCents: 3
|
|
5038
|
+
},
|
|
5017
5039
|
// Physics confirmation — skeptical second opinion on D+J floating-object flags
|
|
5018
5040
|
// (Gemini 3 Flash Preview, ~3 frames per flagged moment, 1 call). Aligned with other vision-QA keys.
|
|
5019
5041
|
"openrouter:video-physics-confirmation": {
|
|
@@ -6566,6 +6588,36 @@ var DropshippingProjectStatusSchema = z37.enum([
|
|
|
6566
6588
|
"completed",
|
|
6567
6589
|
"archived"
|
|
6568
6590
|
]);
|
|
6591
|
+
var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
|
|
6592
|
+
var DropshippingRewardMilestoneSchema = z37.enum([
|
|
6593
|
+
"product_selected",
|
|
6594
|
+
"costing_saved",
|
|
6595
|
+
"product_media_ready",
|
|
6596
|
+
"creatives_completed",
|
|
6597
|
+
"campaign_created"
|
|
6598
|
+
]);
|
|
6599
|
+
var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
|
|
6600
|
+
product_selected: 50,
|
|
6601
|
+
costing_saved: 50,
|
|
6602
|
+
product_media_ready: 50,
|
|
6603
|
+
creatives_completed: 150,
|
|
6604
|
+
campaign_created: 200
|
|
6605
|
+
};
|
|
6606
|
+
var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
|
|
6607
|
+
var DropshippingProjectRewardMilestoneStateSchema = z37.object({
|
|
6608
|
+
milestone: DropshippingRewardMilestoneSchema,
|
|
6609
|
+
credits: z37.number().int().positive(),
|
|
6610
|
+
available: z37.boolean().optional(),
|
|
6611
|
+
earned: z37.boolean(),
|
|
6612
|
+
grantId: z37.string().uuid().nullable(),
|
|
6613
|
+
grantedAt: z37.string().datetime().nullable()
|
|
6614
|
+
});
|
|
6615
|
+
var DropshippingProjectRewardProgressSchema = z37.object({
|
|
6616
|
+
campaignKey: z37.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
|
|
6617
|
+
totalCredits: z37.number().int().positive(),
|
|
6618
|
+
earnedCredits: z37.number().int().nonnegative(),
|
|
6619
|
+
milestones: z37.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
|
|
6620
|
+
});
|
|
6569
6621
|
var DropshippingProjectPhaseSchema = z37.enum([
|
|
6570
6622
|
"research",
|
|
6571
6623
|
"costing",
|
|
@@ -6723,6 +6775,7 @@ var DropshippingProjectResponseSchema = z37.object({
|
|
|
6723
6775
|
version: z37.number().int().positive(),
|
|
6724
6776
|
phase: DropshippingProjectPhaseSchema,
|
|
6725
6777
|
nextAction: DropshippingProjectNextActionSchema.nullable(),
|
|
6778
|
+
rewards: DropshippingProjectRewardProgressSchema,
|
|
6726
6779
|
createdAt: z37.string().datetime(),
|
|
6727
6780
|
updatedAt: z37.string().datetime()
|
|
6728
6781
|
});
|
|
@@ -6789,7 +6842,7 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
6789
6842
|
{
|
|
6790
6843
|
name: "create_product_task",
|
|
6791
6844
|
confirmation: "credit_consuming",
|
|
6792
|
-
schemaHash: "
|
|
6845
|
+
schemaHash: "5b19f7c6dfdc55b0c472df045e24fe73aa134624a141b63342bfbd3bbb0d043b"
|
|
6793
6846
|
},
|
|
6794
6847
|
{
|
|
6795
6848
|
name: "edit_task_draft",
|
|
@@ -6814,17 +6867,17 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
6814
6867
|
{
|
|
6815
6868
|
name: "generate_image_creatives",
|
|
6816
6869
|
confirmation: "credit_consuming",
|
|
6817
|
-
schemaHash: "
|
|
6870
|
+
schemaHash: "82b520e8001e9c57ab0a89d9d66ea5dfc92e6306eed302edfe1005cee5025fbf"
|
|
6818
6871
|
},
|
|
6819
6872
|
{
|
|
6820
6873
|
name: "generate_landing",
|
|
6821
6874
|
confirmation: "credit_consuming",
|
|
6822
|
-
schemaHash: "
|
|
6875
|
+
schemaHash: "23f0c56dc719235e51d16fd61a9703b64fa6d300356ffbf6b21d703324b0bb18"
|
|
6823
6876
|
},
|
|
6824
6877
|
{
|
|
6825
6878
|
name: "generate_video_creative",
|
|
6826
6879
|
confirmation: "credit_consuming",
|
|
6827
|
-
schemaHash: "
|
|
6880
|
+
schemaHash: "79d3ec9310885b482d62c94a27e9c039833c0619d9332a593fe7d32a60ae1388"
|
|
6828
6881
|
},
|
|
6829
6882
|
{
|
|
6830
6883
|
name: "get_meta_campaign_status",
|
|
@@ -8107,7 +8160,7 @@ var CreateProductTaskInput = z40.object({
|
|
|
8107
8160
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
8108
8161
|
pauseForAngleReview: z40.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. \xDAsalo si quiere decidir 15/30s cuando aparezca un winner. Default false."),
|
|
8109
8162
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista" para 15s; al pedir durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
|
|
8110
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez
|
|
8163
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez, entre 3% y 15% m\xE1s caro seg\xFAn formato y tier. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
|
|
8111
8164
|
multiAngleVideos: z40.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."),
|
|
8112
8165
|
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar". angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. Requiere multiAngleVideos:true para varios \xE1ngulos.'),
|
|
8113
8166
|
outputs: z40.array(z40.enum([
|
|
@@ -8582,6 +8635,7 @@ var CreativeRefs = {
|
|
|
8582
8635
|
isCombo: z41.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
8583
8636
|
competitorScanEnabled: z41.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
|
|
8584
8637
|
brandId: z41.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo."),
|
|
8638
|
+
projectId: z41.string().uuid().optional().describe("Opcional. ID de un proyecto guiado de dropshipping activo del usuario. Enlaza esta generaci\xF3n con su progreso y recompensas."),
|
|
8585
8639
|
creativeDirection: z41.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Aplica SOLO a im\xE1genes y landing. Ej. im\xE1genes: "amarillo, azul y rojo, minimalista"; landing: "elegante, paleta fr\xEDa". Para video usa scriptNotes (ambiente/escenario). M\xE1x 500 caracteres.')
|
|
8586
8640
|
};
|
|
8587
8641
|
var VideoInput = z41.object({
|
|
@@ -8601,7 +8655,7 @@ var VideoInput = z41.object({
|
|
|
8601
8655
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
8602
8656
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Los presets funcionan a 15s y 30s. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (una regla visual experimental original), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla).'),
|
|
8603
8657
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista"; para durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
|
|
8604
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "
|
|
8658
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez, entre 3% y 15% m\xE1s caro seg\xFAn formato y tier. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
|
|
8605
8659
|
features: z41.array(z41.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
8606
8660
|
price: CreativeRefs.price,
|
|
8607
8661
|
offer: CreativeRefs.offer,
|
|
@@ -8612,7 +8666,8 @@ var VideoInput = z41.object({
|
|
|
8612
8666
|
pauseForVideoScriptReview: z41.boolean().optional().describe("Opcional. Si true, la tarea pausa despu\xE9s de generar el guion y antes de renderizar. \xDAsalo cuando el usuario quiera editar el guion antes de gastar cr\xE9ditos en el video. Tras la pausa: get_video_script para leerlo, approve_video_script para aprobar (con o sin ediciones). Default false."),
|
|
8613
8667
|
pauseForAngleReview: z41.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. Default false."),
|
|
8614
8668
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8615
|
-
brandId: CreativeRefs.brandId
|
|
8669
|
+
brandId: CreativeRefs.brandId,
|
|
8670
|
+
projectId: CreativeRefs.projectId
|
|
8616
8671
|
}).strict();
|
|
8617
8672
|
var FreeVideoQualityEnum = z41.enum([
|
|
8618
8673
|
"economical",
|
|
@@ -8676,6 +8731,7 @@ var ImageInput = z41.object({
|
|
|
8676
8731
|
isCombo: CreativeRefs.isCombo,
|
|
8677
8732
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8678
8733
|
brandId: CreativeRefs.brandId,
|
|
8734
|
+
projectId: CreativeRefs.projectId,
|
|
8679
8735
|
creativeDirection: CreativeRefs.creativeDirection
|
|
8680
8736
|
});
|
|
8681
8737
|
var LandingInput = z41.object({
|
|
@@ -8693,6 +8749,7 @@ var LandingInput = z41.object({
|
|
|
8693
8749
|
isCombo: CreativeRefs.isCombo,
|
|
8694
8750
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8695
8751
|
brandId: CreativeRefs.brandId,
|
|
8752
|
+
projectId: CreativeRefs.projectId,
|
|
8696
8753
|
creativeDirection: CreativeRefs.creativeDirection,
|
|
8697
8754
|
landingStrategy: LandingStrategyEnum.default("classic").describe('Opcional. Estructura de la landing cl\xE1sica: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution" (problema\u2192soluci\xF3n), "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity" (beneficios claros), "offer_value" (promoci\xF3n/valor) o "lifestyle_identity" (estilo de vida). Default "classic".'),
|
|
8698
8755
|
landingImageFormat: LandingImageFormatEnum.default("9:16").describe('Opcional. Formato/relaci\xF3n de aspecto de las im\xE1genes de la landing cl\xE1sica: "9:16" (vertical, por defecto), "4:5" (vertical compacto para feed) o "1:1" (cuadrado). Default "9:16".')
|
|
@@ -8732,7 +8789,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8732
8789
|
try {
|
|
8733
8790
|
const resolved = resolveVideoPreset(input.videoPreset);
|
|
8734
8791
|
const wireTier = resolveWireVideoTier(input.videoTier, input.durationSeconds);
|
|
8735
|
-
const { videoTier: _publicTier, videoResolution: _vr, ...rest } = input;
|
|
8792
|
+
const { videoTier: _publicTier, videoResolution: _vr, projectId, ...rest } = input;
|
|
8736
8793
|
const wirePayload = {
|
|
8737
8794
|
...rest
|
|
8738
8795
|
};
|
|
@@ -8742,6 +8799,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8742
8799
|
}
|
|
8743
8800
|
wirePayload.videoTier = wireTier;
|
|
8744
8801
|
if (input.videoResolution) wirePayload.videoResolution = input.videoResolution;
|
|
8802
|
+
if (projectId) wirePayload.dropshippingProjectId = projectId;
|
|
8745
8803
|
return await submitCreative(api, {
|
|
8746
8804
|
path: "/v1/creatives/videos",
|
|
8747
8805
|
estimatedSeconds: 300,
|
|
@@ -8754,10 +8812,16 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8754
8812
|
});
|
|
8755
8813
|
server.tool("generate_image_creatives", 'Genera N variantes de imagen creativa (ads est\xE1ticos). Devuelve un taskId.\n\nREQUERIDOS: images (array de 1-5 fotos), productTitle, primaryAngle, language, country.\n\nANTES de invocar, PREG\xDANTALE al usuario:\n- price y offer (se renderizan en la imagen \u2014 nunca los asumas; si dice "t\xFA elige", om\xEDtelos).\n- compareAtPrice si hay descuento (ej. "$129.000" para tachar).\n- creativeArchetype y visualTreatment si quiere un look espec\xEDfico (performance vs premium DTC). Si no le importa, om\xEDtelos.\n\nNO defaultes country/language desde el contexto: preg\xFAntale expl\xEDcitamente.\n\nOTROS OPCIONALES: buyerPersona, nVariants (default 3), imageModel, imageStyle, styleMix, aspectRatio (default 4:5), generateAdCopy, pauseForAngleReview, features, brandColors, isCombo, creativeDirection.', ImageInput.shape, async (input) => {
|
|
8756
8814
|
try {
|
|
8815
|
+
const { projectId, ...rest } = input;
|
|
8757
8816
|
return await submitCreative(api, {
|
|
8758
8817
|
path: "/v1/creatives/images",
|
|
8759
8818
|
estimatedSeconds: 60,
|
|
8760
|
-
input
|
|
8819
|
+
input: {
|
|
8820
|
+
...rest,
|
|
8821
|
+
...projectId ? {
|
|
8822
|
+
dropshippingProjectId: projectId
|
|
8823
|
+
} : {}
|
|
8824
|
+
},
|
|
8761
8825
|
transport
|
|
8762
8826
|
});
|
|
8763
8827
|
} catch (e) {
|
|
@@ -8766,10 +8830,16 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8766
8830
|
});
|
|
8767
8831
|
server.tool("generate_landing", 'Genera una landing page cl\xE1sica basada en im\xE1genes, lista para Shopify. Devuelve un taskId.\n\nREQUERIDOS: images (array de 1-5 fotos), language, country.\n\nANTES de invocar, PREG\xDANTALE al usuario por price, offer y paymentMethods si no los mencion\xF3 \u2014 son los inputs de mayor impacto en conversi\xF3n y nunca debes asumirlos. Si hay descuento, pregunta tambi\xE9n compareAtPrice. NO defaultes country/language desde el contexto: preg\xFAntale expl\xEDcitamente. Si el usuario te dice "t\xFA elige" para esos campos, om\xEDtelos.\n\nOTROS OPCIONALES (puedes invocar sin ellos y dejar que la IA elija defaults): salesAngle, buyerPersona, isCombo, creativeDirection, landingStrategy.', LandingInput.shape, async (input) => {
|
|
8768
8832
|
try {
|
|
8833
|
+
const { projectId, ...rest } = input;
|
|
8769
8834
|
return await submitCreative(api, {
|
|
8770
8835
|
path: "/v1/creatives/landing",
|
|
8771
8836
|
estimatedSeconds: 60,
|
|
8772
|
-
input
|
|
8837
|
+
input: {
|
|
8838
|
+
...rest,
|
|
8839
|
+
...projectId ? {
|
|
8840
|
+
dropshippingProjectId: projectId
|
|
8841
|
+
} : {}
|
|
8842
|
+
},
|
|
8773
8843
|
transport
|
|
8774
8844
|
});
|
|
8775
8845
|
} catch (e) {
|
|
@@ -10451,6 +10521,13 @@ var DropshippingProjectPhase = z51.enum([
|
|
|
10451
10521
|
"advertising",
|
|
10452
10522
|
"complete"
|
|
10453
10523
|
]);
|
|
10524
|
+
var DropshippingRewardMilestone = z51.enum([
|
|
10525
|
+
"product_selected",
|
|
10526
|
+
"costing_saved",
|
|
10527
|
+
"product_media_ready",
|
|
10528
|
+
"creatives_completed",
|
|
10529
|
+
"campaign_created"
|
|
10530
|
+
]);
|
|
10454
10531
|
var TargetCountry = z51.enum([
|
|
10455
10532
|
"CO",
|
|
10456
10533
|
"MX",
|
|
@@ -10573,6 +10650,19 @@ var CostingResultSchema = z51.object({
|
|
|
10573
10650
|
wasPriceAutoAdjusted: z51.boolean(),
|
|
10574
10651
|
profitabilityStatus: z51.literal("healthy")
|
|
10575
10652
|
});
|
|
10653
|
+
var RewardProgressSchema = z51.object({
|
|
10654
|
+
campaignKey: z51.literal("dropshipping-launch-v1"),
|
|
10655
|
+
totalCredits: z51.number().int().positive(),
|
|
10656
|
+
earnedCredits: z51.number().int().nonnegative(),
|
|
10657
|
+
milestones: z51.array(z51.object({
|
|
10658
|
+
milestone: DropshippingRewardMilestone,
|
|
10659
|
+
credits: z51.number().int().positive(),
|
|
10660
|
+
available: z51.boolean().optional(),
|
|
10661
|
+
earned: z51.boolean(),
|
|
10662
|
+
grantId: ProjectId.nullable(),
|
|
10663
|
+
grantedAt: z51.string().datetime().nullable()
|
|
10664
|
+
})).length(DropshippingRewardMilestone.options.length)
|
|
10665
|
+
});
|
|
10576
10666
|
var ProjectResponseSchema = z51.object({
|
|
10577
10667
|
id: ProjectId,
|
|
10578
10668
|
taskId: ProjectId.nullable(),
|
|
@@ -10592,6 +10682,7 @@ var ProjectResponseSchema = z51.object({
|
|
|
10592
10682
|
version: z51.number().int().positive(),
|
|
10593
10683
|
phase: DropshippingProjectPhase,
|
|
10594
10684
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
10685
|
+
rewards: RewardProgressSchema,
|
|
10595
10686
|
createdAt: z51.string().datetime(),
|
|
10596
10687
|
updatedAt: z51.string().datetime()
|
|
10597
10688
|
}).passthrough();
|
|
@@ -10609,6 +10700,11 @@ function projectText(raw) {
|
|
|
10609
10700
|
nextAction: project.nextAction,
|
|
10610
10701
|
hasReferenceImage: project.hasReferenceImage,
|
|
10611
10702
|
costingSaved: Boolean(project.costingResult),
|
|
10703
|
+
rewardProgress: {
|
|
10704
|
+
earnedCredits: project.rewards.earnedCredits,
|
|
10705
|
+
totalCredits: project.rewards.totalCredits,
|
|
10706
|
+
milestones: project.rewards.milestones
|
|
10707
|
+
},
|
|
10612
10708
|
version: project.version,
|
|
10613
10709
|
message: `Siguiente paso: ${next}. Relee este proyecto despu\xE9s de cada mutaci\xF3n.`
|
|
10614
10710
|
})
|
package/dist/stdio.js
CHANGED
|
@@ -150,7 +150,7 @@ var ApiClient = class {
|
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
// src/index.ts
|
|
153
|
-
var MCP_VERSION = "2.
|
|
153
|
+
var MCP_VERSION = "2.2.0";
|
|
154
154
|
|
|
155
155
|
// src/tools/tasks.ts
|
|
156
156
|
import { z as z40 } from "zod";
|
|
@@ -1421,11 +1421,12 @@ var IngestOptions = z13.object({
|
|
|
1421
1421
|
* shorter than the generated angle count leaves the remaining positions
|
|
1422
1422
|
* auto-selected. Empty/omitted → all angles auto-select as before. */
|
|
1423
1423
|
angleNarratives: z13.array(NarrativeStyle).max(3).optional(),
|
|
1424
|
-
//
|
|
1425
|
-
//
|
|
1424
|
+
// 480p is the recommended default for every tier (flipped back 2026-07-30 — the
|
|
1425
|
+
// 720p premium is real but small, and users on the entry plan were defaulting
|
|
1426
|
+
// into it while burning half a month of credits on one video).
|
|
1426
1427
|
// This Zod default is what callers that omit the field (MCP/API) actually get,
|
|
1427
|
-
// so it must agree with resolveSingleCallAwareResolution's unset fallback (
|
|
1428
|
-
videoResolution: VideoResolution.default("
|
|
1428
|
+
// so it must agree with resolveSingleCallAwareResolution's unset fallback (480p).
|
|
1429
|
+
videoResolution: VideoResolution.default("480p"),
|
|
1429
1430
|
generateAdCopy: z13.boolean().default(true),
|
|
1430
1431
|
generateAiMusic: z13.boolean().optional(),
|
|
1431
1432
|
voiceId: VoiceId.optional(),
|
|
@@ -1540,9 +1541,9 @@ var IngestResumePayload = z13.object({
|
|
|
1540
1541
|
videoModel: VideoModel.default("veo"),
|
|
1541
1542
|
videoTier: VideoTier.optional(),
|
|
1542
1543
|
narrativeStyle: NarrativeStyle.default("review"),
|
|
1543
|
-
//
|
|
1544
|
-
// with IngestOptions.videoResolution and resolveSingleCallAwareResolution.
|
|
1545
|
-
videoResolution: VideoResolution.default("
|
|
1544
|
+
// 480p is the recommended default for every tier (flipped back 2026-07-30) — keep in
|
|
1545
|
+
// sync with IngestOptions.videoResolution and resolveSingleCallAwareResolution.
|
|
1546
|
+
videoResolution: VideoResolution.default("480p"),
|
|
1546
1547
|
pauseForVideoScriptReview: z13.boolean().optional(),
|
|
1547
1548
|
generateAiMusic: z13.boolean().optional(),
|
|
1548
1549
|
scriptNotes: z13.string().max(2e3).optional(),
|
|
@@ -5001,16 +5002,37 @@ var DEFAULT_PRICING = {
|
|
|
5001
5002
|
ourCostCents: 0.15,
|
|
5002
5003
|
userPriceCents: 0.3
|
|
5003
5004
|
},
|
|
5004
|
-
// Video QA —
|
|
5005
|
-
//
|
|
5006
|
-
//
|
|
5007
|
-
// (
|
|
5008
|
-
//
|
|
5009
|
-
//
|
|
5005
|
+
// Video QA — anatomy. THREE keys, and they do NOT share a unit. Getting this wrong
|
|
5006
|
+
// over-charges by ~42x, which is exactly what a first pass at the 2026-07-30 change did.
|
|
5007
|
+
//
|
|
5008
|
+
// (a) The arm-scan's per-FRAME counting sweep. STILL LIVE on the whole-video concat path
|
|
5009
|
+
// (`scanClipArms` at apps/api/src/workers/core/video-concat-core.ts), which bills
|
|
5010
|
+
// units:1 PER SAMPLED FRAME, up to ARM_SCAN_FRAME_CEILING. Rate must stay per-frame.
|
|
5011
|
+
// Sized above the 30d prod average (10303 rows => 0.132c user/frame).
|
|
5010
5012
|
"openrouter:video-anatomy-arm-scan": {
|
|
5011
5013
|
ourCostCents: 0.1,
|
|
5012
5014
|
userPriceCents: 0.2
|
|
5013
5015
|
},
|
|
5016
|
+
// (b) The frame JUDGE that replaced the sweep on the `analyzeVideoClipDJ` path: ALL frames
|
|
5017
|
+
// in ONE multi-image call, so a unit is one call. MEASURED, not estimated —
|
|
5018
|
+
// usage.cost on a real 16-frame judgement at 768px is $0.0417 => 4.17c our. The table is
|
|
5019
|
+
// the FALLBACK used when OpenRouter omits usage.cost, so it must sit at or above that.
|
|
5020
|
+
// Billed PER FRAME (units = frames in the call), like the sweep and for the same reason:
|
|
5021
|
+
// the cost scales with IMAGES and QA_FRAME_JUDGE_FRAMES is env-overridable, so a per-CALL
|
|
5022
|
+
// unit would freeze the fallback charge and the credit-gate quote at the cap the rate
|
|
5023
|
+
// happened to be measured at. Measured $0.0417 over 16 frames => 0.26c/frame; priced at
|
|
5024
|
+
// 0.32c for headroom (n=1 on one clip, and the 1.9k reasoning-token share moves with
|
|
5025
|
+
// QA_DETECTOR_EFFORT). Re-derive from 30d of BillingEntry once this key has volume.
|
|
5026
|
+
"openrouter:video-qa-anatomy-frame-judge": {
|
|
5027
|
+
ourCostCents: 0.32,
|
|
5028
|
+
userPriceCents: 0.64
|
|
5029
|
+
},
|
|
5030
|
+
// (c) Tracing confirmation of a frames-only finding: 3 stills + a 3s 480p slice, one call,
|
|
5031
|
+
// no 16-image prompt — materially cheaper than the judgement it verifies.
|
|
5032
|
+
"openrouter:video-qa-anatomy-tracing-confirm": {
|
|
5033
|
+
ourCostCents: 1.5,
|
|
5034
|
+
userPriceCents: 3
|
|
5035
|
+
},
|
|
5014
5036
|
// Physics confirmation — skeptical second opinion on D+J floating-object flags
|
|
5015
5037
|
// (Gemini 3 Flash Preview, ~3 frames per flagged moment, 1 call). Aligned with other vision-QA keys.
|
|
5016
5038
|
"openrouter:video-physics-confirmation": {
|
|
@@ -6563,6 +6585,36 @@ var DropshippingProjectStatusSchema = z37.enum([
|
|
|
6563
6585
|
"completed",
|
|
6564
6586
|
"archived"
|
|
6565
6587
|
]);
|
|
6588
|
+
var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
|
|
6589
|
+
var DropshippingRewardMilestoneSchema = z37.enum([
|
|
6590
|
+
"product_selected",
|
|
6591
|
+
"costing_saved",
|
|
6592
|
+
"product_media_ready",
|
|
6593
|
+
"creatives_completed",
|
|
6594
|
+
"campaign_created"
|
|
6595
|
+
]);
|
|
6596
|
+
var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
|
|
6597
|
+
product_selected: 50,
|
|
6598
|
+
costing_saved: 50,
|
|
6599
|
+
product_media_ready: 50,
|
|
6600
|
+
creatives_completed: 150,
|
|
6601
|
+
campaign_created: 200
|
|
6602
|
+
};
|
|
6603
|
+
var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
|
|
6604
|
+
var DropshippingProjectRewardMilestoneStateSchema = z37.object({
|
|
6605
|
+
milestone: DropshippingRewardMilestoneSchema,
|
|
6606
|
+
credits: z37.number().int().positive(),
|
|
6607
|
+
available: z37.boolean().optional(),
|
|
6608
|
+
earned: z37.boolean(),
|
|
6609
|
+
grantId: z37.string().uuid().nullable(),
|
|
6610
|
+
grantedAt: z37.string().datetime().nullable()
|
|
6611
|
+
});
|
|
6612
|
+
var DropshippingProjectRewardProgressSchema = z37.object({
|
|
6613
|
+
campaignKey: z37.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
|
|
6614
|
+
totalCredits: z37.number().int().positive(),
|
|
6615
|
+
earnedCredits: z37.number().int().nonnegative(),
|
|
6616
|
+
milestones: z37.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
|
|
6617
|
+
});
|
|
6566
6618
|
var DropshippingProjectPhaseSchema = z37.enum([
|
|
6567
6619
|
"research",
|
|
6568
6620
|
"costing",
|
|
@@ -6720,6 +6772,7 @@ var DropshippingProjectResponseSchema = z37.object({
|
|
|
6720
6772
|
version: z37.number().int().positive(),
|
|
6721
6773
|
phase: DropshippingProjectPhaseSchema,
|
|
6722
6774
|
nextAction: DropshippingProjectNextActionSchema.nullable(),
|
|
6775
|
+
rewards: DropshippingProjectRewardProgressSchema,
|
|
6723
6776
|
createdAt: z37.string().datetime(),
|
|
6724
6777
|
updatedAt: z37.string().datetime()
|
|
6725
6778
|
});
|
|
@@ -6786,7 +6839,7 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
6786
6839
|
{
|
|
6787
6840
|
name: "create_product_task",
|
|
6788
6841
|
confirmation: "credit_consuming",
|
|
6789
|
-
schemaHash: "
|
|
6842
|
+
schemaHash: "5b19f7c6dfdc55b0c472df045e24fe73aa134624a141b63342bfbd3bbb0d043b"
|
|
6790
6843
|
},
|
|
6791
6844
|
{
|
|
6792
6845
|
name: "edit_task_draft",
|
|
@@ -6811,17 +6864,17 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
6811
6864
|
{
|
|
6812
6865
|
name: "generate_image_creatives",
|
|
6813
6866
|
confirmation: "credit_consuming",
|
|
6814
|
-
schemaHash: "
|
|
6867
|
+
schemaHash: "82b520e8001e9c57ab0a89d9d66ea5dfc92e6306eed302edfe1005cee5025fbf"
|
|
6815
6868
|
},
|
|
6816
6869
|
{
|
|
6817
6870
|
name: "generate_landing",
|
|
6818
6871
|
confirmation: "credit_consuming",
|
|
6819
|
-
schemaHash: "
|
|
6872
|
+
schemaHash: "23f0c56dc719235e51d16fd61a9703b64fa6d300356ffbf6b21d703324b0bb18"
|
|
6820
6873
|
},
|
|
6821
6874
|
{
|
|
6822
6875
|
name: "generate_video_creative",
|
|
6823
6876
|
confirmation: "credit_consuming",
|
|
6824
|
-
schemaHash: "
|
|
6877
|
+
schemaHash: "79d3ec9310885b482d62c94a27e9c039833c0619d9332a593fe7d32a60ae1388"
|
|
6825
6878
|
},
|
|
6826
6879
|
{
|
|
6827
6880
|
name: "get_meta_campaign_status",
|
|
@@ -8063,7 +8116,7 @@ var CreateProductTaskInput = z40.object({
|
|
|
8063
8116
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
8064
8117
|
pauseForAngleReview: z40.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. \xDAsalo si quiere decidir 15/30s cuando aparezca un winner. Default false."),
|
|
8065
8118
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista" para 15s; al pedir durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
|
|
8066
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez
|
|
8119
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez, entre 3% y 15% m\xE1s caro seg\xFAn formato y tier. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
|
|
8067
8120
|
multiAngleVideos: z40.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."),
|
|
8068
8121
|
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar". angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. Requiere multiAngleVideos:true para varios \xE1ngulos.'),
|
|
8069
8122
|
outputs: z40.array(z40.enum([
|
|
@@ -8538,6 +8591,7 @@ var CreativeRefs = {
|
|
|
8538
8591
|
isCombo: z41.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
8539
8592
|
competitorScanEnabled: z41.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
|
|
8540
8593
|
brandId: z41.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo."),
|
|
8594
|
+
projectId: z41.string().uuid().optional().describe("Opcional. ID de un proyecto guiado de dropshipping activo del usuario. Enlaza esta generaci\xF3n con su progreso y recompensas."),
|
|
8541
8595
|
creativeDirection: z41.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Aplica SOLO a im\xE1genes y landing. Ej. im\xE1genes: "amarillo, azul y rojo, minimalista"; landing: "elegante, paleta fr\xEDa". Para video usa scriptNotes (ambiente/escenario). M\xE1x 500 caracteres.')
|
|
8542
8596
|
};
|
|
8543
8597
|
var VideoInput = z41.object({
|
|
@@ -8557,7 +8611,7 @@ var VideoInput = z41.object({
|
|
|
8557
8611
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
8558
8612
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Los presets funcionan a 15s y 30s. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (una regla visual experimental original), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla).'),
|
|
8559
8613
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista"; para durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
|
|
8560
|
-
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "
|
|
8614
|
+
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez, entre 3% y 15% m\xE1s caro seg\xFAn formato y tier. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
|
|
8561
8615
|
features: z41.array(z41.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
8562
8616
|
price: CreativeRefs.price,
|
|
8563
8617
|
offer: CreativeRefs.offer,
|
|
@@ -8568,7 +8622,8 @@ var VideoInput = z41.object({
|
|
|
8568
8622
|
pauseForVideoScriptReview: z41.boolean().optional().describe("Opcional. Si true, la tarea pausa despu\xE9s de generar el guion y antes de renderizar. \xDAsalo cuando el usuario quiera editar el guion antes de gastar cr\xE9ditos en el video. Tras la pausa: get_video_script para leerlo, approve_video_script para aprobar (con o sin ediciones). Default false."),
|
|
8569
8623
|
pauseForAngleReview: z41.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. Default false."),
|
|
8570
8624
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8571
|
-
brandId: CreativeRefs.brandId
|
|
8625
|
+
brandId: CreativeRefs.brandId,
|
|
8626
|
+
projectId: CreativeRefs.projectId
|
|
8572
8627
|
}).strict();
|
|
8573
8628
|
var FreeVideoQualityEnum = z41.enum([
|
|
8574
8629
|
"economical",
|
|
@@ -8632,6 +8687,7 @@ var ImageInput = z41.object({
|
|
|
8632
8687
|
isCombo: CreativeRefs.isCombo,
|
|
8633
8688
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8634
8689
|
brandId: CreativeRefs.brandId,
|
|
8690
|
+
projectId: CreativeRefs.projectId,
|
|
8635
8691
|
creativeDirection: CreativeRefs.creativeDirection
|
|
8636
8692
|
});
|
|
8637
8693
|
var LandingInput = z41.object({
|
|
@@ -8649,6 +8705,7 @@ var LandingInput = z41.object({
|
|
|
8649
8705
|
isCombo: CreativeRefs.isCombo,
|
|
8650
8706
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8651
8707
|
brandId: CreativeRefs.brandId,
|
|
8708
|
+
projectId: CreativeRefs.projectId,
|
|
8652
8709
|
creativeDirection: CreativeRefs.creativeDirection,
|
|
8653
8710
|
landingStrategy: LandingStrategyEnum.default("classic").describe('Opcional. Estructura de la landing cl\xE1sica: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution" (problema\u2192soluci\xF3n), "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity" (beneficios claros), "offer_value" (promoci\xF3n/valor) o "lifestyle_identity" (estilo de vida). Default "classic".'),
|
|
8654
8711
|
landingImageFormat: LandingImageFormatEnum.default("9:16").describe('Opcional. Formato/relaci\xF3n de aspecto de las im\xE1genes de la landing cl\xE1sica: "9:16" (vertical, por defecto), "4:5" (vertical compacto para feed) o "1:1" (cuadrado). Default "9:16".')
|
|
@@ -8688,7 +8745,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8688
8745
|
try {
|
|
8689
8746
|
const resolved = resolveVideoPreset(input.videoPreset);
|
|
8690
8747
|
const wireTier = resolveWireVideoTier(input.videoTier, input.durationSeconds);
|
|
8691
|
-
const { videoTier: _publicTier, videoResolution: _vr, ...rest } = input;
|
|
8748
|
+
const { videoTier: _publicTier, videoResolution: _vr, projectId, ...rest } = input;
|
|
8692
8749
|
const wirePayload = {
|
|
8693
8750
|
...rest
|
|
8694
8751
|
};
|
|
@@ -8698,6 +8755,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8698
8755
|
}
|
|
8699
8756
|
wirePayload.videoTier = wireTier;
|
|
8700
8757
|
if (input.videoResolution) wirePayload.videoResolution = input.videoResolution;
|
|
8758
|
+
if (projectId) wirePayload.dropshippingProjectId = projectId;
|
|
8701
8759
|
return await submitCreative(api, {
|
|
8702
8760
|
path: "/v1/creatives/videos",
|
|
8703
8761
|
estimatedSeconds: 300,
|
|
@@ -8710,10 +8768,16 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8710
8768
|
});
|
|
8711
8769
|
server.tool("generate_image_creatives", 'Genera N variantes de imagen creativa (ads est\xE1ticos). Devuelve un taskId.\n\nREQUERIDOS: images (array de 1-5 fotos), productTitle, primaryAngle, language, country.\n\nANTES de invocar, PREG\xDANTALE al usuario:\n- price y offer (se renderizan en la imagen \u2014 nunca los asumas; si dice "t\xFA elige", om\xEDtelos).\n- compareAtPrice si hay descuento (ej. "$129.000" para tachar).\n- creativeArchetype y visualTreatment si quiere un look espec\xEDfico (performance vs premium DTC). Si no le importa, om\xEDtelos.\n\nNO defaultes country/language desde el contexto: preg\xFAntale expl\xEDcitamente.\n\nOTROS OPCIONALES: buyerPersona, nVariants (default 3), imageModel, imageStyle, styleMix, aspectRatio (default 4:5), generateAdCopy, pauseForAngleReview, features, brandColors, isCombo, creativeDirection.', ImageInput.shape, async (input) => {
|
|
8712
8770
|
try {
|
|
8771
|
+
const { projectId, ...rest } = input;
|
|
8713
8772
|
return await submitCreative(api, {
|
|
8714
8773
|
path: "/v1/creatives/images",
|
|
8715
8774
|
estimatedSeconds: 60,
|
|
8716
|
-
input
|
|
8775
|
+
input: {
|
|
8776
|
+
...rest,
|
|
8777
|
+
...projectId ? {
|
|
8778
|
+
dropshippingProjectId: projectId
|
|
8779
|
+
} : {}
|
|
8780
|
+
},
|
|
8717
8781
|
transport
|
|
8718
8782
|
});
|
|
8719
8783
|
} catch (e) {
|
|
@@ -8722,10 +8786,16 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8722
8786
|
});
|
|
8723
8787
|
server.tool("generate_landing", 'Genera una landing page cl\xE1sica basada en im\xE1genes, lista para Shopify. Devuelve un taskId.\n\nREQUERIDOS: images (array de 1-5 fotos), language, country.\n\nANTES de invocar, PREG\xDANTALE al usuario por price, offer y paymentMethods si no los mencion\xF3 \u2014 son los inputs de mayor impacto en conversi\xF3n y nunca debes asumirlos. Si hay descuento, pregunta tambi\xE9n compareAtPrice. NO defaultes country/language desde el contexto: preg\xFAntale expl\xEDcitamente. Si el usuario te dice "t\xFA elige" para esos campos, om\xEDtelos.\n\nOTROS OPCIONALES (puedes invocar sin ellos y dejar que la IA elija defaults): salesAngle, buyerPersona, isCombo, creativeDirection, landingStrategy.', LandingInput.shape, async (input) => {
|
|
8724
8788
|
try {
|
|
8789
|
+
const { projectId, ...rest } = input;
|
|
8725
8790
|
return await submitCreative(api, {
|
|
8726
8791
|
path: "/v1/creatives/landing",
|
|
8727
8792
|
estimatedSeconds: 60,
|
|
8728
|
-
input
|
|
8793
|
+
input: {
|
|
8794
|
+
...rest,
|
|
8795
|
+
...projectId ? {
|
|
8796
|
+
dropshippingProjectId: projectId
|
|
8797
|
+
} : {}
|
|
8798
|
+
},
|
|
8729
8799
|
transport
|
|
8730
8800
|
});
|
|
8731
8801
|
} catch (e) {
|
|
@@ -10407,6 +10477,13 @@ var DropshippingProjectPhase = z51.enum([
|
|
|
10407
10477
|
"advertising",
|
|
10408
10478
|
"complete"
|
|
10409
10479
|
]);
|
|
10480
|
+
var DropshippingRewardMilestone = z51.enum([
|
|
10481
|
+
"product_selected",
|
|
10482
|
+
"costing_saved",
|
|
10483
|
+
"product_media_ready",
|
|
10484
|
+
"creatives_completed",
|
|
10485
|
+
"campaign_created"
|
|
10486
|
+
]);
|
|
10410
10487
|
var TargetCountry = z51.enum([
|
|
10411
10488
|
"CO",
|
|
10412
10489
|
"MX",
|
|
@@ -10529,6 +10606,19 @@ var CostingResultSchema = z51.object({
|
|
|
10529
10606
|
wasPriceAutoAdjusted: z51.boolean(),
|
|
10530
10607
|
profitabilityStatus: z51.literal("healthy")
|
|
10531
10608
|
});
|
|
10609
|
+
var RewardProgressSchema = z51.object({
|
|
10610
|
+
campaignKey: z51.literal("dropshipping-launch-v1"),
|
|
10611
|
+
totalCredits: z51.number().int().positive(),
|
|
10612
|
+
earnedCredits: z51.number().int().nonnegative(),
|
|
10613
|
+
milestones: z51.array(z51.object({
|
|
10614
|
+
milestone: DropshippingRewardMilestone,
|
|
10615
|
+
credits: z51.number().int().positive(),
|
|
10616
|
+
available: z51.boolean().optional(),
|
|
10617
|
+
earned: z51.boolean(),
|
|
10618
|
+
grantId: ProjectId.nullable(),
|
|
10619
|
+
grantedAt: z51.string().datetime().nullable()
|
|
10620
|
+
})).length(DropshippingRewardMilestone.options.length)
|
|
10621
|
+
});
|
|
10532
10622
|
var ProjectResponseSchema = z51.object({
|
|
10533
10623
|
id: ProjectId,
|
|
10534
10624
|
taskId: ProjectId.nullable(),
|
|
@@ -10548,6 +10638,7 @@ var ProjectResponseSchema = z51.object({
|
|
|
10548
10638
|
version: z51.number().int().positive(),
|
|
10549
10639
|
phase: DropshippingProjectPhase,
|
|
10550
10640
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
10641
|
+
rewards: RewardProgressSchema,
|
|
10551
10642
|
createdAt: z51.string().datetime(),
|
|
10552
10643
|
updatedAt: z51.string().datetime()
|
|
10553
10644
|
}).passthrough();
|
|
@@ -10565,6 +10656,11 @@ function projectText(raw) {
|
|
|
10565
10656
|
nextAction: project.nextAction,
|
|
10566
10657
|
hasReferenceImage: project.hasReferenceImage,
|
|
10567
10658
|
costingSaved: Boolean(project.costingResult),
|
|
10659
|
+
rewardProgress: {
|
|
10660
|
+
earnedCredits: project.rewards.earnedCredits,
|
|
10661
|
+
totalCredits: project.rewards.totalCredits,
|
|
10662
|
+
milestones: project.rewards.milestones
|
|
10663
|
+
},
|
|
10568
10664
|
version: project.version,
|
|
10569
10665
|
message: `Siguiente paso: ${next}. Relee este proyecto despu\xE9s de cada mutaci\xF3n.`
|
|
10570
10666
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Product Maker MCP server — cost products, generate dropshipping landing pages, UGC videos, and ad creatives, and publish to Shopify and Meta Ads from Claude, ChatGPT, or Gemini.",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"tsx": "^4.16.0",
|
|
64
64
|
"typescript": "^7.0.2",
|
|
65
65
|
"vitest": "^2.1.9",
|
|
66
|
-
"@packages/product-research": "0.1.0",
|
|
67
66
|
"@packages/product-economics": "0.1.0",
|
|
67
|
+
"@packages/product-research": "0.1.0",
|
|
68
68
|
"@packages/types": "0.1.0"
|
|
69
69
|
},
|
|
70
70
|
"publishConfig": {
|