@wix/mcp 1.0.85 → 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 +97 -16
- package/build/cjs/index.cjs +126 -22
- package/build/cjs/toolkit.cjs +113 -16
- 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/docs.js +5 -3
- package/build/dts/docs/get-to-know.js +14 -11
- package/build/dts/import-claude-design-tool/index.js +2 -2
- package/build/dts/infra/tool-bi.d.ts +5 -1
- package/build/dts/infra/tool-bi.js +22 -1
- package/build/dts/tool-utils.js +12 -1
- package/build/dts/toolkit-entry.d.cts +5 -1
- package/build/dts/toolkit-entry.d.ts +5 -1
- package/build/dts/toolkit.js +1 -1
- package/build/dts/wix-mcp-server.js +3 -0
- package/build/esm/index.js +126 -22
- package/build/esm/toolkit.js +113 -16
- package/package.json +3 -3
package/build/dts/toolkit.js
CHANGED
|
@@ -319,7 +319,7 @@ export function createWixToolkit(options) {
|
|
|
319
319
|
additionalFields = formatToolResultAdditionalFields(cbResult, {
|
|
320
320
|
returnedRows: toolBiParams.returnedRows,
|
|
321
321
|
originalLength: toolBiParams.originalLength
|
|
322
|
-
});
|
|
322
|
+
}, { name: clientName });
|
|
323
323
|
}
|
|
324
324
|
// Panorama: finish or report error
|
|
325
325
|
if (!isDevEnvironment) {
|
|
@@ -183,6 +183,9 @@ export class WixMcpServer extends McpServer {
|
|
|
183
183
|
additionalFields = formatToolResultAdditionalFields(cbResult, {
|
|
184
184
|
returnedRows: toolBiParams.returnedRows,
|
|
185
185
|
originalLength: toolBiParams.originalLength
|
|
186
|
+
}, {
|
|
187
|
+
name: this.getClientName?.() || this.server.getClientVersion()?.name,
|
|
188
|
+
userAgent: this.getUserAgent?.()
|
|
186
189
|
});
|
|
187
190
|
}
|
|
188
191
|
if (toolSucceeded && !isDevEnvironment) {
|
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"];
|
|
@@ -29740,7 +29748,25 @@ function extractText(result) {
|
|
|
29740
29748
|
return result.content.filter((content) => content.type === "text" && content.text != null).map((content) => content.text).join("\n");
|
|
29741
29749
|
}
|
|
29742
29750
|
var TOOL_RESULT_PREVIEW_MAX_CHARS = 4e3;
|
|
29743
|
-
|
|
29751
|
+
var CODEX_OUTPUT_BUDGET_BYTES = 4e4;
|
|
29752
|
+
function getCodexTruncation(resultText, client) {
|
|
29753
|
+
const isCodex = [client?.name, client?.userAgent].some(
|
|
29754
|
+
(identity) => identity?.toLowerCase().includes("codex")
|
|
29755
|
+
);
|
|
29756
|
+
if (!isCodex) {
|
|
29757
|
+
return void 0;
|
|
29758
|
+
}
|
|
29759
|
+
const resultBytes = new TextEncoder().encode(resultText).length;
|
|
29760
|
+
if (resultBytes <= CODEX_OUTPUT_BUDGET_BYTES) {
|
|
29761
|
+
return void 0;
|
|
29762
|
+
}
|
|
29763
|
+
return {
|
|
29764
|
+
resultBytes,
|
|
29765
|
+
budgetBytes: CODEX_OUTPUT_BUDGET_BYTES,
|
|
29766
|
+
truncatedBytes: resultBytes - CODEX_OUTPUT_BUDGET_BYTES
|
|
29767
|
+
};
|
|
29768
|
+
}
|
|
29769
|
+
function formatToolResultAdditionalFields(result, extras, client) {
|
|
29744
29770
|
const resultText = extractText(result);
|
|
29745
29771
|
const contentTypes = [
|
|
29746
29772
|
...new Set(
|
|
@@ -29757,6 +29783,7 @@ function formatToolResultAdditionalFields(result, extras) {
|
|
|
29757
29783
|
resultTextLength: resultText.length,
|
|
29758
29784
|
resultPreviewTruncated: resultText.length > TOOL_RESULT_PREVIEW_MAX_CHARS,
|
|
29759
29785
|
resultContentTypes: contentTypes,
|
|
29786
|
+
codexTruncation: getCodexTruncation(resultText, client),
|
|
29760
29787
|
...extras
|
|
29761
29788
|
});
|
|
29762
29789
|
}
|
|
@@ -29938,10 +29965,17 @@ var WixMcpServer = class extends McpServer {
|
|
|
29938
29965
|
if (!toolSucceeded) {
|
|
29939
29966
|
errorBody = extractText(cbResult);
|
|
29940
29967
|
} else {
|
|
29941
|
-
additionalFields = formatToolResultAdditionalFields(
|
|
29942
|
-
|
|
29943
|
-
|
|
29944
|
-
|
|
29968
|
+
additionalFields = formatToolResultAdditionalFields(
|
|
29969
|
+
cbResult,
|
|
29970
|
+
{
|
|
29971
|
+
returnedRows: toolBiParams.returnedRows,
|
|
29972
|
+
originalLength: toolBiParams.originalLength
|
|
29973
|
+
},
|
|
29974
|
+
{
|
|
29975
|
+
name: this.getClientName?.() || this.server.getClientVersion()?.name,
|
|
29976
|
+
userAgent: this.getUserAgent?.()
|
|
29977
|
+
}
|
|
29978
|
+
);
|
|
29945
29979
|
}
|
|
29946
29980
|
if (toolSucceeded && !isDevEnvironment) {
|
|
29947
29981
|
panorama.transaction(toolName).finish({ toolInvocationId });
|
|
@@ -30847,6 +30881,7 @@ function rethrowIfUnauthorized(error2) {
|
|
|
30847
30881
|
|
|
30848
30882
|
// src/config/api-request-rules.ts
|
|
30849
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.";
|
|
30850
30885
|
|
|
30851
30886
|
// src/config/default-config.ts
|
|
30852
30887
|
var AGENT_GOAL = dedent_default`
|
|
@@ -30947,7 +30982,7 @@ var SITE_CREATION_COPY = {
|
|
|
30947
30982
|
var SITE_GUIDANCE = dedent_default`
|
|
30948
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.
|
|
30949
30984
|
|
|
30950
|
-
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.
|
|
30951
30986
|
|
|
30952
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.
|
|
30953
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.
|
|
@@ -31006,12 +31041,25 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
31006
31041
|
siteId?: string;
|
|
31007
31042
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
31008
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).
|
|
31009
31047
|
body?: unknown;
|
|
31010
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";
|
|
31011
31058
|
}
|
|
31012
31059
|
interface WixResponse<T = unknown> {
|
|
31013
31060
|
status: number;
|
|
31014
31061
|
data: T;
|
|
31062
|
+
encoding?: "base64";
|
|
31015
31063
|
json(): Promise<T>;
|
|
31016
31064
|
}
|
|
31017
31065
|
declare const wix: {
|
|
@@ -31150,6 +31198,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
31150
31198
|
ReadFullDocsArticle: dedent_default`
|
|
31151
31199
|
Fetches the full Wix docs article or method article with code examples for using the method.
|
|
31152
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.
|
|
31153
31202
|
For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include ?apiView=SDK.
|
|
31154
31203
|
${reminder}
|
|
31155
31204
|
`,
|
|
@@ -31282,7 +31331,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
31282
31331
|
`,
|
|
31283
31332
|
"import-claude-design-from-url": dedent_default`
|
|
31284
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.
|
|
31285
|
-
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.
|
|
31286
31335
|
`,
|
|
31287
31336
|
RunWixCliCommand: dedent_default`
|
|
31288
31337
|
Executes Wix CLI commands for Wix app development and management.
|
|
@@ -31709,7 +31758,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
31709
31758
|
CreateWixBusinessGuide: dedent_default`
|
|
31710
31759
|
Provides comprehensive documentation for creating a new Wix business (site, app, etc.).
|
|
31711
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\`.
|
|
31712
|
-
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.
|
|
31713
31762
|
|
|
31714
31763
|
## What This Tool Contains
|
|
31715
31764
|
|
|
@@ -31996,6 +32045,22 @@ function renderApps(apps, knownApps) {
|
|
|
31996
32045
|
}
|
|
31997
32046
|
return lines.join("\n");
|
|
31998
32047
|
}
|
|
32048
|
+
function sanitizeCustomAppName(raw) {
|
|
32049
|
+
return raw.replace(/[\x00-\x1f\x7f]/g, " ").replace(/[`*_[\]|<>]/g, "").replace(/\s+/g, " ").trim().slice(0, 60);
|
|
32050
|
+
}
|
|
32051
|
+
function renderCustomAppsWithSkillsTools(apps) {
|
|
32052
|
+
const relevant = apps.filter((a2) => a2.appId && (a2.hasSkills || a2.hasTools)).sort(
|
|
32053
|
+
(a2, b2) => (a2.appName ?? a2.appId ?? "").localeCompare(b2.appName ?? b2.appId ?? "")
|
|
32054
|
+
);
|
|
32055
|
+
if (!relevant.length) return "";
|
|
32056
|
+
const lines = [];
|
|
32057
|
+
for (const app of relevant) {
|
|
32058
|
+
const sanitizedName = app.appName ? sanitizeCustomAppName(app.appName) : "";
|
|
32059
|
+
const name = sanitizedName || app.appId;
|
|
32060
|
+
lines.push(`- \`${name}\` (ID: \`${app.appId}\`)`);
|
|
32061
|
+
}
|
|
32062
|
+
return lines.join("\n");
|
|
32063
|
+
}
|
|
31999
32064
|
function renderProperties(props) {
|
|
32000
32065
|
const sections = [];
|
|
32001
32066
|
const regionalFormat = [];
|
|
@@ -32058,6 +32123,15 @@ function renderSite(site, index, knownApps) {
|
|
|
32058
32123
|
lines.push("");
|
|
32059
32124
|
lines.push(appsContent);
|
|
32060
32125
|
}
|
|
32126
|
+
const customAppsWithSkillsToolsContent = renderCustomAppsWithSkillsTools(
|
|
32127
|
+
site.customApps ?? []
|
|
32128
|
+
);
|
|
32129
|
+
if (customAppsWithSkillsToolsContent) {
|
|
32130
|
+
lines.push("");
|
|
32131
|
+
lines.push("### Custom Apps with skills and tools");
|
|
32132
|
+
lines.push("");
|
|
32133
|
+
lines.push(customAppsWithSkillsToolsContent);
|
|
32134
|
+
}
|
|
32061
32135
|
lines.push("");
|
|
32062
32136
|
lines.push("---");
|
|
32063
32137
|
lines.push("");
|
|
@@ -32321,7 +32395,10 @@ var paramDescriptions = {
|
|
|
32321
32395
|
ARRAY_QUERY_PARAMS_RULE
|
|
32322
32396
|
].join("\n"),
|
|
32323
32397
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
32324
|
-
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"),
|
|
32325
32402
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
32326
32403
|
sourceDocUrl: [
|
|
32327
32404
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -32645,15 +32722,17 @@ Failed to fetch content: ${errorMsg}`
|
|
|
32645
32722
|
const baseContentsPromise = Promise.all(
|
|
32646
32723
|
baseDocsWithoutRecipes.map(fetchDoc)
|
|
32647
32724
|
);
|
|
32648
|
-
const skillsContentPromise = getSkillsByPortal(httpClient6, {
|
|
32725
|
+
const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient6, {
|
|
32649
32726
|
portalId: REST_PORTAL_ID,
|
|
32650
32727
|
...repo && { repo },
|
|
32651
32728
|
...commitHash && { commitHash },
|
|
32652
|
-
|
|
32729
|
+
tags: skillsTags
|
|
32653
32730
|
}).catch((err) => {
|
|
32654
32731
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
32655
32732
|
return null;
|
|
32656
|
-
})
|
|
32733
|
+
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
32734
|
+
(doc) => doc?.text ?? null
|
|
32735
|
+
);
|
|
32657
32736
|
const filter = {};
|
|
32658
32737
|
if (siteId) filter.siteId = siteId;
|
|
32659
32738
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -32860,7 +32939,9 @@ function getErrorMessage(error2) {
|
|
|
32860
32939
|
}
|
|
32861
32940
|
function shouldTryMenuFallbackForDocsRead(error2, articleUrl) {
|
|
32862
32941
|
const message = getErrorMessage(error2);
|
|
32863
|
-
|
|
32942
|
+
const { pathname } = new URL(articleUrl);
|
|
32943
|
+
const isMenuFallbackUrl = articleUrl.includes("/api-reference/") || pathname.startsWith("/docs/velo");
|
|
32944
|
+
if (!message.includes("404") || !isMenuFallbackUrl) {
|
|
32864
32945
|
return false;
|
|
32865
32946
|
}
|
|
32866
32947
|
return !["This resource is deprecated", "No schema found"].some(
|
|
@@ -33513,7 +33594,7 @@ var addDocsTools = (server, allowedTools = [
|
|
|
33513
33594
|
content: [
|
|
33514
33595
|
{
|
|
33515
33596
|
type: "text",
|
|
33516
|
-
text: `Note: "${articleUrl}" is
|
|
33597
|
+
text: `Note: "${articleUrl}" is not an article. Showing the closest documentation menu below; read the article you need from its links. For category URLs, use BrowseWixRESTDocsMenu directly next time.
|
|
33517
33598
|
|
|
33518
33599
|
${text}`
|
|
33519
33600
|
}
|
|
@@ -33605,7 +33686,7 @@ ${text}`
|
|
|
33605
33686
|
content: [
|
|
33606
33687
|
{
|
|
33607
33688
|
type: "text",
|
|
33608
|
-
text: `Note: "${articleUrl}" is
|
|
33689
|
+
text: `Note: "${articleUrl}" is not an article. Showing the closest documentation menu below; read the article you need from its links. For category URLs, use BrowseWixRESTDocsMenu directly next time.
|
|
33609
33690
|
|
|
33610
33691
|
${text}`
|
|
33611
33692
|
}
|
|
@@ -45723,12 +45804,12 @@ function addImportClaudeDesignTool(server, authStrategy, options) {
|
|
|
45723
45804
|
designUrl = new URL(args.url);
|
|
45724
45805
|
} catch {
|
|
45725
45806
|
return errorResult(
|
|
45726
|
-
"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."
|
|
45727
45808
|
);
|
|
45728
45809
|
}
|
|
45729
45810
|
if (designUrl.protocol !== "https:" || !designUrl.hostname.endsWith(CLAUDE_USER_CONTENT_HOST_SUFFIX)) {
|
|
45730
45811
|
return errorResult(
|
|
45731
|
-
"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."
|
|
45732
45813
|
);
|
|
45733
45814
|
}
|
|
45734
45815
|
const accountHeaders = await authStrategy.getAccountAuthHeaders();
|
|
@@ -46783,12 +46864,31 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
|
|
|
46783
46864
|
reportBi?.({
|
|
46784
46865
|
originalLength: typeof data.result === "string" ? data.result.length : JSON.stringify(data.result)?.length
|
|
46785
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
|
+
}
|
|
46786
46880
|
return {
|
|
46787
46881
|
content: [
|
|
46788
46882
|
{ type: "text", text: truncateResponse(data.result, maxResponseSize) }
|
|
46789
46883
|
]
|
|
46790
46884
|
};
|
|
46791
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
|
+
}
|
|
46792
46892
|
function addExecuteTool(server, options) {
|
|
46793
46893
|
const {
|
|
46794
46894
|
codeModeBaseUrl,
|
|
@@ -47160,10 +47260,14 @@ function createWixToolkit(options) {
|
|
|
47160
47260
|
if (!toolSucceeded) {
|
|
47161
47261
|
errorBody = extractText(cbResult);
|
|
47162
47262
|
} else {
|
|
47163
|
-
additionalFields = formatToolResultAdditionalFields(
|
|
47164
|
-
|
|
47165
|
-
|
|
47166
|
-
|
|
47263
|
+
additionalFields = formatToolResultAdditionalFields(
|
|
47264
|
+
cbResult,
|
|
47265
|
+
{
|
|
47266
|
+
returnedRows: toolBiParams.returnedRows,
|
|
47267
|
+
originalLength: toolBiParams.originalLength
|
|
47268
|
+
},
|
|
47269
|
+
{ name: clientName }
|
|
47270
|
+
);
|
|
47167
47271
|
}
|
|
47168
47272
|
if (!isDevEnvironment) {
|
|
47169
47273
|
if (toolSucceeded) {
|
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
|
|
|
@@ -13226,6 +13241,22 @@ function renderApps(apps, knownApps) {
|
|
|
13226
13241
|
}
|
|
13227
13242
|
return lines.join("\n");
|
|
13228
13243
|
}
|
|
13244
|
+
function sanitizeCustomAppName(raw) {
|
|
13245
|
+
return raw.replace(/[\x00-\x1f\x7f]/g, " ").replace(/[`*_[\]|<>]/g, "").replace(/\s+/g, " ").trim().slice(0, 60);
|
|
13246
|
+
}
|
|
13247
|
+
function renderCustomAppsWithSkillsTools(apps) {
|
|
13248
|
+
const relevant = apps.filter((a) => a.appId && (a.hasSkills || a.hasTools)).sort(
|
|
13249
|
+
(a, b) => (a.appName ?? a.appId ?? "").localeCompare(b.appName ?? b.appId ?? "")
|
|
13250
|
+
);
|
|
13251
|
+
if (!relevant.length) return "";
|
|
13252
|
+
const lines = [];
|
|
13253
|
+
for (const app of relevant) {
|
|
13254
|
+
const sanitizedName = app.appName ? sanitizeCustomAppName(app.appName) : "";
|
|
13255
|
+
const name = sanitizedName || app.appId;
|
|
13256
|
+
lines.push(`- \`${name}\` (ID: \`${app.appId}\`)`);
|
|
13257
|
+
}
|
|
13258
|
+
return lines.join("\n");
|
|
13259
|
+
}
|
|
13229
13260
|
function renderProperties(props) {
|
|
13230
13261
|
const sections = [];
|
|
13231
13262
|
const regionalFormat = [];
|
|
@@ -13288,6 +13319,15 @@ function renderSite(site, index, knownApps) {
|
|
|
13288
13319
|
lines.push("");
|
|
13289
13320
|
lines.push(appsContent);
|
|
13290
13321
|
}
|
|
13322
|
+
const customAppsWithSkillsToolsContent = renderCustomAppsWithSkillsTools(
|
|
13323
|
+
site.customApps ?? []
|
|
13324
|
+
);
|
|
13325
|
+
if (customAppsWithSkillsToolsContent) {
|
|
13326
|
+
lines.push("");
|
|
13327
|
+
lines.push("### Custom Apps with skills and tools");
|
|
13328
|
+
lines.push("");
|
|
13329
|
+
lines.push(customAppsWithSkillsToolsContent);
|
|
13330
|
+
}
|
|
13291
13331
|
lines.push("");
|
|
13292
13332
|
lines.push("---");
|
|
13293
13333
|
lines.push("");
|
|
@@ -13551,7 +13591,10 @@ var paramDescriptions = {
|
|
|
13551
13591
|
ARRAY_QUERY_PARAMS_RULE
|
|
13552
13592
|
].join("\n"),
|
|
13553
13593
|
method: "The HTTP method to use for the API call (e.g. GET, POST, PUT, DELETE)",
|
|
13554
|
-
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"),
|
|
13555
13598
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
13556
13599
|
sourceDocUrl: [
|
|
13557
13600
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
@@ -13875,15 +13918,17 @@ Failed to fetch content: ${errorMsg}`
|
|
|
13875
13918
|
const baseContentsPromise = Promise.all(
|
|
13876
13919
|
baseDocsWithoutRecipes.map(fetchDoc)
|
|
13877
13920
|
);
|
|
13878
|
-
const skillsContentPromise = getSkillsByPortal(httpClient, {
|
|
13921
|
+
const skillsContentPromise = skillsTags?.length ? getSkillsByPortal(httpClient, {
|
|
13879
13922
|
portalId: REST_PORTAL_ID,
|
|
13880
13923
|
...repo && { repo },
|
|
13881
13924
|
...commitHash && { commitHash },
|
|
13882
|
-
|
|
13925
|
+
tags: skillsTags
|
|
13883
13926
|
}).catch((err) => {
|
|
13884
13927
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
13885
13928
|
return null;
|
|
13886
|
-
})
|
|
13929
|
+
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
13930
|
+
(doc) => doc?.text ?? null
|
|
13931
|
+
);
|
|
13887
13932
|
const filter = {};
|
|
13888
13933
|
if (siteId) filter.siteId = siteId;
|
|
13889
13934
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -14079,7 +14124,9 @@ function getErrorMessage(error) {
|
|
|
14079
14124
|
}
|
|
14080
14125
|
function shouldTryMenuFallbackForDocsRead(error, articleUrl) {
|
|
14081
14126
|
const message = getErrorMessage(error);
|
|
14082
|
-
|
|
14127
|
+
const { pathname } = new URL(articleUrl);
|
|
14128
|
+
const isMenuFallbackUrl = articleUrl.includes("/api-reference/") || pathname.startsWith("/docs/velo");
|
|
14129
|
+
if (!message.includes("404") || !isMenuFallbackUrl) {
|
|
14083
14130
|
return false;
|
|
14084
14131
|
}
|
|
14085
14132
|
return !["This resource is deprecated", "No schema found"].some(
|
|
@@ -14732,7 +14779,7 @@ var addDocsTools = (server, allowedTools = [
|
|
|
14732
14779
|
content: [
|
|
14733
14780
|
{
|
|
14734
14781
|
type: "text",
|
|
14735
|
-
text: `Note: "${articleUrl}" is
|
|
14782
|
+
text: `Note: "${articleUrl}" is not an article. Showing the closest documentation menu below; read the article you need from its links. For category URLs, use BrowseWixRESTDocsMenu directly next time.
|
|
14736
14783
|
|
|
14737
14784
|
${text}`
|
|
14738
14785
|
}
|
|
@@ -14824,7 +14871,7 @@ ${text}`
|
|
|
14824
14871
|
content: [
|
|
14825
14872
|
{
|
|
14826
14873
|
type: "text",
|
|
14827
|
-
text: `Note: "${articleUrl}" is
|
|
14874
|
+
text: `Note: "${articleUrl}" is not an article. Showing the closest documentation menu below; read the article you need from its links. For category URLs, use BrowseWixRESTDocsMenu directly next time.
|
|
14828
14875
|
|
|
14829
14876
|
${text}`
|
|
14830
14877
|
}
|
|
@@ -14917,6 +14964,14 @@ ${text}`
|
|
|
14917
14964
|
|
|
14918
14965
|
// src/tool-utils.ts
|
|
14919
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
|
+
};
|
|
14920
14975
|
var safeParseJSON = (text) => {
|
|
14921
14976
|
try {
|
|
14922
14977
|
return JSON.parse(text);
|
|
@@ -14940,7 +14995,7 @@ var buildErrorMessage = ({
|
|
|
14940
14995
|
].filter((str) => !!str).join("\n");
|
|
14941
14996
|
return `${baseMessage}
|
|
14942
14997
|
|
|
14943
|
-
${
|
|
14998
|
+
${getRetryHint(String(errorDetails))}`;
|
|
14944
14999
|
};
|
|
14945
15000
|
var handleWixAPIResponse = async (response) => {
|
|
14946
15001
|
const requestId = response.headers?.["x-wix-request-id"];
|
|
@@ -16607,12 +16662,31 @@ function formatExecuteResult(data, maxResponseSize, reportBi) {
|
|
|
16607
16662
|
reportBi?.({
|
|
16608
16663
|
originalLength: typeof data.result === "string" ? data.result.length : JSON.stringify(data.result)?.length
|
|
16609
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
|
+
}
|
|
16610
16678
|
return {
|
|
16611
16679
|
content: [
|
|
16612
16680
|
{ type: "text", text: truncateResponse(data.result, maxResponseSize) }
|
|
16613
16681
|
]
|
|
16614
16682
|
};
|
|
16615
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
|
+
}
|
|
16616
16690
|
function addExecuteTool(server, options) {
|
|
16617
16691
|
const {
|
|
16618
16692
|
codeModeBaseUrl,
|
|
@@ -18566,7 +18640,25 @@ function extractText(result) {
|
|
|
18566
18640
|
return result.content.filter((content) => content.type === "text" && content.text != null).map((content) => content.text).join("\n");
|
|
18567
18641
|
}
|
|
18568
18642
|
var TOOL_RESULT_PREVIEW_MAX_CHARS = 4e3;
|
|
18569
|
-
|
|
18643
|
+
var CODEX_OUTPUT_BUDGET_BYTES = 4e4;
|
|
18644
|
+
function getCodexTruncation(resultText, client) {
|
|
18645
|
+
const isCodex = [client?.name, client?.userAgent].some(
|
|
18646
|
+
(identity) => identity?.toLowerCase().includes("codex")
|
|
18647
|
+
);
|
|
18648
|
+
if (!isCodex) {
|
|
18649
|
+
return void 0;
|
|
18650
|
+
}
|
|
18651
|
+
const resultBytes = new TextEncoder().encode(resultText).length;
|
|
18652
|
+
if (resultBytes <= CODEX_OUTPUT_BUDGET_BYTES) {
|
|
18653
|
+
return void 0;
|
|
18654
|
+
}
|
|
18655
|
+
return {
|
|
18656
|
+
resultBytes,
|
|
18657
|
+
budgetBytes: CODEX_OUTPUT_BUDGET_BYTES,
|
|
18658
|
+
truncatedBytes: resultBytes - CODEX_OUTPUT_BUDGET_BYTES
|
|
18659
|
+
};
|
|
18660
|
+
}
|
|
18661
|
+
function formatToolResultAdditionalFields(result, extras, client) {
|
|
18570
18662
|
const resultText = extractText(result);
|
|
18571
18663
|
const contentTypes = [
|
|
18572
18664
|
...new Set(
|
|
@@ -18583,6 +18675,7 @@ function formatToolResultAdditionalFields(result, extras) {
|
|
|
18583
18675
|
resultTextLength: resultText.length,
|
|
18584
18676
|
resultPreviewTruncated: resultText.length > TOOL_RESULT_PREVIEW_MAX_CHARS,
|
|
18585
18677
|
resultContentTypes: contentTypes,
|
|
18678
|
+
codexTruncation: getCodexTruncation(resultText, client),
|
|
18586
18679
|
...extras
|
|
18587
18680
|
});
|
|
18588
18681
|
}
|
|
@@ -18838,10 +18931,14 @@ function createWixToolkit(options) {
|
|
|
18838
18931
|
if (!toolSucceeded) {
|
|
18839
18932
|
errorBody = extractText(cbResult);
|
|
18840
18933
|
} else {
|
|
18841
|
-
additionalFields = formatToolResultAdditionalFields(
|
|
18842
|
-
|
|
18843
|
-
|
|
18844
|
-
|
|
18934
|
+
additionalFields = formatToolResultAdditionalFields(
|
|
18935
|
+
cbResult,
|
|
18936
|
+
{
|
|
18937
|
+
returnedRows: toolBiParams.returnedRows,
|
|
18938
|
+
originalLength: toolBiParams.originalLength
|
|
18939
|
+
},
|
|
18940
|
+
{ name: clientName }
|
|
18941
|
+
);
|
|
18845
18942
|
}
|
|
18846
18943
|
if (!isDevEnvironment) {
|
|
18847
18944
|
if (toolSucceeded) {
|
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": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@wix/bi-logger-wix-code-data": "^1.485.0",
|
|
44
44
|
"@wix/common-widget-types": "^1.77.0",
|
|
45
45
|
"@wix/design-system": "^1.256.2",
|
|
46
|
-
"@wix/dynamic-context-enricher": "0.1.
|
|
46
|
+
"@wix/dynamic-context-enricher": "0.1.4",
|
|
47
47
|
"@wix/http-client": "^2.85.0",
|
|
48
48
|
"@wix/panorama-client-node": "^3.253.0",
|
|
49
49
|
"@wix/standalone-node-bi-logger": "^1.7.24",
|
|
@@ -133,5 +133,5 @@
|
|
|
133
133
|
]
|
|
134
134
|
}
|
|
135
135
|
},
|
|
136
|
-
"falconPackageHash": "
|
|
136
|
+
"falconPackageHash": "c9087b06450361359889e6ef0ea5562b59ca3f0ea641de700d905ce2"
|
|
137
137
|
}
|