@wix/mcp 1.0.92 → 1.0.93

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.
@@ -10714,9 +10714,12 @@ var runSemanticSearch = async (toolName, toolParams, maxResults = 20, rerank = f
10714
10714
  );
10715
10715
  return data?.results;
10716
10716
  };
10717
- var runPlatformizedSemanticSearch = async (toolName, searchTerm, maxResults = 20, linesInEachResult) => {
10717
+ var runPlatformizedSemanticSearch = async (toolName, searchTerm, maxResults = 20, linesInEachResult, extraDocumentTypes) => {
10718
10718
  const startTime = Date.now();
10719
- logger.log(`[SemanticSearch/v2] Tool: ${toolName}, Query: "${searchTerm}"`);
10719
+ const documentTypes = extraDocumentTypes?.length ? [toolName, ...extraDocumentTypes] : void 0;
10720
+ logger.log(
10721
+ `[SemanticSearch/v2] Tool: ${documentTypes ? documentTypes.join("+") : toolName}, Query: "${searchTerm}"`
10722
+ );
10720
10723
  const response = await fetch(
10721
10724
  "https://www.wixapis.com/mcp-docs-search/v1/docs/search/markdown",
10722
10725
  {
@@ -10727,7 +10730,7 @@ var runPlatformizedSemanticSearch = async (toolName, searchTerm, maxResults = 20
10727
10730
  },
10728
10731
  body: JSON.stringify({
10729
10732
  search_term: searchTerm,
10730
- document_type: toolName,
10733
+ ...documentTypes ? { document_types: documentTypes } : { document_type: toolName },
10731
10734
  maximum_results: maxResults,
10732
10735
  lines_in_each_result: linesInEachResult
10733
10736
  })
@@ -10756,14 +10759,16 @@ var runSemanticSearchAndFormat = async ({
10756
10759
  maxResults = DEFAULT_MAX_RESULTS,
10757
10760
  rerank,
10758
10761
  linesInEachResult,
10759
- usePlatformizedSearch = true
10762
+ usePlatformizedSearch = true,
10763
+ extraDocumentTypes
10760
10764
  }) => {
10761
10765
  if (usePlatformizedSearch) {
10762
10766
  return runPlatformizedSemanticSearch(
10763
10767
  toolName,
10764
10768
  toolParams.searchTerm,
10765
10769
  maxResults,
10766
- linesInEachResult
10770
+ linesInEachResult,
10771
+ extraDocumentTypes
10767
10772
  );
10768
10773
  } else {
10769
10774
  const results = await runSemanticSearch(
@@ -12305,13 +12310,14 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
12305
12310
  unzip(input: string | Uint8Array): Promise<Array<{ path: string; bytes: Uint8Array; text(): string }>>;
12306
12311
  };
12307
12312
  declare const siteId: string | undefined;
12308
- // Files from the ExecuteWixAPI \`files\` param. Text entries have \`content\`;
12309
- // an entry tagged \`=== FILE: <path> base64 ===\` has encoding:'base64' and
12310
- // base64 \`content\` (a binary file — image, font).
12313
+ // Files from the ExecuteWixAPI \`files\` param, followed by the resolved
12314
+ // \`attachments\`. Text entries have \`content\`; an entry tagged
12315
+ // \`=== FILE: <path> base64 ===\` — and every attachment, path = its file name —
12316
+ // has encoding:'base64' and base64 \`content\`.
12311
12317
  declare const files: Array<{ path: string; content: string; encoding?: "base64" }>;
12312
12318
  \`\`\`
12313
12319
 
12314
- FILE UPLOADS: put every file in the \`files\` param (never inline in \`code\`). Text goes raw; a small binary (icon, logo, font) rides as a \`base64\`-tagged entry — large images/video are referenced by URL (\`<img src="https://...">\`), not bundled. \`wix.multipart()\` turns the whole set into one upload body (bytes, so binary is safe):
12320
+ FILE UPLOADS: files never go inline in \`code\`; two params feed the \`files\` global. \`attachments\` takes files attached in the chat or created in your file sandbox, of any type and size up to 10 MB per call (a zip of a whole site, HTML, images, PDFs): pass the files themselves, all in one call, and the platform resolves each into \`{ download_url, file_id, file_name?, mime_type? }\` — the bytes are fetched for you and arrive as base64 entries named by file name. The \`files\` param takes content you have as text here: text goes raw; a small binary (icon, logo, font) rides as a \`base64\`-tagged entry — large images/video are referenced by URL (\`<img src="https://...">\`), not bundled. \`wix.multipart()\` turns the whole set into one upload body (bytes, so binary is safe):
12315
12321
  \`\`\`javascript
12316
12322
  // files param:
12317
12323
  // === FILE: index.html ===
@@ -12326,6 +12332,12 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
12326
12332
  return res.data;
12327
12333
  }
12328
12334
  \`\`\`
12335
+ A site zip passed through \`attachments\` is one base64 entry; unzip it and upload the entries:
12336
+ \`\`\`javascript
12337
+ // attachments: [site.zip] → files = [{ path: "site.zip", content: "<base64>", encoding: "base64" }]
12338
+ const entries = await wix.unzip(files[0].content); // [{ path, bytes, text() }]
12339
+ const mp = wix.multipart(entries);
12340
+ \`\`\`
12329
12341
  DOWNLOAD + EDIT + RE-UPLOAD: fetch the zip as base64, \`wix.unzip()\` it, edit text via \`entry.text()\`, keep binary as bytes, and hand the entries back to \`wix.multipart()\`:
12330
12342
  \`\`\`javascript
12331
12343
  const r = await wix.request({ scope: "account", method: "GET", responseType: "base64", url: zipUrl });
@@ -12530,12 +12542,12 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
12530
12542
  NEVER call this tool with a missing, empty, or guessed siteId — ask first instead.
12531
12543
 
12532
12544
  Parameters — provide image input via image and/or imageUrls, OR imageBase64:
12533
- • image (array): chat file ATTACHMENTS. Each item is an object with download_url and file_id (both required), plus optional file_name and mime_type. Pass ALL attachments in one call.
12545
+ • image (array): chat file ATTACHMENTS — files the user attached, or files you created in your own file sandbox. Each item is an object with download_url and file_id (both required), plus optional file_name and mime_type. Pass ALL attachments in one call.
12534
12546
  • imageUrls (array): plain public image URLs the user pasted or other tools produced (no file_id). Pass ALL URLs in one call. Can be combined with image.
12535
12547
  • imageBase64 (string): base64-encoded image + mimeType. One image at a time. Do NOT combine with image/imageUrls.
12536
12548
 
12537
12549
  Delivering the bytes — this is where uploads most often fail:
12538
- • NEVER pass a local or sandbox file path (e.g. /mnt/..., /home/user/..., /Users/...) in any field — the server cannot reach your filesystem. Use a public http(s) URL (imageUrls) or the complete base64 (imageBase64).
12550
+ • Pass a file as a file, in image: the platform resolves it into download_url and file_id before it reaches this tool — this includes files you created in your sandbox. This server does not share your filesystem, so a bare path string (e.g. /mnt/..., /home/user/..., /Users/...) is not a file. Without a file to pass, use a public http(s) URL (imageUrls) or the complete base64 (imageBase64).
12539
12551
  • imageBase64 must be the WHOLE file, not truncated. For large images prefer imageUrls, since long base64 is easily cut off and will be rejected as unreadable.
12540
12552
  `,
12541
12553
  SupportAndFeedback: dedent_default`
@@ -13787,7 +13799,7 @@ var paramDescriptions = {
13787
13799
  },
13788
13800
  SearchWixRESTDocumentation: {
13789
13801
  searchTerm: `The search term to look up in the Wix REST API Documentation \u2014 a natural-language description of the endpoint, resource, or action you need across any Wix domain (Stores, eCommerce, Bookings, CRM, Members, CMS, Events, Blog, Forms, Media, site settings, etc.), e.g. "create a catalog item with inventory", "book a service", "update data collection items". Match the wording to how many entities you will act on: a plural term ("update products") surfaces the resource's bulk methods, which a singular term ("update a product") ranks lower or leaves out. Results are ranked by relevance, so describe the goal rather than guessing an exact API name.`,
13790
- maxResults: "The maximum number of results to return, default is 10, max is 15",
13802
+ maxResults: "The maximum number of results to return (1\u201317, default 17). Results mix REST API documentation with matching recipes and skills.",
13791
13803
  reason: "One sentence describing the original user request and the task you are trying to accomplish with this search."
13792
13804
  },
13793
13805
  WixBusinessFlowsDocumentation: {
@@ -13808,7 +13820,7 @@ var paramDescriptions = {
13808
13820
  },
13809
13821
  SearchWixHeadlessDocumentation: {
13810
13822
  searchTerm: "The search term to search for in the Headless Documentation",
13811
- maxResults: "The maximum number of results to return, default is 10, max is 15"
13823
+ maxResults: "The maximum number of results to return (1\u201317, default 17). Results mix Headless documentation with matching recipes and skills."
13812
13824
  },
13813
13825
  SearchWixVeloDocumentation: {
13814
13826
  searchTerm: "The search term to search for in the Velo Documentation",
@@ -13836,7 +13848,7 @@ var paramDescriptions = {
13836
13848
  },
13837
13849
  UploadImageToWixSite: {
13838
13850
  siteId: "The ID (UUID) of the Wix site to upload to. REQUIRED. If the user has not clearly specified which site, ASK them which site to upload to (or use ListWixSites to help them pick) BEFORE calling this tool. NEVER call this tool with a missing, empty, placeholder, or guessed siteId \u2014 ask first instead.",
13839
- image: "Array of file ATTACHMENTS the user uploaded in the chat. Each item requires download_url and file_id, and may optionally include file_name and mime_type \u2014 attached files are automatically resolved to these fields by the platform, so just include them here. For plain image URLs the user pasted, use imageUrls instead. ALWAYS pass ALL attachments together in a single call \u2014 NEVER call this tool once per image. Do NOT use together with imageBase64.",
13851
+ image: "Array of file ATTACHMENTS: files the user uploaded in the chat, or files you created in your own file sandbox. Each item requires download_url and file_id, and may optionally include file_name and mime_type \u2014 the platform resolves a file passed here into these fields automatically, so just include the files. For plain image URLs the user pasted, use imageUrls instead. ALWAYS pass ALL attachments together in a single call \u2014 NEVER call this tool once per image. Do NOT use together with imageBase64.",
13840
13852
  imageUrls: "Array of publicly accessible image URLs (e.g. links the user pasted or URLs produced by other tools). Use this for plain URLs that are NOT chat attachments \u2014 no file_id is needed. ALWAYS pass ALL URLs together in a single call. Can be combined with image; do NOT use together with imageBase64.",
13841
13853
  imageBase64: 'Base64-encoded image data. Use when the client can read a file and encode it as base64. May include a data URL prefix (e.g. "data:image/jpeg;base64,...") or be raw base64. Do NOT use together with image.',
13842
13854
  mimeType: 'MIME type of the image (e.g. "image/jpeg", "image/png", "image/webp"). Required when imageBase64 does not include a data URL prefix.',
@@ -14495,7 +14507,7 @@ var addDocsTools = (server, allowedTools = [
14495
14507
  const d = desc("SearchWixRESTDocumentation");
14496
14508
  return {
14497
14509
  searchTerm: external_exports.string().describe(d.searchTerm),
14498
- maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15),
14510
+ maxResults: external_exports.number().describe(d.maxResults).min(1).max(17).optional().default(17),
14499
14511
  reason: external_exports.string().describe(d.reason)
14500
14512
  };
14501
14513
  })(),
@@ -14510,9 +14522,12 @@ var addDocsTools = (server, allowedTools = [
14510
14522
  toolParams: {
14511
14523
  searchTerm
14512
14524
  },
14513
- maxResults: Math.max(1, Math.min(maxResults ?? 15, 15)),
14525
+ maxResults: Math.max(1, Math.min(maxResults ?? 17, 17)),
14514
14526
  linesInEachResult: 30,
14515
- usePlatformizedSearch
14527
+ usePlatformizedSearch,
14528
+ // Merge recipes/skills into the REST ranking — they live in a
14529
+ // separate corpus the REST document_type doesn't cover on its own.
14530
+ extraDocumentTypes: ["SKILLS"]
14516
14531
  });
14517
14532
  const grounding = result.includes(QUERY_CAPABILITY_MARKER) ? [
14518
14533
  REST_SEARCH_API_GROUNDING_REMINDER,
@@ -14775,7 +14790,7 @@ var addDocsTools = (server, allowedTools = [
14775
14790
  const d = desc("SearchWixHeadlessDocumentation");
14776
14791
  return {
14777
14792
  searchTerm: external_exports.string().describe(d.searchTerm),
14778
- maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
14793
+ maxResults: external_exports.number().describe(d.maxResults).min(1).max(17).optional().default(17)
14779
14794
  };
14780
14795
  })(),
14781
14796
  { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
@@ -14787,8 +14802,11 @@ var addDocsTools = (server, allowedTools = [
14787
14802
  toolParams: {
14788
14803
  searchTerm
14789
14804
  },
14790
- maxResults: Math.max(1, Math.min(maxResults ?? 15, 15)),
14791
- usePlatformizedSearch
14805
+ maxResults: Math.max(1, Math.min(maxResults ?? 17, 17)),
14806
+ usePlatformizedSearch,
14807
+ // Merge recipes/skills into the headless ranking — same separate
14808
+ // corpus the WIX_HEADLESS document_type doesn't cover on its own.
14809
+ extraDocumentTypes: ["SKILLS"]
14792
14810
  });
14793
14811
  return {
14794
14812
  content: [
@@ -16705,6 +16723,189 @@ ${text.slice(0, 2e3)}`
16705
16723
  );
16706
16724
  }
16707
16725
 
16726
+ // src/code-mode/attachments.ts
16727
+ var MAX_ATTACHMENTS_BYTES = 10 * 1024 * 1024;
16728
+ var MAX_REDIRECTS = 4;
16729
+ var OAI_USERCONTENT_HOST = /^[a-z0-9-]+\.oaiusercontent\.com$/;
16730
+ var OAI_BLOB_ACCOUNTS = new Set(
16731
+ [
16732
+ "australiaeast",
16733
+ "brazilsouth",
16734
+ "cacentral",
16735
+ "centralindia",
16736
+ "centralus",
16737
+ "centralusdr",
16738
+ "denmarkeast",
16739
+ "eastus",
16740
+ "eastus2",
16741
+ "indiasocentral",
16742
+ "italynorth",
16743
+ "japaneast",
16744
+ "koreacentral",
16745
+ "northcentralus",
16746
+ "northeu",
16747
+ "nznorth",
16748
+ "polandcentral",
16749
+ "seasia",
16750
+ "southcentralus",
16751
+ "southeastus3",
16752
+ "ukwest",
16753
+ "westcentralus",
16754
+ "westus",
16755
+ "westus2",
16756
+ "westus3"
16757
+ ].map((region) => `oaisdmntpr${region}.blob.core.windows.net`)
16758
+ );
16759
+ function isAllowedAttachmentHost(hostname) {
16760
+ const h = hostname.toLowerCase();
16761
+ return OAI_USERCONTENT_HOST.test(h) || OAI_BLOB_ACCOUNTS.has(h);
16762
+ }
16763
+ function checkAttachmentUrl(url) {
16764
+ if (url.protocol !== "https:") return "is not an https URL";
16765
+ if (url.port) return "uses a non-default port";
16766
+ if (!isAllowedAttachmentHost(url.hostname)) {
16767
+ return `host "${url.hostname}" is not a ChatGPT file host`;
16768
+ }
16769
+ return void 0;
16770
+ }
16771
+ var AttachmentError = class extends Error {
16772
+ };
16773
+ function attachmentPath(a, url) {
16774
+ let fromUrl = "";
16775
+ try {
16776
+ fromUrl = decodeURIComponent(
16777
+ url.pathname.split("/").filter(Boolean).pop() ?? ""
16778
+ );
16779
+ } catch {
16780
+ fromUrl = "";
16781
+ }
16782
+ const raw = (a.file_name?.trim() || fromUrl || a.file_id).replace(/\\/g, "/");
16783
+ const segments = raw.split("/").filter((s) => s && s !== "." && s !== "..");
16784
+ return segments.join("/") || a.file_id;
16785
+ }
16786
+ function toBase64(bytes) {
16787
+ let binary = "";
16788
+ const chunk = 32768;
16789
+ for (let i = 0; i < bytes.length; i += chunk) {
16790
+ binary += String.fromCharCode(...bytes.subarray(i, i + chunk));
16791
+ }
16792
+ return btoa(binary);
16793
+ }
16794
+ async function fetchAllowed(start, fetchImpl, label) {
16795
+ let url = start;
16796
+ for (let hop = 0; ; hop++) {
16797
+ const res = await fetchImpl(url.toString(), { redirect: "manual" });
16798
+ const location = res.headers.get("location");
16799
+ const isRedirect = res.status >= 300 && res.status < 400 && location;
16800
+ if (!isRedirect) return res;
16801
+ await res.body?.cancel().catch(() => void 0);
16802
+ if (hop >= MAX_REDIRECTS) {
16803
+ throw new AttachmentError(`${label}: too many redirects.`);
16804
+ }
16805
+ let next;
16806
+ try {
16807
+ next = new URL(location, url);
16808
+ } catch {
16809
+ throw new AttachmentError(`${label}: redirect to an invalid URL.`);
16810
+ }
16811
+ const problem = checkAttachmentUrl(next);
16812
+ if (problem) {
16813
+ throw new AttachmentError(
16814
+ `${label}: the download redirected to a URL that ${problem}; refused.`
16815
+ );
16816
+ }
16817
+ url = next;
16818
+ }
16819
+ }
16820
+ async function readWithin(res, budget, overBudget) {
16821
+ const declared = Number(res.headers.get("content-length") ?? 0);
16822
+ if (declared > budget) throw overBudget();
16823
+ if (!res.body) {
16824
+ const bytes = new Uint8Array(await res.arrayBuffer());
16825
+ if (bytes.byteLength > budget) throw overBudget();
16826
+ return bytes;
16827
+ }
16828
+ const reader = res.body.getReader();
16829
+ const chunks = [];
16830
+ let total = 0;
16831
+ for (; ; ) {
16832
+ const { done, value } = await reader.read();
16833
+ if (done) break;
16834
+ total += value.byteLength;
16835
+ if (total > budget) {
16836
+ await reader.cancel().catch(() => void 0);
16837
+ throw overBudget();
16838
+ }
16839
+ chunks.push(value);
16840
+ }
16841
+ const out = new Uint8Array(total);
16842
+ let offset = 0;
16843
+ for (const c of chunks) {
16844
+ out.set(c, offset);
16845
+ offset += c.byteLength;
16846
+ }
16847
+ return out;
16848
+ }
16849
+ async function resolveAttachments(attachments, fetchImpl = fetch) {
16850
+ if (!Array.isArray(attachments) || attachments.length === 0) return [];
16851
+ const items = [];
16852
+ attachments.forEach((raw, i) => {
16853
+ const a = typeof raw === "object" && raw;
16854
+ const downloadUrl = a && typeof a.download_url === "string" ? a.download_url : "";
16855
+ let url;
16856
+ try {
16857
+ url = /^https?:\/\//i.test(downloadUrl) ? new URL(downloadUrl) : void 0;
16858
+ } catch {
16859
+ url = void 0;
16860
+ }
16861
+ if (!a || !url) {
16862
+ throw new AttachmentError(
16863
+ `attachments[${i}] was not resolved to a download URL (got ${JSON.stringify(
16864
+ typeof raw === "string" ? raw : (a && a.download_url) ?? raw
16865
+ )}). The platform did not hydrate this attachment; retry once, and if it still arrives like this put the file in the \`files\` bundle instead (\`=== FILE: <path> base64 ===\` for binary).`
16866
+ );
16867
+ }
16868
+ const problem = checkAttachmentUrl(url);
16869
+ if (problem) {
16870
+ throw new AttachmentError(
16871
+ `attachments[${i}].download_url ${problem}. Only platform-resolved attachments are accepted here; for any other URL fetch it in \`code\` via wix.request or put the bytes in the \`files\` bundle.`
16872
+ );
16873
+ }
16874
+ items.push({ a, url });
16875
+ });
16876
+ let remaining = MAX_ATTACHMENTS_BYTES;
16877
+ const out = [];
16878
+ for (const [i, { a, url }] of items.entries()) {
16879
+ const path = attachmentPath(a, url);
16880
+ const label = `attachments[${i}] (${path})`;
16881
+ let res;
16882
+ try {
16883
+ res = await fetchAllowed(url, fetchImpl, label);
16884
+ } catch (e) {
16885
+ if (e instanceof AttachmentError) throw e;
16886
+ throw new AttachmentError(
16887
+ `${label}: download failed (${e.message}).`
16888
+ );
16889
+ }
16890
+ if (!res.ok) {
16891
+ await res.body?.cancel().catch(() => void 0);
16892
+ throw new AttachmentError(
16893
+ `${label}: download returned HTTP ${res.status}. The download_url may have expired; attach the file again.`
16894
+ );
16895
+ }
16896
+ const bytes = await readWithin(
16897
+ res,
16898
+ remaining,
16899
+ () => new AttachmentError(
16900
+ `${label} pushes the attachments past ${MAX_ATTACHMENTS_BYTES} bytes in total for this call; split the upload across calls.`
16901
+ )
16902
+ );
16903
+ remaining -= bytes.byteLength;
16904
+ out.push({ path, content: toBase64(bytes), encoding: "base64" });
16905
+ }
16906
+ return out;
16907
+ }
16908
+
16708
16909
  // src/code-mode/validation.ts
16709
16910
  var EXECUTE_FUNCTION_EXPRESSION_HINT = 'ExecuteWixAPI code must be a function expression, not a script body. Pass code like: async () => { const response = await wix.request({ scope: "site", method: "GET", url: "https://www.wixapis.com/..." }); return response.data; }. Do not write top-level const/await/return outside the function and do not invoke the function yourself.';
16710
16911
  function validateExecuteCode(code) {
@@ -16916,7 +17117,7 @@ function addExecuteTool(server, options) {
16916
17117
  } = options;
16917
17118
  const executeUrl = `${codeModeBaseUrl}/api/code-mode/execute`;
16918
17119
  const d = desc("ExecuteWixAPI");
16919
- server.tool(
17120
+ const registered = server.tool(
16920
17121
  EXECUTE_TOOL_NAME,
16921
17122
  toolDescriptions?.[EXECUTE_TOOL_NAME] ?? defaultToolDescriptions.ExecuteWixAPI,
16922
17123
  {
@@ -16945,6 +17146,20 @@ function addExecuteTool(server, options) {
16945
17146
  'Use base64 entries for small assets (icons, logos, fonts) and for files you downloaded and are re-uploading; large images/video go in by URL (`<img src="https://...">`), not in the bundle. A file containing a line exactly like the delimiter is not supported.'
16946
17147
  ].join(" ")
16947
17148
  ),
17149
+ // ChatGPT file attachments (`openai/fileParams`). Item shape must match
17150
+ // OpenAI's file schema: download_url + file_id required, the rest optional.
17151
+ // Declaring it is what makes the platform hand us a download URL instead
17152
+ // of a sandbox path. Resolved host-side into base64 `files` entries.
17153
+ attachments: external_exports.array(
17154
+ external_exports.object({
17155
+ download_url: external_exports.string(),
17156
+ file_id: external_exports.string(),
17157
+ file_name: external_exports.string().optional(),
17158
+ mime_type: external_exports.string().optional()
17159
+ })
17160
+ ).optional().describe(
17161
+ 'Files attached in this chat, or files you created in your own file sandbox (any type: a zip of a site, HTML, images, PDFs). Pass the files themselves and the platform resolves each into { download_url, file_id, file_name?, mime_type? }; the bytes are fetched here and appended to the `files` global as { path, content, encoding: "base64" } entries (path = file_name), so `wix.multipart()` and `wix.unzip()` work on them unchanged. Prefer this over base64 in `files` whenever you have a file handle. Up to 10 MB per call.'
17162
+ ),
16948
17163
  // Visitor mode takes an agent-supplied token and pins the site; account/site
16949
17164
  // mode lets the agent pick the site.
16950
17165
  ...visitor ? {
@@ -16959,7 +17174,15 @@ function addExecuteTool(server, options) {
16959
17174
  },
16960
17175
  { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
16961
17176
  async (rawArgs, extra) => {
16962
- const { code, reason, hasMutations, sourceDocUrls, visitorToken, files } = rawArgs;
17177
+ const {
17178
+ code,
17179
+ reason,
17180
+ hasMutations,
17181
+ sourceDocUrls,
17182
+ visitorToken,
17183
+ files,
17184
+ attachments
17185
+ } = rawArgs;
16963
17186
  const siteId = visitor ? visitor.siteId : rawArgs.siteId;
16964
17187
  logger.log(
16965
17188
  `[ExecuteWixAPI]${visitor ? " (visitor)" : ""} Executing code (${code.length} chars), siteId=${siteId ?? "none"}, hasMutations=${hasMutations}, sourceDocUrls=${JSON.stringify(sourceDocUrls)}, reason="${reason}"`
@@ -16971,6 +17194,13 @@ function addExecuteTool(server, options) {
16971
17194
  );
16972
17195
  return executeTextResult(validation.error);
16973
17196
  }
17197
+ let attachmentFiles = [];
17198
+ try {
17199
+ attachmentFiles = await resolveAttachments(attachments);
17200
+ } catch (e) {
17201
+ if (e instanceof AttachmentError) return executeErrorResult(e.message);
17202
+ throw e;
17203
+ }
16974
17204
  const accountHeaders = await authStrategy?.getAccountAuthHeaders();
16975
17205
  const siteAuthContext = !visitor && authStrategy?.getSiteAuthContext ? await authStrategy.getSiteAuthContext() : void 0;
16976
17206
  let siteHeaders;
@@ -17005,7 +17235,8 @@ function addExecuteTool(server, options) {
17005
17235
  accountToken: visitor ? visitorToken : accountHeaders?.Authorization,
17006
17236
  accountId: accountHeaders?.["wix-account-id"],
17007
17237
  siteAuthContext,
17008
- ...files ? { files } : {}
17238
+ ...files ? { files } : {},
17239
+ ...attachmentFiles.length ? { attachmentFiles } : {}
17009
17240
  },
17010
17241
  visitor ? visitorToken : accountHeaders?.Authorization ?? siteHeaders?.Authorization,
17011
17242
  codeModeFetch
@@ -17036,6 +17267,9 @@ function addExecuteTool(server, options) {
17036
17267
  }
17037
17268
  }
17038
17269
  );
17270
+ registered?.update?.({
17271
+ _meta: { ...registered._meta, "openai/fileParams": ["attachments"] }
17272
+ });
17039
17273
  }
17040
17274
 
17041
17275
  // ../../node_modules/@wix/panorama-common-shared/dist/esm/types/enum-types.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/mcp",
3
- "version": "1.0.92",
3
+ "version": "1.0.93",
4
4
  "description": "A Model Context Protocol server for Wix AI tools",
5
5
  "bin": "./build/bin-standalone.js",
6
6
  "dependencies": {
@@ -133,5 +133,5 @@
133
133
  ]
134
134
  }
135
135
  },
136
- "falconPackageHash": "54656e5ebcb80096bd722cc5f9776c97996d45e5c6701b4288e04af9"
136
+ "falconPackageHash": "416cbd091ed4f59d7a920a4a98434246c6a211bf9c981dd78ad9a627"
137
137
  }