@diviops/mcp-server 1.4.1 → 1.5.2
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 +128 -311
- package/dist/index.js +1 -1
- package/dist/wp-cli.js +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,367 +1,184 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DiviOps MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**AI-driven WordPress site authoring — Divi-native, with the rest of WP in scope.**
|
|
4
|
+
|
|
5
|
+
Programmatic site authoring through Claude Code, Claude Desktop, and any other MCP client. Built on Divi 5 as the page authoring foundation, the suite also handles WordPress data models — custom post types, Secure Custom Fields, taxonomies, site audits, and hybrid sites where Divi authors the marketing pages and custom PHP templates handle the dynamic ones, with design tokens harmonized across both surfaces. Pairs with a WordPress companion plugin and ships alongside a Claude skill that knows the Divi 5 block format.
|
|
4
6
|
|
|
5
7
|
```
|
|
6
|
-
Claude Code <-> MCP Server (stdio) <-> WordPress REST API <->
|
|
8
|
+
Claude Code <-> MCP Server (stdio) <-> WordPress REST API <-> DiviOps Agent plugin
|
|
7
9
|
```
|
|
8
10
|
|
|
9
|
-
##
|
|
11
|
+
## Use cases
|
|
10
12
|
|
|
11
|
-
-
|
|
12
|
-
- **PHP** >= 7.4
|
|
13
|
-
- **WordPress** >= 6.5
|
|
14
|
-
- **Divi 5** theme active
|
|
15
|
-
- **DiviOps Agent** WordPress plugin installed and active
|
|
13
|
+
DiviOps fits multiple WordPress workflows where AI-driven authoring + management is the value:
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
- **Page building (Divi authoring)** — create + edit Divi pages, sections, modules, canvases via prompt; preset-driven design system reuse; Theme Builder layouts and templates.
|
|
16
|
+
- **SCF setup + management** — provision Secure Custom Fields field groups, sync schemas, export/import field group definitions; SCF data model becomes a tool surface, not an admin-UI flow.
|
|
17
|
+
- **CPT + post population** — register custom post types via wp-cli passthrough; bulk-populate posts and pages across any post type, not just Divi-built ones.
|
|
18
|
+
- **Data model reasoning** — schema introspection across Divi modules + SCF field groups + post meta; ask Claude what fields a post type carries, what attributes a module accepts, what tokens are defined.
|
|
19
|
+
- **WordPress site auditing** — preset audits, design-token usage scans, orphan detection (presets, variables, dangling references); broader site surveys via wp-cli (`wp option list`, `wp post list --format=json`, `wp user list`).
|
|
20
|
+
- **Hybrid sites (Divi + custom PHP)** — Divi authors the marketing pages; custom PHP templates handle dynamic ones (CPT listings, single-post views, member portals); design tokens harmonized across both surfaces via CSS custom properties driven from the Divi variable system.
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
## Quick start
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
Three steps to your first tool call.
|
|
22
25
|
|
|
23
|
-
###
|
|
24
|
-
|
|
25
|
-
Go to **WP Admin -> Users -> Your Profile -> Application Passwords**:
|
|
26
|
-
- Enter a name (e.g., "MCP Server")
|
|
27
|
-
- Click "Add New Application Password"
|
|
28
|
-
- Copy the generated password
|
|
26
|
+
### 1. Install the WordPress plugin
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
Download and activate the **DiviOps Agent** plugin — [direct zip](https://github.com/oaris-dev/diviops/raw/main/diviops-agent.zip) or browse the [public distribution repo](https://github.com/oaris-dev/diviops). Requires Divi 5.1+ on WordPress 6.5+.
|
|
31
29
|
|
|
32
|
-
###
|
|
30
|
+
### 2. Create an Application Password
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
--env WP_APP_PASSWORD=xxxxXXXXxxxxXXXXxxxxXXXX \
|
|
39
|
-
-- npx @diviops/mcp-server
|
|
40
|
-
```
|
|
32
|
+
In **WP Admin → Users → Your Profile → Application Passwords**:
|
|
33
|
+
- Enter a name (e.g. "MCP Server")
|
|
34
|
+
- Click "Add New Application Password"
|
|
35
|
+
- Copy the generated password and strip the spaces
|
|
41
36
|
|
|
42
|
-
|
|
37
|
+
### 3. Register the MCP server with Claude
|
|
43
38
|
|
|
44
|
-
**With WP-CLI** (optional — enables `diviops_meta_wp_cli` tool):
|
|
45
39
|
```bash
|
|
46
40
|
claude mcp add diviops-mcp \
|
|
47
41
|
--env WP_URL=http://your-site.local \
|
|
48
42
|
--env WP_USER=your-wp-username \
|
|
49
43
|
--env WP_APP_PASSWORD=xxxxXXXXxxxxXXXXxxxxXXXX \
|
|
50
|
-
--env "WP_PATH=/path/to/wordpress" \
|
|
51
|
-
-- npx @diviops/mcp-server
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
**With Docker-based WP-CLI** (optional — uses a custom command prefix):
|
|
55
|
-
```bash
|
|
56
|
-
claude mcp add diviops-mcp \
|
|
57
|
-
--env WP_URL=https://site-name.ddev.site \
|
|
58
|
-
--env WP_USER=your-wp-username \
|
|
59
|
-
--env WP_APP_PASSWORD=xxxxXXXXxxxxXXXXxxxxXXXX \
|
|
60
|
-
--env "WP_CLI_CMD=ddev wp" \
|
|
61
|
-
-- npx @diviops/mcp-server
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Environment Variables
|
|
65
|
-
|
|
66
|
-
| Variable | Required | Description |
|
|
67
|
-
|----------|----------|-------------|
|
|
68
|
-
| `WP_URL` | Yes | WordPress site URL (e.g. `http://mysite.local`) |
|
|
69
|
-
| `WP_USER` | Yes | WordPress username with Editor or Admin role |
|
|
70
|
-
| `WP_APP_PASSWORD` | Yes | Application Password (spaces stripped) |
|
|
71
|
-
| `WP_PATH` | No | WordPress filesystem path for Local by Flywheel, or wrapper working directory when `WP_CLI_CMD` needs project context |
|
|
72
|
-
| `WP_CLI_CMD` | No | Custom WP-CLI command prefix for containerized environments, e.g. `ddev wp`, `npx wp-env run cli wp`, `docker exec -u www-data devkinsta_fpm wp --path=/www/kinsta/public/sitename` |
|
|
73
|
-
| `LOCAL_SITE_ID` | No | Override auto-detection of Local by Flywheel site ID |
|
|
74
|
-
| `DIVIOPS_WP_CLI_ALLOW` | No | Comma-separated list of extended WP-CLI commands to enable (see [WP-CLI Security](#wp-cli-security)) |
|
|
75
|
-
| `DIVIOPS_WP_CLI_SAFE_FS_ROOT` | No | Absolute path to constrain filesystem-touching commands (`wp export`, `acf export/import`). Defaults to `<WP_PATH>/.diviops-tmp/` in host mode. **Required** in `WP_CLI_CMD` wrapper mode (must be the container-namespace path, since the host path can't be inferred) |
|
|
76
|
-
| `DIVIOPS_WP_CLI_UNSAFE_FS` | No | Set to `1` to disable filesystem flag validation entirely. For trusted single-user local-dev setups where the `--dir` / positional-path safety checks get in the way |
|
|
77
|
-
|
|
78
|
-
### Local Development Environments
|
|
79
|
-
|
|
80
|
-
The server connects via standard WordPress REST API and works with any environment that exposes WordPress over HTTP with Application Password support.
|
|
81
|
-
|
|
82
|
-
| Environment | WP_URL | WP-CLI setup | Notes |
|
|
83
|
-
|-------------|--------|--------------|-------|
|
|
84
|
-
| **Local by Flywheel** | `http://site-name.local` | `WP_PATH=/path/to/site/app/public` | Site ID auto-detected, fully supported |
|
|
85
|
-
| **WordPress Studio** | `http://localhost:{port}` | `WP_CLI_CMD="studio wp --path=/path/to/site"` | Port auto-assigned (8881, 8882, ...). Uses SQLite, not MySQL |
|
|
86
|
-
| **DDEV** | `https://site-name.ddev.site` | `WP_CLI_CMD="ddev wp"` plus `WP_PATH=/path/to/project` | Wrapper runs from `WP_PATH` so DDEV can resolve the site |
|
|
87
|
-
| **wp-env** | `http://localhost:8888` | `WP_CLI_CMD="npx wp-env run cli wp"` plus `WP_PATH=/path/to/project` | Wrapper runs from `WP_PATH`; requires `WP_ENVIRONMENT_TYPE=local` (see below) |
|
|
88
|
-
| **DevKinsta** | `https://site-name.local` | `WP_CLI_CMD="docker exec -u www-data devkinsta_fpm wp --path=/www/kinsta/public/sitename"` | HTTPS with self-signed certs |
|
|
89
|
-
| **Custom / Remote** | Your site URL | `WP_PATH=/path/to/site` or `WP_CLI_CMD="..."` | Works with any WP host |
|
|
90
|
-
|
|
91
|
-
> **Application Passwords on HTTP:** WordPress requires HTTPS for Application Passwords unless `WP_ENVIRONMENT_TYPE` is set to `'local'`. HTTPS environments (DDEV, DevKinsta) work out of the box. HTTP environments (wp-env, WordPress Studio) need this in `wp-config.php`:
|
|
92
|
-
> ```php
|
|
93
|
-
> define('WP_ENVIRONMENT_TYPE', 'local');
|
|
94
|
-
> ```
|
|
95
|
-
> Local by Flywheel sets this automatically.
|
|
96
|
-
|
|
97
|
-
> **WP-CLI note:** `WP_PATH` keeps the existing Local by Flywheel behavior by running `wp` directly on the host filesystem. For Docker-based environments (DDEV, wp-env, DevKinsta, WordPress Studio), set `WP_CLI_CMD` to the wrapper command instead. When `WP_CLI_CMD` is set, the server executes the wrapper from `WP_PATH` if provided, otherwise from its current working directory. The MCP server still validates the requested WP-CLI subcommand against its allowlist before executing either path.
|
|
98
|
-
|
|
99
|
-
## Available Tools (66)
|
|
100
|
-
|
|
101
|
-
### Read (30)
|
|
102
|
-
| Tool | Description |
|
|
103
|
-
|------|-------------|
|
|
104
|
-
| `diviops_meta_ping` | Test WordPress connection and Divi version |
|
|
105
|
-
| `diviops_meta_info` | DiviOps server identity, version, license type, capabilities |
|
|
106
|
-
| `diviops_page_list` | List pages/posts with Divi status |
|
|
107
|
-
| `diviops_page_get` | Get page details and raw content |
|
|
108
|
-
| `diviops_page_get_layout` | Get parsed block tree (layout structure) |
|
|
109
|
-
| `diviops_section_get` | Get a single section's markup by admin label |
|
|
110
|
-
| `diviops_schema_list_modules` | List all available Divi modules |
|
|
111
|
-
| `diviops_schema_get_module` | Get attribute schema for a module. Default `mode: "single"` returns one module's schema (optimized; `raw: true` for full). `mode: "dump_all"` snapshots every Divi module in one call along with a `schema_version` hash over `*PresetAttrsMap.php` and a `divi_version` field — build-time entry point for the skill regen pipeline. |
|
|
112
|
-
| `diviops_schema_get_settings` | Get Divi site settings and theme options |
|
|
113
|
-
| `diviops_global_color_list` | Get global color palette |
|
|
114
|
-
| `diviops_global_font_list` | Get global font definitions |
|
|
115
|
-
| `diviops_meta_find_icon` | Search 1,989 icons by keyword (FA + Divi) |
|
|
116
|
-
| `diviops_template_list` | List available MCP prompt templates |
|
|
117
|
-
| `diviops_template_get` | Get a specific template's block markup |
|
|
118
|
-
| `diviops_preset_audit` | Audit presets with referenced/unreferenced analysis. Walks both page content and in-registry `groupPresets` chains; exposes `block_ref_count`, `group_ref_count`, `referenced_by_presets`. Also reports `orphan_default_pointers` — per-bucket `default` pointers referencing UUIDs missing from `items[]` (legacy damage from past unsafe deletes; clear via `diviops_preset_set_default` in bucket-addressed mode: `type` + `module` + `unset=true`) |
|
|
119
|
-
| `diviops_preset_scan_orphans` | List page-referenced preset UUIDs missing from the D5 registry (separates dangling orphans from D4-legacy refs) |
|
|
120
|
-
| `diviops_library_list` | List saved Divi Library items |
|
|
121
|
-
| `diviops_library_get` | Get a library item's block markup |
|
|
122
|
-
| `diviops_render_preview` | Render block markup to HTML for preview |
|
|
123
|
-
| `diviops_validate_blocks` | Validate block markup (structure, required attrs, known pitfalls) |
|
|
124
|
-
| `diviops_tb_template_list` | List Theme Builder templates with conditions and layout IDs |
|
|
125
|
-
| `diviops_tb_layout_get` | Get a Theme Builder layout's block markup (header/body/footer) |
|
|
126
|
-
| `diviops_variable_list` | List design token variables (filter by type or prefix) |
|
|
127
|
-
| `diviops_variable_scan_orphans` | Find `gvid-`/`gcid-` refs with no backing Variable Manager entry (orphans render as invalid CSS) + unused variables (defined, never referenced). Scans pages, Theme Builder layouts (header/body/footer), Divi Library items, canvas pages, and the preset registry |
|
|
128
|
-
| `diviops_variable_used_on_page` | Detect which `gvid-` (numeric/font) IDs a single page emits — the exact set Divi 5.4.0+ uses to scope selective `:root{--gvid-*}` CSS variable emission. Walks the same content stack the frontend assembles (post_content + active TB header/body/footer + appended canvases + presets). `gcid-` colors are out of scope (separate emission path). Use for per-page orphan validation, preflight before bulk variable rename, or to debug why a numeric/font variable doesn't render on a specific page. Read-only |
|
|
129
|
-
| `diviops_canvas_list` | List all canvas pages |
|
|
130
|
-
| `diviops_canvas_get` | Get canvas content |
|
|
131
|
-
| `diviops_scf_status` | Show SCF (Secure Custom Fields) sync status — pending JSON-vs-DB drift across field groups, post types, taxonomies, options pages. Wraps `wp scf json status` |
|
|
132
|
-
| `diviops_scf_field_group_list` | List all SCF/ACF field groups (post_name = ACF key, post_title, post_status, post_modified). Queries the `acf-field-group` post type via `wp post list` (works on SCF 6.8.4+ and older ACF) |
|
|
133
|
-
| `diviops_scf_field_group_get` | Fetch a single SCF/ACF field-group post by ACF key (`group_abc123` → post_name) or numeric WP post ID. For the parsed/structured field tree, use `diviops_scf_export --field-groups=<key> --stdout` |
|
|
134
|
-
|
|
135
|
-
### Write (34)
|
|
136
|
-
| Tool | Description |
|
|
137
|
-
|------|-------------|
|
|
138
|
-
| `diviops_page_create` | Create a new page with optional Divi content |
|
|
139
|
-
| `diviops_page_update_content` | Full page content rewrite |
|
|
140
|
-
| `diviops_page_trash` | Trash (default) or permanently delete (`force=true`) a page. Idempotent on already-trashed posts. Supports `dry_run` |
|
|
141
|
-
| `diviops_page_update_status` | Update post_status (publish/draft/private/pending/future). `future` requires `date_gmt` (ISO 8601 UTC); `publish` clears stale future dates so re-publishing takes effect immediately. Supports `dry_run` |
|
|
142
|
-
| `diviops_section_append` | Append a section to existing page (start or end) |
|
|
143
|
-
| `diviops_section_replace` | Replace a section by admin label |
|
|
144
|
-
| `diviops_section_remove` | Remove a section by admin label |
|
|
145
|
-
| `diviops_module_update` | Update specific module attributes by label or text match |
|
|
146
|
-
| `diviops_module_move` | Move a block before/after another block (reorder modules, sections) |
|
|
147
|
-
| `diviops_module_lock` | Lock a module so VB users cannot edit it (frontend renders normally) |
|
|
148
|
-
| `diviops_module_unlock` | Unlock a module by removing `attrs.locked` (matches VB's absence convention) |
|
|
149
|
-
| `diviops_module_clone` | Deep-copy a module + insert next to source within the same parent |
|
|
150
|
-
| `diviops_global_color_create` | Add a new global color to Divi's palette (writes canonical shape; closes ET's bundle Zod gap that drops `label`) |
|
|
151
|
-
| `diviops_global_color_update` | Update an existing global color by gcid (only provided fields change) |
|
|
152
|
-
| `diviops_global_color_delete` | Delete a global color (refuses if `usedInPosts` non-empty unless `force=true`; customizer-bound defaults always protected) |
|
|
153
|
-
| `diviops_preset_cleanup` | Remove spam/duplicate presets, bulk rename |
|
|
154
|
-
| `diviops_preset_create` | Write a new preset to the D5 registry (module or group type, supports `divi/column` etc.). Optional `make_default: true` sets it as the bucket's default; optional `priority` controls stack-merge order |
|
|
155
|
-
| `diviops_preset_reassign` | Rewrite `modulePreset` references across pages (dry-run by default; optional `strip_inline` removes redundant inline attrs) |
|
|
156
|
-
| `diviops_preset_update` | Update a specific preset (name, attrs, priority) |
|
|
157
|
-
| `diviops_preset_delete` | Delete a preset by ID. Refuses with HTTP 409 `preset_is_default` when the target is the registered default for its bucket — clear the pointer first via `diviops_preset_set_default` with `unset=true`, or pass `force=true` to delete and clear the pointer in one write |
|
|
158
|
-
| `diviops_preset_set_default` | Set or clear the per-module/group default preset. Two modes: by `preset_id` (UUID-addressed; auto-resolves bucket) or by `type` + `module` + `unset=true` (bucket-addressed clear, used to repair orphan default pointers when the UUID is gone from `items[]`). Defaults apply to NEW instances only — use `diviops_preset_reassign` for retroactive swaps |
|
|
159
|
-
| `diviops_library_save` | Save block markup to Divi Library |
|
|
160
|
-
| `diviops_tb_layout_update` | Update a Theme Builder layout's block markup |
|
|
161
|
-
| `diviops_tb_template_create` | Create Theme Builder template with header/footer and conditions |
|
|
162
|
-
| `diviops_variable_create` | Create a design token variable. For `type=numbers` fluid tokens, pass `min`+`max` shorthand (anchors default to 320px/1920px) or explicit `targets` like `{"320px":"20px","1920px":"60px"}` — server generates arithmetically-correct `clamp()` instead of hand-written math that silently under-reaches the stated max. All-px inputs emit px (root-agnostic). Rem inputs OR rem output require explicit opt-in: pass `output_unit="rem"` (accepts the 1rem=16px default) or `root_font_size_px:N` (declares your site's actual root font-size, e.g. `10` for `html { font-size: 62.5% }`, `20` for `html { font-size: 20px }`) |
|
|
163
|
-
| `diviops_variable_create_fluid_system` | Batch-emit a fluid typography + spacing + radius variable set in one call. Mirrors Divi 5.4.0's Variable Generator Modal at the algorithm level (clamp() math is identical to `diviops_variable_create`'s fluid mode) but layers profile-selectable anchors over it: `divi-default` (360→1350) matches ET's defaults, `wide` (320→1920) matches the diviops convention, `custom` takes explicit anchors. Each category is independent and optional. Typography uses modular-scale chains (named ratios `major-third`/`perfect-fifth`/`golden`/etc., or raw numbers) — h1 = largest, hN = base. Spacing/radius support `linear` or `geometric` step distributions. `dry_run: true` returns the full plan without persisting; `overwrite: false` (default) skips existing IDs. Single atomic write to the registry — mid-batch failures roll back cleanly |
|
|
164
|
-
| `diviops_variable_delete` | Delete a variable by ID. Returns HTTP 409 when live references exist unless `force=true` (use `diviops_variable_scan_orphans` to find reference locations). Returns HTTP 403 for Divi's customizer-bound defaults (`gcid-primary-color`, `gcid-secondary-color`, `gcid-heading-color`, `gcid-body-color`, `gcid-link-color` — managed via WP Customizer) |
|
|
165
|
-
| `diviops_canvas_create` | Create a canvas page |
|
|
166
|
-
| `diviops_canvas_duplicate` | Deep-copy a canvas (content + canvas-specific meta). Default copy title `<source> (Copy)` auto-suffixes on collision (Copy 2, …); explicit `title` collisions return 409. Supports `dry_run` |
|
|
167
|
-
| `diviops_canvas_update` | Update canvas content and/or metadata. Pass any subset of fields — `{canvas_post_id, title}` renames without touching content |
|
|
168
|
-
| `diviops_canvas_delete` | Delete a canvas page |
|
|
169
|
-
| `diviops_scf_export` | Export SCF schema (field groups, post types, taxonomies, options pages) as JSON to a directory under the safe-root, or to stdout. Wraps `wp scf json export` |
|
|
170
|
-
| `diviops_scf_import` | Import SCF schema from a JSON file (mutates DB; idempotent — existing items are updated). Wraps `wp scf json import <file>` |
|
|
171
|
-
| `diviops_scf_sync` | Apply pending JSON-on-disk SCF changes to the DB. Defaults to `dry_run: true` for safety. Wraps `wp scf json sync` |
|
|
172
|
-
|
|
173
|
-
### Utility (2)
|
|
174
|
-
| Tool | Description |
|
|
175
|
-
|------|-------------|
|
|
176
|
-
| `diviops_meta_wp_cli` | Run WP-CLI commands (allowlisted, requires `WP_PATH` or `WP_CLI_CMD`) |
|
|
177
|
-
| `diviops_meta_flush_cache` | Flush Divi's compiled CSS cache under `wp-content/et-cache/`. `wp cache flush` does NOT touch these files — the frontend can keep serving stale CSS after mutations. Delegates to Divi's native clearer (`ET_Core_PageResource::remove_static_resources`) when available — also clears Theme Builder / archive / taxonomy / home / notfound CSS, object cache, module features cache, post features cache, dynamic assets cache, Google Fonts cache, post meta caches. Falls back to a filesystem walk of numeric-named subdirs when Divi is inactive. Response includes `backend: "divi_native"` or `"fs_fallback"`. Exactly one selector required: `post_id`, `all`, or `after` (unix ts) — no default to `all` |
|
|
178
|
-
|
|
179
|
-
## WP-CLI Security
|
|
180
|
-
|
|
181
|
-
The `diviops_meta_wp_cli` tool validates every command against a safety allowlist before execution. Commands not on the list are rejected.
|
|
182
|
-
|
|
183
|
-
### Default allowlist (always available)
|
|
184
|
-
|
|
185
|
-
Read-only commands plus non-destructive writes needed for core MCP functionality and local development workflows:
|
|
186
|
-
|
|
187
|
-
| Category | Commands |
|
|
188
|
-
|----------|----------|
|
|
189
|
-
| Options | `option get`, `option list` |
|
|
190
|
-
| Posts | `post list`, `post get`, `post create`, `post update` |
|
|
191
|
-
| Post meta | `post meta get`, `post meta list`, `post meta set`, `post meta update` |
|
|
192
|
-
| Post types | `post-type list`, `post-type get` |
|
|
193
|
-
| Taxonomies | `taxonomy list`, `term list`, `term create`, `term update` |
|
|
194
|
-
| ACF / SCF | `acf export`, `acf import`, `acf field-group list`, `acf field-group get`, `scf json {status,sync,import,export}` (also aliased as `acf json …` per SCF 6.8.4+) |
|
|
195
|
-
| Users | `user list` |
|
|
196
|
-
| Cache | `cache flush`, `transient delete`, `rewrite flush` |
|
|
197
|
-
| Export | `export` (WXR data export to file) |
|
|
198
|
-
| Info | `cron event list`, `plugin list`, `theme list`, `menu list`, `site url` |
|
|
199
|
-
| Core (read-only) | `core version`, `core check-update`, `core is-installed`, `core verify-checksums`, `core language list` |
|
|
200
|
-
| DB (introspection) | `db columns`, `db size`, `db tables`, `db check`, `db search` |
|
|
201
|
-
|
|
202
|
-
### Extended commands (opt-in)
|
|
203
|
-
|
|
204
|
-
These commands carry higher risk and require explicit opt-in via the `DIVIOPS_WP_CLI_ALLOW` environment variable:
|
|
205
|
-
|
|
206
|
-
| Command | Risk | Why opt-in |
|
|
207
|
-
|---------|------|------------|
|
|
208
|
-
| `option update` | High | Can change site URL, admin email, or security settings |
|
|
209
|
-
| `option delete` | High | Permanently removes a WP option (no undo) |
|
|
210
|
-
| `post delete` | Medium | Permanently removes content |
|
|
211
|
-
| `post meta delete` | Medium | Removes metadata |
|
|
212
|
-
| `term delete` | Medium | Permanently removes taxonomy terms |
|
|
213
|
-
| `search-replace` | High | Bulk database modification — can corrupt content if misused |
|
|
214
|
-
| `import` | Medium | Bulk content ingestion from WXR files |
|
|
215
|
-
| `plugin activate` | Medium | Can enable untrusted plugins |
|
|
216
|
-
| `plugin deactivate` | Medium | Can disable security plugins |
|
|
217
|
-
| `eval-file` | Critical | Executes arbitrary PHP from a file path |
|
|
218
|
-
|
|
219
|
-
To enable extended commands, add `DIVIOPS_WP_CLI_ALLOW` to your MCP registration:
|
|
220
|
-
|
|
221
|
-
```bash
|
|
222
|
-
claude mcp add diviops-mcp \
|
|
223
|
-
--env WP_URL=http://your-site.local \
|
|
224
|
-
--env WP_USER=admin \
|
|
225
|
-
--env WP_APP_PASSWORD=xxxx \
|
|
226
|
-
--env "WP_PATH=/path/to/wordpress" \
|
|
227
|
-
--env "DIVIOPS_WP_CLI_ALLOW=option update,post delete,search-replace" \
|
|
228
44
|
-- npx @diviops/mcp-server
|
|
229
45
|
```
|
|
230
46
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
#### Wildcard / "god-mode" (local dev only)
|
|
234
|
-
|
|
235
|
-
For trusted local-dev environments where you don't want to re-list every extended command per site, the values `*` and `all` grant the full extended set:
|
|
236
|
-
|
|
237
|
-
```bash
|
|
238
|
-
--env "DIVIOPS_WP_CLI_ALLOW=*"
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
The sentinel grants exactly the extended set above — it does NOT unlock anything beyond it (notably: `db query` stays out by design). The server emits a startup warning to stderr whenever the wildcard is active, so the broad grant is never silent. Auto-adopts new extended commands on future versions.
|
|
242
|
-
|
|
243
|
-
> **Don't use this in shared or production environments.** Pin the specific commands you need with the comma-separated form instead.
|
|
47
|
+
Then ask Claude: **"List the pages on my site."** Claude calls `diviops_page_list` and renders the result. You're authoring with the suite.
|
|
244
48
|
|
|
245
|
-
|
|
49
|
+
For a deeper walkthrough (containerized environments, WP-CLI configuration, troubleshooting installation), see [setup-guide.md](../docs/setup-guide.md).
|
|
246
50
|
|
|
247
|
-
|
|
51
|
+
## Example workflow
|
|
248
52
|
|
|
249
|
-
|
|
53
|
+
> **You:** Create a hero section on a new page called "Spring Launch" with a heading, subheading, and a CTA button. Use my brand colors.
|
|
250
54
|
|
|
251
|
-
|
|
252
|
-
- **`wp export` must pass `--dir=<path-under-safe-root>`** (or `--stdout`). Without `--dir`, wp-cli writes to the current working directory; on prod that's typically the web root.
|
|
253
|
-
- **`--filename_format=` must be a filename template**, not a path — separators (`/`, `\`) are rejected so a crafted template can't escape `--dir`'s scope.
|
|
254
|
-
- **`acf export/import`'s positional path** must resolve under the safe root.
|
|
255
|
-
- **`scf json export`'s `--dir=` flag** must resolve under the safe root (or pass `--stdout` for in-memory transfer). **`scf json import`'s positional `<file>` path** must resolve under the safe root.
|
|
256
|
-
- **Wrapper mode (`WP_CLI_CMD`)**: the host-derived safe root doesn't correspond to the wrapper's filesystem (e.g., container paths like `/www/app`), so `DIVIOPS_WP_CLI_SAFE_FS_ROOT` is **required** and must be set to the container-namespace path. FS-sensitive commands are rejected with a clear error if it's missing.
|
|
257
|
-
- **Escape hatch**: `DIVIOPS_WP_CLI_UNSAFE_FS=1` disables validation entirely. Appropriate for trusted single-user local-dev setups that don't want the guard.
|
|
55
|
+
Claude orchestrates a few tool calls in sequence:
|
|
258
56
|
|
|
259
|
-
|
|
57
|
+
1. `diviops_global_color_list` — discovers your brand palette.
|
|
58
|
+
2. `diviops_template_list` / `diviops_template_get` — pulls a verified hero template that matches the request.
|
|
59
|
+
3. `diviops_page_create` — creates `Spring Launch` as a draft with the hero block markup.
|
|
60
|
+
4. `diviops_validate_blocks` — confirms the markup is well-formed before save.
|
|
61
|
+
5. `diviops_render_preview` — returns the rendered HTML so you can verify before publishing.
|
|
260
62
|
|
|
261
|
-
|
|
63
|
+
The skill enforces the Divi block format, the design system, and the response contract throughout — you stay at the prompt level.
|
|
262
64
|
|
|
263
|
-
|
|
65
|
+
## Tools at a glance
|
|
264
66
|
|
|
265
|
-
|
|
67
|
+
The server exposes **66 tools** across the categories below. Each category links to representative tools; the full table lives in [server-reference.md](../docs/server-reference.md).
|
|
266
68
|
|
|
267
|
-
|
|
69
|
+
| Category | Use case | Tool prefixes |
|
|
70
|
+
|----------|----------|---------------|
|
|
71
|
+
| Page authoring | Create, edit, restructure pages | `page_*`, `section_*`, `module_*` |
|
|
72
|
+
| Design system | Manage colors, fonts, variables, presets | `variable_*`, `global_color_*`, `global_font_*`, `preset_*` |
|
|
73
|
+
| Library + templates | Reusable layouts + Theme Builder | `library_*`, `template_*`, `tb_*` |
|
|
74
|
+
| Schema introspection | Module attribute discovery | `schema_*` |
|
|
75
|
+
| Canvas / off-canvas | Popups, modals, menus | `canvas_*` |
|
|
76
|
+
| SCF integration | Secure Custom Fields sync | `scf_*` |
|
|
77
|
+
| Render + validate | Preview HTML, validate block markup | `render_preview`, `validate_blocks` |
|
|
78
|
+
| WP-CLI passthrough | Escape hatch for site ops | `meta_wp_cli` |
|
|
79
|
+
| Cache + meta | Connection probe, identity, icons, cache flush | `meta_*` |
|
|
268
80
|
|
|
269
|
-
|
|
270
|
-
- Operation targets a **single item** (one variable, one preset, one page)
|
|
271
|
-
- Safety check is **binary** (safe / not safe)
|
|
272
|
-
- The reason for blocking is compact enough to fit in the error body (e.g., "3 live references")
|
|
273
|
-
- The caller can decide from the error alone — no full diff needed
|
|
81
|
+
See [server-reference.md](../docs/server-reference.md) for per-tool descriptions.
|
|
274
82
|
|
|
275
|
-
|
|
276
|
-
| Tool | Guard | Override |
|
|
277
|
-
|------|-------|----------|
|
|
278
|
-
| `diviops_variable_delete` | HTTP 409 when live references exist | `force=true` |
|
|
279
|
-
| `diviops_preset_delete` | HTTP 409 `preset_is_default` when target is the registered default for its bucket | `force=true` (deletes + clears the `default` pointer in the same write) |
|
|
83
|
+
## Response contract
|
|
280
84
|
|
|
281
|
-
|
|
85
|
+
Tools return a standardized envelope. The shape lets clients branch on `ok` and machine-readable `error.code` without parsing freeform messages.
|
|
282
86
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
- Two round-trips are acceptable because the caller is already in review mode
|
|
290
|
-
|
|
291
|
-
**Current tools:**
|
|
292
|
-
| Tool | Preview flag | Commit flag |
|
|
293
|
-
|------|--------------|-------------|
|
|
294
|
-
| `diviops_preset_reassign` | `mode: "dry-run"` (default) | `mode: "apply"` |
|
|
295
|
-
| `diviops_preset_cleanup` | `dry_run: true` (default) | `dry_run: false` |
|
|
296
|
-
|
|
297
|
-
> Both preview-then-commit tools share the same semantic pattern but use different parameter shapes (`mode` enum vs `dry_run` bool). Both predate this convention and stay as-is for caller compatibility. **New bulk tools should use the enum form** (`mode: "dry-run" | "apply"`) — it's more extensible if future modes are needed (`"interactive"`, `"selective"`, etc.) and keeps the interface consistent as the tool set grows.
|
|
298
|
-
|
|
299
|
-
### Pattern B (variant) — universal `dry_run: boolean` on every write tool
|
|
300
|
-
|
|
301
|
-
Every mutating tool also accepts an optional `dry_run: boolean` (default `false`). When `true`, the response carries a uniform plan shape — `{ ok: true, data: { dry_run: true, plan: { summary, changes[, warnings] } } }` — and no state is mutated. Apply mode (`dry_run` omitted) keeps each tool's pre-existing response shape unchanged, so adding the parameter is non-breaking.
|
|
87
|
+
```jsonc
|
|
88
|
+
// Success
|
|
89
|
+
{ "ok": true, "data": <payload> }
|
|
90
|
+
// Failure
|
|
91
|
+
{ "ok": false, "error": { "code": "<code>", "message": "<human>", "hint": "<optional>" } }
|
|
92
|
+
```
|
|
302
93
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
94
|
+
### Standard error codes
|
|
95
|
+
|
|
96
|
+
| code | HTTP | meaning |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `not_found` | 404 | Target ID does not resolve |
|
|
99
|
+
| `invalid_input` | 400 | Schema violation, malformed args |
|
|
100
|
+
| `validation_failed` | 400 | `validate_blocks`-detected shape error |
|
|
101
|
+
| `conflict` | 409 | Uniqueness collision |
|
|
102
|
+
| `forbidden` | 403 | Row-level WordPress auth signal |
|
|
103
|
+
| `capability_missing` | 412 | Plugin version below required for this tool |
|
|
104
|
+
| `wp_error` | 500 | Underlying WordPress error |
|
|
105
|
+
| `divi_error` | 500 | Divi-specific error (block parser, validator, etc.) |
|
|
106
|
+
|
|
107
|
+
### Namespace-specific codes
|
|
108
|
+
|
|
109
|
+
Namespaces extend the vocabulary using the `<namespace>.<reason>` convention — e.g. `meta_wp_cli.command_failed`, `scf.not_configured`, `preset.bucket_mismatch`, `variable.customizer_default_immutable`. Namespace-prefixed codes carry structured `error.data` documenting the failure (exit codes, conflicting fields, reference counts, etc.). Per-tool descriptions name the codes each tool emits and the `error.data` shape that accompanies them.
|
|
110
|
+
|
|
111
|
+
### `dry_run` plan shape
|
|
112
|
+
|
|
113
|
+
Every write tool accepts `dry_run: boolean` (default `false`). When `true`, the response carries a uniform plan shape and no state is mutated:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"ok": true,
|
|
118
|
+
"data": {
|
|
119
|
+
"dry_run": true,
|
|
120
|
+
"plan": {
|
|
121
|
+
"summary": "Would update 1 attr path(s) on module 'Hero CTA' (page #42, type divi/button).",
|
|
122
|
+
"changes": [
|
|
123
|
+
{ "kind": "module.update", "target": "page#42/divi/button/Hero CTA#button.decoration.font.font.desktop.value.color", "before": "#000", "after": "#ff0066" }
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
306
129
|
|
|
307
|
-
|
|
130
|
+
`meta_wp_cli` and `scf_import` do not accept `dry_run` (raw passthrough / upstream gap respectively). For bulk preview-then-commit flows (preset reassign, preset cleanup), see [safety-patterns.md](../docs/safety-patterns.md).
|
|
308
131
|
|
|
309
|
-
|
|
132
|
+
### `_meta.idempotent` markers
|
|
310
133
|
|
|
311
|
-
|
|
134
|
+
Every tool's `_meta.idempotent` field documents how it behaves under repeat calls with identical inputs. Some tools are silent-success idempotent (e.g. `page_trash` on an already-trashed post returns `ok: true` with `data.already_trashed = true`); others are side-effect-equivalent (re-running produces the same final state via different intermediate effects). See [idempotency-audit.md](../docs/idempotency-audit.md) for the per-tool record.
|
|
312
135
|
|
|
313
|
-
|
|
136
|
+
## Configuration
|
|
314
137
|
|
|
315
|
-
|
|
138
|
+
### Environment variables
|
|
316
139
|
|
|
317
|
-
|
|
140
|
+
| Variable | Required | Description |
|
|
141
|
+
|----------|----------|-------------|
|
|
142
|
+
| `WP_URL` | Yes | WordPress site URL (e.g. `http://mysite.local`) |
|
|
143
|
+
| `WP_USER` | Yes | WordPress username with Editor or Admin role |
|
|
144
|
+
| `WP_APP_PASSWORD` | Yes | Application Password (spaces stripped) |
|
|
145
|
+
| `WP_PATH` | No | WordPress filesystem path for Local by Flywheel, or wrapper working directory when `WP_CLI_CMD` needs project context |
|
|
146
|
+
| `WP_CLI_CMD` | No | Custom WP-CLI command prefix for containerized environments (e.g. `ddev wp`, `npx wp-env run cli wp`) |
|
|
147
|
+
| `LOCAL_SITE_ID` | No | Override auto-detection of Local by Flywheel site ID |
|
|
148
|
+
| `DIVIOPS_WP_CLI_ALLOW` | No | Opt-in extended WP-CLI commands — see [wp-cli-security.md](../docs/wp-cli-security.md) |
|
|
149
|
+
| `DIVIOPS_WP_CLI_SAFE_FS_ROOT` | No | Path to constrain filesystem-touching wp-cli commands. **Required** in `WP_CLI_CMD` wrapper mode |
|
|
150
|
+
| `DIVIOPS_WP_CLI_UNSAFE_FS` | No | Set to `1` to disable filesystem flag validation entirely |
|
|
318
151
|
|
|
319
|
-
|
|
152
|
+
### Containerized environments
|
|
320
153
|
|
|
321
|
-
-
|
|
322
|
-
- "Show me the layout structure of page 42"
|
|
323
|
-
- "Create a new landing page with a hero section, 3-column features, and a CTA"
|
|
324
|
-
- "Save the hero section from page 312 to the Divi Library"
|
|
325
|
-
- "Validate this block markup before saving"
|
|
154
|
+
The server connects via standard WordPress REST API and works with any environment that exposes WordPress over HTTP with Application Password support — Local by Flywheel, DDEV, wp-env, WordPress Studio, DevKinsta, custom hosts. See [setup-guide.md](../docs/setup-guide.md) for environment-specific `WP_CLI_CMD` examples and HTTPS / `WP_ENVIRONMENT_TYPE` notes.
|
|
326
155
|
|
|
327
156
|
## Troubleshooting
|
|
328
157
|
|
|
329
|
-
|
|
330
|
-
Ensure `WP_URL`, `WP_USER`, and `WP_APP_PASSWORD` are all set. Check your `claude mcp add` command.
|
|
331
|
-
|
|
332
|
-
### "Connection failed" error
|
|
333
|
-
- Verify the WP plugin is active: visit `{WP_URL}/wp-json/diviops/v1/schema/settings` in your browser
|
|
334
|
-
- Check Application Password is correct (try with curl first)
|
|
158
|
+
Common quick fixes — full reference in [troubleshooting.md](../docs/troubleshooting.md).
|
|
335
159
|
|
|
336
|
-
|
|
337
|
-
|
|
160
|
+
- **"Missing required environment variable(s)"** — ensure `WP_URL`, `WP_USER`, `WP_APP_PASSWORD` are all set on `claude mcp add`.
|
|
161
|
+
- **"Connection failed"** — verify the plugin is active by visiting `{WP_URL}/wp-json/diviops/v1/schema/settings`; test the credentials with `curl -u "user:pass" …`.
|
|
162
|
+
- **"This tool requires plugin capability"** — the plugin doesn't advertise the capability this tool needs. Update the plugin to the latest release.
|
|
163
|
+
- **Preset edits not visible on the frontend** — Divi serves frontend CSS from `wp-content/et-cache/{post_id}/`, which `wp cache flush` doesn't touch. Use `diviops_meta_flush_cache` after preset writes.
|
|
338
164
|
|
|
339
|
-
|
|
340
|
-
The plugin returned HTTP 426 because this MCP server is below the plugin's `MIN_SERVER_VERSION`. Update the MCP server (`npm install -g @diviops/mcp-server@latest` or rebuild from source).
|
|
165
|
+
## Learn more
|
|
341
166
|
|
|
342
|
-
|
|
343
|
-
-
|
|
344
|
-
-
|
|
167
|
+
- [setup-guide.md](../docs/setup-guide.md) — full onboarding walkthrough (containerized envs, HTTPS, Application Passwords)
|
|
168
|
+
- [server-reference.md](../docs/server-reference.md) — full per-tool reference table
|
|
169
|
+
- [wp-cli-security.md](../docs/wp-cli-security.md) — allowlist, extended commands, FS validation
|
|
170
|
+
- [safety-patterns.md](../docs/safety-patterns.md) — Pattern A (refuse-with-override) + Pattern B (preview-then-commit) + universal `dry_run`
|
|
171
|
+
- [troubleshooting.md](../docs/troubleshooting.md) — common errors and resolutions
|
|
172
|
+
- [idempotency-audit.md](../docs/idempotency-audit.md) — repeat-call semantics per tool
|
|
173
|
+
- **`divi-5-builder` Claude skill** — block format rules, design patterns, workflow guidance (ships in the dist repo)
|
|
345
174
|
|
|
346
|
-
|
|
347
|
-
```bash
|
|
348
|
-
curl -u "username:apppassword" http://site.local/wp-json/diviops/v1/schema/settings
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Preset edits not visible on the frontend
|
|
352
|
-
|
|
353
|
-
After `preset_update` / `preset_create`, the preset option is updated immediately but Divi serves frontend CSS from a **per-post static cache** that neither `wp cache flush` nor `wp transient delete --all` invalidates.
|
|
354
|
-
|
|
355
|
-
Cache location: `wp-content/et-cache/{post_id}/` — contains files like `et-divi-dynamic-tb-*-{post_id}-critical.css` with preset CSS baked in.
|
|
356
|
-
|
|
357
|
-
To force regeneration for a specific page:
|
|
358
|
-
```bash
|
|
359
|
-
rm -rf wp-content/et-cache/{post_id}/
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
Next visit re-renders and writes fresh CSS. Applies to: any change that affects preset-derived CSS output (preset_update, preset_create when used by an existing page, preset_reassign in apply mode).
|
|
175
|
+
## Requirements
|
|
363
176
|
|
|
364
|
-
|
|
177
|
+
- Node.js >= 18.0.0
|
|
178
|
+
- PHP >= 7.4
|
|
179
|
+
- WordPress >= 6.5
|
|
180
|
+
- Divi 5 theme active
|
|
181
|
+
- DiviOps Agent WordPress plugin installed and active
|
|
365
182
|
|
|
366
183
|
## License
|
|
367
184
|
|
package/dist/index.js
CHANGED
|
@@ -1708,7 +1708,7 @@ registerPluginTool("diviops_canvas_delete", {
|
|
|
1708
1708
|
});
|
|
1709
1709
|
// ── WP-CLI ──────────────────────────────────────────────────────────
|
|
1710
1710
|
server.registerTool("diviops_meta_wp_cli", {
|
|
1711
|
-
description: "Run a WP-CLI command on the WordPress site. Requires WP_PATH env var (LOCAL_SITE_ID auto-detected from Local by Flywheel), or WP_CLI_CMD for containerized wrappers. Commands validated against a safety allowlist. Default tier covers read ops across options/posts/post-types/taxonomies/users/info/core/db, non-destructive writes (post/term create+update, post meta read/write, cache/rewrite/transient flush), ACF/SCF schema ops (`acf export/import/field-group list/get` plus SCF 6.8.4+ `scf json {status,sync,import,export}` and the `acf json …` aliases), and WXR export. Extended tier (requires DIVIOPS_WP_CLI_ALLOW env var) adds destructive or bulk-modifying ops: option update, post/post meta/term delete, search-replace, import, plugin activate/deactivate, eval-file. Filesystem-touching commands (`wp export`, `acf export/import`, `scf|acf json export/import`) are additionally constrained: path arguments must resolve under a safe root (defaults to `<WP_PATH>/.diviops-tmp/`, overridable via DIVIOPS_WP_CLI_SAFE_FS_ROOT, disable via DIVIOPS_WP_CLI_UNSAFE_FS=1); `wp export` and `scf json export` require an explicit `--dir=<path>` (or `--stdout`). In WP_CLI_CMD wrapper mode, DIVIOPS_WP_CLI_SAFE_FS_ROOT is required for FS-sensitive commands. Prefer the typed `diviops_scf_*` wrappers for SCF round-trips — they're easier to invoke and accept the same safe-root scoping. Use --format=json for structured output. Full allowlist + tier rationale + filesystem semantics in the MCP server README. Returns the standardized envelope { ok, data?, error: { code, message, hint? } }. Success payload: { stdout: string, stderr: string, exit_code: 0 }. Four failure modes converge on 'meta_wp_cli.command_failed' with error.data = { exit_code: number | null, stdout: string, stderr: string }: (a) numeric exit_code — wp-cli ran and exited non-zero; stdout/stderr are raw streams verbatim. (b) exit_code=null and message starts with 'wp-cli command terminated:' — execFile launched the child but it was killed (timeout or signal); stdout/stderr carry whatever streamed before the kill. (c) exit_code=null and message starts with 'wp-cli could not spawn:' — the OS refused to start the child (ENOENT/EACCES/EPERM); child never ran, stdout/stderr are empty. (d) exit_code=null and message is the rejection reason — pre-execution rejection by the allowlist / FS validator; rejection reason synthesized into error.data.stderr because the child never ran. A missing wp-cli configuration surfaces as 'meta_wp_cli.not_configured'. stdout is always passed through as a string (no server-side JSON parse) — pass --format=json and parse on the caller side when you want structured output.",
|
|
1711
|
+
description: "Run a WP-CLI command on the WordPress site. Requires WP_PATH env var (LOCAL_SITE_ID auto-detected from Local by Flywheel), or WP_CLI_CMD for containerized wrappers. Commands validated against a safety allowlist. Default tier covers read ops across options/posts/post-types/taxonomies/users/info/core/db, non-destructive writes (post/term create+update, post meta read/write, cache/rewrite/transient flush, `plugin update` from authenticated sources), ACF/SCF schema ops (`acf export/import/field-group list/get` plus SCF 6.8.4+ `scf json {status,sync,import,export}` and the `acf json …` aliases), and WXR export. Extended tier (requires DIVIOPS_WP_CLI_ALLOW env var) adds destructive or bulk-modifying ops: option update, post/post meta/term delete, search-replace, import, plugin activate/deactivate, eval-file. Filesystem-touching commands (`wp export`, `acf export/import`, `scf|acf json export/import`) are additionally constrained: path arguments must resolve under a safe root (defaults to `<WP_PATH>/.diviops-tmp/`, overridable via DIVIOPS_WP_CLI_SAFE_FS_ROOT, disable via DIVIOPS_WP_CLI_UNSAFE_FS=1); `wp export` and `scf json export` require an explicit `--dir=<path>` (or `--stdout`). In WP_CLI_CMD wrapper mode, DIVIOPS_WP_CLI_SAFE_FS_ROOT is required for FS-sensitive commands. Prefer the typed `diviops_scf_*` wrappers for SCF round-trips — they're easier to invoke and accept the same safe-root scoping. Use --format=json for structured output. Full allowlist + tier rationale + filesystem semantics in the MCP server README. Returns the standardized envelope { ok, data?, error: { code, message, hint? } }. Success payload: { stdout: string, stderr: string, exit_code: 0 }. Four failure modes converge on 'meta_wp_cli.command_failed' with error.data = { exit_code: number | null, stdout: string, stderr: string }: (a) numeric exit_code — wp-cli ran and exited non-zero; stdout/stderr are raw streams verbatim. (b) exit_code=null and message starts with 'wp-cli command terminated:' — execFile launched the child but it was killed (timeout or signal); stdout/stderr carry whatever streamed before the kill. (c) exit_code=null and message starts with 'wp-cli could not spawn:' — the OS refused to start the child (ENOENT/EACCES/EPERM); child never ran, stdout/stderr are empty. (d) exit_code=null and message is the rejection reason — pre-execution rejection by the allowlist / FS validator; rejection reason synthesized into error.data.stderr because the child never ran. A missing wp-cli configuration surfaces as 'meta_wp_cli.not_configured'. stdout is always passed through as a string (no server-side JSON parse) — pass --format=json and parse on the caller side when you want structured output.",
|
|
1712
1712
|
inputSchema: {
|
|
1713
1713
|
command: z
|
|
1714
1714
|
.string()
|
package/dist/wp-cli.js
CHANGED
|
@@ -62,9 +62,14 @@ const DEFAULT_COMMANDS = [
|
|
|
62
62
|
'rewrite flush',
|
|
63
63
|
// Export (reads data, writes to file only)
|
|
64
64
|
'export',
|
|
65
|
-
// Info (read-only)
|
|
65
|
+
// Info (read-only + non-destructive writes)
|
|
66
66
|
'cron event list',
|
|
67
67
|
'plugin list',
|
|
68
|
+
// `plugin update` runs from authenticated sources (WP plugin repo or licensed
|
|
69
|
+
// update server) — same trust model as `core check-update`. Unlike `plugin
|
|
70
|
+
// activate` / `plugin deactivate` (extended tier), it does not enable
|
|
71
|
+
// previously-disabled code paths; it refreshes already-installed plugins.
|
|
72
|
+
'plugin update',
|
|
68
73
|
'theme list',
|
|
69
74
|
'menu list',
|
|
70
75
|
'site url',
|