@respira/wordpress-mcp-server 8.2.6 → 8.2.8

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 CHANGED
@@ -5,6 +5,22 @@ 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.2.8] - 2026-08-11
9
+
10
+ ### Fixed
11
+
12
+ - **`apply_builder_patch` and `update_element`'s `unset` operation had no valid shape a strict client could use.** The write-path handling for removing a stale attribute alias (e.g. a Divi 5 button's leftover `content` key) was already correct; the served tool schema for `operations`/`updates` never documented `unset` as a real property, so a client validating against the schema had nowhere to put it. Both tool definitions now declare it, matching the plugin's REST route and native ability registry, which already did.
13
+
14
+ ## [8.2.7] - 2026-08-10
15
+
16
+ ### Fixed
17
+
18
+ - **A host briefly refusing one request read as "your site is down".** When a server in front of WordPress returned a 5xx, the message said the site might be down, misconfigured or behind a failing proxy, and told you to check that it loads in a browser. On a site that is up and serving hundreds of other calls that is a wild goose chase, and it is the one people take: a customer was told a firewall was blocking Respira when his host had shed six requests out of roughly a thousand, in two short bursts, all during heavy page building. 503 and 504 now read as what they are, a host declining a single request, usually the account's cap on simultaneous PHP processes, with the advice that helps: wait a few seconds, retry, and space out large builder writes. The message also now says that because the response came from in front of WordPress, WordPress never ran and nothing was written, so the call is safe to repeat.
19
+
20
+ ### Added
21
+
22
+ - Three Figma conversion skills: figma-to-divi, figma-to-bricks and figma-to-gutenberg.
23
+
8
24
  ## [8.2.6] - 2026-08-10
9
25
 
