@wix/mcp 1.0.93 → 1.0.95

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.
Files changed (84) hide show
  1. package/README.md +2 -2
  2. package/build/bin-standalone.js +1200 -455
  3. package/build/cjs/index.cjs +3237 -1264
  4. package/build/cjs/toolkit.cjs +2177 -469
  5. package/build/dts/api-call/headless-release.d.ts +56 -0
  6. package/build/dts/api-call/headless-release.js +135 -0
  7. package/build/dts/api-call/index.d.ts +9 -1
  8. package/build/dts/api-call/index.js +19 -10
  9. package/build/dts/api-call/site-files.d.ts +42 -0
  10. package/build/dts/api-call/site-files.js +290 -0
  11. package/build/dts/api-call/upload-headless-website-files.d.ts +118 -0
  12. package/build/dts/api-call/upload-headless-website-files.js +624 -0
  13. package/build/dts/api-call/upload-image-tool.d.ts +2 -0
  14. package/build/dts/api-call/upload-image-tool.js +8 -4
  15. package/build/dts/bin.d.ts +1 -1
  16. package/build/dts/bin.js +4 -5
  17. package/build/dts/code-mode/attachments.js +1 -1
  18. package/build/dts/code-mode/index.d.ts +6 -1
  19. package/build/dts/code-mode/index.js +47 -13
  20. package/build/dts/code-mode/truncate-response.js +5 -1
  21. package/build/dts/config/default-config.d.ts +35 -9
  22. package/build/dts/config/default-config.js +348 -207
  23. package/build/dts/config/file-params.d.ts +22 -0
  24. package/build/dts/config/file-params.js +24 -0
  25. package/build/dts/config/param-descriptions.d.ts +14 -2
  26. package/build/dts/config/param-descriptions.js +34 -15
  27. package/build/dts/constants.d.ts +1 -0
  28. package/build/dts/constants.js +1 -0
  29. package/build/dts/docs/docs.d.ts +16 -3
  30. package/build/dts/docs/docs.js +211 -39
  31. package/build/dts/docs/fetch-article.d.ts +21 -0
  32. package/build/dts/docs/fetch-article.js +70 -5
  33. package/build/dts/docs/get-to-know.d.ts +7 -2
  34. package/build/dts/docs/get-to-know.js +37 -15
  35. package/build/dts/docs/mintlify-docs.d.ts +121 -0
  36. package/build/dts/docs/mintlify-docs.js +391 -0
  37. package/build/dts/docs/semanticSearch.d.ts +2 -1
  38. package/build/dts/docs/semanticSearch.js +14 -7
  39. package/build/dts/docs/start-deploy-website.d.ts +7 -6
  40. package/build/dts/docs/start-deploy-website.js +13 -8
  41. package/build/dts/docs/start-headless-build.d.ts +17 -0
  42. package/build/dts/docs/start-headless-build.js +60 -0
  43. package/build/dts/graphql/index.js +3 -1
  44. package/build/dts/import-claude-design-tool/index.js +2 -2
  45. package/build/dts/index.d.ts +3 -2
  46. package/build/dts/index.js +3 -2
  47. package/build/dts/infra/redact-personal-data.d.ts +4 -0
  48. package/build/dts/infra/redact-personal-data.js +79 -0
  49. package/build/dts/site-widget-tools/constants.d.ts +49 -1
  50. package/build/dts/site-widget-tools/constants.js +64 -7
  51. package/build/dts/site-widget-tools/index.d.ts +1 -0
  52. package/build/dts/site-widget-tools/index.js +1 -0
  53. package/build/dts/site-widget-tools/pick-images-tool/index.d.ts +14 -0
  54. package/build/dts/site-widget-tools/pick-images-tool/index.js +138 -0
  55. package/build/dts/site-widget-tools/search-site-templates-tool/index.js +33 -9
  56. package/build/dts/site-widget-tools/site-builder-tool/index.js +22 -2
  57. package/build/dts/site-widget-tools/site-creation-tool/index.d.ts +7 -1
  58. package/build/dts/site-widget-tools/site-creation-tool/index.js +22 -51
  59. package/build/dts/site-widget-tools/suggested-domain-tool/index.js +6 -3
  60. package/build/dts/support/index.d.ts +4 -0
  61. package/build/dts/support/index.js +13 -7
  62. package/build/dts/toolkit-entry.d.cts +19 -12
  63. package/build/dts/toolkit-entry.d.ts +19 -12
  64. package/build/dts/toolkit.d.ts +2 -2
  65. package/build/dts/toolkit.js +23 -7
  66. package/build/dts/wix-mcp-server.d.ts +11 -0
  67. package/build/dts/wix-mcp-server.js +28 -6
  68. package/build/dts/wixel/constants.d.ts +8 -1
  69. package/build/dts/wixel/constants.js +8 -1
  70. package/build/dts/wixel/index.d.ts +1 -1
  71. package/build/dts/wixel/index.js +2 -2
  72. package/build/dts/wixel/wixel-a2a-client.d.ts +83 -0
  73. package/build/dts/wixel/wixel-a2a-client.js +166 -0
  74. package/build/dts/wixel/wixel-bi.d.ts +2 -1
  75. package/build/dts/wixel/wixel-bi.js +2 -1
  76. package/build/dts/wixel/{external-agent-api.d.ts → wixel-session-entries.d.ts} +11 -33
  77. package/build/dts/wixel/{external-agent-api.js → wixel-session-entries.js} +33 -54
  78. package/build/dts/wixel/wixel-session-tools.d.ts +21 -26
  79. package/build/dts/wixel/wixel-session-tools.js +494 -599
  80. package/build/esm/index.js +3335 -1376
  81. package/build/esm/toolkit.js +2273 -565
  82. package/package.json +4 -4
  83. package/build/dts/docs/create-site-guide.d.ts +0 -3
  84. package/build/dts/docs/create-site-guide.js +0 -109
