@respira/wordpress-mcp-server 8.1.4 → 8.1.5
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/CHANGELOG.md +6 -0
- package/README.md +5 -5
- package/dist/__tests__/oq-put-fallback-403.test.d.ts +2 -0
- package/dist/__tests__/oq-put-fallback-403.test.d.ts.map +1 -0
- package/dist/__tests__/oq-put-fallback-403.test.js +59 -0
- package/dist/__tests__/oq-put-fallback-403.test.js.map +1 -0
- package/dist/server.js +8 -8
- package/dist/server.js.map +1 -1
- package/dist/wordpress-client.d.ts +15 -0
- package/dist/wordpress-client.d.ts.map +1 -1
- package/dist/wordpress-client.js +40 -5
- package/dist/wordpress-client.js.map +1 -1
- package/package.json +2 -2
- package/skills/migrate-elementor-to-breakdance/SKILL.md +1 -1
- package/skills/migrate-elementor-to-bricks/SKILL.md +1 -1
- package/skills/migrate-elementor-to-gutenberg/SKILL.md +1 -1
- package/skills/migrate-elementor-to-oxygen/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ All notable changes to Respira WordPress MCP Server will be documented in this f
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [8.1.5] - 2026-08-01
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Updates now succeed on hosts that block PUT at the edge.** Managed hosts and WAFs commonly allow `GET` and `POST` but reject `PUT`, `PATCH` and `DELETE` before the request ever reaches WordPress. The result was every update failing with "403 Forbidden from the web server (not WordPress)" while creating pages and reading them worked perfectly, which sends you looking at plugin whitelists, permalink settings, CDN exceptions and User-Agent rules when the only thing that actually mattered was the HTTP verb. Respira already shipped the fallback that fixes this, retrying the write as a `POST`, but it only fired on `404` (the old-plugin case), so it never ran for the hosts that needed it. It now also fires on `403` and `405`, at all five write paths. Reported, root-caused and verified live against a real write by O.Q., who also identified the exact shape of the fix.
|
|
13
|
+
|
|
8
14
|
## [8.1.4] - 2026-07-30
|
|
9
15
|
|
|
10
16
|
### Fixed
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<h1 align="center">Respira WordPress MCP Server</h1>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
|
-
<strong>198 MCP tools, 303 with the WooCommerce add-on.
|
|
10
|
+
<strong>198 MCP tools, 303 with the WooCommerce add-on. 17 page builders and the native Site Editor. MCP 2026-07-28 with legacy-client support.</strong><br>
|
|
11
11
|
Element-level editing, full page creation, HTML-to-builder conversion with rendering fidelity validation, per-site tool governance, storefront design intelligence, stock images, bulk operations — all through one MCP server.
|
|
12
12
|
</p>
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<a href="https://www.npmjs.com/package/@respira/wordpress-mcp-server"><img src="https://img.shields.io/npm/v/@respira/wordpress-mcp-server.svg?style=flat-square&color=10b981" alt="npm version"></a>
|
|
16
16
|
<a href="https://www.npmjs.com/package/@respira/wordpress-mcp-server"><img src="https://img.shields.io/npm/dm/@respira/wordpress-mcp-server.svg?style=flat-square" alt="npm downloads"></a>
|
|
17
17
|
<img src="https://img.shields.io/badge/tools-303-10b981?style=flat-square" alt="303 Tools with WooCommerce">
|
|
18
|
-
<img src="https://img.shields.io/badge/builders-
|
|
18
|
+
<img src="https://img.shields.io/badge/builders-17-10b981?style=flat-square" alt="16 Page Builders">
|
|
19
19
|
<img src="https://img.shields.io/badge/TypeScript-100%25-blue?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript">
|
|
20
20
|
</p>
|
|
21
21
|
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
Other WordPress MCP servers wrap the REST API. They can create posts and pages, but **they can't touch your page builder content**.
|
|
35
35
|
|
|
36
|
-
Respira includes a WordPress plugin that gives AI **native access** to
|
|
36
|
+
Respira includes a WordPress plugin that gives AI **native access** to 17 page builders, plus element-level precision, full page creation from structure, HTML-to-builder conversion, storefront design intelligence, stock image search, and bulk operations across hundreds of pages.
|
|
37
37
|
|
|
38
38
|
### New in 8.1: MCP 2026-07-28, without breaking existing clients
|
|
39
39
|
|
|
@@ -129,7 +129,7 @@ The MCP server exposes 198 core tools and 103 WooCommerce add-on tools. It autom
|
|
|
129
129
|
|
|
130
130
|
| Capability | Respira | Typical WordPress MCP servers |
|
|
131
131
|
|---|---|---|
|
|
132
|
-
| Page builder support | **
|
|
132
|
+
| Page builder support | **17 builders** (incl. Spectra, Kadence, GenerateBlocks) | None, or a single builder |
|
|
133
133
|
| Element-level find/update/move/remove | **Yes** | No |
|
|
134
134
|
| Build full pages from structure | **Yes** | No |
|
|
135
135
|
| Convert HTML to native builder | **Yes** | No |
|
|
@@ -817,6 +817,6 @@ MIT © [Respira](https://respira.press)
|
|
|
817
817
|
---
|
|
818
818
|
|
|
819
819
|
<p align="center">
|
|
820
|
-
<strong>198 core tools, 303 with WooCommerce.
|
|
820
|
+
<strong>198 core tools, 303 with WooCommerce. 17 builders. The AI infrastructure layer for WordPress.</strong><br>
|
|
821
821
|
<a href="https://respira.press">respira.press</a>
|
|
822
822
|
</p>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oq-put-fallback-403.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/oq-put-fallback-403.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { isRetryableAsPost } from '../wordpress-client.js';
|
|
4
|
+
/**
|
|
5
|
+
* O.Q. field report, 2026-07-31.
|
|
6
|
+
*
|
|
7
|
+
* Managed hosts and WAFs allow GET and POST but block PUT, PATCH and DELETE at
|
|
8
|
+
* the edge, before WordPress sees the request. Every update failed with
|
|
9
|
+
* "403 Forbidden from the web server (not WordPress)" while creation and reads
|
|
10
|
+
* worked, which sends the customer chasing plugin whitelists and CDN rules when
|
|
11
|
+
* the only thing that mattered was the HTTP verb.
|
|
12
|
+
*
|
|
13
|
+
* The client already had a PUT-to-POST fallback. It only fired on 404.
|
|
14
|
+
*
|
|
15
|
+
* THE PART THIS TEST EXISTS FOR: widening the status check alone does NOT fix
|
|
16
|
+
* it, and a build plus the existing suite passed while the bug was still live.
|
|
17
|
+
* The response interceptor rewrites a non-WordPress 403 into a coded Error via
|
|
18
|
+
* codedError(), which sets `name` and does NOT carry `response` across. So a
|
|
19
|
+
* predicate that only looks at `error.response.status` never fires on the exact
|
|
20
|
+
* case the fallback exists for. Proven against a real site with a shim
|
|
21
|
+
* returning 403 on PUT: the status-only version still failed the write, the
|
|
22
|
+
* shape-aware version completed it.
|
|
23
|
+
*/
|
|
24
|
+
describe('isRetryableAsPost', () => {
|
|
25
|
+
it('fires on the transformed non-WordPress 403, which has no response object', () => {
|
|
26
|
+
// Exactly what codedError() produces for a host-level block.
|
|
27
|
+
const coded = new Error('Site blocked: ... 403 Forbidden from the web server (not WordPress).');
|
|
28
|
+
coded.name = 'http_403_non_wordpress';
|
|
29
|
+
assert.equal(isRetryableAsPost(coded), true);
|
|
30
|
+
});
|
|
31
|
+
it('a status-only check would have missed that error', () => {
|
|
32
|
+
const coded = new Error('Site blocked');
|
|
33
|
+
coded.name = 'http_403_non_wordpress';
|
|
34
|
+
// Documents why the first attempt at this fix did nothing.
|
|
35
|
+
assert.equal(coded.response, undefined);
|
|
36
|
+
});
|
|
37
|
+
it('still fires on the original raw 404 case (old plugin, no v2 route)', () => {
|
|
38
|
+
assert.equal(isRetryableAsPost({ response: { status: 404 } }), true);
|
|
39
|
+
});
|
|
40
|
+
it('fires on a raw 403 and 405', () => {
|
|
41
|
+
assert.equal(isRetryableAsPost({ response: { status: 403 } }), true);
|
|
42
|
+
assert.equal(isRetryableAsPost({ response: { status: 405 } }), true);
|
|
43
|
+
});
|
|
44
|
+
it('does NOT retry a 403 raised by WordPress itself', () => {
|
|
45
|
+
// A real permission decision. Retrying as POST just fails again, slower,
|
|
46
|
+
// and would muddy the error the user needs to see.
|
|
47
|
+
const wpDenied = new Error('Sorry, you are not allowed to edit this post.');
|
|
48
|
+
wpDenied.name = 'rest_cannot_edit';
|
|
49
|
+
assert.equal(isRetryableAsPost(wpDenied), false);
|
|
50
|
+
});
|
|
51
|
+
it('does not retry unrelated failures', () => {
|
|
52
|
+
assert.equal(isRetryableAsPost({ response: { status: 500 } }), false);
|
|
53
|
+
assert.equal(isRetryableAsPost({ response: { status: 401 } }), false);
|
|
54
|
+
assert.equal(isRetryableAsPost(new Error('network down')), false);
|
|
55
|
+
assert.equal(isRetryableAsPost(undefined), false);
|
|
56
|
+
assert.equal(isRetryableAsPost(null), false);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=oq-put-fallback-403.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oq-put-fallback-403.test.js","sourceRoot":"","sources":["../../src/__tests__/oq-put-fallback-403.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,6DAA6D;QAC7D,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAChG,KAAK,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACtC,2DAA2D;QAC3D,MAAM,CAAC,KAAK,CAAE,KAAa,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,yEAAyE;QACzE,mDAAmD;QACnD,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC5E,QAAQ,CAAC,IAAI,GAAG,kBAAkB,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -1836,7 +1836,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1836
1836
|
},
|
|
1837
1837
|
{
|
|
1838
1838
|
name: 'wordpress_update_page',
|
|
1839
|
-
description: 'Update PAGE-LEVEL fields (title, status, slug, full HTML content replacement, custom CSS). For editing SPECIFIC elements WITHIN a page (text widgets, images, buttons, headings), use respira_update_element instead — it is element-aware, builder-aware, snapshot-safe, and works across all
|
|
1839
|
+
description: 'Update PAGE-LEVEL fields (title, status, slug, full HTML content replacement, custom CSS). For editing SPECIFIC elements WITHIN a page (text widgets, images, buttons, headings), use respira_update_element instead — it is element-aware, builder-aware, snapshot-safe, and works across all 17 page builders. Use respira_update_page only when you need to replace the entire content body, change the page title/slug/status, or set page-level metadata. When direct editing is enabled and you target an original page, Respira returns a confirmation_required preflight by default so you can choose live/original or duplicate.',
|
|
1840
1840
|
inputSchema: {
|
|
1841
1841
|
type: 'object',
|
|
1842
1842
|
properties: {
|
|
@@ -2293,7 +2293,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
2293
2293
|
properties: {
|
|
2294
2294
|
builder: {
|
|
2295
2295
|
type: 'string',
|
|
2296
|
-
description: 'Optional. Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. Omit to auto-detect the active site builder.',
|
|
2296
|
+
description: 'Optional. Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery, flatsome, spectra, kadence, generateblocks, greenshift. Omit to auto-detect the active site builder.',
|
|
2297
2297
|
},
|
|
2298
2298
|
page_id: {
|
|
2299
2299
|
type: 'number',
|
|
@@ -2312,7 +2312,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
2312
2312
|
properties: {
|
|
2313
2313
|
builder: {
|
|
2314
2314
|
type: 'string',
|
|
2315
|
-
description: 'Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. Use get_builder_info to discover the active builder first.',
|
|
2315
|
+
description: 'Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery, flatsome, spectra, kadence, generateblocks, greenshift. Use get_builder_info to discover the active builder first.',
|
|
2316
2316
|
},
|
|
2317
2317
|
page_id: {
|
|
2318
2318
|
type: 'number',
|
|
@@ -2376,13 +2376,13 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
2376
2376
|
},
|
|
2377
2377
|
{
|
|
2378
2378
|
name: 'wordpress_inject_builder_content',
|
|
2379
|
-
description: 'REPLACE (or append to) the entire page builder layout. WARNING: By default this REPLACES all existing content (use mode:"append" to add content without destroying existing elements). For editing a single module, use wordpress_update_module instead. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. For Divi, divi_version is required ("4" or "5"). Replacing a page that already has content with mode="replace" requires confirm_replace=true, else returns 409 respira_replace_confirmation_required. Alternatives: mode="append" to add to existing content, or edit_target="live" to overwrite the live page directly. The gate prevents silent data loss.\n\nCanonical Divi 5 nested shape: `content: [{ type: "section", children: [{ type: "row", children: [{ type: "column", children: [{ type: "heading", settings: {...} }] }] }] }]` (rows/cols/columns/modules/elements/innerBlocks also accepted as `children` aliases). Each Divi module needs its render-critical attr in `settings` (e.g. heading→title, text→content, button→button_text); the plugin names any missing one via `respira_divi_required_attrs_missing`.',
|
|
2379
|
+
description: 'REPLACE (or append to) the entire page builder layout. WARNING: By default this REPLACES all existing content (use mode:"append" to add content without destroying existing elements). For editing a single module, use wordpress_update_module instead. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery, flatsome, spectra, kadence, generateblocks, greenshift. For Divi, divi_version is required ("4" or "5"). Replacing a page that already has content with mode="replace" requires confirm_replace=true, else returns 409 respira_replace_confirmation_required. Alternatives: mode="append" to add to existing content, or edit_target="live" to overwrite the live page directly. The gate prevents silent data loss.\n\nCanonical Divi 5 nested shape: `content: [{ type: "section", children: [{ type: "row", children: [{ type: "column", children: [{ type: "heading", settings: {...} }] }] }] }]` (rows/cols/columns/modules/elements/innerBlocks also accepted as `children` aliases). Each Divi module needs its render-critical attr in `settings` (e.g. heading→title, text→content, button→button_text); the plugin names any missing one via `respira_divi_required_attrs_missing`.',
|
|
2380
2380
|
inputSchema: {
|
|
2381
2381
|
type: 'object',
|
|
2382
2382
|
properties: {
|
|
2383
2383
|
builder: {
|
|
2384
2384
|
type: 'string',
|
|
2385
|
-
description: 'Builder identifier. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery.',
|
|
2385
|
+
description: 'Builder identifier. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery, flatsome, spectra, kadence, generateblocks, greenshift.',
|
|
2386
2386
|
},
|
|
2387
2387
|
page_id: {
|
|
2388
2388
|
type: 'number',
|
|
@@ -2442,7 +2442,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
2442
2442
|
properties: {
|
|
2443
2443
|
builder: {
|
|
2444
2444
|
type: 'string',
|
|
2445
|
-
description: 'Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery.',
|
|
2445
|
+
description: 'Builder name. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery, flatsome, spectra, kadence, generateblocks, greenshift.',
|
|
2446
2446
|
},
|
|
2447
2447
|
page_id: {
|
|
2448
2448
|
type: 'number',
|
|
@@ -7843,7 +7843,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
7843
7843
|
// --- Element Operations ---
|
|
7844
7844
|
{
|
|
7845
7845
|
name: 'wordpress_find_element',
|
|
7846
|
-
description: 'Find an element in a page by ID, type, CSS class, text content, or uncode_shortcode_id. This is the PRIMARY tool for locating content to edit — use it instead of searching the database or reading PHP files. Works with all
|
|
7846
|
+
description: 'Find an element in a page by ID, type, CSS class, text content, or uncode_shortcode_id. This is the PRIMARY tool for locating content to edit — use it instead of searching the database or reading PHP files. Works with all 17 page builders. Use identifier_type "content" to search by visible text (e.g. find a heading containing "2025" to update a year). On WPBakery + Uncode pages, prefer identifier_type "uncode_shortcode_id" — the id is stable across saves and theme updates while class lists and admin labels drift. Returns matching element(s) with their position, settings, and element ID for use with update_element.',
|
|
7847
7847
|
inputSchema: {
|
|
7848
7848
|
type: 'object',
|
|
7849
7849
|
properties: {
|
|
@@ -7865,7 +7865,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
7865
7865
|
},
|
|
7866
7866
|
{
|
|
7867
7867
|
name: 'wordpress_update_element',
|
|
7868
|
-
description: 'Update settings or content on a specific element in a page. This is the PRIMARY tool for making content changes (text edits, style changes, image swaps, link updates, etc.). Works with all
|
|
7868
|
+
description: 'Update settings or content on a specific element in a page. This is the PRIMARY tool for making content changes (text edits, style changes, image swaps, link updates, etc.). Works with all 17 page builders. First use find_element to locate the element, then pass the same identifier here with the updates object containing the new values. On WPBakery + Uncode pages, prefer identifier_type "uncode_shortcode_id" for stable round-trip matching. Response includes target_id, original_id, edit_target ("live" or "duplicate"), is_duplicate, duplicate_created and post_status so the caller can never mistake a duplicate-routed write for a live-page change.\n\nLive-edit confirmation: when respira_allow_direct_edit=1 AND the post is a published original, the first call returns `status: "confirmation_required"` with a `next_call_examples` payload. Re-call with the suggested `edit_target` (and `confirm_live_edit: true` for the live path) to acknowledge. Both params are exposed at the top level here so autonomous flows can complete the handshake through MCP without polluting the `updates` object.',
|
|
7869
7869
|
inputSchema: {
|
|
7870
7870
|
type: 'object',
|
|
7871
7871
|
properties: {
|