@elementor/editor-canvas 4.3.0-1017 → 4.3.0-1019
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/dist/index.js +98 -197
- package/dist/index.mjs +69 -168
- package/package.json +20 -20
- package/src/init.tsx +3 -4
- package/src/mcp/canvas-mcp.ts +0 -2
- package/src/mcp/mcp-description.ts +18 -30
- package/src/mcp/tools/build-composition/tool.ts +0 -130
package/dist/index.js
CHANGED
|
@@ -2466,11 +2466,11 @@ function getVal2(val) {
|
|
|
2466
2466
|
var transformOriginTransformer = createTransformer((value) => {
|
|
2467
2467
|
const x = getVal2(value.x);
|
|
2468
2468
|
const y = getVal2(value.y);
|
|
2469
|
-
const
|
|
2470
|
-
if (x === DEFAULT_XY && y === DEFAULT_XY &&
|
|
2469
|
+
const z3 = getVal2(value.z);
|
|
2470
|
+
if (x === DEFAULT_XY && y === DEFAULT_XY && z3 === DEFAULT_Z) {
|
|
2471
2471
|
return null;
|
|
2472
2472
|
}
|
|
2473
|
-
return `${x} ${y} ${
|
|
2473
|
+
return `${x} ${y} ${z3}`;
|
|
2474
2474
|
});
|
|
2475
2475
|
|
|
2476
2476
|
// src/transformers/styles/transform-rotate-transformer.ts
|
|
@@ -4477,115 +4477,13 @@ function getElementDisplayName(container) {
|
|
|
4477
4477
|
}
|
|
4478
4478
|
}
|
|
4479
4479
|
|
|
4480
|
-
// src/mcp/tools/build-composition/tool.ts
|
|
4481
|
-
var import_editor_documents2 = require("@elementor/editor-documents");
|
|
4482
|
-
var import_editor_elements11 = require("@elementor/editor-elements");
|
|
4483
|
-
var import_http_client7 = require("@elementor/http-client");
|
|
4484
|
-
var import_schema = require("@elementor/schema");
|
|
4485
|
-
|
|
4486
|
-
// src/mcp/utils/get-mcp-error-message.ts
|
|
4487
|
-
var import_http_client6 = require("@elementor/http-client");
|
|
4488
|
-
function getMcpErrorMessage(error, toolName) {
|
|
4489
|
-
if (error instanceof import_http_client6.AxiosError) {
|
|
4490
|
-
const data = error.response?.data;
|
|
4491
|
-
if (data?.message) {
|
|
4492
|
-
return data.code ? `${data.code}: ${data.message}` : data.message;
|
|
4493
|
-
}
|
|
4494
|
-
}
|
|
4495
|
-
if (error instanceof Error) {
|
|
4496
|
-
return error.message;
|
|
4497
|
-
}
|
|
4498
|
-
return `${toolName} failed with an unknown error.`;
|
|
4499
|
-
}
|
|
4500
|
-
|
|
4501
|
-
// src/mcp/tools/build-composition/tool.ts
|
|
4502
|
-
var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
|
|
4503
|
-
var initBuildCompositionTool = (reg) => {
|
|
4504
|
-
const { addTool } = reg;
|
|
4505
|
-
addTool({
|
|
4506
|
-
name: "build-composition",
|
|
4507
|
-
description: "Build a V4 element composition on the Elementor canvas via the server-side MCP ability. Pass the raw XML tags directly as xmlStructure \u2014 do NOT wrap the value in <![CDATA[ ... ]]>, code fences, or quotes. The document is saved as a draft. Reload the editor after calling this tool to see the result.",
|
|
4508
|
-
schema: {
|
|
4509
|
-
xmlStructure: import_schema.z.string().describe(
|
|
4510
|
-
'Valid XML structure with custom Elementor widget tags. Every element MUST have a unique configuration-id attribute (e.g. <e-heading configuration-id="hero-title"></e-heading>). No attributes, classes, IDs, or text nodes in XML. Pass raw XML \u2014 do not wrap in CDATA.'
|
|
4511
|
-
),
|
|
4512
|
-
elementConfig: import_schema.z.record(
|
|
4513
|
-
import_schema.z.string().describe("configuration-id"),
|
|
4514
|
-
import_schema.z.record(import_schema.z.string().describe("property name"), import_schema.z.any().describe("PropValue"))
|
|
4515
|
-
).optional().describe("Map configuration-id \u2192 widget PropValues ($$type + value)."),
|
|
4516
|
-
style: import_schema.z.record(
|
|
4517
|
-
import_schema.z.string().describe("configuration-id"),
|
|
4518
|
-
import_schema.z.record(import_schema.z.string().describe("CSS property name"), import_schema.z.string().describe("CSS value"))
|
|
4519
|
-
).optional().describe(
|
|
4520
|
-
"Map configuration-id \u2192 raw CSS declarations (property \u2192 value strings; no selectors). Server converts to native styles; unconvertible declarations become the element custom CSS."
|
|
4521
|
-
),
|
|
4522
|
-
parentId: import_schema.z.string().optional().describe("ID of the parent container. Omit or pass 'document' to insert at document root."),
|
|
4523
|
-
mode: import_schema.z.enum(["append", "replace_children"]).optional().describe(
|
|
4524
|
-
"'append' (default) inserts under parentId; 'replace_children' removes existing direct children of parentId first, then inserts."
|
|
4525
|
-
),
|
|
4526
|
-
dryRun: import_schema.z.boolean().optional().describe("If true, validate and return the resolved tree without persisting.")
|
|
4527
|
-
},
|
|
4528
|
-
outputSchema: {
|
|
4529
|
-
rootElementIds: import_schema.z.array(import_schema.z.string()),
|
|
4530
|
-
previewUrl: import_schema.z.string(),
|
|
4531
|
-
version: import_schema.z.string(),
|
|
4532
|
-
resolvedXml: import_schema.z.string(),
|
|
4533
|
-
llmInstructions: import_schema.z.string(),
|
|
4534
|
-
warnings: import_schema.z.array(import_schema.z.string()).optional(),
|
|
4535
|
-
removedElementIds: import_schema.z.array(import_schema.z.string()).optional()
|
|
4536
|
-
},
|
|
4537
|
-
handler: async ({ xmlStructure, elementConfig, style, parentId, mode, dryRun }) => {
|
|
4538
|
-
const document2 = (0, import_editor_documents2.getCurrentDocument)();
|
|
4539
|
-
if (!document2?.id) {
|
|
4540
|
-
throw new Error("No active document found.");
|
|
4541
|
-
}
|
|
4542
|
-
try {
|
|
4543
|
-
const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL5, {
|
|
4544
|
-
tool: "build-composition",
|
|
4545
|
-
input: {
|
|
4546
|
-
post_id: document2.id,
|
|
4547
|
-
xml_structure: xmlStructure,
|
|
4548
|
-
element_config: elementConfig ?? {},
|
|
4549
|
-
style: style ?? {},
|
|
4550
|
-
parent_id: parentId ?? "document",
|
|
4551
|
-
mode: mode ?? "append",
|
|
4552
|
-
dry_run: dryRun ?? false
|
|
4553
|
-
}
|
|
4554
|
-
});
|
|
4555
|
-
if (!dryRun) {
|
|
4556
|
-
await (0, import_editor_documents2.reloadCurrentDocument)();
|
|
4557
|
-
const [firstRootId] = data.data.root_element_ids;
|
|
4558
|
-
if (firstRootId) {
|
|
4559
|
-
(0, import_editor_elements11.selectElement)(firstRootId);
|
|
4560
|
-
(0, import_editor_elements11.getContainer)(firstRootId)?.view?.el?.scrollIntoView({
|
|
4561
|
-
behavior: "smooth",
|
|
4562
|
-
block: "center"
|
|
4563
|
-
});
|
|
4564
|
-
}
|
|
4565
|
-
}
|
|
4566
|
-
return {
|
|
4567
|
-
rootElementIds: data.data.root_element_ids,
|
|
4568
|
-
previewUrl: data.data.preview_url,
|
|
4569
|
-
version: data.data.version,
|
|
4570
|
-
resolvedXml: data.data.resolved_xml,
|
|
4571
|
-
llmInstructions: data.data.llm_instructions,
|
|
4572
|
-
warnings: data.data.warnings,
|
|
4573
|
-
removedElementIds: data.data.removed_element_ids
|
|
4574
|
-
};
|
|
4575
|
-
} catch (error) {
|
|
4576
|
-
throw new Error(getMcpErrorMessage(error, "build-composition"));
|
|
4577
|
-
}
|
|
4578
|
-
}
|
|
4579
|
-
});
|
|
4580
|
-
};
|
|
4581
|
-
|
|
4582
4480
|
// src/mcp/tools/configure-element/tool.ts
|
|
4583
|
-
var
|
|
4481
|
+
var import_editor_elements13 = require("@elementor/editor-elements");
|
|
4584
4482
|
var import_editor_mcp3 = require("@elementor/editor-mcp");
|
|
4585
4483
|
var import_editor_props7 = require("@elementor/editor-props");
|
|
4586
4484
|
|
|
4587
4485
|
// src/mcp/utils/do-update-element-property.ts
|
|
4588
|
-
var
|
|
4486
|
+
var import_editor_elements12 = require("@elementor/editor-elements");
|
|
4589
4487
|
var import_editor_props6 = require("@elementor/editor-props");
|
|
4590
4488
|
var import_editor_styles4 = require("@elementor/editor-styles");
|
|
4591
4489
|
var import_editor_v1_adapters20 = require("@elementor/editor-v1-adapters");
|
|
@@ -4605,7 +4503,7 @@ var readStoredCustomCssText = (raw) => {
|
|
|
4605
4503
|
};
|
|
4606
4504
|
|
|
4607
4505
|
// src/mcp/utils/resolve-canonical-prop-name.ts
|
|
4608
|
-
var
|
|
4506
|
+
var import_editor_elements11 = require("@elementor/editor-elements");
|
|
4609
4507
|
function buildAliasToCanonicalMap(schema) {
|
|
4610
4508
|
const aliasToCanonical = {};
|
|
4611
4509
|
for (const [canonical, propType] of Object.entries(schema)) {
|
|
@@ -4622,14 +4520,14 @@ function buildAliasToCanonicalMap(schema) {
|
|
|
4622
4520
|
return aliasToCanonical;
|
|
4623
4521
|
}
|
|
4624
4522
|
function resolveCanonicalPropName(elementType, propertyName) {
|
|
4625
|
-
const schema = (0,
|
|
4523
|
+
const schema = (0, import_editor_elements11.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4626
4524
|
if (!schema || schema[propertyName]) {
|
|
4627
4525
|
return propertyName;
|
|
4628
4526
|
}
|
|
4629
4527
|
return buildAliasToCanonicalMap(schema)[propertyName] ?? propertyName;
|
|
4630
4528
|
}
|
|
4631
4529
|
function resolveCanonicalPropKeys(elementType, props) {
|
|
4632
|
-
const schema = (0,
|
|
4530
|
+
const schema = (0, import_editor_elements11.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4633
4531
|
if (!schema) {
|
|
4634
4532
|
return { ...props };
|
|
4635
4533
|
}
|
|
@@ -4751,7 +4649,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4751
4649
|
const { elementId, propertyValue, elementType, customCssWriteMode = "replace" } = params;
|
|
4752
4650
|
const propertyName = params.propertyName === "_styles" ? params.propertyName : resolveCanonicalPropName(elementType, params.propertyName);
|
|
4753
4651
|
if (propertyName === "_styles") {
|
|
4754
|
-
const elementStyles = (0,
|
|
4652
|
+
const elementStyles = (0, import_editor_elements12.getElementStyles)(elementId) || {};
|
|
4755
4653
|
const propertyMapValue = propertyValue;
|
|
4756
4654
|
const styleSchema = (0, import_editor_styles4.getStylesSchema)();
|
|
4757
4655
|
const transformedStyleValues = Object.fromEntries(
|
|
@@ -4808,7 +4706,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4808
4706
|
});
|
|
4809
4707
|
delete transformedStyleValues.custom_css;
|
|
4810
4708
|
if (!localStyle) {
|
|
4811
|
-
(0,
|
|
4709
|
+
(0, import_editor_elements12.createElementStyle)({
|
|
4812
4710
|
elementId,
|
|
4813
4711
|
...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
|
|
4814
4712
|
classesProp: "classes",
|
|
@@ -4822,7 +4720,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4822
4720
|
}
|
|
4823
4721
|
});
|
|
4824
4722
|
} else {
|
|
4825
|
-
(0,
|
|
4723
|
+
(0, import_editor_elements12.updateElementStyle)({
|
|
4826
4724
|
elementId,
|
|
4827
4725
|
styleId: localStyle.id,
|
|
4828
4726
|
meta: {
|
|
@@ -4837,7 +4735,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4837
4735
|
}
|
|
4838
4736
|
return;
|
|
4839
4737
|
}
|
|
4840
|
-
const elementPropSchema = (0,
|
|
4738
|
+
const elementPropSchema = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4841
4739
|
if (!elementPropSchema) {
|
|
4842
4740
|
throw new Error(`No prop schema found for element type: ${elementType}`);
|
|
4843
4741
|
}
|
|
@@ -4855,7 +4753,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4855
4753
|
Expected Schema: ${jsonSchema}`
|
|
4856
4754
|
);
|
|
4857
4755
|
}
|
|
4858
|
-
(0,
|
|
4756
|
+
(0, import_editor_elements12.updateElementSettings)({
|
|
4859
4757
|
id: elementId,
|
|
4860
4758
|
props: {
|
|
4861
4759
|
[propertyName]: value
|
|
@@ -4978,29 +4876,29 @@ Note: \`link\` is valid only when the element's PropType schema (which you must
|
|
|
4978
4876
|
};
|
|
4979
4877
|
|
|
4980
4878
|
// src/mcp/tools/configure-element/schema.ts
|
|
4981
|
-
var
|
|
4879
|
+
var import_schema = require("@elementor/schema");
|
|
4982
4880
|
var inputSchema = {
|
|
4983
|
-
propertiesToChange:
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4881
|
+
propertiesToChange: import_schema.z.record(
|
|
4882
|
+
import_schema.z.string().describe("The property name."),
|
|
4883
|
+
import_schema.z.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
|
|
4884
|
+
import_schema.z.any()
|
|
4987
4885
|
).describe("An object record containing property names and their new values to be set on the element"),
|
|
4988
|
-
style:
|
|
4989
|
-
|
|
4990
|
-
|
|
4886
|
+
style: import_schema.z.record(
|
|
4887
|
+
import_schema.z.string().describe('A CSS property name, e.g. "color", "margin-top".'),
|
|
4888
|
+
import_schema.z.string().nullable().describe(
|
|
4991
4889
|
'A CSS value, e.g. "red", "10px", "1px solid #000". Use null to reset the property to its default.'
|
|
4992
4890
|
)
|
|
4993
4891
|
).describe(
|
|
4994
4892
|
"Raw CSS declarations as a flat property\u2192value map. Converted to native styles server-side; any declaration that cannot be converted is stored as the element custom CSS. A null value resets that property to its default."
|
|
4995
4893
|
).default({}),
|
|
4996
|
-
elementType:
|
|
4997
|
-
elementId:
|
|
4894
|
+
elementType: import_schema.z.string().describe("The type of the element to retrieve the schema"),
|
|
4895
|
+
elementId: import_schema.z.string().describe("The unique id of the element to configure")
|
|
4998
4896
|
};
|
|
4999
4897
|
var outputSchema = {
|
|
5000
|
-
success:
|
|
4898
|
+
success: import_schema.z.boolean().describe(
|
|
5001
4899
|
"Whether the configuration change was successful, only if propertyName and propertyValue are provided"
|
|
5002
4900
|
),
|
|
5003
|
-
warnings:
|
|
4901
|
+
warnings: import_schema.z.string().describe(
|
|
5004
4902
|
'Non-fatal notices. Present when some props were skipped because they are not in the element schema (e.g. a "link" on a widget with no link prop). Other changes were still applied.'
|
|
5005
4903
|
).optional()
|
|
5006
4904
|
};
|
|
@@ -5031,13 +4929,13 @@ var initConfigureElementTool = (reg) => {
|
|
|
5031
4929
|
{ description: "Dynamic tags catalog", uri: DYNAMIC_TAGS_URI }
|
|
5032
4930
|
],
|
|
5033
4931
|
handler: async ({ elementId, propertiesToChange, elementType, style }) => {
|
|
5034
|
-
const widgetData = (0,
|
|
4932
|
+
const widgetData = (0, import_editor_elements13.getWidgetsCache)()?.[elementType];
|
|
5035
4933
|
if (!widgetData) {
|
|
5036
4934
|
throw new Error(
|
|
5037
4935
|
`Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
|
|
5038
4936
|
);
|
|
5039
4937
|
}
|
|
5040
|
-
const container = (0,
|
|
4938
|
+
const container = (0, import_editor_elements13.getContainer)(elementId);
|
|
5041
4939
|
if (!container) {
|
|
5042
4940
|
throw new Error(`Element with id ${elementId} not found`);
|
|
5043
4941
|
}
|
|
@@ -5137,36 +5035,53 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
|
|
|
5137
5035
|
}
|
|
5138
5036
|
|
|
5139
5037
|
// src/mcp/tools/get-page-structure/tool.ts
|
|
5140
|
-
var
|
|
5141
|
-
var
|
|
5142
|
-
var
|
|
5143
|
-
|
|
5038
|
+
var import_editor_documents2 = require("@elementor/editor-documents");
|
|
5039
|
+
var import_http_client7 = require("@elementor/http-client");
|
|
5040
|
+
var import_schema3 = require("@elementor/schema");
|
|
5041
|
+
|
|
5042
|
+
// src/mcp/utils/get-mcp-error-message.ts
|
|
5043
|
+
var import_http_client6 = require("@elementor/http-client");
|
|
5044
|
+
function getMcpErrorMessage(error, toolName) {
|
|
5045
|
+
if (error instanceof import_http_client6.AxiosError) {
|
|
5046
|
+
const data = error.response?.data;
|
|
5047
|
+
if (data?.message) {
|
|
5048
|
+
return data.code ? `${data.code}: ${data.message}` : data.message;
|
|
5049
|
+
}
|
|
5050
|
+
}
|
|
5051
|
+
if (error instanceof Error) {
|
|
5052
|
+
return error.message;
|
|
5053
|
+
}
|
|
5054
|
+
return `${toolName} failed with an unknown error.`;
|
|
5055
|
+
}
|
|
5056
|
+
|
|
5057
|
+
// src/mcp/tools/get-page-structure/tool.ts
|
|
5058
|
+
var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
|
|
5144
5059
|
var initGetPageStructureTool = (reg) => {
|
|
5145
5060
|
const { addTool } = reg;
|
|
5146
5061
|
addTool({
|
|
5147
5062
|
name: "get-page-structure",
|
|
5148
5063
|
description: "Returns a lean Elementor element tree skeleton (id, elType, widgetType, title, nested elements) for a post or page. If no postId is provided, uses the currently open document. Optionally scope to a subtree with elementId. Set includeContent=true (requires elementId) to also return each node's settings and styles.",
|
|
5149
5064
|
schema: {
|
|
5150
|
-
postId:
|
|
5065
|
+
postId: import_schema3.z.number().optional().describe(
|
|
5151
5066
|
"WordPress post ID of the Elementor document. If omitted, uses the currently open document."
|
|
5152
5067
|
),
|
|
5153
|
-
elementId:
|
|
5154
|
-
includeContent:
|
|
5068
|
+
elementId: import_schema3.z.string().optional().describe("If provided, returns only the subtree rooted at that element id."),
|
|
5069
|
+
includeContent: import_schema3.z.boolean().optional().describe(
|
|
5155
5070
|
"If true, includes each node's settings and styles (same shape build-composition accepts as input). Requires elementId."
|
|
5156
5071
|
)
|
|
5157
5072
|
},
|
|
5158
5073
|
outputSchema: {
|
|
5159
|
-
elements:
|
|
5074
|
+
elements: import_schema3.z.array(import_schema3.z.any()).describe(
|
|
5160
5075
|
"Skeleton of Elementor elements (id, elType, widgetType, title, nested elements). When includeContent is true, each node also includes settings and styles."
|
|
5161
5076
|
)
|
|
5162
5077
|
},
|
|
5163
5078
|
handler: async ({ postId, elementId, includeContent }) => {
|
|
5164
|
-
const resolvedPostId = postId ?? (0,
|
|
5079
|
+
const resolvedPostId = postId ?? (0, import_editor_documents2.getCurrentDocument)()?.id;
|
|
5165
5080
|
if (!resolvedPostId) {
|
|
5166
5081
|
throw new Error("No post ID provided and no active document found.");
|
|
5167
5082
|
}
|
|
5168
5083
|
try {
|
|
5169
|
-
const { data } = await (0,
|
|
5084
|
+
const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL5, {
|
|
5170
5085
|
tool: "get-page-structure",
|
|
5171
5086
|
input: {
|
|
5172
5087
|
post_id: resolvedPostId,
|
|
@@ -5196,7 +5111,6 @@ var initCanvasMcp = (reg) => {
|
|
|
5196
5111
|
initGeneralContextResource(reg);
|
|
5197
5112
|
initBestPracticesResource(reg);
|
|
5198
5113
|
initConfigureElementTool(reg);
|
|
5199
|
-
initBuildCompositionTool(reg);
|
|
5200
5114
|
initGetPageStructureTool(reg);
|
|
5201
5115
|
initBreakpointsResource(reg);
|
|
5202
5116
|
};
|
|
@@ -5204,7 +5118,7 @@ var initCanvasMcp = (reg) => {
|
|
|
5204
5118
|
// src/mcp/mcp-description.ts
|
|
5205
5119
|
var ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace("{widgetType}", "element-schema");
|
|
5206
5120
|
var mcpDescription = `Elementor Canvas MCP
|
|
5207
|
-
This MCP enables
|
|
5121
|
+
This MCP enables configuration and styling of existing V4 elements on the Elementor canvas using the configure-element tool.
|
|
5208
5122
|
|
|
5209
5123
|
# Core Concepts
|
|
5210
5124
|
|
|
@@ -5223,66 +5137,54 @@ The \`$$type\` defines how Elementor interprets the value. Providing the correct
|
|
|
5223
5137
|
- **Global Classes**: Reusable style sets that can be applied to elements (\`elementor://global-classes\`)
|
|
5224
5138
|
- **Widget Schemas**: Configuration options for each widget type (\`${WIDGET_SCHEMA_URI}\`)
|
|
5225
5139
|
|
|
5226
|
-
#
|
|
5140
|
+
# Configuring Elements with configure-element
|
|
5227
5141
|
|
|
5228
|
-
The \`
|
|
5142
|
+
The \`configure-element\` tool updates settings and styles on existing V4 elements. Read the configure-element guide resource before use.
|
|
5229
5143
|
|
|
5230
5144
|
## Complete Workflow
|
|
5231
5145
|
|
|
5232
5146
|
### 1. Parse User Requirements
|
|
5233
|
-
Understand what needs to
|
|
5147
|
+
Understand what needs to change: content, settings, or styling on existing elements.
|
|
5234
5148
|
|
|
5235
5149
|
### 2. Check Global Resources FIRST
|
|
5236
|
-
Always check existing resources before
|
|
5150
|
+
Always check existing resources before styling:
|
|
5237
5151
|
- List \`elementor://global-variables\` for available variables (colors, sizes, fonts)
|
|
5238
5152
|
- List \`elementor://global-classes\` for available style sets
|
|
5239
5153
|
- **Always prefer using existing global resources over creating inline styles**
|
|
5240
5154
|
|
|
5241
5155
|
### 3. Retrieve Widget Schemas
|
|
5242
|
-
For each
|
|
5156
|
+
For each element you will configure:
|
|
5243
5157
|
- List \`${WIDGET_SCHEMA_URI}\` to see available widgets
|
|
5244
5158
|
- Retrieve configuration schema from \`${ELEMENT_SCHEMA_URI}\` for each widget
|
|
5245
|
-
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
5159
|
+
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
5246
5160
|
|
|
5247
|
-
### 4.
|
|
5248
|
-
|
|
5249
|
-
- Each element must have a unique \`configuration-id\` attribute
|
|
5250
|
-
- No text nodes, classes, or IDs in XML - structure only
|
|
5251
|
-
- Example:
|
|
5252
|
-
\`\`\`xml
|
|
5253
|
-
<e-container configuration-id="container-1">
|
|
5254
|
-
<e-heading configuration-id="heading-1" />
|
|
5255
|
-
<e-text configuration-id="text-1" />
|
|
5256
|
-
</e-container>
|
|
5257
|
-
\`\`\`
|
|
5161
|
+
### 4. Get Current Element State
|
|
5162
|
+
Use page structure and element configuration resources to find element IDs and current values.
|
|
5258
5163
|
|
|
5259
|
-
### 5. Create
|
|
5260
|
-
Map
|
|
5164
|
+
### 5. Create propertiesToChange
|
|
5165
|
+
Map property names to PropValues using the widget schema:
|
|
5261
5166
|
- Use correct \`$$type\` matching the widget's schema
|
|
5262
5167
|
- Use global variables in PropValues where applicable
|
|
5263
5168
|
- Example:
|
|
5264
5169
|
\`\`\`json
|
|
5265
5170
|
{
|
|
5266
|
-
"
|
|
5267
|
-
|
|
5268
|
-
"tag": { "$$type": "string", "value": "h1" }
|
|
5269
|
-
}
|
|
5171
|
+
"text": { "$$type": "string", "value": "Welcome" },
|
|
5172
|
+
"tag": { "$$type": "string", "value": "h1" }
|
|
5270
5173
|
}
|
|
5271
5174
|
\`\`\`
|
|
5272
5175
|
|
|
5273
5176
|
### 6. Create style
|
|
5274
|
-
|
|
5177
|
+
Provide raw CSS declarations (property \u2192 value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
|
|
5275
5178
|
- Example:
|
|
5276
5179
|
\`\`\`json
|
|
5277
5180
|
{
|
|
5278
|
-
"
|
|
5279
|
-
|
|
5181
|
+
"color": "#1a1a1a",
|
|
5182
|
+
"font-size": "2rem"
|
|
5280
5183
|
}
|
|
5281
5184
|
\`\`\`
|
|
5282
5185
|
|
|
5283
|
-
### 7. Execute
|
|
5284
|
-
Call the tool with
|
|
5285
|
-
At the response you will also find llm_instructions for you to do afterwards, read and follow them!
|
|
5186
|
+
### 7. Execute configure-element
|
|
5187
|
+
Call the tool with elementId, elementType, propertiesToChange, and style as needed.
|
|
5286
5188
|
|
|
5287
5189
|
## Key Points
|
|
5288
5190
|
|
|
@@ -5310,7 +5212,7 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
|
|
|
5310
5212
|
`;
|
|
5311
5213
|
|
|
5312
5214
|
// src/prevent-link-in-link-commands.ts
|
|
5313
|
-
var
|
|
5215
|
+
var import_editor_elements14 = require("@elementor/editor-elements");
|
|
5314
5216
|
var import_editor_notifications3 = require("@elementor/editor-notifications");
|
|
5315
5217
|
var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
|
|
5316
5218
|
var import_i18n4 = require("@wordpress/i18n");
|
|
@@ -5381,24 +5283,24 @@ function shouldBlock(sourceElements, targetElements) {
|
|
|
5381
5283
|
return false;
|
|
5382
5284
|
}
|
|
5383
5285
|
const isSourceContainsAnAnchor = sourceElements.some((src) => {
|
|
5384
|
-
return src?.id ? (0,
|
|
5286
|
+
return src?.id ? (0, import_editor_elements14.isElementAnchored)(src.id) || !!(0, import_editor_elements14.getAnchoredDescendantId)(src.id) : false;
|
|
5385
5287
|
});
|
|
5386
5288
|
if (!isSourceContainsAnAnchor) {
|
|
5387
5289
|
return false;
|
|
5388
5290
|
}
|
|
5389
5291
|
const isTargetContainsAnAnchor = targetElements.some((target) => {
|
|
5390
|
-
return target?.id ? (0,
|
|
5292
|
+
return target?.id ? (0, import_editor_elements14.isElementAnchored)(target.id) || !!(0, import_editor_elements14.getAnchoredAncestorId)(target.id) : false;
|
|
5391
5293
|
});
|
|
5392
5294
|
return isTargetContainsAnAnchor;
|
|
5393
5295
|
}
|
|
5394
5296
|
|
|
5395
5297
|
// src/style-commands/paste-style.ts
|
|
5396
|
-
var
|
|
5298
|
+
var import_editor_elements17 = require("@elementor/editor-elements");
|
|
5397
5299
|
var import_editor_props10 = require("@elementor/editor-props");
|
|
5398
5300
|
var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
|
|
5399
5301
|
|
|
5400
5302
|
// src/utils/command-utils.ts
|
|
5401
|
-
var
|
|
5303
|
+
var import_editor_elements15 = require("@elementor/editor-elements");
|
|
5402
5304
|
var import_editor_props9 = require("@elementor/editor-props");
|
|
5403
5305
|
var import_i18n5 = require("@wordpress/i18n");
|
|
5404
5306
|
function hasAtomicWidgets(args) {
|
|
@@ -5423,7 +5325,7 @@ function getClassesProp(container) {
|
|
|
5423
5325
|
}
|
|
5424
5326
|
function getContainerSchema(container) {
|
|
5425
5327
|
const type = container?.model.get("widgetType") || container?.model.get("elType");
|
|
5426
|
-
const widgetsCache = (0,
|
|
5328
|
+
const widgetsCache = (0, import_editor_elements15.getWidgetsCache)();
|
|
5427
5329
|
const elementType = widgetsCache?.[type];
|
|
5428
5330
|
return elementType?.atomic_props_schema ?? null;
|
|
5429
5331
|
}
|
|
@@ -5436,11 +5338,11 @@ function getClipboardElements(storageKey = "clipboard") {
|
|
|
5436
5338
|
}
|
|
5437
5339
|
}
|
|
5438
5340
|
function getTitleForContainers(containers) {
|
|
5439
|
-
return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0,
|
|
5341
|
+
return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements15.getElementLabel)(containers[0].id);
|
|
5440
5342
|
}
|
|
5441
5343
|
|
|
5442
5344
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
5443
|
-
var
|
|
5345
|
+
var import_editor_elements16 = require("@elementor/editor-elements");
|
|
5444
5346
|
var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
|
|
5445
5347
|
var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
|
|
5446
5348
|
var import_i18n6 = require("@wordpress/i18n");
|
|
@@ -5453,7 +5355,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5453
5355
|
if (!classesProp) {
|
|
5454
5356
|
return null;
|
|
5455
5357
|
}
|
|
5456
|
-
const originalStyles = (0,
|
|
5358
|
+
const originalStyles = (0, import_editor_elements16.getElementStyles)(container.id);
|
|
5457
5359
|
const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
|
|
5458
5360
|
const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
|
|
5459
5361
|
const revertData = {
|
|
@@ -5462,7 +5364,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5462
5364
|
};
|
|
5463
5365
|
if (styleId) {
|
|
5464
5366
|
newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
|
|
5465
|
-
(0,
|
|
5367
|
+
(0, import_editor_elements16.updateElementStyle)({
|
|
5466
5368
|
elementId,
|
|
5467
5369
|
styleId,
|
|
5468
5370
|
meta,
|
|
@@ -5473,7 +5375,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5473
5375
|
} else {
|
|
5474
5376
|
const [firstVariant] = newStyle.variants;
|
|
5475
5377
|
const additionalVariants = newStyle.variants.slice(1);
|
|
5476
|
-
revertData.styleId = (0,
|
|
5378
|
+
revertData.styleId = (0, import_editor_elements16.createElementStyle)({
|
|
5477
5379
|
elementId,
|
|
5478
5380
|
classesProp,
|
|
5479
5381
|
label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -5491,7 +5393,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5491
5393
|
return;
|
|
5492
5394
|
}
|
|
5493
5395
|
if (!revertData.originalStyle) {
|
|
5494
|
-
(0,
|
|
5396
|
+
(0, import_editor_elements16.deleteElementStyle)(container.id, revertData.styleId);
|
|
5495
5397
|
return;
|
|
5496
5398
|
}
|
|
5497
5399
|
const classesProp = getClassesProp(container);
|
|
@@ -5500,7 +5402,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5500
5402
|
}
|
|
5501
5403
|
const [firstVariant] = revertData.originalStyle.variants;
|
|
5502
5404
|
const additionalVariants = revertData.originalStyle.variants.slice(1);
|
|
5503
|
-
(0,
|
|
5405
|
+
(0, import_editor_elements16.createElementStyle)({
|
|
5504
5406
|
elementId: container.id,
|
|
5505
5407
|
classesProp,
|
|
5506
5408
|
label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -5537,7 +5439,7 @@ function pasteStyles(args, pasteLocalStyle) {
|
|
|
5537
5439
|
}
|
|
5538
5440
|
const clipboardElements = getClipboardElements(storageKey);
|
|
5539
5441
|
const [clipboardElement] = clipboardElements ?? [];
|
|
5540
|
-
const clipboardContainer = (0,
|
|
5442
|
+
const clipboardContainer = (0, import_editor_elements17.getContainer)(clipboardElement.id);
|
|
5541
5443
|
if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
|
|
5542
5444
|
return;
|
|
5543
5445
|
}
|
|
@@ -5556,7 +5458,7 @@ function getClassesWithoutLocalStyle(clipboardContainer, style) {
|
|
|
5556
5458
|
if (!classesProp) {
|
|
5557
5459
|
return [];
|
|
5558
5460
|
}
|
|
5559
|
-
const classesSetting = (0,
|
|
5461
|
+
const classesSetting = (0, import_editor_elements17.getElementSetting)(clipboardContainer.id, classesProp);
|
|
5560
5462
|
return classesSetting?.value.filter((styleId) => styleId !== style?.id) ?? [];
|
|
5561
5463
|
}
|
|
5562
5464
|
function pasteClasses(containers, classes) {
|
|
@@ -5565,10 +5467,10 @@ function pasteClasses(containers, classes) {
|
|
|
5565
5467
|
if (!classesProp) {
|
|
5566
5468
|
return;
|
|
5567
5469
|
}
|
|
5568
|
-
const classesSetting = (0,
|
|
5470
|
+
const classesSetting = (0, import_editor_elements17.getElementSetting)(container.id, classesProp);
|
|
5569
5471
|
const currentClasses = import_editor_props10.classesPropTypeUtil.extract(classesSetting) ?? [];
|
|
5570
5472
|
const newClasses = import_editor_props10.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
|
|
5571
|
-
(0,
|
|
5473
|
+
(0, import_editor_elements17.updateElementSettings)({
|
|
5572
5474
|
id: container.id,
|
|
5573
5475
|
props: { [classesProp]: newClasses }
|
|
5574
5476
|
});
|
|
@@ -5579,7 +5481,7 @@ function pasteClasses(containers, classes) {
|
|
|
5579
5481
|
var import_editor_v1_adapters25 = require("@elementor/editor-v1-adapters");
|
|
5580
5482
|
|
|
5581
5483
|
// src/style-commands/undoable-actions/reset-element-style.ts
|
|
5582
|
-
var
|
|
5484
|
+
var import_editor_elements18 = require("@elementor/editor-elements");
|
|
5583
5485
|
var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
|
|
5584
5486
|
var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
|
|
5585
5487
|
var import_i18n7 = require("@wordpress/i18n");
|
|
@@ -5588,9 +5490,9 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
|
|
|
5588
5490
|
do: ({ containers }) => {
|
|
5589
5491
|
return containers.map((container) => {
|
|
5590
5492
|
const elementId = container.model.get("id");
|
|
5591
|
-
const containerStyles = (0,
|
|
5493
|
+
const containerStyles = (0, import_editor_elements18.getElementStyles)(elementId);
|
|
5592
5494
|
Object.keys(containerStyles ?? {}).forEach(
|
|
5593
|
-
(styleId) => (0,
|
|
5495
|
+
(styleId) => (0, import_editor_elements18.deleteElementStyle)(elementId, styleId)
|
|
5594
5496
|
);
|
|
5595
5497
|
return containerStyles;
|
|
5596
5498
|
});
|
|
@@ -5606,7 +5508,7 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
|
|
|
5606
5508
|
Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
|
|
5607
5509
|
const [firstVariant] = style.variants;
|
|
5608
5510
|
const additionalVariants = style.variants.slice(1);
|
|
5609
|
-
(0,
|
|
5511
|
+
(0, import_editor_elements18.createElementStyle)({
|
|
5610
5512
|
elementId,
|
|
5611
5513
|
classesProp,
|
|
5612
5514
|
styleId,
|
|
@@ -5680,10 +5582,9 @@ function init() {
|
|
|
5680
5582
|
initCanvasMcp(
|
|
5681
5583
|
(0, import_editor_mcp4.getMCPByDomain)("canvas", {
|
|
5682
5584
|
instructions: `Everything related to V4 ( Atomic ) canvas.
|
|
5683
|
-
# Canvas workflow
|
|
5684
|
-
- Configure
|
|
5685
|
-
-
|
|
5686
|
-
- Get and retrieve element configuration values
|
|
5585
|
+
# Canvas workflow
|
|
5586
|
+
- Configure element settings and styles with configure-element
|
|
5587
|
+
- Get page structure and element configuration values
|
|
5687
5588
|
`,
|
|
5688
5589
|
docs: mcpDescription
|
|
5689
5590
|
})
|
|
@@ -5806,10 +5707,10 @@ function useEscapeOnCanvas(canvasDocument, onEscape) {
|
|
|
5806
5707
|
}
|
|
5807
5708
|
|
|
5808
5709
|
// src/utils/after-render.ts
|
|
5809
|
-
var
|
|
5710
|
+
var import_editor_elements19 = require("@elementor/editor-elements");
|
|
5810
5711
|
function doAfterRender(elementIds, callback) {
|
|
5811
5712
|
const pending = elementIds.map((elementId) => {
|
|
5812
|
-
const view = (0,
|
|
5713
|
+
const view = (0, import_editor_elements19.getContainer)(elementId)?.view;
|
|
5813
5714
|
if (!view || !hasDoAfterRender(view)) {
|
|
5814
5715
|
return void 0;
|
|
5815
5716
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -2418,11 +2418,11 @@ function getVal2(val) {
|
|
|
2418
2418
|
var transformOriginTransformer = createTransformer((value) => {
|
|
2419
2419
|
const x = getVal2(value.x);
|
|
2420
2420
|
const y = getVal2(value.y);
|
|
2421
|
-
const
|
|
2422
|
-
if (x === DEFAULT_XY && y === DEFAULT_XY &&
|
|
2421
|
+
const z3 = getVal2(value.z);
|
|
2422
|
+
if (x === DEFAULT_XY && y === DEFAULT_XY && z3 === DEFAULT_Z) {
|
|
2423
2423
|
return null;
|
|
2424
2424
|
}
|
|
2425
|
-
return `${x} ${y} ${
|
|
2425
|
+
return `${x} ${y} ${z3}`;
|
|
2426
2426
|
});
|
|
2427
2427
|
|
|
2428
2428
|
// src/transformers/styles/transform-rotate-transformer.ts
|
|
@@ -4443,110 +4443,8 @@ function getElementDisplayName(container) {
|
|
|
4443
4443
|
}
|
|
4444
4444
|
}
|
|
4445
4445
|
|
|
4446
|
-
// src/mcp/tools/build-composition/tool.ts
|
|
4447
|
-
import { getCurrentDocument, reloadCurrentDocument } from "@elementor/editor-documents";
|
|
4448
|
-
import { getContainer as getContainer4, selectElement } from "@elementor/editor-elements";
|
|
4449
|
-
import { httpService as httpService6 } from "@elementor/http-client";
|
|
4450
|
-
import { z } from "@elementor/schema";
|
|
4451
|
-
|
|
4452
|
-
// src/mcp/utils/get-mcp-error-message.ts
|
|
4453
|
-
import { AxiosError } from "@elementor/http-client";
|
|
4454
|
-
function getMcpErrorMessage(error, toolName) {
|
|
4455
|
-
if (error instanceof AxiosError) {
|
|
4456
|
-
const data = error.response?.data;
|
|
4457
|
-
if (data?.message) {
|
|
4458
|
-
return data.code ? `${data.code}: ${data.message}` : data.message;
|
|
4459
|
-
}
|
|
4460
|
-
}
|
|
4461
|
-
if (error instanceof Error) {
|
|
4462
|
-
return error.message;
|
|
4463
|
-
}
|
|
4464
|
-
return `${toolName} failed with an unknown error.`;
|
|
4465
|
-
}
|
|
4466
|
-
|
|
4467
|
-
// src/mcp/tools/build-composition/tool.ts
|
|
4468
|
-
var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
|
|
4469
|
-
var initBuildCompositionTool = (reg) => {
|
|
4470
|
-
const { addTool } = reg;
|
|
4471
|
-
addTool({
|
|
4472
|
-
name: "build-composition",
|
|
4473
|
-
description: "Build a V4 element composition on the Elementor canvas via the server-side MCP ability. Pass the raw XML tags directly as xmlStructure \u2014 do NOT wrap the value in <![CDATA[ ... ]]>, code fences, or quotes. The document is saved as a draft. Reload the editor after calling this tool to see the result.",
|
|
4474
|
-
schema: {
|
|
4475
|
-
xmlStructure: z.string().describe(
|
|
4476
|
-
'Valid XML structure with custom Elementor widget tags. Every element MUST have a unique configuration-id attribute (e.g. <e-heading configuration-id="hero-title"></e-heading>). No attributes, classes, IDs, or text nodes in XML. Pass raw XML \u2014 do not wrap in CDATA.'
|
|
4477
|
-
),
|
|
4478
|
-
elementConfig: z.record(
|
|
4479
|
-
z.string().describe("configuration-id"),
|
|
4480
|
-
z.record(z.string().describe("property name"), z.any().describe("PropValue"))
|
|
4481
|
-
).optional().describe("Map configuration-id \u2192 widget PropValues ($$type + value)."),
|
|
4482
|
-
style: z.record(
|
|
4483
|
-
z.string().describe("configuration-id"),
|
|
4484
|
-
z.record(z.string().describe("CSS property name"), z.string().describe("CSS value"))
|
|
4485
|
-
).optional().describe(
|
|
4486
|
-
"Map configuration-id \u2192 raw CSS declarations (property \u2192 value strings; no selectors). Server converts to native styles; unconvertible declarations become the element custom CSS."
|
|
4487
|
-
),
|
|
4488
|
-
parentId: z.string().optional().describe("ID of the parent container. Omit or pass 'document' to insert at document root."),
|
|
4489
|
-
mode: z.enum(["append", "replace_children"]).optional().describe(
|
|
4490
|
-
"'append' (default) inserts under parentId; 'replace_children' removes existing direct children of parentId first, then inserts."
|
|
4491
|
-
),
|
|
4492
|
-
dryRun: z.boolean().optional().describe("If true, validate and return the resolved tree without persisting.")
|
|
4493
|
-
},
|
|
4494
|
-
outputSchema: {
|
|
4495
|
-
rootElementIds: z.array(z.string()),
|
|
4496
|
-
previewUrl: z.string(),
|
|
4497
|
-
version: z.string(),
|
|
4498
|
-
resolvedXml: z.string(),
|
|
4499
|
-
llmInstructions: z.string(),
|
|
4500
|
-
warnings: z.array(z.string()).optional(),
|
|
4501
|
-
removedElementIds: z.array(z.string()).optional()
|
|
4502
|
-
},
|
|
4503
|
-
handler: async ({ xmlStructure, elementConfig, style, parentId, mode, dryRun }) => {
|
|
4504
|
-
const document2 = getCurrentDocument();
|
|
4505
|
-
if (!document2?.id) {
|
|
4506
|
-
throw new Error("No active document found.");
|
|
4507
|
-
}
|
|
4508
|
-
try {
|
|
4509
|
-
const { data } = await httpService6().post(MCP_PROXY_URL5, {
|
|
4510
|
-
tool: "build-composition",
|
|
4511
|
-
input: {
|
|
4512
|
-
post_id: document2.id,
|
|
4513
|
-
xml_structure: xmlStructure,
|
|
4514
|
-
element_config: elementConfig ?? {},
|
|
4515
|
-
style: style ?? {},
|
|
4516
|
-
parent_id: parentId ?? "document",
|
|
4517
|
-
mode: mode ?? "append",
|
|
4518
|
-
dry_run: dryRun ?? false
|
|
4519
|
-
}
|
|
4520
|
-
});
|
|
4521
|
-
if (!dryRun) {
|
|
4522
|
-
await reloadCurrentDocument();
|
|
4523
|
-
const [firstRootId] = data.data.root_element_ids;
|
|
4524
|
-
if (firstRootId) {
|
|
4525
|
-
selectElement(firstRootId);
|
|
4526
|
-
getContainer4(firstRootId)?.view?.el?.scrollIntoView({
|
|
4527
|
-
behavior: "smooth",
|
|
4528
|
-
block: "center"
|
|
4529
|
-
});
|
|
4530
|
-
}
|
|
4531
|
-
}
|
|
4532
|
-
return {
|
|
4533
|
-
rootElementIds: data.data.root_element_ids,
|
|
4534
|
-
previewUrl: data.data.preview_url,
|
|
4535
|
-
version: data.data.version,
|
|
4536
|
-
resolvedXml: data.data.resolved_xml,
|
|
4537
|
-
llmInstructions: data.data.llm_instructions,
|
|
4538
|
-
warnings: data.data.warnings,
|
|
4539
|
-
removedElementIds: data.data.removed_element_ids
|
|
4540
|
-
};
|
|
4541
|
-
} catch (error) {
|
|
4542
|
-
throw new Error(getMcpErrorMessage(error, "build-composition"));
|
|
4543
|
-
}
|
|
4544
|
-
}
|
|
4545
|
-
});
|
|
4546
|
-
};
|
|
4547
|
-
|
|
4548
4446
|
// src/mcp/tools/configure-element/tool.ts
|
|
4549
|
-
import { getContainer as
|
|
4447
|
+
import { getContainer as getContainer4, getWidgetsCache as getWidgetsCache6 } from "@elementor/editor-elements";
|
|
4550
4448
|
import { dispatchMcpStylesAppliedEvent } from "@elementor/editor-mcp";
|
|
4551
4449
|
import { Schema as Schema2 } from "@elementor/editor-props";
|
|
4552
4450
|
|
|
@@ -4950,29 +4848,29 @@ Note: \`link\` is valid only when the element's PropType schema (which you must
|
|
|
4950
4848
|
};
|
|
4951
4849
|
|
|
4952
4850
|
// src/mcp/tools/configure-element/schema.ts
|
|
4953
|
-
import { z
|
|
4851
|
+
import { z } from "@elementor/schema";
|
|
4954
4852
|
var inputSchema = {
|
|
4955
|
-
propertiesToChange:
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4853
|
+
propertiesToChange: z.record(
|
|
4854
|
+
z.string().describe("The property name."),
|
|
4855
|
+
z.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
|
|
4856
|
+
z.any()
|
|
4959
4857
|
).describe("An object record containing property names and their new values to be set on the element"),
|
|
4960
|
-
style:
|
|
4961
|
-
|
|
4962
|
-
|
|
4858
|
+
style: z.record(
|
|
4859
|
+
z.string().describe('A CSS property name, e.g. "color", "margin-top".'),
|
|
4860
|
+
z.string().nullable().describe(
|
|
4963
4861
|
'A CSS value, e.g. "red", "10px", "1px solid #000". Use null to reset the property to its default.'
|
|
4964
4862
|
)
|
|
4965
4863
|
).describe(
|
|
4966
4864
|
"Raw CSS declarations as a flat property\u2192value map. Converted to native styles server-side; any declaration that cannot be converted is stored as the element custom CSS. A null value resets that property to its default."
|
|
4967
4865
|
).default({}),
|
|
4968
|
-
elementType:
|
|
4969
|
-
elementId:
|
|
4866
|
+
elementType: z.string().describe("The type of the element to retrieve the schema"),
|
|
4867
|
+
elementId: z.string().describe("The unique id of the element to configure")
|
|
4970
4868
|
};
|
|
4971
4869
|
var outputSchema = {
|
|
4972
|
-
success:
|
|
4870
|
+
success: z.boolean().describe(
|
|
4973
4871
|
"Whether the configuration change was successful, only if propertyName and propertyValue are provided"
|
|
4974
4872
|
),
|
|
4975
|
-
warnings:
|
|
4873
|
+
warnings: z.string().describe(
|
|
4976
4874
|
'Non-fatal notices. Present when some props were skipped because they are not in the element schema (e.g. a "link" on a widget with no link prop). Other changes were still applied.'
|
|
4977
4875
|
).optional()
|
|
4978
4876
|
};
|
|
@@ -5009,7 +4907,7 @@ var initConfigureElementTool = (reg) => {
|
|
|
5009
4907
|
`Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
|
|
5010
4908
|
);
|
|
5011
4909
|
}
|
|
5012
|
-
const container =
|
|
4910
|
+
const container = getContainer4(elementId);
|
|
5013
4911
|
if (!container) {
|
|
5014
4912
|
throw new Error(`Element with id ${elementId} not found`);
|
|
5015
4913
|
}
|
|
@@ -5109,36 +5007,53 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
|
|
|
5109
5007
|
}
|
|
5110
5008
|
|
|
5111
5009
|
// src/mcp/tools/get-page-structure/tool.ts
|
|
5112
|
-
import { getCurrentDocument
|
|
5113
|
-
import { httpService as
|
|
5114
|
-
import { z as
|
|
5115
|
-
|
|
5010
|
+
import { getCurrentDocument } from "@elementor/editor-documents";
|
|
5011
|
+
import { httpService as httpService6 } from "@elementor/http-client";
|
|
5012
|
+
import { z as z2 } from "@elementor/schema";
|
|
5013
|
+
|
|
5014
|
+
// src/mcp/utils/get-mcp-error-message.ts
|
|
5015
|
+
import { AxiosError } from "@elementor/http-client";
|
|
5016
|
+
function getMcpErrorMessage(error, toolName) {
|
|
5017
|
+
if (error instanceof AxiosError) {
|
|
5018
|
+
const data = error.response?.data;
|
|
5019
|
+
if (data?.message) {
|
|
5020
|
+
return data.code ? `${data.code}: ${data.message}` : data.message;
|
|
5021
|
+
}
|
|
5022
|
+
}
|
|
5023
|
+
if (error instanceof Error) {
|
|
5024
|
+
return error.message;
|
|
5025
|
+
}
|
|
5026
|
+
return `${toolName} failed with an unknown error.`;
|
|
5027
|
+
}
|
|
5028
|
+
|
|
5029
|
+
// src/mcp/tools/get-page-structure/tool.ts
|
|
5030
|
+
var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
|
|
5116
5031
|
var initGetPageStructureTool = (reg) => {
|
|
5117
5032
|
const { addTool } = reg;
|
|
5118
5033
|
addTool({
|
|
5119
5034
|
name: "get-page-structure",
|
|
5120
5035
|
description: "Returns a lean Elementor element tree skeleton (id, elType, widgetType, title, nested elements) for a post or page. If no postId is provided, uses the currently open document. Optionally scope to a subtree with elementId. Set includeContent=true (requires elementId) to also return each node's settings and styles.",
|
|
5121
5036
|
schema: {
|
|
5122
|
-
postId:
|
|
5037
|
+
postId: z2.number().optional().describe(
|
|
5123
5038
|
"WordPress post ID of the Elementor document. If omitted, uses the currently open document."
|
|
5124
5039
|
),
|
|
5125
|
-
elementId:
|
|
5126
|
-
includeContent:
|
|
5040
|
+
elementId: z2.string().optional().describe("If provided, returns only the subtree rooted at that element id."),
|
|
5041
|
+
includeContent: z2.boolean().optional().describe(
|
|
5127
5042
|
"If true, includes each node's settings and styles (same shape build-composition accepts as input). Requires elementId."
|
|
5128
5043
|
)
|
|
5129
5044
|
},
|
|
5130
5045
|
outputSchema: {
|
|
5131
|
-
elements:
|
|
5046
|
+
elements: z2.array(z2.any()).describe(
|
|
5132
5047
|
"Skeleton of Elementor elements (id, elType, widgetType, title, nested elements). When includeContent is true, each node also includes settings and styles."
|
|
5133
5048
|
)
|
|
5134
5049
|
},
|
|
5135
5050
|
handler: async ({ postId, elementId, includeContent }) => {
|
|
5136
|
-
const resolvedPostId = postId ??
|
|
5051
|
+
const resolvedPostId = postId ?? getCurrentDocument()?.id;
|
|
5137
5052
|
if (!resolvedPostId) {
|
|
5138
5053
|
throw new Error("No post ID provided and no active document found.");
|
|
5139
5054
|
}
|
|
5140
5055
|
try {
|
|
5141
|
-
const { data } = await
|
|
5056
|
+
const { data } = await httpService6().post(MCP_PROXY_URL5, {
|
|
5142
5057
|
tool: "get-page-structure",
|
|
5143
5058
|
input: {
|
|
5144
5059
|
post_id: resolvedPostId,
|
|
@@ -5168,7 +5083,6 @@ var initCanvasMcp = (reg) => {
|
|
|
5168
5083
|
initGeneralContextResource(reg);
|
|
5169
5084
|
initBestPracticesResource(reg);
|
|
5170
5085
|
initConfigureElementTool(reg);
|
|
5171
|
-
initBuildCompositionTool(reg);
|
|
5172
5086
|
initGetPageStructureTool(reg);
|
|
5173
5087
|
initBreakpointsResource(reg);
|
|
5174
5088
|
};
|
|
@@ -5176,7 +5090,7 @@ var initCanvasMcp = (reg) => {
|
|
|
5176
5090
|
// src/mcp/mcp-description.ts
|
|
5177
5091
|
var ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace("{widgetType}", "element-schema");
|
|
5178
5092
|
var mcpDescription = `Elementor Canvas MCP
|
|
5179
|
-
This MCP enables
|
|
5093
|
+
This MCP enables configuration and styling of existing V4 elements on the Elementor canvas using the configure-element tool.
|
|
5180
5094
|
|
|
5181
5095
|
# Core Concepts
|
|
5182
5096
|
|
|
@@ -5195,66 +5109,54 @@ The \`$$type\` defines how Elementor interprets the value. Providing the correct
|
|
|
5195
5109
|
- **Global Classes**: Reusable style sets that can be applied to elements (\`elementor://global-classes\`)
|
|
5196
5110
|
- **Widget Schemas**: Configuration options for each widget type (\`${WIDGET_SCHEMA_URI}\`)
|
|
5197
5111
|
|
|
5198
|
-
#
|
|
5112
|
+
# Configuring Elements with configure-element
|
|
5199
5113
|
|
|
5200
|
-
The \`
|
|
5114
|
+
The \`configure-element\` tool updates settings and styles on existing V4 elements. Read the configure-element guide resource before use.
|
|
5201
5115
|
|
|
5202
5116
|
## Complete Workflow
|
|
5203
5117
|
|
|
5204
5118
|
### 1. Parse User Requirements
|
|
5205
|
-
Understand what needs to
|
|
5119
|
+
Understand what needs to change: content, settings, or styling on existing elements.
|
|
5206
5120
|
|
|
5207
5121
|
### 2. Check Global Resources FIRST
|
|
5208
|
-
Always check existing resources before
|
|
5122
|
+
Always check existing resources before styling:
|
|
5209
5123
|
- List \`elementor://global-variables\` for available variables (colors, sizes, fonts)
|
|
5210
5124
|
- List \`elementor://global-classes\` for available style sets
|
|
5211
5125
|
- **Always prefer using existing global resources over creating inline styles**
|
|
5212
5126
|
|
|
5213
5127
|
### 3. Retrieve Widget Schemas
|
|
5214
|
-
For each
|
|
5128
|
+
For each element you will configure:
|
|
5215
5129
|
- List \`${WIDGET_SCHEMA_URI}\` to see available widgets
|
|
5216
5130
|
- Retrieve configuration schema from \`${ELEMENT_SCHEMA_URI}\` for each widget
|
|
5217
|
-
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
5131
|
+
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
5218
5132
|
|
|
5219
|
-
### 4.
|
|
5220
|
-
|
|
5221
|
-
- Each element must have a unique \`configuration-id\` attribute
|
|
5222
|
-
- No text nodes, classes, or IDs in XML - structure only
|
|
5223
|
-
- Example:
|
|
5224
|
-
\`\`\`xml
|
|
5225
|
-
<e-container configuration-id="container-1">
|
|
5226
|
-
<e-heading configuration-id="heading-1" />
|
|
5227
|
-
<e-text configuration-id="text-1" />
|
|
5228
|
-
</e-container>
|
|
5229
|
-
\`\`\`
|
|
5133
|
+
### 4. Get Current Element State
|
|
5134
|
+
Use page structure and element configuration resources to find element IDs and current values.
|
|
5230
5135
|
|
|
5231
|
-
### 5. Create
|
|
5232
|
-
Map
|
|
5136
|
+
### 5. Create propertiesToChange
|
|
5137
|
+
Map property names to PropValues using the widget schema:
|
|
5233
5138
|
- Use correct \`$$type\` matching the widget's schema
|
|
5234
5139
|
- Use global variables in PropValues where applicable
|
|
5235
5140
|
- Example:
|
|
5236
5141
|
\`\`\`json
|
|
5237
5142
|
{
|
|
5238
|
-
"
|
|
5239
|
-
|
|
5240
|
-
"tag": { "$$type": "string", "value": "h1" }
|
|
5241
|
-
}
|
|
5143
|
+
"text": { "$$type": "string", "value": "Welcome" },
|
|
5144
|
+
"tag": { "$$type": "string", "value": "h1" }
|
|
5242
5145
|
}
|
|
5243
5146
|
\`\`\`
|
|
5244
5147
|
|
|
5245
5148
|
### 6. Create style
|
|
5246
|
-
|
|
5149
|
+
Provide raw CSS declarations (property \u2192 value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
|
|
5247
5150
|
- Example:
|
|
5248
5151
|
\`\`\`json
|
|
5249
5152
|
{
|
|
5250
|
-
"
|
|
5251
|
-
|
|
5153
|
+
"color": "#1a1a1a",
|
|
5154
|
+
"font-size": "2rem"
|
|
5252
5155
|
}
|
|
5253
5156
|
\`\`\`
|
|
5254
5157
|
|
|
5255
|
-
### 7. Execute
|
|
5256
|
-
Call the tool with
|
|
5257
|
-
At the response you will also find llm_instructions for you to do afterwards, read and follow them!
|
|
5158
|
+
### 7. Execute configure-element
|
|
5159
|
+
Call the tool with elementId, elementType, propertiesToChange, and style as needed.
|
|
5258
5160
|
|
|
5259
5161
|
## Key Points
|
|
5260
5162
|
|
|
@@ -5369,7 +5271,7 @@ function shouldBlock(sourceElements, targetElements) {
|
|
|
5369
5271
|
}
|
|
5370
5272
|
|
|
5371
5273
|
// src/style-commands/paste-style.ts
|
|
5372
|
-
import { getContainer as
|
|
5274
|
+
import { getContainer as getContainer5, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
|
|
5373
5275
|
import { classesPropTypeUtil } from "@elementor/editor-props";
|
|
5374
5276
|
import {
|
|
5375
5277
|
__privateListenTo as listenTo5,
|
|
@@ -5522,7 +5424,7 @@ function pasteStyles(args, pasteLocalStyle) {
|
|
|
5522
5424
|
}
|
|
5523
5425
|
const clipboardElements = getClipboardElements(storageKey);
|
|
5524
5426
|
const [clipboardElement] = clipboardElements ?? [];
|
|
5525
|
-
const clipboardContainer =
|
|
5427
|
+
const clipboardContainer = getContainer5(clipboardElement.id);
|
|
5526
5428
|
if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
|
|
5527
5429
|
return;
|
|
5528
5430
|
}
|
|
@@ -5669,10 +5571,9 @@ function init() {
|
|
|
5669
5571
|
initCanvasMcp(
|
|
5670
5572
|
getMCPByDomain("canvas", {
|
|
5671
5573
|
instructions: `Everything related to V4 ( Atomic ) canvas.
|
|
5672
|
-
# Canvas workflow
|
|
5673
|
-
- Configure
|
|
5674
|
-
-
|
|
5675
|
-
- Get and retrieve element configuration values
|
|
5574
|
+
# Canvas workflow
|
|
5575
|
+
- Configure element settings and styles with configure-element
|
|
5576
|
+
- Get page structure and element configuration values
|
|
5676
5577
|
`,
|
|
5677
5578
|
docs: mcpDescription
|
|
5678
5579
|
})
|
|
@@ -5799,10 +5700,10 @@ function useEscapeOnCanvas(canvasDocument, onEscape) {
|
|
|
5799
5700
|
}
|
|
5800
5701
|
|
|
5801
5702
|
// src/utils/after-render.ts
|
|
5802
|
-
import { getContainer as
|
|
5703
|
+
import { getContainer as getContainer6 } from "@elementor/editor-elements";
|
|
5803
5704
|
function doAfterRender(elementIds, callback) {
|
|
5804
5705
|
const pending = elementIds.map((elementId) => {
|
|
5805
|
-
const view =
|
|
5706
|
+
const view = getContainer6(elementId)?.view;
|
|
5806
5707
|
if (!view || !hasDoAfterRender(view)) {
|
|
5807
5708
|
return void 0;
|
|
5808
5709
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "4.3.0-
|
|
4
|
+
"version": "4.3.0-1019",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,26 +37,26 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "4.3.0-
|
|
41
|
-
"@elementor/editor-controls": "4.3.0-
|
|
42
|
-
"@elementor/editor-documents": "4.3.0-
|
|
43
|
-
"@elementor/editor-elements": "4.3.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.3.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.3.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.3.0-
|
|
47
|
-
"@elementor/editor-props": "4.3.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.3.0-
|
|
49
|
-
"@elementor/editor-styles": "4.3.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.3.0-
|
|
51
|
-
"@elementor/editor-ui": "4.3.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.3.0-
|
|
53
|
-
"@elementor/events": "4.3.0-
|
|
54
|
-
"@elementor/http-client": "4.3.0-
|
|
55
|
-
"@elementor/schema": "4.3.0-
|
|
56
|
-
"@elementor/twing": "4.3.0-
|
|
40
|
+
"@elementor/editor": "4.3.0-1019",
|
|
41
|
+
"@elementor/editor-controls": "4.3.0-1019",
|
|
42
|
+
"@elementor/editor-documents": "4.3.0-1019",
|
|
43
|
+
"@elementor/editor-elements": "4.3.0-1019",
|
|
44
|
+
"@elementor/editor-interactions": "4.3.0-1019",
|
|
45
|
+
"@elementor/editor-mcp": "4.3.0-1019",
|
|
46
|
+
"@elementor/editor-notifications": "4.3.0-1019",
|
|
47
|
+
"@elementor/editor-props": "4.3.0-1019",
|
|
48
|
+
"@elementor/editor-responsive": "4.3.0-1019",
|
|
49
|
+
"@elementor/editor-styles": "4.3.0-1019",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.3.0-1019",
|
|
51
|
+
"@elementor/editor-ui": "4.3.0-1019",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.3.0-1019",
|
|
53
|
+
"@elementor/events": "4.3.0-1019",
|
|
54
|
+
"@elementor/http-client": "4.3.0-1019",
|
|
55
|
+
"@elementor/schema": "4.3.0-1019",
|
|
56
|
+
"@elementor/twing": "4.3.0-1019",
|
|
57
57
|
"@elementor/ui": "1.37.5",
|
|
58
|
-
"@elementor/utils": "4.3.0-
|
|
59
|
-
"@elementor/wp-media": "4.3.0-
|
|
58
|
+
"@elementor/utils": "4.3.0-1019",
|
|
59
|
+
"@elementor/wp-media": "4.3.0-1019",
|
|
60
60
|
"@floating-ui/react": "^0.27.5",
|
|
61
61
|
"@wordpress/i18n": "^5.13.0",
|
|
62
62
|
"dompurify": "^3.2.6"
|
package/src/init.tsx
CHANGED
|
@@ -54,10 +54,9 @@ export function init() {
|
|
|
54
54
|
initCanvasMcp(
|
|
55
55
|
getMCPByDomain( 'canvas', {
|
|
56
56
|
instructions: `Everything related to V4 ( Atomic ) canvas.
|
|
57
|
-
# Canvas workflow
|
|
58
|
-
- Configure
|
|
59
|
-
-
|
|
60
|
-
- Get and retrieve element configuration values
|
|
57
|
+
# Canvas workflow
|
|
58
|
+
- Configure element settings and styles with configure-element
|
|
59
|
+
- Get page structure and element configuration values
|
|
61
60
|
`,
|
|
62
61
|
docs: mcpDescription,
|
|
63
62
|
} )
|
package/src/mcp/canvas-mcp.ts
CHANGED
|
@@ -10,7 +10,6 @@ import { initEditorStateResource } from './resources/editor-state-resource';
|
|
|
10
10
|
import { initGeneralContextResource } from './resources/general-context-resource';
|
|
11
11
|
import { initSelectedElementResource } from './resources/selected-element-resource';
|
|
12
12
|
import { initWidgetsSchemaResource } from './resources/widgets-schema-resource';
|
|
13
|
-
import { initBuildCompositionTool } from './tools/build-composition/tool';
|
|
14
13
|
import { initConfigureElementTool } from './tools/configure-element/tool';
|
|
15
14
|
import { initGetPageStructureTool } from './tools/get-page-structure/tool';
|
|
16
15
|
import { getDynamicTagNamesByCategories } from './utils/resolve-dynamic-tag';
|
|
@@ -29,7 +28,6 @@ export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
|
|
|
29
28
|
initGeneralContextResource( reg );
|
|
30
29
|
initBestPracticesResource( reg );
|
|
31
30
|
initConfigureElementTool( reg );
|
|
32
|
-
initBuildCompositionTool( reg );
|
|
33
31
|
initGetPageStructureTool( reg );
|
|
34
32
|
initBreakpointsResource( reg );
|
|
35
33
|
};
|
|
@@ -3,7 +3,7 @@ import { WIDGET_SCHEMA_URI } from './resources/widgets-schema-resource';
|
|
|
3
3
|
const ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace( '{widgetType}', 'element-schema' );
|
|
4
4
|
|
|
5
5
|
export const mcpDescription = `Elementor Canvas MCP
|
|
6
|
-
This MCP enables
|
|
6
|
+
This MCP enables configuration and styling of existing V4 elements on the Elementor canvas using the configure-element tool.
|
|
7
7
|
|
|
8
8
|
# Core Concepts
|
|
9
9
|
|
|
@@ -22,66 +22,54 @@ The \`$$type\` defines how Elementor interprets the value. Providing the correct
|
|
|
22
22
|
- **Global Classes**: Reusable style sets that can be applied to elements (\`elementor://global-classes\`)
|
|
23
23
|
- **Widget Schemas**: Configuration options for each widget type (\`${ WIDGET_SCHEMA_URI }\`)
|
|
24
24
|
|
|
25
|
-
#
|
|
25
|
+
# Configuring Elements with configure-element
|
|
26
26
|
|
|
27
|
-
The \`
|
|
27
|
+
The \`configure-element\` tool updates settings and styles on existing V4 elements. Read the configure-element guide resource before use.
|
|
28
28
|
|
|
29
29
|
## Complete Workflow
|
|
30
30
|
|
|
31
31
|
### 1. Parse User Requirements
|
|
32
|
-
Understand what needs to
|
|
32
|
+
Understand what needs to change: content, settings, or styling on existing elements.
|
|
33
33
|
|
|
34
34
|
### 2. Check Global Resources FIRST
|
|
35
|
-
Always check existing resources before
|
|
35
|
+
Always check existing resources before styling:
|
|
36
36
|
- List \`elementor://global-variables\` for available variables (colors, sizes, fonts)
|
|
37
37
|
- List \`elementor://global-classes\` for available style sets
|
|
38
38
|
- **Always prefer using existing global resources over creating inline styles**
|
|
39
39
|
|
|
40
40
|
### 3. Retrieve Widget Schemas
|
|
41
|
-
For each
|
|
41
|
+
For each element you will configure:
|
|
42
42
|
- List \`${ WIDGET_SCHEMA_URI }\` to see available widgets
|
|
43
43
|
- Retrieve configuration schema from \`${ ELEMENT_SCHEMA_URI }\` for each widget
|
|
44
|
-
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
44
|
+
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
45
45
|
|
|
46
|
-
### 4.
|
|
47
|
-
|
|
48
|
-
- Each element must have a unique \`configuration-id\` attribute
|
|
49
|
-
- No text nodes, classes, or IDs in XML - structure only
|
|
50
|
-
- Example:
|
|
51
|
-
\`\`\`xml
|
|
52
|
-
<e-container configuration-id="container-1">
|
|
53
|
-
<e-heading configuration-id="heading-1" />
|
|
54
|
-
<e-text configuration-id="text-1" />
|
|
55
|
-
</e-container>
|
|
56
|
-
\`\`\`
|
|
46
|
+
### 4. Get Current Element State
|
|
47
|
+
Use page structure and element configuration resources to find element IDs and current values.
|
|
57
48
|
|
|
58
|
-
### 5. Create
|
|
59
|
-
Map
|
|
49
|
+
### 5. Create propertiesToChange
|
|
50
|
+
Map property names to PropValues using the widget schema:
|
|
60
51
|
- Use correct \`$$type\` matching the widget's schema
|
|
61
52
|
- Use global variables in PropValues where applicable
|
|
62
53
|
- Example:
|
|
63
54
|
\`\`\`json
|
|
64
55
|
{
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
"tag": { "$$type": "string", "value": "h1" }
|
|
68
|
-
}
|
|
56
|
+
"text": { "$$type": "string", "value": "Welcome" },
|
|
57
|
+
"tag": { "$$type": "string", "value": "h1" }
|
|
69
58
|
}
|
|
70
59
|
\`\`\`
|
|
71
60
|
|
|
72
61
|
### 6. Create style
|
|
73
|
-
|
|
62
|
+
Provide raw CSS declarations (property → value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
|
|
74
63
|
- Example:
|
|
75
64
|
\`\`\`json
|
|
76
65
|
{
|
|
77
|
-
"
|
|
78
|
-
|
|
66
|
+
"color": "#1a1a1a",
|
|
67
|
+
"font-size": "2rem"
|
|
79
68
|
}
|
|
80
69
|
\`\`\`
|
|
81
70
|
|
|
82
|
-
### 7. Execute
|
|
83
|
-
Call the tool with
|
|
84
|
-
At the response you will also find llm_instructions for you to do afterwards, read and follow them!
|
|
71
|
+
### 7. Execute configure-element
|
|
72
|
+
Call the tool with elementId, elementType, propertiesToChange, and style as needed.
|
|
85
73
|
|
|
86
74
|
## Key Points
|
|
87
75
|
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { getCurrentDocument, reloadCurrentDocument } from '@elementor/editor-documents';
|
|
2
|
-
import { getContainer, selectElement } from '@elementor/editor-elements';
|
|
3
|
-
import { type MCPRegistryEntry } from '@elementor/editor-mcp';
|
|
4
|
-
import { type HttpResponse, httpService } from '@elementor/http-client';
|
|
5
|
-
import { z } from '@elementor/schema';
|
|
6
|
-
|
|
7
|
-
import { getMcpErrorMessage } from '../../utils/get-mcp-error-message';
|
|
8
|
-
|
|
9
|
-
const MCP_PROXY_URL = 'elementor/v1/mcp-proxy';
|
|
10
|
-
|
|
11
|
-
type BuildCompositionResponse = {
|
|
12
|
-
success: boolean;
|
|
13
|
-
post_id: number;
|
|
14
|
-
root_element_ids: string[];
|
|
15
|
-
preview_url: string;
|
|
16
|
-
version: string;
|
|
17
|
-
resolved_xml: string;
|
|
18
|
-
llm_instructions: string;
|
|
19
|
-
warnings?: string[];
|
|
20
|
-
removed_element_ids?: string[];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const initBuildCompositionTool = ( reg: MCPRegistryEntry ) => {
|
|
24
|
-
const { addTool } = reg;
|
|
25
|
-
|
|
26
|
-
addTool( {
|
|
27
|
-
name: 'build-composition',
|
|
28
|
-
description:
|
|
29
|
-
'Build a V4 element composition on the Elementor canvas via the server-side MCP ability. ' +
|
|
30
|
-
'Pass the raw XML tags directly as xmlStructure — do NOT wrap the value in <![CDATA[ ... ]]>, ' +
|
|
31
|
-
'code fences, or quotes. The document is saved as a draft. Reload the editor after calling ' +
|
|
32
|
-
'this tool to see the result.',
|
|
33
|
-
schema: {
|
|
34
|
-
xmlStructure: z
|
|
35
|
-
.string()
|
|
36
|
-
.describe(
|
|
37
|
-
'Valid XML structure with custom Elementor widget tags. Every element MUST have a unique ' +
|
|
38
|
-
'configuration-id attribute (e.g. <e-heading configuration-id="hero-title"></e-heading>). ' +
|
|
39
|
-
'No attributes, classes, IDs, or text nodes in XML. Pass raw XML — do not wrap in CDATA.'
|
|
40
|
-
),
|
|
41
|
-
elementConfig: z
|
|
42
|
-
.record(
|
|
43
|
-
z.string().describe( 'configuration-id' ),
|
|
44
|
-
z.record( z.string().describe( 'property name' ), z.any().describe( 'PropValue' ) )
|
|
45
|
-
)
|
|
46
|
-
.optional()
|
|
47
|
-
.describe( 'Map configuration-id → widget PropValues ($$type + value).' ),
|
|
48
|
-
style: z
|
|
49
|
-
.record(
|
|
50
|
-
z.string().describe( 'configuration-id' ),
|
|
51
|
-
z.record( z.string().describe( 'CSS property name' ), z.string().describe( 'CSS value' ) )
|
|
52
|
-
)
|
|
53
|
-
.optional()
|
|
54
|
-
.describe(
|
|
55
|
-
'Map configuration-id → raw CSS declarations (property → value strings; no selectors). ' +
|
|
56
|
-
'Server converts to native styles; unconvertible declarations become the element custom CSS.'
|
|
57
|
-
),
|
|
58
|
-
parentId: z
|
|
59
|
-
.string()
|
|
60
|
-
.optional()
|
|
61
|
-
.describe( "ID of the parent container. Omit or pass 'document' to insert at document root." ),
|
|
62
|
-
mode: z
|
|
63
|
-
.enum( [ 'append', 'replace_children' ] )
|
|
64
|
-
.optional()
|
|
65
|
-
.describe(
|
|
66
|
-
"'append' (default) inserts under parentId; 'replace_children' removes existing direct children of parentId first, then inserts."
|
|
67
|
-
),
|
|
68
|
-
dryRun: z
|
|
69
|
-
.boolean()
|
|
70
|
-
.optional()
|
|
71
|
-
.describe( 'If true, validate and return the resolved tree without persisting.' ),
|
|
72
|
-
},
|
|
73
|
-
outputSchema: {
|
|
74
|
-
rootElementIds: z.array( z.string() ),
|
|
75
|
-
previewUrl: z.string(),
|
|
76
|
-
version: z.string(),
|
|
77
|
-
resolvedXml: z.string(),
|
|
78
|
-
llmInstructions: z.string(),
|
|
79
|
-
warnings: z.array( z.string() ).optional(),
|
|
80
|
-
removedElementIds: z.array( z.string() ).optional(),
|
|
81
|
-
},
|
|
82
|
-
handler: async ( { xmlStructure, elementConfig, style, parentId, mode, dryRun } ) => {
|
|
83
|
-
const document = getCurrentDocument();
|
|
84
|
-
|
|
85
|
-
if ( ! document?.id ) {
|
|
86
|
-
throw new Error( 'No active document found.' );
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
const { data } = await httpService().post< HttpResponse< BuildCompositionResponse > >( MCP_PROXY_URL, {
|
|
91
|
-
tool: 'build-composition',
|
|
92
|
-
input: {
|
|
93
|
-
post_id: document.id,
|
|
94
|
-
xml_structure: xmlStructure,
|
|
95
|
-
element_config: elementConfig ?? {},
|
|
96
|
-
style: style ?? {},
|
|
97
|
-
parent_id: parentId ?? 'document',
|
|
98
|
-
mode: mode ?? 'append',
|
|
99
|
-
dry_run: dryRun ?? false,
|
|
100
|
-
},
|
|
101
|
-
} );
|
|
102
|
-
|
|
103
|
-
if ( ! dryRun ) {
|
|
104
|
-
await reloadCurrentDocument();
|
|
105
|
-
|
|
106
|
-
const [ firstRootId ] = data.data.root_element_ids;
|
|
107
|
-
if ( firstRootId ) {
|
|
108
|
-
selectElement( firstRootId );
|
|
109
|
-
getContainer( firstRootId )?.view?.el?.scrollIntoView( {
|
|
110
|
-
behavior: 'smooth',
|
|
111
|
-
block: 'center',
|
|
112
|
-
} );
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
rootElementIds: data.data.root_element_ids,
|
|
118
|
-
previewUrl: data.data.preview_url,
|
|
119
|
-
version: data.data.version,
|
|
120
|
-
resolvedXml: data.data.resolved_xml,
|
|
121
|
-
llmInstructions: data.data.llm_instructions,
|
|
122
|
-
warnings: data.data.warnings,
|
|
123
|
-
removedElementIds: data.data.removed_element_ids,
|
|
124
|
-
};
|
|
125
|
-
} catch ( error ) {
|
|
126
|
-
throw new Error( getMcpErrorMessage( error, 'build-composition' ) );
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
} );
|
|
130
|
-
};
|