# Royal MCP’s Elementor Tools — Reference

> Reference for Royal MCP's 11 Elementor tools: clone pages, replace text and images, read outlines and widget settings, manage templates and add widgets.

- Canonical: <https://royalplugins.com/support/royal-mcp/elementor-tools/>
- Last updated: 2026-09-21
- HTML version: <https://royalplugins.com/support/royal-mcp/elementor-tools/>

---

Royal MCP ships **eleven Elementor tools** today. This page is the per-tool reference: what each one does, what arguments it takes, what to ask Claude, and the gotchas worth knowing. The design philosophy behind the deliberately narrow tool surface is on the [blog](https://royalplugins.com/blog/editing-elementor-with-claude-four-workflows/); this page is the how. For the tested workflow patterns that compose these tools into safe sequences (clone-and-customize, bulk find-and-replace, template application), load our [Elementor Claude Skill](https://royalplugins.com/skills/elementor-claude-skill/).

### Prerequisites

Royal MCP is installed and connected to your AI client of choice ([Claude](https://royalplugins.com/support/royal-mcp/connecting-to-claude/), [ChatGPT](https://royalplugins.com/support/royal-mcp/connecting-to-chatgpt/), or another MCP-capable tool). Elementor (free or Pro) is active on your site. When both are present, all eleven Elementor tools auto-register — no configuration.

## Why the Tool Set Stays Narrow

The design commitment: **never generate Elementor JSON from scratch — always work from an existing-known-good source.** Every tool below either reads a page, clones a page, or modifies content inside a page that already exists. None of them try to invent Elementor’s widget schemas from a prompt. That commitment is what keeps the tool surface deliberately narrow.

Atomic widgets (Elementor 4.0+ Editor V4 elements) pass through opaquely on clones. We don’t decode atomic schemas because Elementor itself may shift them — and shift them they have (the 4.1 Classes API refactor broke direct `_elementor_data` writes in third-party tools that decode). Working from a known-good source survives that.

## Tools at a Glance

| Tool | Purpose | Best used when |
| --- | --- | --- |
| `elementor_clone_page` | Duplicate a page with fresh element IDs | Building a variant of an existing page |
| `elementor_replace_text` | Bulk text substitution across widget settings | Retargeting a cloned page (city, brand, product) |
| `elementor_replace_image` | Swap image URLs across image-bearing widgets | Retargeting hero, gallery, background images on a clone |
| `elementor_get_page_outline` | Compact structural summary of a page (~2KB) | Letting Claude reason over a page’s shape before editing |
| `elementor_get_widget_settings` | Read full settings JSON for a single widget by element ID | Inspecting an element before a targeted modification |
| `elementor_list_local_templates` | Enumerate saved templates from the Library | Finding an existing template to import into a page |
| `elementor_import_template` | Create a new template from a JSON payload | Storing a design in the Library for reuse |
| `elementor_add_widget` | Insert a new widget or container into a page | Adding a specific widget to a specific spot |
| `elementor_apply_template_to_page` | Insert an existing library template onto a target page | Reusing a saved section or layout on another page in one call |
| `elementor_rebuild_post_content` | Rebuild a page’s `post_content` from its Elementor tree | Restoring WP search / RSS visibility for a page with empty `post_content` |
| `elementor_rebuild_post_content_bulk` | Batch-rebuild `post_content` for every affected page | Sitewide fix for empty `post_content` after past clone operations |

## The Eleven Tools

### elementor\_clone\_page

Duplicate an existing Elementor page or post as a new draft, with all element IDs regenerated.

#### What it does

Reads the full `_elementor_data` tree from the source post, deep-clones the JSON, regenerates every element’s `id` so the new page opens cleanly in the Elementor editor (Elementor requires unique IDs per document; collisions break the editor). Preserves the Container model, legacy section/column trees, and atomic widgets as-is. Returns the new post ID.

#### Arguments

- `source_post_id` *(integer, required)* — post or page ID to clone from. Must have Elementor data.
- `new_title` *(string, required)* — title for the new post.
- `new_status` *(string, optional)* — one of `draft`, `publish`, `private`, `pending`. Defaults to `draft`.

#### Example prompt

“Clone the ‘New York Services’ page as a new draft titled ‘Los Angeles Services’.”

#### Returns

New post ID + edit URL. Draft by default so you can review before publishing.

#### Gotchas

- Featured images copy over; large numbers of unique element IDs are regenerated in memory (fine for any real-world page but not tuned for pathological ID counts).
- Atomic widgets pass through opaquely — their internal IDs are regenerated at the outer element level.

### elementor\_replace\_text

Bulk text substitution across every text-bearing widget on a page.

#### What it does

Walks the `_elementor_data` tree and replaces every occurrence of a target string inside known text fields — heading title, text-editor content, button text, image caption/alt, testimonial content, icon-list items, tab labels, accordion titles, call-to-action text, and more. Atomic widgets are skipped (opaque passthrough by design). Case-sensitive by default.

#### Arguments

- `post_id` *(integer, required)*
- `find` *(string, required)* — text to search for.
- `replace` *(string, required)* — text to substitute.
- `case_insensitive` *(boolean, optional)* — defaults to `false`.

#### Example prompt

“On the Los Angeles Services page draft, replace ‘New York’ with ‘Los Angeles’ everywhere.”

#### Returns

Count of replacements made, so Claude knows how much actually changed.

#### Gotchas

- Substring-based, not word-boundary-aware. If “New York” appears inside a longer phrase you don’t want changed, be more specific with the target string.
- Only rewrites text-field values. Doesn’t touch link URLs, image URLs (that’s `elementor_replace_image`), or CSS.

### elementor\_replace\_image

Swap image URLs across every image-bearing widget on a page.

#### What it does

Walks the page and rewrites matching image URLs in the image widget, image-box, background image (on sections, columns, and containers), gallery items, and other image-carrying widgets. Optionally also remaps the corresponding WordPress attachment ID so the Media Library reference stays clean.

#### Arguments

- `post_id` *(integer, required)*
- `old_url` *(string, required)* — URL to find.
- `new_url` *(string, required)* — URL to replace with.
- `old_id` *(integer, optional)* — old WP attachment ID.
- `new_id` *(integer, optional)* — new WP attachment ID. Passing both `old_id` and `new_id` keeps the attachment reference consistent.

#### Example prompt

“On the LA Services page draft, swap the hero image from `hero-nyc.jpg` to the LA skyline photo I uploaded on Tuesday.”

#### Returns

Count of URL replacements. If you passed attachment IDs, the attachment reference count is included too.

#### Gotchas

- Only swaps *image* URLs. Doesn’t touch `<a href>` destinations or video URLs.
- WebP conversions and Elementor’s image size variants aren’t automatically regenerated — if the new image needs different derivative sizes, an image-optimizer or force-regen may still be worth running.

### elementor\_get\_page\_outline

A ~2KB structural summary of a page for AI reasoning.

#### What it does

Returns a simplified outline — section/container hierarchy, widget types per slot, and short text snippets pulled from text-bearing widgets. Small enough for an AI to reason over a full page without consuming the entire `_elementor_data` budget. Useful *before* calling clone or replace to understand what you’re about to touch.

#### Arguments

- `post_id` *(integer, required)*
- No filters — the outline is intentionally compact.

#### Example prompt

“Show me the outline of the New York Services page so I can decide which sections to change before cloning.”

#### Returns

Nested JSON: sections/containers with type, layout, child widget types, and short text snippets.

#### Gotchas

- Not a full serialization. If you need every setting on every widget, this isn’t the tool — use it as a map, not the territory.
- Atomic widgets show as opaque nodes (widget type only, no snippet).

### elementor\_get\_widget\_settings

Read the full settings object for a single Elementor widget, container, section, or column by element ID.

#### What it does

Returns the complete raw settings JSON for any element on an Elementor page — the same settings object Elementor’s editor stores in `_elementor_data`. Complements `elementor_get_page_outline` (which returns a compact structural summary): use the outline to find the element ID you want, then read this to see exactly what that widget contains before modifying it. Works for widgets, containers, sections, and columns.

#### Arguments

- `post_id` *(integer, required)* — the Elementor-edited post or page.
- `element_id` *(string, required)* — the element ID (from `elementor_get_page_outline` output).

#### Example prompt

“Read the settings for element `abc12345` on the Home page so I can see exactly what the hero heading contains before I change it.”

#### Returns

The element’s full settings JSON, its widget type (or container / section / column type), and its position in the page tree. Ideal precursor to a targeted write via `elementor_replace_text`, `elementor_replace_image`, or a raw `_elementor_data` modification.

#### Gotchas

- Cap-checked via `read_post` on the target.
- Returns raw settings JSON with no format normalization — you get exactly what Elementor stores, including any nested repeater rows or dynamic-tag markers.
- Atomic widgets (Editor V4, prefixed `a-` or `e-`) return their opaque settings blob unchanged — we don’t decode atomic schemas.

### elementor\_list\_local\_templates

Enumerate saved templates from the Elementor Library.

#### What it does

Lists entries from the `elementor_library` custom post type — the Elementor Template Library. Returns id, name, type, and last-modified date for each. Filter by type if you’re looking for something specific.

#### Arguments

- `type` *(string, optional)* — filter: `page`, `section`, `widget`, `popup`, `header`, `footer`, `single`, `archive`.
- `limit` *(integer, optional)* — max templates to return. Defaults to 50.

#### Example prompt

“List my saved section templates so I can pick one to import.”

#### Returns

Array of templates with `id`, `name`, `type`, and `date_modified`.

#### Gotchas

- Returns metadata only, not the template payload. To use a template, call `elementor_import_template` with the exported JSON — the Library entries here are references you can inspect in the Elementor editor.

### elementor\_import\_template

Create a new template in the Elementor Library from a JSON payload.

#### What it does

Accepts the JSON shape the Elementor editor exports (an array of section/container elements), validates the top-level structure, and stores it as `_elementor_data` on a new post in the `elementor_library` CPT. Returns the new template post ID.

#### Arguments

- `title` *(string, required)* — template name.
- `template_type` *(string, optional)* — `page`, `section`, `widget`, `popup`, `header`, `footer`, `single`, or `archive`. Defaults to `page`.
- `template_json` *(string, required)* — JSON-encoded array of Elementor elements (the export shape).

#### Example prompt

“Save this Elementor JSON I exported as a section template called ‘Pricing Grid v2’.”

#### Returns

New template post ID. Templates land in the Library and are usable from the Elementor editor immediately.

#### Gotchas

- Top-level shape validation only — malformed nested settings will still store but may produce editor warnings.
- Element IDs from the source JSON are preserved; if you’re copying between sites, that’s fine (templates live in their own namespace).

### elementor\_add\_widget

Add a new widget or container to an existing Elementor page.

#### What it does

Dual-surface tool. The **curated** path takes high-frequency widget types (container, heading, text-editor, button, image, image-box, icon-box, icon-list, video, divider, spacer) with flat parameters — the tool expands them into Elementor’s canonical settings object internally, saving tokens on the AI side. The **raw** path takes any widget type plus a full settings object for widgets outside the curated list. Container widgets can include children inline in a single call. Atomic widgets (Editor V4, prefixed `a-` or `e-`) pass through opaquely on the raw path.

#### Common arguments

- `post_id` *(integer, required)* — target post or page. Must be Elementor-edited.
- `widget_type` *(string, required)* — Elementor widget slug (e.g. `heading`, `button`, `html`), or `container` for a Flexbox container.
- `parent_id` *(string, optional)* — element ID to insert under. Must be a container, section, or column. Omit to append at document top level.
- `position` *(integer, optional)* — zero-indexed position within parent. Omit to append at end.

#### Curated shortcut arguments (used per widget\_type)

- **container:** `flex_direction` (`row`/`column`), `content_width` (`boxed`/`full`), `children` (array of inline child definitions).
- **heading:** `title`, `header_size` (h1–h6, div, span, p; default h2).
- **text-editor:** `editor` (HTML content).
- **button:** `text`, `link_url`, `link_target` (`_blank`/`_self`).
- **image / image-box:** `image_url`, `image_alt`, `link_url`, `link_target`.
- …plus curated params for icon-box, icon-list, video, divider, spacer.

#### Raw fallback

For any widget type outside the curated list, supply `settings` as a full Elementor settings object. When `settings` is provided, raw wins — curated params are ignored.

#### Example prompt (curated)

“Add an H2 heading ‘Ready to Get Started?’ at the bottom of the LA Services page, then add a button below it saying ‘Book a Call’ linking to `/contact/`.”

#### Returns

New element ID, parent context, and an edit URL you can jump straight to in Elementor.

#### Gotchas

- Cap-checked via `edit_post` on the target post.
- Elementor’s own core MCP module (out of experimental as of WordCamp US 2026, Aug 26) is building a `Create_Element_Ability` that will cover this same primitive layer inside Elementor itself. We ship `elementor_add_widget` because it’s genuinely useful today; the tools that don’t overlap with what Elementor’s core module ships — clone, replace, template ops — are the durable ones. See [Editing Elementor with Claude](https://royalplugins.com/blog/editing-elementor-with-claude-four-workflows/) for the full context.

### elementor\_apply\_template\_to\_page

Insert an existing library template onto a target page in one call.

#### What it does

Bridges `elementor_list_local_templates` (enumerate) and the raw `elementor_add_widget` primitive: pass a template ID and a target page, and the template’s sections drop straight onto the page. Same two-click workflow Elementor’s editor exposes, exposed as one MCP call. Element IDs are regenerated on insertion, so re-applying the same template multiple times never collides.

#### Arguments

- `template_id` *(integer, required)* — template post ID from `elementor_list_local_templates` (must be an `elementor_library` CPT entry).
- `target_post_id` *(integer, required)* — page or post to insert into. Must be Elementor-edited (has `_elementor_data`) or completely empty (will be seeded).
- `position` *(string, optional)* — `top`, `bottom`, or `after_element`. Defaults to `bottom`.
- `after_element_id` *(string, optional)* — required when `position="after_element"`. Element ID (from `elementor_get_page_outline`) to insert immediately after.

#### Example prompt

“Apply the ‘Testimonials Section’ template to the LA Services page after the pricing section.”

#### Returns

List of inserted element IDs + the target’s edit URL and view URL. Emits a 72-hour undo token that restores the target page’s prior `_elementor_data` if you need to reverse the insertion.

#### Gotchas

- Cap-checked as `edit_post` on `target_post_id` plus `read_post` on `template_id`.
- Templates apply as-is; if the template was designed for a different brand or layout width, the insertion may need visual review before publish.

### elementor\_rebuild\_post\_content

Rebuild a page’s `post_content` from its Elementor tree.

#### What it does

Regenerates `post_content` from `_elementor_data` using Elementor’s own render pipeline. Fixes pages where `post_content` is empty — which breaks WordPress core search, RSS excerpts, SEO auto-descriptions, and read-after-write verification. Idempotent by default: skips pages that already have populated `post_content` unless `force=true`.

#### Arguments

- `post_id` *(integer, required)* — post or page ID to rebuild.
- `force` *(boolean, optional)* — defaults to `false`. When `true`, rebuild even if `post_content` is already non-empty (destructive — replaces existing content).

#### Example prompt

“Rebuild the post\_content on the /pricing page — WP search can’t find anything on it.”

#### Returns

`action=repaired` with `prior_length` + `new_length`, or `action=skipped_populated` / `no_elementor_data` depending on the page’s state. Emits a 72-hour undo token capturing the prior `post_content`.

#### Gotchas

- Only rewrites `post_content`. Doesn’t touch `_elementor_data`, meta, or any other post field.
- Use `elementor_rebuild_post_content_bulk` for sitewide sweeps — single-page calls are for spot repairs.

### elementor\_rebuild\_post\_content\_bulk

Batch-rebuild `post_content` across every affected page in one pass.

#### What it does

Scans every post with `_elementor_data` + empty `post_content` and rebuilds them in batch. Fixes bulk SEO / search damage from prior clone operations that shipped without populated `post_content`. Supports a `dry_run` preview mode that reports the count + first 20 candidate post IDs without writing anything.

#### Arguments

- `dry_run` *(boolean, optional)* — defaults to `false`. When `true`, report what would be repaired without writing.
- `limit` *(integer, optional)* — max posts to repair per call. Default 50, max 200.
- `post_type` *(string, optional)* — filter to a single post type (e.g. `page` or `post`). Default is all post types.

#### Example prompt (dry run first)

“Dry-run a bulk post\_content rebuild across all pages and show me the count.”

#### Returns

Count of pages repaired (or candidate count in dry-run mode) plus the list of affected post IDs.

#### Gotchas

- **No undo tokens emitted.** Bulk rebuild of empty content is generally not something users want to reverse — take a [SiteVault](https://royalplugins.com/sitevault/) snapshot beforehand if you need reversal capability.
- Cap-checked as `edit_posts`.
- Always dry-run first on a large site to see the candidate count before committing.

## Why This Design Survives Elementor Version Boundaries

Elementor 4.1 shipped a Classes API refactor that broke direct `_elementor_data` write paths for third-party tools decoding widget schemas. The tools that survived that refactor were the ones treating existing pages as opaque known-good sources. That’s the design commitment carried through this whole toolset: read a source, clone it, modify content inside it — never invent structure from a prompt. When Elementor 4.2 or 5.0 shifts the atomic model again (they will), this approach keeps working.

## Related

- [Editing Elementor with Claude — The Four Workflows That Work Today](https://royalplugins.com/blog/editing-elementor-with-claude-four-workflows/) — the strategic / when-to-use-what piece.
- [Claude Skills for WordPress: Turn Prompts Into Reusable Workflows](https://royalplugins.com/blog/claude-skills-for-wordpress/) — how Skills package the workflows in this reference into tested playbooks Claude loads on demand.
- [Connecting Royal MCP to Claude](https://royalplugins.com/support/royal-mcp/connecting-to-claude/) — setup guide.
- [Connecting Royal MCP to ChatGPT](https://royalplugins.com/support/royal-mcp/connecting-to-chatgpt/) — setup guide.
- [Royal MCP landing page](https://royalplugins.com/royal-mcp/) — overview + full tool count breakdown.

[Back to Royal MCP docs](https://royalplugins.com/support/royal-mcp/)
[All support articles](https://royalplugins.com/support/)
