@respira/wordpress-mcp-server 6.11.0 → 6.11.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 CHANGED
@@ -602,6 +602,34 @@ Or install globally: `npm install -g @respira/wordpress-mcp-server` then use `{
602
602
 
603
603
  </details>
604
604
 
605
+ <details>
606
+ <summary><b>"HTML instead of JSON" / homepage redirect on every tool call</b></summary>
607
+
608
+ Some WordPress sites have plugin or theme rewrite rules that catch `/wp-json/[anything]` and rewrite the path to `index.php` *without* the `?rest_route=` query var. The result: WordPress's `redirect_canonical()` 301-redirects the request to the homepage (you'll see `x-redirect-by: WordPress` on the redirect chain), and the MCP server gets HTML back where it expected JSON.
609
+
610
+ Since v6.11.2, the MCP server **auto-detects this and transparently retries the call as `?rest_route=...` against the site root**. If the retry returns JSON, it sets a per-session sticky flag and routes every subsequent call directly through `?rest_route=`, with one stderr warning on first activation.
611
+
612
+ For sites where you know this rewrite shadowing is in play, you can skip the pretty-permalink probe entirely by adding `forceRestRoute: true` to the site config:
613
+
614
+ ```json
615
+ {
616
+ "sites": [
617
+ {
618
+ "id": "my-site",
619
+ "name": "My WordPress Site",
620
+ "url": "https://yoursite.com",
621
+ "apiKey": "respira_your-api-key",
622
+ "default": true,
623
+ "forceRestRoute": true
624
+ }
625
+ ]
626
+ }
627
+ ```
628
+
629
+ Run `wordpress_diagnose_connection` for triangulation — it now probes both the pretty path and the `?rest_route=` form, and reports `rest_route_fallback_worked`, `rest_route_fallback_active`, and `force_rest_route_configured`.
630
+
631
+ </details>
632
+
605
633
  <details>
606
634
  <summary><b>Tools not showing</b></summary>
607
635
 
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tests for the v6.11.2 `?rest_route=` auto-fallback that engages when a
3
+ * WordPress site has plugin/theme rewrite rules shadowing `/wp-json/[anything]`
4
+ * and triggering `redirect_canonical()` (homepage 301 with header
5
+ * `x-redirect-by: WordPress`).
6
+ *
7
+ * Mocks `axios.defaults.adapter` so both the per-instance clients AND the
8
+ * inline `axios.request()` call inside `retryViaRestRoute` go through the
9
+ * same fake. This works because dispatchRequest.js resolves the adapter as
10
+ * `config.adapter || defaults.adapter` per request — instances don't snapshot
11
+ * defaults at creation time.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=rest-route-fallback.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest-route-fallback.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/rest-route-fallback.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Tests for the v6.11.2 `?rest_route=` auto-fallback that engages when a
3
+ * WordPress site has plugin/theme rewrite rules shadowing `/wp-json/[anything]`
4
+ * and triggering `redirect_canonical()` (homepage 301 with header
5
+ * `x-redirect-by: WordPress`).
6
+ *
7
+ * Mocks `axios.defaults.adapter` so both the per-instance clients AND the
8
+ * inline `axios.request()` call inside `retryViaRestRoute` go through the
9
+ * same fake. This works because dispatchRequest.js resolves the adapter as
10
+ * `config.adapter || defaults.adapter` per request — instances don't snapshot
11
+ * defaults at creation time.
12
+ */
13
+ import { test } from 'node:test';
14
+ import assert from 'node:assert/strict';
15
+ import axios from 'axios';
16
+ import { WordPressClient } from '../wordpress-client.js';
17
+ const callLog = [];
18
+ let currentHandler = null;
19
+ const originalAdapter = axios.defaults.adapter;
20
+ function installMockAdapter() {
21
+ callLog.length = 0;
22
+ axios.defaults.adapter = ((config) => {
23
+ callLog.push({
24
+ method: (config.method || 'get').toLowerCase(),
25
+ url: config.url,
26
+ baseURL: config.baseURL,
27
+ params: config.params,
28
+ });
29
+ if (!currentHandler) {
30
+ return Promise.reject(new Error('no mock handler installed'));
31
+ }
32
+ const result = currentHandler(config);
33
+ return Promise.resolve(result).then((r) => ({
34
+ status: r.status,
35
+ statusText: 'OK',
36
+ headers: r.headers || {},
37
+ config,
38
+ data: r.data,
39
+ request: {},
40
+ }));
41
+ });
42
+ }
43
+ function restoreAdapter() {
44
+ axios.defaults.adapter = originalAdapter;
45
+ currentHandler = null;
46
+ }
47
+ function setHandler(h) {
48
+ currentHandler = h;
49
+ }
50
+ function buildConfig(extras = {}) {
51
+ return {
52
+ id: 'test-site',
53
+ name: 'Test Site',
54
+ url: 'https://example.com',
55
+ apiKey: 'respira_test_key',
56
+ ...extras,
57
+ };
58
+ }
59
+ // HTML body that mimics a WordPress homepage redirect from `redirect_canonical()`.
60
+ const HOMEPAGE_HTML = '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Climate Solutions News</title></head><body><h1>Welcome</h1></body></html>';
61
+ // -----------------------------------------------------------------------------
62
+ // Tests
63
+ // -----------------------------------------------------------------------------
64
+ test('rest_route fallback: pretty path returns HTML, fallback returns JSON, caller sees JSON transparently', async () => {
65
+ installMockAdapter();
66
+ try {
67
+ const client = new WordPressClient(buildConfig());
68
+ setHandler((config) => {
69
+ const url = config.url || '';
70
+ const baseURL = config.baseURL || '';
71
+ const fullUrl = url.startsWith('http') ? url : `${baseURL}${url}`;
72
+ if (/[?&]rest_route=/.test(fullUrl)) {
73
+ // Fallback succeeds with proper JSON.
74
+ return {
75
+ status: 200,
76
+ headers: { 'content-type': 'application/json' },
77
+ data: { pages: [{ id: 1, title: 'Home' }], total: 1, totalPages: 1 },
78
+ };
79
+ }
80
+ // Pretty path returns HTML.
81
+ return {
82
+ status: 200,
83
+ headers: { 'content-type': 'text/html; charset=UTF-8' },
84
+ data: HOMEPAGE_HTML,
85
+ };
86
+ });
87
+ const pages = await client.listPages({ perPage: 50 });
88
+ assert.deepEqual(pages, { pages: [{ id: 1, title: 'Home' }], total: 1, totalPages: 1 });
89
+ // Three adapter calls expected:
90
+ // 1. v2 negotiation probe to /wp-json/respira/v2/status → HTML
91
+ // 2. Auto-fallback to /?rest_route=/respira/v2/status → JSON (sticky flag trips)
92
+ // 3. listPages — interceptor rewrites directly to ?rest_route= → JSON
93
+ assert.equal(callLog.length, 3, `expected 3 adapter calls, got ${callLog.length}`);
94
+ // First call is the pretty path (against the v2 status endpoint).
95
+ const firstFullUrl = callLog[0].url.startsWith('http')
96
+ ? callLog[0].url
97
+ : `${callLog[0].baseURL || ''}${callLog[0].url}`;
98
+ assert.match(firstFullUrl, /\/wp-json\/respira\//, 'first call should be a pretty /wp-json/respira/ URL');
99
+ // The fallback retry was issued.
100
+ assert.ok(callLog.some((c) => /[?&]rest_route=/.test(c.url)), 'expected at least one ?rest_route= adapter call');
101
+ // No call should hit the pretty `/wp-json/respira/.../pages` path after the sticky flag tripped.
102
+ const callsAfterFallback = callLog.slice(2);
103
+ for (const c of callsAfterFallback) {
104
+ const full = c.url.startsWith('http') ? c.url : `${c.baseURL || ''}${c.url}`;
105
+ assert.match(full, /[?&]rest_route=/, `post-sticky call should be in rest_route form, got: ${full}`);
106
+ }
107
+ // Sticky flag should be on after a successful fallback.
108
+ assert.equal(client.useRestRouteFallback, true);
109
+ }
110
+ finally {
111
+ restoreAdapter();
112
+ }
113
+ });
114
+ test('rest_route fallback: HTML on both paths — error surfaces with both URLs', async () => {
115
+ installMockAdapter();
116
+ try {
117
+ const client = new WordPressClient(buildConfig());
118
+ setHandler(() => ({
119
+ status: 200,
120
+ headers: { 'content-type': 'text/html; charset=UTF-8' },
121
+ data: HOMEPAGE_HTML,
122
+ }));
123
+ let caught = null;
124
+ try {
125
+ await client.listPages();
126
+ }
127
+ catch (err) {
128
+ caught = err;
129
+ }
130
+ assert.ok(caught, 'expected listPages to throw when both pretty and rest_route return HTML');
131
+ assert.equal(caught.code, 'respira_html_instead_of_json');
132
+ assert.match(caught.message, /HTML instead of JSON/);
133
+ // Original pretty URL is in the error.
134
+ assert.ok(typeof caught.url === 'string' && caught.url.includes('/wp-json/'));
135
+ // Fallback URL is also surfaced.
136
+ assert.ok(typeof caught.fallbackUrl === 'string' && /rest_route=/.test(caught.fallbackUrl));
137
+ // Sticky flag stays off — fallback didn't succeed.
138
+ assert.equal(client.useRestRouteFallback, false);
139
+ }
140
+ finally {
141
+ restoreAdapter();
142
+ }
143
+ });
144
+ test('rest_route fallback: sticky flag — second call goes directly to ?rest_route=', async () => {
145
+ installMockAdapter();
146
+ try {
147
+ const client = new WordPressClient(buildConfig());
148
+ setHandler((config) => {
149
+ const url = config.url || '';
150
+ const baseURL = config.baseURL || '';
151
+ const fullUrl = url.startsWith('http') ? url : `${baseURL}${url}`;
152
+ if (/[?&]rest_route=/.test(fullUrl)) {
153
+ return {
154
+ status: 200,
155
+ headers: { 'content-type': 'application/json' },
156
+ data: { pages: [], total: 0, totalPages: 0 },
157
+ };
158
+ }
159
+ return {
160
+ status: 200,
161
+ headers: { 'content-type': 'text/html; charset=UTF-8' },
162
+ data: HOMEPAGE_HTML,
163
+ };
164
+ });
165
+ // First call: pretty path → HTML → fallback → JSON. Two adapter calls.
166
+ await client.listPages();
167
+ const callsAfterFirst = callLog.length;
168
+ assert.equal(client.useRestRouteFallback, true);
169
+ // Second call: should go directly to ?rest_route= — exactly one more adapter call.
170
+ await client.listPages();
171
+ const newCalls = callLog.slice(callsAfterFirst);
172
+ assert.equal(newCalls.length, 1, 'sticky flag should make the second call hit only one URL');
173
+ assert.match(newCalls[0].url, /[?&]rest_route=/, 'second call should be in rest_route form');
174
+ }
175
+ finally {
176
+ restoreAdapter();
177
+ }
178
+ });
179
+ test('forceRestRoute=true skips the pretty-permalink probe entirely', async () => {
180
+ installMockAdapter();
181
+ try {
182
+ const client = new WordPressClient(buildConfig({ forceRestRoute: true }));
183
+ setHandler((config) => {
184
+ const url = config.url || '';
185
+ const baseURL = config.baseURL || '';
186
+ const fullUrl = url.startsWith('http') ? url : `${baseURL}${url}`;
187
+ if (/[?&]rest_route=/.test(fullUrl)) {
188
+ return {
189
+ status: 200,
190
+ headers: { 'content-type': 'application/json' },
191
+ data: { pages: [{ id: 7 }], total: 1, totalPages: 1 },
192
+ };
193
+ }
194
+ // If anyone hits the pretty path while forceRestRoute is on, fail loud.
195
+ throw new Error(`pretty path was hit despite forceRestRoute=true: ${fullUrl}`);
196
+ });
197
+ assert.equal(client.useRestRouteFallback, true, 'sticky flag should be primed from forceRestRoute');
198
+ const pages = await client.listPages();
199
+ assert.deepEqual(pages, { pages: [{ id: 7 }], total: 1, totalPages: 1 });
200
+ // Every adapter call should be in rest_route form.
201
+ for (const c of callLog) {
202
+ assert.match(c.url, /[?&]rest_route=/, `expected rest_route form, got ${c.url}`);
203
+ }
204
+ }
205
+ finally {
206
+ restoreAdapter();
207
+ }
208
+ });
209
+ test('diagnose_connection reports rest_route_fallback_worked: true when applicable', async () => {
210
+ installMockAdapter();
211
+ try {
212
+ const client = new WordPressClient(buildConfig());
213
+ setHandler((config) => {
214
+ const url = config.url || '';
215
+ const baseURL = config.baseURL || '';
216
+ const fullUrl = url.startsWith('http') ? url : `${baseURL}${url}`;
217
+ // /wp-json/ root: returns the route listing JSON cleanly.
218
+ if (/\/wp-json\/?$/.test(fullUrl) || fullUrl.endsWith('/wp-json/')) {
219
+ return {
220
+ status: 200,
221
+ headers: { 'content-type': 'application/json' },
222
+ data: { namespaces: ['respira/v1'] },
223
+ };
224
+ }
225
+ // ?rest_route= form: returns JSON.
226
+ if (/[?&]rest_route=/.test(fullUrl)) {
227
+ return {
228
+ status: 200,
229
+ headers: { 'content-type': 'application/json' },
230
+ data: { ok: true, pong: true },
231
+ };
232
+ }
233
+ // Pretty respira path: returns HTML (homepage redirect).
234
+ if (/\/wp-json\/respira\//.test(fullUrl)) {
235
+ return {
236
+ status: 200,
237
+ headers: { 'content-type': 'text/html; charset=UTF-8' },
238
+ data: HOMEPAGE_HTML,
239
+ };
240
+ }
241
+ return {
242
+ status: 404,
243
+ headers: { 'content-type': 'application/json' },
244
+ data: { code: 'rest_no_route' },
245
+ };
246
+ });
247
+ const report = await client.diagnoseConnection({});
248
+ assert.equal(report.success, true);
249
+ assert.equal(report.rest_route_fallback_worked, true);
250
+ assert.equal(report.html_instead_of_json, true);
251
+ // The pretty respira_ping probe should be HTML, the rest_route ping should be JSON.
252
+ const pretty = report.outside_probes.find((p) => p.label === 'respira_ping');
253
+ const restRoute = report.outside_probes.find((p) => p.label === 'respira_ping_rest_route');
254
+ assert.ok(pretty, 'expected respira_ping probe in report');
255
+ assert.ok(restRoute, 'expected respira_ping_rest_route probe in report');
256
+ assert.equal(pretty.looks_like_html, true);
257
+ assert.equal(restRoute.looks_like_html, false);
258
+ // Recommendation about rewrite shadowing.
259
+ assert.ok(report.recommendations.some((r) => /rest_route/i.test(r) && /shadow/i.test(r)), 'expected a recommendation mentioning rest_route + shadowing');
260
+ }
261
+ finally {
262
+ restoreAdapter();
263
+ }
264
+ });
265
+ //# sourceMappingURL=rest-route-fallback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest-route-fallback.test.js","sourceRoot":"","sources":["../../src/__tests__/rest-route-fallback.test.ts"],"names":[],"mappings":"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"}
package/dist/server.d.ts CHANGED
@@ -60,6 +60,26 @@ export declare class RespiraWordPressServer {
60
60
  */
61
61
  private isAcfAvailable;
62
62
  private getWooCommerceTools;
63
+ /**
64
+ * camelCase → snake_case rename map (mcp-v6.11.1).
65
+ *
66
+ * Schemas advertise snake_case only. Handlers can read either form for one
67
+ * release; camelCase emits a deprecation warning to stderr and will be
68
+ * removed in mcp-v6.13.
69
+ *
70
+ * Mirrors both directions so wordpress-client.ts (which still reads
71
+ * camelCase fields like data.customCss / data.featuredMedia / args.edit_target
72
+ * before mapping them to plugin-side snake_case) keeps working unchanged.
73
+ * The wordpress-client surface is purely internal — its rename can ride
74
+ * along in a follow-up release without breaking callers.
75
+ */
76
+ private static readonly CAMEL_TO_SNAKE_PARAMS;
77
+ /**
78
+ * Normalize tool args so handlers see both snake_case (new, advertised in
79
+ * the schema) and camelCase (legacy, kept working for one release with a
80
+ * deprecation warning). Mutates the args object in place and returns it.
81
+ */
82
+ private normalizeArgsForBackCompat;
63
83
  private handleToolCall;
64
84
  private dispatchToolCall;
65
85
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,kBAAkB,CAAC;AAuBzE,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;IAEpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAW;IAErD;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;gBA4Bb,WAAW,EAAE,mBAAmB,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE;IAyPvE,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,oBAAoB;IAQ5B,gEAAgE;IAChE,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,aAAa;YA0LP,kBAAkB;YA6BlB,yBAAyB;IASvC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;YAyBd,QAAQ;IAmjEtB;;;;;;OAMG;IACH,yEAAyE;IACzE,OAAO,CAAC,mBAAmB,CAAoD;IAC/E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;YAEpC,oBAAoB;YAqDpB,2BAA2B;IAazC;;;;OAIG;YACW,cAAc;IAY5B,OAAO,CAAC,mBAAmB;YAwTb,cAAc;YAoBd,gBAAgB;IAqkB9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+QzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6UxB,GAAG;CAKV"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,kBAAkB,CAAC;AAuBzE,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;IAEpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAY;IAEtD;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;gBA4Bb,WAAW,EAAE,mBAAmB,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE;IAyPvE,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,oBAAoB;IAQ5B,gEAAgE;IAChE,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,aAAa;YA0LP,kBAAkB;YA6BlB,yBAAyB;IASvC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;YAyBd,QAAQ;IAmjEtB;;;;;;OAMG;IACH,yEAAyE;IACzE,OAAO,CAAC,mBAAmB,CAAoD;IAC/E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;YAEpC,oBAAoB;YAqDpB,2BAA2B;IAazC;;;;OAIG;YACW,cAAc;IAY5B,OAAO,CAAC,mBAAmB;IAwT3B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAe3C;IAEF;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;YAmCpB,cAAc;YA0Bd,gBAAgB;IAqkB9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+QzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6UxB,GAAG;CAKV"}