claude-plugin-wordpress-manager 2.12.1 → 2.12.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/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  All notable changes to the WordPress Manager plugin for Claude Code.
4
4
 
5
+ ## [2.12.2] — 2026-03-01
6
+
7
+ ### Fixed — Structured Data Tools Rewrite
8
+
9
+ **sd_inject: content-block approach (replaces broken meta approach)**
10
+ - JSON-LD now injected as `<!-- wp:html -->` block in post content
11
+ - No mu-plugin or `register_post_meta()` required — works out of the box
12
+ - Idempotent: re-injecting same @type replaces existing block, no duplicates
13
+
14
+ **sd_list_schemas: content scanning (replaces broken meta scanning)**
15
+ - Scans post content for `<script type="application/ld+json">` blocks
16
+ - No longer depends on unregistered `_schema_json_ld` meta field
17
+
18
+ **sd_validate: multi-block support**
19
+ - Now finds ALL JSON-LD scripts on a page (not just the first)
20
+ - Reports per-schema issues with type labels
21
+
22
+ ### Validated end-to-end on opencactus.com
23
+ - sd_inject Article on post 2348: ✅
24
+ - sd_list_schemas finds injected schema: ✅
25
+ - sd_validate on live URL: ✅ (2 schemas detected)
26
+ - Idempotency verified: ✅
27
+
5
28
  ## [2.12.1] — 2026-03-01
6
29
 
7
30
  ### Fixed — Critical MCP Tool Parameter Passing
package/docs/GUIDE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # WordPress Manager - Guida Completa per Utenti e Amministratori
2
2
 
3
- **Versione:** 2.12.1
3
+ **Versione:** 2.12.2
4
4
  **Ultimo aggiornamento:** 2026-03-01
5
5
  **Repository:** https://github.com/morrealev/wordpress-manager
6
6
 
