@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.
@@ -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/meta-upload/resolve";
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("ads_meta_remote_upload_error", mediaKind, {
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("ads_meta_remote_upload_started", item.mediaKind);
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("ads_meta_remote_upload_completed", item.mediaKind);
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("ads_meta_remote_upload_error", item.mediaKind, {
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, requestedSessionId);
2198
+ const status = parseStatusResult(result);
2207
2199
  state.assets = status.assets;
2208
2200
  renderCompletionAction();
2209
2201
  if (!status.assets.length) {
2210
- if (status.legacyKindAmbiguous) {
2211
- requireFallback(
2212
- "El tipo del asset legacy es ambiguo. Vuelve a comprobar o usa el enlace seguro.",
2213
- "warning",
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, expectedSessionId) {
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
- let legacyKindAmbiguous = false;
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 metaGuard =
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": "2.10.1",
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/product-research": "0.1.0",
69
- "@packages/types": "0.1.0"
68
+ "@packages/types": "0.1.0",
69
+ "@packages/product-research": "0.1.0"
70
70
  },
71
71
  "publishConfig": {
72
72
  "access": "public"