10
26
  ### Fixed
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transient-5xx-guidance.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transient-5xx-guidance.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/transient-5xx-guidance.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { isReplaySafeRetry } from '../wordpress-client.js';
4
+ // A customer was told a firewall was blocking Respira. It was not. His host had
5
+ // shed six requests out of roughly a thousand, in two short bursts, every one of
6
+ // them a heavy builder write, while the site served everything else normally.
7
+ //
8
+ // Two things produced that wrong diagnosis, and both are ours:
9
+ //
10
+ // 1. the message for a non-WordPress 5xx said "the site may be down ... check
11
+ // that the site loads normally in a browser", which is a wild goose chase
12
+ // on a site that is up;
13
+ // 2. the write never retried, because writes only retry when the response
14
+ // advertises idempotency support and no plugin build has ever sent that
15
+ // header. See the note on the retry test below.
16
+ test('a read retries on any 5xx', () => {
17
+ for (const status of [500, 502, 503, 504]) {
18
+ assert.equal(isReplaySafeRetry({ method: 'GET', status }), true, `GET ${status}`);
19
+ }
20
+ });
21
+ test('a write does NOT retry on a 5xx unless the site advertises idempotency', () => {
22
+ // This is correct in isolation: replaying a write whose commit state is
23
+ // unknown can apply an edit twice.
24
+ for (const status of [502, 503, 504]) {
25
+ assert.equal(isReplaySafeRetry({ method: 'POST', status }), false, `POST ${status} must not blind-retry`);
26
+ assert.equal(isReplaySafeRetry({ method: 'POST', status, idempotencySupported: true }), true, `POST ${status} may retry when the site advertises replay safety`);
27
+ }
28
+ });
29
+ test('a write does not retry on a 500, even with idempotency support', () => {
30
+ // 500 means WordPress ran and failed. Repeating it fails again more slowly.
31
+ assert.equal(isReplaySafeRetry({ method: 'POST', status: 500, idempotencySupported: true }), false);
32
+ });
33
+ // KNOWN GAP, deliberately recorded rather than asserted away.
34
+ //
35
+ // `idempotencySupported` is read from the `x-respira-idempotency-supported`
36
+ // response header. No plugin build has ever sent that header: the replay
37
+ // machinery (write receipts, stable call_id, idempotent_replay) lives on the
38
+ // native/streamable transport, not the REST path this client uses. So the
39
+ // branch above is unreachable in production and every npm-connected write dies
40
+ // on the first transient 5xx.
41
+ //
42
+ // Closing it means the plugin advertising the header AND deduplicating a
43
+ // replayed call_id on the REST write path. Until then the client compensates by
44
+ // telling the agent the write did not commit, so it can retry deliberately.
45
+ test('the retry branch that never fires is still specified, so closing the gap has a target', () => {
46
+ assert.equal(isReplaySafeRetry({ method: 'POST', status: 503, idempotencySupported: true }), true, 'when the plugin starts advertising idempotency, writes must retry on 503');
47
+ });
48
+ //# sourceMappingURL=transient-5xx-guidance.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transient-5xx-guidance.test.js","sourceRoot":"","sources":["../../src/__tests__/transient-5xx-guidance.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,gFAAgF;AAChF,iFAAiF;AACjF,8EAA8E;AAC9E,EAAE;AACF,+DAA+D;AAC/D,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,6BAA6B;AAC7B,4EAA4E;AAC5E,6EAA6E;AAC7E,qDAAqD;AAErD,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACrC,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,MAAM,EAAE,CAAC,CAAC;IACpF,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wEAAwE,EAAE,GAAG,EAAE;IAClF,wEAAwE;IACxE,mCAAmC;IACnC,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,KAAK,CACV,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAC7C,KAAK,EACL,QAAQ,MAAM,uBAAuB,CACtC,CAAC;QACF,MAAM,CAAC,KAAK,CACV,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,EACzE,IAAI,EACJ,QAAQ,MAAM,mDAAmD,CAClE,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gEAAgE,EAAE,GAAG,EAAE;IAC1E,4EAA4E;IAC5E,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AACtG,CAAC,CAAC,CAAC;AAEH,8DAA8D;AAC9D,EAAE;AACF,4EAA4E;AAC5E,yEAAyE;AACzE,6EAA6E;AAC7E,0EAA0E;AAC1E,+EAA+E;AAC/E,8BAA8B;AAC9B,EAAE;AACF,yEAAyE;AACzE,gFAAgF;AAChF,4EAA4E;AAC5E,IAAI,CAAC,uFAAuF,EAAE,GAAG,EAAE;IACjG,MAAM,CAAC,KAAK,CACV,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,EAC9E,IAAI,EACJ,0EAA0E,CAC3E,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,kBAAkB,CAAC;AAsHzE;;;;;;;;;;;;;;;;GAgBG;AACH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,MAAM,CAoBhF;AAiID,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,YAAY,CAA4B;IAChD,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAA4B;IAChD,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB,CAAS;IACpC,iFAAiF;IACjF,OAAO,CAAC,iBAAiB,CAAK;IAC9B,iFAAiF;IACjF,OAAO,CAAC,mBAAmB,CAAgC;IAE3D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;IAEhE;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;gBA4Bb,WAAW,EAAE,mBAAmB,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE;IA6VvE,OAAO,CAAC,cAAc;IAItB;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IA4BrB,gEAAgE;IAChE,OAAO,CAAC,aAAa;IAUrB;;;;;;OAMG;YACW,UAAU;IA2CxB;;;;;;;;;;;;;;OAcG;YACW,WAAW;IAiJzB;;;;;;;;;OASG;YACW,kBAAkB;IA4OhC;;;;;;;;OAQG;IACH,OAAO,CAAC,qBAAqB;IAgE7B;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;YACW,qBAAqB;YAiBrB,kBAAkB;IA6FhC,yFAAyF;IACzF,OAAO,CAAC,gBAAgB;IASxB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,6BAA6B;IA0BrC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,yBAAyB;IA+BjC,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,aAAa;YAmQP,kBAAkB;YA6BlB,yBAAyB;IASvC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;YAyBd,QAAQ;IA02GtB;;;;;;OAMG;IACH;;;;;;;;;;;;;oDAagD;IAChD,OAAO,CAAC,mBAAmB,CAAoD;IAC/E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAU;IAC1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAS;IAC1D;;mDAE+C;IAC/C,OAAO,CAAC,0BAA0B,CAAoC;IAEtE;;;;;;;;OAQG;YACW,0BAA0B;YAyC1B,oBAAoB;YA6CpB,2BAA2B;IAQzC;;;;OAIG;YACW,cAAc;IAQ5B,OAAO,CAAC,mBAAmB;IAw9C3B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAe3C;IAEF;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;YAmCpB,cAAc;IA4G5B,oEAAoE;IACpE,OAAO,CAAC,iBAAiB;IAoBzB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,eAAe;YAuCT,gBAAgB;IAk4C9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkZzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6UxB,GAAG;CA+CV"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,kBAAkB,CAAC;AAsHzE;;;;;;;;;;;;;;;;GAgBG;AACH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,MAAM,CAoBhF;AAiID,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,YAAY,CAA4B;IAChD,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAA4B;IAChD,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB,CAAS;IACpC,iFAAiF;IACjF,OAAO,CAAC,iBAAiB,CAAK;IAC9B,iFAAiF;IACjF,OAAO,CAAC,mBAAmB,CAAgC;IAE3D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;IAEhE;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;gBA4Bb,WAAW,EAAE,mBAAmB,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE;IA6VvE,OAAO,CAAC,cAAc;IAItB;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IA4BrB,gEAAgE;IAChE,OAAO,CAAC,aAAa;IAUrB;;;;;;OAMG;YACW,UAAU;IA2CxB;;;;;;;;;;;;;;OAcG;YACW,WAAW;IAiJzB;;;;;;;;;OASG;YACW,kBAAkB;IA4OhC;;;;;;;;OAQG;IACH,OAAO,CAAC,qBAAqB;IAgE7B;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;YACW,qBAAqB;YAiBrB,kBAAkB;IA6FhC,yFAAyF;IACzF,OAAO,CAAC,gBAAgB;IASxB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,6BAA6B;IA0BrC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,yBAAyB;IA+BjC,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,aAAa;YAmQP,kBAAkB;YA6BlB,yBAAyB;IASvC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;YAyBd,QAAQ;IAi3GtB;;;;;;OAMG;IACH;;;;;;;;;;;;;oDAagD;IAChD,OAAO,CAAC,mBAAmB,CAAoD;IAC/E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAU;IAC1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAS;IAC1D;;mDAE+C;IAC/C,OAAO,CAAC,0BAA0B,CAAoC;IAEtE;;;;;;;;OAQG;YACW,0BAA0B;YAyC1B,oBAAoB;YA6CpB,2BAA2B;IAQzC;;;;OAIG;YACW,cAAc;IAQ5B,OAAO,CAAC,mBAAmB;IAw9C3B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAe3C;IAEF;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;YAmCpB,cAAc;IA4G5B,oEAAoE;IACpE,OAAO,CAAC,iBAAiB;IAoBzB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,eAAe;YAuCT,gBAAgB;IAk4C9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA0ZzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6UxB,GAAG;CA+CV"}
package/dist/server.js CHANGED
@@ -3185,7 +3185,14 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
3185
3185
  },
