claude-plugin-wordpress-manager 2.4.0 → 2.9.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.
Files changed (83) hide show
  1. package/.claude-plugin/plugin.json +10 -3
  2. package/CHANGELOG.md +103 -0
  3. package/agents/wp-content-strategist.md +104 -0
  4. package/agents/wp-monitoring-agent.md +44 -0
  5. package/agents/wp-site-manager.md +19 -0
  6. package/docs/GUIDE.md +183 -23
  7. package/docs/plans/2026-03-01-tier4-5-implementation.md +1783 -0
  8. package/docs/plans/2026-03-01-tier4-5-observability-automation-design.md +426 -0
  9. package/docs/plans/2026-03-01-wcop-reassessment-v2.6.0.md +403 -0
  10. package/hooks/hooks.json +9 -0
  11. package/package.json +19 -3
  12. package/servers/wp-rest-bridge/build/tools/comments.d.ts +6 -6
  13. package/servers/wp-rest-bridge/build/tools/cwv.d.ts +3 -0
  14. package/servers/wp-rest-bridge/build/tools/cwv.js +196 -0
  15. package/servers/wp-rest-bridge/build/tools/ga4.d.ts +3 -0
  16. package/servers/wp-rest-bridge/build/tools/ga4.js +323 -0
  17. package/servers/wp-rest-bridge/build/tools/gsc.d.ts +3 -0
  18. package/servers/wp-rest-bridge/build/tools/gsc.js +354 -0
  19. package/servers/wp-rest-bridge/build/tools/index.d.ts +38 -38
  20. package/servers/wp-rest-bridge/build/tools/index.js +18 -0
  21. package/servers/wp-rest-bridge/build/tools/media.d.ts +2 -2
  22. package/servers/wp-rest-bridge/build/tools/multisite-sites.d.ts +2 -2
  23. package/servers/wp-rest-bridge/build/tools/plausible.d.ts +3 -0
  24. package/servers/wp-rest-bridge/build/tools/plausible.js +207 -0
  25. package/servers/wp-rest-bridge/build/tools/plugin-repository.d.ts +1 -1
  26. package/servers/wp-rest-bridge/build/tools/search.d.ts +2 -2
  27. package/servers/wp-rest-bridge/build/tools/slack.d.ts +3 -0
  28. package/servers/wp-rest-bridge/build/tools/slack.js +129 -0
  29. package/servers/wp-rest-bridge/build/tools/unified-content.d.ts +8 -8
  30. package/servers/wp-rest-bridge/build/tools/unified-taxonomies.d.ts +4 -4
  31. package/servers/wp-rest-bridge/build/tools/users.d.ts +6 -6
  32. package/servers/wp-rest-bridge/build/tools/wc-coupons.d.ts +1 -1
  33. package/servers/wp-rest-bridge/build/tools/wc-customers.d.ts +3 -3
  34. package/servers/wp-rest-bridge/build/tools/wc-orders.d.ts +4 -4
  35. package/servers/wp-rest-bridge/build/tools/wc-products.d.ts +8 -8
  36. package/servers/wp-rest-bridge/build/tools/wc-webhooks.d.ts +4 -4
  37. package/servers/wp-rest-bridge/build/tools/wc-workflows.d.ts +3 -0
  38. package/servers/wp-rest-bridge/build/tools/wc-workflows.js +222 -0
  39. package/servers/wp-rest-bridge/build/wordpress.d.ts +23 -0
  40. package/servers/wp-rest-bridge/build/wordpress.js +178 -0
  41. package/servers/wp-rest-bridge/package.json +1 -0
  42. package/skills/wordpress-router/SKILL.md +1 -1
  43. package/skills/wordpress-router/references/decision-tree.md +12 -2
  44. package/skills/wp-alerting/SKILL.md +142 -0
  45. package/skills/wp-alerting/references/alert-thresholds.md +79 -0
  46. package/skills/wp-alerting/references/escalation-paths.md +92 -0
  47. package/skills/wp-alerting/references/report-scheduling.md +142 -0
  48. package/skills/wp-alerting/references/slack-integration.md +109 -0
  49. package/skills/wp-alerting/scripts/alerting_inspect.mjs +150 -0
  50. package/skills/wp-analytics/SKILL.md +158 -0
  51. package/skills/wp-analytics/references/analytics-dashboards.md +83 -0
  52. package/skills/wp-analytics/references/cwv-monitoring.md +101 -0
  53. package/skills/wp-analytics/references/ga4-integration.md +76 -0
  54. package/skills/wp-analytics/references/plausible-setup.md +92 -0
  55. package/skills/wp-analytics/references/traffic-attribution.md +92 -0
  56. package/skills/wp-analytics/scripts/analytics_inspect.mjs +153 -0
  57. package/skills/wp-content/SKILL.md +1 -0
  58. package/skills/wp-content-attribution/SKILL.md +3 -0
  59. package/skills/wp-content-optimization/SKILL.md +173 -0
  60. package/skills/wp-content-optimization/references/content-freshness.md +234 -0
  61. package/skills/wp-content-optimization/references/headline-optimization.md +171 -0
  62. package/skills/wp-content-optimization/references/meta-optimization.md +243 -0
  63. package/skills/wp-content-optimization/references/readability-analysis.md +201 -0
  64. package/skills/wp-content-optimization/references/seo-content-scoring.md +245 -0
  65. package/skills/wp-content-optimization/scripts/content_optimization_inspect.mjs +237 -0
  66. package/skills/wp-content-workflows/SKILL.md +142 -0
  67. package/skills/wp-content-workflows/references/content-lifecycle-hooks.md +131 -0
  68. package/skills/wp-content-workflows/references/multi-channel-actions.md +151 -0
  69. package/skills/wp-content-workflows/references/schedule-triggers.md +118 -0
  70. package/skills/wp-content-workflows/references/trigger-management.md +159 -0
  71. package/skills/wp-content-workflows/references/wp-action-hooks.md +114 -0
  72. package/skills/wp-content-workflows/scripts/workflow_inspect.mjs +202 -0
  73. package/skills/wp-monitoring/SKILL.md +3 -0
  74. package/skills/wp-programmatic-seo/SKILL.md +2 -0
  75. package/skills/wp-search-console/SKILL.md +122 -0
  76. package/skills/wp-search-console/references/competitor-gap-analysis.md +226 -0
  77. package/skills/wp-search-console/references/content-seo-feedback.md +181 -0
  78. package/skills/wp-search-console/references/gsc-setup.md +110 -0
  79. package/skills/wp-search-console/references/indexing-management.md +182 -0
  80. package/skills/wp-search-console/references/keyword-tracking.md +181 -0
  81. package/skills/wp-search-console/scripts/search_console_inspect.mjs +178 -0
  82. package/skills/wp-social-email/SKILL.md +1 -0
  83. package/skills/wp-webhooks/SKILL.md +1 -0
