elementor-mcp-agent 0.1.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -121
- package/dist/server.js +2335 -322
- package/dist/server.js.map +1 -1
- package/package.json +16 -5
package/README.md
CHANGED
|
@@ -3,29 +3,23 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/elementor-mcp-agent)
|
|
4
4
|
[](./LICENSE)
|
|
5
5
|
|
|
6
|
-
> **Agency-grade MCP server for WordPress Elementor.** Multi-site management, safe Elementor
|
|
6
|
+
> **Agency-grade MCP server for WordPress Elementor.** Multi-site management, safe Elementor edits with backup + auto-rollback + CSS flush, template export/import, global widget detection, screenshots, WP-CLI escape hatch.
|
|
7
7
|
|
|
8
|
-
Built for agencies running many client sites on Elementor / Elementor Pro who want Claude (or any MCP client) to drive the toil — without breaking pages
|
|
8
|
+
Built for agencies running many client sites on Elementor / Elementor Pro who want Claude (or any MCP client) to drive the toil — **without breaking pages**.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
## Why this exists
|
|
13
13
|
|
|
14
|
-
There are
|
|
14
|
+
There are 25+ WordPress MCP servers on GitHub today. None targets the **agency multi-site workflow** with:
|
|
15
15
|
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## ⚠️ Status: early days
|
|
27
|
-
|
|
28
|
-
v0.1.0 is shipped end-to-end (CI green, 14 tests passing, npm + MCP Registry listed) but the tool surface is intentionally focused. Expect rapid iteration. Don't run destructive operations on production without testing on staging first.
|
|
16
|
+
- **Real backup before every edit** (postmeta via WP-CLI when SSH available, JSON file fallback — never silently lost)
|
|
17
|
+
- **Two-call confirmation** for any destructive op (TTL 60s)
|
|
18
|
+
- **JSON validation + auto-rollback** if an edit produces invalid Elementor data
|
|
19
|
+
- **3-level CSS flush fallback** (REST → wp-cli native → option/meta delete → re-save)
|
|
20
|
+
- **Global widget awareness** — preflight check warns if a page references shared widgets
|
|
21
|
+
- **WP-CLI escape hatch** for everything the REST API can't do safely
|
|
22
|
+
- **Screenshots** via headless Chrome (no puppeteer dep)
|
|
29
23
|
|
|
30
24
|
---
|
|
31
25
|
|
|
@@ -35,59 +29,31 @@ v0.1.0 is shipped end-to-end (CI green, 14 tests passing, npm + MCP Registry lis
|
|
|
35
29
|
npx -y elementor-mcp-agent
|
|
36
30
|
```
|
|
37
31
|
|
|
38
|
-
Or globally:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install -g elementor-mcp-agent
|
|
42
|
-
```
|
|
43
|
-
|
|
44
32
|
## Configure
|
|
45
33
|
|
|
46
|
-
The server needs to know about your sites. The simplest path: an env var with a JSON array.
|
|
47
|
-
|
|
48
34
|
```bash
|
|
49
|
-
export ELEMENTOR_MCP_SITES='[
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"application_password": "yyyy yyyy yyyy yyyy yyyy yyyy"
|
|
35
|
+
export ELEMENTOR_MCP_SITES='[{
|
|
36
|
+
"id": "client-acme",
|
|
37
|
+
"url": "https://acme.example.com",
|
|
38
|
+
"username": "admin",
|
|
39
|
+
"application_password": "xxxx xxxx xxxx xxxx xxxx xxxx",
|
|
40
|
+
"ssh": {
|
|
41
|
+
"host": "host.example.com",
|
|
42
|
+
"user": "username",
|
|
43
|
+
"port": 22,
|
|
44
|
+
"path": "/path/to/wordpress",
|
|
45
|
+
"wp_cli_path": "wp"
|
|
61
46
|
}
|
|
62
|
-
]'
|
|
47
|
+
}]'
|
|
63
48
|
```
|
|
64
49
|
|
|
65
|
-
Generate the **WordPress Application Password** at
|
|
66
|
-
`https://{your-site}/wp-admin/profile.php#application-passwords-section`
|
|
50
|
+
Generate the **WordPress Application Password** at `https://{your-site}/wp-admin/profile.php#application-passwords-section`.
|
|
67
51
|
|
|
68
|
-
|
|
52
|
+
The `ssh` block is **optional** but unlocks **8 additional tools** (WP-CLI escape hatch + reliable custom-postmeta backups). The MCP works without SSH — backups go to local JSON files instead.
|
|
69
53
|
|
|
70
|
-
|
|
54
|
+
`wp_cli_path` auto-detects if omitted (tries `wp`, then `~/bin/wp.phar`, then `~/wp-cli.phar`).
|
|
71
55
|
|
|
72
|
-
|
|
73
|
-
export ELEMENTOR_MCP_CONFIG_PATH="/path/to/sites.json"
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
With `sites.json`:
|
|
77
|
-
```json
|
|
78
|
-
{
|
|
79
|
-
"sites": [
|
|
80
|
-
{ "id": "...", "url": "...", "username": "...", "application_password": "..." }
|
|
81
|
-
],
|
|
82
|
-
"default_site_id": "client-acme",
|
|
83
|
-
"rate_limit_per_minute": 60,
|
|
84
|
-
"confirmation_ttl_seconds": 60
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Configure Claude Desktop
|
|
89
|
-
|
|
90
|
-
`~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
56
|
+
### Claude Desktop config
|
|
91
57
|
|
|
92
58
|
```json
|
|
93
59
|
{
|
|
@@ -96,91 +62,129 @@ With `sites.json`:
|
|
|
96
62
|
"command": "npx",
|
|
97
63
|
"args": ["-y", "elementor-mcp-agent"],
|
|
98
64
|
"env": {
|
|
99
|
-
"ELEMENTOR_MCP_SITES": "[{\"id\":\"acme\",\"url\":\"https://acme.com\",\"username\":\"admin\",\"application_password\":\"
|
|
65
|
+
"ELEMENTOR_MCP_SITES": "[{\"id\":\"acme\",\"url\":\"https://acme.com\",\"username\":\"admin\",\"application_password\":\"...\"}]"
|
|
100
66
|
}
|
|
101
67
|
}
|
|
102
68
|
}
|
|
103
69
|
}
|
|
104
70
|
```
|
|
105
71
|
|
|
106
|
-
### Configure Claude Code
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
claude mcp add elementor \
|
|
110
|
-
-e ELEMENTOR_MCP_SITES='[{"id":"acme","url":"https://acme.com","username":"admin","application_password":"xxxx..."}]' \
|
|
111
|
-
-- npx -y elementor-mcp-agent
|
|
112
|
-
```
|
|
113
|
-
|
|
114
72
|
---
|
|
115
73
|
|
|
116
|
-
## Tools (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- `
|
|
135
|
-
- `
|
|
136
|
-
- `
|
|
74
|
+
## Tools (34)
|
|
75
|
+
|
|
76
|
+
### Sites & health
|
|
77
|
+
- `list_sites` — enumerate the pool
|
|
78
|
+
- `ping_site` — auth + version probe
|
|
79
|
+
- `site_health` — multi-call health snapshot
|
|
80
|
+
|
|
81
|
+
### Pages
|
|
82
|
+
- `list_elementor_pages` — pages in builder mode
|
|
83
|
+
- `read_page_elementor` — parsed summary + optional full tree
|
|
84
|
+
- `list_widgets_in_page` — flat widget inventory with excerpts
|
|
85
|
+
- `list_global_widgets` — shared widgets (edit one → affects every page using it)
|
|
86
|
+
- `preflight_check` — validate a page is safe to edit
|
|
87
|
+
- `elementor_find_replace` — text replace with **dry-run → token → apply → backup → validate → rollback if invalid**
|
|
88
|
+
- `list_elementor_backups` / `restore_elementor_backup` — full restore chain with pre-restore safety backup
|
|
89
|
+
- `duplicate_elementor_page` — clone within a site (data + page_settings + edit_mode)
|
|
90
|
+
|
|
91
|
+
### Templates
|
|
92
|
+
- `list_elementor_templates` — Theme Builder distinguished from regular library
|
|
93
|
+
- `export_elementor_template` — portable JSON
|
|
94
|
+
- `import_elementor_template` — drop into target site
|
|
95
|
+
- `apply_template_to_page` — push template data onto an existing page
|
|
96
|
+
|
|
97
|
+
### WP-CLI escape hatch (require SSH)
|
|
98
|
+
- `wp_cli_run` — arbitrary wp-cli command with destructive-pattern detection + confirmation
|
|
99
|
+
- `wp_search_replace` — `wp search-replace` with mandatory dry-run
|
|
100
|
+
- `wp_elementor_flush_css` — 3-level fallback
|
|
101
|
+
- `wp_plugin_list` / `wp_plugin_update` (with confirmation)
|
|
102
|
+
|
|
103
|
+
### Visual
|
|
104
|
+
- `screenshot_page` — headless Chrome PNG of any URL
|
|
105
|
+
- `compare_screenshots` — SHA-256 + byte-delta
|
|
106
|
+
|
|
107
|
+
### Widgets (v1.1 — widget-level CRUD)
|
|
108
|
+
- `read_widget` — fetch one widget by id (read-only)
|
|
109
|
+
- `update_widget_settings` — shallow-merge settings, with backup + validate + flush
|
|
110
|
+
- `delete_widget` — remove a widget from its parent container
|
|
111
|
+
- `duplicate_widget` — clone as sibling with fresh id
|
|
112
|
+
- `swap_widget_type` — replace widgetType + settings, preserve id + position
|
|
113
|
+
- `add_widget` — append a widget into a parent container
|
|
114
|
+
- `move_widget` — move a widget between containers (with position)
|
|
115
|
+
|
|
116
|
+
### Bulk & fleet (v1.1)
|
|
117
|
+
- `bulk_find_replace_site` — find/replace across every Elementor page of one site, per-page backup + validate + flush
|
|
118
|
+
- `fleet_find_replace` — same across **every site in the pool** (sequential, dry-run mandatory)
|
|
119
|
+
- `restore_from_file` — restore `_elementor_data` from a JSON file backup, with pre-restore safety backup
|
|
120
|
+
|
|
121
|
+
### Fleet
|
|
122
|
+
- `check_elementor_versions` — flag outdated installs against wordpress.org latest
|
|
137
123
|
|
|
138
124
|
---
|
|
139
125
|
|
|
140
|
-
## Safety
|
|
126
|
+
## Safety guarantees
|
|
141
127
|
|
|
142
|
-
|
|
128
|
+
Hardcoded in `src/elementor/policies.ts`:
|
|
143
129
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
130
|
+
```ts
|
|
131
|
+
BACKUP_BEFORE_WRITE = true
|
|
132
|
+
BACKUP_PAGE_SETTINGS = true
|
|
133
|
+
VALIDATE_JSON_AFTER_EDIT = true
|
|
134
|
+
BLOCK_GLOBAL_WIDGET_WRITES_BY_DEFAULT = true
|
|
135
|
+
CONFIRMATION_TTL_SECONDS = 60
|
|
136
|
+
GLOBAL_WIDGET_CONFIRMATION_TTL_SECONDS = 30
|
|
137
|
+
FLUSH_CSS_AFTER_WRITE = true
|
|
138
|
+
MAX_ELEMENTOR_DATA_BYTES = 5_000_000
|
|
139
|
+
```
|
|
153
140
|
|
|
154
|
-
|
|
141
|
+
And these wp-cli patterns are **hard-blocked** regardless of confirmation:
|
|
142
|
+
- `rm -rf`
|
|
143
|
+
- `sudo *`
|
|
144
|
+
- `db reset --yes` / `db drop --yes`
|
|
155
145
|
|
|
156
146
|
---
|
|
157
147
|
|
|
158
|
-
##
|
|
148
|
+
## End-to-end verified
|
|
159
149
|
|
|
160
|
-
|
|
161
|
-
- [ ] `widget_swap` — replace one widget by another with field mapping
|
|
162
|
-
- [ ] `restore_elementor_backup` — restore a page from a timestamped backup
|
|
163
|
-
- [ ] `bulk_find_replace` — apply find/replace across all pages of a site
|
|
164
|
-
- [ ] WP-CLI runner via SSH for ops the REST API can't do
|
|
150
|
+
v1.0.0 was tested in real conditions against a live WordPress install with Elementor 4.0.9:
|
|
165
151
|
|
|
166
|
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
-
|
|
170
|
-
-
|
|
152
|
+
- ✅ 21/24 tools validated end-to-end
|
|
153
|
+
- ✅ find_replace → backup → restore round-trip preserves data
|
|
154
|
+
- ✅ duplicate_page copies data + page_settings + edit_mode
|
|
155
|
+
- ✅ apply_template_to_page with auto-backup
|
|
156
|
+
- ✅ wp_cli_run destructive flow (post delete) requires confirmation
|
|
157
|
+
- ✅ screenshots identical detection via SHA-256
|
|
158
|
+
- ✅ CSS flush uses `wp elementor flush-css` when SSH available, falls back to option-delete otherwise
|
|
171
159
|
|
|
172
|
-
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
160
|
+
7 bugs found during testing, all fixed:
|
|
161
|
+
- REST API silently drops unregistered postmeta writes → switched to WP-CLI primary for backups
|
|
162
|
+
- `wp` not in SSH PATH on managed hosts → auto-detection + `wp_cli_path` config
|
|
163
|
+
- SSH post-quantum banner pollution → stderr filter
|
|
164
|
+
- Default Kit returned as "widget" → client-side filter
|
|
165
|
+
- `_elementor_page_settings` type object/string mismatch → normalisation
|
|
166
|
+
- Chrome cold-start screenshot timeout → bumped to 60s
|
|
167
|
+
- Templates listing same filter bug → fixed
|
|
176
168
|
|
|
177
169
|
---
|
|
178
170
|
|
|
179
|
-
##
|
|
180
|
-
|
|
181
|
-
See [ARCHITECTURE.md](./ARCHITECTURE.md) for the full design rationale.
|
|
171
|
+
## Roadmap
|
|
182
172
|
|
|
183
|
-
|
|
173
|
+
**v1.1** ✅ shipped
|
|
174
|
+
- Widget-level CRUD: `read_widget`, `update_widget_settings`, `delete_widget`, `duplicate_widget`, `swap_widget_type`, `add_widget`, `move_widget`
|
|
175
|
+
- `bulk_find_replace_site` (across all Elementor pages of one site)
|
|
176
|
+
- `fleet_find_replace` (across all sites in pool)
|
|
177
|
+
- `restore_from_file`
|
|
178
|
+
|
|
179
|
+
**v1.2**
|
|
180
|
+
- Global styles read/write
|
|
181
|
+
- Theme Builder template push across sites
|
|
182
|
+
- Section/column-level operations
|
|
183
|
+
|
|
184
|
+
**v2.0**
|
|
185
|
+
- WooCommerce-aware tools
|
|
186
|
+
- Visual diff (pixel comparison)
|
|
187
|
+
- Schedule + cron scheduling
|
|
184
188
|
|
|
185
189
|
---
|
|
186
190
|
|