claude-plugin-wordpress-manager 1.4.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 (142) hide show
  1. package/.claude-plugin/plugin.json +19 -0
  2. package/.mcp.json +19 -0
  3. package/CHANGELOG.md +62 -0
  4. package/LICENSE +69 -0
  5. package/README.md +213 -0
  6. package/agents/wp-content-strategist.md +148 -0
  7. package/agents/wp-deployment-engineer.md +93 -0
  8. package/agents/wp-performance-optimizer.md +198 -0
  9. package/agents/wp-security-auditor.md +161 -0
  10. package/agents/wp-site-manager.md +109 -0
  11. package/commands/wp-audit.md +37 -0
  12. package/commands/wp-backup.md +45 -0
  13. package/commands/wp-deploy.md +38 -0
  14. package/commands/wp-setup.md +64 -0
  15. package/commands/wp-status.md +53 -0
  16. package/docs/GUIDE.md +1190 -0
  17. package/hooks/hooks.json +57 -0
  18. package/hooks/scripts/backup-reminder.sh +29 -0
  19. package/hooks/scripts/pre-deploy-check.sh +49 -0
  20. package/package.json +46 -0
  21. package/scripts/health-check.sh +110 -0
  22. package/scripts/validate-wp-operation.sh +115 -0
  23. package/servers/wp-rest-bridge/build/server.d.ts +2 -0
  24. package/servers/wp-rest-bridge/build/server.js +74 -0
  25. package/servers/wp-rest-bridge/build/tools/comments.d.ts +227 -0
  26. package/servers/wp-rest-bridge/build/tools/comments.js +192 -0
  27. package/servers/wp-rest-bridge/build/tools/index.d.ts +919 -0
  28. package/servers/wp-rest-bridge/build/tools/index.js +30 -0
  29. package/servers/wp-rest-bridge/build/tools/media.d.ts +174 -0
  30. package/servers/wp-rest-bridge/build/tools/media.js +247 -0
  31. package/servers/wp-rest-bridge/build/tools/plugin-repository.d.ts +62 -0
  32. package/servers/wp-rest-bridge/build/tools/plugin-repository.js +149 -0
  33. package/servers/wp-rest-bridge/build/tools/plugins.d.ts +153 -0
  34. package/servers/wp-rest-bridge/build/tools/plugins.js +175 -0
  35. package/servers/wp-rest-bridge/build/tools/search.d.ts +44 -0
  36. package/servers/wp-rest-bridge/build/tools/search.js +44 -0
  37. package/servers/wp-rest-bridge/build/tools/unified-content.d.ts +328 -0
  38. package/servers/wp-rest-bridge/build/tools/unified-content.js +628 -0
  39. package/servers/wp-rest-bridge/build/tools/unified-taxonomies.d.ts +244 -0
  40. package/servers/wp-rest-bridge/build/tools/unified-taxonomies.js +492 -0
  41. package/servers/wp-rest-bridge/build/tools/users.d.ts +269 -0
  42. package/servers/wp-rest-bridge/build/tools/users.js +226 -0
  43. package/servers/wp-rest-bridge/build/types.d.ts +151 -0
  44. package/servers/wp-rest-bridge/build/types.js +2 -0
  45. package/servers/wp-rest-bridge/build/wordpress.d.ts +48 -0
  46. package/servers/wp-rest-bridge/build/wordpress.js +305 -0
  47. package/servers/wp-rest-bridge/package.json +27 -0
  48. package/skills/wordpress-router/SKILL.md +78 -0
  49. package/skills/wordpress-router/references/decision-tree.md +88 -0
  50. package/skills/wp-abilities-api/SKILL.md +97 -0
  51. package/skills/wp-abilities-api/references/php-registration.md +67 -0
  52. package/skills/wp-abilities-api/references/rest-api.md +13 -0
  53. package/skills/wp-audit/SKILL.md +114 -0
  54. package/skills/wp-audit/references/performance-checklist.md +113 -0
  55. package/skills/wp-audit/references/security-checklist.md +95 -0
  56. package/skills/wp-audit/references/seo-checklist.md +128 -0
  57. package/skills/wp-backup/SKILL.md +87 -0
  58. package/skills/wp-backup/references/backup-strategies.md +116 -0
  59. package/skills/wp-backup/references/restore-procedures.md +129 -0
  60. package/skills/wp-block-development/SKILL.md +176 -0
  61. package/skills/wp-block-development/references/attributes-and-serialization.md +22 -0
  62. package/skills/wp-block-development/references/block-json.md +49 -0
  63. package/skills/wp-block-development/references/creating-new-blocks.md +46 -0
  64. package/skills/wp-block-development/references/debugging.md +36 -0
  65. package/skills/wp-block-development/references/deprecations.md +24 -0
  66. package/skills/wp-block-development/references/dynamic-rendering.md +23 -0
  67. package/skills/wp-block-development/references/inner-blocks.md +25 -0
  68. package/skills/wp-block-development/references/registration.md +30 -0
  69. package/skills/wp-block-development/references/supports-and-wrappers.md +18 -0
  70. package/skills/wp-block-development/references/tooling-and-testing.md +21 -0
  71. package/skills/wp-block-development/scripts/list_blocks.mjs +121 -0
  72. package/skills/wp-block-themes/SKILL.md +118 -0
  73. package/skills/wp-block-themes/references/creating-new-block-theme.md +37 -0
  74. package/skills/wp-block-themes/references/debugging.md +24 -0
  75. package/skills/wp-block-themes/references/patterns.md +18 -0
  76. package/skills/wp-block-themes/references/style-variations.md +14 -0
  77. package/skills/wp-block-themes/references/templates-and-parts.md +16 -0
  78. package/skills/wp-block-themes/references/theme-json.md +59 -0
  79. package/skills/wp-block-themes/scripts/detect_block_themes.mjs +117 -0
  80. package/skills/wp-content/SKILL.md +103 -0
  81. package/skills/wp-content/references/content-templates.md +230 -0
  82. package/skills/wp-content/references/seo-optimization.md +169 -0
  83. package/skills/wp-deploy/SKILL.md +52 -0
  84. package/skills/wp-deploy/references/hostinger-deploy.md +51 -0
  85. package/skills/wp-deploy/references/ssh-deploy.md +63 -0
  86. package/skills/wp-interactivity-api/SKILL.md +181 -0
  87. package/skills/wp-interactivity-api/references/debugging.md +29 -0
  88. package/skills/wp-interactivity-api/references/directives-quickref.md +30 -0
  89. package/skills/wp-interactivity-api/references/server-side-rendering.md +310 -0
  90. package/skills/wp-migrate/SKILL.md +100 -0
  91. package/skills/wp-migrate/references/cross-platform.md +104 -0
  92. package/skills/wp-migrate/references/hostinger-migration.md +86 -0
  93. package/skills/wp-performance/SKILL.md +148 -0
  94. package/skills/wp-performance/references/autoload-options.md +24 -0
  95. package/skills/wp-performance/references/cron.md +20 -0
  96. package/skills/wp-performance/references/database.md +20 -0
  97. package/skills/wp-performance/references/http-api.md +15 -0
  98. package/skills/wp-performance/references/measurement.md +21 -0
  99. package/skills/wp-performance/references/object-cache.md +24 -0
  100. package/skills/wp-performance/references/query-monitor-headless.md +38 -0
  101. package/skills/wp-performance/references/server-timing.md +22 -0
  102. package/skills/wp-performance/references/wp-cli-doctor.md +24 -0
  103. package/skills/wp-performance/references/wp-cli-profile.md +32 -0
  104. package/skills/wp-performance/scripts/perf_inspect.mjs +128 -0
  105. package/skills/wp-phpstan/SKILL.md +99 -0
  106. package/skills/wp-phpstan/references/configuration.md +52 -0
  107. package/skills/wp-phpstan/references/third-party-classes.md +76 -0
  108. package/skills/wp-phpstan/references/wordpress-annotations.md +124 -0
  109. package/skills/wp-phpstan/scripts/phpstan_inspect.mjs +263 -0
  110. package/skills/wp-playground/SKILL.md +103 -0
  111. package/skills/wp-playground/references/blueprints.md +36 -0
  112. package/skills/wp-playground/references/cli-commands.md +39 -0
  113. package/skills/wp-playground/references/debugging.md +16 -0
  114. package/skills/wp-plugin-development/SKILL.md +114 -0
  115. package/skills/wp-plugin-development/references/data-and-cron.md +19 -0
  116. package/skills/wp-plugin-development/references/debugging.md +19 -0
  117. package/skills/wp-plugin-development/references/lifecycle.md +33 -0
  118. package/skills/wp-plugin-development/references/security.md +29 -0
  119. package/skills/wp-plugin-development/references/settings-api.md +22 -0
  120. package/skills/wp-plugin-development/references/structure.md +16 -0
  121. package/skills/wp-plugin-development/scripts/detect_plugins.mjs +122 -0
  122. package/skills/wp-project-triage/SKILL.md +40 -0
  123. package/skills/wp-project-triage/references/triage.schema.json +143 -0
  124. package/skills/wp-project-triage/scripts/detect_wp_project.mjs +592 -0
  125. package/skills/wp-rest-api/SKILL.md +116 -0
  126. package/skills/wp-rest-api/references/authentication.md +18 -0
  127. package/skills/wp-rest-api/references/custom-content-types.md +20 -0
  128. package/skills/wp-rest-api/references/discovery-and-params.md +20 -0
  129. package/skills/wp-rest-api/references/responses-and-fields.md +30 -0
  130. package/skills/wp-rest-api/references/routes-and-endpoints.md +36 -0
  131. package/skills/wp-rest-api/references/schema.md +22 -0
  132. package/skills/wp-wpcli-and-ops/SKILL.md +125 -0
  133. package/skills/wp-wpcli-and-ops/references/automation.md +30 -0
  134. package/skills/wp-wpcli-and-ops/references/cron-and-cache.md +23 -0
  135. package/skills/wp-wpcli-and-ops/references/debugging.md +17 -0
  136. package/skills/wp-wpcli-and-ops/references/multisite.md +22 -0
  137. package/skills/wp-wpcli-and-ops/references/packages-and-updates.md +22 -0
  138. package/skills/wp-wpcli-and-ops/references/safety.md +30 -0
  139. package/skills/wp-wpcli-and-ops/references/search-replace.md +40 -0
  140. package/skills/wp-wpcli-and-ops/scripts/wpcli_inspect.mjs +90 -0
  141. package/skills/wpds/SKILL.md +60 -0
  142. package/skills/wpds/references/wpds-mcp-setup.md +59 -0