@@ -14,7 +14,7 @@ declare const wcListOrdersSchema: z.ZodObject<{
14
14
  per_page: number;
15
15
  order: "asc" | "desc";
16
16
  status?: "trash" | "pending" | "any" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded" | "failed" | undefined;
17
- orderby?: "slug" | "date" | "id" | "title" | undefined;
17
+ orderby?: "id" | "slug" | "date" | "title" | undefined;
18
18
  after?: string | undefined;
19
19
  before?: string | undefined;
20
20
  customer?: number | undefined;
@@ -22,7 +22,7 @@ declare const wcListOrdersSchema: z.ZodObject<{
22
22
  page?: number | undefined;
23
23
  per_page?: number | undefined;
24
24
  status?: "trash" | "pending" | "any" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded" | "failed" | undefined;
25
- orderby?: "slug" | "date" | "id" | "title" | undefined;
25
+ orderby?: "id" | "slug" | "date" | "title" | undefined;
26
26
  order?: "asc" | "desc" | undefined;
27
27
  after?: string | undefined;
28
28
  before?: string | undefined;
@@ -39,11 +39,11 @@ declare const wcUpdateOrderStatusSchema: z.ZodObject<{
39
39
  id: z.ZodNumber;
40
40
  status: z.ZodEnum<["pending", "processing", "on-hold", "completed", "cancelled", "refunded", "failed"]>;
41
41
  }, "strict", z.ZodTypeAny, {
42
- status: "pending" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded" | "failed";
43
42
  id: number;
44
- }, {
45
43
  status: "pending" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded" | "failed";
44
+ }, {
46
45
  id: number;
46
+ status: "pending" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded" | "failed";
47
47
  }>;
48
48
  declare const wcListOrderNotesSchema: z.ZodObject<{
49
49
  order_id: z.ZodNumber;
@@ -17,17 +17,17 @@ declare const wcListProductsSchema: z.ZodObject<{
17
17
  order: "asc" | "desc";
18
18
  search?: string | undefined;
19
19
  status?: "draft" | "pending" | "private" | "publish" | "any" | undefined;
20
- orderby?: "slug" | "date" | "id" | "title" | "price" | "popularity" | "rating" | undefined;
20
+ orderby?: "id" | "slug" | "date" | "title" | "price" | "popularity" | "rating" | undefined;
21
21
  category?: number | undefined;
22
22
  tag?: number | undefined;
23
23
  sku?: string | undefined;
24
24
  stock_status?: "instock" | "outofstock" | "onbackorder" | undefined;
25
25
  }, {
26
+ search?: string | undefined;
26
27
  page?: number | undefined;
27
28
  per_page?: number | undefined;
28
- search?: string | undefined;
29
29
  status?: "draft" | "pending" | "private" | "publish" | "any" | undefined;
30
- orderby?: "slug" | "date" | "id" | "title" | "price" | "popularity" | "rating" | undefined;
30
+ orderby?: "id" | "slug" | "date" | "title" | "price" | "popularity" | "rating" | undefined;
31
31
  order?: "asc" | "desc" | undefined;
32
32
  category?: number | undefined;
33
33
  tag?: number | undefined;
@@ -74,8 +74,8 @@ declare const wcCreateProductSchema: z.ZodObject<{
74
74
  src: string;
75
75
  }>, "many">>;
76
76
  }, "strict", z.ZodTypeAny, {
77
- status: "draft" | "pending" | "private" | "publish";
78
77
  type: "simple" | "grouped" | "external" | "variable";
78
+ status: "draft" | "pending" | "private" | "publish";
79
79
  name: string;
80
80
  categories?: {
81
81
  id: number;
@@ -95,8 +95,8 @@ declare const wcCreateProductSchema: z.ZodObject<{
95
95
  }[] | undefined;
96
96
  }, {
97
97
  name: string;
98
- status?: "draft" | "pending" | "private" | "publish" | undefined;
99
98
  type?: "simple" | "grouped" | "external" | "variable" | undefined;
99
+ status?: "draft" | "pending" | "private" | "publish" | undefined;
100
100
  categories?: {
101
101
  id: number;
102
102
  }[] | undefined;
@@ -174,13 +174,13 @@ declare const wcListProductCategoriesSchema: z.ZodObject<{
174
174
  order: "asc" | "desc";
175
175
  search?: string | undefined;
176
176
  parent?: number | undefined;
177
- orderby?: "slug" | "id" | "name" | "count" | undefined;
177
+ orderby?: "id" | "slug" | "name" | "count" | undefined;
178
178
  }, {
179
+ search?: string | undefined;
179
180
  page?: number | undefined;
180
181
  per_page?: number | undefined;
181
- search?: string | undefined;
182
182
  parent?: number | undefined;
183
- orderby?: "slug" | "id" | "name" | "count" | undefined;
183
+ orderby?: "id" | "slug" | "name" | "count" | undefined;
184
184
  order?: "asc" | "desc" | undefined;
185
185
  }>;
186
186
  declare const wcListProductVariationsSchema: z.ZodObject<{
@@ -17,14 +17,14 @@ declare const wcCreateWebhookSchema: z.ZodObject<{
17
17
  name: string;
18
18
  topic: string;
19
19
  delivery_url: string;
20
- status?: "active" | "paused" | "disabled" | undefined;
21
20
  secret?: string | undefined;
21
+ status?: "active" | "paused" | "disabled" | undefined;
22
22
  }, {
23
23
  name: string;
24
24
  topic: string;
25
25
  delivery_url: string;
26
- status?: "active" | "paused" | "disabled" | undefined;
27
26
  secret?: string | undefined;
27
+ status?: "active" | "paused" | "disabled" | undefined;
28
28
  }>;
29
29
  declare const wcUpdateWebhookSchema: z.ZodObject<{
30
30
  id: z.ZodNumber;
@@ -35,18 +35,18 @@ declare const wcUpdateWebhookSchema: z.ZodObject<{
35
35
  status: z.ZodOptional<z.ZodEnum<["active", "paused", "disabled"]>>;
36
36
  }, "strict", z.ZodTypeAny, {
37
37
  id: number;
38
+ secret?: string | undefined;
38
39
  status?: "active" | "paused" | "disabled" | undefined;
39
40
  name?: string | undefined;
40
41
  topic?: string | undefined;
41
42
  delivery_url?: string | undefined;
42
- secret?: string | undefined;
43
43
  }, {
44
44
  id: number;
45
+ secret?: string | undefined;
45
46
  status?: "active" | "paused" | "disabled" | undefined;
46
47
  name?: string | undefined;
47
48
  topic?: string | undefined;
48
49
  delivery_url?: string | undefined;
49
- secret?: string | undefined;
50
50
  }>;
51
51
  declare const wcDeleteWebhookSchema: z.ZodObject<{
52
52
  id: z.ZodNumber;
@@ -0,0 +1,3 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare const wcWorkflowTools: Tool[];
3
+ export declare const wcWorkflowHandlers: Record<string, Function>;
@@ -0,0 +1,222 @@
1
+ import { makeWordPressRequest } from '../wordpress.js';
2
+ import { z } from 'zod';
3
+ const WF_NAMESPACE = 'wp-manager/v1';
4
+ // ── Zod Schemas ─────────────────────────────────────────────────
5
+ const actionSchema = z.object({
6
+ channel: z.enum(['slack', 'email', 'webhook']).describe('Notification channel'),
7
+ template: z.string().describe('Message template (supports {{variable}} placeholders)'),
8
+ recipients: z.array(z.string()).describe('Recipients (emails, Slack channels, or webhook URLs)'),
9
+ }).strict();
10
+ const conditionsSchema = z.record(z.any())
11
+ .describe('Trigger conditions object (structure depends on trigger type)');
12
+ const wfListTriggersSchema = z.object({
13
+ status: z.enum(['active', 'inactive', 'all']).optional()
14
+ .describe('Filter by trigger status (default: all)'),
15
+ type: z.enum(['schedule', 'hook', 'content']).optional()
16
+ .describe('Filter by trigger type'),
17
+ limit: z.number().optional().default(50)
18
+ .describe('Max triggers to return (default 50)'),
19
+ }).strict();
20
+ const wfCreateTriggerSchema = z.object({
21
+ name: z.string().describe('Trigger name (human-readable identifier)'),
22
+ type: z.enum(['schedule', 'hook', 'content'])
23
+ .describe('Trigger type: schedule (cron-based), hook (WP action/filter), content (post lifecycle)'),
24
+ conditions: conditionsSchema,
25
+ actions: z.array(actionSchema).min(1)
26
+ .describe('Actions to execute when trigger fires'),
27
+ status: z.enum(['active', 'inactive']).optional()
28
+ .describe('Initial status (default: active)'),
29
+ description: z.string().optional()
30
+ .describe('Human-readable description of what this trigger does'),
31
+ }).strict();
32
+ const wfUpdateTriggerSchema = z.object({
33
+ trigger_id: z.number().describe('Trigger ID to update'),
34
+ name: z.string().optional().describe('Updated trigger name'),
35
+ status: z.enum(['active', 'inactive']).optional()
36
+ .describe('Updated trigger status'),
37
+ conditions: conditionsSchema.optional(),
38
+ actions: z.array(actionSchema).optional()
39
+ .describe('Updated actions array'),
40
+ description: z.string().optional()
41
+ .describe('Updated description'),
42
+ }).strict();
43
+ const wfDeleteTriggerSchema = z.object({
44
+ trigger_id: z.number().describe('Trigger ID to delete'),
45
+ }).strict();
46
+ // ── Tool Definitions ────────────────────────────────────────────
47
+ export const wcWorkflowTools = [
48
+ {
49
+ name: "wf_list_triggers",
50
+ description: "Lists all configured workflow triggers (scheduled events, WP hooks, content lifecycle) with their status, conditions, and actions",
51
+ inputSchema: {
52
+ type: "object",
53
+ properties: {
54
+ status: {
55
+ type: "string",
56
+ enum: ["active", "inactive", "all"],
57
+ description: "Filter by trigger status (default: all)",
58
+ },
59
+ type: {
60
+ type: "string",
61
+ enum: ["schedule", "hook", "content"],
62
+ description: "Filter by trigger type",
63
+ },
64
+ limit: {
65
+ type: "number",
66
+ description: "Max triggers to return (default 50)",
67
+ },
68
+ },
69
+ },
70
+ },
71
+ {
72
+ name: "wf_create_trigger",
73
+ description: "Creates a new workflow trigger that fires Slack alerts, emails, or webhook notifications on scheduled events, WP hooks, or content lifecycle changes",
74
+ inputSchema: {
75
+ type: "object",
76
+ properties: {
77
+ name: { type: "string", description: "Trigger name (human-readable identifier)" },
78
+ type: {
79
+ type: "string",
80
+ enum: ["schedule", "hook", "content"],
81
+ description: "Trigger type: schedule (cron), hook (WP action/filter), content (post lifecycle)",
82
+ },
83
+ conditions: {
84
+ type: "object",
85
+ description: "Trigger conditions (structure depends on type)",
86
+ },
87
+ actions: {
88
+ type: "array",
89
+ items: {
90
+ type: "object",
91
+ properties: {
92
+ channel: { type: "string", enum: ["slack", "email", "webhook"], description: "Notification channel" },
93
+ template: { type: "string", description: "Message template (supports {{variable}} placeholders)" },
94
+ recipients: { type: "array", items: { type: "string" }, description: "Recipients list" },
95
+ },
96
+ required: ["channel", "template", "recipients"],
97
+ },
98
+ description: "Actions to execute when trigger fires",
99
+ },
100
+ status: {
101
+ type: "string",
102
+ enum: ["active", "inactive"],
103
+ description: "Initial status (default: active)",
104
+ },
105
+ description: { type: "string", description: "What this trigger does" },
106
+ },
107
+ required: ["name", "type", "conditions", "actions"],
108
+ },
109
+ },
110
+ {
111
+ name: "wf_update_trigger",
112
+ description: "Updates an existing workflow trigger (name, status, conditions, actions, or description)",
113
+ inputSchema: {
114
+ type: "object",
115
+ properties: {
116
+ trigger_id: { type: "number", description: "Trigger ID to update" },
117
+ name: { type: "string", description: "Updated trigger name" },
118
+ status: {
119
+ type: "string",
120
+ enum: ["active", "inactive"],
121
+ description: "Updated trigger status",
122
+ },
123
+ conditions: {
124
+ type: "object",
125
+ description: "Updated trigger conditions",
126
+ },
127
+ actions: {
128
+ type: "array",
129
+ items: {
130
+ type: "object",
131
+ properties: {
132
+ channel: { type: "string", enum: ["slack", "email", "webhook"], description: "Notification channel" },
133
+ template: { type: "string", description: "Message template" },
134
+ recipients: { type: "array", items: { type: "string" }, description: "Recipients list" },
135
+ },
136
+ required: ["channel", "template", "recipients"],
137
+ },
138
+ description: "Updated actions array",
139
+ },
140
+ description: { type: "string", description: "Updated description" },
141
+ },
142
+ required: ["trigger_id"],
143
+ },
144
+ },
145
+ {
146
+ name: "wf_delete_trigger",
147
+ description: "Deletes a workflow trigger (stops all associated automation and notifications)",
148
+ inputSchema: {
149
+ type: "object",
150
+ properties: {
151
+ trigger_id: { type: "number", description: "Trigger ID to delete" },
152
+ },
153
+ required: ["trigger_id"],
154
+ },
155
+ },
156
+ ];
157
+ // ── Handlers ────────────────────────────────────────────────────
158
+ export const wcWorkflowHandlers = {
159
+ wf_list_triggers: async (params) => {
160
+ try {
161
+ const queryParts = [];
162
+ if (params.status && params.status !== 'all')
163
+ queryParts.push(`status=${params.status}`);
164
+ if (params.type)
165
+ queryParts.push(`type=${params.type}`);
166
+ if (params.limit)
167
+ queryParts.push(`per_page=${params.limit}`);
168
+ const query = queryParts.length > 0 ? `?${queryParts.join('&')}` : '';
169
+ const response = await makeWordPressRequest('GET', `workflows${query}`, undefined, {
170
+ namespace: WF_NAMESPACE,
171
+ });
172
+ return { toolResult: { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] } };
173
+ }
174
+ catch (error) {
175
+ const errorMessage = error.response?.data?.message || error.message;
176
+ return { toolResult: { isError: true, content: [{ type: "text", text: `Error listing workflow triggers: ${errorMessage}` }] } };
177
+ }
178
+ },
179
+ wf_create_trigger: async (params) => {
180
+ try {
181
+ const { name, type, conditions, actions, status, description } = params;
182
+ const body = { name, type, conditions, actions };
183
+ if (status)
184
+ body.status = status;
185
+ if (description)
186
+ body.description = description;
187
+ const response = await makeWordPressRequest('POST', 'workflows', body, {
188
+ namespace: WF_NAMESPACE,
189
+ });
190
+ return { toolResult: { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] } };
191
+ }
192
+ catch (error) {
193
+ const errorMessage = error.response?.data?.message || error.message;
194
+ return { toolResult: { isError: true, content: [{ type: "text", text: `Error creating workflow trigger: ${errorMessage}` }] } };
195
+ }
196
+ },
197
+ wf_update_trigger: async (params) => {
198
+ try {
199
+ const { trigger_id, ...updates } = params;
200
+ const response = await makeWordPressRequest('PUT', `workflows/${trigger_id}`, updates, {
201
+ namespace: WF_NAMESPACE,
202
+ });
203
+ return { toolResult: { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] } };
204
+ }
205
+ catch (error) {
206
+ const errorMessage = error.response?.data?.message || error.message;
207
+ return { toolResult: { isError: true, content: [{ type: "text", text: `Error updating workflow trigger: ${errorMessage}` }] } };
208
+ }
209
+ },
210
+ wf_delete_trigger: async (params) => {
211
+ try {
212
+ const response = await makeWordPressRequest('DELETE', `workflows/${params.trigger_id}?force=true`, undefined, {
213
+ namespace: WF_NAMESPACE,
214
+ });
215
+ return { toolResult: { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] } };
216
+ }
217
+ catch (error) {
218
+ const errorMessage = error.response?.data?.message || error.message;
219
+ return { toolResult: { isError: true, content: [{ type: "text", text: `Error deleting workflow trigger: ${errorMessage}` }] } };
220
+ }
221
+ },
222
+ };
@@ -14,6 +14,15 @@ interface SiteConfig {
14
14
  mailchimp_api_key?: string;
15
15
  buffer_access_token?: string;
16
16
  sendgrid_api_key?: string;
17
+ gsc_service_account_key?: string;
18
+ gsc_site_url?: string;
19
+ ga4_property_id?: string;
20
+ ga4_service_account_key?: string;
21
+ plausible_api_key?: string;
22
+ plausible_base_url?: string;
23
+ google_api_key?: string;
24
+ slack_webhook_url?: string;
25
+ slack_bot_token?: string;
17
26
  }
18
27
  /**
19
28
  * Parse WP_SITES_CONFIG JSON and initialize all site clients
@@ -78,6 +87,20 @@ export declare function hasBuffer(siteId?: string): boolean;
78
87
  export declare function makeBufferRequest(method: string, endpoint: string, data?: any, siteId?: string): Promise<any>;
79
88
  export declare function hasSendGrid(siteId?: string): boolean;
80
89
  export declare function makeSendGridRequest(method: string, endpoint: string, data?: any, siteId?: string): Promise<any>;
90
+ export declare function hasGSC(siteId?: string): boolean;
91
+ export declare function getGSCSiteUrl(siteId?: string): string;
92
+ export declare function getGSCAuth(siteId?: string): Promise<any>;
93
+ export declare function hasGA4(siteId?: string): boolean;
94
+ export declare function getGA4PropertyId(siteId?: string): string;
95
+ export declare function getGA4Auth(siteId?: string): Promise<any>;
96
+ export declare function hasPlausible(siteId?: string): boolean;
97
+ export declare function makePlausibleRequest(method: string, endpoint: string, params?: Record<string, any>, siteId?: string): Promise<any>;
98
+ export declare function hasGoogleApiKey(siteId?: string): boolean;
99
+ export declare function getGoogleApiKey(siteId?: string): string;
100
+ export declare function hasSlackWebhook(siteId?: string): boolean;
101
+ export declare function getSlackWebhookUrl(siteId?: string): string;
102
+ export declare function hasSlackBot(siteId?: string): boolean;
103
+ export declare function makeSlackBotRequest(method: string, endpoint: string, data?: Record<string, any>, siteId?: string): Promise<any>;
81
104
  /**
82
105
  * Search the WordPress.org Plugin Repository
83
106
  */
@@ -1,5 +1,7 @@
1
1
  // src/wordpress.ts - Multi-site WordPress REST API client
2
2
  import axios from 'axios';
3
+ import { google } from 'googleapis';
4
+ import { readFileSync } from 'fs';
3
5
  // ── Concurrency Limiter ──────────────────────────────────────────────
4
6
  // Simple FIFO semaphore to cap concurrent requests per site
5
7
  class ConcurrencyLimiter {
@@ -35,6 +37,8 @@ const wcSiteClients = new Map();
35
37
  const mcSiteClients = new Map();
36
38
  const bufSiteClients = new Map();
37
39
  const sgSiteClients = new Map();
40
+ const plSiteClients = new Map();
41
+ const slackBotClients = new Map();
38
42
  let activeSiteId = '';
39
43
  const parsedSiteConfigs = new Map();
40
44
  const MAX_CONCURRENT_PER_SITE = 5;
@@ -99,6 +103,14 @@ export async function initWordPress() {
99
103
  await initSendGridClient(site.id, site.sendgrid_api_key);
100
104
  logToStderr(`Initialized SendGrid for site: ${site.id}`);
101
105
  }
106
+ if (site.plausible_api_key) {
107
+ await initPlausibleClient(site.id, site.plausible_api_key, site.plausible_base_url);
108
+ logToStderr(`Initialized Plausible for site: ${site.id}`);
109
+ }
110
+ if (site.slack_bot_token) {
111
+ await initSlackBotClient(site.id, site.slack_bot_token);
112
+ logToStderr(`Initialized Slack Bot for site: ${site.id}`);
113
+ }
102
114
  }
103
115
  activeSiteId = defaultSite || sites[0].id;
104
116
  logToStderr(`Active site: ${activeSiteId}`);
@@ -201,6 +213,27 @@ async function initSendGridClient(id, apiKey) {
201
213
  });
202
214
  sgSiteClients.set(id, client);
203
215
  }
216
+ async function initPlausibleClient(id, apiKey, baseUrl) {
217
+ const client = axios.create({
218
+ baseURL: (baseUrl || 'https://plausible.io') + '/api/v1/',
219
+ headers: {
220
+ 'Authorization': `Bearer ${apiKey}`,
221
+ },
222
+ timeout: DEFAULT_TIMEOUT_MS,
223
+ });
224
+ plSiteClients.set(id, client);
225
+ }
226
+ async function initSlackBotClient(id, botToken) {
227
+ const client = axios.create({
228
+ baseURL: 'https://slack.com/api/',
229
+ headers: {
230
+ 'Authorization': `Bearer ${botToken}`,
231
+ 'Content-Type': 'application/json; charset=utf-8',
232
+ },
233
+ timeout: DEFAULT_TIMEOUT_MS,
234
+ });
235
+ slackBotClients.set(id, client);
236
+ }
204
237
  // ── Site Management ──────────────────────────────────────────────────
205
238
  /**
206
239
  * Get the active site's client, or a specific site's client
@@ -469,6 +502,151 @@ export async function makeSendGridRequest(method, endpoint, data, siteId) {
469
502
  limiter.release();
470
503
  }
471
504
  }
505
+ // ── Google Search Console Interface ─────────────────────────────
506
+ const gscAuthClients = new Map();
507
+ export function hasGSC(siteId) {
508
+ const id = siteId || activeSiteId;
509
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
510
+ const site = sites.find((s) => s.id === id);
511
+ return !!(site?.gsc_service_account_key && site?.gsc_site_url);
512
+ }
513
+ export function getGSCSiteUrl(siteId) {
514
+ const id = siteId || activeSiteId;
515
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
516
+ const site = sites.find((s) => s.id === id);
517
+ if (!site?.gsc_site_url) {
518
+ throw new Error(`GSC site URL not configured for site "${id}". Add gsc_site_url to WP_SITES_CONFIG.`);
519
+ }
520
+ return site.gsc_site_url;
521
+ }
522
+ export async function getGSCAuth(siteId) {
523
+ const id = siteId || activeSiteId;
524
+ // Return cached client if available
525
+ if (gscAuthClients.has(id)) {
526
+ return gscAuthClients.get(id);
527
+ }
528
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
529
+ const site = sites.find((s) => s.id === id);
530
+ if (!site?.gsc_service_account_key) {
531
+ throw new Error(`GSC not configured for site "${id}". Add gsc_service_account_key (path to JSON key file) to WP_SITES_CONFIG.`);
532
+ }
533
+ const keyContent = JSON.parse(readFileSync(site.gsc_service_account_key, 'utf-8'));
534
+ const auth = new google.auth.GoogleAuth({
535
+ credentials: keyContent,
536
+ scopes: ['https://www.googleapis.com/auth/webmasters'],
537
+ });
538
+ const authClient = await auth.getClient();
539
+ gscAuthClients.set(id, authClient);
540
+ return authClient;
541
+ }
542
+ // ── Google Analytics 4 Interface ─────────────────────────────────
543
+ const ga4AuthClients = new Map();
544
+ export function hasGA4(siteId) {
545
+ const id = siteId || activeSiteId;
546
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
547
+ const site = sites.find((s) => s.id === id);
548
+ return !!(site?.ga4_property_id && site?.ga4_service_account_key);
549
+ }
550
+ export function getGA4PropertyId(siteId) {
551
+ const id = siteId || activeSiteId;
552
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
553
+ const site = sites.find((s) => s.id === id);
554
+ if (!site?.ga4_property_id) {
555
+ throw new Error(`GA4 property not configured for site "${id}". Add ga4_property_id to WP_SITES_CONFIG.`);
556
+ }
557
+ return site.ga4_property_id;
558
+ }
559
+ export async function getGA4Auth(siteId) {
560
+ const id = siteId || activeSiteId;
561
+ if (ga4AuthClients.has(id))
562
+ return ga4AuthClients.get(id);
563
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
564
+ const site = sites.find((s) => s.id === id);
565
+ if (!site?.ga4_service_account_key) {
566
+ throw new Error(`GA4 not configured for site "${id}". Add ga4_service_account_key to WP_SITES_CONFIG.`);
567
+ }
568
+ const keyContent = JSON.parse(readFileSync(site.ga4_service_account_key, 'utf-8'));
569
+ const auth = new google.auth.GoogleAuth({
570
+ credentials: keyContent,
571
+ scopes: ['https://www.googleapis.com/auth/analytics.readonly'],
572
+ });
573
+ const authClient = await auth.getClient();
574
+ ga4AuthClients.set(id, authClient);
575
+ return authClient;
576
+ }
577
+ // ── Plausible Analytics Interface ────────────────────────────────
578
+ export function hasPlausible(siteId) {
579
+ const id = siteId || activeSiteId;
580
+ return plSiteClients.has(id);
581
+ }
582
+ export async function makePlausibleRequest(method, endpoint, params, siteId) {
583
+ const id = siteId || activeSiteId;
584
+ const client = plSiteClients.get(id);
585
+ if (!client) {
586
+ throw new Error(`Plausible not configured for site "${id}". Add plausible_api_key to WP_SITES_CONFIG.`);
587
+ }
588
+ const limiter = getLimiter(id);
589
+ await limiter.acquire();
590
+ try {
591
+ const response = await client.request({ method, url: endpoint, params });
592
+ return response.data;
593
+ }
594
+ finally {
595
+ limiter.release();
596
+ }
597
+ }
598
+ // ── Core Web Vitals Interface (Google API Key) ───────────────────
599
+ export function hasGoogleApiKey(siteId) {
600
+ const id = siteId || activeSiteId;
601
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
602
+ const site = sites.find((s) => s.id === id);
603
+ return !!site?.google_api_key;
604
+ }
605
+ export function getGoogleApiKey(siteId) {
606
+ const id = siteId || activeSiteId;
607
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
608
+ const site = sites.find((s) => s.id === id);
609
+ if (!site?.google_api_key) {
610
+ throw new Error(`Google API key not configured for site "${id}". Add google_api_key to WP_SITES_CONFIG.`);
611
+ }
612
+ return site.google_api_key;
613
+ }
614
+ // ── Slack Interface ─────────────────────────────────────────────
615
+ export function hasSlackWebhook(siteId) {
616
+ const id = siteId || activeSiteId;
617
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
618
+ const site = sites.find((s) => s.id === id);
619
+ return !!site?.slack_webhook_url;
620
+ }
621
+ export function getSlackWebhookUrl(siteId) {
622
+ const id = siteId || activeSiteId;
623
+ const sites = JSON.parse(process.env.WP_SITES_CONFIG || '[]');
624
+ const site = sites.find((s) => s.id === id);
625
+ if (!site?.slack_webhook_url) {
626
+ throw new Error(`Slack webhook not configured for site "${id}". Add slack_webhook_url to WP_SITES_CONFIG.`);
627
+ }
628
+ return site.slack_webhook_url;
629
+ }
630
+ export function hasSlackBot(siteId) {
631
+ const id = siteId || activeSiteId;
632
+ return slackBotClients.has(id);
633
+ }
634
+ export async function makeSlackBotRequest(method, endpoint, data, siteId) {
635
+ const id = siteId || activeSiteId;
636
+ const client = slackBotClients.get(id);
637
+ if (!client) {
638
+ throw new Error(`Slack Bot not configured for site "${id}". Add slack_bot_token to WP_SITES_CONFIG.`);
639
+ }
640
+ const limiter = getLimiter(id);
641
+ await limiter.acquire();
642
+ try {
643
+ const response = await client.request({ method, url: endpoint, data });
644
+ return response.data;
645
+ }
646
+ finally {
647
+ limiter.release();
648
+ }
649
+ }
472
650
  // ── Plugin Repository (External API) ────────────────────────────────
473
651
  /**
474
652
  * Search the WordPress.org Plugin Repository
@@ -17,6 +17,7 @@
17
17
  "@modelcontextprotocol/sdk": "^1.27.1",
18
18
  "axios": "^1.7.9",
19
19
  "form-data": "^4.0.1",
20
+ "googleapis": "^171.4.0",
20
21
  "zod": "^3.24.2"
21
22
  },
22
23
  "devDependencies": {
@@ -4,7 +4,7 @@ description: “Use when the user asks about WordPress — whether development (
4
4
  blocks, REST API) or operations (deploy, audit, backup, migrate, content management).
5
5
  Classifies the task and routes to the correct development or operational skill/agent.”
6
6
  compatibility: “Targets WordPress 6.9+ (PHP 7.2.24+). Filesystem-based agent with bash + node. Some workflows require WP-CLI.”
7
- version: 1.1.0
7
+ version: 1.4.0
8
8
  source: “WordPress/agent-skills (GPL-2.0-or-later) + wordpress-manager extensions”
9
9
  ---
10
10
 
@@ -1,4 +1,4 @@
1
- # Router decision tree (v11 — development + local environment + operations + multisite + CI/CD + monitoring + webhooks + content repurposing + programmatic SEO + content attribution + multi-language network + social/email distribution)
1
+ # Router decision tree (v16 — development + local environment + operations + multisite + CI/CD + monitoring + webhooks + content repurposing + programmatic SEO + content attribution + multi-language network + social/email distribution + search console + content optimization + analytics + alerting + workflows)
2
2
 
3
3
  This routing guide covers WordPress **development**, **local environment**, and **operations** workflows.
4
4
 
@@ -14,7 +14,7 @@ Keywords that indicate **local environment**:
14
14
  local site, Studio, LocalWP, Local by Flywheel, wp-env, local WordPress, start site, stop site, create local site, local development, symlink plugin, local database, switch PHP version, localhost, local preview, detect environment, WASM, SQLite local
15
15
 
16
16
  Keywords that indicate **operations**:
17
- deploy, push to production, audit, security check, backup, restore, migrate, move site, create post, manage content, site status, check plugins, performance check, SEO audit, WooCommerce, prodotto, ordine, coupon, negozio, catalogo, inventario, vendite, carrello, multisite, network, sub-site, sub-sito, domain mapping, super admin, network activate, monitor, uptime, health report, trend, scansione periodica, alerting, performance baseline, fleet, all sites, network health, cross-site, webhook, outbound notification, event propagation, Zapier, content sync, repurpose content, social posts from blog, content atomization, newsletter from posts, content distribution, programmatic SEO, template pages, city pages, location pages, bulk page generation, scalable landing pages, content ROI, attribution, which content drives sales, conversion tracking, UTM tracking, revenue per post, multilingual, multi-language, hreflang, international SEO, translate site, language sites, localize content, social publish, schedule post, Buffer, email campaign, Mailchimp, SendGrid, transactional email, content distribution, newsletter send
17
+ deploy, push to production, audit, security check, backup, restore, migrate, move site, create post, manage content, site status, check plugins, performance check, SEO audit, WooCommerce, prodotto, ordine, coupon, negozio, catalogo, inventario, vendite, carrello, multisite, network, sub-site, sub-sito, domain mapping, super admin, network activate, monitor, uptime, health report, trend, scansione periodica, alerting, performance baseline, fleet, all sites, network health, cross-site, webhook, outbound notification, event propagation, Zapier, content sync, repurpose content, social posts from blog, content atomization, newsletter from posts, content distribution, programmatic SEO, template pages, city pages, location pages, bulk page generation, scalable landing pages, content ROI, attribution, which content drives sales, conversion tracking, UTM tracking, revenue per post, multilingual, multi-language, hreflang, international SEO, translate site, language sites, localize content, social publish, schedule post, Buffer, email campaign, Mailchimp, SendGrid, transactional email, content distribution, newsletter send, Google Search Console, GSC, keyword tracking, keyword rankings, search analytics, indexing status, URL inspection, sitemap submit, search performance, SERP data, optimize content, headline scoring, readability analysis, SEO score, content scoring, meta optimization, content freshness, content triage, bulk optimize, Flesch-Kincaid, keyword density, Google Analytics, GA4, traffic analytics, pageviews, sessions, user analytics, Plausible, privacy analytics, Core Web Vitals, CWV, LCP, INP, CLS, PageSpeed, page speed, site speed, performance score, Slack alert, email alert, notification channel, alert threshold, severity routing, escalation, incident notification, uptime alert, error alert, performance alert, scheduled report, health digest, alert cooldown, alert dedup, workflow trigger, automation, scheduled event, content lifecycle, cron trigger, hook trigger, workflow rule, automate, trigger management
18
18
 
19
19
  Keywords that indicate **development**:
20
20
  create block, block.json, theme.json, register_rest_route, plugin development, hooks, PHPStan, build, test, scaffold, i18n, translation, accessibility, a11y, headless, decoupled, WPGraphQL, CI, CD, pipeline, GitHub Actions, GitLab CI, deploy automatico, workflow, quality gate
@@ -106,6 +106,16 @@ Priority: `gutenberg` > `wp-core` > `wp-site` > `wp-block-theme` > `wp-block-plu
106
106
  → `wp-multilang-network` skill + `wp-site-manager` agent
107
107
  - **Social/email distribution / publish to social / schedule post / email campaign / Mailchimp / Buffer / SendGrid / newsletter / transactional email / content distribution**
108
108
  → `wp-social-email` skill + `wp-distribution-manager` agent
109
+ - **Google Search Console / keyword tracking / indexing status / sitemap submit / search performance / GSC / SERP data**
110
+ → `wp-search-console` skill + `wp-content-strategist` agent
111
+ - **Content optimization / headline scoring / readability / SEO score / meta optimization / content freshness / content triage / optimize posts / Flesch-Kincaid / keyword density**
112
+ → `wp-content-optimization` skill + `wp-content-strategist` agent
113
+ - **Google Analytics / GA4 / Plausible / traffic analytics / pageviews / sessions / user analytics / Core Web Vitals / CWV / PageSpeed / site speed / performance score**
114
+ → `wp-analytics` skill + `wp-monitoring-agent` agent
115
+ - **Slack alert / email alert / notification channel / alert threshold / severity routing / escalation / incident notification / uptime alert / performance alert / scheduled report / health digest / alert cooldown**
116
+ → `wp-alerting` skill + `wp-monitoring-agent` agent
117
+ - **Workflow trigger / automation / scheduled event / content lifecycle / cron trigger / hook trigger / workflow rule / automate / trigger management**
118
+ → `wp-content-workflows` skill + `wp-site-manager` agent
109
119
 
110
120
  ## Step 2c: route by local environment intent (keywords)
111
121