@@ -110,7 +110,7 @@ WordPress Manager e un plugin per **Claude Code** (la CLI ufficiale di Anthropic
110
110
  ### Componenti del Plugin
111
111
 
112
112
  ```
113
- wordpress-manager/ # v2.12.1
113
+ wordpress-manager/ # v2.12.2
114
114
  +-- .claude-plugin/plugin.json # Manifest
115
115
  +-- .mcp.json # Server MCP bundled
116
116
  +-- LICENSE # MIT + GPL-2.0-or-later
@@ -181,8 +181,8 @@ wordpress-manager/ # v2.12.1
181
181
  | +-- [DISTRIBUZIONE DIRETTA + CONTENT FACTORY - 4 skill]
182
182
  | +-- wp-linkedin/ # LinkedIn direct posting e analytics (v2.10.0)
183
183
  | +-- wp-twitter/ # Twitter/X direct posting e thread (v2.10.0)
184
- | +-- wp-structured-data/ # Schema.org/JSON-LD validation e injection (v2.12.1)
185
- | +-- wp-content-generation/ # AI content generation pipeline (v2.12.1)
184
+ | +-- wp-structured-data/ # Schema.org/JSON-LD validation e injection (v2.12.2)
185
+ | +-- wp-content-generation/ # AI content generation pipeline (v2.12.2)
186
186
  +-- hooks/ # 12 hook di sicurezza
187
187
  | +-- hooks.json # 10 prompt + 2 command
188
188
  | +-- scripts/ # Script per hook command-type
@@ -619,9 +619,9 @@ IDEAZIONE -> BOZZA -> REVISIONE -> OTTIMIZZAZIONE -> PUBBLICAZIONE -> MONITORAGG
619
619
 
620
620
  **AI Content Optimization** (v2.6.0): Pipeline AI-driven in 5 step per ottimizzazione contenuti: headline scoring → readability analysis (Flesch-Kincaid) → SEO scoring → meta optimization → content freshness check. Include bulk triage per analisi rapida di tutti i contenuti con classificazione Quick Wins / Maintain / Deep Review / Outdated. Usa la skill `wp-content-optimization`.
621
621
 
622
- **AI Content Generation** (v2.12.1): Pipeline completa 7 step per generare contenuti da zero: brief → keyword research (GSC se disponibile) → outline (4 pattern: standard, tutorial, listicle, FAQ) → draft (calibrato sulla voce del sito) → SEO optimize → structured data injection → publish as draft. Procedure-based, usa tool MCP esistenti (`wp/v2`, `gsc_*`, `sd_*`). Usa la skill `wp-content-generation`.
622
+ **AI Content Generation** (v2.12.2): Pipeline completa 7 step per generare contenuti da zero: brief → keyword research (GSC se disponibile) → outline (4 pattern: standard, tutorial, listicle, FAQ) → draft (calibrato sulla voce del sito) → SEO optimize → structured data injection → publish as draft. Procedure-based, usa tool MCP esistenti (`wp/v2`, `gsc_*`, `sd_*`). Usa la skill `wp-content-generation`.
623
623
 
624
- **Structured Data Management** (v2.12.1): Gestione completa Schema.org/JSON-LD con 3 tool MCP dedicati: `sd_validate` (validazione markup via URL o inline), `sd_inject` (iniezione JSON-LD nei post), `sd_list_schemas` (audit sitewide). 8 tipi supportati: Article, Product, FAQ, HowTo, LocalBusiness, Event, Organization, BreadcrumbList. Usa la skill `wp-structured-data`.
624
+ **Structured Data Management** (v2.12.2): Gestione completa Schema.org/JSON-LD con 3 tool MCP dedicati: `sd_validate` (validazione markup via URL o inline), `sd_inject` (iniezione JSON-LD nei post), `sd_list_schemas` (audit sitewide). 8 tipi supportati: Article, Product, FAQ, HowTo, LocalBusiness, Event, Organization, BreadcrumbList. Usa la skill `wp-structured-data`.
625
625
 
626
626
  **Skill correlata**: `wp-content`, `wp-i18n`, `wp-content-repurposing`, `wp-programmatic-seo`, `wp-search-console`, `wp-content-optimization`, `wp-content-generation`, `wp-structured-data`
627
627
 
@@ -965,7 +965,7 @@ Le skill di sviluppo provengono da due fonti:
965
965
  - **3 skill strategia + SEO internazionale** (MIT) aggiunte in v2.3.0: Programmatic SEO, Content-Commerce Attribution, Multi-Language Network.
966
966
  - **3 skill distribuzione + SEO avanzato** (MIT) aggiunte in v2.4.0-v2.6.0: Social/Email Distribution, Google Search Console, AI Content Optimization.
967
967
  - **3 skill analytics + alerting + automazione** (MIT) aggiunte in v2.7.0-v2.9.0: Analytics (GA4/Plausible/CWV), Smart Alerting (Slack/SendGrid severity routing), Automated Workflows (triggers + multi-channel actions).
968
- - **4 skill distribuzione diretta + content factory** (MIT) aggiunte in v2.10.0-v2.12.1: LinkedIn Direct (posting + analytics), Twitter/X Direct (tweet + thread + metriche), Structured Data (Schema.org/JSON-LD), AI Content Generation (pipeline 7-step).
968
+ - **4 skill distribuzione diretta + content factory** (MIT) aggiunte in v2.10.0-v2.12.2: LinkedIn Direct (posting + analytics), Twitter/X Direct (tweet + thread + metriche), Structured Data (Schema.org/JSON-LD), AI Content Generation (pipeline 7-step).
969
969
 
970
970
  ### Il Router Unificato
971
971
 
@@ -1194,7 +1194,7 @@ Aggiunte in v2.7.0-v2.9.0, queste skill completano il layer Observability + Auto
1194
1194
 
1195
1195
  ### Panoramica Skills Distribuzione Diretta + Content Factory (4)
1196
1196
 
1197
- Aggiunte in v2.10.0-v2.12.1, queste skill completano il WCOP portando il punteggio totale da 8.8/10 a 9.2/10 (Distribution 9/10, Content Factory 10/10).
1197
+ Aggiunte in v2.10.0-v2.12.2, queste skill completano il WCOP portando il punteggio totale da 8.8/10 a 9.2/10 (Distribution 9/10, Content Factory 10/10).
1198
1198
 
1199
1199
  | Skill | Si attiva quando... | Risorse | Agent dedicato |
1200
1200
  |-------|---------------------|---------|----------------|
@@ -1238,8 +1238,8 @@ Le skill includono 31 script Node.js (`.mjs`) che eseguono analisi automatica de
1238
1238
  | `workflow_inspect.mjs` | Action channel config, automation plugins, custom REST endpoints, WP-Cron, webhook config (v2.9.0) |
1239
1239
  | `linkedin_inspect.mjs` | LinkedIn access token, profile info, API connectivity (v2.10.0) |
1240
1240
  | `twitter_inspect.mjs` | Twitter Bearer token, OAuth tokens, API v2 connectivity (v2.10.0) |
1241
- | `schema_inspect.mjs` | SEO plugins (Yoast, Rank Math), existing JSON-LD in theme, Schema Pro (v2.12.1) |
1242
- | `content_gen_inspect.mjs` | REST access, GSC credentials, pipeline step availability (v2.12.1) |
1241
+ | `schema_inspect.mjs` | SEO plugins (Yoast, Rank Math), existing JSON-LD in theme, Schema Pro (v2.12.2) |
1242
+ | `content_gen_inspect.mjs` | REST access, GSC credentials, pipeline step availability (v2.12.2) |
1243
1243
 
1244
1244
  ### WordPress Playground — Ambienti Disposable
1245
1245
 
@@ -2363,6 +2363,6 @@ bash ~/.claude/plugins/local/wordpress-manager/scripts/validate-wp-operation.sh
2363
2363
 
2364
2364
  ---
2365
2365
 
2366
- *Guida v2.12.1 — WordPress Manager Plugin per Claude Code*
2366
+ *Guida v2.12.2 — WordPress Manager Plugin per Claude Code*
2367
2367
  *Ultimo aggiornamento: 2026-03-01*
2368
2368
  *WCOP Score: 8.8/10 (Tier 4+5 complete)*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plugin-wordpress-manager",
3
- "version": "2.12.1",
3
+ "version": "2.12.2",
4
4
  "description": "Unified WordPress management and development plugin for Claude Code. Orchestrates Hostinger MCP, WP REST API bridge (148 tools incl. 30 WooCommerce + 10 Multisite + 4 Webhooks + 7 Mailchimp + 5 Buffer + 6 SendGrid + 8 GSC + 6 GA4 + 4 Plausible + 4 CWV + 3 Slack + 4 Workflows + 5 LinkedIn + 5 Twitter + 3 Schema), and WordPress.com MCP with 43 skills, 12 agents, and security hooks. v2.12.0 completes WCOP Tier 6+7 with content generation + structured data.",
5
5
  "author": {
6
6
  "name": "vinmor",
@@ -72,29 +72,35 @@ export const schemaHandlers = {
72
72
  return { toolResult: { isError: true, content: [{ type: "text", text: "Invalid JSON in markup parameter." }] } };
73
73
  }
74
74
  } else {
75
- // Fetch URL and extract JSON-LD
75
+ // Fetch URL and extract ALL JSON-LD blocks
76
76
  const response = await axios.get(url, { timeout: 15000 });
77
77
  const html = response.data;
78
- const jsonLdMatch = html.match(/<script[^>]*type="application\/ld\+json"[^>]*>([\s\S]*?)<\/script>/i);
79
- if (!jsonLdMatch) {
80
- return { toolResult: { content: [{ type: "text", text: JSON.stringify({ valid: false, error: "No JSON-LD found on page", url }, null, 2) }] } };
78
+ const jsonLdRegex = /<script[^>]*type="application\/ld\+json"[^>]*>([\s\S]*?)<\/script>/gi;
79
+ const allJsonLd = [];
80
+ let match;
81
+ while ((match = jsonLdRegex.exec(html)) !== null) {
82
+ try {
83
+ const parsed = JSON.parse(match[1]);
84
+ if (Array.isArray(parsed)) allJsonLd.push(...parsed);
85
+ else allJsonLd.push(parsed);
86
+ } catch { /* skip invalid JSON-LD blocks */ }
81
87
  }
82
- try {
83
- jsonLd = JSON.parse(jsonLdMatch[1]);
84
- } catch {
85
- return { toolResult: { content: [{ type: "text", text: JSON.stringify({ valid: false, error: "Invalid JSON-LD on page", url }, null, 2) }] } };
88
+ if (allJsonLd.length === 0) {
89
+ return { toolResult: { content: [{ type: "text", text: JSON.stringify({ valid: false, error: "No valid JSON-LD found on page", url }, null, 2) }] } };
86
90
  }
91
+ jsonLd = allJsonLd;
87
92
  }
88
93
 
89
94
  // Basic Schema.org validation
90
95
  const issues = [];
91
96
  const schemas = Array.isArray(jsonLd) ? jsonLd : [jsonLd];
92
97
  for (const schema of schemas) {
93
- if (!schema['@context'] || !schema['@context'].includes('schema.org')) {
94
- issues.push('Missing or invalid @context (should include schema.org)');
98
+ const schemaLabel = schema['@type'] || '(unnamed)';
99
+ if (!schema['@context'] || !String(schema['@context']).includes('schema.org')) {
100
+ issues.push(`${schemaLabel}: Missing or invalid @context (should include schema.org)`);
95
101
  }
96
102
  if (!schema['@type']) {
97
- issues.push('Missing @type');
103
+ issues.push(`${schemaLabel}: Missing @type`);
98
104
  }
99
105
  }
100
106
 
@@ -119,12 +125,22 @@ export const schemaHandlers = {
119
125
  '@context': 'https://schema.org',
120
126
  '@type': schema_type,
121
127
  ...schema_data,
122
- });
123
- // Store JSON-LD in post meta via WordPress REST API
124
- const response = await makeWordPressRequest('POST', `posts/${post_id}`, {
125
- meta: { _schema_json_ld: jsonLd },
126
- });
127
- return { toolResult: { content: [{ type: "text", text: JSON.stringify({ success: true, post_id, schema_type, stored: true }, null, 2) }] } };
128
+ }, null, 2);
129
+ const scriptBlock = `\n<!-- wp:html -->\n<script type="application/ld+json">\n${jsonLd}\n</script>\n<!-- /wp:html -->`;
130
+ // Fetch current post content
131
+ const post = await makeWordPressRequest('GET', `posts/${post_id}`, { _fields: 'content', context: 'edit' });
132
+ let content = post.content?.raw || post.content?.rendered || '';
133
+ // Remove existing JSON-LD block for this schema type if present
134
+ const existingPattern = new RegExp(
135
+ `\\n?<!-- wp:html -->\\n<script type="application/ld\\+json">\\n[\\s\\S]*?"@type":\\s*"${schema_type}"[\\s\\S]*?</script>\\n<!-- /wp:html -->`,
136
+ 'g'
137
+ );
138
+ content = content.replace(existingPattern, '');
139
+ // Append new JSON-LD block
140
+ content = content.trimEnd() + scriptBlock;
141
+ // Update post
142
+ await makeWordPressRequest('POST', `posts/${post_id}`, { content });
143
+ return { toolResult: { content: [{ type: "text", text: JSON.stringify({ success: true, post_id, schema_type, method: 'content_block', note: 'JSON-LD injected as wp:html block in post content' }, null, 2) }] } };
128
144
  } catch (error) {
129
145
  const errorMessage = error.response?.data?.message || error.message;
130
146
  return { toolResult: { isError: true, content: [{ type: "text", text: `Error injecting schema: ${errorMessage}` }] } };
@@ -134,19 +150,24 @@ export const schemaHandlers = {
134
150
  sd_list_schemas: async (params) => {
135
151
  try {
136
152
  const { schema_type } = params;
137
- // Fetch recent posts and check for JSON-LD in meta
138
- const posts = await makeWordPressRequest('GET', 'posts', { per_page: 100, _fields: 'id,title,meta' });
153
+ // Fetch posts and scan content for JSON-LD script blocks
154
+ const posts = await makeWordPressRequest('GET', 'posts', { per_page: 100, _fields: 'id,title,content' });
139
155
  const schemas = {};
156
+ const jsonLdRegex = /<script[^>]*type="application\/ld\+json"[^>]*>([\s\S]*?)<\/script>/gi;
140
157
  for (const post of posts) {
141
- const meta = post.meta?._schema_json_ld;
142
- if (meta) {
158
+ const content = post.content?.rendered || '';
159
+ let match;
160
+ while ((match = jsonLdRegex.exec(content)) !== null) {
143
161
  try {
144
- const parsed = JSON.parse(meta);
145
- const type = parsed['@type'] || 'Unknown';
146
- if (schema_type && type !== schema_type) continue;
147
- if (!schemas[type]) schemas[type] = { count: 0, posts: [] };
148
- schemas[type].count++;
149
- schemas[type].posts.push({ id: post.id, title: post.title?.rendered });
162
+ const parsed = JSON.parse(match[1]);
163
+ const items = Array.isArray(parsed) ? parsed : [parsed];
164
+ for (const item of items) {
165
+ const type = item['@type'] || 'Unknown';
166
+ if (schema_type && type !== schema_type) continue;
167
+ if (!schemas[type]) schemas[type] = { count: 0, posts: [] };
168
+ schemas[type].count++;
169
+ schemas[type].posts.push({ id: post.id, title: post.title?.rendered });
170
+ }
150
171
  } catch { /* skip invalid JSON */ }
151
172
  }
152
173
  }