@elementor/editor-canvas 4.3.0-1001 → 4.3.0-1003

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
@@ -116,13 +116,13 @@ var initWidgetsSchemaResource = (reg) => {
116
116
  if (!widgetType) {
117
117
  throw new Error("No widget type provided.");
118
118
  }
119
- const schema2 = await fetchWidgetSchema(widgetType);
119
+ const schema = await fetchWidgetSchema(widgetType);
120
120
  return {
121
121
  contents: [
122
122
  {
123
123
  uri: uri.toString(),
124
124
  mimeType: "application/json",
125
- text: JSON.stringify(schema2)
125
+ text: JSON.stringify(schema)
126
126
  }
127
127
  ]
128
128
  };
@@ -1310,10 +1310,10 @@ var getMultiPropsValue = (multiProps) => {
1310
1310
  // src/renderers/create-props-resolver.ts
1311
1311
  var TRANSFORM_DEPTH_LIMIT = 3;
1312
1312
  function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
1313
- async function resolve({ props, schema: schema2, signal, renderContext }) {
1314
- schema2 = schema2 ?? initialSchema;
1313
+ async function resolve({ props, schema, signal, renderContext }) {
1314
+ schema = schema ?? initialSchema;
1315
1315
  const promises = Promise.all(
1316
- Object.entries(schema2).map(async ([key, type]) => {
1316
+ Object.entries(schema).map(async ([key, type]) => {
1317
1317
  const value = props[key] ?? type.default;
1318
1318
  const transformed = await transform({ value, key, type, signal, renderContext });
1319
1319
  onPropResolve?.({ key, value: transformed, propValue: value, propType: type });
@@ -3961,7 +3961,7 @@ function initTabsModelExtensions() {
3961
3961
  }
3962
3962
 
3963
3963
  // src/mcp/canvas-mcp.ts
3964
- var import_editor_props9 = require("@elementor/editor-props");
3964
+ var import_editor_props8 = require("@elementor/editor-props");
3965
3965
 
3966
3966
  // src/mcp/resources/available-widgets-resource.ts
3967
3967
  var import_http_client3 = require("@elementor/http-client");
@@ -4482,8 +4482,25 @@ function getElementDisplayName(container) {
4482
4482
  // src/mcp/tools/build-composition/tool.ts
4483
4483
  var import_editor_documents2 = require("@elementor/editor-documents");
4484
4484
  var import_editor_elements11 = require("@elementor/editor-elements");
4485
- var import_http_client6 = require("@elementor/http-client");
4485
+ var import_http_client7 = require("@elementor/http-client");
4486
4486
  var import_schema = require("@elementor/schema");
4487
+
4488
+ // src/mcp/utils/get-mcp-error-message.ts
4489
+ var import_http_client6 = require("@elementor/http-client");
4490
+ function getMcpErrorMessage(error, toolName) {
4491
+ if (error instanceof import_http_client6.AxiosError) {
4492
+ const data = error.response?.data;
4493
+ if (data?.message) {
4494
+ return data.code ? `${data.code}: ${data.message}` : data.message;
4495
+ }
4496
+ }
4497
+ if (error instanceof Error) {
4498
+ return error.message;
4499
+ }
4500
+ return `${toolName} failed with an unknown error.`;
4501
+ }
4502
+
4503
+ // src/mcp/tools/build-composition/tool.ts
4487
4504
  var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
4488
4505
  var initBuildCompositionTool = (reg) => {
4489
4506
  const { addTool } = reg;
@@ -4521,7 +4538,7 @@ var initBuildCompositionTool = (reg) => {
4521
4538
  throw new Error("No active document found.");
4522
4539
  }
4523
4540
  try {
4524
- const { data } = await (0, import_http_client6.httpService)().post(MCP_PROXY_URL5, {
4541
+ const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL5, {
4525
4542
  tool: "build-composition",
4526
4543
  input: {
4527
4544
  post_id: document2.id,
@@ -4552,23 +4569,11 @@ var initBuildCompositionTool = (reg) => {
4552
4569
  warnings: data.data.warnings
4553
4570
  };
4554
4571
  } catch (error) {
4555
- throw new Error(getErrorMessage(error));
4572
+ throw new Error(getMcpErrorMessage(error, "build-composition"));
4556
4573
  }
4557
4574
  }
4558
4575
  });
4559
4576
  };
4560
- function getErrorMessage(error) {
4561
- if (error instanceof import_http_client6.AxiosError) {
4562
- const data = error.response?.data;
4563
- if (data?.message) {
4564
- return data.code ? `${data.code}: ${data.message}` : data.message;
4565
- }
4566
- }
4567
- if (error instanceof Error) {
4568
- return error.message;
4569
- }
4570
- return "build-composition failed with an unknown error.";
4571
- }
4572
4577
 
4573
4578
  // src/mcp/tools/configure-element/tool.ts
4574
4579
  var import_editor_elements14 = require("@elementor/editor-elements");
@@ -4597,9 +4602,9 @@ var readStoredCustomCssText = (raw) => {
4597
4602
 
4598
4603
  // src/mcp/utils/resolve-canonical-prop-name.ts
4599
4604
  var import_editor_elements12 = require("@elementor/editor-elements");
4600
- function buildAliasToCanonicalMap(schema2) {
4605
+ function buildAliasToCanonicalMap(schema) {
4601
4606
  const aliasToCanonical = {};
4602
- for (const [canonical, propType] of Object.entries(schema2)) {
4607
+ for (const [canonical, propType] of Object.entries(schema)) {
4603
4608
  const aliases = propType.meta?.aliases;
4604
4609
  if (!Array.isArray(aliases)) {
4605
4610
  continue;
@@ -4613,26 +4618,26 @@ function buildAliasToCanonicalMap(schema2) {
4613
4618
  return aliasToCanonical;
4614
4619
  }
4615
4620
  function resolveCanonicalPropName(elementType, propertyName) {
4616
- const schema2 = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4617
- if (!schema2 || schema2[propertyName]) {
4621
+ const schema = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4622
+ if (!schema || schema[propertyName]) {
4618
4623
  return propertyName;
4619
4624
  }
4620
- return buildAliasToCanonicalMap(schema2)[propertyName] ?? propertyName;
4625
+ return buildAliasToCanonicalMap(schema)[propertyName] ?? propertyName;
4621
4626
  }
4622
4627
  function resolveCanonicalPropKeys(elementType, props) {
4623
- const schema2 = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4624
- if (!schema2) {
4628
+ const schema = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4629
+ if (!schema) {
4625
4630
  return { ...props };
4626
4631
  }
4627
- const aliasToCanonical = buildAliasToCanonicalMap(schema2);
4632
+ const aliasToCanonical = buildAliasToCanonicalMap(schema);
4628
4633
  const resolved = {};
4629
4634
  for (const [key, value] of Object.entries(props)) {
4630
- if (schema2[key]) {
4635
+ if (schema[key]) {
4631
4636
  resolved[key] = value;
4632
4637
  }
4633
4638
  }
4634
4639
  for (const [key, value] of Object.entries(props)) {
4635
- if (schema2[key]) {
4640
+ if (schema[key]) {
4636
4641
  continue;
4637
4642
  }
4638
4643
  const canonical = aliasToCanonical[key];
@@ -4680,9 +4685,9 @@ var dynamicTagLLMResolver = (value) => {
4680
4685
  }
4681
4686
  };
4682
4687
  };
4683
- var buildStrictSettings = (schema2, provided) => {
4688
+ var buildStrictSettings = (schema, provided) => {
4684
4689
  const settings = {};
4685
- for (const [key, propType] of Object.entries(schema2)) {
4690
+ for (const [key, propType] of Object.entries(schema)) {
4686
4691
  if (OMITTED_DYNAMIC_SETTING_KEYS.includes(key)) {
4687
4692
  continue;
4688
4693
  }
@@ -5109,102 +5114,49 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
5109
5114
  }`;
5110
5115
  }
5111
5116
 
5112
- // src/mcp/tools/get-element-config/tool.ts
5113
- var import_editor_elements15 = require("@elementor/editor-elements");
5114
- var import_editor_props8 = require("@elementor/editor-props");
5117
+ // src/mcp/tools/get-page-structure/tool.ts
5118
+ var import_editor_documents3 = require("@elementor/editor-documents");
5119
+ var import_http_client8 = require("@elementor/http-client");
5115
5120
  var import_schema4 = require("@elementor/schema");
5116
- var schema = {
5117
- elementId: import_schema4.z.string()
5118
- };
5119
- var outputSchema2 = {
5120
- properties: import_schema4.z.record(import_schema4.z.string(), import_schema4.z.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
5121
- style: import_schema4.z.record(import_schema4.z.string(), import_schema4.z.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
5122
- childElements: import_schema4.z.array(
5123
- import_schema4.z.object({
5124
- id: import_schema4.z.string(),
5125
- elementType: import_schema4.z.string(),
5126
- childElements: import_schema4.z.array(import_schema4.z.any()).describe("An array of child element IDs, when applicable, same structure recursively")
5127
- })
5128
- ).describe("An array of child element IDs, when applicable, with recursive structure")
5129
- };
5130
- var structuredElements = (element) => {
5131
- const children = element.children || [];
5132
- return children.map((child) => {
5133
- return {
5134
- id: child.id,
5135
- elementType: child.model.get("elType") || child.model.get("widgetType") || "unknown",
5136
- childElements: structuredElements(child)
5137
- };
5138
- });
5139
- };
5140
- var initGetElementConfigTool = (reg) => {
5121
+ var MCP_PROXY_URL6 = "elementor/v1/mcp-proxy";
5122
+ var initGetPageStructureTool = (reg) => {
5141
5123
  const { addTool } = reg;
5142
5124
  addTool({
5143
- name: "get-element-configuration-values",
5144
- description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
5145
- schema,
5146
- outputSchema: outputSchema2,
5147
- handler: async ({ elementId }) => {
5148
- const element = (0, import_editor_elements15.getContainer)(elementId);
5149
- if (!element) {
5150
- throw new Error(`Element with ID ${elementId} not found.`);
5151
- }
5152
- const elementType = element.model.get("widgetType") || element.model.get("elType") || "";
5153
- const widgetData = (0, import_editor_elements15.getWidgetsCache)()?.[elementType];
5154
- if (!widgetData) {
5155
- throw new Error(
5156
- `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
5157
- );
5158
- }
5159
- if (!widgetData.atomic_props_schema) {
5160
- throw new Error(
5161
- `This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${elementType}`
5162
- );
5163
- }
5164
- const elementRawSettings = element.settings;
5165
- const propSchema = (0, import_editor_elements15.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
5166
- if (!elementRawSettings || !propSchema) {
5167
- throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
5125
+ name: "get-page-structure",
5126
+ description: "Returns the Elementor element tree (widgets, containers, and nested content) for a post or page. If no postId is provided, uses the currently open document. Only works for posts saved with Elementor.",
5127
+ schema: {
5128
+ postId: import_schema4.z.number().optional().describe(
5129
+ "WordPress post ID of the Elementor document. If omitted, uses the currently open document."
5130
+ )
5131
+ },
5132
+ outputSchema: {
5133
+ elements: import_schema4.z.array(import_schema4.z.any()).describe("Root-level Elementor elements for the document.")
5134
+ },
5135
+ handler: async ({ postId }) => {
5136
+ const resolvedPostId = postId ?? (0, import_editor_documents3.getCurrentDocument)()?.id;
5137
+ if (!resolvedPostId) {
5138
+ throw new Error("No post ID provided and no active document found.");
5168
5139
  }
5169
- const propValues = {};
5170
- const stylePropValues = {};
5171
- import_editor_props8.Schema.configurableKeys(propSchema).forEach((key) => {
5172
- propValues[key] = structuredClone(elementRawSettings.get(key));
5173
- });
5174
- const elementStyles = (0, import_editor_elements15.getElementStyles)(elementId) || {};
5175
- const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
5176
- if (localStyle) {
5177
- const defaultVariant = localStyle.variants.find(
5178
- (variant) => variant.meta.breakpoint === "desktop" && !variant.meta.state
5179
- );
5180
- if (defaultVariant) {
5181
- const styleProps = defaultVariant.props || {};
5182
- Object.keys(styleProps).forEach((stylePropName) => {
5183
- if (typeof styleProps[stylePropName] !== "undefined") {
5184
- stylePropValues[stylePropName] = structuredClone(styleProps[stylePropName]);
5185
- }
5186
- });
5187
- if (defaultVariant.custom_css) {
5188
- stylePropValues.custom_css = atob(defaultVariant.custom_css.raw);
5140
+ try {
5141
+ const { data } = await (0, import_http_client8.httpService)().post(MCP_PROXY_URL6, {
5142
+ tool: "get-page-structure",
5143
+ input: {
5144
+ post_id: resolvedPostId
5189
5145
  }
5190
- }
5146
+ });
5147
+ return {
5148
+ elements: data.data.elements
5149
+ };
5150
+ } catch (error) {
5151
+ throw new Error(getMcpErrorMessage(error, "get-page-structure"));
5191
5152
  }
5192
- return {
5193
- properties: {
5194
- ...propValues
5195
- },
5196
- style: {
5197
- ...stylePropValues
5198
- },
5199
- childElements: structuredElements(element)
5200
- };
5201
5153
  }
5202
5154
  });
5203
5155
  };
5204
5156
 
5205
5157
  // src/mcp/canvas-mcp.ts
5206
5158
  var initCanvasMcp = (reg) => {
5207
- import_editor_props9.Schema.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
5159
+ import_editor_props8.Schema.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
5208
5160
  initWidgetsSchemaResource(reg);
5209
5161
  initAvailableWidgetsResource(reg);
5210
5162
  initDocumentStructureResource(reg);
@@ -5213,9 +5165,9 @@ var initCanvasMcp = (reg) => {
5213
5165
  initEditorStateResource(reg);
5214
5166
  initGeneralContextResource(reg);
5215
5167
  initBestPracticesResource(reg);
5216
- initGetElementConfigTool(reg);
5217
5168
  initConfigureElementTool(reg);
5218
5169
  initBuildCompositionTool(reg);
5170
+ initGetPageStructureTool(reg);
5219
5171
  initBreakpointsResource(reg);
5220
5172
  };
5221
5173
 
@@ -5328,7 +5280,7 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
5328
5280
  `;
5329
5281
 
5330
5282
  // src/prevent-link-in-link-commands.ts
5331
- var import_editor_elements16 = require("@elementor/editor-elements");
5283
+ var import_editor_elements15 = require("@elementor/editor-elements");
5332
5284
  var import_editor_notifications3 = require("@elementor/editor-notifications");
5333
5285
  var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
5334
5286
  var import_i18n4 = require("@wordpress/i18n");
@@ -5399,25 +5351,25 @@ function shouldBlock(sourceElements, targetElements) {
5399
5351
  return false;
5400
5352
  }
5401
5353
  const isSourceContainsAnAnchor = sourceElements.some((src) => {
5402
- return src?.id ? (0, import_editor_elements16.isElementAnchored)(src.id) || !!(0, import_editor_elements16.getAnchoredDescendantId)(src.id) : false;
5354
+ return src?.id ? (0, import_editor_elements15.isElementAnchored)(src.id) || !!(0, import_editor_elements15.getAnchoredDescendantId)(src.id) : false;
5403
5355
  });
5404
5356
  if (!isSourceContainsAnAnchor) {
5405
5357
  return false;
5406
5358
  }
5407
5359
  const isTargetContainsAnAnchor = targetElements.some((target) => {
5408
- return target?.id ? (0, import_editor_elements16.isElementAnchored)(target.id) || !!(0, import_editor_elements16.getAnchoredAncestorId)(target.id) : false;
5360
+ return target?.id ? (0, import_editor_elements15.isElementAnchored)(target.id) || !!(0, import_editor_elements15.getAnchoredAncestorId)(target.id) : false;
5409
5361
  });
5410
5362
  return isTargetContainsAnAnchor;
5411
5363
  }
5412
5364
 
5413
5365
  // src/style-commands/paste-style.ts
5414
- var import_editor_elements19 = require("@elementor/editor-elements");
5415
- var import_editor_props11 = require("@elementor/editor-props");
5366
+ var import_editor_elements18 = require("@elementor/editor-elements");
5367
+ var import_editor_props10 = require("@elementor/editor-props");
5416
5368
  var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
5417
5369
 
5418
5370
  // src/utils/command-utils.ts
5419
- var import_editor_elements17 = require("@elementor/editor-elements");
5420
- var import_editor_props10 = require("@elementor/editor-props");
5371
+ var import_editor_elements16 = require("@elementor/editor-elements");
5372
+ var import_editor_props9 = require("@elementor/editor-props");
5421
5373
  var import_i18n5 = require("@wordpress/i18n");
5422
5374
  function hasAtomicWidgets(args) {
5423
5375
  const { containers = [args.container] } = args;
@@ -5435,13 +5387,13 @@ function getClassesProp(container) {
5435
5387
  return null;
5436
5388
  }
5437
5389
  const [propKey] = Object.entries(propsSchema).find(
5438
- ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props10.CLASSES_PROP_KEY
5390
+ ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props9.CLASSES_PROP_KEY
5439
5391
  ) ?? [];
5440
5392
  return propKey ?? null;
5441
5393
  }
5442
5394
  function getContainerSchema(container) {
5443
5395
  const type = container?.model.get("widgetType") || container?.model.get("elType");
5444
- const widgetsCache = (0, import_editor_elements17.getWidgetsCache)();
5396
+ const widgetsCache = (0, import_editor_elements16.getWidgetsCache)();
5445
5397
  const elementType = widgetsCache?.[type];
5446
5398
  return elementType?.atomic_props_schema ?? null;
5447
5399
  }
@@ -5454,11 +5406,11 @@ function getClipboardElements(storageKey = "clipboard") {
5454
5406
  }
5455
5407
  }
5456
5408
  function getTitleForContainers(containers) {
5457
- return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements17.getElementLabel)(containers[0].id);
5409
+ return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements16.getElementLabel)(containers[0].id);
5458
5410
  }
5459
5411
 
5460
5412
  // src/style-commands/undoable-actions/paste-element-style.ts
5461
- var import_editor_elements18 = require("@elementor/editor-elements");
5413
+ var import_editor_elements17 = require("@elementor/editor-elements");
5462
5414
  var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
5463
5415
  var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
5464
5416
  var import_i18n6 = require("@wordpress/i18n");
@@ -5471,7 +5423,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5471
5423
  if (!classesProp) {
5472
5424
  return null;
5473
5425
  }
5474
- const originalStyles = (0, import_editor_elements18.getElementStyles)(container.id);
5426
+ const originalStyles = (0, import_editor_elements17.getElementStyles)(container.id);
5475
5427
  const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
5476
5428
  const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
5477
5429
  const revertData = {
@@ -5480,7 +5432,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5480
5432
  };
5481
5433
  if (styleId) {
5482
5434
  newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
5483
- (0, import_editor_elements18.updateElementStyle)({
5435
+ (0, import_editor_elements17.updateElementStyle)({
5484
5436
  elementId,
5485
5437
  styleId,
5486
5438
  meta,
@@ -5491,7 +5443,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5491
5443
  } else {
5492
5444
  const [firstVariant] = newStyle.variants;
5493
5445
  const additionalVariants = newStyle.variants.slice(1);
5494
- revertData.styleId = (0, import_editor_elements18.createElementStyle)({
5446
+ revertData.styleId = (0, import_editor_elements17.createElementStyle)({
5495
5447
  elementId,
5496
5448
  classesProp,
5497
5449
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -5509,7 +5461,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5509
5461
  return;
5510
5462
  }
5511
5463
  if (!revertData.originalStyle) {
5512
- (0, import_editor_elements18.deleteElementStyle)(container.id, revertData.styleId);
5464
+ (0, import_editor_elements17.deleteElementStyle)(container.id, revertData.styleId);
5513
5465
  return;
5514
5466
  }
5515
5467
  const classesProp = getClassesProp(container);
@@ -5518,7 +5470,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5518
5470
  }
5519
5471
  const [firstVariant] = revertData.originalStyle.variants;
5520
5472
  const additionalVariants = revertData.originalStyle.variants.slice(1);
5521
- (0, import_editor_elements18.createElementStyle)({
5473
+ (0, import_editor_elements17.createElementStyle)({
5522
5474
  elementId: container.id,
5523
5475
  classesProp,
5524
5476
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -5555,7 +5507,7 @@ function pasteStyles(args, pasteLocalStyle) {
5555
5507
  }
5556
5508
  const clipboardElements = getClipboardElements(storageKey);
5557
5509
  const [clipboardElement] = clipboardElements ?? [];
5558
- const clipboardContainer = (0, import_editor_elements19.getContainer)(clipboardElement.id);
5510
+ const clipboardContainer = (0, import_editor_elements18.getContainer)(clipboardElement.id);
5559
5511
  if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
5560
5512
  return;
5561
5513
  }
@@ -5574,7 +5526,7 @@ function getClassesWithoutLocalStyle(clipboardContainer, style) {
5574
5526
  if (!classesProp) {
5575
5527
  return [];
5576
5528
  }
5577
- const classesSetting = (0, import_editor_elements19.getElementSetting)(clipboardContainer.id, classesProp);
5529
+ const classesSetting = (0, import_editor_elements18.getElementSetting)(clipboardContainer.id, classesProp);
5578
5530
  return classesSetting?.value.filter((styleId) => styleId !== style?.id) ?? [];
5579
5531
  }
5580
5532
  function pasteClasses(containers, classes) {
@@ -5583,10 +5535,10 @@ function pasteClasses(containers, classes) {
5583
5535
  if (!classesProp) {
5584
5536
  return;
5585
5537
  }
5586
- const classesSetting = (0, import_editor_elements19.getElementSetting)(container.id, classesProp);
5587
- const currentClasses = import_editor_props11.classesPropTypeUtil.extract(classesSetting) ?? [];
5588
- const newClasses = import_editor_props11.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
5589
- (0, import_editor_elements19.updateElementSettings)({
5538
+ const classesSetting = (0, import_editor_elements18.getElementSetting)(container.id, classesProp);
5539
+ const currentClasses = import_editor_props10.classesPropTypeUtil.extract(classesSetting) ?? [];
5540
+ const newClasses = import_editor_props10.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
5541
+ (0, import_editor_elements18.updateElementSettings)({
5590
5542
  id: container.id,
5591
5543
  props: { [classesProp]: newClasses }
5592
5544
  });
@@ -5597,7 +5549,7 @@ function pasteClasses(containers, classes) {
5597
5549
  var import_editor_v1_adapters25 = require("@elementor/editor-v1-adapters");
5598
5550
 
5599
5551
  // src/style-commands/undoable-actions/reset-element-style.ts
5600
- var import_editor_elements20 = require("@elementor/editor-elements");
5552
+ var import_editor_elements19 = require("@elementor/editor-elements");
5601
5553
  var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
5602
5554
  var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
5603
5555
  var import_i18n7 = require("@wordpress/i18n");
@@ -5606,9 +5558,9 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
5606
5558
  do: ({ containers }) => {
5607
5559
  return containers.map((container) => {
5608
5560
  const elementId = container.model.get("id");
5609
- const containerStyles = (0, import_editor_elements20.getElementStyles)(elementId);
5561
+ const containerStyles = (0, import_editor_elements19.getElementStyles)(elementId);
5610
5562
  Object.keys(containerStyles ?? {}).forEach(
5611
- (styleId) => (0, import_editor_elements20.deleteElementStyle)(elementId, styleId)
5563
+ (styleId) => (0, import_editor_elements19.deleteElementStyle)(elementId, styleId)
5612
5564
  );
5613
5565
  return containerStyles;
5614
5566
  });
@@ -5624,7 +5576,7 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
5624
5576
  Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
5625
5577
  const [firstVariant] = style.variants;
5626
5578
  const additionalVariants = style.variants.slice(1);
5627
- (0, import_editor_elements20.createElementStyle)({
5579
+ (0, import_editor_elements19.createElementStyle)({
5628
5580
  elementId,
5629
5581
  classesProp,
5630
5582
  styleId,
@@ -5824,10 +5776,10 @@ function useEscapeOnCanvas(canvasDocument, onEscape) {
5824
5776
  }
5825
5777
 
5826
5778
  // src/utils/after-render.ts
5827
- var import_editor_elements21 = require("@elementor/editor-elements");
5779
+ var import_editor_elements20 = require("@elementor/editor-elements");
5828
5780
  function doAfterRender(elementIds, callback) {
5829
5781
  const pending = elementIds.map((elementId) => {
5830
- const view = (0, import_editor_elements21.getContainer)(elementId)?.view;
5782
+ const view = (0, import_editor_elements20.getContainer)(elementId)?.view;
5831
5783
  if (!view || !hasDoAfterRender(view)) {
5832
5784
  return void 0;
5833
5785
  }
package/dist/index.mjs CHANGED
@@ -47,13 +47,13 @@ var initWidgetsSchemaResource = (reg) => {
47
47
  if (!widgetType) {
48
48
  throw new Error("No widget type provided.");
49
49
  }
50
- const schema2 = await fetchWidgetSchema(widgetType);
50
+ const schema = await fetchWidgetSchema(widgetType);
51
51
  return {
52
52
  contents: [
53
53
  {
54
54
  uri: uri.toString(),
55
55
  mimeType: "application/json",
56
- text: JSON.stringify(schema2)
56
+ text: JSON.stringify(schema)
57
57
  }
58
58
  ]
59
59
  };
@@ -1260,10 +1260,10 @@ var getMultiPropsValue = (multiProps) => {
1260
1260
  // src/renderers/create-props-resolver.ts
1261
1261
  var TRANSFORM_DEPTH_LIMIT = 3;
1262
1262
  function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
1263
- async function resolve({ props, schema: schema2, signal, renderContext }) {
1264
- schema2 = schema2 ?? initialSchema;
1263
+ async function resolve({ props, schema, signal, renderContext }) {
1264
+ schema = schema ?? initialSchema;
1265
1265
  const promises = Promise.all(
1266
- Object.entries(schema2).map(async ([key, type]) => {
1266
+ Object.entries(schema).map(async ([key, type]) => {
1267
1267
  const value = props[key] ?? type.default;
1268
1268
  const transformed = await transform({ value, key, type, signal, renderContext });
1269
1269
  onPropResolve?.({ key, value: transformed, propValue: value, propType: type });
@@ -3922,7 +3922,7 @@ function initTabsModelExtensions() {
3922
3922
  }
3923
3923
 
3924
3924
  // src/mcp/canvas-mcp.ts
3925
- import { Schema as Schema4 } from "@elementor/editor-props";
3925
+ import { Schema as Schema3 } from "@elementor/editor-props";
3926
3926
 
3927
3927
  // src/mcp/resources/available-widgets-resource.ts
3928
3928
  import { httpService as httpService3 } from "@elementor/http-client";
@@ -4448,8 +4448,25 @@ function getElementDisplayName(container) {
4448
4448
  // src/mcp/tools/build-composition/tool.ts
4449
4449
  import { getCurrentDocument, reloadCurrentDocument } from "@elementor/editor-documents";
4450
4450
  import { getContainer as getContainer4, selectElement } from "@elementor/editor-elements";
4451
- import { AxiosError, httpService as httpService6 } from "@elementor/http-client";
4451
+ import { httpService as httpService6 } from "@elementor/http-client";
4452
4452
  import { z } from "@elementor/schema";
4453
+
4454
+ // src/mcp/utils/get-mcp-error-message.ts
4455
+ import { AxiosError } from "@elementor/http-client";
4456
+ function getMcpErrorMessage(error, toolName) {
4457
+ if (error instanceof AxiosError) {
4458
+ const data = error.response?.data;
4459
+ if (data?.message) {
4460
+ return data.code ? `${data.code}: ${data.message}` : data.message;
4461
+ }
4462
+ }
4463
+ if (error instanceof Error) {
4464
+ return error.message;
4465
+ }
4466
+ return `${toolName} failed with an unknown error.`;
4467
+ }
4468
+
4469
+ // src/mcp/tools/build-composition/tool.ts
4453
4470
  var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
4454
4471
  var initBuildCompositionTool = (reg) => {
4455
4472
  const { addTool } = reg;
@@ -4518,23 +4535,11 @@ var initBuildCompositionTool = (reg) => {
4518
4535
  warnings: data.data.warnings
4519
4536
  };
4520
4537
  } catch (error) {
4521
- throw new Error(getErrorMessage(error));
4538
+ throw new Error(getMcpErrorMessage(error, "build-composition"));
4522
4539
  }
4523
4540
  }
4524
4541
  });
4525
4542
  };
4526
- function getErrorMessage(error) {
4527
- if (error instanceof AxiosError) {
4528
- const data = error.response?.data;
4529
- if (data?.message) {
4530
- return data.code ? `${data.code}: ${data.message}` : data.message;
4531
- }
4532
- }
4533
- if (error instanceof Error) {
4534
- return error.message;
4535
- }
4536
- return "build-composition failed with an unknown error.";
4537
- }
4538
4543
 
4539
4544
  // src/mcp/tools/configure-element/tool.ts
4540
4545
  import { getContainer as getContainer5, getWidgetsCache as getWidgetsCache6 } from "@elementor/editor-elements";
@@ -4569,9 +4574,9 @@ var readStoredCustomCssText = (raw) => {
4569
4574
 
4570
4575
  // src/mcp/utils/resolve-canonical-prop-name.ts
4571
4576
  import { getWidgetsCache as getWidgetsCache4 } from "@elementor/editor-elements";
4572
- function buildAliasToCanonicalMap(schema2) {
4577
+ function buildAliasToCanonicalMap(schema) {
4573
4578
  const aliasToCanonical = {};
4574
- for (const [canonical, propType] of Object.entries(schema2)) {
4579
+ for (const [canonical, propType] of Object.entries(schema)) {
4575
4580
  const aliases = propType.meta?.aliases;
4576
4581
  if (!Array.isArray(aliases)) {
4577
4582
  continue;
@@ -4585,26 +4590,26 @@ function buildAliasToCanonicalMap(schema2) {
4585
4590
  return aliasToCanonical;
4586
4591
  }
4587
4592
  function resolveCanonicalPropName(elementType, propertyName) {
4588
- const schema2 = getWidgetsCache4()?.[elementType]?.atomic_props_schema;
4589
- if (!schema2 || schema2[propertyName]) {
4593
+ const schema = getWidgetsCache4()?.[elementType]?.atomic_props_schema;
4594
+ if (!schema || schema[propertyName]) {
4590
4595
  return propertyName;
4591
4596
  }
4592
- return buildAliasToCanonicalMap(schema2)[propertyName] ?? propertyName;
4597
+ return buildAliasToCanonicalMap(schema)[propertyName] ?? propertyName;
4593
4598
  }
4594
4599
  function resolveCanonicalPropKeys(elementType, props) {
4595
- const schema2 = getWidgetsCache4()?.[elementType]?.atomic_props_schema;
4596
- if (!schema2) {
4600
+ const schema = getWidgetsCache4()?.[elementType]?.atomic_props_schema;
4601
+ if (!schema) {
4597
4602
  return { ...props };
4598
4603
  }
4599
- const aliasToCanonical = buildAliasToCanonicalMap(schema2);
4604
+ const aliasToCanonical = buildAliasToCanonicalMap(schema);
4600
4605
  const resolved = {};
4601
4606
  for (const [key, value] of Object.entries(props)) {
4602
- if (schema2[key]) {
4607
+ if (schema[key]) {
4603
4608
  resolved[key] = value;
4604
4609
  }
4605
4610
  }
4606
4611
  for (const [key, value] of Object.entries(props)) {
4607
- if (schema2[key]) {
4612
+ if (schema[key]) {
4608
4613
  continue;
4609
4614
  }
4610
4615
  const canonical = aliasToCanonical[key];
@@ -4652,9 +4657,9 @@ var dynamicTagLLMResolver = (value) => {
4652
4657
  }
4653
4658
  };
4654
4659
  };
4655
- var buildStrictSettings = (schema2, provided) => {
4660
+ var buildStrictSettings = (schema, provided) => {
4656
4661
  const settings = {};
4657
- for (const [key, propType] of Object.entries(schema2)) {
4662
+ for (const [key, propType] of Object.entries(schema)) {
4658
4663
  if (OMITTED_DYNAMIC_SETTING_KEYS.includes(key)) {
4659
4664
  continue;
4660
4665
  }
@@ -5081,102 +5086,49 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
5081
5086
  }`;
5082
5087
  }
5083
5088
 
5084
- // src/mcp/tools/get-element-config/tool.ts
5085
- import { getContainer as getContainer6, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache7 } from "@elementor/editor-elements";
5086
- import { Schema as Schema3 } from "@elementor/editor-props";
5089
+ // src/mcp/tools/get-page-structure/tool.ts
5090
+ import { getCurrentDocument as getCurrentDocument2 } from "@elementor/editor-documents";
5091
+ import { httpService as httpService7 } from "@elementor/http-client";
5087
5092
  import { z as z3 } from "@elementor/schema";
5088
- var schema = {
5089
- elementId: z3.string()
5090
- };
5091
- var outputSchema2 = {
5092
- properties: z3.record(z3.string(), z3.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
5093
- style: z3.record(z3.string(), z3.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
5094
- childElements: z3.array(
5095
- z3.object({
5096
- id: z3.string(),
5097
- elementType: z3.string(),
5098
- childElements: z3.array(z3.any()).describe("An array of child element IDs, when applicable, same structure recursively")
5099
- })
5100
- ).describe("An array of child element IDs, when applicable, with recursive structure")
5101
- };
5102
- var structuredElements = (element) => {
5103
- const children = element.children || [];
5104
- return children.map((child) => {
5105
- return {
5106
- id: child.id,
5107
- elementType: child.model.get("elType") || child.model.get("widgetType") || "unknown",
5108
- childElements: structuredElements(child)
5109
- };
5110
- });
5111
- };
5112
- var initGetElementConfigTool = (reg) => {
5093
+ var MCP_PROXY_URL6 = "elementor/v1/mcp-proxy";
5094
+ var initGetPageStructureTool = (reg) => {
5113
5095
  const { addTool } = reg;
5114
5096
  addTool({
5115
- name: "get-element-configuration-values",
5116
- description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
5117
- schema,
5118
- outputSchema: outputSchema2,
5119
- handler: async ({ elementId }) => {
5120
- const element = getContainer6(elementId);
5121
- if (!element) {
5122
- throw new Error(`Element with ID ${elementId} not found.`);
5123
- }
5124
- const elementType = element.model.get("widgetType") || element.model.get("elType") || "";
5125
- const widgetData = getWidgetsCache7()?.[elementType];
5126
- if (!widgetData) {
5127
- throw new Error(
5128
- `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
5129
- );
5130
- }
5131
- if (!widgetData.atomic_props_schema) {
5132
- throw new Error(
5133
- `This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${elementType}`
5134
- );
5135
- }
5136
- const elementRawSettings = element.settings;
5137
- const propSchema = getWidgetsCache7()?.[elementType]?.atomic_props_schema;
5138
- if (!elementRawSettings || !propSchema) {
5139
- throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
5097
+ name: "get-page-structure",
5098
+ description: "Returns the Elementor element tree (widgets, containers, and nested content) for a post or page. If no postId is provided, uses the currently open document. Only works for posts saved with Elementor.",
5099
+ schema: {
5100
+ postId: z3.number().optional().describe(
5101
+ "WordPress post ID of the Elementor document. If omitted, uses the currently open document."
5102
+ )
5103
+ },
5104
+ outputSchema: {
5105
+ elements: z3.array(z3.any()).describe("Root-level Elementor elements for the document.")
5106
+ },
5107
+ handler: async ({ postId }) => {
5108
+ const resolvedPostId = postId ?? getCurrentDocument2()?.id;
5109
+ if (!resolvedPostId) {
5110
+ throw new Error("No post ID provided and no active document found.");
5140
5111
  }
5141
- const propValues = {};
5142
- const stylePropValues = {};
5143
- Schema3.configurableKeys(propSchema).forEach((key) => {
5144
- propValues[key] = structuredClone(elementRawSettings.get(key));
5145
- });
5146
- const elementStyles = getElementStyles2(elementId) || {};
5147
- const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
5148
- if (localStyle) {
5149
- const defaultVariant = localStyle.variants.find(
5150
- (variant) => variant.meta.breakpoint === "desktop" && !variant.meta.state
5151
- );
5152
- if (defaultVariant) {
5153
- const styleProps = defaultVariant.props || {};
5154
- Object.keys(styleProps).forEach((stylePropName) => {
5155
- if (typeof styleProps[stylePropName] !== "undefined") {
5156
- stylePropValues[stylePropName] = structuredClone(styleProps[stylePropName]);
5157
- }
5158
- });
5159
- if (defaultVariant.custom_css) {
5160
- stylePropValues.custom_css = atob(defaultVariant.custom_css.raw);
5112
+ try {
5113
+ const { data } = await httpService7().post(MCP_PROXY_URL6, {
5114
+ tool: "get-page-structure",
5115
+ input: {
5116
+ post_id: resolvedPostId
5161
5117
  }
5162
- }
5118
+ });
5119
+ return {
5120
+ elements: data.data.elements
5121
+ };
5122
+ } catch (error) {
5123
+ throw new Error(getMcpErrorMessage(error, "get-page-structure"));
5163
5124
  }
5164
- return {
5165
- properties: {
5166
- ...propValues
5167
- },
5168
- style: {
5169
- ...stylePropValues
5170
- },
5171
- childElements: structuredElements(element)
5172
- };
5173
5125
  }
5174
5126
  });
5175
5127
  };
5176
5128
 
5177
5129
  // src/mcp/canvas-mcp.ts
5178
5130
  var initCanvasMcp = (reg) => {
5179
- Schema4.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
5131
+ Schema3.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
5180
5132
  initWidgetsSchemaResource(reg);
5181
5133
  initAvailableWidgetsResource(reg);
5182
5134
  initDocumentStructureResource(reg);
@@ -5185,9 +5137,9 @@ var initCanvasMcp = (reg) => {
5185
5137
  initEditorStateResource(reg);
5186
5138
  initGeneralContextResource(reg);
5187
5139
  initBestPracticesResource(reg);
5188
- initGetElementConfigTool(reg);
5189
5140
  initConfigureElementTool(reg);
5190
5141
  initBuildCompositionTool(reg);
5142
+ initGetPageStructureTool(reg);
5191
5143
  initBreakpointsResource(reg);
5192
5144
  };
5193
5145
 
@@ -5387,7 +5339,7 @@ function shouldBlock(sourceElements, targetElements) {
5387
5339
  }
5388
5340
 
5389
5341
  // src/style-commands/paste-style.ts
5390
- import { getContainer as getContainer7, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
5342
+ import { getContainer as getContainer6, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
5391
5343
  import { classesPropTypeUtil } from "@elementor/editor-props";
5392
5344
  import {
5393
5345
  __privateListenTo as listenTo5,
@@ -5396,7 +5348,7 @@ import {
5396
5348
  } from "@elementor/editor-v1-adapters";
5397
5349
 
5398
5350
  // src/utils/command-utils.ts
5399
- import { getElementLabel as getElementLabel2, getWidgetsCache as getWidgetsCache8 } from "@elementor/editor-elements";
5351
+ import { getElementLabel as getElementLabel2, getWidgetsCache as getWidgetsCache7 } from "@elementor/editor-elements";
5400
5352
  import { CLASSES_PROP_KEY } from "@elementor/editor-props";
5401
5353
  import { __ as __5 } from "@wordpress/i18n";
5402
5354
  function hasAtomicWidgets(args) {
@@ -5421,7 +5373,7 @@ function getClassesProp(container) {
5421
5373
  }
5422
5374
  function getContainerSchema(container) {
5423
5375
  const type = container?.model.get("widgetType") || container?.model.get("elType");
5424
- const widgetsCache = getWidgetsCache8();
5376
+ const widgetsCache = getWidgetsCache7();
5425
5377
  const elementType = widgetsCache?.[type];
5426
5378
  return elementType?.atomic_props_schema ?? null;
5427
5379
  }
@@ -5441,7 +5393,7 @@ function getTitleForContainers(containers) {
5441
5393
  import {
5442
5394
  createElementStyle as createElementStyle2,
5443
5395
  deleteElementStyle,
5444
- getElementStyles as getElementStyles3,
5396
+ getElementStyles as getElementStyles2,
5445
5397
  updateElementStyle as updateElementStyle2
5446
5398
  } from "@elementor/editor-elements";
5447
5399
  import { ELEMENTS_STYLES_RESERVED_LABEL } from "@elementor/editor-styles-repository";
@@ -5456,7 +5408,7 @@ var undoablePasteElementStyle = () => undoable2(
5456
5408
  if (!classesProp) {
5457
5409
  return null;
5458
5410
  }
5459
- const originalStyles = getElementStyles3(container.id);
5411
+ const originalStyles = getElementStyles2(container.id);
5460
5412
  const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
5461
5413
  const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
5462
5414
  const revertData = {
@@ -5540,7 +5492,7 @@ function pasteStyles(args, pasteLocalStyle) {
5540
5492
  }
5541
5493
  const clipboardElements = getClipboardElements(storageKey);
5542
5494
  const [clipboardElement] = clipboardElements ?? [];
5543
- const clipboardContainer = getContainer7(clipboardElement.id);
5495
+ const clipboardContainer = getContainer6(clipboardElement.id);
5544
5496
  if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
5545
5497
  return;
5546
5498
  }
@@ -5586,7 +5538,7 @@ import {
5586
5538
  } from "@elementor/editor-v1-adapters";
5587
5539
 
5588
5540
  // src/style-commands/undoable-actions/reset-element-style.ts
5589
- import { createElementStyle as createElementStyle3, deleteElementStyle as deleteElementStyle2, getElementStyles as getElementStyles4 } from "@elementor/editor-elements";
5541
+ import { createElementStyle as createElementStyle3, deleteElementStyle as deleteElementStyle2, getElementStyles as getElementStyles3 } from "@elementor/editor-elements";
5590
5542
  import { ELEMENTS_STYLES_RESERVED_LABEL as ELEMENTS_STYLES_RESERVED_LABEL2 } from "@elementor/editor-styles-repository";
5591
5543
  import { undoable as undoable3 } from "@elementor/editor-v1-adapters";
5592
5544
  import { __ as __7 } from "@wordpress/i18n";
@@ -5595,7 +5547,7 @@ var undoableResetElementStyle = () => undoable3(
5595
5547
  do: ({ containers }) => {
5596
5548
  return containers.map((container) => {
5597
5549
  const elementId = container.model.get("id");
5598
- const containerStyles = getElementStyles4(elementId);
5550
+ const containerStyles = getElementStyles3(elementId);
5599
5551
  Object.keys(containerStyles ?? {}).forEach(
5600
5552
  (styleId) => deleteElementStyle2(elementId, styleId)
5601
5553
  );
@@ -5817,10 +5769,10 @@ function useEscapeOnCanvas(canvasDocument, onEscape) {
5817
5769
  }
5818
5770
 
5819
5771
  // src/utils/after-render.ts
5820
- import { getContainer as getContainer8 } from "@elementor/editor-elements";
5772
+ import { getContainer as getContainer7 } from "@elementor/editor-elements";
5821
5773
  function doAfterRender(elementIds, callback) {
5822
5774
  const pending = elementIds.map((elementId) => {
5823
- const view = getContainer8(elementId)?.view;
5775
+ const view = getContainer7(elementId)?.view;
5824
5776
  if (!view || !hasDoAfterRender(view)) {
5825
5777
  return void 0;
5826
5778
  }
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-1001",
4
+ "version": "4.3.0-1003",
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-1001",
41
- "@elementor/editor-controls": "4.3.0-1001",
42
- "@elementor/editor-documents": "4.3.0-1001",
43
- "@elementor/editor-elements": "4.3.0-1001",
44
- "@elementor/editor-interactions": "4.3.0-1001",
45
- "@elementor/editor-mcp": "4.3.0-1001",
46
- "@elementor/editor-notifications": "4.3.0-1001",
47
- "@elementor/editor-props": "4.3.0-1001",
48
- "@elementor/editor-responsive": "4.3.0-1001",
49
- "@elementor/editor-styles": "4.3.0-1001",
50
- "@elementor/editor-styles-repository": "4.3.0-1001",
51
- "@elementor/editor-ui": "4.3.0-1001",
52
- "@elementor/editor-v1-adapters": "4.3.0-1001",
53
- "@elementor/events": "4.3.0-1001",
54
- "@elementor/http-client": "4.3.0-1001",
55
- "@elementor/schema": "4.3.0-1001",
56
- "@elementor/twing": "4.3.0-1001",
40
+ "@elementor/editor": "4.3.0-1003",
41
+ "@elementor/editor-controls": "4.3.0-1003",
42
+ "@elementor/editor-documents": "4.3.0-1003",
43
+ "@elementor/editor-elements": "4.3.0-1003",
44
+ "@elementor/editor-interactions": "4.3.0-1003",
45
+ "@elementor/editor-mcp": "4.3.0-1003",
46
+ "@elementor/editor-notifications": "4.3.0-1003",
47
+ "@elementor/editor-props": "4.3.0-1003",
48
+ "@elementor/editor-responsive": "4.3.0-1003",
49
+ "@elementor/editor-styles": "4.3.0-1003",
50
+ "@elementor/editor-styles-repository": "4.3.0-1003",
51
+ "@elementor/editor-ui": "4.3.0-1003",
52
+ "@elementor/editor-v1-adapters": "4.3.0-1003",
53
+ "@elementor/events": "4.3.0-1003",
54
+ "@elementor/http-client": "4.3.0-1003",
55
+ "@elementor/schema": "4.3.0-1003",
56
+ "@elementor/twing": "4.3.0-1003",
57
57
  "@elementor/ui": "1.37.5",
58
- "@elementor/utils": "4.3.0-1001",
59
- "@elementor/wp-media": "4.3.0-1001",
58
+ "@elementor/utils": "4.3.0-1003",
59
+ "@elementor/wp-media": "4.3.0-1003",
60
60
  "@floating-ui/react": "^0.27.5",
61
61
  "@wordpress/i18n": "^5.13.0",
62
62
  "dompurify": "^3.2.6"
@@ -12,7 +12,7 @@ import { initSelectedElementResource } from './resources/selected-element-resour
12
12
  import { initWidgetsSchemaResource } from './resources/widgets-schema-resource';
13
13
  import { initBuildCompositionTool } from './tools/build-composition/tool';
14
14
  import { initConfigureElementTool } from './tools/configure-element/tool';
15
- import { initGetElementConfigTool } from './tools/get-element-config/tool';
15
+ import { initGetPageStructureTool } from './tools/get-page-structure/tool';
16
16
  import { getDynamicTagNamesByCategories } from './utils/resolve-dynamic-tag';
17
17
 
18
18
  export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
@@ -28,8 +28,8 @@ export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
28
28
  initEditorStateResource( reg );
29
29
  initGeneralContextResource( reg );
30
30
  initBestPracticesResource( reg );
31
- initGetElementConfigTool( reg );
32
31
  initConfigureElementTool( reg );
33
32
  initBuildCompositionTool( reg );
33
+ initGetPageStructureTool( reg );
34
34
  initBreakpointsResource( reg );
35
35
  };
@@ -1,9 +1,11 @@
1
1
  import { getCurrentDocument, reloadCurrentDocument } from '@elementor/editor-documents';
2
2
  import { getContainer, selectElement } from '@elementor/editor-elements';
3
3
  import { type MCPRegistryEntry } from '@elementor/editor-mcp';
4
- import { AxiosError, type HttpResponse, httpService } from '@elementor/http-client';
4
+ import { type HttpResponse, httpService } from '@elementor/http-client';
5
5
  import { z } from '@elementor/schema';
6
6
 
7
+ import { getMcpErrorMessage } from '../../utils/get-mcp-error-message';
8
+
7
9
  const MCP_PROXY_URL = 'elementor/v1/mcp-proxy';
8
10
 
9
11
  type BuildCompositionResponse = {
@@ -111,23 +113,8 @@ export const initBuildCompositionTool = ( reg: MCPRegistryEntry ) => {
111
113
  warnings: data.data.warnings,
112
114
  };
113
115
  } catch ( error ) {
114
- throw new Error( getErrorMessage( error ) );
116
+ throw new Error( getMcpErrorMessage( error, 'build-composition' ) );
115
117
  }
116
118
  },
117
119
  } );
118
120
  };
119
-
120
- function getErrorMessage( error: unknown ): string {
121
- if ( error instanceof AxiosError ) {
122
- const data = error.response?.data as { message?: string; code?: string } | undefined;
123
- if ( data?.message ) {
124
- return data.code ? `${ data.code }: ${ data.message }` : data.message;
125
- }
126
- }
127
-
128
- if ( error instanceof Error ) {
129
- return error.message;
130
- }
131
-
132
- return 'build-composition failed with an unknown error.';
133
- }
@@ -0,0 +1,56 @@
1
+ import { getCurrentDocument } from '@elementor/editor-documents';
2
+ import { type MCPRegistryEntry } from '@elementor/editor-mcp';
3
+ import { type HttpResponse, httpService } from '@elementor/http-client';
4
+ import { z } from '@elementor/schema';
5
+
6
+ import { getMcpErrorMessage } from '../../utils/get-mcp-error-message';
7
+
8
+ const MCP_PROXY_URL = 'elementor/v1/mcp-proxy';
9
+
10
+ type GetPageStructureResponse = {
11
+ elements: Array< Record< string, unknown > >;
12
+ };
13
+
14
+ export const initGetPageStructureTool = ( reg: MCPRegistryEntry ) => {
15
+ const { addTool } = reg;
16
+
17
+ addTool( {
18
+ name: 'get-page-structure',
19
+ description:
20
+ 'Returns the Elementor element tree (widgets, containers, and nested content) for a post or page. ' +
21
+ 'If no postId is provided, uses the currently open document. Only works for posts saved with Elementor.',
22
+ schema: {
23
+ postId: z
24
+ .number()
25
+ .optional()
26
+ .describe(
27
+ 'WordPress post ID of the Elementor document. If omitted, uses the currently open document.'
28
+ ),
29
+ },
30
+ outputSchema: {
31
+ elements: z.array( z.any() ).describe( 'Root-level Elementor elements for the document.' ),
32
+ },
33
+ handler: async ( { postId } ) => {
34
+ const resolvedPostId = postId ?? getCurrentDocument()?.id;
35
+
36
+ if ( ! resolvedPostId ) {
37
+ throw new Error( 'No post ID provided and no active document found.' );
38
+ }
39
+
40
+ try {
41
+ const { data } = await httpService().post< HttpResponse< GetPageStructureResponse > >( MCP_PROXY_URL, {
42
+ tool: 'get-page-structure',
43
+ input: {
44
+ post_id: resolvedPostId,
45
+ },
46
+ } );
47
+
48
+ return {
49
+ elements: data.data.elements,
50
+ };
51
+ } catch ( error ) {
52
+ throw new Error( getMcpErrorMessage( error, 'get-page-structure' ) );
53
+ }
54
+ },
55
+ } );
56
+ };
@@ -0,0 +1,16 @@
1
+ import { AxiosError } from '@elementor/http-client';
2
+
3
+ export function getMcpErrorMessage( error: unknown, toolName: string ): string {
4
+ if ( error instanceof AxiosError ) {
5
+ const data = error.response?.data as { message?: string; code?: string } | undefined;
6
+ if ( data?.message ) {
7
+ return data.code ? `${ data.code }: ${ data.message }` : data.message;
8
+ }
9
+ }
10
+
11
+ if ( error instanceof Error ) {
12
+ return error.message;
13
+ }
14
+
15
+ return `${ toolName } failed with an unknown error.`;
16
+ }
@@ -1,114 +0,0 @@
1
- import { getContainer, getElementStyles, getWidgetsCache, type V1Element } from '@elementor/editor-elements';
2
- import { type MCPRegistryEntry } from '@elementor/editor-mcp';
3
- import { type PropValue, Schema } from '@elementor/editor-props';
4
- import { z } from '@elementor/schema';
5
-
6
- const schema = {
7
- elementId: z.string(),
8
- };
9
-
10
- const outputSchema = {
11
- properties: z
12
- .record( z.string(), z.any() )
13
- .describe( 'A record mapping PropTypes to their corresponding PropValues' ),
14
- style: z
15
- .record( z.string(), z.any() )
16
- .describe( 'A record mapping StyleSchema properties to their corresponding PropValues' ),
17
- childElements: z
18
- .array(
19
- z.object( {
20
- id: z.string(),
21
- elementType: z.string(),
22
- childElements: z
23
- .array( z.any() )
24
- .describe( 'An array of child element IDs, when applicable, same structure recursively' ),
25
- } )
26
- )
27
- .describe( 'An array of child element IDs, when applicable, with recursive structure' ),
28
- };
29
- type ElementStructure = {
30
- id: string;
31
- elementType: string;
32
- childElements: ElementStructure[];
33
- };
34
- const structuredElements = ( element: V1Element ): ElementStructure[] => {
35
- const children = element.children || [];
36
- return children.map( ( child ) => {
37
- return {
38
- id: child.id,
39
- elementType: child.model.get( 'elType' ) || child.model.get( 'widgetType' ) || 'unknown',
40
- childElements: structuredElements( child ),
41
- };
42
- } );
43
- };
44
-
45
- export const initGetElementConfigTool = ( reg: MCPRegistryEntry ) => {
46
- const { addTool } = reg;
47
-
48
- addTool( {
49
- name: 'get-element-configuration-values',
50
- description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
51
- schema,
52
- outputSchema,
53
- handler: async ( { elementId } ) => {
54
- const element = getContainer( elementId );
55
- if ( ! element ) {
56
- throw new Error( `Element with ID ${ elementId } not found.` );
57
- }
58
- const elementType = element.model.get( 'widgetType' ) || element.model.get( 'elType' ) || '';
59
- const widgetData = getWidgetsCache()?.[ elementType ];
60
- if ( ! widgetData ) {
61
- throw new Error(
62
- `Unknown element type: ${ elementType }. Check the available-widgets resource for valid types.`
63
- );
64
- }
65
- if ( ! widgetData.atomic_props_schema ) {
66
- throw new Error(
67
- `This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${ elementType }`
68
- );
69
- }
70
- const elementRawSettings = element.settings;
71
- const propSchema = getWidgetsCache()?.[ elementType ]?.atomic_props_schema;
72
-
73
- if ( ! elementRawSettings || ! propSchema ) {
74
- throw new Error( `No settings or prop schema found for element ID: ${ elementId }` );
75
- }
76
-
77
- const propValues: Record< string, PropValue > = {};
78
- const stylePropValues: Record< string, PropValue > = {};
79
-
80
- Schema.configurableKeys( propSchema ).forEach( ( key ) => {
81
- propValues[ key ] = structuredClone( elementRawSettings.get( key ) );
82
- } );
83
- const elementStyles = getElementStyles( elementId ) || {};
84
- const localStyle = Object.values( elementStyles ).find( ( style ) => style.label === 'local' );
85
-
86
- if ( localStyle ) {
87
- const defaultVariant = localStyle.variants.find(
88
- ( variant ) => variant.meta.breakpoint === 'desktop' && ! variant.meta.state
89
- );
90
- if ( defaultVariant ) {
91
- const styleProps = defaultVariant.props || {};
92
- Object.keys( styleProps ).forEach( ( stylePropName ) => {
93
- if ( typeof styleProps[ stylePropName ] !== 'undefined' ) {
94
- stylePropValues[ stylePropName ] = structuredClone( styleProps[ stylePropName ] );
95
- }
96
- } );
97
- if ( defaultVariant.custom_css ) {
98
- stylePropValues.custom_css = atob( defaultVariant.custom_css.raw );
99
- }
100
- }
101
- }
102
-
103
- return {
104
- properties: {
105
- ...propValues,
106
- },
107
- style: {
108
- ...stylePropValues,
109
- },
110
- childElements: structuredElements( element ),
111
- };
112
- },
113
- } );
114
- };