claude-plugin-wordpress-manager 1.7.2 → 1.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 (56) hide show
  1. package/.claude-plugin/plugin.json +7 -3
  2. package/CHANGELOG.md +55 -0
  3. package/agents/wp-ecommerce-manager.md +136 -0
  4. package/agents/wp-site-manager.md +27 -0
  5. package/docs/plans/2026-02-28-multisite-v1.9.0-design.md +258 -0
  6. package/docs/plans/2026-02-28-multisite-v1.9.0.md +1604 -0
  7. package/docs/plans/2026-02-28-roadmap-v1.8-v2.1-design.md +314 -0
  8. package/docs/plans/2026-02-28-woocommerce-v1.8.0.md +2012 -0
  9. package/package.json +8 -3
  10. package/servers/wp-rest-bridge/build/tools/index.d.ts +1187 -0
  11. package/servers/wp-rest-bridge/build/tools/index.js +26 -2
  12. package/servers/wp-rest-bridge/build/tools/multisite-network.d.ts +132 -0
  13. package/servers/wp-rest-bridge/build/tools/multisite-network.js +157 -0
  14. package/servers/wp-rest-bridge/build/tools/multisite-sites.d.ts +150 -0
  15. package/servers/wp-rest-bridge/build/tools/multisite-sites.js +160 -0
  16. package/servers/wp-rest-bridge/build/tools/wc-coupons.d.ts +144 -0
  17. package/servers/wp-rest-bridge/build/tools/wc-coupons.js +92 -0
  18. package/servers/wp-rest-bridge/build/tools/wc-customers.d.ts +141 -0
  19. package/servers/wp-rest-bridge/build/tools/wc-customers.js +92 -0
  20. package/servers/wp-rest-bridge/build/tools/wc-orders.d.ts +186 -0
  21. package/servers/wp-rest-bridge/build/tools/wc-orders.js +128 -0
  22. package/servers/wp-rest-bridge/build/tools/wc-products.d.ts +324 -0
  23. package/servers/wp-rest-bridge/build/tools/wc-products.js +177 -0
  24. package/servers/wp-rest-bridge/build/tools/wc-reports.d.ts +117 -0
  25. package/servers/wp-rest-bridge/build/tools/wc-reports.js +94 -0
  26. package/servers/wp-rest-bridge/build/tools/wc-settings.d.ts +72 -0
  27. package/servers/wp-rest-bridge/build/tools/wc-settings.js +70 -0
  28. package/servers/wp-rest-bridge/build/types.d.ts +98 -0
  29. package/servers/wp-rest-bridge/build/wordpress.d.ts +28 -0
  30. package/servers/wp-rest-bridge/build/wordpress.js +85 -0
  31. package/servers/wp-rest-bridge/build/wpcli.d.ts +23 -0
  32. package/servers/wp-rest-bridge/build/wpcli.js +72 -0
  33. package/skills/wordpress-router/references/decision-tree.md +6 -2
  34. package/skills/wp-audit/SKILL.md +1 -0
  35. package/skills/wp-backup/SKILL.md +1 -0
  36. package/skills/wp-deploy/SKILL.md +1 -0
  37. package/skills/wp-multisite/SKILL.md +92 -0
  38. package/skills/wp-multisite/references/domain-mapping.md +70 -0
  39. package/skills/wp-multisite/references/migration-multisite.md +76 -0
  40. package/skills/wp-multisite/references/network-plugins.md +66 -0
  41. package/skills/wp-multisite/references/network-setup.md +69 -0
  42. package/skills/wp-multisite/references/site-management.md +67 -0
  43. package/skills/wp-multisite/references/user-roles.md +73 -0
  44. package/skills/wp-multisite/scripts/multisite_inspect.mjs +160 -0
  45. package/skills/wp-security/SKILL.md +4 -0
  46. package/skills/wp-woocommerce/SKILL.md +110 -0
  47. package/skills/wp-woocommerce/references/analytics-reports.md +75 -0
  48. package/skills/wp-woocommerce/references/coupon-marketing.md +92 -0
  49. package/skills/wp-woocommerce/references/order-workflow.md +88 -0
  50. package/skills/wp-woocommerce/references/payment-gateways.md +69 -0
  51. package/skills/wp-woocommerce/references/product-management.md +61 -0
  52. package/skills/wp-woocommerce/references/shipping-setup.md +79 -0
  53. package/skills/wp-woocommerce/references/tax-configuration.md +91 -0
  54. package/skills/wp-woocommerce/references/wc-extensions.md +97 -0
  55. package/skills/wp-woocommerce/scripts/woocommerce_inspect.mjs +181 -0
  56. package/skills/wp-wpcli-and-ops/SKILL.md +4 -0