3186
3186
  updates: {
3187
3187
  type: 'object',
3188
- description: 'Patch to merge into the matched element. Same shape as wordpress_update_module.updates: { content?: string, attributes?: object, ...flat_settings_keys? }. Flat keys (admin_label, background_color, font_size, ...) route through the adapter\'s deep-set helper.',
3188
+ description: 'Patch to merge into the matched element. Same shape as wordpress_update_module.updates: { content?: string, attributes?: object, unset?: string[], ...flat_settings_keys? }. Flat keys (admin_label, background_color, font_size, ...) route through the adapter\'s deep-set helper. `unset` is a STRUCTURED array of attribute key names to remove (e.g. ["content"] drops a stale content alias attribute so the module\'s real content attribute takes precedence) — never a single string, and never merged in as literal data.',
3189
+ properties: {
3190
+ unset: {
3191
+ type: 'array',
3192
+ items: { type: 'string' },
3193
+ description: 'Attribute key names to remove from the matched element (e.g. a stale content alias). A single string is also accepted and treated as a one-element list.',
3194
+ },
3195
+ },
3189
3196
  },
3190
3197
  },
3191
3198
  },
@@ -8200,7 +8207,14 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
8200
8207
  identifier_value: { type: 'string', description: 'Value to match' },
8201
8208
  updates: {
8202
8209
  type: 'object',
8203
- description: 'Key-value pairs of settings to update on the matched element. Do NOT put `edit_target` or `confirm_live_edit` in this object; pass them as top-level params (otherwise they get persisted as element settings).',
8210
+ description: 'Key-value pairs of settings to update on the matched element. Do NOT put `edit_target` or `confirm_live_edit` in this object; pass them as top-level params (otherwise they get persisted as element settings). `unset` is a STRUCTURED array of attribute key names to remove (e.g. ["content"] drops a stale content alias attribute so a different one takes precedence) — never a single string, and never treated as a value to write.',
8211
+ properties: {
8212
+ unset: {
8213
+ type: 'array',
8214
+ items: { type: 'string' },
8215
+ description: 'Attribute key names to remove from the matched element. A single string is also accepted and treated as a one-element list.',
8216
+ },
8217
+ },
8204
8218
  },
8205
8219
  edit_target: {
8206
8220
  type: 'string',