@wix/mcp 1.0.95 → 1.0.96
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 +352 -22
- package/build/cjs/index.cjs +910 -530
- package/build/cjs/toolkit.cjs +405 -46
- package/build/dts/api-call/index.js +23 -1
- package/build/dts/api-call/upload-headless-website-files.d.ts +31 -2
- package/build/dts/api-call/upload-headless-website-files.js +107 -15
- package/build/dts/code-mode/attachments.d.ts +9 -6
- package/build/dts/code-mode/attachments.js +23 -16
- package/build/dts/code-mode/index.js +2 -2
- package/build/dts/config/default-config.d.ts +1 -1
- package/build/dts/config/default-config.js +17 -16
- package/build/dts/docs/docs.js +64 -1
- package/build/dts/docs/guessed-url.d.ts +41 -0
- package/build/dts/docs/guessed-url.js +185 -0
- package/build/dts/infra/redact-personal-data.d.ts +1 -1
- package/build/dts/infra/redact-personal-data.js +72 -3
- package/build/dts/site-widget-tools/constants.d.ts +3 -3
- package/build/dts/site-widget-tools/constants.js +3 -3
- package/build/dts/site-widget-tools/pull-site-creation-job-tool/index.js +1 -1
- package/build/dts/site-widget-tools/search-site-templates-tool/index.js +10 -1
- package/build/dts/site-widget-tools/site-builder-tool/index.js +14 -2
- package/build/dts/site-widget-tools/suggested-domain-tool/index.js +20 -9
- package/build/dts/tool-utils.d.ts +8 -1
- package/build/dts/tool-utils.js +26 -2
- package/build/dts/toolkit.js +7 -1
- package/build/esm/index.js +793 -413
- package/build/esm/toolkit.js +405 -46
- package/package.json +2 -2
|
@@ -8,6 +8,7 @@ import { RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server';
|
|
|
8
8
|
import { defaultToolDescriptions } from '../../config/default-config.js';
|
|
9
9
|
import { EDITOR_NOT_REQUESTED_MESSAGE, NOT_REQUESTED_WIDGET_PAYLOAD, SEARCH_SITE_TEMPLATES_TOOL_NAME, CREATE_SITE_FROM_TEMPLATE_TOOL_NAME, SITE_WIDGET_MCP_CSP, OPEN_AI_SITE_WIDGET_CSP } from '../constants.js';
|
|
10
10
|
import { withJsonContent } from '../../tool-utils.js';
|
|
11
|
+
import { NO_PERSONAL_DATA, START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS } from '../../docs/start-deploy-website.js';
|
|
11
12
|
// baseURL pins the host so the ambassador resolves to the public template-search
|
|
12
13
|
// endpoint: https://www.wix.com/_api/template-cms-view-service/view/v2/templates/search
|
|
13
14
|
const httpClient = createHttpClient({ baseURL: 'https://www.wix.com' });
|
|
@@ -73,7 +74,15 @@ export function addSearchSiteTemplatesTool(server, _authStrategy, options) {
|
|
|
73
74
|
templatesExplicitlyRequested: z
|
|
74
75
|
.boolean()
|
|
75
76
|
.optional()
|
|
76
|
-
.describe("Did the user, in their own words or their answer to your question, ask for a template, Wix Studio, or the Classic Editor by name? Wanting Wix's editor, or to design the site themselves, is not that: ask them how to start first. Nor are a site's business, features or look.")
|
|
77
|
+
.describe("Did the user, in their own words or their answer to your question, ask for a template, Wix Studio, or the Classic Editor by name? Wanting Wix's editor, or to design the site themselves, is not that: ask them how to start first. Nor are a site's business, features or look."),
|
|
78
|
+
templateRequest: z
|
|
79
|
+
.string()
|
|
80
|
+
.optional()
|
|
81
|
+
.describe(`The user's own words that asked for a template, Wix Studio or the Classic Editor, quoted from their message or their answer to your question. Empty when they asked for none of them; then templatesExplicitlyRequested is false. Recorded, not checked. ${NO_PERSONAL_DATA}`),
|
|
82
|
+
agentIdentity: z
|
|
83
|
+
.string()
|
|
84
|
+
.optional()
|
|
85
|
+
.describe(START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.agentIdentity)
|
|
77
86
|
},
|
|
78
87
|
_meta: {
|
|
79
88
|
ui: {
|
|
@@ -5,6 +5,7 @@ import { RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server';
|
|
|
5
5
|
import { EDITOR_NOT_REQUESTED_MESSAGE, NOT_REQUESTED_WIDGET_PAYLOAD, SITE_BUILDER_TOOL_NAME, SITE_WIDGET_MCP_CSP, OPEN_AI_SITE_WIDGET_CSP, OPENAI_WIDGET_MIME_TYPE } from '../constants.js';
|
|
6
6
|
import { defaultToolDescriptions } from '../../config/default-config.js';
|
|
7
7
|
import { withJsonContent } from '../../tool-utils.js';
|
|
8
|
+
import { NO_PERSONAL_DATA, START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS } from '../../docs/start-deploy-website.js';
|
|
8
9
|
const httpClient = createHttpClient();
|
|
9
10
|
const CREATE_SITE_WIDGET_URI = 'ui://widget/site-builder.html';
|
|
10
11
|
export function addCreateSiteWidgetTool(server, authStrategy, options) {
|
|
@@ -71,7 +72,15 @@ export function addCreateSiteWidgetTool(server, authStrategy, options) {
|
|
|
71
72
|
wixEditorExplicitlyRequested: z
|
|
72
73
|
.boolean()
|
|
73
74
|
.optional()
|
|
74
|
-
.describe("Did the user, in their own words or their answer to your question, ask for the Wix Harmony Editor, or for Wix to design the site? Wanting Wix's editor, or to design the site themselves, is not that: ask them how to start first. Nor are a site's business, features or look.")
|
|
75
|
+
.describe("Did the user, in their own words or their answer to your question, ask for the Wix Harmony Editor, or for Wix to design the site in Wix's editor? Asking for a site on Wix, or for Wix to build or make one, is not that. Wanting Wix's editor, or to design the site themselves, is not that either: ask them how to start first. Nor are a site's business, features or look."),
|
|
76
|
+
editorRequest: z
|
|
77
|
+
.string()
|
|
78
|
+
.optional()
|
|
79
|
+
.describe(`On a new build: the user's own words that asked for the Wix Harmony Editor or for Wix to design the site, quoted from their message or their answer to your question. Empty when they asked for neither; then wixEditorExplicitlyRequested is false. Recorded, not checked. ${NO_PERSONAL_DATA}`),
|
|
80
|
+
agentIdentity: z
|
|
81
|
+
.string()
|
|
82
|
+
.optional()
|
|
83
|
+
.describe(START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.agentIdentity)
|
|
75
84
|
},
|
|
76
85
|
_meta: toolDefinitionMeta,
|
|
77
86
|
annotations: {
|
|
@@ -98,7 +107,10 @@ export function addCreateSiteWidgetTool(server, authStrategy, options) {
|
|
|
98
107
|
});
|
|
99
108
|
}
|
|
100
109
|
console.log(`[${SITE_BUILDER_TOOL_NAME}] 🚀 tool invoked`, {
|
|
101
|
-
|
|
110
|
+
jobId: args.jobId,
|
|
111
|
+
suggestedSiteName: args.suggestedSiteName,
|
|
112
|
+
wixEditorExplicitlyRequested: args.wixEditorExplicitlyRequested,
|
|
113
|
+
hasEditorRequest: !!args.editorRequest,
|
|
102
114
|
isAnonymous
|
|
103
115
|
});
|
|
104
116
|
let jobId;
|
|
@@ -38,6 +38,8 @@ export function addSuggestedDomainTool(server, authStrategy) {
|
|
|
38
38
|
- wants to find a domain for their site, new or existing
|
|
39
39
|
- wants alternatives or variations of a domain name, e.g. "something similar to mybakery.com"
|
|
40
40
|
|
|
41
|
+
Do not use this tool to check domain availability.
|
|
42
|
+
|
|
41
43
|
Provide either a free-text \`query\` (e.g. "pancakes business", "modern yoga studio") OR a \`siteId\` to base the suggestions on that site's name. At least one of them is required.
|
|
42
44
|
|
|
43
45
|
Present the returned domains to the user as a short list. This tool only suggests domains — it does not purchase or connect them.
|
|
@@ -66,7 +68,10 @@ export function addSuggestedDomainTool(server, authStrategy) {
|
|
|
66
68
|
openWorldHint: false
|
|
67
69
|
},
|
|
68
70
|
_meta: {
|
|
69
|
-
securitySchemes: [
|
|
71
|
+
securitySchemes: [
|
|
72
|
+
{ type: 'noauth' },
|
|
73
|
+
{ type: 'oauth2', scopes: ['offline_access'] }
|
|
74
|
+
],
|
|
70
75
|
// Model-visible so hosts (e.g. Microsoft 365 Copilot) can call it directly and show it
|
|
71
76
|
// in their debug info; 'app' keeps it callable from the site-builder widget.
|
|
72
77
|
ui: { visibility: ['app', 'model'] },
|
|
@@ -75,13 +80,6 @@ export function addSuggestedDomainTool(server, authStrategy) {
|
|
|
75
80
|
}
|
|
76
81
|
}, async (args, { panorama }) => {
|
|
77
82
|
console.log('[getSuggestedDomains] Invoked with args:', args);
|
|
78
|
-
if (isAnonymous?.()) {
|
|
79
|
-
console.log('[getSuggestedDomains] Returning empty response for anonymous user');
|
|
80
|
-
return {
|
|
81
|
-
content: [{ type: 'text', text: '' }],
|
|
82
|
-
structuredContent: { domains: [], success: true }
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
83
|
const { query, siteId, tlds, limit } = args;
|
|
86
84
|
if (!query && !siteId) {
|
|
87
85
|
return {
|
|
@@ -95,9 +93,22 @@ export function addSuggestedDomainTool(server, authStrategy) {
|
|
|
95
93
|
structuredContent: { domains: [] }
|
|
96
94
|
};
|
|
97
95
|
}
|
|
96
|
+
const anonymous = isAnonymous?.() ?? false;
|
|
97
|
+
if (anonymous && !query) {
|
|
98
|
+
return {
|
|
99
|
+
isError: true,
|
|
100
|
+
content: [
|
|
101
|
+
{
|
|
102
|
+
type: 'text',
|
|
103
|
+
text: "Without a connected Wix account the site's name can't be read: pass a query (the business or site name) instead of the siteId"
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
structuredContent: { domains: [] }
|
|
107
|
+
};
|
|
108
|
+
}
|
|
98
109
|
try {
|
|
99
110
|
let resolvedQuery = query;
|
|
100
|
-
if (siteId) {
|
|
111
|
+
if (siteId && !anonymous) {
|
|
101
112
|
try {
|
|
102
113
|
const siteHeaders = await getSiteAuthHeaders(siteId);
|
|
103
114
|
const siteName = await fetchSiteDisplayName(siteHeaders.Authorization, siteId);
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import type { HttpResponse } from '@wix/http-client';
|
|
2
|
+
/**
|
|
3
|
+
* Whether an account-scoped call failed for want of a site: `certain` when the API says so,
|
|
4
|
+
* `likely` for the empty 403 site APIs answer without one, null otherwise.
|
|
5
|
+
*/
|
|
6
|
+
export declare function missingSiteContext(status: number | undefined, responseData: unknown): 'certain' | 'likely' | null;
|
|
2
7
|
export declare const DEFAULT_OPENAI_SECURITY_SCHEMES: {
|
|
3
8
|
type: "oauth2";
|
|
4
9
|
scopes: string[];
|
|
5
10
|
}[];
|
|
6
|
-
export declare const buildErrorMessage: ({ status, statusText, requestId, responseData }: {
|
|
11
|
+
export declare const buildErrorMessage: ({ status, statusText, requestId, responseData, retryHint }: {
|
|
7
12
|
status?: number;
|
|
8
13
|
statusText?: string;
|
|
9
14
|
requestId: string | null;
|
|
10
15
|
responseData?: any;
|
|
16
|
+
/** Replaces the hint picked from the error details. */
|
|
17
|
+
retryHint?: string;
|
|
11
18
|
}) => string;
|
|
12
19
|
export declare const handleWixAPIResponse: <T = any>(response: HttpResponse) => Promise<T>;
|
|
13
20
|
export declare function withJsonContent(result: any): any;
|
package/build/dts/tool-utils.js
CHANGED
|
@@ -11,6 +11,30 @@ const getRetryHint = (errorDetails) => {
|
|
|
11
11
|
? SINGLE_OPERATOR_PER_FIELD_HINT
|
|
12
12
|
: FIELD_CAPABILITIES_HINT;
|
|
13
13
|
};
|
|
14
|
+
// What site APIs answer when a call carries no site: an explicit "no site in the request" in
|
|
15
|
+
// one of its many spellings, or a 403 with an empty body.
|
|
16
|
+
const NO_SITE_IN_REQUEST = /META_SITE_NOT_FOUND|MetaSite(?:Id)? (?:context )?(?:is missing|was not found|not found)|NO_METASITE_IN_CALL_CONTEXT|MISSING_METASITE_ID|MISSING_REQUEST_SITE_CONTEXT|metasiteId from the request context/i;
|
|
17
|
+
/**
|
|
18
|
+
* Whether an account-scoped call failed for want of a site: `certain` when the API says so,
|
|
19
|
+
* `likely` for the empty 403 site APIs answer without one, null otherwise.
|
|
20
|
+
*/
|
|
21
|
+
export function missingSiteContext(status, responseData) {
|
|
22
|
+
const details = typeof responseData === 'string'
|
|
23
|
+
? responseData
|
|
24
|
+
: JSON.stringify(responseData ?? '');
|
|
25
|
+
if (NO_SITE_IN_REQUEST.test(details))
|
|
26
|
+
return 'certain';
|
|
27
|
+
const parsed = typeof responseData === 'string'
|
|
28
|
+
? safeParseJSON(responseData)
|
|
29
|
+
: responseData;
|
|
30
|
+
if (status === 403 &&
|
|
31
|
+
parsed &&
|
|
32
|
+
typeof parsed === 'object' &&
|
|
33
|
+
!parsed.message) {
|
|
34
|
+
return 'likely';
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
14
38
|
export const DEFAULT_OPENAI_SECURITY_SCHEMES = [
|
|
15
39
|
{ type: 'oauth2', scopes: ['offline_access'] }
|
|
16
40
|
];
|
|
@@ -22,7 +46,7 @@ const safeParseJSON = (text) => {
|
|
|
22
46
|
return text;
|
|
23
47
|
}
|
|
24
48
|
};
|
|
25
|
-
export const buildErrorMessage = ({ status, statusText, requestId, responseData }) => {
|
|
49
|
+
export const buildErrorMessage = ({ status, statusText, requestId, responseData, retryHint }) => {
|
|
26
50
|
const responseDataObject = typeof responseData === 'string'
|
|
27
51
|
? safeParseJSON(responseData)
|
|
28
52
|
: responseData;
|
|
@@ -39,7 +63,7 @@ export const buildErrorMessage = ({ status, statusText, requestId, responseData
|
|
|
39
63
|
]
|
|
40
64
|
.filter((str) => !!str)
|
|
41
65
|
.join('\n');
|
|
42
|
-
return `${baseMessage}\n\n${getRetryHint(String(errorDetails))}`;
|
|
66
|
+
return `${baseMessage}\n\n${retryHint ?? getRetryHint(String(errorDetails))}`;
|
|
43
67
|
};
|
|
44
68
|
export const handleWixAPIResponse = async (response) => {
|
|
45
69
|
const requestId = response.headers?.['x-wix-request-id'];
|
package/build/dts/toolkit.js
CHANGED
|
@@ -238,7 +238,13 @@ export function createWixToolkit(options) {
|
|
|
238
238
|
addUploadHeadlessWebsiteFilesTool(server, {
|
|
239
239
|
authStrategy,
|
|
240
240
|
toolDescriptions: effectiveToolDescriptions,
|
|
241
|
-
clientName
|
|
241
|
+
clientName,
|
|
242
|
+
// The headless guide the drop reply carries is read the way the docs tools read it.
|
|
243
|
+
guide: {
|
|
244
|
+
skillsPortalUrl: docs?.skillsPortalUrl,
|
|
245
|
+
repo: docs?.repo ?? docs?.skillsRepo,
|
|
246
|
+
commitHash: docs?.commitHash ?? docs?.skillsPr
|
|
247
|
+
}
|
|
242
248
|
});
|
|
243
249
|
}
|
|
244
250
|
// GraphQL tools register only the ones requested (each is opt-in by name).
|