@@ -51,7 +51,7 @@ function errorResponse(text) {
51
51
  // ---------------------------------------------------------------------------
52
52
  // Upload flows
53
53
  // ---------------------------------------------------------------------------
54
- async function uploadFromUrl(item, authHeaders, displayName) {
54
+ async function uploadFromUrl(item, authHeaders, displayName, imagePickerToolName) {
55
55
  if (!item.download_url) {
56
56
  return {
57
57
  success: false,
@@ -61,7 +61,7 @@ async function uploadFromUrl(item, authHeaders, displayName) {
61
61
  if (!/^https?:\/\//i.test(item.download_url)) {
62
62
  return {
63
63
  success: false,
64
- error: `download_url must be a publicly accessible http(s) URL, not a local or sandbox file path (got: "${item.download_url}"). For a user-attached file, pass the file so the platform resolves it to a real download_url; if you only have the raw bytes, use imageBase64 instead.`
64
+ error: `This server can't read files on your machine or sandbox (got: "${item.download_url}"). Send this image as imageBase64 (the whole file, one per call) or as a public URL in imageUrls${imagePickerToolName ? `, or call ${imagePickerToolName} so the user picks it` : ''}.`
65
65
  };
66
66
  }
67
67
  try {
@@ -165,7 +165,11 @@ function formatBatchResults(results) {
165
165
  // Tool registration
166
166
  // ---------------------------------------------------------------------------
167
167
  export function addUploadImageTool(server, strategy, options) {
168
- const description = options?.description ?? defaultToolDescriptions.UploadImageToWixSite;
168
+ const imagePickerToolName = options?.imagePickerToolName;
169
+ const baseDescription = options?.description || defaultToolDescriptions.UploadImageToWixSite;
170
+ const description = imagePickerToolName
171
+ ? `${baseDescription}\nIf you can't deliver the image any of these ways, call ${imagePickerToolName} so the user picks it.`
172
+ : baseDescription;
169
173
  const hints = {
170
174
  readOnlyHint: options?.hints?.readOnlyHint ?? false,
171
175
  destructiveHint: options?.hints?.destructiveHint ?? false,
@@ -226,7 +230,7 @@ export function addUploadImageTool(server, strategy, options) {
226
230
  logger.log(`[WixMCP] Uploading ${total} image(s) to Wix site: ${siteId}`);
227
231
  try {
228
232
  const authHeaders = await strategy.getSiteAuthHeaders(siteId);
229
- const urlResults = await Promise.all(urlItems.map((item) => uploadFromUrl(item, authHeaders, displayName)));
233
+ const urlResults = await Promise.all(urlItems.map((item) => uploadFromUrl(item, authHeaders, displayName, imagePickerToolName)));
230
234
  let base64Result = null;
231
235
  if (imageBase64) {
232
236
  const result = await uploadFromBase64(imageBase64, mimeType, authHeaders, displayName);
@@ -1,5 +1,5 @@
1
1
  import './infra/sentry.js';
2
- declare const PUBLIC_TOOLS: readonly ["WDS", "REST", "SDK", "BUILD_APPS", "WIX_HEADLESS", "VELO", "BUSINESS_SOLUTIONS", "CLI", "OVERVIEW"];
2
+ declare const PUBLIC_TOOLS: readonly ["WDS", "REST", "SDK", "BUILD_APPS", "WIX_HEADLESS", "VELO", "BUSINESS_SOLUTIONS", "CLI", "OVERVIEW", "HELP_CENTER"];
3
3
  declare const EXPERIMENTAL_TOOLS: readonly ["WIX_API", "CLI_COMMAND", "GET_TO_KNOW_WIX", "CREATE_WIX_BUSINESS_GUIDE", "VELO_README", "WIX_API_THROUGH_FS", "GRAPHQL"];
4
4
  type Tool = (typeof PUBLIC_TOOLS)[number] | (typeof EXPERIMENTAL_TOOLS)[number];
5
5
  export declare const DEFAULT_TOOLS: Tool[];
package/build/dts/bin.js CHANGED
@@ -21,7 +21,7 @@ const EXPERIMENTAL_TOOLS = [
21
21
  'WIX_API',
22
22
  'CLI_COMMAND',
23
23
  'GET_TO_KNOW_WIX',
24
- 'CREATE_WIX_BUSINESS_GUIDE',
24
+ 'CREATE_WIX_BUSINESS_GUIDE', // accepted so old configs still start; the tool was removed
25
25
  'VELO_README',
26
26
  'WIX_API_THROUGH_FS',
27
27
  'GRAPHQL'
@@ -90,15 +90,14 @@ logger.log('Active tools:', activeTools);
90
90
  const docsTools = activeTools.filter((tool) => VALID_DOCS_TOOLS.includes(tool));
91
91
  const isWixCliAuth = Boolean(parsedArgs['wixCliAuth']);
92
92
  const hasGetToKnowWix = activeTools.includes('GET_TO_KNOW_WIX') || isWixCliAuth;
93
- const hasCreateWixBusinessGuide = activeTools.includes('CREATE_WIX_BUSINESS_GUIDE');
94
93
  const hasDynamicContext = Boolean(parsedArgs['dynamicContext']) || isWixCliAuth;
95
- if (docsTools.length > 0 || hasGetToKnowWix || hasCreateWixBusinessGuide) {
94
+ if (docsTools.length > 0 || hasGetToKnowWix) {
96
95
  logger.log('Adding docs tools:', docsTools);
97
96
  addDocsTools(server, docsTools, {
98
97
  getToKnowWixEnabled: hasGetToKnowWix,
99
- createWixBusinessGuideEnabled: hasCreateWixBusinessGuide,
100
98
  dynamicContextEnabled: hasDynamicContext,
101
- cliEnabled: true // bin.ts is always a CLI client (e.g. Claude Code)
99
+ // Mintlify docs: --docsSite=mintlify-links (or WIX_MCP_DOCS_SITE).
100
+ docsSite: parsedArgs['docsSite'] ?? process.env.WIX_MCP_DOCS_SITE
102
101
  });
103
102
  }
104
103
  if (activeTools.includes('VELO_README')) {
@@ -183,7 +183,7 @@ export async function resolveAttachments(attachments, fetchImpl = fetch) {
183
183
  url = undefined;
184
184
  }
185
185
  if (!a || !url) {
186
- throw new AttachmentError(`attachments[${i}] was not resolved to a download URL (got ${JSON.stringify(typeof raw === 'string' ? raw : ((a && a.download_url) ?? raw))}). 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).`);
186
+ throw new AttachmentError(`attachments[${i}] was not resolved to a download URL (got ${JSON.stringify(typeof raw === 'string' ? raw : ((a && a.download_url) ?? raw))}). \`attachments\` works only in ChatGPT, which swaps each file for a download URL before the call reaches Wix. Here it arrived as written, and Wix cannot read a path on your machine, so retrying the same value fails the same way. Upload another way. With a shell that reaches the internet, send the file from there (for a site, the StartDeployWebsite recipe's curl drop). Otherwise leave \`attachments\` out and put the files in \`files\`: text as is, and a binary as a \`=== FILE: <path> base64 ===\` entry only when it is a few KB (an icon, a logo), since a larger base64 payload does not survive your own output. A larger image goes in by public URL or through the user (the Media Manager).`);
187
187
  }
188
188
  const problem = checkAttachmentUrl(url);
189
189
  if (problem) {
@@ -20,8 +20,13 @@ export interface CodeModeOptions {
20
20
  };
21
21
  disableTools?: string[];
22
22
  toolDescriptions?: Record<string, string>;
23
- /** Max response size in chars before truncation (default: 24,000, ~6,000 tokens). */
23
+ /** Max response size in chars before truncation (defaults: ExecuteWixAPI 100,000, SearchWixAPISpec 64,000). */
24
24
  maxResponseSize?: number;
25
+ /**
26
+ * The connection's docsSite (see ../docs/mintlify-docs.ts). SearchWixAPISpec
27
+ * passes it on, so a Mintlify mode also finds schemas by Mintlify page URL.
28
+ */
29
+ docsSite?: string;
25
30
  }
26
31
  export declare const EXECUTE_TOOL_NAME = "ExecuteWixAPI";
27
32
  export declare function addCodeModeTools(server: WixMcpServer, options: CodeModeOptions): Promise<void>;
@@ -1,13 +1,16 @@
1
1
  import { z } from 'zod';
2
2
  import { AttachmentError, resolveAttachments } from './attachments.js';
3
+ import { fileParamNote } from '../config/file-params.js';
3
4
  import { logger } from '../infra/logger.js';
4
5
  import { defaultToolDescriptions } from '../config/default-config.js';
5
6
  import { truncateResponse } from './truncate-response.js';
6
7
  import { MAX_ALLOWED_RESPONSE_CHARS } from '../infra/response-size-limits.js';
7
8
  import { validateExecuteCode } from './validation.js';
8
9
  import { desc } from '../config/param-descriptions.js';
10
+ import { isMintlifyDocsSite, rewriteDocsLinks, toDevWixHostText } from '../docs/mintlify-docs.js';
9
11
  import { rethrowIfUnauthorized } from '../auth/index.js';
10
12
  import { WixFetchError } from '../wix-fetch-error.js';
13
+ import { addUploadHeadlessWebsiteFilesTool, UPLOAD_HEADLESS_WEBSITE_FILES_TOOL_NAME } from '../api-call/upload-headless-website-files.js';
11
14
  // Looks `fetch` up per call so a host or test that swaps the global is honored.
12
15
  const defaultCodeModeFetch = (url, init) => fetch(url, init);
13
16
  const SEARCH_TOOL_NAME = 'SearchWixAPISpec';
@@ -25,6 +28,15 @@ export async function addCodeModeTools(server, options) {
25
28
  maxResponseSize
26
29
  });
27
30
  }
31
+ // Account-owner flow, registered beside the code-mode tools (same file
32
+ // inputs, no runtime dependency); never in visitor mode.
33
+ if (!disableTools.includes(UPLOAD_HEADLESS_WEBSITE_FILES_TOOL_NAME) &&
34
+ authStrategy) {
35
+ addUploadHeadlessWebsiteFilesTool(server, {
36
+ authStrategy,
37
+ toolDescriptions
38
+ });
39
+ }
28
40
  }
29
41
  /**
30
42
  * Register SearchWixAPISpec. The description must stay a byte-stable
@@ -34,13 +46,13 @@ export async function addCodeModeTools(server, options) {
34
46
  * lightIndex.
35
47
  */
36
48
  export function addSearchCodeModeTool(server, options) {
37
- const { codeModeBaseUrl, codeModeFetch, authStrategy, disableTools = [], toolDescriptions, maxResponseSize } = options;
49
+ const { codeModeBaseUrl, codeModeFetch, authStrategy, disableTools = [], toolDescriptions, maxResponseSize, docsSite } = options;
38
50
  if (disableTools.includes(SEARCH_TOOL_NAME)) {
39
51
  return;
40
52
  }
41
53
  const description = toolDescriptions?.[SEARCH_TOOL_NAME] ??
42
54
  defaultToolDescriptions.SearchWixAPISpec;
43
- registerSearchTool(server, codeModeBaseUrl, description, maxResponseSize, authStrategy, codeModeFetch);
55
+ registerSearchTool(server, codeModeBaseUrl, description, maxResponseSize, authStrategy, codeModeFetch, docsSite);
44
56
  }
45
57
  export function addExecuteCodeModeTool(server, options) {
46
58
  const { codeModeBaseUrl, codeModeFetch, authStrategy, visitor, disableTools = [], toolDescriptions, maxResponseSize } = options;
@@ -57,6 +69,9 @@ export function addExecuteCodeModeTool(server, options) {
57
69
  });
58
70
  }
59
71
  const SEARCH_MAX_RESPONSE_CHARS = 64_000;
72
+ // ExecuteWixAPI's own default, ~25,000 tokens, so a full API listing comes back
73
+ // whole. A session's maxResponseSize still overrides it.
74
+ const EXECUTE_MAX_RESPONSE_CHARS = 100_000;
60
75
  /**
61
76
  * Search needs no auth of its own; without a header the call is bucketed by the
62
77
  * Worker's own IP (see postExecute). Anonymous sessions throw here and stay on
@@ -70,7 +85,7 @@ async function resolveLoopbackAuthorization(authStrategy) {
70
85
  return undefined;
71
86
  }
72
87
  }
73
- function registerSearchTool(server, codeModeBaseUrl, description, maxResponseSize, authStrategy, codeModeFetch = defaultCodeModeFetch) {
88
+ function registerSearchTool(server, codeModeBaseUrl, description, maxResponseSize, authStrategy, codeModeFetch = defaultCodeModeFetch, docsSite) {
74
89
  const searchUrl = `${codeModeBaseUrl}/api/code-mode/search`;
75
90
  server.tool(SEARCH_TOOL_NAME, description, {
76
91
  code: z
@@ -89,7 +104,8 @@ function registerSearchTool(server, codeModeBaseUrl, description, maxResponseSiz
89
104
  'Content-Type': 'application/json',
90
105
  ...(authorization ? { Authorization: authorization } : {})
91
106
  },
92
- body: JSON.stringify({ code })
107
+ // docsSite only when set: without it the request is as before.
108
+ body: JSON.stringify(docsSite ? { code, docsSite } : { code })
93
109
  });
94
110
  if (!resp.ok) {
95
111
  const errorBody = await resp.text();
@@ -116,7 +132,13 @@ function registerSearchTool(server, codeModeBaseUrl, description, maxResponseSiz
116
132
  ]
117
133
  };
118
134
  }
119
- const text = truncateResponse(data.result, maxResponseSize ?? SEARCH_MAX_RESPONSE_CHARS);
135
+ // Mintlify docs: the index shows docsUrls on the Mintlify host by rule.
136
+ // Map them back, then resolve each to its Mintlify page as the docs tools
137
+ // do, so a page the site doesn't have keeps its dev.wix.com link.
138
+ const result = isMintlifyDocsSite(docsSite) && data.result !== undefined
139
+ ? JSON.parse((await rewriteDocsLinks(toDevWixHostText(JSON.stringify(data.result)), { label: 'search SearchWixAPISpec' })).text)
140
+ : data.result;
141
+ const text = truncateResponse(result, maxResponseSize ?? SEARCH_MAX_RESPONSE_CHARS);
120
142
  return {
121
143
  content: [{ type: 'text', text }]
122
144
  };
@@ -157,10 +179,13 @@ async function postExecute(executeUrl, body, authorization, codeModeFetch = defa
157
179
  }
158
180
  return (await resp.json());
159
181
  }
160
- function executeErrorResult(message) {
182
+ function executeErrorResult(message, failedCalls) {
161
183
  return {
162
184
  isError: true,
163
- content: [{ type: 'text', text: `Execute error: ${message}` }]
185
+ content: [{ type: 'text', text: `Execute error: ${message}` }],
186
+ // The failed calls as fields, request ids included. The text carries the
187
+ // ids too, for clients that don't read structured results.
188
+ ...(failedCalls?.length ? { structuredContent: { failedCalls } } : {})
164
189
  };
165
190
  }
166
191
  function executeTextResult(message) {
@@ -170,7 +195,7 @@ function executeTextResult(message) {
170
195
  }
171
196
  function formatExecuteResult(data, maxResponseSize, reportBi) {
172
197
  if (data.error) {
173
- return executeErrorResult(data.error);
198
+ return executeErrorResult(data.error, data.failedCalls);
174
199
  }
175
200
  // Before the slice -- resultTextLength is measured after it and saturates.
176
201
  reportBi?.({
@@ -193,7 +218,10 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
193
218
  }
194
219
  return {
195
220
  content: [
196
- { type: 'text', text: truncateResponse(data.result, maxResponseSize) }
221
+ {
222
+ type: 'text',
223
+ text: truncateResponse(data.result, maxResponseSize ?? EXECUTE_MAX_RESPONSE_CHARS)
224
+ }
197
225
  ]
198
226
  };
199
227
  }
@@ -234,8 +262,8 @@ function addExecuteTool(server, options) {
234
262
  hasMutations: z
235
263
  .boolean()
236
264
  .describe(visitor
237
- ? 'Whether this code creates, updates, deletes, publishes, imports, uploads, or otherwise mutates site data on the visitor’s behalf. Set this to true for create/update/delete/bulk create/import/upload calls even if the reason is inspection, verification, or response-shape discovery. Read-only GET/query/list/search calls can use false.'
238
- : 'Whether this code creates, updates, deletes, publishes, installs, imports, uploads, or otherwise mutates Wix data or site/account state. Set this to true for create/update/delete/bulk create/import/upload calls even if the reason is inspection, verification, or response-shape discovery. Read-only GET/query/list/search calls can use false.'),
265
+ ? 'True if the code changes site data on the visitor’s behalf (create, update, delete, import, upload); false if it only reads (get, query, list, search).'
266
+ : 'True if the code changes anything in the Wix account or a site (create, update, delete, publish, install, import, upload); false if it only reads (get, query, list, search).'),
239
267
  sourceDocUrls: z.array(z.string()).describe(d.sourceDocUrls),
240
268
  files: z
241
269
  .string()
@@ -259,7 +287,8 @@ function addExecuteTool(server, options) {
259
287
  mime_type: z.string().optional()
260
288
  }))
261
289
  .optional()
262
- .describe('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.'),
290
+ .describe(fileParamNote('use `files`, or upload from your shell if it reaches the internet') +
291
+ ' Any type: a zip of a site, HTML, images, PDFs. 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.'),
263
292
  // Visitor mode takes an agent-supplied token and pins the site; account/site
264
293
  // mode lets the agent pick the site.
265
294
  ...(visitor
@@ -274,7 +303,11 @@ function addExecuteTool(server, options) {
274
303
  .optional()
275
304
  .describe('Default Wix site ID for the `wix.request()` calls in this execution. Optional in the schema, but required for site-level work: supply a `siteId` either here, as the default for every request, or on an individual request. Without one, a request runs at account scope, where site-level endpoints fail. Setting `scope: "account"` on a request runs it at account scope and ignores any `siteId`. Determine the target site with GetSiteContext or ListWixSites before calling; do not pass a guessed or empty value.')
276
305
  })
277
- }, { readOnlyHint: false, destructiveHint: true, openWorldHint: false }, async (rawArgs,
306
+ },
307
+ // openWorldHint true: agent code picks the Wix endpoints at run time (and may
308
+ // receive platform-resolved attachment URLs); the sandbox's host allowlist
309
+ // bounds it, but the operation set is open-ended, which is what the hint means.
310
+ { readOnlyHint: false, destructiveHint: true, openWorldHint: true }, async (rawArgs,
278
311
  // Partial: duck-typed servers (the toolkit's capturing server, test
279
312
  // doubles) build their own extra and may not supply every field.
280
313
  extra) => {
@@ -346,6 +379,7 @@ function addExecuteTool(server, options) {
346
379
  sessionId,
347
380
  toolInvocationId,
348
381
  clientName: server.server?.getClientVersion?.()?.name,
382
+ ...(visitor ? { visitorMode: true } : {}),
349
383
  // A visitor token is a site-scoped bearer token: sent as siteToken
350
384
  // (→ Authorization + wix-site-id) and as accountToken only to satisfy
351
385
  // the runtime's required field. Account/site mode uses strategy tokens.
@@ -17,6 +17,10 @@ export function truncateResponse(content, maxChars = DEFAULT_MAX_CHARS) {
17
17
  const truncated = text.slice(0, effectiveMax);
18
18
  const estimatedTokens = Math.ceil(text.length / CHARS_PER_TOKEN);
19
19
  const limitTokens = Math.ceil(effectiveMax / CHARS_PER_TOKEN);
20
- return `${truncated}\n\n--- TRUNCATED ---\nResponse was ~${estimatedTokens.toLocaleString()} tokens (limit: ${limitTokens.toLocaleString()}). Refine your code to return less data.`;
20
+ const cutChars = text.length - effectiveMax;
21
+ const note = `Response was ~${estimatedTokens.toLocaleString()} tokens (limit: ${limitTokens.toLocaleString()}). Showing the first ${effectiveMax.toLocaleString()} of ${text.length.toLocaleString()} characters; the last ${cutChars.toLocaleString()} were cut. To get the rest, run again and return less per call — only the fields you need, the next page (cursor or offset), or the next slice of a large array — and repeat until you have it all.`;
22
+ // At the top as well as the end: a client that cuts a long result keeps its
23
+ // head, so a note only at the end is the first thing lost.
24
+ return `[TRUNCATED: ${note}]\n\n${truncated}\n\n--- TRUNCATED ---\n${note}`;
21
25
  }
22
26
  //# sourceMappingURL=truncate-response.js.map
@@ -21,33 +21,48 @@ export interface ModeDefaultConfig {
21
21
  skillsPrOverrideEnabled?: boolean;
22
22
  graphqlEnabled?: boolean;
23
23
  }
24
+ /**
25
+ * CallWixSiteAPI's advice when the Wix MCP lists no ExecuteWixAPI. True only where the server serves
26
+ * ExecuteWixAPI (a client with an old or cached tool list); `addApiCallTool` swaps it for
27
+ * `CALL_WIX_SITE_API_NO_EXECUTE_LINE` where ExecuteWixAPI is off on purpose.
28
+ */
29
+ export declare const CALL_WIX_SITE_API_RECONNECT_LINE = "If the Wix MCP offers no ExecuteWixAPI at all, your Wix connection is likely an old or cached version: tell the user once to reconnect the Wix connector or restart the client, and use this tool until then.";
30
+ export declare const CALL_WIX_SITE_API_NO_EXECUTE_LINE = "If ExecuteWixAPI isn't in your tool list, use this tool.";
24
31
  export declare const SYSTEM_REMINDER_GUIDELINES: string;
25
32
  export declare function buildSystemReminder(includeReadme: boolean, includeImageUploadGuidance?: boolean): string;
26
33
  export declare const SYSTEM_REMINDER: string;
34
+ /** SearchWixHelpCenter's description and response both carry this: Help Center is for people, the developer docs for the agent's own actions. */
35
+ export declare const HELP_CENTER_IS_FOR_PEOPLE = "The Help Center is written for people doing things by hand in Wix's dashboard and editors. To act on a site yourself, the Wix developer docs come first: find the method with SearchWixRESTDocumentation or BrowseWixRESTDocsMenu.";
36
+ /**
37
+ * The MCP server's \`instructions\`, sent in its reply to initialize. Clients that show them
38
+ * (ChatGPT and Codex use the first 512 characters; Claude Code loads them at session start and
39
+ * cuts at 4,096) get the site-creation routing before any tool definition. Sent only to a session
40
+ * that has every tool it names (SERVER_INSTRUCTIONS_TOOLS).
41
+ * Each tool named here carries a comment pointing back to this text. A change to any of them (a
42
+ * name, what it is for, a new site-creation tool) updates this text and that list with it.
43
+ */
44
+ export declare const SERVER_INSTRUCTIONS = "Wix: build and manage Wix sites. A new site is written in code and uploaded: StartDeployWebsite returns the upload guide; StartHeadlessBuild returns the headless guide, for a site that needs Wix business features (forms, a store, bookings, a CMS, members, payments). WixSiteBuilder or SearchSiteTemplates only when the user asked for Wix's editor, the Wix Harmony Editor, a template, Wix Studio or the Classic Editor. For anything else, except ListWixSites and UploadImageToWixSite, call WixREADME first.";
45
+ /** The tools SERVER_INSTRUCTIONS names. */
46
+ export declare const SERVER_INSTRUCTIONS_TOOLS: string[];
27
47
  export declare const SITE_CREATION_COPY: {
28
48
  readonly templatePick: {
29
49
  readonly nonWidget: "After the user selects a template, call `CreateSiteFromTemplate`.";
30
50
  readonly widget: "The gallery creates the site when the user picks one.";
31
51
  };
32
- readonly unstatedMethod: {
33
- readonly nonWidget: "you MUST ask whether they want to build with AI or start from a template, and create nothing and show nothing until they answer";
34
- readonly widget: "you MUST call `WixSiteCreation` and let them choose";
35
- };
36
- readonly normalCreationRoute: {
37
- readonly nonWidget: "route those through `WixSiteBuilder` or `SearchSiteTemplates`";
38
- readonly widget: "route those through `WixSiteCreation`";
39
- };
40
52
  };
41
53
  /** Rewrites non-widget copy into its widget form; a no-op on text that carries no divergence. */
42
54
  export declare const toWidget: (text: string) => string;
43
55
  export declare const executeWixApiDescription: string;
44
- export declare function buildToolDescriptions(includeReadme: boolean, includeImageUploadGuidance?: boolean): Record<string, string>;
56
+ export declare function buildToolDescriptions(includeReadme: boolean, includeImageUploadGuidance?: boolean, { usageGuideOnce }?: {
57
+ usageGuideOnce?: boolean;
58
+ }): Record<string, string>;
45
59
  /**
46
60
  * Canonical (README-inclusive) tool descriptions used by the live MCP server and
47
61
  * all existing importers.
48
62
  */
49
63
  export declare const defaultToolDescriptions: Record<string, string>;
50
64
  export declare const executeCodeModeToolDescriptions: Record<string, string>;
65
+ export declare const WIX_SKILLS_README_SECTION: string;
51
66
  /**
52
67
  * Default readme docs - content for WixREADME tool response.
53
68
  * Assumes both ExecuteWixAPI and SearchWixAPISpec are available (execute-and-search mode).
@@ -55,6 +70,9 @@ export declare const executeCodeModeToolDescriptions: Record<string, string>;
55
70
  * Joined rather than interpolated into one `dedent` — `dedent` reads indentation from the literal
56
71
  * parts only, so a multi-line interpolation gets flattened.
57
72
  */
73
+ export declare function buildReadmeDocs({ recipesIndex }?: {
74
+ recipesIndex?: boolean;
75
+ }): ReadmeDocConfig[];
58
76
  export declare const defaultReadmeDocs: ReadmeDocConfig[];
59
77
  /**
60
78
  * Merge base config with overrides
@@ -68,6 +86,14 @@ export declare function mergeConfig(base: ModeDefaultConfig, overrides: Partial<
68
86
  * All tools enabled, all descriptions, good readmeDocs
69
87
  */
70
88
  export declare const defaultConfig: ModeDefaultConfig;
89
+ /**
90
+ * For a session without WixREADME (mode=code, getToKnowWixEnabled off, WixREADME disabled): the
91
+ * usage guide WixREADME carries goes back onto every tool, as it was before usageGuideOnce.
92
+ * Custom tool descriptions are kept.
93
+ */
94
+ export declare function withUsageGuideOnEveryTool<Config extends {
95
+ toolDescriptions?: Record<string, string>;
96
+ }>(config: Config): Config;
71
97
  /**
72
98
  * Delta for clients that declared the MCP-Apps UI extension. Merged over the mode config at
73
99
  * request time, since the mode override and the widget variant have to compose.