@@ -6,6 +6,14 @@ import { userTools, userHandlers } from './users.js';
6
6
  import { pluginRepositoryTools, pluginRepositoryHandlers } from './plugin-repository.js';
7
7
  import { commentTools, commentHandlers } from './comments.js';
8
8
  import { searchTools, searchHandlers } from './search.js';
9
+ import { wcProductTools, wcProductHandlers } from './wc-products.js';
10
+ import { wcOrderTools, wcOrderHandlers } from './wc-orders.js';
11
+ import { wcCustomerTools, wcCustomerHandlers } from './wc-customers.js';
12
+ import { wcCouponTools, wcCouponHandlers } from './wc-coupons.js';
13
+ import { wcReportTools, wcReportHandlers } from './wc-reports.js';
14
+ import { wcSettingTools, wcSettingHandlers } from './wc-settings.js';
15
+ import { multisiteSiteTools, multisiteSiteHandlers } from './multisite-sites.js';
16
+ import { multisiteNetworkTools, multisiteNetworkHandlers } from './multisite-network.js';
9
17
  // Combine all tools
10
18
  export const allTools = [
11
19
  ...unifiedContentTools, // 8 tools
@@ -15,7 +23,15 @@ export const allTools = [
15
23
  ...userTools, // 6 tools
16
24
  ...pluginRepositoryTools, // 2 tools
17
25
  ...commentTools, // 5 tools
18
- ...searchTools // 1 tool
26
+ ...searchTools, // 1 tool
27
+ ...wcProductTools, // 7 tools
28
+ ...wcOrderTools, // 6 tools
29
+ ...wcCustomerTools, // 4 tools
30
+ ...wcCouponTools, // 4 tools
31
+ ...wcReportTools, // 5 tools
32
+ ...wcSettingTools, // 4 tools
33
+ ...multisiteSiteTools, // 5 tools
34
+ ...multisiteNetworkTools, // 5 tools
19
35
  ];
20
36
  // Combine all handlers
21
37
  export const toolHandlers = {
@@ -26,5 +42,13 @@ export const toolHandlers = {
26
42
  ...userHandlers,
27
43
  ...pluginRepositoryHandlers,
28
44
  ...commentHandlers,
29
- ...searchHandlers
45
+ ...searchHandlers,
46
+ ...wcProductHandlers,
47
+ ...wcOrderHandlers,
48
+ ...wcCustomerHandlers,
49
+ ...wcCouponHandlers,
50
+ ...wcReportHandlers,
51
+ ...wcSettingHandlers,
52
+ ...multisiteSiteHandlers,
53
+ ...multisiteNetworkHandlers,
30
54
  };
@@ -0,0 +1,132 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import { z } from 'zod';
3
+ declare const msListNetworkPluginsSchema: z.ZodObject<{
4
+ site_id: z.ZodOptional<z.ZodString>;
5
+ }, "strict", z.ZodTypeAny, {
6
+ site_id?: string | undefined;
7
+ }, {
8
+ site_id?: string | undefined;
9
+ }>;
10
+ declare const msNetworkActivatePluginSchema: z.ZodObject<{
11
+ plugin_slug: z.ZodString;
12
+ site_id: z.ZodOptional<z.ZodString>;
13
+ }, "strict", z.ZodTypeAny, {
14
+ plugin_slug: string;
15
+ site_id?: string | undefined;
16
+ }, {
17
+ plugin_slug: string;
18
+ site_id?: string | undefined;
19
+ }>;
20
+ declare const msNetworkDeactivatePluginSchema: z.ZodObject<{
21
+ plugin_slug: z.ZodString;
22
+ site_id: z.ZodOptional<z.ZodString>;
23
+ }, "strict", z.ZodTypeAny, {
24
+ plugin_slug: string;
25
+ site_id?: string | undefined;
26
+ }, {
27
+ plugin_slug: string;
28
+ site_id?: string | undefined;
29
+ }>;
30
+ declare const msListSuperAdminsSchema: z.ZodObject<{
31
+ site_id: z.ZodOptional<z.ZodString>;
32
+ }, "strict", z.ZodTypeAny, {
33
+ site_id?: string | undefined;
34
+ }, {
35
+ site_id?: string | undefined;
36
+ }>;
37
+ declare const msGetNetworkSettingsSchema: z.ZodObject<{
38
+ site_id: z.ZodOptional<z.ZodString>;
39
+ }, "strict", z.ZodTypeAny, {
40
+ site_id?: string | undefined;
41
+ }, {
42
+ site_id?: string | undefined;
43
+ }>;
44
+ export declare const multisiteNetworkTools: Tool[];
45
+ export declare const multisiteNetworkHandlers: {
46
+ ms_list_network_plugins: (params: z.infer<typeof msListNetworkPluginsSchema>) => Promise<{
47
+ toolResult: {
48
+ content: {
49
+ type: string;
50
+ text: string;
51
+ }[];
52
+ isError?: undefined;
53
+ };
54
+ } | {
55
+ toolResult: {
56
+ isError: boolean;
57
+ content: {
58
+ type: string;
59
+ text: string;
60
+ }[];
61
+ };
62
+ }>;
63
+ ms_network_activate_plugin: (params: z.infer<typeof msNetworkActivatePluginSchema>) => Promise<{
64
+ toolResult: {
65
+ content: {
66
+ type: string;
67
+ text: string;
68
+ }[];
69
+ isError?: undefined;
70
+ };
71
+ } | {
72
+ toolResult: {
73
+ isError: boolean;
74
+ content: {
75
+ type: string;
76
+ text: string;
77
+ }[];
78
+ };
79
+ }>;
80
+ ms_network_deactivate_plugin: (params: z.infer<typeof msNetworkDeactivatePluginSchema>) => Promise<{
81
+ toolResult: {
82
+ content: {
83
+ type: string;
84
+ text: string;
85
+ }[];
86
+ isError?: undefined;
87
+ };
88
+ } | {
89
+ toolResult: {
90
+ isError: boolean;
91
+ content: {
92
+ type: string;
93
+ text: string;
94
+ }[];
95
+ };
96
+ }>;
97
+ ms_list_super_admins: (params: z.infer<typeof msListSuperAdminsSchema>) => Promise<{
98
+ toolResult: {
99
+ content: {
100
+ type: string;
101
+ text: string;
102
+ }[];
103
+ isError?: undefined;
104
+ };
105
+ } | {
106
+ toolResult: {
107
+ isError: boolean;
108
+ content: {
109
+ type: string;
110
+ text: string;
111
+ }[];
112
+ };
113
+ }>;
114
+ ms_get_network_settings: (params: z.infer<typeof msGetNetworkSettingsSchema>) => Promise<{
115
+ toolResult: {
116
+ content: {
117
+ type: string;
118
+ text: string;
119
+ }[];
120
+ isError?: undefined;
121
+ };
122
+ } | {
123
+ toolResult: {
124
+ isError: boolean;
125
+ content: {
126
+ type: string;
127
+ text: string;
128
+ }[];
129
+ };
130
+ }>;
131
+ };
132
+ export {};
@@ -0,0 +1,157 @@
1
+ import { makeWordPressRequest } from '../wordpress.js';
2
+ import { executeWpCli, isMultisite } from '../wpcli.js';
3
+ import { z } from 'zod';
4
+ // ── Schemas ──────────────────────────────────────────────────────────
5
+ const msListNetworkPluginsSchema = z.object({
6
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
7
+ }).strict();
8
+ const msNetworkActivatePluginSchema = z.object({
9
+ plugin_slug: z.string().describe('Plugin slug to network-activate (e.g., "akismet", "jetpack")'),
10
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
11
+ }).strict();
12
+ const msNetworkDeactivatePluginSchema = z.object({
13
+ plugin_slug: z.string().describe('Plugin slug to network-deactivate'),
14
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
15
+ }).strict();
16
+ const msListSuperAdminsSchema = z.object({
17
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
18
+ }).strict();
19
+ const msGetNetworkSettingsSchema = z.object({
20
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
21
+ }).strict();
22
+ // ── Tools ────────────────────────────────────────────────────────────
23
+ export const multisiteNetworkTools = [
24
+ {
25
+ name: 'ms_list_network_plugins',
26
+ description: 'Lists all plugins on the multisite network with their activation status (uses REST API).',
27
+ inputSchema: { type: 'object', properties: msListNetworkPluginsSchema.shape }
28
+ },
29
+ {
30
+ name: 'ms_network_activate_plugin',
31
+ description: 'Network-activates a plugin across all sites in the multisite network (uses wp-cli).',
32
+ inputSchema: { type: 'object', properties: msNetworkActivatePluginSchema.shape }
33
+ },
34
+ {
35
+ name: 'ms_network_deactivate_plugin',
36
+ description: 'Network-deactivates a plugin from all sites in the multisite network (uses wp-cli).',
37
+ inputSchema: { type: 'object', properties: msNetworkDeactivatePluginSchema.shape }
38
+ },
39
+ {
40
+ name: 'ms_list_super_admins',
41
+ description: 'Lists all Super Admin users in the multisite network (uses wp-cli).',
42
+ inputSchema: { type: 'object', properties: msListSuperAdminsSchema.shape }
43
+ },
44
+ {
45
+ name: 'ms_get_network_settings',
46
+ description: 'Gets network-wide settings (site name, admin email, registration policy) via wp-cli.',
47
+ inputSchema: { type: 'object', properties: msGetNetworkSettingsSchema.shape }
48
+ }
49
+ ];
50
+ // ── Helpers ──────────────────────────────────────────────────────────
51
+ function requireMultisite(siteId) {
52
+ if (!isMultisite(siteId)) {
53
+ throw new Error(`Site is not configured as multisite. ` +
54
+ `Set is_multisite: true in WP_SITES_CONFIG.`);
55
+ }
56
+ }
57
+ // ── Handlers ─────────────────────────────────────────────────────────
58
+ export const multisiteNetworkHandlers = {
59
+ ms_list_network_plugins: async (params) => {
60
+ try {
61
+ requireMultisite(params.site_id);
62
+ const result = await makeWordPressRequest('GET', 'plugins', undefined, {
63
+ siteId: params.site_id
64
+ });
65
+ return {
66
+ toolResult: {
67
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
68
+ }
69
+ };
70
+ }
71
+ catch (error) {
72
+ const errorMessage = error.response?.data?.message || error.message;
73
+ return {
74
+ toolResult: {
75
+ isError: true,
76
+ content: [{ type: 'text', text: `Error listing network plugins: ${errorMessage}` }]
77
+ }
78
+ };
79
+ }
80
+ },
81
+ ms_network_activate_plugin: async (params) => {
82
+ try {
83
+ requireMultisite(params.site_id);
84
+ const result = await executeWpCli(`plugin activate ${params.plugin_slug} --network`, params.site_id, { skipJson: true });
85
+ return {
86
+ toolResult: {
87
+ content: [{ type: 'text', text: result || `Plugin "${params.plugin_slug}" network-activated successfully.` }]
88
+ }
89
+ };
90
+ }
91
+ catch (error) {
92
+ return {
93
+ toolResult: {
94
+ isError: true,
95
+ content: [{ type: 'text', text: `Error network-activating plugin: ${error.message}` }]
96
+ }
97
+ };
98
+ }
99
+ },
100
+ ms_network_deactivate_plugin: async (params) => {
101
+ try {
102
+ requireMultisite(params.site_id);
103
+ const result = await executeWpCli(`plugin deactivate ${params.plugin_slug} --network`, params.site_id, { skipJson: true });
104
+ return {
105
+ toolResult: {
106
+ content: [{ type: 'text', text: result || `Plugin "${params.plugin_slug}" network-deactivated successfully.` }]
107
+ }
108
+ };
109
+ }
110
+ catch (error) {
111
+ return {
112
+ toolResult: {
113
+ isError: true,
114
+ content: [{ type: 'text', text: `Error network-deactivating plugin: ${error.message}` }]
115
+ }
116
+ };
117
+ }
118
+ },
119
+ ms_list_super_admins: async (params) => {
120
+ try {
121
+ requireMultisite(params.site_id);
122
+ const result = await executeWpCli('super-admin list', params.site_id, { skipJson: true });
123
+ return {
124
+ toolResult: {
125
+ content: [{ type: 'text', text: result }]
126
+ }
127
+ };
128
+ }
129
+ catch (error) {
130
+ return {
131
+ toolResult: {
132
+ isError: true,
133
+ content: [{ type: 'text', text: `Error listing super admins: ${error.message}` }]
134
+ }
135
+ };
136
+ }
137
+ },
138
+ ms_get_network_settings: async (params) => {
139
+ try {
140
+ requireMultisite(params.site_id);
141
+ const result = await executeWpCli('network meta list 1', params.site_id);
142
+ return {
143
+ toolResult: {
144
+ content: [{ type: 'text', text: result }]
145
+ }
146
+ };
147
+ }
148
+ catch (error) {
149
+ return {
150
+ toolResult: {
151
+ isError: true,
152
+ content: [{ type: 'text', text: `Error getting network settings: ${error.message}` }]
153
+ }
154
+ };
155
+ }
156
+ }
157
+ };
@@ -0,0 +1,150 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import { z } from 'zod';
3
+ declare const msListSitesSchema: z.ZodObject<{
4
+ site_id: z.ZodOptional<z.ZodString>;
5
+ }, "strict", z.ZodTypeAny, {
6
+ site_id?: string | undefined;
7
+ }, {
8
+ site_id?: string | undefined;
9
+ }>;
10
+ declare const msGetSiteSchema: z.ZodObject<{
11
+ blog_id: z.ZodNumber;
12
+ site_id: z.ZodOptional<z.ZodString>;
13
+ }, "strict", z.ZodTypeAny, {
14
+ blog_id: number;
15
+ site_id?: string | undefined;
16
+ }, {
17
+ blog_id: number;
18
+ site_id?: string | undefined;
19
+ }>;
20
+ declare const msCreateSiteSchema: z.ZodObject<{
21
+ slug: z.ZodString;
22
+ title: z.ZodString;
23
+ email: z.ZodString;
24
+ site_id: z.ZodOptional<z.ZodString>;
25
+ }, "strict", z.ZodTypeAny, {
26
+ slug: string;
27
+ title: string;
28
+ email: string;
29
+ site_id?: string | undefined;
30
+ }, {
31
+ slug: string;
32
+ title: string;
33
+ email: string;
34
+ site_id?: string | undefined;
35
+ }>;
36
+ declare const msActivateSiteSchema: z.ZodObject<{
37
+ blog_id: z.ZodNumber;
38
+ active: z.ZodBoolean;
39
+ site_id: z.ZodOptional<z.ZodString>;
40
+ }, "strict", z.ZodTypeAny, {
41
+ active: boolean;
42
+ blog_id: number;
43
+ site_id?: string | undefined;
44
+ }, {
45
+ active: boolean;
46
+ blog_id: number;
47
+ site_id?: string | undefined;
48
+ }>;
49
+ declare const msDeleteSiteSchema: z.ZodObject<{
50
+ blog_id: z.ZodNumber;
51
+ confirm: z.ZodLiteral<true>;
52
+ site_id: z.ZodOptional<z.ZodString>;
53
+ }, "strict", z.ZodTypeAny, {
54
+ blog_id: number;
55
+ confirm: true;
56
+ site_id?: string | undefined;
57
+ }, {
58
+ blog_id: number;
59
+ confirm: true;
60
+ site_id?: string | undefined;
61
+ }>;
62
+ export declare const multisiteSiteTools: Tool[];
63
+ export declare const multisiteSiteHandlers: {
64
+ ms_list_sites: (params: z.infer<typeof msListSitesSchema>) => Promise<{
65
+ toolResult: {
66
+ content: {
67
+ type: string;
68
+ text: string;
69
+ }[];
70
+ isError?: undefined;
71
+ };
72
+ } | {
73
+ toolResult: {
74
+ isError: boolean;
75
+ content: {
76
+ type: string;
77
+ text: string;
78
+ }[];
79
+ };
80
+ }>;
81
+ ms_get_site: (params: z.infer<typeof msGetSiteSchema>) => Promise<{
82
+ toolResult: {
83
+ content: {
84
+ type: string;
85
+ text: string;
86
+ }[];
87
+ isError?: undefined;
88
+ };
89
+ } | {
90
+ toolResult: {
91
+ isError: boolean;
92
+ content: {
93
+ type: string;
94
+ text: string;
95
+ }[];
96
+ };
97
+ }>;
98
+ ms_create_site: (params: z.infer<typeof msCreateSiteSchema>) => Promise<{
99
+ toolResult: {
100
+ content: {
101
+ type: string;
102
+ text: string;
103
+ }[];
104
+ isError?: undefined;
105
+ };
106
+ } | {
107
+ toolResult: {
108
+ isError: boolean;
109
+ content: {
110
+ type: string;
111
+ text: string;
112
+ }[];
113
+ };
114
+ }>;
115
+ ms_activate_site: (params: z.infer<typeof msActivateSiteSchema>) => Promise<{
116
+ toolResult: {
117
+ content: {
118
+ type: string;
119
+ text: string;
120
+ }[];
121
+ isError?: undefined;
122
+ };
123
+ } | {
124
+ toolResult: {
125
+ isError: boolean;
126
+ content: {
127
+ type: string;
128
+ text: string;
129
+ }[];
130
+ };
131
+ }>;
132
+ ms_delete_site: (params: z.infer<typeof msDeleteSiteSchema>) => Promise<{
133
+ toolResult: {
134
+ content: {
135
+ type: string;
136
+ text: string;
137
+ }[];
138
+ isError?: undefined;
139
+ };
140
+ } | {
141
+ toolResult: {
142
+ isError: boolean;
143
+ content: {
144
+ type: string;
145
+ text: string;
146
+ }[];
147
+ };
148
+ }>;
149
+ };
150
+ export {};
@@ -0,0 +1,160 @@
1
+ import { executeWpCli, isMultisite } from '../wpcli.js';
2
+ import { z } from 'zod';
3
+ // ── Schemas ──────────────────────────────────────────────────────────
4
+ const msListSitesSchema = z.object({
5
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
6
+ }).strict();
7
+ const msGetSiteSchema = z.object({
8
+ blog_id: z.number().describe('Blog ID of the sub-site to retrieve'),
9
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
10
+ }).strict();
11
+ const msCreateSiteSchema = z.object({
12
+ slug: z.string().describe('URL slug for the new sub-site (e.g., "blog", "shop")'),
13
+ title: z.string().describe('Title of the new sub-site'),
14
+ email: z.string().describe('Admin email for the new sub-site'),
15
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
16
+ }).strict();
17
+ const msActivateSiteSchema = z.object({
18
+ blog_id: z.number().describe('Blog ID of the sub-site'),
19
+ active: z.boolean().describe('true to activate, false to deactivate'),
20
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
21
+ }).strict();
22
+ const msDeleteSiteSchema = z.object({
23
+ blog_id: z.number().describe('Blog ID of the sub-site to delete'),
24
+ confirm: z.literal(true).describe('Must be true to confirm deletion (safety gate)'),
25
+ site_id: z.string().optional().describe('Target site ID (defaults to active site)')
26
+ }).strict();
27
+ // ── Tools ────────────────────────────────────────────────────────────
28
+ export const multisiteSiteTools = [
29
+ {
30
+ name: 'ms_list_sites',
31
+ description: 'Lists all sub-sites in a WordPress Multisite network. Requires wp-cli and is_multisite configuration.',
32
+ inputSchema: { type: 'object', properties: msListSitesSchema.shape }
33
+ },
34
+ {
35
+ name: 'ms_get_site',
36
+ description: 'Gets details of a specific sub-site by blog ID.',
37
+ inputSchema: { type: 'object', properties: msGetSiteSchema.shape }
38
+ },
39
+ {
40
+ name: 'ms_create_site',
41
+ description: 'Creates a new sub-site in the multisite network.',
42
+ inputSchema: { type: 'object', properties: msCreateSiteSchema.shape }
43
+ },
44
+ {
45
+ name: 'ms_activate_site',
46
+ description: 'Activates or deactivates a sub-site in the multisite network.',
47
+ inputSchema: { type: 'object', properties: msActivateSiteSchema.shape }
48
+ },
49
+ {
50
+ name: 'ms_delete_site',
51
+ description: 'Permanently deletes a sub-site. Requires confirm: true as safety gate.',
52
+ inputSchema: { type: 'object', properties: msDeleteSiteSchema.shape }
53
+ }
54
+ ];
55
+ // ── Helpers ──────────────────────────────────────────────────────────
56
+ function requireMultisite(siteId) {
57
+ if (!isMultisite(siteId)) {
58
+ throw new Error(`Site is not configured as multisite. ` +
59
+ `Set is_multisite: true in WP_SITES_CONFIG.`);
60
+ }
61
+ }
62
+ // ── Handlers ─────────────────────────────────────────────────────────
63
+ export const multisiteSiteHandlers = {
64
+ ms_list_sites: async (params) => {
65
+ try {
66
+ requireMultisite(params.site_id);
67
+ const result = await executeWpCli('site list', params.site_id);
68
+ return {
69
+ toolResult: {
70
+ content: [{ type: 'text', text: result }]
71
+ }
72
+ };
73
+ }
74
+ catch (error) {
75
+ return {
76
+ toolResult: {
77
+ isError: true,
78
+ content: [{ type: 'text', text: `Error listing sites: ${error.message}` }]
79
+ }
80
+ };
81
+ }
82
+ },
83
+ ms_get_site: async (params) => {
84
+ try {
85
+ requireMultisite(params.site_id);
86
+ const result = await executeWpCli(`site list --blog_id=${params.blog_id}`, params.site_id);
87
+ return {
88
+ toolResult: {
89
+ content: [{ type: 'text', text: result }]
90
+ }
91
+ };
92
+ }
93
+ catch (error) {
94
+ return {
95
+ toolResult: {
96
+ isError: true,
97
+ content: [{ type: 'text', text: `Error getting site: ${error.message}` }]
98
+ }
99
+ };
100
+ }
101
+ },
102
+ ms_create_site: async (params) => {
103
+ try {
104
+ requireMultisite(params.site_id);
105
+ const result = await executeWpCli(`site create --slug=${params.slug} --title="${params.title}" --email=${params.email}`, params.site_id, { skipJson: true });
106
+ return {
107
+ toolResult: {
108
+ content: [{ type: 'text', text: result }]
109
+ }
110
+ };
111
+ }
112
+ catch (error) {
113
+ return {
114
+ toolResult: {
115
+ isError: true,
116
+ content: [{ type: 'text', text: `Error creating site: ${error.message}` }]
117
+ }
118
+ };
119
+ }
120
+ },
121
+ ms_activate_site: async (params) => {
122
+ try {
123
+ requireMultisite(params.site_id);
124
+ const action = params.active ? 'activate' : 'deactivate';
125
+ const result = await executeWpCli(`site ${action} ${params.blog_id}`, params.site_id, { skipJson: true });
126
+ return {
127
+ toolResult: {
128
+ content: [{ type: 'text', text: result || `Site ${params.blog_id} ${action}d successfully.` }]
129
+ }
130
+ };
131
+ }
132
+ catch (error) {
133
+ return {
134
+ toolResult: {
135
+ isError: true,
136
+ content: [{ type: 'text', text: `Error ${params.active ? 'activating' : 'deactivating'} site: ${error.message}` }]
137
+ }
138
+ };
139
+ }
140
+ },
141
+ ms_delete_site: async (params) => {
142
+ try {
143
+ requireMultisite(params.site_id);
144
+ const result = await executeWpCli(`site delete ${params.blog_id} --yes`, params.site_id, { skipJson: true });
145
+ return {
146
+ toolResult: {
147
+ content: [{ type: 'text', text: result || `Site ${params.blog_id} deleted successfully.` }]
148
+ }
149
+ };
150
+ }
151
+ catch (error) {
152
+ return {
153
+ toolResult: {
154
+ isError: true,
155
+ content: [{ type: 'text', text: `Error deleting site: ${error.message}` }]
156
+ }
157
+ };
158
+ }
159
+ }
160
+ };