@productmaker/mcp 2.10.1 → 3.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 +7 -15
- package/dist/http.js +145 -192
- package/dist/stdio.js +145 -192
- package/dist/ui/meta-upload-app.html +17 -74
- package/package.json +3 -3
|
@@ -1179,15 +1179,10 @@
|
|
|
1179
1179
|
const mediaKind = candidate.mediaKind;
|
|
1180
1180
|
const assetRole = candidate.assetRole;
|
|
1181
1181
|
const expiresAt = boundedString(candidate.expiresAt, 100);
|
|
1182
|
-
const checkToolName =
|
|
1183
|
-
"check_media_upload",
|
|
1184
|
-
"check_meta_media_upload",
|
|
1185
|
-
].includes(candidate.checkToolName)
|
|
1186
|
-
? candidate.checkToolName
|
|
1187
|
-
: "check_meta_media_upload";
|
|
1182
|
+
const checkToolName = "check_media_upload";
|
|
1188
1183
|
const resolveEndpoint =
|
|
1189
1184
|
boundedString(candidate.resolveEndpoint, 200) ||
|
|
1190
|
-
"/api/
|
|
1185
|
+
"/api/upload-media/resolve";
|
|
1191
1186
|
if (!sessionId || !["image", "video", "mixed"].includes(mediaKind))
|
|
1192
1187
|
return null;
|
|
1193
1188
|
if (!["media", "thumbnail"].includes(assetRole)) return null;
|
|
@@ -1480,7 +1475,7 @@
|
|
|
1480
1475
|
"warning",
|
|
1481
1476
|
);
|
|
1482
1477
|
renderItems();
|
|
1483
|
-
emitAnalytics("
|
|
1478
|
+
emitAnalytics("mcp_media_upload_error", mediaKind, {
|
|
1484
1479
|
failureStage: "bridge",
|
|
1485
1480
|
errorType: "bridge_download_failed",
|
|
1486
1481
|
});
|
|
@@ -1564,18 +1559,18 @@
|
|
|
1564
1559
|
inspection.mediaKind === "image"
|
|
1565
1560
|
? await compressImage(item.file, inspection)
|
|
1566
1561
|
: item.file;
|
|
1567
|
-
emitAnalytics("
|
|
1562
|
+
emitAnalytics("mcp_media_upload_started", item.mediaKind);
|
|
1568
1563
|
await uploadWithRetries(item);
|
|
1569
1564
|
item.status = "uploaded";
|
|
1570
1565
|
item.progress = 100;
|
|
1571
1566
|
item.error = "";
|
|
1572
|
-
emitAnalytics("
|
|
1567
|
+
emitAnalytics("mcp_media_upload_completed", item.mediaKind);
|
|
1573
1568
|
} catch (error) {
|
|
1574
1569
|
const failure = safeFailure(error);
|
|
1575
1570
|
item.status = "failed";
|
|
1576
1571
|
item.error = failure.message;
|
|
1577
1572
|
item.failureStage = failure.stage;
|
|
1578
|
-
emitAnalytics("
|
|
1573
|
+
emitAnalytics("mcp_media_upload_error", item.mediaKind, {
|
|
1579
1574
|
failureStage: failure.stage,
|
|
1580
1575
|
errorType: failure.code,
|
|
1581
1576
|
});
|
|
@@ -1901,10 +1896,7 @@
|
|
|
1901
1896
|
const body = await response.json();
|
|
1902
1897
|
if (!isRecord(body)) throw new Error("invalid_resolve_response");
|
|
1903
1898
|
const uploadUrl = boundedString(body.uploadUrl, 3000);
|
|
1904
|
-
const assetId = boundedString(
|
|
1905
|
-
body.assetId || body.stagingAssetId,
|
|
1906
|
-
300,
|
|
1907
|
-
);
|
|
1899
|
+
const assetId = boundedString(body.assetId, 300);
|
|
1908
1900
|
const parsedUploadUrl = new URL(uploadUrl);
|
|
1909
1901
|
if (!safeWebProtocol(parsedUploadUrl) || !assetId) {
|
|
1910
1902
|
const error = new Error("invalid_resolve_response");
|
|
@@ -2203,21 +2195,14 @@
|
|
|
2203
2195
|
state.session.sessionId !== requestedSessionId
|
|
2204
2196
|
)
|
|
2205
2197
|
return;
|
|
2206
|
-
const status = parseStatusResult(result
|
|
2198
|
+
const status = parseStatusResult(result);
|
|
2207
2199
|
state.assets = status.assets;
|
|
2208
2200
|
renderCompletionAction();
|
|
2209
2201
|
if (!status.assets.length) {
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
);
|
|
2215
|
-
} else {
|
|
2216
|
-
requireFallback(
|
|
2217
|
-
"La sesión sigue pendiente. Continúa desde el enlace seguro para terminar la carga.",
|
|
2218
|
-
"warning",
|
|
2219
|
-
);
|
|
2220
|
-
}
|
|
2202
|
+
requireFallback(
|
|
2203
|
+
"La sesión sigue pendiente. Continúa desde el enlace seguro para terminar la carga.",
|
|
2204
|
+
"warning",
|
|
2205
|
+
);
|
|
2221
2206
|
return;
|
|
2222
2207
|
}
|
|
2223
2208
|
|
|
@@ -2255,9 +2240,7 @@
|
|
|
2255
2240
|
}
|
|
2256
2241
|
|
|
2257
2242
|
async function callReadOnlyTool(name, args) {
|
|
2258
|
-
if (
|
|
2259
|
-
!["check_media_upload", "check_meta_media_upload"].includes(name)
|
|
2260
|
-
) {
|
|
2243
|
+
if (name !== "check_media_upload") {
|
|
2261
2244
|
throw new Error("tool_not_allowed");
|
|
2262
2245
|
}
|
|
2263
2246
|
const bridge = openAiBridge();
|
|
@@ -2302,58 +2285,22 @@
|
|
|
2302
2285
|
return parsed;
|
|
2303
2286
|
}
|
|
2304
2287
|
|
|
2305
|
-
function parseStatusResult(result
|
|
2288
|
+
function parseStatusResult(result) {
|
|
2306
2289
|
const payload = resultPayload(result);
|
|
2307
|
-
if (
|
|
2308
|
-
state.session.checkToolName === "check_meta_media_upload" &&
|
|
2309
|
-
payload.sessionId !== expectedSessionId
|
|
2310
|
-
)
|
|
2311
|
-
throw new Error("status_session_mismatch");
|
|
2312
2290
|
const status = payload.status;
|
|
2313
2291
|
if (!["pending", "uploaded"].includes(status))
|
|
2314
2292
|
throw new Error("invalid_status");
|
|
2315
2293
|
const assets = Array.isArray(payload.assets)
|
|
2316
2294
|
? payload.assets.slice(0, MAX_FILES).flatMap((asset) => {
|
|
2317
2295
|
if (!isRecord(asset)) return [];
|
|
2318
|
-
const assetId = boundedString(
|
|
2319
|
-
asset.assetId || asset.stagingAssetId,
|
|
2320
|
-
300,
|
|
2321
|
-
);
|
|
2296
|
+
const assetId = boundedString(asset.assetId, 300);
|
|
2322
2297
|
const mediaKind = asset.mediaKind;
|
|
2323
2298
|
return assetId && ["image", "video"].includes(mediaKind)
|
|
2324
2299
|
? [{ assetId, mediaKind }]
|
|
2325
2300
|
: [];
|
|
2326
2301
|
})
|
|
2327
2302
|
: [];
|
|
2328
|
-
|
|
2329
|
-
const legacyStagingAssetId = boundedString(
|
|
2330
|
-
payload.stagingAssetId,
|
|
2331
|
-
300,
|
|
2332
|
-
);
|
|
2333
|
-
if (!assets.length && legacyStagingAssetId) {
|
|
2334
|
-
const localKinds = new Set(
|
|
2335
|
-
state.items
|
|
2336
|
-
.filter((item) => item.status === "uploaded")
|
|
2337
|
-
.map((item) => item.mediaKind)
|
|
2338
|
-
.filter((mediaKind) => ["image", "video"].includes(mediaKind)),
|
|
2339
|
-
);
|
|
2340
|
-
const inferredMediaKind =
|
|
2341
|
-
localKinds.size === 1
|
|
2342
|
-
? Array.from(localKinds)[0]
|
|
2343
|
-
: localKinds.size === 0 &&
|
|
2344
|
-
["image", "video"].includes(state.session.mediaKind)
|
|
2345
|
-
? state.session.mediaKind
|
|
2346
|
-
: null;
|
|
2347
|
-
if (inferredMediaKind) {
|
|
2348
|
-
assets.push({
|
|
2349
|
-
assetId: legacyStagingAssetId,
|
|
2350
|
-
mediaKind: inferredMediaKind,
|
|
2351
|
-
});
|
|
2352
|
-
} else {
|
|
2353
|
-
legacyKindAmbiguous = true;
|
|
2354
|
-
}
|
|
2355
|
-
}
|
|
2356
|
-
return { status, assets, legacyKindAmbiguous };
|
|
2303
|
+
return { status, assets };
|
|
2357
2304
|
}
|
|
2358
2305
|
|
|
2359
2306
|
async function notifyChatUploadComplete() {
|
|
@@ -2370,11 +2317,7 @@
|
|
|
2370
2317
|
const assets = state.assets
|
|
2371
2318
|
.map((asset) => `${asset.mediaKind} asset_id ${asset.assetId}`)
|
|
2372
2319
|
.join(", ");
|
|
2373
|
-
const
|
|
2374
|
-
state.session.checkToolName === "check_meta_media_upload"
|
|
2375
|
-
? " Do not publish anything until you have asked me for the Meta portfolio, ad account, and Facebook Page."
|
|
2376
|
-
: "";
|
|
2377
|
-
const message = `The ProductMaker upload is complete. Continue my previous request using these uploaded assets: ${assets}. Do not ask me to upload them again.${metaGuard}`;
|
|
2320
|
+
const message = `The ProductMaker upload is complete. Continue my previous request using these uploaded assets: ${assets}. Do not ask me to upload them again. Ask only for the remaining inputs required by my original request.`;
|
|
2378
2321
|
try {
|
|
2379
2322
|
const bridge = openAiBridge();
|
|
2380
2323
|
if (bridge && typeof bridge.sendFollowUpMessage === "function") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.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.",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"typescript": "^7.0.2",
|
|
66
66
|
"vitest": "^2.1.9",
|
|
67
67
|
"@packages/product-economics": "0.1.0",
|
|
68
|
-
"@packages/
|
|
69
|
-
"@packages/
|
|
68
|
+
"@packages/types": "0.1.0",
|
|
69
|
+
"@packages/product-research": "0.1.0"
|
|
70
70
|
},
|
|
71
71
|
"publishConfig": {
|
|
72
72
|
"access": "public"
|