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.
- package/.claude-plugin/plugin.json +19 -0
- package/.mcp.json +19 -0
- package/CHANGELOG.md +62 -0
- package/LICENSE +69 -0
- package/README.md +213 -0
- package/agents/wp-content-strategist.md +148 -0
- package/agents/wp-deployment-engineer.md +93 -0
- package/agents/wp-performance-optimizer.md +198 -0
- package/agents/wp-security-auditor.md +161 -0
- package/agents/wp-site-manager.md +109 -0
- package/commands/wp-audit.md +37 -0
- package/commands/wp-backup.md +45 -0
- package/commands/wp-deploy.md +38 -0
- package/commands/wp-setup.md +64 -0
- package/commands/wp-status.md +53 -0
- package/docs/GUIDE.md +1190 -0
- package/hooks/hooks.json +57 -0
- package/hooks/scripts/backup-reminder.sh +29 -0
- package/hooks/scripts/pre-deploy-check.sh +49 -0
- package/package.json +46 -0
- package/scripts/health-check.sh +110 -0
- package/scripts/validate-wp-operation.sh +115 -0
- package/servers/wp-rest-bridge/build/server.d.ts +2 -0
- package/servers/wp-rest-bridge/build/server.js +74 -0
- package/servers/wp-rest-bridge/build/tools/comments.d.ts +227 -0
- package/servers/wp-rest-bridge/build/tools/comments.js +192 -0
- package/servers/wp-rest-bridge/build/tools/index.d.ts +919 -0
- package/servers/wp-rest-bridge/build/tools/index.js +30 -0
- package/servers/wp-rest-bridge/build/tools/media.d.ts +174 -0
- package/servers/wp-rest-bridge/build/tools/media.js +247 -0
- package/servers/wp-rest-bridge/build/tools/plugin-repository.d.ts +62 -0
- package/servers/wp-rest-bridge/build/tools/plugin-repository.js +149 -0
- package/servers/wp-rest-bridge/build/tools/plugins.d.ts +153 -0
- package/servers/wp-rest-bridge/build/tools/plugins.js +175 -0
- package/servers/wp-rest-bridge/build/tools/search.d.ts +44 -0
- package/servers/wp-rest-bridge/build/tools/search.js +44 -0
- package/servers/wp-rest-bridge/build/tools/unified-content.d.ts +328 -0
- package/servers/wp-rest-bridge/build/tools/unified-content.js +628 -0
- package/servers/wp-rest-bridge/build/tools/unified-taxonomies.d.ts +244 -0
- package/servers/wp-rest-bridge/build/tools/unified-taxonomies.js +492 -0
- package/servers/wp-rest-bridge/build/tools/users.d.ts +269 -0
- package/servers/wp-rest-bridge/build/tools/users.js +226 -0
- package/servers/wp-rest-bridge/build/types.d.ts +151 -0
- package/servers/wp-rest-bridge/build/types.js +2 -0
- package/servers/wp-rest-bridge/build/wordpress.d.ts +48 -0
- package/servers/wp-rest-bridge/build/wordpress.js +305 -0
- package/servers/wp-rest-bridge/package.json +27 -0
- package/skills/wordpress-router/SKILL.md +78 -0
- package/skills/wordpress-router/references/decision-tree.md +88 -0
- package/skills/wp-abilities-api/SKILL.md +97 -0
- package/skills/wp-abilities-api/references/php-registration.md +67 -0
- package/skills/wp-abilities-api/references/rest-api.md +13 -0
- package/skills/wp-audit/SKILL.md +114 -0
- package/skills/wp-audit/references/performance-checklist.md +113 -0
- package/skills/wp-audit/references/security-checklist.md +95 -0
- package/skills/wp-audit/references/seo-checklist.md +128 -0
- package/skills/wp-backup/SKILL.md +87 -0
- package/skills/wp-backup/references/backup-strategies.md +116 -0
- package/skills/wp-backup/references/restore-procedures.md +129 -0
- package/skills/wp-block-development/SKILL.md +176 -0
- package/skills/wp-block-development/references/attributes-and-serialization.md +22 -0
- package/skills/wp-block-development/references/block-json.md +49 -0
- package/skills/wp-block-development/references/creating-new-blocks.md +46 -0
- package/skills/wp-block-development/references/debugging.md +36 -0
- package/skills/wp-block-development/references/deprecations.md +24 -0
- package/skills/wp-block-development/references/dynamic-rendering.md +23 -0
- package/skills/wp-block-development/references/inner-blocks.md +25 -0
- package/skills/wp-block-development/references/registration.md +30 -0
- package/skills/wp-block-development/references/supports-and-wrappers.md +18 -0
- package/skills/wp-block-development/references/tooling-and-testing.md +21 -0
- package/skills/wp-block-development/scripts/list_blocks.mjs +121 -0
- package/skills/wp-block-themes/SKILL.md +118 -0
- package/skills/wp-block-themes/references/creating-new-block-theme.md +37 -0
- package/skills/wp-block-themes/references/debugging.md +24 -0
- package/skills/wp-block-themes/references/patterns.md +18 -0
- package/skills/wp-block-themes/references/style-variations.md +14 -0
- package/skills/wp-block-themes/references/templates-and-parts.md +16 -0
- package/skills/wp-block-themes/references/theme-json.md +59 -0
- package/skills/wp-block-themes/scripts/detect_block_themes.mjs +117 -0
- package/skills/wp-content/SKILL.md +103 -0
- package/skills/wp-content/references/content-templates.md +230 -0
- package/skills/wp-content/references/seo-optimization.md +169 -0
- package/skills/wp-deploy/SKILL.md +52 -0
- package/skills/wp-deploy/references/hostinger-deploy.md +51 -0
- package/skills/wp-deploy/references/ssh-deploy.md +63 -0
- package/skills/wp-interactivity-api/SKILL.md +181 -0
- package/skills/wp-interactivity-api/references/debugging.md +29 -0
- package/skills/wp-interactivity-api/references/directives-quickref.md +30 -0
- package/skills/wp-interactivity-api/references/server-side-rendering.md +310 -0
- package/skills/wp-migrate/SKILL.md +100 -0
- package/skills/wp-migrate/references/cross-platform.md +104 -0
- package/skills/wp-migrate/references/hostinger-migration.md +86 -0
- package/skills/wp-performance/SKILL.md +148 -0
- package/skills/wp-performance/references/autoload-options.md +24 -0
- package/skills/wp-performance/references/cron.md +20 -0
- package/skills/wp-performance/references/database.md +20 -0
- package/skills/wp-performance/references/http-api.md +15 -0
- package/skills/wp-performance/references/measurement.md +21 -0
- package/skills/wp-performance/references/object-cache.md +24 -0
- package/skills/wp-performance/references/query-monitor-headless.md +38 -0
- package/skills/wp-performance/references/server-timing.md +22 -0
- package/skills/wp-performance/references/wp-cli-doctor.md +24 -0
- package/skills/wp-performance/references/wp-cli-profile.md +32 -0
- package/skills/wp-performance/scripts/perf_inspect.mjs +128 -0
- package/skills/wp-phpstan/SKILL.md +99 -0
- package/skills/wp-phpstan/references/configuration.md +52 -0
- package/skills/wp-phpstan/references/third-party-classes.md +76 -0
- package/skills/wp-phpstan/references/wordpress-annotations.md +124 -0
- package/skills/wp-phpstan/scripts/phpstan_inspect.mjs +263 -0
- package/skills/wp-playground/SKILL.md +103 -0
- package/skills/wp-playground/references/blueprints.md +36 -0
- package/skills/wp-playground/references/cli-commands.md +39 -0
- package/skills/wp-playground/references/debugging.md +16 -0
- package/skills/wp-plugin-development/SKILL.md +114 -0
- package/skills/wp-plugin-development/references/data-and-cron.md +19 -0
- package/skills/wp-plugin-development/references/debugging.md +19 -0
- package/skills/wp-plugin-development/references/lifecycle.md +33 -0
- package/skills/wp-plugin-development/references/security.md +29 -0
- package/skills/wp-plugin-development/references/settings-api.md +22 -0
- package/skills/wp-plugin-development/references/structure.md +16 -0
- package/skills/wp-plugin-development/scripts/detect_plugins.mjs +122 -0
- package/skills/wp-project-triage/SKILL.md +40 -0
- package/skills/wp-project-triage/references/triage.schema.json +143 -0
- package/skills/wp-project-triage/scripts/detect_wp_project.mjs +592 -0
- package/skills/wp-rest-api/SKILL.md +116 -0
- package/skills/wp-rest-api/references/authentication.md +18 -0
- package/skills/wp-rest-api/references/custom-content-types.md +20 -0
- package/skills/wp-rest-api/references/discovery-and-params.md +20 -0
- package/skills/wp-rest-api/references/responses-and-fields.md +30 -0
- package/skills/wp-rest-api/references/routes-and-endpoints.md +36 -0
- package/skills/wp-rest-api/references/schema.md +22 -0
- package/skills/wp-wpcli-and-ops/SKILL.md +125 -0
- package/skills/wp-wpcli-and-ops/references/automation.md +30 -0
- package/skills/wp-wpcli-and-ops/references/cron-and-cache.md +23 -0
- package/skills/wp-wpcli-and-ops/references/debugging.md +17 -0
- package/skills/wp-wpcli-and-ops/references/multisite.md +22 -0
- package/skills/wp-wpcli-and-ops/references/packages-and-updates.md +22 -0
- package/skills/wp-wpcli-and-ops/references/safety.md +30 -0
- package/skills/wp-wpcli-and-ops/references/search-replace.md +40 -0
- package/skills/wp-wpcli-and-ops/scripts/wpcli_inspect.mjs +90 -0
- package/skills/wpds/SKILL.md +60 -0
- 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
|
+
};
|