@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 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 z4 = getVal2(value.z);
2470
- if (x === DEFAULT_XY && y === DEFAULT_XY && z4 === DEFAULT_Z) {
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} ${z4}`;
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 import_editor_elements14 = require("@elementor/editor-elements");
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 import_editor_elements13 = require("@elementor/editor-elements");
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 import_editor_elements12 = require("@elementor/editor-elements");
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, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
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, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
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, import_editor_elements13.getElementStyles)(elementId) || {};
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, import_editor_elements13.createElementStyle)({
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, import_editor_elements13.updateElementStyle)({
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, import_editor_elements13.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
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, import_editor_elements13.updateElementSettings)({
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 import_schema2 = require("@elementor/schema");
4879
+ var import_schema = require("@elementor/schema");
4982
4880
  var inputSchema = {
4983
- propertiesToChange: import_schema2.z.record(
4984
- import_schema2.z.string().describe("The property name."),
4985
- import_schema2.z.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
4986
- import_schema2.z.any()
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: import_schema2.z.record(
4989
- import_schema2.z.string().describe('A CSS property name, e.g. "color", "margin-top".'),
4990
- import_schema2.z.string().nullable().describe(
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: import_schema2.z.string().describe("The type of the element to retrieve the schema"),
4997
- elementId: import_schema2.z.string().describe("The unique id of the element to configure")
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: import_schema2.z.boolean().describe(
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: import_schema2.z.string().describe(
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, import_editor_elements14.getWidgetsCache)()?.[elementType];
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, import_editor_elements14.getContainer)(elementId);
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 import_editor_documents3 = require("@elementor/editor-documents");
5141
- var import_http_client8 = require("@elementor/http-client");
5142
- var import_schema4 = require("@elementor/schema");
5143
- var MCP_PROXY_URL6 = "elementor/v1/mcp-proxy";
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: import_schema4.z.number().optional().describe(
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: import_schema4.z.string().optional().describe("If provided, returns only the subtree rooted at that element id."),
5154
- includeContent: import_schema4.z.boolean().optional().describe(
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: import_schema4.z.array(import_schema4.z.any()).describe(
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, import_editor_documents3.getCurrentDocument)()?.id;
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, import_http_client8.httpService)().post(MCP_PROXY_URL6, {
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 creation, configuration, and styling of elements on the Elementor canvas using the build_composition tool.
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
- # Building Compositions with build_composition
5140
+ # Configuring Elements with configure-element
5227
5141
 
5228
- The \`build_composition\` tool is the primary way to create elements. It accepts structure (XML), configuration, and styling in a single operation.
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 be built: structure, content, and styling.
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 building:
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 widget you'll use:
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\` (omit default_settings from elementConfig unless the user asks to change them)
5159
+ - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
5246
5160
 
5247
- ### 4. Build XML Structure
5248
- Create valid XML with configuration-ids:
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 elementConfig
5260
- Map each configuration-id to its widget properties using PropValues:
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
- "heading-1": {
5267
- "text": { "$$type": "string", "value": "Welcome" },
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
- Map each configuration-id to raw CSS declarations (property \u2192 value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
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
- "heading-1": "color: #1a1a1a; font-size: 2rem;"
5279
- }
5181
+ "color": "#1a1a1a",
5182
+ "font-size": "2rem"
5280
5183
  }
5281
5184
  \`\`\`
5282
5185
 
5283
- ### 7. Execute build_composition
5284
- Call the tool with your XML structure, elementConfig, and style. The response will contain the created element IDs.
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 import_editor_elements15 = require("@elementor/editor-elements");
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, import_editor_elements15.isElementAnchored)(src.id) || !!(0, import_editor_elements15.getAnchoredDescendantId)(src.id) : false;
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, import_editor_elements15.isElementAnchored)(target.id) || !!(0, import_editor_elements15.getAnchoredAncestorId)(target.id) : false;
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 import_editor_elements18 = require("@elementor/editor-elements");
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 import_editor_elements16 = require("@elementor/editor-elements");
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, import_editor_elements16.getWidgetsCache)();
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, import_editor_elements16.getElementLabel)(containers[0].id);
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 import_editor_elements17 = require("@elementor/editor-elements");
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, import_editor_elements17.getElementStyles)(container.id);
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, import_editor_elements17.updateElementStyle)({
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, import_editor_elements17.createElementStyle)({
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, import_editor_elements17.deleteElementStyle)(container.id, revertData.styleId);
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, import_editor_elements17.createElementStyle)({
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, import_editor_elements18.getContainer)(clipboardElement.id);
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, import_editor_elements18.getElementSetting)(clipboardContainer.id, classesProp);
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, import_editor_elements18.getElementSetting)(container.id, classesProp);
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, import_editor_elements18.updateElementSettings)({
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 import_editor_elements19 = require("@elementor/editor-elements");
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, import_editor_elements19.getElementStyles)(elementId);
5493
+ const containerStyles = (0, import_editor_elements18.getElementStyles)(elementId);
5592
5494
  Object.keys(containerStyles ?? {}).forEach(
5593
- (styleId) => (0, import_editor_elements19.deleteElementStyle)(elementId, styleId)
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, import_editor_elements19.createElementStyle)({
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 for new compositions
5684
- - Configure elements settings and styles
5685
- - Build compositions/sections out of V4 atomic elements using context aware designs using the website resources
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 import_editor_elements20 = require("@elementor/editor-elements");
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, import_editor_elements20.getContainer)(elementId)?.view;
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 z4 = getVal2(value.z);
2422
- if (x === DEFAULT_XY && y === DEFAULT_XY && z4 === DEFAULT_Z) {
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} ${z4}`;
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 getContainer5, getWidgetsCache as getWidgetsCache6 } from "@elementor/editor-elements";
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 as z2 } from "@elementor/schema";
4851
+ import { z } from "@elementor/schema";
4954
4852
  var inputSchema = {
4955
- propertiesToChange: z2.record(
4956
- z2.string().describe("The property name."),
4957
- z2.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
4958
- z2.any()
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: z2.record(
4961
- z2.string().describe('A CSS property name, e.g. "color", "margin-top".'),
4962
- z2.string().nullable().describe(
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: z2.string().describe("The type of the element to retrieve the schema"),
4969
- elementId: z2.string().describe("The unique id of the element to configure")
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: z2.boolean().describe(
4870
+ success: z.boolean().describe(
4973
4871
  "Whether the configuration change was successful, only if propertyName and propertyValue are provided"
4974
4872
  ),
4975
- warnings: z2.string().describe(
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 = getContainer5(elementId);
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 as getCurrentDocument2 } from "@elementor/editor-documents";
5113
- import { httpService as httpService7 } from "@elementor/http-client";
5114
- import { z as z3 } from "@elementor/schema";
5115
- var MCP_PROXY_URL6 = "elementor/v1/mcp-proxy";
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: z3.number().optional().describe(
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: z3.string().optional().describe("If provided, returns only the subtree rooted at that element id."),
5126
- includeContent: z3.boolean().optional().describe(
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: z3.array(z3.any()).describe(
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 ?? getCurrentDocument2()?.id;
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 httpService7().post(MCP_PROXY_URL6, {
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 creation, configuration, and styling of elements on the Elementor canvas using the build_composition tool.
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
- # Building Compositions with build_composition
5112
+ # Configuring Elements with configure-element
5199
5113
 
5200
- The \`build_composition\` tool is the primary way to create elements. It accepts structure (XML), configuration, and styling in a single operation.
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 be built: structure, content, and styling.
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 building:
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 widget you'll use:
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\` (omit default_settings from elementConfig unless the user asks to change them)
5131
+ - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
5218
5132
 
5219
- ### 4. Build XML Structure
5220
- Create valid XML with configuration-ids:
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 elementConfig
5232
- Map each configuration-id to its widget properties using PropValues:
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
- "heading-1": {
5239
- "text": { "$$type": "string", "value": "Welcome" },
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
- Map each configuration-id to raw CSS declarations (property \u2192 value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
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
- "heading-1": "color: #1a1a1a; font-size: 2rem;"
5251
- }
5153
+ "color": "#1a1a1a",
5154
+ "font-size": "2rem"
5252
5155
  }
5253
5156
  \`\`\`
5254
5157
 
5255
- ### 7. Execute build_composition
5256
- Call the tool with your XML structure, elementConfig, and style. The response will contain the created element IDs.
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 getContainer6, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
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 = getContainer6(clipboardElement.id);
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 for new compositions
5673
- - Configure elements settings and styles
5674
- - Build compositions/sections out of V4 atomic elements using context aware designs using the website resources
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 getContainer7 } from "@elementor/editor-elements";
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 = getContainer7(elementId)?.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-1017",
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-1017",
41
- "@elementor/editor-controls": "4.3.0-1017",
42
- "@elementor/editor-documents": "4.3.0-1017",
43
- "@elementor/editor-elements": "4.3.0-1017",
44
- "@elementor/editor-interactions": "4.3.0-1017",
45
- "@elementor/editor-mcp": "4.3.0-1017",
46
- "@elementor/editor-notifications": "4.3.0-1017",
47
- "@elementor/editor-props": "4.3.0-1017",
48
- "@elementor/editor-responsive": "4.3.0-1017",
49
- "@elementor/editor-styles": "4.3.0-1017",
50
- "@elementor/editor-styles-repository": "4.3.0-1017",
51
- "@elementor/editor-ui": "4.3.0-1017",
52
- "@elementor/editor-v1-adapters": "4.3.0-1017",
53
- "@elementor/events": "4.3.0-1017",
54
- "@elementor/http-client": "4.3.0-1017",
55
- "@elementor/schema": "4.3.0-1017",
56
- "@elementor/twing": "4.3.0-1017",
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-1017",
59
- "@elementor/wp-media": "4.3.0-1017",
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 for new compositions
58
- - Configure elements settings and styles
59
- - Build compositions/sections out of V4 atomic elements using context aware designs using the website resources
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
  } )
@@ -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 creation, configuration, and styling of elements on the Elementor canvas using the build_composition tool.
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
- # Building Compositions with build_composition
25
+ # Configuring Elements with configure-element
26
26
 
27
- The \`build_composition\` tool is the primary way to create elements. It accepts structure (XML), configuration, and styling in a single operation.
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 be built: structure, content, and styling.
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 building:
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 widget you'll use:
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\` (omit default_settings from elementConfig unless the user asks to change them)
44
+ - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
45
45
 
46
- ### 4. Build XML Structure
47
- Create valid XML with configuration-ids:
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 elementConfig
59
- Map each configuration-id to its widget properties using PropValues:
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
- "heading-1": {
66
- "text": { "$$type": "string", "value": "Welcome" },
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
- Map each configuration-id to raw CSS declarations (property → value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
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
- "heading-1": "color: #1a1a1a; font-size: 2rem;"
78
- }
66
+ "color": "#1a1a1a",
67
+ "font-size": "2rem"
79
68
  }
80
69
  \`\`\`
81
70
 
82
- ### 7. Execute build_composition
83
- Call the tool with your XML structure, elementConfig, and style. The response will contain the created element IDs.
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
- };