@@ -0,0 +1,30 @@
1
+ import { unifiedContentTools, unifiedContentHandlers } from './unified-content.js';
2
+ import { unifiedTaxonomyTools, unifiedTaxonomyHandlers } from './unified-taxonomies.js';
3
+ import { pluginTools, pluginHandlers } from './plugins.js';
4
+ import { mediaTools, mediaHandlers } from './media.js';
5
+ import { userTools, userHandlers } from './users.js';
6
+ import { pluginRepositoryTools, pluginRepositoryHandlers } from './plugin-repository.js';
7
+ import { commentTools, commentHandlers } from './comments.js';
8
+ import { searchTools, searchHandlers } from './search.js';
9
+ // Combine all tools
10
+ export const allTools = [
11
+ ...unifiedContentTools, // 8 tools
12
+ ...unifiedTaxonomyTools, // 8 tools
13
+ ...pluginTools, // 6 tools
14
+ ...mediaTools, // 5 tools
15
+ ...userTools, // 6 tools
16
+ ...pluginRepositoryTools, // 2 tools
17
+ ...commentTools, // 5 tools
18
+ ...searchTools // 1 tool
19
+ ];
20
+ // Combine all handlers
21
+ export const toolHandlers = {
22
+ ...unifiedContentHandlers,
23
+ ...unifiedTaxonomyHandlers,
24
+ ...pluginHandlers,
25
+ ...mediaHandlers,
26
+ ...userHandlers,
27
+ ...pluginRepositoryHandlers,
28
+ ...commentHandlers,
29
+ ...searchHandlers
30
+ };
@@ -0,0 +1,174 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import { z } from 'zod';
3
+ declare const listMediaSchema: z.ZodObject<{
4
+ page: z.ZodOptional<z.ZodNumber>;
5
+ per_page: z.ZodOptional<z.ZodNumber>;
6
+ search: z.ZodOptional<z.ZodString>;
7
+ _embed: z.ZodOptional<z.ZodBoolean>;
8
+ _fields: z.ZodOptional<z.ZodString>;
9
+ include_pagination: z.ZodOptional<z.ZodBoolean>;
10
+ }, "strict", z.ZodTypeAny, {
11
+ page?: number | undefined;
12
+ per_page?: number | undefined;
13
+ search?: string | undefined;
14
+ _embed?: boolean | undefined;
15
+ _fields?: string | undefined;
16
+ include_pagination?: boolean | undefined;
17
+ }, {
18
+ page?: number | undefined;
19
+ per_page?: number | undefined;
20
+ search?: string | undefined;
21
+ _embed?: boolean | undefined;
22
+ _fields?: string | undefined;
23
+ include_pagination?: boolean | undefined;
24
+ }>;
25
+ declare const getMediaSchema: z.ZodObject<{
26
+ id: z.ZodNumber;
27
+ _embed: z.ZodOptional<z.ZodBoolean>;
28
+ _fields: z.ZodOptional<z.ZodString>;
29
+ }, "strict", z.ZodTypeAny, {
30
+ id: number;
31
+ _embed?: boolean | undefined;
32
+ _fields?: string | undefined;
33
+ }, {
34
+ id: number;
35
+ _embed?: boolean | undefined;
36
+ _fields?: string | undefined;
37
+ }>;
38
+ declare const createMediaSchema: z.ZodObject<{
39
+ title: z.ZodString;
40
+ alt_text: z.ZodOptional<z.ZodString>;
41
+ caption: z.ZodOptional<z.ZodString>;
42
+ description: z.ZodOptional<z.ZodString>;
43
+ source_url: z.ZodString;
44
+ }, "strict", z.ZodTypeAny, {
45
+ title: string;
46
+ source_url: string;
47
+ description?: string | undefined;
48
+ alt_text?: string | undefined;
49
+ caption?: string | undefined;
50
+ }, {
51
+ title: string;
52
+ source_url: string;
53
+ description?: string | undefined;
54
+ alt_text?: string | undefined;
55
+ caption?: string | undefined;
56
+ }>;
57
+ declare const editMediaSchema: z.ZodObject<{
58
+ id: z.ZodNumber;
59
+ title: z.ZodOptional<z.ZodString>;
60
+ alt_text: z.ZodOptional<z.ZodString>;
61
+ caption: z.ZodOptional<z.ZodString>;
62
+ description: z.ZodOptional<z.ZodString>;
63
+ }, "strict", z.ZodTypeAny, {
64
+ id: number;
65
+ title?: string | undefined;
66
+ description?: string | undefined;
67
+ alt_text?: string | undefined;
68
+ caption?: string | undefined;
69
+ }, {
70
+ id: number;
71
+ title?: string | undefined;
72
+ description?: string | undefined;
73
+ alt_text?: string | undefined;
74
+ caption?: string | undefined;
75
+ }>;
76
+ declare const deleteMediaSchema: z.ZodObject<{
77
+ id: z.ZodNumber;
78
+ force: z.ZodOptional<z.ZodBoolean>;
79
+ }, "strict", z.ZodTypeAny, {
80
+ id: number;
81
+ force?: boolean | undefined;
82
+ }, {
83
+ id: number;
84
+ force?: boolean | undefined;
85
+ }>;
86
+ export declare const mediaTools: Tool[];
87
+ export declare const mediaHandlers: {
88
+ list_media: (params: z.infer<typeof listMediaSchema>) => Promise<{
89
+ toolResult: {
90
+ content: {
91
+ type: string;
92
+ text: string;
93
+ }[];
94
+ isError?: undefined;
95
+ };
96
+ } | {
97
+ toolResult: {
98
+ isError: boolean;
99
+ content: {
100
+ type: string;
101
+ text: string;
102
+ }[];
103
+ };
104
+ }>;
105
+ get_media: (params: z.infer<typeof getMediaSchema>) => Promise<{
106
+ toolResult: {
107
+ content: {
108
+ type: string;
109
+ text: string;
110
+ }[];
111
+ isError?: undefined;
112
+ };
113
+ } | {
114
+ toolResult: {
115
+ isError: boolean;
116
+ content: {
117
+ type: string;
118
+ text: string;
119
+ }[];
120
+ };
121
+ }>;
122
+ create_media: (params: z.infer<typeof createMediaSchema>) => Promise<{
123
+ toolResult: {
124
+ content: {
125
+ type: string;
126
+ text: string;
127
+ }[];
128
+ isError?: undefined;
129
+ };
130
+ } | {
131
+ toolResult: {
132
+ isError: boolean;
133
+ content: {
134
+ type: string;
135
+ text: string;
136
+ }[];
137
+ };
138
+ }>;
139
+ edit_media: (params: z.infer<typeof editMediaSchema>) => Promise<{
140
+ toolResult: {
141
+ content: {
142
+ type: string;
143
+ text: string;
144
+ }[];
145
+ isError?: undefined;
146
+ };
147
+ } | {
148
+ toolResult: {
149
+ isError: boolean;
150
+ content: {
151
+ type: string;
152
+ text: string;
153
+ }[];
154
+ };
155
+ }>;
156
+ delete_media: (params: z.infer<typeof deleteMediaSchema>) => Promise<{
157
+ toolResult: {
158
+ content: {
159
+ type: string;
160
+ text: string;
161
+ }[];
162
+ isError?: undefined;
163
+ };
164
+ } | {
165
+ toolResult: {
166
+ isError: boolean;
167
+ content: {
168
+ type: string;
169
+ text: string;
170
+ }[];
171
+ };
172
+ }>;
173
+ };
174
+ export {};
@@ -0,0 +1,247 @@
1
+ import { makeWordPressRequest } from '../wordpress.js';
2
+ import { z } from 'zod';
3
+ // MIME type to file extension map
4
+ const MIME_EXT_MAP = {
5
+ 'image/jpeg': 'jpg',
6
+ 'image/png': 'png',
7
+ 'image/gif': 'gif',
8
+ 'image/webp': 'webp',
9
+ 'image/svg+xml': 'svg',
10
+ 'image/bmp': 'bmp',
11
+ 'image/tiff': 'tiff',
12
+ 'video/mp4': 'mp4',
13
+ 'video/webm': 'webm',
14
+ 'audio/mpeg': 'mp3',
15
+ 'audio/ogg': 'ogg',
16
+ 'application/pdf': 'pdf',
17
+ };
18
+ function getExtFromMime(contentType) {
19
+ if (!contentType)
20
+ return undefined;
21
+ // Strip charset and params: "image/jpeg; charset=utf-8" → "image/jpeg"
22
+ const mime = contentType.split(';')[0].trim().toLowerCase();
23
+ return MIME_EXT_MAP[mime];
24
+ }
25
+ function getExtFromUrl(url) {
26
+ try {
27
+ const pathname = new URL(url).pathname;
28
+ const match = pathname.match(/\.(\w{2,5})$/);
29
+ return match ? match[1].toLowerCase() : undefined;
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ }
35
+ // Schema for listing media items
36
+ const listMediaSchema = z.object({
37
+ page: z.number().optional().describe("Page number"),
38
+ per_page: z.number().min(1).max(100).optional().describe("Items per page"),
39
+ search: z.string().optional().describe("Search term for media"),
40
+ _embed: z.boolean().optional().describe("Inline related resources"),
41
+ _fields: z.string().optional().describe("Comma-separated list of fields to return"),
42
+ include_pagination: z.boolean().optional().describe("Include pagination metadata in response")
43
+ }).strict();
44
+ // Schema for getting a single media item
45
+ const getMediaSchema = z.object({
46
+ id: z.number().describe("Media ID"),
47
+ _embed: z.boolean().optional().describe("Inline related resources"),
48
+ _fields: z.string().optional().describe("Comma-separated list of fields to return")
49
+ }).strict();
50
+ // Schema for creating a new media item
51
+ const createMediaSchema = z.object({
52
+ title: z.string().describe("Media title"),
53
+ alt_text: z.string().optional().describe("Alternate text for the media"),
54
+ caption: z.string().optional().describe("Caption of the media"),
55
+ description: z.string().optional().describe("Description of the media"),
56
+ source_url: z.string().describe("Source URL of the media file")
57
+ }).strict();
58
+ // Schema for editing an existing media item
59
+ const editMediaSchema = z.object({
60
+ id: z.number().describe("Media ID to edit"),
61
+ title: z.string().optional().describe("Media title"),
62
+ alt_text: z.string().optional().describe("Alternate text for the media"),
63
+ caption: z.string().optional().describe("Caption of the media"),
64
+ description: z.string().optional().describe("Description of the media")
65
+ }).strict();
66
+ // Schema for deleting a media item
67
+ const deleteMediaSchema = z.object({
68
+ id: z.number().describe("Media ID to delete"),
69
+ force: z.boolean().optional().describe("Force deletion bypassing trash")
70
+ }).strict();
71
+ // Define the tool set for media operations
72
+ export const mediaTools = [
73
+ {
74
+ name: "list_media",
75
+ description: "Lists media items with filtering and pagination options",
76
+ inputSchema: { type: "object", properties: listMediaSchema.shape }
77
+ },
78
+ {
79
+ name: "get_media",
80
+ description: "Gets a single media item by ID",
81
+ inputSchema: { type: "object", properties: getMediaSchema.shape }
82
+ },
83
+ {
84
+ name: "create_media",
85
+ description: "Creates a new media item",
86
+ inputSchema: { type: "object", properties: createMediaSchema.shape }
87
+ },
88
+ {
89
+ name: "edit_media",
90
+ description: "Updates an existing media item",
91
+ inputSchema: { type: "object", properties: editMediaSchema.shape }
92
+ },
93
+ {
94
+ name: "delete_media",
95
+ description: "Deletes a media item",
96
+ inputSchema: { type: "object", properties: deleteMediaSchema.shape }
97
+ }
98
+ ];
99
+ // Define handlers for each media operation
100
+ export const mediaHandlers = {
101
+ list_media: async (params) => {
102
+ try {
103
+ const { include_pagination, ...queryParams } = params;
104
+ const response = await makeWordPressRequest("GET", "media", queryParams, {
105
+ includePagination: include_pagination,
106
+ });
107
+ return {
108
+ toolResult: {
109
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }]
110
+ }
111
+ };
112
+ }
113
+ catch (error) {
114
+ const errorMessage = error.response?.data?.message || error.message;
115
+ return {
116
+ toolResult: {
117
+ isError: true,
118
+ content: [{ type: "text", text: `Error listing media: ${errorMessage}` }]
119
+ }
120
+ };
121
+ }
122
+ },
123
+ get_media: async (params) => {
124
+ try {
125
+ const queryParams = {};
126
+ if (params._embed)
127
+ queryParams._embed = true;
128
+ if (params._fields)
129
+ queryParams._fields = params._fields;
130
+ const response = await makeWordPressRequest("GET", `media/${params.id}`, queryParams);
131
+ return {
132
+ toolResult: {
133
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }]
134
+ }
135
+ };
136
+ }
137
+ catch (error) {
138
+ const errorMessage = error.response?.data?.message || error.message;
139
+ return {
140
+ toolResult: {
141
+ isError: true,
142
+ content: [{ type: "text", text: `Error getting media: ${errorMessage}` }]
143
+ }
144
+ };
145
+ }
146
+ },
147
+ create_media: async (params) => {
148
+ try {
149
+ if (params.source_url && params.source_url.startsWith('http')) {
150
+ // Download the media file from the URL and upload as multipart form-data
151
+ const axios = (await import('axios')).default;
152
+ const FormData = (await import('form-data')).default;
153
+ const fileRes = await axios.get(params.source_url, { responseType: 'arraybuffer' });
154
+ // Derive extension from content-type header or source URL
155
+ const ext = getExtFromMime(fileRes.headers['content-type'])
156
+ || getExtFromUrl(params.source_url)
157
+ || 'jpg';
158
+ const basename = params.title ? params.title.replace(/\s+/g, '_') : 'upload';
159
+ const filename = `${basename}.${ext}`;
160
+ const form = new FormData();
161
+ form.append('file', Buffer.from(fileRes.data), {
162
+ filename: filename,
163
+ contentType: fileRes.headers['content-type'] || 'application/octet-stream'
164
+ });
165
+ // Append additional fields if provided
166
+ if (params.title)
167
+ form.append('title', params.title);
168
+ if (params.alt_text)
169
+ form.append('alt_text', params.alt_text);
170
+ if (params.caption)
171
+ form.append('caption', params.caption);
172
+ if (params.description)
173
+ form.append('description', params.description);
174
+ // Use the enhanced makeWordPressRequest function with FormData support
175
+ // Media uploads get a longer timeout (120s)
176
+ const response = await makeWordPressRequest('POST', 'media', form, {
177
+ isFormData: true,
178
+ headers: form.getHeaders(),
179
+ rawResponse: true,
180
+ timeout: 120000
181
+ });
182
+ return {
183
+ toolResult: {
184
+ content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }]
185
+ }
186
+ };
187
+ }
188
+ else {
189
+ const response = await makeWordPressRequest("POST", "media", params);
190
+ return {
191
+ toolResult: {
192
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }]
193
+ }
194
+ };
195
+ }
196
+ }
197
+ catch (error) {
198
+ const errorMessage = error.response?.data?.message || error.message;
199
+ return {
200
+ toolResult: {
201
+ isError: true,
202
+ content: [{ type: "text", text: `Error creating media: ${errorMessage}` }]
203
+ }
204
+ };
205
+ }
206
+ },
207
+ edit_media: async (params) => {
208
+ try {
209
+ const { id, ...updateData } = params;
210
+ const response = await makeWordPressRequest("POST", `media/${id}`, updateData);
211
+ return {
212
+ toolResult: {
213
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }]
214
+ }
215
+ };
216
+ }
217
+ catch (error) {
218
+ const errorMessage = error.response?.data?.message || error.message;
219
+ return {
220
+ toolResult: {
221
+ isError: true,
222
+ content: [{ type: "text", text: `Error editing media: ${errorMessage}` }]
223
+ }
224
+ };
225
+ }
226
+ },
227
+ delete_media: async (params) => {
228
+ try {
229
+ const { id, ...deleteData } = params;
230
+ const response = await makeWordPressRequest("DELETE", `media/${id}`, deleteData);
231
+ return {
232
+ toolResult: {
233
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }]
234
+ }
235
+ };
236
+ }
237
+ catch (error) {
238
+ const errorMessage = error.response?.data?.message || error.message;
239
+ return {
240
+ toolResult: {
241
+ isError: true,
242
+ content: [{ type: "text", text: `Error deleting media: ${errorMessage}` }]
243
+ }
244
+ };
245
+ }
246
+ }
247
+ };
@@ -0,0 +1,62 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import { z } from 'zod';
3
+ declare const searchPluginRepositorySchema: z.ZodObject<{
4
+ search: z.ZodString;
5
+ page: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
6
+ per_page: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
7
+ }, "strict", z.ZodTypeAny, {
8
+ page: number;
9
+ per_page: number;
10
+ search: string;
11
+ }, {
12
+ search: string;
13
+ page?: number | undefined;
14
+ per_page?: number | undefined;
15
+ }>;
16
+ declare const getPluginDetailsSchema: z.ZodObject<{
17
+ slug: z.ZodString;
18
+ }, "strict", z.ZodTypeAny, {
19
+ slug: string;
20
+ }, {
21
+ slug: string;
22
+ }>;
23
+ type SearchPluginRepositoryParams = z.infer<typeof searchPluginRepositorySchema>;
24
+ type GetPluginDetailsParams = z.infer<typeof getPluginDetailsSchema>;
25
+ export declare const pluginRepositoryTools: Tool[];
26
+ export declare const pluginRepositoryHandlers: {
27
+ search_plugin_repository: (params: SearchPluginRepositoryParams) => Promise<{
28
+ toolResult: {
29
+ content: {
30
+ type: string;
31
+ text: string;
32
+ }[];
33
+ isError?: undefined;
34
+ };
35
+ } | {
36
+ toolResult: {
37
+ isError: boolean;
38
+ content: {
39
+ type: string;
40
+ text: string;
41
+ }[];
42
+ };
43
+ }>;
44
+ get_plugin_details: (params: GetPluginDetailsParams) => Promise<{
45
+ toolResult: {
46
+ content: {
47
+ type: string;
48
+ text: string;
49
+ }[];
50
+ isError?: undefined;
51
+ };
52
+ } | {
53
+ toolResult: {
54
+ isError: boolean;
55
+ content: {
56
+ type: string;
57
+ text: string;
58
+ }[];
59
+ };
60
+ }>;
61
+ };
62
+ export {};
@@ -0,0 +1,149 @@
1
+ import { searchWordPressPluginRepository } from '../wordpress.js';
2
+ import { z } from 'zod';
3
+ // Define the schema for plugin repository search
4
+ const searchPluginRepositorySchema = z.object({
5
+ search: z.string().describe("Search query for WordPress.org plugin repository"),
6
+ page: z.number().min(1).optional().default(1).describe("Page number (1-based)"),
7
+ per_page: z.number().min(1).max(100).optional().default(10).describe("Number of results per page (max 100)")
8
+ }).strict();
9
+ // Define the schema for getting plugin details
10
+ const getPluginDetailsSchema = z.object({
11
+ slug: z.string().describe("Plugin slug from WordPress.org repository")
12
+ }).strict();
13
+ // Define the plugin repository tools
14
+ export const pluginRepositoryTools = [
15
+ {
16
+ name: "search_plugin_repository",
17
+ description: "Search for plugins in the WordPress.org plugin repository",
18
+ inputSchema: { type: "object", properties: searchPluginRepositorySchema.shape }
19
+ },
20
+ {
21
+ name: "get_plugin_details",
22
+ description: "Get detailed information about a plugin from the WordPress.org repository",
23
+ inputSchema: { type: "object", properties: getPluginDetailsSchema.shape }
24
+ }
25
+ ];
26
+ // Define handlers for plugin repository operations
27
+ export const pluginRepositoryHandlers = {
28
+ search_plugin_repository: async (params) => {
29
+ try {
30
+ const response = await searchWordPressPluginRepository(params.search, params.page, params.per_page);
31
+ // Format the response to be more user-friendly
32
+ const formattedPlugins = response.plugins.map((plugin) => ({
33
+ name: plugin.name,
34
+ slug: plugin.slug,
35
+ version: plugin.version,
36
+ author: plugin.author,
37
+ requires_wp: plugin.requires,
38
+ tested: plugin.tested,
39
+ rating: plugin.rating,
40
+ active_installs: plugin.active_installs,
41
+ downloaded: plugin.downloaded,
42
+ last_updated: plugin.last_updated,
43
+ short_description: plugin.short_description,
44
+ download_link: plugin.download_link,
45
+ homepage: plugin.homepage
46
+ }));
47
+ const result = {
48
+ info: {
49
+ page: response.info.page,
50
+ pages: response.info.pages,
51
+ results: response.info.results
52
+ },
53
+ plugins: formattedPlugins
54
+ };
55
+ return {
56
+ toolResult: {
57
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
58
+ },
59
+ };
60
+ }
61
+ catch (error) {
62
+ const errorMessage = error.response?.data?.message || error.message;
63
+ return {
64
+ toolResult: {
65
+ isError: true,
66
+ content: [{ type: 'text', text: `Error searching plugin repository: ${errorMessage}` }],
67
+ },
68
+ };
69
+ }
70
+ },
71
+ get_plugin_details: async (params) => {
72
+ try {
73
+ // For plugin details, we use a different action in the WordPress.org API
74
+ const apiUrl = 'https://api.wordpress.org/plugins/info/1.2/';
75
+ const requestData = {
76
+ action: 'plugin_information',
77
+ request: {
78
+ slug: params.slug,
79
+ fields: {
80
+ description: true,
81
+ sections: true,
82
+ tested: true,
83
+ requires: true,
84
+ rating: true,
85
+ ratings: true,
86
+ downloaded: true,
87
+ downloadlink: true,
88
+ last_updated: true,
89
+ homepage: true,
90
+ tags: true,
91
+ compatibility: true,
92
+ author: true,
93
+ contributors: true,
94
+ banners: true,
95
+ icons: true
96
+ }
97
+ }
98
+ };
99
+ // Use axios directly for this specific request
100
+ const axios = (await import('axios')).default;
101
+ const response = await axios.post(apiUrl, requestData, {
102
+ headers: {
103
+ 'Content-Type': 'application/json'
104
+ }
105
+ });
106
+ // Format the plugin details
107
+ const plugin = response.data;
108
+ const formattedPlugin = {
109
+ name: plugin.name,
110
+ slug: plugin.slug,
111
+ version: plugin.version,
112
+ author: plugin.author,
113
+ author_profile: plugin.author_profile,
114
+ contributors: plugin.contributors,
115
+ requires_wp: plugin.requires,
116
+ tested: plugin.tested,
117
+ requires_php: plugin.requires_php,
118
+ rating: plugin.rating,
119
+ ratings: plugin.ratings,
120
+ active_installs: plugin.active_installs,
121
+ downloaded: plugin.downloaded,
122
+ last_updated: plugin.last_updated,
123
+ added: plugin.added,
124
+ homepage: plugin.homepage,
125
+ description: plugin.description,
126
+ short_description: plugin.short_description,
127
+ download_link: plugin.download_link,
128
+ tags: plugin.tags,
129
+ sections: plugin.sections,
130
+ banners: plugin.banners,
131
+ icons: plugin.icons
132
+ };
133
+ return {
134
+ toolResult: {
135
+ content: [{ type: 'text', text: JSON.stringify(formattedPlugin, null, 2) }],
136
+ },
137
+ };
138
+ }
139
+ catch (error) {
140
+ const errorMessage = error.response?.data?.message || error.message;
141
+ return {
142
+ toolResult: {
143
+ isError: true,
144
+ content: [{ type: 'text', text: `Error getting plugin details: ${errorMessage}` }],
145
+ },
146
+ };
147
+ }
148
+ }
149
+ };