@wix/mcp 1.0.5 → 1.0.7
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/bin.js +1 -1
- package/build/bin.js +665 -82
- package/build/bin.js.map +7 -0
- package/build/chunk-QGIZNLF4.js +8179 -0
- package/build/chunk-QGIZNLF4.js.map +7 -0
- package/build/index.js +201 -6
- package/build/index.js.map +7 -0
- package/build/panorama.d.ts +2 -0
- package/build/wix-mcp-server.d.ts +4 -1
- package/package.json +8 -5
- package/build/api-call/index.js +0 -124
- package/build/cli-tools/cli.js +0 -338
- package/build/cli-tools/utils.js +0 -25
- package/build/docs/docs.js +0 -448
- package/build/docs/long-content.js +0 -1
- package/build/docs/semanticSearch.js +0 -108
- package/build/docs/semanticSearch.test.js +0 -459
- package/build/interactive-command-tools/eventually.js +0 -15
- package/build/interactive-command-tools/handleStdout.js +0 -75
- package/build/interactive-command-tools/interactive-command-utils.js +0 -75
- package/build/logger.js +0 -61
- package/build/resources/docs.js +0 -45
- package/build/sentry.js +0 -10
- package/build/support/index.js +0 -32
- package/build/tool-utils.js +0 -29
- package/build/tool-utils.spec.js +0 -119
- package/build/wix-mcp-server.js +0 -51
package/build/resources/docs.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { logger } from '../logger.js';
|
|
2
|
-
const getPortalIndex = async (portalName) => {
|
|
3
|
-
const response = await fetch(`https://dev.wix.com/digor/api/portal-index?portalName=${portalName}`);
|
|
4
|
-
const data = await response.json();
|
|
5
|
-
return data;
|
|
6
|
-
};
|
|
7
|
-
const addPortalResources = async (server, portalName) => {
|
|
8
|
-
// get portal index:
|
|
9
|
-
const portalIndexResponse = await getPortalIndex(portalName);
|
|
10
|
-
logger.log(`portalIndexResponse for ${portalName}`, JSON.stringify(portalIndexResponse, null, 2));
|
|
11
|
-
// for each portalIndex entry, add a resource to the server:
|
|
12
|
-
for (const entry of portalIndexResponse.portalIndex) {
|
|
13
|
-
logger.log(`entry ${JSON.stringify(entry, null, 2)}`);
|
|
14
|
-
const name = entry.url;
|
|
15
|
-
const uri = entry.url.replace('https://dev.wix.com/docs/', 'wix-docs://');
|
|
16
|
-
logger.log(`adding resource ${name} ${uri}`);
|
|
17
|
-
server.resource(name, uri, async (uri) => {
|
|
18
|
-
logger.log(`fetching resource ${uri}`);
|
|
19
|
-
const docsURL = uri
|
|
20
|
-
.toString()
|
|
21
|
-
.replace('wix-docs://', 'https://dev.wix.com/docs/');
|
|
22
|
-
const response = await fetch(`https://dev.wix.com/digor/api/get-article-content?articleUrl=${encodeURIComponent(docsURL)}`);
|
|
23
|
-
const data = await response.json();
|
|
24
|
-
return {
|
|
25
|
-
contents: [
|
|
26
|
-
{
|
|
27
|
-
uri: uri.href,
|
|
28
|
-
text: data.articleContent || 'No content found'
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
};
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
export const addDocsResources = async (server, portals) => {
|
|
36
|
-
for (const portal of portals) {
|
|
37
|
-
try {
|
|
38
|
-
logger.log(`Processing portal: ${portal}`);
|
|
39
|
-
await addPortalResources(server, portal);
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
logger.error(`Error processing portal ${portal}:`, error);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
package/build/sentry.js
DELETED
package/build/support/index.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
export function addSupportTool(server) {
|
|
3
|
-
server.tool('SupportAndFeedback', [
|
|
4
|
-
'If the user would like to provide Wix with some feedback (good or bad), about the tools in Wix MCP,',
|
|
5
|
-
'for example they used the tools provided, and they reflected satisfaction or dissatisfaction with the tools.',
|
|
6
|
-
'Also, if you encounter too many errors tyring to call the Wix API, you can also suggest the user to provide feedback to Wix using this tool.',
|
|
7
|
-
'**IMPORTANT NOTE**',
|
|
8
|
-
'This tool is not sending the message, but formats it in order to another tool to actually send it'
|
|
9
|
-
].join('\n'), {
|
|
10
|
-
requestId: z
|
|
11
|
-
.string()
|
|
12
|
-
.optional()
|
|
13
|
-
.describe('request id if returned from the server in a failed API call to Wix'),
|
|
14
|
-
message: z.string().describe('The message to send to Wix')
|
|
15
|
-
}, async ({ requestId, message }) => {
|
|
16
|
-
return {
|
|
17
|
-
content: [
|
|
18
|
-
{
|
|
19
|
-
type: 'text',
|
|
20
|
-
text: `${message} ${requestId ? `request id: ${requestId}` : ''}`
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
type: 'text',
|
|
24
|
-
text: 'You should present the user with the formatted message above and ask if they would like to send it to Wix.' +
|
|
25
|
-
'If the user confirms, you can get the details about send feedback API from the article `https://dev.wix.com/docs/kb-only/MCP_REST_RECIPES_KB_ID/TRAIN_send_mcp_feedback_to_wix_from_user`.' +
|
|
26
|
-
'You can use the `ReadFullDocsArticle` tool to fetch the article and get the details about the API call.' +
|
|
27
|
-
'Once you have the details, you can use the `ManageWixSite` (if site id is in context) or `CallWixSiteAPI` (if site id is not in context) tool to call the API and send the feedback to Wix.'
|
|
28
|
-
}
|
|
29
|
-
]
|
|
30
|
-
};
|
|
31
|
-
});
|
|
32
|
-
}
|
package/build/tool-utils.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const safeParseJSON = (text) => {
|
|
2
|
-
try {
|
|
3
|
-
return JSON.parse(text);
|
|
4
|
-
}
|
|
5
|
-
catch {
|
|
6
|
-
return text;
|
|
7
|
-
}
|
|
8
|
-
};
|
|
9
|
-
export const handleWixAPIResponse = async (response) => {
|
|
10
|
-
const responseText = await response.text();
|
|
11
|
-
const responseData = safeParseJSON(responseText);
|
|
12
|
-
if (!response.ok) {
|
|
13
|
-
const requestId = response.headers.get('x-wix-request-id');
|
|
14
|
-
const errorDetails = typeof responseData === 'object'
|
|
15
|
-
? JSON.stringify(responseData)
|
|
16
|
-
: responseData;
|
|
17
|
-
throw new Error([
|
|
18
|
-
`Failed to call Wix API: ${response.status} ${response.statusText}.`,
|
|
19
|
-
requestId ? `request id: ${requestId}` : '',
|
|
20
|
-
// Wix 404 for API does not exist is huge (generic 404 page) and loaded to the context
|
|
21
|
-
response.status === 404 && errorDetails.includes('<html')
|
|
22
|
-
? 'Not found'
|
|
23
|
-
: errorDetails
|
|
24
|
-
]
|
|
25
|
-
.filter((str) => !!str)
|
|
26
|
-
.join('\n'));
|
|
27
|
-
}
|
|
28
|
-
return responseData;
|
|
29
|
-
};
|
package/build/tool-utils.spec.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { handleWixAPIResponse } from './tool-utils.js';
|
|
2
|
-
import { expect, test, vi, describe, beforeEach } from 'vitest';
|
|
3
|
-
// Mock the global fetch function
|
|
4
|
-
global.fetch = vi.fn();
|
|
5
|
-
describe('handleWixAPIResponse', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
// Reset the mock before each test
|
|
8
|
-
global.fetch.mockClear();
|
|
9
|
-
});
|
|
10
|
-
describe('safeParseJSON', () => {
|
|
11
|
-
test('should parse valid JSON string', async () => {
|
|
12
|
-
const jsonString = '{"key": "value", "number": 123}';
|
|
13
|
-
global.fetch.mockResolvedValueOnce(new Response(jsonString, { status: 200 }));
|
|
14
|
-
const result = await handleWixAPIResponse(new Response(jsonString, { status: 200 }));
|
|
15
|
-
expect(result).toEqual({ key: 'value', number: 123 });
|
|
16
|
-
});
|
|
17
|
-
test('should return the original string if parsing fails', async () => {
|
|
18
|
-
const invalidJSONString = 'this is not valid json';
|
|
19
|
-
global.fetch.mockResolvedValueOnce(new Response(invalidJSONString, { status: 200 }));
|
|
20
|
-
const result = await handleWixAPIResponse(new Response(invalidJSONString, { status: 200 }));
|
|
21
|
-
expect(result).toBe(invalidJSONString);
|
|
22
|
-
});
|
|
23
|
-
test('should return an empty string if the response text is empty', async () => {
|
|
24
|
-
global.fetch.mockResolvedValueOnce(new Response('', { status: 200 }));
|
|
25
|
-
const result = await handleWixAPIResponse(new Response('', { status: 200 }));
|
|
26
|
-
expect(result).toBe('');
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
test('should return parsed JSON data for a successful response', async () => {
|
|
30
|
-
const mockData = { message: 'Success!' };
|
|
31
|
-
global.fetch.mockResolvedValueOnce(new Response(JSON.stringify(mockData), {
|
|
32
|
-
status: 200,
|
|
33
|
-
statusText: 'OK',
|
|
34
|
-
headers: new Headers({ 'Content-Type': 'application/json' })
|
|
35
|
-
}));
|
|
36
|
-
const response = new Response(JSON.stringify(mockData), {
|
|
37
|
-
status: 200,
|
|
38
|
-
statusText: 'OK',
|
|
39
|
-
headers: new Headers({ 'Content-Type': 'application/json' })
|
|
40
|
-
});
|
|
41
|
-
const result = await handleWixAPIResponse(response);
|
|
42
|
-
expect(result).toEqual(mockData);
|
|
43
|
-
});
|
|
44
|
-
test('should return the original string if the successful response is not JSON', async () => {
|
|
45
|
-
const mockData = 'This is plain text';
|
|
46
|
-
global.fetch.mockResolvedValueOnce(new Response(mockData, { status: 200, statusText: 'OK' }));
|
|
47
|
-
const response = new Response(mockData, { status: 200, statusText: 'OK' });
|
|
48
|
-
const result = await handleWixAPIResponse(response);
|
|
49
|
-
expect(result).toBe(mockData);
|
|
50
|
-
});
|
|
51
|
-
test('should throw an error for a failed response with JSON error details', async () => {
|
|
52
|
-
const mockError = { error: 'Something went wrong', code: 500 };
|
|
53
|
-
const mockRequestId = 'some-request-id';
|
|
54
|
-
global.fetch.mockResolvedValueOnce(new Response(JSON.stringify(mockError), {
|
|
55
|
-
status: 500,
|
|
56
|
-
statusText: 'Internal Server Error',
|
|
57
|
-
headers: new Headers({ 'x-wix-request-id': mockRequestId })
|
|
58
|
-
}));
|
|
59
|
-
const response = new Response(JSON.stringify(mockError), {
|
|
60
|
-
status: 500,
|
|
61
|
-
statusText: 'Internal Server Error',
|
|
62
|
-
headers: new Headers({ 'x-wix-request-id': mockRequestId })
|
|
63
|
-
});
|
|
64
|
-
await expect(handleWixAPIResponse(response)).rejects.toThrowError([
|
|
65
|
-
'Failed to call Wix API: 500 Internal Server Error.',
|
|
66
|
-
`request id: ${mockRequestId}`,
|
|
67
|
-
'{"error":"Something went wrong","code":500}'
|
|
68
|
-
].join('\n'));
|
|
69
|
-
});
|
|
70
|
-
test('should throw an error for a failed response with non-JSON error details', async () => {
|
|
71
|
-
const mockError = 'Internal server error occurred.';
|
|
72
|
-
global.fetch.mockResolvedValueOnce(new Response(mockError, {
|
|
73
|
-
status: 503,
|
|
74
|
-
statusText: 'Service Unavailable'
|
|
75
|
-
}));
|
|
76
|
-
const response = new Response(mockError, {
|
|
77
|
-
status: 503,
|
|
78
|
-
statusText: 'Service Unavailable'
|
|
79
|
-
});
|
|
80
|
-
await expect(handleWixAPIResponse(response)).rejects.toThrowError(['Failed to call Wix API: 503 Service Unavailable.', mockError].join('\n'));
|
|
81
|
-
});
|
|
82
|
-
test('should include the request ID in the error message if present', async () => {
|
|
83
|
-
const mockError = { message: 'Unauthorized' };
|
|
84
|
-
const mockRequestId = 'another-id';
|
|
85
|
-
global.fetch.mockResolvedValueOnce(new Response(JSON.stringify(mockError), {
|
|
86
|
-
status: 401,
|
|
87
|
-
statusText: 'Unauthorized',
|
|
88
|
-
headers: new Headers({ 'x-wix-request-id': mockRequestId })
|
|
89
|
-
}));
|
|
90
|
-
const response = new Response(JSON.stringify(mockError), {
|
|
91
|
-
status: 401,
|
|
92
|
-
statusText: 'Unauthorized',
|
|
93
|
-
headers: new Headers({ 'x-wix-request-id': mockRequestId })
|
|
94
|
-
});
|
|
95
|
-
await expect(handleWixAPIResponse(response)).rejects.toThrowError([
|
|
96
|
-
'Failed to call Wix API: 401 Unauthorized.',
|
|
97
|
-
`request id: ${mockRequestId}`,
|
|
98
|
-
'{"message":"Unauthorized"}'
|
|
99
|
-
].join('\n'));
|
|
100
|
-
});
|
|
101
|
-
test('should return "Not found" in the error message for a 404 with HTML content', async () => {
|
|
102
|
-
const mockHtmlError = '<html><body><h1>404 Not Found</h1></body></html>';
|
|
103
|
-
global.fetch.mockResolvedValueOnce(new Response(mockHtmlError, { status: 404, statusText: 'Not Found' }));
|
|
104
|
-
const response = new Response(mockHtmlError, {
|
|
105
|
-
status: 404,
|
|
106
|
-
statusText: 'Not Found'
|
|
107
|
-
});
|
|
108
|
-
await expect(handleWixAPIResponse(response)).rejects.toThrowError(['Failed to call Wix API: 404 Not Found.', 'Not found'].join('\n'));
|
|
109
|
-
});
|
|
110
|
-
test('should include the HTML content in the error message for a 404 without typical HTML structure', async () => {
|
|
111
|
-
const mockNonHtmlError = 'Resource not found on the server.';
|
|
112
|
-
global.fetch.mockResolvedValueOnce(new Response(mockNonHtmlError, { status: 404, statusText: 'Not Found' }));
|
|
113
|
-
const response = new Response(mockNonHtmlError, {
|
|
114
|
-
status: 404,
|
|
115
|
-
statusText: 'Not Found'
|
|
116
|
-
});
|
|
117
|
-
await expect(handleWixAPIResponse(response)).rejects.toThrowError(['Failed to call Wix API: 404 Not Found.', mockNonHtmlError].join('\n'));
|
|
118
|
-
});
|
|
119
|
-
});
|
package/build/wix-mcp-server.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// import type { PanoramaClientForComponent } from '@wix/panorama-client-node';
|
|
2
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
//import { globalConfig, panoramaFactory } from './panorama.js';
|
|
4
|
-
import { captureException } from '@sentry/node';
|
|
5
|
-
export class WixMcpServer extends McpServer {
|
|
6
|
-
tool(...args) {
|
|
7
|
-
const cbIndex = args.findIndex((arg) => typeof arg === 'function');
|
|
8
|
-
if (cbIndex !== -1) {
|
|
9
|
-
const originalCb = args[cbIndex];
|
|
10
|
-
const toolName = args[0];
|
|
11
|
-
const panoramaComponentId = toolName;
|
|
12
|
-
/*const panorama = panoramaFactory.client({
|
|
13
|
-
baseParams: {
|
|
14
|
-
componentId: panoramaComponentId
|
|
15
|
-
}
|
|
16
|
-
});*/
|
|
17
|
-
/*setTags({
|
|
18
|
-
panoramaSessionId: globalConfig.getSessionId()
|
|
19
|
-
});*/
|
|
20
|
-
const wrappedCb = async (...cbArgs) => {
|
|
21
|
-
const argsBeforeExtra = cbArgs.slice(0, cbArgs.length - 1);
|
|
22
|
-
const extra = cbArgs[cbArgs.length - 1];
|
|
23
|
-
const wrappedExtra = {
|
|
24
|
-
...extra
|
|
25
|
-
// panorama: panorama.createClientForComponent()
|
|
26
|
-
};
|
|
27
|
-
//panorama.transaction(toolName).start();
|
|
28
|
-
try {
|
|
29
|
-
const cbResult = await originalCb(...argsBeforeExtra, wrappedExtra);
|
|
30
|
-
//panorama.transaction(toolName).finish();
|
|
31
|
-
return cbResult;
|
|
32
|
-
}
|
|
33
|
-
catch (e) {
|
|
34
|
-
//panorama.errorMonitor().reportError(e as Error);
|
|
35
|
-
captureException(e, {
|
|
36
|
-
tags: {
|
|
37
|
-
componentId: panoramaComponentId,
|
|
38
|
-
toolName
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
return {
|
|
42
|
-
isError: true,
|
|
43
|
-
content: [{ type: 'text', text: e.message }]
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
args[cbIndex] = wrappedCb;
|
|
48
|
-
}
|
|
49
|
-
return super.tool.apply(this, args);
|
|
50
|
-
}
|
|
51
|
-
}
|