@elementor/editor-mcp 3.33.0-159

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/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Editor V4 MCP Server Module
2
+
3
+ > [!WARNING]
4
+ > This package is under development and not ready for production use.
5
+
@@ -0,0 +1,33 @@
1
+ import * as _elementor_external_angie_sdk from '@elementor-external/angie-sdk';
2
+ import { AngieMcpSdk } from '@elementor-external/angie-sdk';
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ export { McpServer, ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import { ZodRawShape, z, ZodTypeAny } from '@elementor/schema';
6
+ import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
7
+ import { ServerRequest, ServerNotification } from '@modelcontextprotocol/sdk/types.js';
8
+
9
+ declare function init(): Promise<void>;
10
+
11
+ declare const registerMcp: (mcp: McpServer, name: string) => void;
12
+ declare function activateMcpRegistration(sdk: AngieMcpSdk): Promise<void>;
13
+ /**
14
+ *
15
+ * @param namespace The namespace of the MCP server. It should contain only lowercase alphabetic characters.
16
+ */
17
+ declare const getMCPByDomain: (namespace: string) => MCPRegistryEntry;
18
+ interface MCPRegistryEntry {
19
+ addTool: <T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined>(opts: ToolRegistrationOptions<T, O>) => void;
20
+ setMCPDescription: (description: string) => void;
21
+ }
22
+ type ToolRegistrationOptions<InputArgs extends undefined | ZodRawShape = undefined, OutputSchema extends undefined | ZodRawShape = undefined, ExpectedOutput = OutputSchema extends ZodRawShape ? z.objectOutputType<OutputSchema, ZodTypeAny> : string> = {
23
+ name: string;
24
+ description: string;
25
+ schema?: InputArgs;
26
+ outputSchema?: OutputSchema;
27
+ handler: InputArgs extends ZodRawShape ? (args: z.objectOutputType<InputArgs, ZodTypeAny>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => ExpectedOutput | Promise<ExpectedOutput> : (args: unknown, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => ExpectedOutput | Promise<ExpectedOutput>;
28
+ isDestrcutive?: boolean;
29
+ };
30
+
31
+ declare const getAngieSdk: () => _elementor_external_angie_sdk.AngieMcpSdk;
32
+
33
+ export { type MCPRegistryEntry, activateMcpRegistration, getAngieSdk, getMCPByDomain, init, registerMcp };
@@ -0,0 +1,33 @@
1
+ import * as _elementor_external_angie_sdk from '@elementor-external/angie-sdk';
2
+ import { AngieMcpSdk } from '@elementor-external/angie-sdk';
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ export { McpServer, ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import { ZodRawShape, z, ZodTypeAny } from '@elementor/schema';
6
+ import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
7
+ import { ServerRequest, ServerNotification } from '@modelcontextprotocol/sdk/types.js';
8
+
9
+ declare function init(): Promise<void>;
10
+
11
+ declare const registerMcp: (mcp: McpServer, name: string) => void;
12
+ declare function activateMcpRegistration(sdk: AngieMcpSdk): Promise<void>;
13
+ /**
14
+ *
15
+ * @param namespace The namespace of the MCP server. It should contain only lowercase alphabetic characters.
16
+ */
17
+ declare const getMCPByDomain: (namespace: string) => MCPRegistryEntry;
18
+ interface MCPRegistryEntry {
19
+ addTool: <T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined>(opts: ToolRegistrationOptions<T, O>) => void;
20
+ setMCPDescription: (description: string) => void;
21
+ }
22
+ type ToolRegistrationOptions<InputArgs extends undefined | ZodRawShape = undefined, OutputSchema extends undefined | ZodRawShape = undefined, ExpectedOutput = OutputSchema extends ZodRawShape ? z.objectOutputType<OutputSchema, ZodTypeAny> : string> = {
23
+ name: string;
24
+ description: string;
25
+ schema?: InputArgs;
26
+ outputSchema?: OutputSchema;
27
+ handler: InputArgs extends ZodRawShape ? (args: z.objectOutputType<InputArgs, ZodTypeAny>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => ExpectedOutput | Promise<ExpectedOutput> : (args: unknown, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => ExpectedOutput | Promise<ExpectedOutput>;
28
+ isDestrcutive?: boolean;
29
+ };
30
+
31
+ declare const getAngieSdk: () => _elementor_external_angie_sdk.AngieMcpSdk;
32
+
33
+ export { type MCPRegistryEntry, activateMcpRegistration, getAngieSdk, getMCPByDomain, init, registerMcp };
package/dist/index.js ADDED
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ McpServer: () => import_mcp2.McpServer,
24
+ activateMcpRegistration: () => activateMcpRegistration,
25
+ getAngieSdk: () => getAngieSdk,
26
+ getMCPByDomain: () => getMCPByDomain,
27
+ init: () => init,
28
+ registerMcp: () => registerMcp
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/init.ts
33
+ var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
34
+ var import_angie_sdk = require("@elementor-external/angie-sdk");
35
+
36
+ // src/mcp-registry.ts
37
+ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
38
+
39
+ // src/test-utils/mock-mcp-registry.ts
40
+ var mockMcpRegistry = () => {
41
+ return {
42
+ addTool: () => {
43
+ },
44
+ setMCPDescription: () => {
45
+ }
46
+ };
47
+ };
48
+
49
+ // src/mcp-registry.ts
50
+ var mcpRegistry = {};
51
+ var mcpDescriptions = {};
52
+ var isMcpRegistrationActivated = typeof globalThis.jest !== "undefined";
53
+ var registerMcp = (mcp, name) => {
54
+ if (isMcpRegistrationActivated) {
55
+ throw new Error("MCP Registration is already activated. Cannot register new MCP servers.");
56
+ }
57
+ const mcpName = isAlphabet(name);
58
+ mcpRegistry[mcpName] = mcp;
59
+ };
60
+ async function activateMcpRegistration(sdk2) {
61
+ if (isMcpRegistrationActivated) {
62
+ return;
63
+ }
64
+ isMcpRegistrationActivated = true;
65
+ const mcpServerList = Object.entries(mcpRegistry);
66
+ for await (const entry of mcpServerList) {
67
+ const [key, mcpServer] = entry;
68
+ await sdk2.registerServer({
69
+ name: `editor-${key}`,
70
+ server: mcpServer,
71
+ version: "1.0.0",
72
+ description: mcpDescriptions[key] || key
73
+ });
74
+ }
75
+ }
76
+ var isAlphabet = (str) => {
77
+ const passes = !!str && /^[a-z]+$/.test(str);
78
+ if (!passes) {
79
+ throw new Error("Not alphabet");
80
+ }
81
+ return str;
82
+ };
83
+ var getMCPByDomain = (namespace) => {
84
+ const mcpName = `editor-${isAlphabet(namespace)}`;
85
+ if (typeof globalThis.jest !== "undefined") {
86
+ return mockMcpRegistry();
87
+ }
88
+ if (!mcpRegistry[namespace]) {
89
+ mcpRegistry[namespace] = new import_mcp.McpServer({
90
+ name: mcpName,
91
+ version: "1.0.0"
92
+ });
93
+ }
94
+ const mcpServer = mcpRegistry[namespace];
95
+ const { addTool } = createToolRegistrator(mcpServer);
96
+ return {
97
+ addTool,
98
+ setMCPDescription: (description) => {
99
+ mcpDescriptions[namespace] = description;
100
+ }
101
+ };
102
+ };
103
+ function createToolRegistrator(server) {
104
+ function addTool(opts) {
105
+ const inputSchema = opts.schema ? opts.schema : {};
106
+ if (isMcpRegistrationActivated) {
107
+ throw new Error("MCP Registration is already activated. Cannot add new tools.");
108
+ }
109
+ const toolCallback = async function(args, extra) {
110
+ try {
111
+ const invocationResult = await opts.handler(opts.schema ? args : {}, extra);
112
+ return {
113
+ structuredContent: typeof invocationResult === "string" ? void 0 : invocationResult,
114
+ content: [
115
+ {
116
+ type: "text",
117
+ text: typeof invocationResult === "string" ? invocationResult : JSON.stringify(invocationResult)
118
+ }
119
+ ]
120
+ };
121
+ } catch (error) {
122
+ return {
123
+ isError: true,
124
+ content: [
125
+ {
126
+ type: "text",
127
+ text: error.message || "Unknown error"
128
+ }
129
+ ]
130
+ };
131
+ }
132
+ };
133
+ server.registerTool(
134
+ opts.name,
135
+ {
136
+ description: opts.description,
137
+ inputSchema,
138
+ outputSchema: opts.outputSchema,
139
+ title: opts.name,
140
+ annotations: {
141
+ destructiveHint: opts.isDestrcutive,
142
+ readOnlyHint: opts.isDestrcutive ? false : void 0,
143
+ title: opts.name
144
+ }
145
+ },
146
+ toolCallback
147
+ );
148
+ }
149
+ return {
150
+ addTool
151
+ };
152
+ }
153
+
154
+ // src/init.ts
155
+ var sdk;
156
+ var getSDK = () => {
157
+ if (typeof globalThis.jest !== "undefined") {
158
+ return {};
159
+ }
160
+ if (!sdk) {
161
+ sdk = new import_angie_sdk.AngieMcpSdk();
162
+ }
163
+ return sdk;
164
+ };
165
+ function init() {
166
+ if ((0, import_editor_v1_adapters.isExperimentActive)("editor_mcp")) {
167
+ return getSDK().waitForReady();
168
+ }
169
+ return Promise.resolve();
170
+ }
171
+ function startMCPServer() {
172
+ if ((0, import_editor_v1_adapters.isExperimentActive)("editor_mcp")) {
173
+ return getSDK().waitForReady().then(() => activateMcpRegistration(sdk));
174
+ }
175
+ return Promise.resolve();
176
+ }
177
+ document.addEventListener(
178
+ "DOMContentLoaded",
179
+ () => {
180
+ startMCPServer();
181
+ },
182
+ {
183
+ once: true
184
+ }
185
+ );
186
+
187
+ // src/index.ts
188
+ var import_mcp2 = require("@modelcontextprotocol/sdk/server/mcp.js");
189
+ var getAngieSdk = () => getSDK();
190
+ // Annotate the CommonJS export names for ESM import in node:
191
+ 0 && (module.exports = {
192
+ McpServer,
193
+ activateMcpRegistration,
194
+ getAngieSdk,
195
+ getMCPByDomain,
196
+ init,
197
+ registerMcp
198
+ });
199
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/init.ts","../src/mcp-registry.ts","../src/test-utils/mock-mcp-registry.ts"],"sourcesContent":["import { getSDK } from './init';\n\nexport { McpServer, type ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nexport { init } from './init';\nexport * from './mcp-registry';\nexport const getAngieSdk = () => getSDK();\n","import { isExperimentActive } from '@elementor/editor-v1-adapters';\nimport { AngieMcpSdk } from '@elementor-external/angie-sdk';\n\nimport { activateMcpRegistration } from './mcp-registry';\n\nlet sdk: AngieMcpSdk;\n\nexport const getSDK = () => {\n\t// @ts-ignore - QUnit fails this\n\tif ( typeof globalThis.jest !== 'undefined' ) {\n\t\treturn {} as unknown as AngieMcpSdk;\n\t}\n\tif ( ! sdk ) {\n\t\tsdk = new AngieMcpSdk();\n\t}\n\treturn sdk;\n};\n\nexport function init() {\n\tif ( isExperimentActive( 'editor_mcp' ) ) {\n\t\treturn getSDK().waitForReady();\n\t}\n\treturn Promise.resolve();\n}\n\nexport function startMCPServer() {\n\tif ( isExperimentActive( 'editor_mcp' ) ) {\n\t\treturn getSDK()\n\t\t\t.waitForReady()\n\t\t\t.then( () => activateMcpRegistration( sdk ) );\n\t}\n\treturn Promise.resolve();\n}\n\ndocument.addEventListener(\n\t'DOMContentLoaded',\n\t() => {\n\t\tstartMCPServer();\n\t},\n\t{\n\t\tonce: true,\n\t}\n);\n","import { type z, type ZodRawShape, type ZodTypeAny } from '@elementor/schema';\nimport { type AngieMcpSdk } from '@elementor-external/angie-sdk';\nimport { McpServer, type ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { type RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport { type ServerNotification, type ServerRequest } from '@modelcontextprotocol/sdk/types.js';\n\nimport { mockMcpRegistry } from './test-utils/mock-mcp-registry';\n\nconst mcpRegistry: { [ namespace: string ]: McpServer } = {};\nconst mcpDescriptions: { [ namespace: string ]: string } = {};\n// @ts-ignore - QUnit fails this\nlet isMcpRegistrationActivated = false || typeof globalThis.jest !== 'undefined';\n\nexport const registerMcp = ( mcp: McpServer, name: string ) => {\n\tif ( isMcpRegistrationActivated ) {\n\t\tthrow new Error( 'MCP Registration is already activated. Cannot register new MCP servers.' );\n\t}\n\tconst mcpName = isAlphabet( name );\n\tmcpRegistry[ mcpName ] = mcp;\n};\n\nexport async function activateMcpRegistration( sdk: AngieMcpSdk ) {\n\tif ( isMcpRegistrationActivated ) {\n\t\treturn;\n\t}\n\tisMcpRegistrationActivated = true;\n\tconst mcpServerList = Object.entries( mcpRegistry );\n\tfor await ( const entry of mcpServerList ) {\n\t\tconst [ key, mcpServer ] = entry;\n\t\tawait sdk.registerServer( {\n\t\t\tname: `editor-${ key }`,\n\t\t\tserver: mcpServer,\n\t\t\tversion: '1.0.0',\n\t\t\tdescription: mcpDescriptions[ key ] || key,\n\t\t} );\n\t}\n}\n\nconst isAlphabet = ( str: string ): string | never => {\n\tconst passes = !! str && /^[a-z]+$/.test( str );\n\tif ( ! passes ) {\n\t\tthrow new Error( 'Not alphabet' );\n\t}\n\treturn str;\n};\n\n/**\n *\n * @param namespace The namespace of the MCP server. It should contain only lowercase alphabetic characters.\n */\nexport const getMCPByDomain = ( namespace: string ): MCPRegistryEntry => {\n\tconst mcpName = `editor-${ isAlphabet( namespace ) }`;\n\t// @ts-ignore - QUnit fails this\n\tif ( typeof globalThis.jest !== 'undefined' ) {\n\t\treturn mockMcpRegistry();\n\t}\n\tif ( ! mcpRegistry[ namespace ] ) {\n\t\tmcpRegistry[ namespace ] = new McpServer( {\n\t\t\tname: mcpName,\n\t\t\tversion: '1.0.0',\n\t\t} );\n\t}\n\tconst mcpServer = mcpRegistry[ namespace ];\n\tconst { addTool } = createToolRegistrator( mcpServer );\n\treturn {\n\t\taddTool,\n\t\tsetMCPDescription: ( description: string ) => {\n\t\t\tmcpDescriptions[ namespace ] = description;\n\t\t},\n\t};\n};\n\nexport interface MCPRegistryEntry {\n\taddTool: < T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined >(\n\t\topts: ToolRegistrationOptions< T, O >\n\t) => void;\n\tsetMCPDescription: ( description: string ) => void;\n}\n\ntype ToolRegistrationOptions<\n\tInputArgs extends undefined | ZodRawShape = undefined,\n\tOutputSchema extends undefined | ZodRawShape = undefined,\n\tExpectedOutput = OutputSchema extends ZodRawShape ? z.objectOutputType< OutputSchema, ZodTypeAny > : string,\n> = {\n\tname: string;\n\tdescription: string;\n\tschema?: InputArgs;\n\toutputSchema?: OutputSchema;\n\thandler: InputArgs extends ZodRawShape\n\t\t? (\n\t\t\t\targs: z.objectOutputType< InputArgs, ZodTypeAny >,\n\t\t\t\textra: RequestHandlerExtra< ServerRequest, ServerNotification >\n\t\t ) => ExpectedOutput | Promise< ExpectedOutput >\n\t\t: (\n\t\t\t\targs: unknown,\n\t\t\t\textra: RequestHandlerExtra< ServerRequest, ServerNotification >\n\t\t ) => ExpectedOutput | Promise< ExpectedOutput >;\n\tisDestrcutive?: boolean;\n};\n\nfunction createToolRegistrator( server: McpServer ) {\n\tfunction addTool< T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined >(\n\t\topts: ToolRegistrationOptions< T, O >\n\t) {\n\t\tconst inputSchema: ZodRawShape = opts.schema ? opts.schema : {};\n\t\tif ( isMcpRegistrationActivated ) {\n\t\t\tthrow new Error( 'MCP Registration is already activated. Cannot add new tools.' );\n\t\t}\n\t\tconst toolCallback: ToolCallback< typeof inputSchema > = async function ( args, extra ) {\n\t\t\ttry {\n\t\t\t\tconst invocationResult = await opts.handler( opts.schema ? args : {}, extra );\n\t\t\t\treturn {\n\t\t\t\t\tstructuredContent: typeof invocationResult === 'string' ? undefined : invocationResult,\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\ttext:\n\t\t\t\t\t\t\t\ttypeof invocationResult === 'string'\n\t\t\t\t\t\t\t\t\t? invocationResult\n\t\t\t\t\t\t\t\t\t: JSON.stringify( invocationResult ),\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t} catch ( error ) {\n\t\t\t\treturn {\n\t\t\t\t\tisError: true,\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\ttext: ( error as Error ).message || 'Unknown error',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t};\n\t\tserver.registerTool(\n\t\t\topts.name,\n\t\t\t{\n\t\t\t\tdescription: opts.description,\n\t\t\t\tinputSchema,\n\t\t\t\toutputSchema: opts.outputSchema,\n\t\t\t\ttitle: opts.name,\n\t\t\t\tannotations: {\n\t\t\t\t\tdestructiveHint: opts.isDestrcutive,\n\t\t\t\t\treadOnlyHint: opts.isDestrcutive ? false : undefined,\n\t\t\t\t\ttitle: opts.name,\n\t\t\t\t},\n\t\t\t},\n\t\t\ttoolCallback\n\t\t);\n\t}\n\treturn {\n\t\taddTool,\n\t};\n}\n","import { type MCPRegistryEntry } from '../mcp-registry';\n\nexport const mockMcpRegistry = (): MCPRegistryEntry => {\n\treturn {\n\t\taddTool: () => {},\n\t\tsetMCPDescription: () => {},\n\t};\n};\n"],"mappings":"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","names":["sdk","import_mcp"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,167 @@
1
+ // src/init.ts
2
+ import { isExperimentActive } from "@elementor/editor-v1-adapters";
3
+ import { AngieMcpSdk } from "@elementor-external/angie-sdk";
4
+
5
+ // src/mcp-registry.ts
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+
8
+ // src/test-utils/mock-mcp-registry.ts
9
+ var mockMcpRegistry = () => {
10
+ return {
11
+ addTool: () => {
12
+ },
13
+ setMCPDescription: () => {
14
+ }
15
+ };
16
+ };
17
+
18
+ // src/mcp-registry.ts
19
+ var mcpRegistry = {};
20
+ var mcpDescriptions = {};
21
+ var isMcpRegistrationActivated = typeof globalThis.jest !== "undefined";
22
+ var registerMcp = (mcp, name) => {
23
+ if (isMcpRegistrationActivated) {
24
+ throw new Error("MCP Registration is already activated. Cannot register new MCP servers.");
25
+ }
26
+ const mcpName = isAlphabet(name);
27
+ mcpRegistry[mcpName] = mcp;
28
+ };
29
+ async function activateMcpRegistration(sdk2) {
30
+ if (isMcpRegistrationActivated) {
31
+ return;
32
+ }
33
+ isMcpRegistrationActivated = true;
34
+ const mcpServerList = Object.entries(mcpRegistry);
35
+ for await (const entry of mcpServerList) {
36
+ const [key, mcpServer] = entry;
37
+ await sdk2.registerServer({
38
+ name: `editor-${key}`,
39
+ server: mcpServer,
40
+ version: "1.0.0",
41
+ description: mcpDescriptions[key] || key
42
+ });
43
+ }
44
+ }
45
+ var isAlphabet = (str) => {
46
+ const passes = !!str && /^[a-z]+$/.test(str);
47
+ if (!passes) {
48
+ throw new Error("Not alphabet");
49
+ }
50
+ return str;
51
+ };
52
+ var getMCPByDomain = (namespace) => {
53
+ const mcpName = `editor-${isAlphabet(namespace)}`;
54
+ if (typeof globalThis.jest !== "undefined") {
55
+ return mockMcpRegistry();
56
+ }
57
+ if (!mcpRegistry[namespace]) {
58
+ mcpRegistry[namespace] = new McpServer({
59
+ name: mcpName,
60
+ version: "1.0.0"
61
+ });
62
+ }
63
+ const mcpServer = mcpRegistry[namespace];
64
+ const { addTool } = createToolRegistrator(mcpServer);
65
+ return {
66
+ addTool,
67
+ setMCPDescription: (description) => {
68
+ mcpDescriptions[namespace] = description;
69
+ }
70
+ };
71
+ };
72
+ function createToolRegistrator(server) {
73
+ function addTool(opts) {
74
+ const inputSchema = opts.schema ? opts.schema : {};
75
+ if (isMcpRegistrationActivated) {
76
+ throw new Error("MCP Registration is already activated. Cannot add new tools.");
77
+ }
78
+ const toolCallback = async function(args, extra) {
79
+ try {
80
+ const invocationResult = await opts.handler(opts.schema ? args : {}, extra);
81
+ return {
82
+ structuredContent: typeof invocationResult === "string" ? void 0 : invocationResult,
83
+ content: [
84
+ {
85
+ type: "text",
86
+ text: typeof invocationResult === "string" ? invocationResult : JSON.stringify(invocationResult)
87
+ }
88
+ ]
89
+ };
90
+ } catch (error) {
91
+ return {
92
+ isError: true,
93
+ content: [
94
+ {
95
+ type: "text",
96
+ text: error.message || "Unknown error"
97
+ }
98
+ ]
99
+ };
100
+ }
101
+ };
102
+ server.registerTool(
103
+ opts.name,
104
+ {
105
+ description: opts.description,
106
+ inputSchema,
107
+ outputSchema: opts.outputSchema,
108
+ title: opts.name,
109
+ annotations: {
110
+ destructiveHint: opts.isDestrcutive,
111
+ readOnlyHint: opts.isDestrcutive ? false : void 0,
112
+ title: opts.name
113
+ }
114
+ },
115
+ toolCallback
116
+ );
117
+ }
118
+ return {
119
+ addTool
120
+ };
121
+ }
122
+
123
+ // src/init.ts
124
+ var sdk;
125
+ var getSDK = () => {
126
+ if (typeof globalThis.jest !== "undefined") {
127
+ return {};
128
+ }
129
+ if (!sdk) {
130
+ sdk = new AngieMcpSdk();
131
+ }
132
+ return sdk;
133
+ };
134
+ function init() {
135
+ if (isExperimentActive("editor_mcp")) {
136
+ return getSDK().waitForReady();
137
+ }
138
+ return Promise.resolve();
139
+ }
140
+ function startMCPServer() {
141
+ if (isExperimentActive("editor_mcp")) {
142
+ return getSDK().waitForReady().then(() => activateMcpRegistration(sdk));
143
+ }
144
+ return Promise.resolve();
145
+ }
146
+ document.addEventListener(
147
+ "DOMContentLoaded",
148
+ () => {
149
+ startMCPServer();
150
+ },
151
+ {
152
+ once: true
153
+ }
154
+ );
155
+
156
+ // src/index.ts
157
+ import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
158
+ var getAngieSdk = () => getSDK();
159
+ export {
160
+ McpServer2 as McpServer,
161
+ activateMcpRegistration,
162
+ getAngieSdk,
163
+ getMCPByDomain,
164
+ init,
165
+ registerMcp
166
+ };
167
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/init.ts","../src/mcp-registry.ts","../src/test-utils/mock-mcp-registry.ts","../src/index.ts"],"sourcesContent":["import { isExperimentActive } from '@elementor/editor-v1-adapters';\nimport { AngieMcpSdk } from '@elementor-external/angie-sdk';\n\nimport { activateMcpRegistration } from './mcp-registry';\n\nlet sdk: AngieMcpSdk;\n\nexport const getSDK = () => {\n\t// @ts-ignore - QUnit fails this\n\tif ( typeof globalThis.jest !== 'undefined' ) {\n\t\treturn {} as unknown as AngieMcpSdk;\n\t}\n\tif ( ! sdk ) {\n\t\tsdk = new AngieMcpSdk();\n\t}\n\treturn sdk;\n};\n\nexport function init() {\n\tif ( isExperimentActive( 'editor_mcp' ) ) {\n\t\treturn getSDK().waitForReady();\n\t}\n\treturn Promise.resolve();\n}\n\nexport function startMCPServer() {\n\tif ( isExperimentActive( 'editor_mcp' ) ) {\n\t\treturn getSDK()\n\t\t\t.waitForReady()\n\t\t\t.then( () => activateMcpRegistration( sdk ) );\n\t}\n\treturn Promise.resolve();\n}\n\ndocument.addEventListener(\n\t'DOMContentLoaded',\n\t() => {\n\t\tstartMCPServer();\n\t},\n\t{\n\t\tonce: true,\n\t}\n);\n","import { type z, type ZodRawShape, type ZodTypeAny } from '@elementor/schema';\nimport { type AngieMcpSdk } from '@elementor-external/angie-sdk';\nimport { McpServer, type ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { type RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport { type ServerNotification, type ServerRequest } from '@modelcontextprotocol/sdk/types.js';\n\nimport { mockMcpRegistry } from './test-utils/mock-mcp-registry';\n\nconst mcpRegistry: { [ namespace: string ]: McpServer } = {};\nconst mcpDescriptions: { [ namespace: string ]: string } = {};\n// @ts-ignore - QUnit fails this\nlet isMcpRegistrationActivated = false || typeof globalThis.jest !== 'undefined';\n\nexport const registerMcp = ( mcp: McpServer, name: string ) => {\n\tif ( isMcpRegistrationActivated ) {\n\t\tthrow new Error( 'MCP Registration is already activated. Cannot register new MCP servers.' );\n\t}\n\tconst mcpName = isAlphabet( name );\n\tmcpRegistry[ mcpName ] = mcp;\n};\n\nexport async function activateMcpRegistration( sdk: AngieMcpSdk ) {\n\tif ( isMcpRegistrationActivated ) {\n\t\treturn;\n\t}\n\tisMcpRegistrationActivated = true;\n\tconst mcpServerList = Object.entries( mcpRegistry );\n\tfor await ( const entry of mcpServerList ) {\n\t\tconst [ key, mcpServer ] = entry;\n\t\tawait sdk.registerServer( {\n\t\t\tname: `editor-${ key }`,\n\t\t\tserver: mcpServer,\n\t\t\tversion: '1.0.0',\n\t\t\tdescription: mcpDescriptions[ key ] || key,\n\t\t} );\n\t}\n}\n\nconst isAlphabet = ( str: string ): string | never => {\n\tconst passes = !! str && /^[a-z]+$/.test( str );\n\tif ( ! passes ) {\n\t\tthrow new Error( 'Not alphabet' );\n\t}\n\treturn str;\n};\n\n/**\n *\n * @param namespace The namespace of the MCP server. It should contain only lowercase alphabetic characters.\n */\nexport const getMCPByDomain = ( namespace: string ): MCPRegistryEntry => {\n\tconst mcpName = `editor-${ isAlphabet( namespace ) }`;\n\t// @ts-ignore - QUnit fails this\n\tif ( typeof globalThis.jest !== 'undefined' ) {\n\t\treturn mockMcpRegistry();\n\t}\n\tif ( ! mcpRegistry[ namespace ] ) {\n\t\tmcpRegistry[ namespace ] = new McpServer( {\n\t\t\tname: mcpName,\n\t\t\tversion: '1.0.0',\n\t\t} );\n\t}\n\tconst mcpServer = mcpRegistry[ namespace ];\n\tconst { addTool } = createToolRegistrator( mcpServer );\n\treturn {\n\t\taddTool,\n\t\tsetMCPDescription: ( description: string ) => {\n\t\t\tmcpDescriptions[ namespace ] = description;\n\t\t},\n\t};\n};\n\nexport interface MCPRegistryEntry {\n\taddTool: < T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined >(\n\t\topts: ToolRegistrationOptions< T, O >\n\t) => void;\n\tsetMCPDescription: ( description: string ) => void;\n}\n\ntype ToolRegistrationOptions<\n\tInputArgs extends undefined | ZodRawShape = undefined,\n\tOutputSchema extends undefined | ZodRawShape = undefined,\n\tExpectedOutput = OutputSchema extends ZodRawShape ? z.objectOutputType< OutputSchema, ZodTypeAny > : string,\n> = {\n\tname: string;\n\tdescription: string;\n\tschema?: InputArgs;\n\toutputSchema?: OutputSchema;\n\thandler: InputArgs extends ZodRawShape\n\t\t? (\n\t\t\t\targs: z.objectOutputType< InputArgs, ZodTypeAny >,\n\t\t\t\textra: RequestHandlerExtra< ServerRequest, ServerNotification >\n\t\t ) => ExpectedOutput | Promise< ExpectedOutput >\n\t\t: (\n\t\t\t\targs: unknown,\n\t\t\t\textra: RequestHandlerExtra< ServerRequest, ServerNotification >\n\t\t ) => ExpectedOutput | Promise< ExpectedOutput >;\n\tisDestrcutive?: boolean;\n};\n\nfunction createToolRegistrator( server: McpServer ) {\n\tfunction addTool< T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined >(\n\t\topts: ToolRegistrationOptions< T, O >\n\t) {\n\t\tconst inputSchema: ZodRawShape = opts.schema ? opts.schema : {};\n\t\tif ( isMcpRegistrationActivated ) {\n\t\t\tthrow new Error( 'MCP Registration is already activated. Cannot add new tools.' );\n\t\t}\n\t\tconst toolCallback: ToolCallback< typeof inputSchema > = async function ( args, extra ) {\n\t\t\ttry {\n\t\t\t\tconst invocationResult = await opts.handler( opts.schema ? args : {}, extra );\n\t\t\t\treturn {\n\t\t\t\t\tstructuredContent: typeof invocationResult === 'string' ? undefined : invocationResult,\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\ttext:\n\t\t\t\t\t\t\t\ttypeof invocationResult === 'string'\n\t\t\t\t\t\t\t\t\t? invocationResult\n\t\t\t\t\t\t\t\t\t: JSON.stringify( invocationResult ),\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t} catch ( error ) {\n\t\t\t\treturn {\n\t\t\t\t\tisError: true,\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\ttext: ( error as Error ).message || 'Unknown error',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t};\n\t\tserver.registerTool(\n\t\t\topts.name,\n\t\t\t{\n\t\t\t\tdescription: opts.description,\n\t\t\t\tinputSchema,\n\t\t\t\toutputSchema: opts.outputSchema,\n\t\t\t\ttitle: opts.name,\n\t\t\t\tannotations: {\n\t\t\t\t\tdestructiveHint: opts.isDestrcutive,\n\t\t\t\t\treadOnlyHint: opts.isDestrcutive ? false : undefined,\n\t\t\t\t\ttitle: opts.name,\n\t\t\t\t},\n\t\t\t},\n\t\t\ttoolCallback\n\t\t);\n\t}\n\treturn {\n\t\taddTool,\n\t};\n}\n","import { type MCPRegistryEntry } from '../mcp-registry';\n\nexport const mockMcpRegistry = (): MCPRegistryEntry => {\n\treturn {\n\t\taddTool: () => {},\n\t\tsetMCPDescription: () => {},\n\t};\n};\n","import { getSDK } from './init';\n\nexport { McpServer, type ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nexport { init } from './init';\nexport * from './mcp-registry';\nexport const getAngieSdk = () => getSDK();\n"],"mappings":"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","names":["sdk","McpServer"]}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@elementor/editor-mcp",
3
+ "version": "3.33.0-159",
4
+ "private": false,
5
+ "author": "Elementor Team",
6
+ "homepage": "https://elementor.com/",
7
+ "license": "GPL-3.0-or-later",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.mts",
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.js"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/elementor/elementor.git",
22
+ "directory": "packages/core/editor-mcp"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/elementor/elementor/issues"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "files": [
31
+ "README.md",
32
+ "CHANGELOG.md",
33
+ "/dist",
34
+ "/src",
35
+ "!**/__tests__"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsup --config=../../tsup.build.ts",
39
+ "dev": "tsup --config=../../tsup.dev.ts"
40
+ },
41
+ "devDependencies": {
42
+ "tsup": "^8.3.5"
43
+ },
44
+ "dependencies": {
45
+ "@elementor-external/angie-sdk": "npm:@elementor/angie-sdk@1.0.1",
46
+ "@elementor/schema": "3.33.0-159",
47
+ "@modelcontextprotocol/sdk": "1.17.3",
48
+ "@elementor/store": "3.33.0-159",
49
+ "@elementor/editor-v1-adapters": "3.33.0-159"
50
+ }
51
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { getSDK } from './init';
2
+
3
+ export { McpServer, type ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ export { init } from './init';
5
+ export * from './mcp-registry';
6
+ export const getAngieSdk = () => getSDK();
package/src/init.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { isExperimentActive } from '@elementor/editor-v1-adapters';
2
+ import { AngieMcpSdk } from '@elementor-external/angie-sdk';
3
+
4
+ import { activateMcpRegistration } from './mcp-registry';
5
+
6
+ let sdk: AngieMcpSdk;
7
+
8
+ export const getSDK = () => {
9
+ // @ts-ignore - QUnit fails this
10
+ if ( typeof globalThis.jest !== 'undefined' ) {
11
+ return {} as unknown as AngieMcpSdk;
12
+ }
13
+ if ( ! sdk ) {
14
+ sdk = new AngieMcpSdk();
15
+ }
16
+ return sdk;
17
+ };
18
+
19
+ export function init() {
20
+ if ( isExperimentActive( 'editor_mcp' ) ) {
21
+ return getSDK().waitForReady();
22
+ }
23
+ return Promise.resolve();
24
+ }
25
+
26
+ export function startMCPServer() {
27
+ if ( isExperimentActive( 'editor_mcp' ) ) {
28
+ return getSDK()
29
+ .waitForReady()
30
+ .then( () => activateMcpRegistration( sdk ) );
31
+ }
32
+ return Promise.resolve();
33
+ }
34
+
35
+ document.addEventListener(
36
+ 'DOMContentLoaded',
37
+ () => {
38
+ startMCPServer();
39
+ },
40
+ {
41
+ once: true,
42
+ }
43
+ );
@@ -0,0 +1,155 @@
1
+ import { type z, type ZodRawShape, type ZodTypeAny } from '@elementor/schema';
2
+ import { type AngieMcpSdk } from '@elementor-external/angie-sdk';
3
+ import { McpServer, type ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ import { type RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
5
+ import { type ServerNotification, type ServerRequest } from '@modelcontextprotocol/sdk/types.js';
6
+
7
+ import { mockMcpRegistry } from './test-utils/mock-mcp-registry';
8
+
9
+ const mcpRegistry: { [ namespace: string ]: McpServer } = {};
10
+ const mcpDescriptions: { [ namespace: string ]: string } = {};
11
+ // @ts-ignore - QUnit fails this
12
+ let isMcpRegistrationActivated = false || typeof globalThis.jest !== 'undefined';
13
+
14
+ export const registerMcp = ( mcp: McpServer, name: string ) => {
15
+ if ( isMcpRegistrationActivated ) {
16
+ throw new Error( 'MCP Registration is already activated. Cannot register new MCP servers.' );
17
+ }
18
+ const mcpName = isAlphabet( name );
19
+ mcpRegistry[ mcpName ] = mcp;
20
+ };
21
+
22
+ export async function activateMcpRegistration( sdk: AngieMcpSdk ) {
23
+ if ( isMcpRegistrationActivated ) {
24
+ return;
25
+ }
26
+ isMcpRegistrationActivated = true;
27
+ const mcpServerList = Object.entries( mcpRegistry );
28
+ for await ( const entry of mcpServerList ) {
29
+ const [ key, mcpServer ] = entry;
30
+ await sdk.registerServer( {
31
+ name: `editor-${ key }`,
32
+ server: mcpServer,
33
+ version: '1.0.0',
34
+ description: mcpDescriptions[ key ] || key,
35
+ } );
36
+ }
37
+ }
38
+
39
+ const isAlphabet = ( str: string ): string | never => {
40
+ const passes = !! str && /^[a-z]+$/.test( str );
41
+ if ( ! passes ) {
42
+ throw new Error( 'Not alphabet' );
43
+ }
44
+ return str;
45
+ };
46
+
47
+ /**
48
+ *
49
+ * @param namespace The namespace of the MCP server. It should contain only lowercase alphabetic characters.
50
+ */
51
+ export const getMCPByDomain = ( namespace: string ): MCPRegistryEntry => {
52
+ const mcpName = `editor-${ isAlphabet( namespace ) }`;
53
+ // @ts-ignore - QUnit fails this
54
+ if ( typeof globalThis.jest !== 'undefined' ) {
55
+ return mockMcpRegistry();
56
+ }
57
+ if ( ! mcpRegistry[ namespace ] ) {
58
+ mcpRegistry[ namespace ] = new McpServer( {
59
+ name: mcpName,
60
+ version: '1.0.0',
61
+ } );
62
+ }
63
+ const mcpServer = mcpRegistry[ namespace ];
64
+ const { addTool } = createToolRegistrator( mcpServer );
65
+ return {
66
+ addTool,
67
+ setMCPDescription: ( description: string ) => {
68
+ mcpDescriptions[ namespace ] = description;
69
+ },
70
+ };
71
+ };
72
+
73
+ export interface MCPRegistryEntry {
74
+ addTool: < T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined >(
75
+ opts: ToolRegistrationOptions< T, O >
76
+ ) => void;
77
+ setMCPDescription: ( description: string ) => void;
78
+ }
79
+
80
+ type ToolRegistrationOptions<
81
+ InputArgs extends undefined | ZodRawShape = undefined,
82
+ OutputSchema extends undefined | ZodRawShape = undefined,
83
+ ExpectedOutput = OutputSchema extends ZodRawShape ? z.objectOutputType< OutputSchema, ZodTypeAny > : string,
84
+ > = {
85
+ name: string;
86
+ description: string;
87
+ schema?: InputArgs;
88
+ outputSchema?: OutputSchema;
89
+ handler: InputArgs extends ZodRawShape
90
+ ? (
91
+ args: z.objectOutputType< InputArgs, ZodTypeAny >,
92
+ extra: RequestHandlerExtra< ServerRequest, ServerNotification >
93
+ ) => ExpectedOutput | Promise< ExpectedOutput >
94
+ : (
95
+ args: unknown,
96
+ extra: RequestHandlerExtra< ServerRequest, ServerNotification >
97
+ ) => ExpectedOutput | Promise< ExpectedOutput >;
98
+ isDestrcutive?: boolean;
99
+ };
100
+
101
+ function createToolRegistrator( server: McpServer ) {
102
+ function addTool< T extends undefined | ZodRawShape = undefined, O extends undefined | ZodRawShape = undefined >(
103
+ opts: ToolRegistrationOptions< T, O >
104
+ ) {
105
+ const inputSchema: ZodRawShape = opts.schema ? opts.schema : {};
106
+ if ( isMcpRegistrationActivated ) {
107
+ throw new Error( 'MCP Registration is already activated. Cannot add new tools.' );
108
+ }
109
+ const toolCallback: ToolCallback< typeof inputSchema > = async function ( args, extra ) {
110
+ try {
111
+ const invocationResult = await opts.handler( opts.schema ? args : {}, extra );
112
+ return {
113
+ structuredContent: typeof invocationResult === 'string' ? undefined : invocationResult,
114
+ content: [
115
+ {
116
+ type: 'text',
117
+ text:
118
+ typeof invocationResult === 'string'
119
+ ? invocationResult
120
+ : JSON.stringify( invocationResult ),
121
+ },
122
+ ],
123
+ };
124
+ } catch ( error ) {
125
+ return {
126
+ isError: true,
127
+ content: [
128
+ {
129
+ type: 'text',
130
+ text: ( error as Error ).message || 'Unknown error',
131
+ },
132
+ ],
133
+ };
134
+ }
135
+ };
136
+ server.registerTool(
137
+ opts.name,
138
+ {
139
+ description: opts.description,
140
+ inputSchema,
141
+ outputSchema: opts.outputSchema,
142
+ title: opts.name,
143
+ annotations: {
144
+ destructiveHint: opts.isDestrcutive,
145
+ readOnlyHint: opts.isDestrcutive ? false : undefined,
146
+ title: opts.name,
147
+ },
148
+ },
149
+ toolCallback
150
+ );
151
+ }
152
+ return {
153
+ addTool,
154
+ };
155
+ }
@@ -0,0 +1,8 @@
1
+ import { type MCPRegistryEntry } from '../mcp-registry';
2
+
3
+ export const mockMcpRegistry = (): MCPRegistryEntry => {
4
+ return {
5
+ addTool: () => {},
6
+ setMCPDescription: () => {},
7
+ };
8
+ };