@respira/wordpress-mcp-server 8.1.5 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +7 -0
- package/TOOL_CATALOG.md +4 -1
- package/dist/__tests__/agent-signature-clientinfo.test.d.ts +2 -0
- package/dist/__tests__/agent-signature-clientinfo.test.d.ts.map +1 -0
- package/dist/__tests__/agent-signature-clientinfo.test.js +38 -0
- package/dist/__tests__/agent-signature-clientinfo.test.js.map +1 -0
- package/dist/__tests__/v2-negotiation-failure.test.d.ts +2 -0
- package/dist/__tests__/v2-negotiation-failure.test.d.ts.map +1 -0
- package/dist/__tests__/v2-negotiation-failure.test.js +104 -0
- package/dist/__tests__/v2-negotiation-failure.test.js.map +1 -0
- package/dist/__tests__/v2-negotiation-through-real-client.test.d.ts +2 -0
- package/dist/__tests__/v2-negotiation-through-real-client.test.d.ts.map +1 -0
- package/dist/__tests__/v2-negotiation-through-real-client.test.js +104 -0
- package/dist/__tests__/v2-negotiation-through-real-client.test.js.map +1 -0
- package/dist/agent-signature.d.ts +2 -1
- package/dist/agent-signature.d.ts.map +1 -1
- package/dist/agent-signature.js +64 -1
- package/dist/agent-signature.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +72 -0
- package/dist/server.js.map +1 -1
- package/dist/wordpress-client.d.ts +48 -0
- package/dist/wordpress-client.d.ts.map +1 -1
- package/dist/wordpress-client.js +95 -10
- package/dist/wordpress-client.js.map +1 -1
- package/package.json +1 -1
- package/tool-capabilities.json +40 -4
package/dist/server.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Provides tools for AI coding assistants to interact with WordPress sites
|
|
5
5
|
*/
|
|
6
6
|
import { Server } from '@modelcontextprotocol/server';
|
|
7
|
+
import { setMcpClientInfo } from './agent-signature.js';
|
|
7
8
|
import { serveStdio } from '@modelcontextprotocol/server/stdio';
|
|
8
9
|
import { execSync } from 'child_process';
|
|
9
10
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
@@ -347,6 +348,7 @@ Follow these on every site. They are what separates a great result from a frustr
|
|
|
347
348
|
5. Load schemas before writing. Use respira_get_builder_inline_schemas (or the per-builder schema tools) so attribute shapes are exact, not improvised.
|
|
348
349
|
6. Dropped styling is not a retry. If a write returns dropped_styling_hint or a STYLING DROPPED message, the builder did not recognize that setting. Do NOT re-send the same write. Pick a supported attribute or move that bit into a code block, then write again. (This is the single biggest source of wasted retries.)
|
|
349
350
|
7. Design-system first. When the builder exposes a design system, read it before building and reuse existing tokens instead of inventing styles: respira_bricks_design_system (Bricks global classes/colors/typography), respira_elementor_design_system (Elementor global colors/typography), and Divi 5 presets/color tokens. This keeps results on-brand and maintainable.
|
|
351
|
+
8. Honor and grow Site Memory. get_site_context / get_builder_info include a site_memory block: rules are hard constraints the plugin enforces (protected content refuses writes — never work around a refusal, tell the user), notes are the site's accumulated conventions. When the user states a durable preference or corrects a mistake worth not repeating, offer to save it with respira_remember so the next session starts warm.
|
|
350
352
|
|
|
351
353
|
## Tool naming
|
|
352
354
|
|
|
@@ -574,6 +576,18 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
574
576
|
|
|
575
577
|
21 tools for product management, categories, tags, orders, stock, and sales reports. All prefixed woocommerce_*.`,
|
|
576
578
|
});
|
|
579
|
+
// Capture the client's self-declared identity from the MCP initialize
|
|
580
|
+
// handshake (highest-trust attribution signal short of an env pin; the
|
|
581
|
+
// ps heuristic misfiles Claude Desktop as claude-code). Best-effort:
|
|
582
|
+
// attribution must never break a connection.
|
|
583
|
+
this.server.oninitialized = () => {
|
|
584
|
+
try {
|
|
585
|
+
const ci = this.server.getClientVersion?.();
|
|
586
|
+
if (ci?.name)
|
|
587
|
+
setMcpClientInfo(ci.name, ci.version);
|
|
588
|
+
}
|
|
589
|
+
catch { /* ignore */ }
|
|
590
|
+
};
|
|
577
591
|
this.versionChecker = new RespiraVersionChecker('@respira/wordpress-mcp-server', RespiraWordPressServer.MCP_SERVER_VERSION);
|
|
578
592
|
// RESPIRA_SITES env var: comma-separated hostnames to restrict visible sites.
|
|
579
593
|
// Used by MCP config packs and multisite configurations.
|
|
@@ -1860,6 +1874,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1860
1874
|
type: 'string',
|
|
1861
1875
|
description: 'URL slug (post_name). Example: "about-us" produces /about-us/.',
|
|
1862
1876
|
},
|
|
1877
|
+
excerpt: {
|
|
1878
|
+
type: 'string',
|
|
1879
|
+
description: 'Post excerpt (wp_posts.post_excerpt) — the "Excerpt"/"Zajawka" panel, RSS summaries and archive teasers. Do NOT pass this inside meta: an excerpt written as post meta reads back fine and renders nowhere.',
|
|
1880
|
+
},
|
|
1863
1881
|
custom_css: {
|
|
1864
1882
|
type: 'string',
|
|
1865
1883
|
description: 'Custom CSS for the page. Auto-detects builder: Divi → _et_pb_custom_css, Elementor → _elementor_page_settings.custom_css.',
|
|
@@ -2137,6 +2155,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
2137
2155
|
type: 'string',
|
|
2138
2156
|
description: 'URL slug (post_name). Example: "my-post" produces /my-post/.',
|
|
2139
2157
|
},
|
|
2158
|
+
excerpt: {
|
|
2159
|
+
type: 'string',
|
|
2160
|
+
description: 'Post excerpt (wp_posts.post_excerpt) — the "Excerpt"/"Zajawka" panel, RSS summaries and archive teasers. Do NOT pass this inside meta: an excerpt written as post meta reads back fine and renders nowhere.',
|
|
2161
|
+
},
|
|
2140
2162
|
author: {
|
|
2141
2163
|
description: 'Author (user id or user login). Requires edit_others_posts capability when different from the acting user.',
|
|
2142
2164
|
oneOf: [
|
|
@@ -4251,6 +4273,45 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
4251
4273
|
},
|
|
4252
4274
|
destructiveHint: true,
|
|
4253
4275
|
},
|
|
4276
|
+
// Site Memory (v8.3, Resonance) — persistent per-site memory that lives IN the
|
|
4277
|
+
// WordPress site, so it travels across clients (Claude, ChatGPT, Cursor) and
|
|
4278
|
+
// sessions. Notes/preferences/lessons are advisory context; rules are ENFORCED
|
|
4279
|
+
// by the plugin (writes to protected content are refused server-side). The
|
|
4280
|
+
// current memory arrives automatically in get_site_context / get_builder_info
|
|
4281
|
+
// under the site_memory key.
|
|
4282
|
+
{
|
|
4283
|
+
name: 'wordpress_remember',
|
|
4284
|
+
description: "Save a durable memory about this site to its persistent Site Memory. Use when the user states a preference (\"always use native modules, never raw HTML\"), corrects a mistake worth not repeating, or you discover a convention or environment quirk the next session should know. The memory is injected into site context for every future agent session, across all AI clients. Ask the user before saving anything they did not state themselves. type=rule creates an ENFORCED constraint (with optional rule.protect post_ids/slugs the plugin will refuse to write to) that only the site owner can later remove. Re-using a key updates the entry. Included on Builder and Studio plans.",
|
|
4285
|
+
inputSchema: {
|
|
4286
|
+
type: 'object',
|
|
4287
|
+
properties: {
|
|
4288
|
+
key: { type: 'string', description: 'Short slug identifying the memory, e.g. "brand-voice" or "never-touch-checkout". Lowercase letters/digits/hyphens, max 64 chars. Re-using a key updates it.' },
|
|
4289
|
+
type: { type: 'string', enum: ['fact', 'preference', 'lesson', 'rule'], description: 'fact = observed setup; preference = user taste; lesson = learned from a mistake or correction; rule = enforced constraint (only the owner can remove it — use for "never touch X" instructions).' },
|
|
4290
|
+
content: { type: 'string', description: 'The memory itself, max 500 chars. Distill: one clear imperative sentence beats a paragraph.' },
|
|
4291
|
+
rule: { type: 'object', description: 'Rules only. {"protect":{"post_ids":[12],"slugs":["checkout"]}} makes the plugin refuse agent writes/deletes to that content, including its duplicates.' },
|
|
4292
|
+
builder: { type: 'string', description: 'Optional builder fingerprint (e.g. "bricks") when the memory is builder-specific, so staleness is detectable after a rebuild.' },
|
|
4293
|
+
builder_version: { type: 'string', description: 'Optional builder version for the fingerprint.' },
|
|
4294
|
+
},
|
|
4295
|
+
required: ['key', 'content'],
|
|
4296
|
+
},
|
|
4297
|
+
},
|
|
4298
|
+
{
|
|
4299
|
+
name: 'wordpress_forget',
|
|
4300
|
+
description: 'Remove a stale entry from this site\'s persistent Site Memory by key. Enforced rules cannot be removed from a conversation — only by the site owner in the Respira dashboard (Site Memory) — so a refusal here is expected behavior, not an error to work around.',
|
|
4301
|
+
inputSchema: {
|
|
4302
|
+
type: 'object',
|
|
4303
|
+
properties: {
|
|
4304
|
+
key: { type: 'string', description: 'Memory key to forget (from wordpress_list_memory).' },
|
|
4305
|
+
},
|
|
4306
|
+
required: ['key'],
|
|
4307
|
+
},
|
|
4308
|
+
},
|
|
4309
|
+
{
|
|
4310
|
+
name: 'wordpress_list_memory',
|
|
4311
|
+
description: 'List everything stored in this site\'s persistent Site Memory: facts, preferences, lessons, and enforced rules, with source and last-updated metadata. The same content arrives automatically in get_site_context; use this when you need keys for updating or forgetting entries.',
|
|
4312
|
+
inputSchema: { type: 'object', properties: {} },
|
|
4313
|
+
readOnlyHint: true,
|
|
4314
|
+
},
|
|
4254
4315
|
{
|
|
4255
4316
|
name: 'wordpress_list_custom_posts',
|
|
4256
4317
|
description: 'List posts of a custom post type. Each row includes author ({id, login, display_name}), taxonomies map, and featured_media alongside id/title/slug/status/date/url.',
|
|
@@ -4424,6 +4485,10 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
4424
4485
|
type: 'string',
|
|
4425
4486
|
description: 'URL slug (post_name).',
|
|
4426
4487
|
},
|
|
4488
|
+
excerpt: {
|
|
4489
|
+
type: 'string',
|
|
4490
|
+
description: 'Post excerpt (wp_posts.post_excerpt) — the "Excerpt"/"Zajawka" panel, RSS summaries and archive teasers. Do NOT pass this inside meta: an excerpt written as post meta reads back fine and renders nowhere.',
|
|
4491
|
+
},
|
|
4427
4492
|
author: {
|
|
4428
4493
|
description: 'Author (user id or user login). Requires edit_others_posts capability when different from the acting user.',
|
|
4429
4494
|
oneOf: [
|
|
@@ -7261,6 +7326,13 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
7261
7326
|
}
|
|
7262
7327
|
case 'wordpress_delete_playbook':
|
|
7263
7328
|
return await client.callRestV1('DELETE', `/playbooks/${args.id}`);
|
|
7329
|
+
// Site Memory (v8.3, Resonance)
|
|
7330
|
+
case 'wordpress_remember':
|
|
7331
|
+
return await client.callRestV1('POST', '/memory', { ...args, source: 'agent' });
|
|
7332
|
+
case 'wordpress_forget':
|
|
7333
|
+
return await client.callRestV1('DELETE', `/memory/${args.key}`);
|
|
7334
|
+
case 'wordpress_list_memory':
|
|
7335
|
+
return await client.callRestV1('GET', '/memory');
|
|
7264
7336
|
case 'wordpress_list_custom_posts':
|
|
7265
7337
|
return await client.listCustomPosts(args.type, args);
|
|
7266
7338
|
case 'wordpress_get_custom_post':
|