@wix/mcp 1.0.86 → 1.0.87
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/build/bin-standalone.js +36 -8
- package/build/cjs/index.cjs +57 -10
- package/build/cjs/toolkit.cjs +55 -8
- package/build/dts/code-mode/index.js +28 -0
- package/build/dts/config/api-request-rules.d.ts +1 -0
- package/build/dts/config/api-request-rules.js +1 -0
- package/build/dts/config/default-config.js +17 -3
- package/build/dts/config/param-descriptions.js +5 -2
- package/build/dts/docs/get-to-know.js +14 -11
- package/build/dts/import-claude-design-tool/index.js +2 -2
- package/build/dts/tool-utils.js +12 -1
- package/build/esm/index.js +57 -10
- package/build/esm/toolkit.js +55 -8
- package/package.json +2 -2
package/build/bin-standalone.js
CHANGED
|
@@ -71552,6 +71552,7 @@ function rethrowIfUnauthorized(error2) {
|
|
|
71552
71552
|
|
|
71553
71553
|
// src/config/api-request-rules.ts
|
|
71554
71554
|
var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
|
|
71555
|
+
var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
|
|
71555
71556
|
|
|
71556
71557
|
// src/config/default-config.ts
|
|
71557
71558
|
var AGENT_GOAL = dedent_default`
|
|
@@ -71652,7 +71653,7 @@ var SITE_CREATION_COPY = {
|
|
|
71652
71653
|
var SITE_GUIDANCE = dedent_default`
|
|
71653
71654
|
A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
|
|
71654
71655
|
|
|
71655
|
-
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool.
|
|
71656
|
+
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
71656
71657
|
|
|
71657
71658
|
Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
|
|
71658
71659
|
If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
|
|
@@ -71711,12 +71712,25 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
71711
71712
|
siteId?: string;
|
|
71712
71713
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
71713
71714
|
url: string;
|
|
71715
|
+
// Plain object → JSON. A string is sent verbatim (set your own Content-Type,
|
|
71716
|
+
// e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
|
|
71717
|
+
// for binary uploads (set your own Content-Type).
|
|
71714
71718
|
body?: unknown;
|
|
71715
71719
|
headers?: Record<string, string>;
|
|
71720
|
+
// "base64" returns the response body as a base64 string (data), with
|
|
71721
|
+
// encoding: "base64" on the result — use it for binary downloads (zip,
|
|
71722
|
+
// image, pdf); decoding those as text corrupts them. Binary content types
|
|
71723
|
+
// are returned as base64 automatically even without this. Decode, edit and
|
|
71724
|
+
// re-upload binary WITHIN this script and return only a small summary. If you
|
|
71725
|
+
// must return the bytes, return the wix.request response object itself (so
|
|
71726
|
+
// encoding: "base64" is preserved and it isn't truncated); a bare base64
|
|
71727
|
+
// string you return is treated as plain text and may be truncated.
|
|
71728
|
+
responseType?: "base64";
|
|
71716
71729
|
}
|
|
71717
71730
|
interface WixResponse<T = unknown> {
|
|
71718
71731
|
status: number;
|
|
71719
71732
|
data: T;
|
|
71733
|
+
encoding?: "base64";
|
|
71720
71734
|
json(): Promise<T>;
|
|
71721
71735
|
}
|
|
71722
71736
|
declare const wix: {
|
|
@@ -71855,6 +71869,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
71855
71869
|
ReadFullDocsArticle: dedent_default`
|
|
71856
71870
|
Fetches the full Wix docs article or method article with code examples for using the method.
|
|
71857
71871
|
Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
|
|
71872
|
+
Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
|
|
71858
71873
|
For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
|
|
71859
71874
|
${reminder}
|
|
71860
71875
|
`,
|
|
@@ -71987,7 +72002,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
71987
72002
|
`,
|
|
71988
72003
|
"import-claude-design-from-url": dedent_default`
|
|
71989
72004
|
Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
|
|
71990
|
-
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool:
|
|
72005
|
+
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
71991
72006
|
`,
|
|
71992
72007
|
RunWixCliCommand: dedent_default`
|
|
71993
72008
|
Executes Wix CLI commands for Wix app development and management.
|
|
@@ -72414,7 +72429,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72414
72429
|
CreateWixBusinessGuide: dedent_default`
|
|
72415
72430
|
Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
|
|
72416
72431
|
Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
|
|
72417
|
-
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool —
|
|
72432
|
+
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
|
|
72418
72433
|
|
|
72419
72434
|
## What This Tool Contains
|
|
72420
72435
|
|
|
@@ -73013,7 +73028,10 @@ var paramDescriptions = {
|
|
|
73013
73028
|
ARRAY_QUERY_PARAMS_RULE
|
|
73014
73029
|
].join("\n"),
|
|
73015
73030
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
73016
|
-
body:
|
|
73031
|
+
body: [
|
|
73032
|
+
'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
73033
|
+
WQL_FILTER_RULE
|
|
73034
|
+
].join("\n"),
|
|
73017
73035
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
73018
73036
|
sourceDocUrl: [
|
|
73019
73037
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -73337,15 +73355,17 @@ Failed to fetch content: ${errorMsg}`
|
|
|
73337
73355
|
const baseContentsPromise = Promise.all(
|
|
73338
73356
|
baseDocsWithoutRecipes.map(fetchDoc)
|
|
73339
73357
|
);
|
|
73340
|
-
const skillsContentPromise = getSkillsByPortal(httpClient, {
|
|
73358
|
+
const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient, {
|
|
73341
73359
|
portalId: REST_PORTAL_ID,
|
|
73342
73360
|
...repo && { repo },
|
|
73343
73361
|
...commitHash && { commitHash },
|
|
73344
|
-
|
|
73362
|
+
tags: skillsTags
|
|
73345
73363
|
}).catch((err) => {
|
|
73346
73364
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
73347
73365
|
return null;
|
|
73348
|
-
})
|
|
73366
|
+
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
73367
|
+
(doc) => doc?.text ?? null
|
|
73368
|
+
);
|
|
73349
73369
|
const filter = {};
|
|
73350
73370
|
if (siteId) filter.siteId = siteId;
|
|
73351
73371
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -85253,6 +85273,14 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
85253
85273
|
|
|
85254
85274
|
// src/tool-utils.ts
|
|
85255
85275
|
var REST_METHOD_CONTRACT_RETRY_HINT = "Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.";
|
|
85276
|
+
var SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator \u2014 `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` \u2014 and retry without re-searching the docs.';
|
|
85277
|
+
var FIELD_CAPABILITIES_HINT = "This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.";
|
|
85278
|
+
var getRetryHint = (errorDetails) => {
|
|
85279
|
+
if (!/Filter contains unsupported operator/i.test(errorDetails)) {
|
|
85280
|
+
return REST_METHOD_CONTRACT_RETRY_HINT;
|
|
85281
|
+
}
|
|
85282
|
+
return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
|
|
85283
|
+
};
|
|
85256
85284
|
var DEFAULT_OPENAI_SECURITY_SCHEMES = [
|
|
85257
85285
|
{ type: "oauth2", scopes: ["offline_access"] }
|
|
85258
85286
|
];
|
|
@@ -85279,7 +85307,7 @@ var buildErrorMessage = ({
|
|
|
85279
85307
|
].filter((str) => !!str).join("\n");
|
|
85280
85308
|
return `${baseMessage}
|
|
85281
85309
|
|
|
85282
|
-
${
|
|
85310
|
+
${getRetryHint(String(errorDetails))}`;
|
|
85283
85311
|
};
|
|
85284
85312
|
var handleWixAPIResponse = async (response) => {
|
|
85285
85313
|
const requestId = response.headers?.["x-wix-request-id"];
|
package/build/cjs/index.cjs
CHANGED
|
@@ -35867,6 +35867,14 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
35867
35867
|
|
|
35868
35868
|
// src/tool-utils.ts
|
|
35869
35869
|
var REST_METHOD_CONTRACT_RETRY_HINT = "Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.";
|
|
35870
|
+
var SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator \u2014 `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` \u2014 and retry without re-searching the docs.';
|
|
35871
|
+
var FIELD_CAPABILITIES_HINT = "This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.";
|
|
35872
|
+
var getRetryHint = (errorDetails) => {
|
|
35873
|
+
if (!/Filter contains unsupported operator/i.test(errorDetails)) {
|
|
35874
|
+
return REST_METHOD_CONTRACT_RETRY_HINT;
|
|
35875
|
+
}
|
|
35876
|
+
return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
|
|
35877
|
+
};
|
|
35870
35878
|
var DEFAULT_OPENAI_SECURITY_SCHEMES = [
|
|
35871
35879
|
{ type: "oauth2", scopes: ["offline_access"] }
|
|
35872
35880
|
];
|
|
@@ -35893,7 +35901,7 @@ var buildErrorMessage = ({
|
|
|
35893
35901
|
].filter((str) => !!str).join("\n");
|
|
35894
35902
|
return `${baseMessage}
|
|
35895
35903
|
|
|
35896
|
-
${
|
|
35904
|
+
${getRetryHint(String(errorDetails))}`;
|
|
35897
35905
|
};
|
|
35898
35906
|
var handleWixAPIResponse = async (response) => {
|
|
35899
35907
|
const requestId = response.headers?.["x-wix-request-id"];
|
|
@@ -37160,6 +37168,7 @@ function rethrowIfUnauthorized(error2) {
|
|
|
37160
37168
|
|
|
37161
37169
|
// src/config/api-request-rules.ts
|
|
37162
37170
|
var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
|
|
37171
|
+
var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
|
|
37163
37172
|
|
|
37164
37173
|
// src/config/default-config.ts
|
|
37165
37174
|
var AGENT_GOAL = dedent_default`
|
|
@@ -37260,7 +37269,7 @@ var SITE_CREATION_COPY = {
|
|
|
37260
37269
|
var SITE_GUIDANCE = dedent_default`
|
|
37261
37270
|
A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
|
|
37262
37271
|
|
|
37263
|
-
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool.
|
|
37272
|
+
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
37264
37273
|
|
|
37265
37274
|
Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
|
|
37266
37275
|
If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
|
|
@@ -37319,12 +37328,25 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
37319
37328
|
siteId?: string;
|
|
37320
37329
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
37321
37330
|
url: string;
|
|
37331
|
+
// Plain object → JSON. A string is sent verbatim (set your own Content-Type,
|
|
37332
|
+
// e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
|
|
37333
|
+
// for binary uploads (set your own Content-Type).
|
|
37322
37334
|
body?: unknown;
|
|
37323
37335
|
headers?: Record<string, string>;
|
|
37336
|
+
// "base64" returns the response body as a base64 string (data), with
|
|
37337
|
+
// encoding: "base64" on the result — use it for binary downloads (zip,
|
|
37338
|
+
// image, pdf); decoding those as text corrupts them. Binary content types
|
|
37339
|
+
// are returned as base64 automatically even without this. Decode, edit and
|
|
37340
|
+
// re-upload binary WITHIN this script and return only a small summary. If you
|
|
37341
|
+
// must return the bytes, return the wix.request response object itself (so
|
|
37342
|
+
// encoding: "base64" is preserved and it isn't truncated); a bare base64
|
|
37343
|
+
// string you return is treated as plain text and may be truncated.
|
|
37344
|
+
responseType?: "base64";
|
|
37324
37345
|
}
|
|
37325
37346
|
interface WixResponse<T = unknown> {
|
|
37326
37347
|
status: number;
|
|
37327
37348
|
data: T;
|
|
37349
|
+
encoding?: "base64";
|
|
37328
37350
|
json(): Promise<T>;
|
|
37329
37351
|
}
|
|
37330
37352
|
declare const wix: {
|
|
@@ -37463,6 +37485,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
37463
37485
|
ReadFullDocsArticle: dedent_default`
|
|
37464
37486
|
Fetches the full Wix docs article or method article with code examples for using the method.
|
|
37465
37487
|
Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
|
|
37488
|
+
Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
|
|
37466
37489
|
For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
|
|
37467
37490
|
${reminder}
|
|
37468
37491
|
`,
|
|
@@ -37595,7 +37618,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
37595
37618
|
`,
|
|
37596
37619
|
"import-claude-design-from-url": dedent_default`
|
|
37597
37620
|
Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
|
|
37598
|
-
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool:
|
|
37621
|
+
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
37599
37622
|
`,
|
|
37600
37623
|
RunWixCliCommand: dedent_default`
|
|
37601
37624
|
Executes Wix CLI commands for Wix app development and management.
|
|
@@ -38022,7 +38045,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
38022
38045
|
CreateWixBusinessGuide: dedent_default`
|
|
38023
38046
|
Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
|
|
38024
38047
|
Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
|
|
38025
|
-
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool —
|
|
38048
|
+
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
|
|
38026
38049
|
|
|
38027
38050
|
## What This Tool Contains
|
|
38028
38051
|
|
|
@@ -38659,7 +38682,10 @@ var paramDescriptions = {
|
|
|
38659
38682
|
ARRAY_QUERY_PARAMS_RULE
|
|
38660
38683
|
].join("\n"),
|
|
38661
38684
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
38662
|
-
body:
|
|
38685
|
+
body: [
|
|
38686
|
+
'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
38687
|
+
WQL_FILTER_RULE
|
|
38688
|
+
].join("\n"),
|
|
38663
38689
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
38664
38690
|
sourceDocUrl: [
|
|
38665
38691
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -38983,15 +39009,17 @@ Failed to fetch content: ${errorMsg}`
|
|
|
38983
39009
|
const baseContentsPromise = Promise.all(
|
|
38984
39010
|
baseDocsWithoutRecipes.map(fetchDoc)
|
|
38985
39011
|
);
|
|
38986
|
-
const skillsContentPromise = getSkillsByPortal(httpClient6, {
|
|
39012
|
+
const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient6, {
|
|
38987
39013
|
portalId: REST_PORTAL_ID,
|
|
38988
39014
|
...repo && { repo },
|
|
38989
39015
|
...commitHash && { commitHash },
|
|
38990
|
-
|
|
39016
|
+
tags: skillsTags
|
|
38991
39017
|
}).catch((err) => {
|
|
38992
39018
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
38993
39019
|
return null;
|
|
38994
|
-
})
|
|
39020
|
+
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
39021
|
+
(doc) => doc?.text ?? null
|
|
39022
|
+
);
|
|
38995
39023
|
const filter = {};
|
|
38996
39024
|
if (siteId) filter.siteId = siteId;
|
|
38997
39025
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -52009,12 +52037,12 @@ function addImportClaudeDesignTool(server, authStrategy, options) {
|
|
|
52009
52037
|
designUrl = new URL(args.url);
|
|
52010
52038
|
} catch {
|
|
52011
52039
|
return errorResult(
|
|
52012
|
-
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
52040
|
+
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md \u2014 it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
52013
52041
|
);
|
|
52014
52042
|
}
|
|
52015
52043
|
if (designUrl.protocol !== "https:" || !designUrl.hostname.endsWith(CLAUDE_USER_CONTENT_HOST_SUFFIX)) {
|
|
52016
52044
|
return errorResult(
|
|
52017
|
-
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
52045
|
+
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md \u2014 it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
52018
52046
|
);
|
|
52019
52047
|
}
|
|
52020
52048
|
const accountHeaders = await authStrategy.getAccountAuthHeaders();
|
|
@@ -53072,12 +53100,31 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
|
|
|
53072
53100
|
reportBi?.({
|
|
53073
53101
|
originalLength: typeof data.result === "string" ? data.result.length : JSON.stringify(data.result)?.length
|
|
53074
53102
|
});
|
|
53103
|
+
const base64Text = base64PayloadText(data.result);
|
|
53104
|
+
if (base64Text !== null) {
|
|
53105
|
+
if (base64Text.length <= MAX_ALLOWED_RESPONSE_CHARS) {
|
|
53106
|
+
return { content: [{ type: "text", text: base64Text }] };
|
|
53107
|
+
}
|
|
53108
|
+
const approxKb = Math.ceil(base64Text.length / 1024).toLocaleString();
|
|
53109
|
+
const limitKb = Math.floor(
|
|
53110
|
+
MAX_ALLOWED_RESPONSE_CHARS / 1024
|
|
53111
|
+
).toLocaleString();
|
|
53112
|
+
return executeErrorResult(
|
|
53113
|
+
`Binary (base64) result is ~${approxKb} KB, too large to return intact (limit ~${limitKb} KB); truncating it would corrupt the base64. Process the bytes inside your ExecuteWixAPI script \u2014 decode, edit, and re-upload in the same call \u2014 and return only a small summary.`
|
|
53114
|
+
);
|
|
53115
|
+
}
|
|
53075
53116
|
return {
|
|
53076
53117
|
content: [
|
|
53077
53118
|
{ type: "text", text: truncateResponse(data.result, maxResponseSize) }
|
|
53078
53119
|
]
|
|
53079
53120
|
};
|
|
53080
53121
|
}
|
|
53122
|
+
function base64PayloadText(result) {
|
|
53123
|
+
if (result !== null && typeof result === "object" && result.encoding === "base64" && typeof result.data === "string") {
|
|
53124
|
+
return JSON.stringify(result);
|
|
53125
|
+
}
|
|
53126
|
+
return null;
|
|
53127
|
+
}
|
|
53081
53128
|
function addExecuteTool(server, options) {
|
|
53082
53129
|
const {
|
|
53083
53130
|
codeModeBaseUrl,
|
package/build/cjs/toolkit.cjs
CHANGED
|
@@ -17655,6 +17655,7 @@ function rethrowIfUnauthorized(error) {
|
|
|
17655
17655
|
|
|
17656
17656
|
// src/config/api-request-rules.ts
|
|
17657
17657
|
var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
|
|
17658
|
+
var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
|
|
17658
17659
|
|
|
17659
17660
|
// src/config/default-config.ts
|
|
17660
17661
|
var AGENT_GOAL = dedent_default`
|
|
@@ -17755,7 +17756,7 @@ var SITE_CREATION_COPY = {
|
|
|
17755
17756
|
var SITE_GUIDANCE = dedent_default`
|
|
17756
17757
|
A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
|
|
17757
17758
|
|
|
17758
|
-
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool.
|
|
17759
|
+
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
17759
17760
|
|
|
17760
17761
|
Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
|
|
17761
17762
|
If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
|
|
@@ -17814,12 +17815,25 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
17814
17815
|
siteId?: string;
|
|
17815
17816
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
17816
17817
|
url: string;
|
|
17818
|
+
// Plain object → JSON. A string is sent verbatim (set your own Content-Type,
|
|
17819
|
+
// e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
|
|
17820
|
+
// for binary uploads (set your own Content-Type).
|
|
17817
17821
|
body?: unknown;
|
|
17818
17822
|
headers?: Record<string, string>;
|
|
17823
|
+
// "base64" returns the response body as a base64 string (data), with
|
|
17824
|
+
// encoding: "base64" on the result — use it for binary downloads (zip,
|
|
17825
|
+
// image, pdf); decoding those as text corrupts them. Binary content types
|
|
17826
|
+
// are returned as base64 automatically even without this. Decode, edit and
|
|
17827
|
+
// re-upload binary WITHIN this script and return only a small summary. If you
|
|
17828
|
+
// must return the bytes, return the wix.request response object itself (so
|
|
17829
|
+
// encoding: "base64" is preserved and it isn't truncated); a bare base64
|
|
17830
|
+
// string you return is treated as plain text and may be truncated.
|
|
17831
|
+
responseType?: "base64";
|
|
17819
17832
|
}
|
|
17820
17833
|
interface WixResponse<T = unknown> {
|
|
17821
17834
|
status: number;
|
|
17822
17835
|
data: T;
|
|
17836
|
+
encoding?: "base64";
|
|
17823
17837
|
json(): Promise<T>;
|
|
17824
17838
|
}
|
|
17825
17839
|
declare const wix: {
|
|
@@ -17958,6 +17972,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
17958
17972
|
ReadFullDocsArticle: dedent_default`
|
|
17959
17973
|
Fetches the full Wix docs article or method article with code examples for using the method.
|
|
17960
17974
|
Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
|
|
17975
|
+
Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
|
|
17961
17976
|
For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
|
|
17962
17977
|
${reminder}
|
|
17963
17978
|
`,
|
|
@@ -18090,7 +18105,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
18090
18105
|
`,
|
|
18091
18106
|
"import-claude-design-from-url": dedent_default`
|
|
18092
18107
|
Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
|
|
18093
|
-
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool:
|
|
18108
|
+
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
18094
18109
|
`,
|
|
18095
18110
|
RunWixCliCommand: dedent_default`
|
|
18096
18111
|
Executes Wix CLI commands for Wix app development and management.
|
|
@@ -18517,7 +18532,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
18517
18532
|
CreateWixBusinessGuide: dedent_default`
|
|
18518
18533
|
Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
|
|
18519
18534
|
Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
|
|
18520
|
-
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool —
|
|
18535
|
+
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
|
|
18521
18536
|
|
|
18522
18537
|
## What This Tool Contains
|
|
18523
18538
|
|
|
@@ -19154,7 +19169,10 @@ var paramDescriptions = {
|
|
|
19154
19169
|
ARRAY_QUERY_PARAMS_RULE
|
|
19155
19170
|
].join("\n"),
|
|
19156
19171
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
19157
|
-
body:
|
|
19172
|
+
body: [
|
|
19173
|
+
'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
19174
|
+
WQL_FILTER_RULE
|
|
19175
|
+
].join("\n"),
|
|
19158
19176
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
19159
19177
|
sourceDocUrl: [
|
|
19160
19178
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -19478,15 +19496,17 @@ Failed to fetch content: ${errorMsg}`
|
|
|
19478
19496
|
const baseContentsPromise = Promise.all(
|
|
19479
19497
|
baseDocsWithoutRecipes.map(fetchDoc)
|
|
19480
19498
|
);
|
|
19481
|
-
const skillsContentPromise = getSkillsByPortal(httpClient, {
|
|
19499
|
+
const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient, {
|
|
19482
19500
|
portalId: REST_PORTAL_ID,
|
|
19483
19501
|
...repo && { repo },
|
|
19484
19502
|
...commitHash && { commitHash },
|
|
19485
|
-
|
|
19503
|
+
tags: skillsTags
|
|
19486
19504
|
}).catch((err) => {
|
|
19487
19505
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
19488
19506
|
return null;
|
|
19489
|
-
})
|
|
19507
|
+
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
19508
|
+
(doc) => doc?.text ?? null
|
|
19509
|
+
);
|
|
19490
19510
|
const filter = {};
|
|
19491
19511
|
if (siteId) filter.siteId = siteId;
|
|
19492
19512
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -20525,6 +20545,14 @@ var import_http_client2 = __toESM(require_index_node(), 1);
|
|
|
20525
20545
|
|
|
20526
20546
|
// src/tool-utils.ts
|
|
20527
20547
|
var REST_METHOD_CONTRACT_RETRY_HINT = "Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.";
|
|
20548
|
+
var SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator \u2014 `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` \u2014 and retry without re-searching the docs.';
|
|
20549
|
+
var FIELD_CAPABILITIES_HINT = "This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.";
|
|
20550
|
+
var getRetryHint = (errorDetails) => {
|
|
20551
|
+
if (!/Filter contains unsupported operator/i.test(errorDetails)) {
|
|
20552
|
+
return REST_METHOD_CONTRACT_RETRY_HINT;
|
|
20553
|
+
}
|
|
20554
|
+
return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
|
|
20555
|
+
};
|
|
20528
20556
|
var safeParseJSON = (text) => {
|
|
20529
20557
|
try {
|
|
20530
20558
|
return JSON.parse(text);
|
|
@@ -20548,7 +20576,7 @@ var buildErrorMessage = ({
|
|
|
20548
20576
|
].filter((str) => !!str).join("\n");
|
|
20549
20577
|
return `${baseMessage}
|
|
20550
20578
|
|
|
20551
|
-
${
|
|
20579
|
+
${getRetryHint(String(errorDetails))}`;
|
|
20552
20580
|
};
|
|
20553
20581
|
var handleWixAPIResponse = async (response) => {
|
|
20554
20582
|
const requestId = response.headers?.["x-wix-request-id"];
|
|
@@ -22215,12 +22243,31 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
|
|
|
22215
22243
|
reportBi?.({
|
|
22216
22244
|
originalLength: typeof data.result === "string" ? data.result.length : JSON.stringify(data.result)?.length
|
|
22217
22245
|
});
|
|
22246
|
+
const base64Text = base64PayloadText(data.result);
|
|
22247
|
+
if (base64Text !== null) {
|
|
22248
|
+
if (base64Text.length <= MAX_ALLOWED_RESPONSE_CHARS) {
|
|
22249
|
+
return { content: [{ type: "text", text: base64Text }] };
|
|
22250
|
+
}
|
|
22251
|
+
const approxKb = Math.ceil(base64Text.length / 1024).toLocaleString();
|
|
22252
|
+
const limitKb = Math.floor(
|
|
22253
|
+
MAX_ALLOWED_RESPONSE_CHARS / 1024
|
|
22254
|
+
).toLocaleString();
|
|
22255
|
+
return executeErrorResult(
|
|
22256
|
+
`Binary (base64) result is ~${approxKb} KB, too large to return intact (limit ~${limitKb} KB); truncating it would corrupt the base64. Process the bytes inside your ExecuteWixAPI script \u2014 decode, edit, and re-upload in the same call \u2014 and return only a small summary.`
|
|
22257
|
+
);
|
|
22258
|
+
}
|
|
22218
22259
|
return {
|
|
22219
22260
|
content: [
|
|
22220
22261
|
{ type: "text", text: truncateResponse(data.result, maxResponseSize) }
|
|
22221
22262
|
]
|
|
22222
22263
|
};
|
|
22223
22264
|
}
|
|
22265
|
+
function base64PayloadText(result) {
|
|
22266
|
+
if (result !== null && typeof result === "object" && result.encoding === "base64" && typeof result.data === "string") {
|
|
22267
|
+
return JSON.stringify(result);
|
|
22268
|
+
}
|
|
22269
|
+
return null;
|
|
22270
|
+
}
|
|
22224
22271
|
function addExecuteTool(server, options) {
|
|
22225
22272
|
const {
|
|
22226
22273
|
codeModeBaseUrl,
|
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { logger } from '../infra/logger.js';
|
|
3
3
|
import { defaultToolDescriptions } from '../config/default-config.js';
|
|
4
4
|
import { truncateResponse } from './truncate-response.js';
|
|
5
|
+
import { MAX_ALLOWED_RESPONSE_CHARS } from '../infra/response-size-limits.js';
|
|
5
6
|
import { validateExecuteCode } from './validation.js';
|
|
6
7
|
import { desc } from '../config/param-descriptions.js';
|
|
7
8
|
import { rethrowIfUnauthorized } from '../auth/index.js';
|
|
@@ -176,12 +177,39 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
|
|
|
176
177
|
? data.result.length
|
|
177
178
|
: JSON.stringify(data.result)?.length
|
|
178
179
|
});
|
|
180
|
+
// A base64/binary payload (a downloaded zip, image, …) must never be sliced:
|
|
181
|
+
// a cut base64 string decodes to garbage, so the usual char-limit truncation
|
|
182
|
+
// would silently corrupt it. Return it whole up to the hard ceiling; past
|
|
183
|
+
// that, fail cleanly rather than hand back a broken blob.
|
|
184
|
+
const base64Text = base64PayloadText(data.result);
|
|
185
|
+
if (base64Text !== null) {
|
|
186
|
+
if (base64Text.length <= MAX_ALLOWED_RESPONSE_CHARS) {
|
|
187
|
+
return { content: [{ type: 'text', text: base64Text }] };
|
|
188
|
+
}
|
|
189
|
+
const approxKb = Math.ceil(base64Text.length / 1024).toLocaleString();
|
|
190
|
+
const limitKb = Math.floor(MAX_ALLOWED_RESPONSE_CHARS / 1024).toLocaleString();
|
|
191
|
+
return executeErrorResult(`Binary (base64) result is ~${approxKb} KB, too large to return intact (limit ~${limitKb} KB); truncating it would corrupt the base64. Process the bytes inside your ExecuteWixAPI script — decode, edit, and re-upload in the same call — and return only a small summary.`);
|
|
192
|
+
}
|
|
179
193
|
return {
|
|
180
194
|
content: [
|
|
181
195
|
{ type: 'text', text: truncateResponse(data.result, maxResponseSize) }
|
|
182
196
|
]
|
|
183
197
|
};
|
|
184
198
|
}
|
|
199
|
+
// A base64 payload the caller returned as a WixResponse carrying
|
|
200
|
+
// `encoding: "base64"` — the shape `wix.request` produces for a binary body.
|
|
201
|
+
// We key off that explicit marker, never a content heuristic: a long string in
|
|
202
|
+
// the base64 alphabet can be ordinary text (e.g. "x".repeat(30000)) and must
|
|
203
|
+
// still truncate normally. Returns the text to keep intact, or null otherwise.
|
|
204
|
+
function base64PayloadText(result) {
|
|
205
|
+
if (result !== null &&
|
|
206
|
+
typeof result === 'object' &&
|
|
207
|
+
result.encoding === 'base64' &&
|
|
208
|
+
typeof result.data === 'string') {
|
|
209
|
+
return JSON.stringify(result);
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
185
213
|
function addExecuteTool(server, options) {
|
|
186
214
|
const { codeModeBaseUrl, codeModeFetch, authStrategy, visitor, toolDescriptions, maxResponseSize } = options;
|
|
187
215
|
const executeUrl = `${codeModeBaseUrl}/api/code-mode/execute`;
|
|
@@ -8,4 +8,5 @@
|
|
|
8
8
|
* single unknown enum member and rejected with HTTP 400.
|
|
9
9
|
*/
|
|
10
10
|
export declare const ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
|
|
11
|
+
export declare const WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
|
|
11
12
|
//# sourceMappingURL=api-request-rules.d.ts.map
|
|
@@ -8,4 +8,5 @@
|
|
|
8
8
|
* single unknown enum member and rejected with HTTP 400.
|
|
9
9
|
*/
|
|
10
10
|
export const ARRAY_QUERY_PARAMS_RULE = 'Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).';
|
|
11
|
+
export const WQL_FILTER_RULE = 'Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators — `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.';
|
|
11
12
|
//# sourceMappingURL=api-request-rules.js.map
|
|
@@ -80,7 +80,7 @@ export const SITE_CREATION_COPY = {
|
|
|
80
80
|
const SITE_GUIDANCE = dedent `
|
|
81
81
|
A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
|
|
82
82
|
|
|
83
|
-
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool.
|
|
83
|
+
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
84
84
|
|
|
85
85
|
Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
|
|
86
86
|
If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
|
|
@@ -142,12 +142,25 @@ const ACCOUNT_SITE_EXECUTE_SCOPE = dedent `
|
|
|
142
142
|
siteId?: string;
|
|
143
143
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
144
144
|
url: string;
|
|
145
|
+
// Plain object → JSON. A string is sent verbatim (set your own Content-Type,
|
|
146
|
+
// e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
|
|
147
|
+
// for binary uploads (set your own Content-Type).
|
|
145
148
|
body?: unknown;
|
|
146
149
|
headers?: Record<string, string>;
|
|
150
|
+
// "base64" returns the response body as a base64 string (data), with
|
|
151
|
+
// encoding: "base64" on the result — use it for binary downloads (zip,
|
|
152
|
+
// image, pdf); decoding those as text corrupts them. Binary content types
|
|
153
|
+
// are returned as base64 automatically even without this. Decode, edit and
|
|
154
|
+
// re-upload binary WITHIN this script and return only a small summary. If you
|
|
155
|
+
// must return the bytes, return the wix.request response object itself (so
|
|
156
|
+
// encoding: "base64" is preserved and it isn't truncated); a bare base64
|
|
157
|
+
// string you return is treated as plain text and may be truncated.
|
|
158
|
+
responseType?: "base64";
|
|
147
159
|
}
|
|
148
160
|
interface WixResponse<T = unknown> {
|
|
149
161
|
status: number;
|
|
150
162
|
data: T;
|
|
163
|
+
encoding?: "base64";
|
|
151
164
|
json(): Promise<T>;
|
|
152
165
|
}
|
|
153
166
|
declare const wix: {
|
|
@@ -283,6 +296,7 @@ export function buildToolDescriptions(includeReadme, includeImageUploadGuidance
|
|
|
283
296
|
ReadFullDocsArticle: dedent `
|
|
284
297
|
Fetches the full Wix docs article or method article with code examples for using the method.
|
|
285
298
|
Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
|
|
299
|
+
Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
|
|
286
300
|
For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
|
|
287
301
|
${reminder}
|
|
288
302
|
`,
|
|
@@ -415,7 +429,7 @@ export function buildToolDescriptions(includeReadme, includeImageUploadGuidance
|
|
|
415
429
|
`,
|
|
416
430
|
'import-claude-design-from-url': dedent `
|
|
417
431
|
Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
|
|
418
|
-
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool:
|
|
432
|
+
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
419
433
|
`,
|
|
420
434
|
RunWixCliCommand: dedent `
|
|
421
435
|
Executes Wix CLI commands for Wix app development and management.
|
|
@@ -842,7 +856,7 @@ export function buildToolDescriptions(includeReadme, includeImageUploadGuidance
|
|
|
842
856
|
CreateWixBusinessGuide: dedent `
|
|
843
857
|
Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
|
|
844
858
|
Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
|
|
845
|
-
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool —
|
|
859
|
+
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
|
|
846
860
|
|
|
847
861
|
## What This Tool Contains
|
|
848
862
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ALLOWED_HOSTNAMES } from '../api-call/validation.js';
|
|
2
|
-
import { ARRAY_QUERY_PARAMS_RULE } from './api-request-rules.js';
|
|
2
|
+
import { ARRAY_QUERY_PARAMS_RULE, WQL_FILTER_RULE } from './api-request-rules.js';
|
|
3
3
|
/**
|
|
4
4
|
* Centralized parameter descriptions organized by tool.
|
|
5
5
|
* Each tool has all its parameter descriptions in one place.
|
|
@@ -15,7 +15,10 @@ export const paramDescriptions = {
|
|
|
15
15
|
ARRAY_QUERY_PARAMS_RULE
|
|
16
16
|
].join('\n'),
|
|
17
17
|
method: 'The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)',
|
|
18
|
-
body:
|
|
18
|
+
body: [
|
|
19
|
+
'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
20
|
+
WQL_FILTER_RULE
|
|
21
|
+
].join('\n'),
|
|
19
22
|
reason: 'One sentence explaining the original user request and why you are calling this API to complete it.',
|
|
20
23
|
sourceDocUrl: [
|
|
21
24
|
'The URL of the documentation or recipe where you found this API endpoint.',
|
|
@@ -169,17 +169,20 @@ export async function addGetToKnowTools({ server, disableTools = [], toolDescrip
|
|
|
169
169
|
// return '';
|
|
170
170
|
// });
|
|
171
171
|
const baseContentsPromise = Promise.all(baseDocsWithoutRecipes.map(fetchDoc));
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
172
|
+
// Filtered lists still come from the portal. The full management index is
|
|
173
|
+
// authored alongside the recipes and is fetched like any other article,
|
|
174
|
+
// using its commit version when a PR override is configured.
|
|
175
|
+
const skillsContentPromise = skillsTags?.length
|
|
176
|
+
? getSkillsByPortal(httpClient, {
|
|
177
|
+
portalId: REST_PORTAL_ID,
|
|
178
|
+
...(repo && { repo }),
|
|
179
|
+
...(commitHash && { commitHash }),
|
|
180
|
+
tags: skillsTags
|
|
181
|
+
}).catch((err) => {
|
|
182
|
+
console.error('[WixREADME] Failed to fetch skills by portal:', err);
|
|
183
|
+
return null;
|
|
184
|
+
})
|
|
185
|
+
: fetchDoc({ action: 'include', url: RECIPES_INDEX_URL }).then((doc) => doc?.text ?? null);
|
|
183
186
|
// Auto-inject site context. With no site targeted this is the account-wide
|
|
184
187
|
// view: single-site accounts "just work", and accounts with more than the
|
|
185
188
|
// cap show the first N sites plus a note to use GetSiteContext for the rest.
|
|
@@ -86,11 +86,11 @@ export function addImportClaudeDesignTool(server, authStrategy, options) {
|
|
|
86
86
|
designUrl = new URL(args.url);
|
|
87
87
|
}
|
|
88
88
|
catch {
|
|
89
|
-
return errorResult(
|
|
89
|
+
return errorResult("Invalid design URL — this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site.");
|
|
90
90
|
}
|
|
91
91
|
if (designUrl.protocol !== 'https:' ||
|
|
92
92
|
!designUrl.hostname.endsWith(CLAUDE_USER_CONTENT_HOST_SUFFIX)) {
|
|
93
|
-
return errorResult(
|
|
93
|
+
return errorResult("Invalid design URL — this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site.");
|
|
94
94
|
}
|
|
95
95
|
// Resolve the caller's account identity BEFORE the design fetch — the
|
|
96
96
|
// design URL is single-use, so an unauthenticated caller must fail
|
package/build/dts/tool-utils.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
const REST_METHOD_CONTRACT_RETRY_HINT = 'Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. ' +
|
|
2
2
|
'Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.';
|
|
3
|
+
const SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator — `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` — and retry without re-searching the docs.';
|
|
4
|
+
const FIELD_CAPABILITIES_HINT = 'This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.';
|
|
5
|
+
const getRetryHint = (errorDetails) => {
|
|
6
|
+
if (!/Filter contains unsupported operator/i.test(errorDetails)) {
|
|
7
|
+
return REST_METHOD_CONTRACT_RETRY_HINT;
|
|
8
|
+
}
|
|
9
|
+
// The API reports a field object with several operators as one unknown operator whose name is that object.
|
|
10
|
+
return /"operator":"\{/.test(errorDetails)
|
|
11
|
+
? SINGLE_OPERATOR_PER_FIELD_HINT
|
|
12
|
+
: FIELD_CAPABILITIES_HINT;
|
|
13
|
+
};
|
|
3
14
|
export const DEFAULT_OPENAI_SECURITY_SCHEMES = [
|
|
4
15
|
{ type: 'oauth2', scopes: ['offline_access'] }
|
|
5
16
|
];
|
|
@@ -28,7 +39,7 @@ export const buildErrorMessage = ({ status, statusText, requestId, responseData
|
|
|
28
39
|
]
|
|
29
40
|
.filter((str) => !!str)
|
|
30
41
|
.join('\n');
|
|
31
|
-
return `${baseMessage}\n\n${
|
|
42
|
+
return `${baseMessage}\n\n${getRetryHint(String(errorDetails))}`;
|
|
32
43
|
};
|
|
33
44
|
export const handleWixAPIResponse = async (response) => {
|
|
34
45
|
const requestId = response.headers?.['x-wix-request-id'];
|
package/build/esm/index.js
CHANGED
|
@@ -27117,6 +27117,14 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
27117
27117
|
|
|
27118
27118
|
// src/tool-utils.ts
|
|
27119
27119
|
var REST_METHOD_CONTRACT_RETRY_HINT = "Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.";
|
|
27120
|
+
var SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator \u2014 `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` \u2014 and retry without re-searching the docs.';
|
|
27121
|
+
var FIELD_CAPABILITIES_HINT = "This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.";
|
|
27122
|
+
var getRetryHint = (errorDetails) => {
|
|
27123
|
+
if (!/Filter contains unsupported operator/i.test(errorDetails)) {
|
|
27124
|
+
return REST_METHOD_CONTRACT_RETRY_HINT;
|
|
27125
|
+
}
|
|
27126
|
+
return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
|
|
27127
|
+
};
|
|
27120
27128
|
var DEFAULT_OPENAI_SECURITY_SCHEMES = [
|
|
27121
27129
|
{ type: "oauth2", scopes: ["offline_access"] }
|
|
27122
27130
|
];
|
|
@@ -27143,7 +27151,7 @@ var buildErrorMessage = ({
|
|
|
27143
27151
|
].filter((str) => !!str).join("\n");
|
|
27144
27152
|
return `${baseMessage}
|
|
27145
27153
|
|
|
27146
|
-
${
|
|
27154
|
+
${getRetryHint(String(errorDetails))}`;
|
|
27147
27155
|
};
|
|
27148
27156
|
var handleWixAPIResponse = async (response) => {
|
|
27149
27157
|
const requestId = response.headers?.["x-wix-request-id"];
|
|
@@ -30873,6 +30881,7 @@ function rethrowIfUnauthorized(error2) {
|
|
|
30873
30881
|
|
|
30874
30882
|
// src/config/api-request-rules.ts
|
|
30875
30883
|
var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
|
|
30884
|
+
var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
|
|
30876
30885
|
|
|
30877
30886
|
// src/config/default-config.ts
|
|
30878
30887
|
var AGENT_GOAL = dedent_default`
|
|
@@ -30973,7 +30982,7 @@ var SITE_CREATION_COPY = {
|
|
|
30973
30982
|
var SITE_GUIDANCE = dedent_default`
|
|
30974
30983
|
A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
|
|
30975
30984
|
|
|
30976
|
-
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool.
|
|
30985
|
+
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
30977
30986
|
|
|
30978
30987
|
Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
|
|
30979
30988
|
If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
|
|
@@ -31032,12 +31041,25 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
31032
31041
|
siteId?: string;
|
|
31033
31042
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
31034
31043
|
url: string;
|
|
31044
|
+
// Plain object → JSON. A string is sent verbatim (set your own Content-Type,
|
|
31045
|
+
// e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
|
|
31046
|
+
// for binary uploads (set your own Content-Type).
|
|
31035
31047
|
body?: unknown;
|
|
31036
31048
|
headers?: Record<string, string>;
|
|
31049
|
+
// "base64" returns the response body as a base64 string (data), with
|
|
31050
|
+
// encoding: "base64" on the result — use it for binary downloads (zip,
|
|
31051
|
+
// image, pdf); decoding those as text corrupts them. Binary content types
|
|
31052
|
+
// are returned as base64 automatically even without this. Decode, edit and
|
|
31053
|
+
// re-upload binary WITHIN this script and return only a small summary. If you
|
|
31054
|
+
// must return the bytes, return the wix.request response object itself (so
|
|
31055
|
+
// encoding: "base64" is preserved and it isn't truncated); a bare base64
|
|
31056
|
+
// string you return is treated as plain text and may be truncated.
|
|
31057
|
+
responseType?: "base64";
|
|
31037
31058
|
}
|
|
31038
31059
|
interface WixResponse<T = unknown> {
|
|
31039
31060
|
status: number;
|
|
31040
31061
|
data: T;
|
|
31062
|
+
encoding?: "base64";
|
|
31041
31063
|
json(): Promise<T>;
|
|
31042
31064
|
}
|
|
31043
31065
|
declare const wix: {
|
|
@@ -31176,6 +31198,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
31176
31198
|
ReadFullDocsArticle: dedent_default`
|
|
31177
31199
|
Fetches the full Wix docs article or method article with code examples for using the method.
|
|
31178
31200
|
Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
|
|
31201
|
+
Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
|
|
31179
31202
|
For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
|
|
31180
31203
|
${reminder}
|
|
31181
31204
|
`,
|
|
@@ -31308,7 +31331,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
31308
31331
|
`,
|
|
31309
31332
|
"import-claude-design-from-url": dedent_default`
|
|
31310
31333
|
Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
|
|
31311
|
-
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool:
|
|
31334
|
+
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
31312
31335
|
`,
|
|
31313
31336
|
RunWixCliCommand: dedent_default`
|
|
31314
31337
|
Executes Wix CLI commands for Wix app development and management.
|
|
@@ -31735,7 +31758,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
31735
31758
|
CreateWixBusinessGuide: dedent_default`
|
|
31736
31759
|
Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
|
|
31737
31760
|
Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
|
|
31738
|
-
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool —
|
|
31761
|
+
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
|
|
31739
31762
|
|
|
31740
31763
|
## What This Tool Contains
|
|
31741
31764
|
|
|
@@ -32372,7 +32395,10 @@ var paramDescriptions = {
|
|
|
32372
32395
|
ARRAY_QUERY_PARAMS_RULE
|
|
32373
32396
|
].join("\n"),
|
|
32374
32397
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
32375
|
-
body:
|
|
32398
|
+
body: [
|
|
32399
|
+
'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
32400
|
+
WQL_FILTER_RULE
|
|
32401
|
+
].join("\n"),
|
|
32376
32402
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
32377
32403
|
sourceDocUrl: [
|
|
32378
32404
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -32696,15 +32722,17 @@ Failed to fetch content: ${errorMsg}`
|
|
|
32696
32722
|
const baseContentsPromise = Promise.all(
|
|
32697
32723
|
baseDocsWithoutRecipes.map(fetchDoc)
|
|
32698
32724
|
);
|
|
32699
|
-
const skillsContentPromise = getSkillsByPortal(httpClient6, {
|
|
32725
|
+
const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient6, {
|
|
32700
32726
|
portalId: REST_PORTAL_ID,
|
|
32701
32727
|
...repo && { repo },
|
|
32702
32728
|
...commitHash && { commitHash },
|
|
32703
|
-
|
|
32729
|
+
tags: skillsTags
|
|
32704
32730
|
}).catch((err) => {
|
|
32705
32731
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
32706
32732
|
return null;
|
|
32707
|
-
})
|
|
32733
|
+
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
32734
|
+
(doc) => doc?.text ?? null
|
|
32735
|
+
);
|
|
32708
32736
|
const filter = {};
|
|
32709
32737
|
if (siteId) filter.siteId = siteId;
|
|
32710
32738
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -45776,12 +45804,12 @@ function addImportClaudeDesignTool(server, authStrategy, options) {
|
|
|
45776
45804
|
designUrl = new URL(args.url);
|
|
45777
45805
|
} catch {
|
|
45778
45806
|
return errorResult(
|
|
45779
|
-
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
45807
|
+
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md \u2014 it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
45780
45808
|
);
|
|
45781
45809
|
}
|
|
45782
45810
|
if (designUrl.protocol !== "https:" || !designUrl.hostname.endsWith(CLAUDE_USER_CONTENT_HOST_SUFFIX)) {
|
|
45783
45811
|
return errorResult(
|
|
45784
|
-
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry: send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
45812
|
+
"Invalid design URL \u2014 this tool only accepts the claudeusercontent.com URL produced by Claude Design. For site files the user provided themselves, do not retry this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md \u2014 it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, send the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload them and get a live hosted site."
|
|
45785
45813
|
);
|
|
45786
45814
|
}
|
|
45787
45815
|
const accountHeaders = await authStrategy.getAccountAuthHeaders();
|
|
@@ -46836,12 +46864,31 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
|
|
|
46836
46864
|
reportBi?.({
|
|
46837
46865
|
originalLength: typeof data.result === "string" ? data.result.length : JSON.stringify(data.result)?.length
|
|
46838
46866
|
});
|
|
46867
|
+
const base64Text = base64PayloadText(data.result);
|
|
46868
|
+
if (base64Text !== null) {
|
|
46869
|
+
if (base64Text.length <= MAX_ALLOWED_RESPONSE_CHARS) {
|
|
46870
|
+
return { content: [{ type: "text", text: base64Text }] };
|
|
46871
|
+
}
|
|
46872
|
+
const approxKb = Math.ceil(base64Text.length / 1024).toLocaleString();
|
|
46873
|
+
const limitKb = Math.floor(
|
|
46874
|
+
MAX_ALLOWED_RESPONSE_CHARS / 1024
|
|
46875
|
+
).toLocaleString();
|
|
46876
|
+
return executeErrorResult(
|
|
46877
|
+
`Binary (base64) result is ~${approxKb} KB, too large to return intact (limit ~${limitKb} KB); truncating it would corrupt the base64. Process the bytes inside your ExecuteWixAPI script \u2014 decode, edit, and re-upload in the same call \u2014 and return only a small summary.`
|
|
46878
|
+
);
|
|
46879
|
+
}
|
|
46839
46880
|
return {
|
|
46840
46881
|
content: [
|
|
46841
46882
|
{ type: "text", text: truncateResponse(data.result, maxResponseSize) }
|
|
46842
46883
|
]
|
|
46843
46884
|
};
|
|
46844
46885
|
}
|
|
46886
|
+
function base64PayloadText(result) {
|
|
46887
|
+
if (result !== null && typeof result === "object" && result.encoding === "base64" && typeof result.data === "string") {
|
|
46888
|
+
return JSON.stringify(result);
|
|
46889
|
+
}
|
|
46890
|
+
return null;
|
|
46891
|
+
}
|
|
46845
46892
|
function addExecuteTool(server, options) {
|
|
46846
46893
|
const {
|
|
46847
46894
|
codeModeBaseUrl,
|
package/build/esm/toolkit.js
CHANGED
|
@@ -12077,6 +12077,7 @@ function rethrowIfUnauthorized(error) {
|
|
|
12077
12077
|
|
|
12078
12078
|
// src/config/api-request-rules.ts
|
|
12079
12079
|
var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
|
|
12080
|
+
var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
|
|
12080
12081
|
|
|
12081
12082
|
// src/config/default-config.ts
|
|
12082
12083
|
var AGENT_GOAL = dedent_default`
|
|
@@ -12177,7 +12178,7 @@ var SITE_CREATION_COPY = {
|
|
|
12177
12178
|
var SITE_GUIDANCE = dedent_default`
|
|
12178
12179
|
A new-site request has two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
|
|
12179
12180
|
|
|
12180
|
-
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool.
|
|
12181
|
+
One case skips all of this: the user ALREADY HAS the finished site as files — hand-written HTML/CSS/JS, a zip, or the export of an AI builder. There is nothing to build, so don't offer AI or templates and don't call any site-creation tool. For a full agentic flow, read the recipe first and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it walks you through creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply (you can't reach the file bytes, or something fails), fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp — they drag the files in and get a live Wix-hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
12181
12182
|
|
|
12182
12183
|
Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
|
|
12183
12184
|
If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
|
|
@@ -12236,12 +12237,25 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
12236
12237
|
siteId?: string;
|
|
12237
12238
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
12238
12239
|
url: string;
|
|
12240
|
+
// Plain object → JSON. A string is sent verbatim (set your own Content-Type,
|
|
12241
|
+
// e.g. multipart/form-data). A Uint8Array/ArrayBuffer is sent as raw bytes
|
|
12242
|
+
// for binary uploads (set your own Content-Type).
|
|
12239
12243
|
body?: unknown;
|
|
12240
12244
|
headers?: Record<string, string>;
|
|
12245
|
+
// "base64" returns the response body as a base64 string (data), with
|
|
12246
|
+
// encoding: "base64" on the result — use it for binary downloads (zip,
|
|
12247
|
+
// image, pdf); decoding those as text corrupts them. Binary content types
|
|
12248
|
+
// are returned as base64 automatically even without this. Decode, edit and
|
|
12249
|
+
// re-upload binary WITHIN this script and return only a small summary. If you
|
|
12250
|
+
// must return the bytes, return the wix.request response object itself (so
|
|
12251
|
+
// encoding: "base64" is preserved and it isn't truncated); a bare base64
|
|
12252
|
+
// string you return is treated as plain text and may be truncated.
|
|
12253
|
+
responseType?: "base64";
|
|
12241
12254
|
}
|
|
12242
12255
|
interface WixResponse<T = unknown> {
|
|
12243
12256
|
status: number;
|
|
12244
12257
|
data: T;
|
|
12258
|
+
encoding?: "base64";
|
|
12245
12259
|
json(): Promise<T>;
|
|
12246
12260
|
}
|
|
12247
12261
|
declare const wix: {
|
|
@@ -12380,6 +12394,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
12380
12394
|
ReadFullDocsArticle: dedent_default`
|
|
12381
12395
|
Fetches the full Wix docs article or method article with code examples for using the method.
|
|
12382
12396
|
Docs articles looks like this: https://dev.wix.com/docs/... and they can either be general docs articles or method articles.
|
|
12397
|
+
Take the URL from the user's message or an earlier tool result. To reach an article you have no URL for, search or browse the docs first.
|
|
12383
12398
|
For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
|
|
12384
12399
|
${reminder}
|
|
12385
12400
|
`,
|
|
@@ -12512,7 +12527,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
12512
12527
|
`,
|
|
12513
12528
|
"import-claude-design-from-url": dedent_default`
|
|
12514
12529
|
Import a design created in Claude's design tool into Wix. Takes the signed claudeusercontent.com URL Claude Design produces for its self-contained HTML bundle (all images, fonts, and styles inlined); any other host is rejected. Creates a live Wix-hosted site and returns its URL.
|
|
12515
|
-
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool:
|
|
12530
|
+
NOT for site files the user provides themselves (their own HTML/CSS/JS, a zip, another builder's export) — for those, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp, where they upload the files and get a live hosted site. Give that URL exactly as written, keeping the utm_campaign=mcp parameter.
|
|
12516
12531
|
`,
|
|
12517
12532
|
RunWixCliCommand: dedent_default`
|
|
12518
12533
|
Executes Wix CLI commands for Wix app development and management.
|
|
@@ -12939,7 +12954,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
12939
12954
|
CreateWixBusinessGuide: dedent_default`
|
|
12940
12955
|
Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
|
|
12941
12956
|
Call this ONLY when the user explicitly asks for a headless site, a Wix Classic Editor site, or manual/advanced account/API-based site creation — these don't need the site's purpose first. For normal site-creation ${SITE_CREATION_COPY.normalCreationRoute.nonWidget}; for a specific template id, call \`CreateSiteFromTemplate\`.
|
|
12942
|
-
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool —
|
|
12957
|
+
Exception, even when the user says "headless": if they ALREADY HAVE the finished site as files (their own HTML/CSS/JS, a zip, an AI-builder export) and want those files hosted, don't call this tool. For a full agentic flow, read the recipe and publish the files yourself: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md — it covers creating the site and uploading the files end to end. If you can't follow it, or it doesn't apply, fall back to sending the user to https://www.wix.com/headless/drop?utm_campaign=mcp to upload the files and get a live hosted site (give that URL exactly, keeping the utm_campaign=mcp parameter). This guide's CLI flow is for BUILDING a headless frontend, not for hosting ready-made files.
|
|
12943
12958
|
|
|
12944
12959
|
## What This Tool Contains
|
|
12945
12960
|
|
|
@@ -13576,7 +13591,10 @@ var paramDescriptions = {
|
|
|
13576
13591
|
ARRAY_QUERY_PARAMS_RULE
|
|
13577
13592
|
].join("\n"),
|
|
13578
13593
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
13579
|
-
body:
|
|
13594
|
+
body: [
|
|
13595
|
+
'The request body as a JSON object or array with all the required fields and values, including nested objects. Pass the actual value (object or array), NOT a JSON string. YOU MUST NEVER MAKE UP A BODY - the body should be based on the conversation context, i.e from the user prompt OR got into the conversation context by the "ReadFullDocsArticle" tool OR by the "SearchWixAPISpec" tool OR by the "ReadFullDocsMethodSchema" tool - i.e based on the API docs, a relevant recipe you read (preferably), a code example you found in the docs, a schema you read etc.. YOU MUST NEVER ASSUME YOU KNOW WHAT THE BODY SCHEMA IS WITHOUT CONCRETE EXAMPLES OR SCHEMA DEFINITIONS FROM THE CONVERSATION CONTEXT. Prefer reading relevant recipes if you have them in context for understand the body schema for API calls.',
|
|
13596
|
+
WQL_FILTER_RULE
|
|
13597
|
+
].join("\n"),
|
|
13580
13598
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
13581
13599
|
sourceDocUrl: [
|
|
13582
13600
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -13900,15 +13918,17 @@ Failed to fetch content: ${errorMsg}`
|
|
|
13900
13918
|
const baseContentsPromise = Promise.all(
|
|
13901
13919
|
baseDocsWithoutRecipes.map(fetchDoc)
|
|
13902
13920
|
);
|
|
13903
|
-
const skillsContentPromise = getSkillsByPortal(httpClient, {
|
|
13921
|
+
const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient, {
|
|
13904
13922
|
portalId: REST_PORTAL_ID,
|
|
13905
13923
|
...repo && { repo },
|
|
13906
13924
|
...commitHash && { commitHash },
|
|
13907
|
-
|
|
13925
|
+
tags: skillsTags
|
|
13908
13926
|
}).catch((err) => {
|
|
13909
13927
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
13910
13928
|
return null;
|
|
13911
|
-
})
|
|
13929
|
+
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
13930
|
+
(doc) => doc?.text ?? null
|
|
13931
|
+
);
|
|
13912
13932
|
const filter = {};
|
|
13913
13933
|
if (siteId) filter.siteId = siteId;
|
|
13914
13934
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -14944,6 +14964,14 @@ ${text}`
|
|
|
14944
14964
|
|
|
14945
14965
|
// src/tool-utils.ts
|
|
14946
14966
|
var REST_METHOD_CONTRACT_RETRY_HINT = "Before retrying, make sure you have everything needed for a correct call: the right endpoint URL, HTTP method, request body shape, and response shape. Use the SearchWixRESTDocumentation tool or BrowseWixRESTDocsMenu tool to find the correct method or relevant related articles, the ReadFullDocsArticle tool to read the method description and all code examples, and the SearchWixAPISpec tool for precise field names and schema details.";
|
|
14967
|
+
var SINGLE_OPERATOR_PER_FIELD_HINT = 'WQL takes one operator per field object. Split the conditions into separate expressions under the matching logical operator \u2014 `{"$and": [{"field": {"$gte": ...}}, {"field": {"$lte": ...}}]}` \u2014 and retry without re-searching the docs.';
|
|
14968
|
+
var FIELD_CAPABILITIES_HINT = "This endpoint declares its filterable and sortable fields with their operators. Read the map with SearchWixAPISpec (`queryMethodData.queryFieldsCapabilitiesMap`, or `searchMethodData.searchFieldsCapabilitiesMap` on search methods) and use only what it lists; otherwise fetch a bounded page and filter or sort the results yourself.";
|
|
14969
|
+
var getRetryHint = (errorDetails) => {
|
|
14970
|
+
if (!/Filter contains unsupported operator/i.test(errorDetails)) {
|
|
14971
|
+
return REST_METHOD_CONTRACT_RETRY_HINT;
|
|
14972
|
+
}
|
|
14973
|
+
return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
|
|
14974
|
+
};
|
|
14947
14975
|
var safeParseJSON = (text) => {
|
|
14948
14976
|
try {
|
|
14949
14977
|
return JSON.parse(text);
|
|
@@ -14967,7 +14995,7 @@ var buildErrorMessage = ({
|
|
|
14967
14995
|
].filter((str) => !!str).join("\n");
|
|
14968
14996
|
return `${baseMessage}
|
|
14969
14997
|
|
|
14970
|
-
${
|
|
14998
|
+
${getRetryHint(String(errorDetails))}`;
|
|
14971
14999
|
};
|
|
14972
15000
|
var handleWixAPIResponse = async (response) => {
|
|
14973
15001
|
const requestId = response.headers?.["x-wix-request-id"];
|
|
@@ -16634,12 +16662,31 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
|
|
|
16634
16662
|
reportBi?.({
|
|
16635
16663
|
originalLength: typeof data.result === "string" ? data.result.length : JSON.stringify(data.result)?.length
|
|
16636
16664
|
});
|
|
16665
|
+
const base64Text = base64PayloadText(data.result);
|
|
16666
|
+
if (base64Text !== null) {
|
|
16667
|
+
if (base64Text.length <= MAX_ALLOWED_RESPONSE_CHARS) {
|
|
16668
|
+
return { content: [{ type: "text", text: base64Text }] };
|
|
16669
|
+
}
|
|
16670
|
+
const approxKb = Math.ceil(base64Text.length / 1024).toLocaleString();
|
|
16671
|
+
const limitKb = Math.floor(
|
|
16672
|
+
MAX_ALLOWED_RESPONSE_CHARS / 1024
|
|
16673
|
+
).toLocaleString();
|
|
16674
|
+
return executeErrorResult(
|
|
16675
|
+
`Binary (base64) result is ~${approxKb} KB, too large to return intact (limit ~${limitKb} KB); truncating it would corrupt the base64. Process the bytes inside your ExecuteWixAPI script \u2014 decode, edit, and re-upload in the same call \u2014 and return only a small summary.`
|
|
16676
|
+
);
|
|
16677
|
+
}
|
|
16637
16678
|
return {
|
|
16638
16679
|
content: [
|
|
16639
16680
|
{ type: "text", text: truncateResponse(data.result, maxResponseSize) }
|
|
16640
16681
|
]
|
|
16641
16682
|
};
|
|
16642
16683
|
}
|
|
16684
|
+
function base64PayloadText(result) {
|
|
16685
|
+
if (result !== null && typeof result === "object" && result.encoding === "base64" && typeof result.data === "string") {
|
|
16686
|
+
return JSON.stringify(result);
|
|
16687
|
+
}
|
|
16688
|
+
return null;
|
|
16689
|
+
}
|
|
16643
16690
|
function addExecuteTool(server, options) {
|
|
16644
16691
|
const {
|
|
16645
16692
|
codeModeBaseUrl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.87",
|
|
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": "
|
|
136
|
+
"falconPackageHash": "c9087b06450361359889e6ef0ea5562b59ca3f0ea641de700d905ce2"
|
|
137
137
|
}
|