mcp-wordpress 1.1.7 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +388 -66
- package/dist/cache/CacheInvalidation.d.ts +118 -0
- package/dist/cache/CacheInvalidation.d.ts.map +1 -0
- package/dist/cache/CacheInvalidation.js +349 -0
- package/dist/cache/CacheInvalidation.js.map +1 -0
- package/dist/cache/CacheManager.d.ts +143 -0
- package/dist/cache/CacheManager.d.ts.map +1 -0
- package/dist/cache/CacheManager.js +308 -0
- package/dist/cache/CacheManager.js.map +1 -0
- package/dist/cache/HttpCacheWrapper.d.ts +121 -0
- package/dist/cache/HttpCacheWrapper.d.ts.map +1 -0
- package/dist/cache/HttpCacheWrapper.js +280 -0
- package/dist/cache/HttpCacheWrapper.js.map +1 -0
- package/dist/cache/__tests__/CacheInvalidation.test.d.ts +5 -0
- package/dist/cache/__tests__/CacheInvalidation.test.d.ts.map +1 -0
- package/dist/cache/__tests__/CacheInvalidation.test.js +236 -0
- package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -0
- package/dist/cache/__tests__/CacheManager.test.d.ts +5 -0
- package/dist/cache/__tests__/CacheManager.test.d.ts.map +1 -0
- package/dist/cache/__tests__/CacheManager.test.js +233 -0
- package/dist/cache/__tests__/CacheManager.test.js.map +1 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.d.ts +5 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.d.ts.map +1 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.js +228 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts +5 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts.map +1 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.js +296 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -0
- package/dist/cache/index.d.ts +12 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +9 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/client/CachedWordPressClient.d.ts +160 -0
- package/dist/client/CachedWordPressClient.d.ts.map +1 -0
- package/dist/client/CachedWordPressClient.js +338 -0
- package/dist/client/CachedWordPressClient.js.map +1 -0
- package/dist/client/WordPressClient.d.ts +81 -0
- package/dist/client/WordPressClient.d.ts.map +1 -0
- package/dist/client/WordPressClient.js +354 -0
- package/dist/client/WordPressClient.js.map +1 -0
- package/dist/config/ConfigurationSchema.d.ts +281 -0
- package/dist/config/ConfigurationSchema.d.ts.map +1 -0
- package/dist/config/ConfigurationSchema.js +205 -0
- package/dist/config/ConfigurationSchema.js.map +1 -0
- package/dist/config/ServerConfiguration.d.ts +38 -0
- package/dist/config/ServerConfiguration.d.ts.map +1 -0
- package/dist/config/ServerConfiguration.js +158 -0
- package/dist/config/ServerConfiguration.js.map +1 -0
- package/dist/docs/DocumentationGenerator.d.ts +184 -0
- package/dist/docs/DocumentationGenerator.d.ts.map +1 -0
- package/dist/docs/DocumentationGenerator.js +735 -0
- package/dist/docs/DocumentationGenerator.js.map +1 -0
- package/dist/docs/MarkdownFormatter.d.ts +84 -0
- package/dist/docs/MarkdownFormatter.d.ts.map +1 -0
- package/dist/docs/MarkdownFormatter.js +448 -0
- package/dist/docs/MarkdownFormatter.js.map +1 -0
- package/dist/docs/index.d.ts +8 -0
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +7 -0
- package/dist/docs/index.js.map +1 -0
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -212
- package/dist/index.js.map +1 -1
- package/dist/performance/AnomalyDetector.d.ts +63 -0
- package/dist/performance/AnomalyDetector.d.ts.map +1 -0
- package/dist/performance/AnomalyDetector.js +222 -0
- package/dist/performance/AnomalyDetector.js.map +1 -0
- package/dist/performance/BenchmarkAnalyzer.d.ts +67 -0
- package/dist/performance/BenchmarkAnalyzer.d.ts.map +1 -0
- package/dist/performance/BenchmarkAnalyzer.js +301 -0
- package/dist/performance/BenchmarkAnalyzer.js.map +1 -0
- package/dist/performance/MetricsCollector.d.ts +139 -0
- package/dist/performance/MetricsCollector.d.ts.map +1 -0
- package/dist/performance/MetricsCollector.js +320 -0
- package/dist/performance/MetricsCollector.js.map +1 -0
- package/dist/performance/PerformanceAnalytics.d.ts +162 -0
- package/dist/performance/PerformanceAnalytics.d.ts.map +1 -0
- package/dist/performance/PerformanceAnalytics.js +554 -0
- package/dist/performance/PerformanceAnalytics.js.map +1 -0
- package/dist/performance/PerformanceMonitor.d.ts +202 -0
- package/dist/performance/PerformanceMonitor.d.ts.map +1 -0
- package/dist/performance/PerformanceMonitor.js +478 -0
- package/dist/performance/PerformanceMonitor.js.map +1 -0
- package/dist/performance/TrendAnalyzer.d.ts +69 -0
- package/dist/performance/TrendAnalyzer.d.ts.map +1 -0
- package/dist/performance/TrendAnalyzer.js +203 -0
- package/dist/performance/TrendAnalyzer.js.map +1 -0
- package/dist/performance/index.d.ts +11 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +8 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/security/InputValidator.d.ts +215 -0
- package/dist/security/InputValidator.d.ts.map +1 -0
- package/dist/security/InputValidator.js +278 -0
- package/dist/security/InputValidator.js.map +1 -0
- package/dist/security/SecurityConfig.d.ts +129 -0
- package/dist/security/SecurityConfig.d.ts.map +1 -0
- package/dist/security/SecurityConfig.js +262 -0
- package/dist/security/SecurityConfig.js.map +1 -0
- package/dist/server/ConnectionTester.d.ts +24 -0
- package/dist/server/ConnectionTester.d.ts.map +1 -0
- package/dist/server/ConnectionTester.js +61 -0
- package/dist/server/ConnectionTester.js.map +1 -0
- package/dist/server/ToolRegistry.d.ts +46 -0
- package/dist/server/ToolRegistry.d.ts.map +1 -0
- package/dist/server/ToolRegistry.js +148 -0
- package/dist/server/ToolRegistry.js.map +1 -0
- package/dist/tools/BaseToolClass.d.ts +76 -0
- package/dist/tools/BaseToolClass.d.ts.map +1 -0
- package/dist/tools/BaseToolClass.js +104 -0
- package/dist/tools/BaseToolClass.js.map +1 -0
- package/dist/tools/BaseToolManager.d.ts +26 -0
- package/dist/tools/BaseToolManager.d.ts.map +1 -0
- package/dist/tools/BaseToolManager.js +56 -0
- package/dist/tools/BaseToolManager.js.map +1 -0
- package/dist/tools/base.d.ts +37 -0
- package/dist/tools/base.d.ts.map +1 -0
- package/dist/tools/base.js +60 -0
- package/dist/tools/base.js.map +1 -0
- package/dist/tools/cache.d.ts +260 -0
- package/dist/tools/cache.d.ts.map +1 -0
- package/dist/tools/cache.js +237 -0
- package/dist/tools/cache.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/performance.d.ts +63 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +865 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/types/client.d.ts +1 -0
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/client.js.map +1 -1
- package/dist/utils/toolWrapper.d.ts +4 -0
- package/dist/utils/toolWrapper.d.ts.map +1 -1
- package/dist/utils/toolWrapper.js +11 -0
- package/dist/utils/toolWrapper.js.map +1 -1
- package/dist/utils/validation.d.ts +68 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +185 -0
- package/dist/utils/validation.js.map +1 -0
- package/docs/CACHING.md +340 -0
- package/docs/DOCKER.md +451 -0
- package/docs/PERFORMANCE_MONITORING.md +471 -0
- package/docs/SECURITY_TESTING.md +393 -0
- package/docs/api/README.md +200 -0
- package/docs/api/categories/auth.md +40 -0
- package/docs/api/categories/cache.md +41 -0
- package/docs/api/categories/comment.md +44 -0
- package/docs/api/categories/media.md +43 -0
- package/docs/api/categories/page.md +43 -0
- package/docs/api/categories/performance.md +44 -0
- package/docs/api/categories/post.md +43 -0
- package/docs/api/categories/site.md +43 -0
- package/docs/api/categories/taxonomy.md +47 -0
- package/docs/api/categories/user.md +43 -0
- package/docs/api/openapi.json +3305 -0
- package/docs/api/summary.json +12 -0
- package/docs/api/tools/wp_approve_comment.md +98 -0
- package/docs/api/tools/wp_cache_clear.md +120 -0
- package/docs/api/tools/wp_cache_info.md +119 -0
- package/docs/api/tools/wp_cache_stats.md +119 -0
- package/docs/api/tools/wp_cache_warm.md +119 -0
- package/docs/api/tools/wp_create_application_password.md +102 -0
- package/docs/api/tools/wp_create_category.md +102 -0
- package/docs/api/tools/wp_create_comment.md +128 -0
- package/docs/api/tools/wp_create_page.md +135 -0
- package/docs/api/tools/wp_create_post.md +147 -0
- package/docs/api/tools/wp_create_tag.md +101 -0
- package/docs/api/tools/wp_create_user.md +135 -0
- package/docs/api/tools/wp_delete_application_password.md +101 -0
- package/docs/api/tools/wp_delete_category.md +100 -0
- package/docs/api/tools/wp_delete_comment.md +101 -0
- package/docs/api/tools/wp_delete_media.md +108 -0
- package/docs/api/tools/wp_delete_page.md +108 -0
- package/docs/api/tools/wp_delete_post.md +117 -0
- package/docs/api/tools/wp_delete_tag.md +100 -0
- package/docs/api/tools/wp_delete_user.md +108 -0
- package/docs/api/tools/wp_get_application_passwords.md +103 -0
- package/docs/api/tools/wp_get_auth_status.md +101 -0
- package/docs/api/tools/wp_get_category.md +103 -0
- package/docs/api/tools/wp_get_comment.md +103 -0
- package/docs/api/tools/wp_get_current_user.md +101 -0
- package/docs/api/tools/wp_get_media.md +103 -0
- package/docs/api/tools/wp_get_page.md +103 -0
- package/docs/api/tools/wp_get_page_revisions.md +103 -0
- package/docs/api/tools/wp_get_post.md +112 -0
- package/docs/api/tools/wp_get_post_revisions.md +103 -0
- package/docs/api/tools/wp_get_site_settings.md +108 -0
- package/docs/api/tools/wp_get_tag.md +103 -0
- package/docs/api/tools/wp_get_user.md +103 -0
- package/docs/api/tools/wp_list_categories.md +111 -0
- package/docs/api/tools/wp_list_comments.md +111 -0
- package/docs/api/tools/wp_list_media.md +145 -0
- package/docs/api/tools/wp_list_pages.md +145 -0
- package/docs/api/tools/wp_list_posts.md +156 -0
- package/docs/api/tools/wp_list_tags.md +110 -0
- package/docs/api/tools/wp_list_users.md +111 -0
- package/docs/api/tools/wp_performance_alerts.md +162 -0
- package/docs/api/tools/wp_performance_benchmark.md +160 -0
- package/docs/api/tools/wp_performance_export.md +162 -0
- package/docs/api/tools/wp_performance_history.md +161 -0
- package/docs/api/tools/wp_performance_optimize.md +162 -0
- package/docs/api/tools/wp_performance_stats.md +160 -0
- package/docs/api/tools/wp_search_site.md +99 -0
- package/docs/api/tools/wp_spam_comment.md +98 -0
- package/docs/api/tools/wp_switch_auth_method.md +122 -0
- package/docs/api/tools/wp_test_auth.md +96 -0
- package/docs/api/tools/wp_update_category.md +102 -0
- package/docs/api/tools/wp_update_comment.md +127 -0
- package/docs/api/tools/wp_update_media.md +129 -0
- package/docs/api/tools/wp_update_page.md +135 -0
- package/docs/api/tools/wp_update_post.md +144 -0
- package/docs/api/tools/wp_update_site_settings.md +127 -0
- package/docs/api/tools/wp_update_tag.md +102 -0
- package/docs/api/tools/wp_update_user.md +134 -0
- package/docs/api/tools/wp_upload_media.md +131 -0
- package/docs/api/types/WordPressPost.md +39 -0
- package/docs/contract-testing.md +183 -0
- package/docs/developer/NPM_AUTH_SETUP.md +3 -3
- package/docs/wordpress-rest-api-authentication-troubleshooting.md +218 -0
- package/package.json +84 -64
- package/src/cache/CacheInvalidation.ts +421 -0
- package/src/cache/CacheManager.ts +391 -0
- package/src/cache/HttpCacheWrapper.ts +372 -0
- package/src/cache/__tests__/CacheInvalidation.test.ts +299 -0
- package/src/cache/__tests__/CacheManager.test.ts +300 -0
- package/src/cache/__tests__/CachedWordPressClient.test.ts +304 -0
- package/src/cache/__tests__/HttpCacheWrapper.test.ts +359 -0
- package/src/cache/index.ts +26 -0
- package/src/client/CachedWordPressClient.ts +442 -0
- package/src/config/ConfigurationSchema.ts +246 -0
- package/src/config/ServerConfiguration.ts +215 -0
- package/src/docs/DocumentationGenerator.ts +952 -0
- package/src/docs/MarkdownFormatter.ts +494 -0
- package/src/docs/index.ts +21 -0
- package/src/index.ts +14 -274
- package/src/performance/MetricsCollector.ts +447 -0
- package/src/performance/PerformanceAnalytics.ts +762 -0
- package/src/performance/PerformanceMonitor.ts +649 -0
- package/src/performance/index.ts +28 -0
- package/src/security/InputValidator.ts +319 -0
- package/src/security/SecurityConfig.ts +301 -0
- package/src/server/ConnectionTester.ts +74 -0
- package/src/server/ToolRegistry.ts +194 -0
- package/src/tools/BaseToolManager.ts +66 -0
- package/src/tools/cache.ts +259 -0
- package/src/tools/index.ts +2 -0
- package/src/tools/performance.ts +948 -0
- package/src/types/client.ts +1 -0
- package/src/utils/toolWrapper.ts +11 -0
- package/src/utils/validation.ts +259 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { WordPressClient } from '../client/api.js';
|
|
3
|
+
import { getErrorMessage } from '../utils/error.js';
|
|
4
|
+
import * as Tools from '../tools/index.js';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Interface for tool definition
|
|
9
|
+
*/
|
|
10
|
+
export interface ToolDefinition {
|
|
11
|
+
name: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
parameters?: Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
handler: (client: WordPressClient, args: any) => Promise<any>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Registry for managing MCP tools
|
|
24
|
+
* Handles tool registration, parameter validation, and execution
|
|
25
|
+
*/
|
|
26
|
+
export class ToolRegistry {
|
|
27
|
+
private server: McpServer;
|
|
28
|
+
private wordpressClients: Map<string, WordPressClient>;
|
|
29
|
+
|
|
30
|
+
constructor(server: McpServer, wordpressClients: Map<string, WordPressClient>) {
|
|
31
|
+
this.server = server;
|
|
32
|
+
this.wordpressClients = wordpressClients;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Register all available tools with the MCP server
|
|
37
|
+
*/
|
|
38
|
+
public registerAllTools(): void {
|
|
39
|
+
// Register all tools from the tools directory
|
|
40
|
+
Object.values(Tools).forEach((ToolClass) => {
|
|
41
|
+
let toolInstance: any;
|
|
42
|
+
|
|
43
|
+
// Cache and Performance tools need the clients map
|
|
44
|
+
if (ToolClass.name === 'CacheTools' || ToolClass.name === 'PerformanceTools') {
|
|
45
|
+
toolInstance = new ToolClass(this.wordpressClients);
|
|
46
|
+
} else {
|
|
47
|
+
toolInstance = new (ToolClass as new () => any)();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const tools = toolInstance.getTools();
|
|
51
|
+
|
|
52
|
+
tools.forEach((tool: ToolDefinition) => {
|
|
53
|
+
this.registerTool(tool);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Register a single tool with parameter validation and execution handling
|
|
60
|
+
*/
|
|
61
|
+
private registerTool(tool: ToolDefinition): void {
|
|
62
|
+
// Create base parameter schema with site parameter
|
|
63
|
+
const baseSchema = {
|
|
64
|
+
site: z
|
|
65
|
+
.string()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe(
|
|
68
|
+
'The ID of the WordPress site to target (from mcp-wordpress.config.json). Required if multiple sites are configured.'
|
|
69
|
+
)
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Merge with tool-specific parameters
|
|
73
|
+
const parameterSchema = this.buildParameterSchema(tool, baseSchema);
|
|
74
|
+
|
|
75
|
+
// Make site parameter required if multiple sites are configured
|
|
76
|
+
if (this.wordpressClients.size > 1) {
|
|
77
|
+
parameterSchema.site = parameterSchema.site.describe(
|
|
78
|
+
'The ID of the WordPress site to target (from mcp-wordpress.config.json). Required when multiple sites are configured.'
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.server.tool(
|
|
83
|
+
tool.name,
|
|
84
|
+
tool.description || `WordPress tool: ${tool.name}`,
|
|
85
|
+
parameterSchema,
|
|
86
|
+
async (args: any) => {
|
|
87
|
+
try {
|
|
88
|
+
const siteId = args.site || 'default';
|
|
89
|
+
const client = this.wordpressClients.get(siteId);
|
|
90
|
+
|
|
91
|
+
if (!client) {
|
|
92
|
+
const availableSites = Array.from(this.wordpressClients.keys()).join(', ');
|
|
93
|
+
return {
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
96
|
+
type: 'text' as const,
|
|
97
|
+
text: `Error: Site with ID '${siteId}' not found. Available sites: ${availableSites}`
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
isError: true
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Call the tool handler with the client and parameters
|
|
105
|
+
const result = await tool.handler(client, args);
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
content: [
|
|
109
|
+
{
|
|
110
|
+
type: 'text' as const,
|
|
111
|
+
text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
};
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (this.isAuthenticationError(error)) {
|
|
117
|
+
return {
|
|
118
|
+
content: [
|
|
119
|
+
{
|
|
120
|
+
type: 'text' as const,
|
|
121
|
+
text: `Authentication failed for site '${args.site || 'default'}'. Please check your credentials.`
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
isError: true
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
content: [
|
|
130
|
+
{
|
|
131
|
+
type: 'text' as const,
|
|
132
|
+
text: `Error: ${getErrorMessage(error)}`
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
isError: true
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Build Zod parameter schema from tool definition
|
|
144
|
+
*/
|
|
145
|
+
private buildParameterSchema(tool: ToolDefinition, baseSchema: any): any {
|
|
146
|
+
return tool.parameters?.reduce(
|
|
147
|
+
(schema: any, param: any) => {
|
|
148
|
+
let zodType = this.getZodTypeForParameter(param);
|
|
149
|
+
|
|
150
|
+
if (param.description) {
|
|
151
|
+
zodType = zodType.describe(param.description);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!param.required) {
|
|
155
|
+
zodType = zodType.optional();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
schema[param.name] = zodType;
|
|
159
|
+
return schema;
|
|
160
|
+
},
|
|
161
|
+
{ ...baseSchema }
|
|
162
|
+
) || baseSchema;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get appropriate Zod type for parameter definition
|
|
167
|
+
*/
|
|
168
|
+
private getZodTypeForParameter(param: any): z.ZodType {
|
|
169
|
+
switch (param.type) {
|
|
170
|
+
case 'string':
|
|
171
|
+
return z.string();
|
|
172
|
+
case 'number':
|
|
173
|
+
return z.number();
|
|
174
|
+
case 'boolean':
|
|
175
|
+
return z.boolean();
|
|
176
|
+
case 'array':
|
|
177
|
+
return z.array(z.string());
|
|
178
|
+
case 'object':
|
|
179
|
+
return z.record(z.any());
|
|
180
|
+
default:
|
|
181
|
+
return z.string();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Check if error is authentication-related
|
|
187
|
+
*/
|
|
188
|
+
private isAuthenticationError(error: any): boolean {
|
|
189
|
+
if (error?.response?.status && [401, 403].includes(error.response.status)) {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return error?.code === 'WORDPRESS_AUTH_ERROR';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base utility class for tool managers to reduce code duplication
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getErrorMessage } from '../utils/error.js';
|
|
6
|
+
|
|
7
|
+
export class BaseToolUtils {
|
|
8
|
+
/**
|
|
9
|
+
* Validate required parameters
|
|
10
|
+
*/
|
|
11
|
+
static validateParams(params: Record<string, any>, required: string[]): void {
|
|
12
|
+
for (const field of required) {
|
|
13
|
+
if (
|
|
14
|
+
!(field in params) ||
|
|
15
|
+
params[field] === undefined ||
|
|
16
|
+
params[field] === null
|
|
17
|
+
) {
|
|
18
|
+
throw new Error(`Missing required parameter: ${field}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Validate ID parameter
|
|
25
|
+
*/
|
|
26
|
+
static validateId(id: unknown, name = 'id'): number {
|
|
27
|
+
const numId = Number(id);
|
|
28
|
+
if (!Number.isInteger(numId) || numId <= 0) {
|
|
29
|
+
throw new Error(`Invalid ${name}: must be a positive integer`);
|
|
30
|
+
}
|
|
31
|
+
return numId;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Handle errors consistently across all tools
|
|
36
|
+
*/
|
|
37
|
+
static handleError(error: unknown, operation: string): string {
|
|
38
|
+
const errorMessage = getErrorMessage(error);
|
|
39
|
+
return `Error in ${operation}: ${errorMessage}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Cache key generation helper
|
|
44
|
+
*/
|
|
45
|
+
static generateCacheKey(
|
|
46
|
+
operation: string,
|
|
47
|
+
params: Record<string, unknown>
|
|
48
|
+
): string {
|
|
49
|
+
const site = params.site || 'default';
|
|
50
|
+
const paramStr = Object.entries(params)
|
|
51
|
+
.filter(([key]) => key !== 'site')
|
|
52
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
53
|
+
.map(([key, value]) => `${key}:${value}`)
|
|
54
|
+
.join('|');
|
|
55
|
+
return `${site}:${operation}:${paramStr}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Format consistent response messages
|
|
60
|
+
*/
|
|
61
|
+
static formatSuccessMessage(operation: string, details?: string): string {
|
|
62
|
+
return details
|
|
63
|
+
? `${operation}: ${details}`
|
|
64
|
+
: `${operation} completed successfully`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache management tools for WordPress MCP Server
|
|
3
|
+
* Provides cache inspection, clearing, and warming capabilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { WordPressClient } from '../client/api.js';
|
|
7
|
+
import { CachedWordPressClient } from '../client/CachedWordPressClient.js';
|
|
8
|
+
import { toolWrapper } from '../utils/toolWrapper.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Cache management tools class
|
|
12
|
+
*/
|
|
13
|
+
export class CacheTools {
|
|
14
|
+
constructor(private clients: Map<string, WordPressClient>) {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get cache management tools
|
|
18
|
+
*/
|
|
19
|
+
getTools() {
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
name: 'wp_cache_stats',
|
|
23
|
+
description: 'Get cache statistics for a WordPress site.',
|
|
24
|
+
parameters: [
|
|
25
|
+
{
|
|
26
|
+
name: 'site',
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Site ID to get cache stats for. If not provided, uses default site or fails if multiple sites configured.'
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
handler: this.handleGetCacheStats.bind(this)
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'wp_cache_clear',
|
|
35
|
+
description: 'Clear cache for a WordPress site.',
|
|
36
|
+
parameters: [
|
|
37
|
+
{
|
|
38
|
+
name: 'site',
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'Site ID to clear cache for.'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'pattern',
|
|
44
|
+
type: 'string',
|
|
45
|
+
description: 'Optional pattern to clear specific cache entries (e.g., "posts", "categories").'
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
handler: this.handleClearCache.bind(this)
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'wp_cache_warm',
|
|
52
|
+
description: 'Pre-warm cache with essential WordPress data.',
|
|
53
|
+
parameters: [
|
|
54
|
+
{
|
|
55
|
+
name: 'site',
|
|
56
|
+
type: 'string',
|
|
57
|
+
description: 'Site ID to warm cache for.'
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
handler: this.handleWarmCache.bind(this)
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'wp_cache_info',
|
|
64
|
+
description: 'Get detailed cache configuration and status information.',
|
|
65
|
+
parameters: [
|
|
66
|
+
{
|
|
67
|
+
name: 'site',
|
|
68
|
+
type: 'string',
|
|
69
|
+
description: 'Site ID to get cache info for.'
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
handler: this.handleGetCacheInfo.bind(this)
|
|
73
|
+
}
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get cache statistics
|
|
79
|
+
*/
|
|
80
|
+
async handleGetCacheStats(params: { site?: string }) {
|
|
81
|
+
return toolWrapper(async () => {
|
|
82
|
+
const client = this.resolveClient(params.site);
|
|
83
|
+
|
|
84
|
+
if (!(client instanceof CachedWordPressClient)) {
|
|
85
|
+
return {
|
|
86
|
+
caching_enabled: false,
|
|
87
|
+
message: 'Caching is disabled for this site. Set DISABLE_CACHE=false to enable caching.'
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const stats = client.getCacheStats();
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
caching_enabled: true,
|
|
95
|
+
cache_stats: {
|
|
96
|
+
hits: stats.cache.hits,
|
|
97
|
+
misses: stats.cache.misses,
|
|
98
|
+
hit_rate: Math.round(stats.cache.hitRate * 100) + '%',
|
|
99
|
+
total_entries: stats.cache.totalSize,
|
|
100
|
+
evictions: stats.cache.evictions
|
|
101
|
+
},
|
|
102
|
+
invalidation_stats: {
|
|
103
|
+
queue_size: stats.invalidation.queueSize,
|
|
104
|
+
rules_count: stats.invalidation.rulesCount,
|
|
105
|
+
processing: stats.invalidation.processing
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Clear cache
|
|
113
|
+
*/
|
|
114
|
+
async handleClearCache(params: { site?: string; pattern?: string }) {
|
|
115
|
+
return toolWrapper(async () => {
|
|
116
|
+
const client = this.resolveClient(params.site);
|
|
117
|
+
|
|
118
|
+
if (!(client instanceof CachedWordPressClient)) {
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
message: 'Caching is not enabled for this site.'
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let cleared: number;
|
|
126
|
+
|
|
127
|
+
if (params.pattern) {
|
|
128
|
+
cleared = client.clearCachePattern(params.pattern);
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
message: `Cleared ${cleared} cache entries matching pattern "${params.pattern}".`,
|
|
132
|
+
cleared_entries: cleared,
|
|
133
|
+
pattern: params.pattern
|
|
134
|
+
};
|
|
135
|
+
} else {
|
|
136
|
+
cleared = client.clearCache();
|
|
137
|
+
return {
|
|
138
|
+
success: true,
|
|
139
|
+
message: `Cleared all cache entries (${cleared} total).`,
|
|
140
|
+
cleared_entries: cleared
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Warm cache with essential data
|
|
148
|
+
*/
|
|
149
|
+
async handleWarmCache(params: { site?: string }) {
|
|
150
|
+
return toolWrapper(async () => {
|
|
151
|
+
const client = this.resolveClient(params.site);
|
|
152
|
+
|
|
153
|
+
if (!(client instanceof CachedWordPressClient)) {
|
|
154
|
+
return {
|
|
155
|
+
success: false,
|
|
156
|
+
message: 'Caching is not enabled for this site.'
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
await client.warmCache();
|
|
161
|
+
|
|
162
|
+
const stats = client.getCacheStats();
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
success: true,
|
|
166
|
+
message: 'Cache warmed with essential WordPress data.',
|
|
167
|
+
cache_entries_after_warming: stats.cache.totalSize,
|
|
168
|
+
warmed_data: [
|
|
169
|
+
'Current user information',
|
|
170
|
+
'Categories',
|
|
171
|
+
'Tags',
|
|
172
|
+
'Site settings'
|
|
173
|
+
]
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get detailed cache information
|
|
180
|
+
*/
|
|
181
|
+
async handleGetCacheInfo(params: { site?: string }) {
|
|
182
|
+
return toolWrapper(async () => {
|
|
183
|
+
const client = this.resolveClient(params.site);
|
|
184
|
+
|
|
185
|
+
if (!(client instanceof CachedWordPressClient)) {
|
|
186
|
+
return {
|
|
187
|
+
caching_enabled: false,
|
|
188
|
+
message: 'Caching is disabled for this site.',
|
|
189
|
+
how_to_enable: 'Remove DISABLE_CACHE=true from environment variables or set it to false.'
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const stats = client.getCacheStats();
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
caching_enabled: true,
|
|
197
|
+
cache_configuration: {
|
|
198
|
+
max_size: 'Configured in SecurityConfig.cache.maxSize',
|
|
199
|
+
default_ttl: 'Configured in SecurityConfig.cache.defaultTTL',
|
|
200
|
+
lru_enabled: 'Configured in SecurityConfig.cache.enableLRU',
|
|
201
|
+
stats_enabled: 'Configured in SecurityConfig.cache.enableStats'
|
|
202
|
+
},
|
|
203
|
+
ttl_presets: {
|
|
204
|
+
static_data: '4 hours (site settings, user roles)',
|
|
205
|
+
semi_static_data: '2 hours (categories, tags, user profiles)',
|
|
206
|
+
dynamic_data: '15 minutes (posts, pages, comments)',
|
|
207
|
+
session_data: '30 minutes (authentication, current user)',
|
|
208
|
+
realtime_data: '1 minute (real-time data)'
|
|
209
|
+
},
|
|
210
|
+
current_stats: {
|
|
211
|
+
total_entries: stats.cache.totalSize,
|
|
212
|
+
hit_rate: Math.round(stats.cache.hitRate * 100) + '%',
|
|
213
|
+
hits: stats.cache.hits,
|
|
214
|
+
misses: stats.cache.misses,
|
|
215
|
+
evictions: stats.cache.evictions
|
|
216
|
+
},
|
|
217
|
+
invalidation_info: {
|
|
218
|
+
queue_size: stats.invalidation.queueSize,
|
|
219
|
+
rules_registered: stats.invalidation.rulesCount,
|
|
220
|
+
currently_processing: stats.invalidation.processing
|
|
221
|
+
},
|
|
222
|
+
performance_benefits: [
|
|
223
|
+
'Reduced API calls to WordPress',
|
|
224
|
+
'Faster response times for repeated requests',
|
|
225
|
+
'Better rate limit utilization',
|
|
226
|
+
'Improved user experience'
|
|
227
|
+
]
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Resolve client from site parameter
|
|
234
|
+
*/
|
|
235
|
+
private resolveClient(siteId?: string): WordPressClient {
|
|
236
|
+
if (!siteId) {
|
|
237
|
+
if (this.clients.size === 1) {
|
|
238
|
+
return Array.from(this.clients.values())[0];
|
|
239
|
+
} else if (this.clients.size === 0) {
|
|
240
|
+
throw new Error('No WordPress sites configured.');
|
|
241
|
+
} else {
|
|
242
|
+
throw new Error(
|
|
243
|
+
`Multiple sites configured. Please specify --site parameter. Available sites: ${Array.from(this.clients.keys()).join(', ')}`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const client = this.clients.get(siteId);
|
|
249
|
+
if (!client) {
|
|
250
|
+
throw new Error(
|
|
251
|
+
`Site "${siteId}" not found. Available sites: ${Array.from(this.clients.keys()).join(', ')}`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return client;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export default CacheTools;
|
package/src/tools/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { default as AuthTools } from './auth.js';
|
|
2
|
+
export { default as CacheTools } from './cache.js';
|
|
2
3
|
export { default as CommentTools } from './comments.js';
|
|
3
4
|
export { default as MediaTools } from './media.js';
|
|
4
5
|
export { default as PageTools } from './pages.js';
|
|
6
|
+
export { default as PerformanceTools } from './performance.js';
|
|
5
7
|
export { default as PostTools } from './posts.js';
|
|
6
8
|
export { default as SiteTools } from './site.js';
|
|
7
9
|
export { default as TaxonomyTools } from './taxonomies.js';
|