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.
Files changed (255) hide show
  1. package/README.md +388 -66
  2. package/dist/cache/CacheInvalidation.d.ts +118 -0
  3. package/dist/cache/CacheInvalidation.d.ts.map +1 -0
  4. package/dist/cache/CacheInvalidation.js +349 -0
  5. package/dist/cache/CacheInvalidation.js.map +1 -0
  6. package/dist/cache/CacheManager.d.ts +143 -0
  7. package/dist/cache/CacheManager.d.ts.map +1 -0
  8. package/dist/cache/CacheManager.js +308 -0
  9. package/dist/cache/CacheManager.js.map +1 -0
  10. package/dist/cache/HttpCacheWrapper.d.ts +121 -0
  11. package/dist/cache/HttpCacheWrapper.d.ts.map +1 -0
  12. package/dist/cache/HttpCacheWrapper.js +280 -0
  13. package/dist/cache/HttpCacheWrapper.js.map +1 -0
  14. package/dist/cache/__tests__/CacheInvalidation.test.d.ts +5 -0
  15. package/dist/cache/__tests__/CacheInvalidation.test.d.ts.map +1 -0
  16. package/dist/cache/__tests__/CacheInvalidation.test.js +236 -0
  17. package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -0
  18. package/dist/cache/__tests__/CacheManager.test.d.ts +5 -0
  19. package/dist/cache/__tests__/CacheManager.test.d.ts.map +1 -0
  20. package/dist/cache/__tests__/CacheManager.test.js +233 -0
  21. package/dist/cache/__tests__/CacheManager.test.js.map +1 -0
  22. package/dist/cache/__tests__/CachedWordPressClient.test.d.ts +5 -0
  23. package/dist/cache/__tests__/CachedWordPressClient.test.d.ts.map +1 -0
  24. package/dist/cache/__tests__/CachedWordPressClient.test.js +228 -0
  25. package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -0
  26. package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts +5 -0
  27. package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts.map +1 -0
  28. package/dist/cache/__tests__/HttpCacheWrapper.test.js +296 -0
  29. package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -0
  30. package/dist/cache/index.d.ts +12 -0
  31. package/dist/cache/index.d.ts.map +1 -0
  32. package/dist/cache/index.js +9 -0
  33. package/dist/cache/index.js.map +1 -0
  34. package/dist/client/CachedWordPressClient.d.ts +160 -0
  35. package/dist/client/CachedWordPressClient.d.ts.map +1 -0
  36. package/dist/client/CachedWordPressClient.js +338 -0
  37. package/dist/client/CachedWordPressClient.js.map +1 -0
  38. package/dist/client/WordPressClient.d.ts +81 -0
  39. package/dist/client/WordPressClient.d.ts.map +1 -0
  40. package/dist/client/WordPressClient.js +354 -0
  41. package/dist/client/WordPressClient.js.map +1 -0
  42. package/dist/config/ConfigurationSchema.d.ts +281 -0
  43. package/dist/config/ConfigurationSchema.d.ts.map +1 -0
  44. package/dist/config/ConfigurationSchema.js +205 -0
  45. package/dist/config/ConfigurationSchema.js.map +1 -0
  46. package/dist/config/ServerConfiguration.d.ts +38 -0
  47. package/dist/config/ServerConfiguration.d.ts.map +1 -0
  48. package/dist/config/ServerConfiguration.js +158 -0
  49. package/dist/config/ServerConfiguration.js.map +1 -0
  50. package/dist/docs/DocumentationGenerator.d.ts +184 -0
  51. package/dist/docs/DocumentationGenerator.d.ts.map +1 -0
  52. package/dist/docs/DocumentationGenerator.js +735 -0
  53. package/dist/docs/DocumentationGenerator.js.map +1 -0
  54. package/dist/docs/MarkdownFormatter.d.ts +84 -0
  55. package/dist/docs/MarkdownFormatter.d.ts.map +1 -0
  56. package/dist/docs/MarkdownFormatter.js +448 -0
  57. package/dist/docs/MarkdownFormatter.js.map +1 -0
  58. package/dist/docs/index.d.ts +8 -0
  59. package/dist/docs/index.d.ts.map +1 -0
  60. package/dist/docs/index.js +7 -0
  61. package/dist/docs/index.js.map +1 -0
  62. package/dist/index.d.ts +1 -4
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +12 -212
  65. package/dist/index.js.map +1 -1
  66. package/dist/performance/AnomalyDetector.d.ts +63 -0
  67. package/dist/performance/AnomalyDetector.d.ts.map +1 -0
  68. package/dist/performance/AnomalyDetector.js +222 -0
  69. package/dist/performance/AnomalyDetector.js.map +1 -0
  70. package/dist/performance/BenchmarkAnalyzer.d.ts +67 -0
  71. package/dist/performance/BenchmarkAnalyzer.d.ts.map +1 -0
  72. package/dist/performance/BenchmarkAnalyzer.js +301 -0
  73. package/dist/performance/BenchmarkAnalyzer.js.map +1 -0
  74. package/dist/performance/MetricsCollector.d.ts +139 -0
  75. package/dist/performance/MetricsCollector.d.ts.map +1 -0
  76. package/dist/performance/MetricsCollector.js +320 -0
  77. package/dist/performance/MetricsCollector.js.map +1 -0
  78. package/dist/performance/PerformanceAnalytics.d.ts +162 -0
  79. package/dist/performance/PerformanceAnalytics.d.ts.map +1 -0
  80. package/dist/performance/PerformanceAnalytics.js +554 -0
  81. package/dist/performance/PerformanceAnalytics.js.map +1 -0
  82. package/dist/performance/PerformanceMonitor.d.ts +202 -0
  83. package/dist/performance/PerformanceMonitor.d.ts.map +1 -0
  84. package/dist/performance/PerformanceMonitor.js +478 -0
  85. package/dist/performance/PerformanceMonitor.js.map +1 -0
  86. package/dist/performance/TrendAnalyzer.d.ts +69 -0
  87. package/dist/performance/TrendAnalyzer.d.ts.map +1 -0
  88. package/dist/performance/TrendAnalyzer.js +203 -0
  89. package/dist/performance/TrendAnalyzer.js.map +1 -0
  90. package/dist/performance/index.d.ts +11 -0
  91. package/dist/performance/index.d.ts.map +1 -0
  92. package/dist/performance/index.js +8 -0
  93. package/dist/performance/index.js.map +1 -0
  94. package/dist/security/InputValidator.d.ts +215 -0
  95. package/dist/security/InputValidator.d.ts.map +1 -0
  96. package/dist/security/InputValidator.js +278 -0
  97. package/dist/security/InputValidator.js.map +1 -0
  98. package/dist/security/SecurityConfig.d.ts +129 -0
  99. package/dist/security/SecurityConfig.d.ts.map +1 -0
  100. package/dist/security/SecurityConfig.js +262 -0
  101. package/dist/security/SecurityConfig.js.map +1 -0
  102. package/dist/server/ConnectionTester.d.ts +24 -0
  103. package/dist/server/ConnectionTester.d.ts.map +1 -0
  104. package/dist/server/ConnectionTester.js +61 -0
  105. package/dist/server/ConnectionTester.js.map +1 -0
  106. package/dist/server/ToolRegistry.d.ts +46 -0
  107. package/dist/server/ToolRegistry.d.ts.map +1 -0
  108. package/dist/server/ToolRegistry.js +148 -0
  109. package/dist/server/ToolRegistry.js.map +1 -0
  110. package/dist/tools/BaseToolClass.d.ts +76 -0
  111. package/dist/tools/BaseToolClass.d.ts.map +1 -0
  112. package/dist/tools/BaseToolClass.js +104 -0
  113. package/dist/tools/BaseToolClass.js.map +1 -0
  114. package/dist/tools/BaseToolManager.d.ts +26 -0
  115. package/dist/tools/BaseToolManager.d.ts.map +1 -0
  116. package/dist/tools/BaseToolManager.js +56 -0
  117. package/dist/tools/BaseToolManager.js.map +1 -0
  118. package/dist/tools/base.d.ts +37 -0
  119. package/dist/tools/base.d.ts.map +1 -0
  120. package/dist/tools/base.js +60 -0
  121. package/dist/tools/base.js.map +1 -0
  122. package/dist/tools/cache.d.ts +260 -0
  123. package/dist/tools/cache.d.ts.map +1 -0
  124. package/dist/tools/cache.js +237 -0
  125. package/dist/tools/cache.js.map +1 -0
  126. package/dist/tools/index.d.ts +2 -0
  127. package/dist/tools/index.d.ts.map +1 -1
  128. package/dist/tools/index.js +2 -0
  129. package/dist/tools/index.js.map +1 -1
  130. package/dist/tools/performance.d.ts +63 -0
  131. package/dist/tools/performance.d.ts.map +1 -0
  132. package/dist/tools/performance.js +865 -0
  133. package/dist/tools/performance.js.map +1 -0
  134. package/dist/types/client.d.ts +1 -0
  135. package/dist/types/client.d.ts.map +1 -1
  136. package/dist/types/client.js.map +1 -1
  137. package/dist/utils/toolWrapper.d.ts +4 -0
  138. package/dist/utils/toolWrapper.d.ts.map +1 -1
  139. package/dist/utils/toolWrapper.js +11 -0
  140. package/dist/utils/toolWrapper.js.map +1 -1
  141. package/dist/utils/validation.d.ts +68 -0
  142. package/dist/utils/validation.d.ts.map +1 -0
  143. package/dist/utils/validation.js +185 -0
  144. package/dist/utils/validation.js.map +1 -0
  145. package/docs/CACHING.md +340 -0
  146. package/docs/DOCKER.md +451 -0
  147. package/docs/PERFORMANCE_MONITORING.md +471 -0
  148. package/docs/SECURITY_TESTING.md +393 -0
  149. package/docs/api/README.md +200 -0
  150. package/docs/api/categories/auth.md +40 -0
  151. package/docs/api/categories/cache.md +41 -0
  152. package/docs/api/categories/comment.md +44 -0
  153. package/docs/api/categories/media.md +43 -0
  154. package/docs/api/categories/page.md +43 -0
  155. package/docs/api/categories/performance.md +44 -0
  156. package/docs/api/categories/post.md +43 -0
  157. package/docs/api/categories/site.md +43 -0
  158. package/docs/api/categories/taxonomy.md +47 -0
  159. package/docs/api/categories/user.md +43 -0
  160. package/docs/api/openapi.json +3305 -0
  161. package/docs/api/summary.json +12 -0
  162. package/docs/api/tools/wp_approve_comment.md +98 -0
  163. package/docs/api/tools/wp_cache_clear.md +120 -0
  164. package/docs/api/tools/wp_cache_info.md +119 -0
  165. package/docs/api/tools/wp_cache_stats.md +119 -0
  166. package/docs/api/tools/wp_cache_warm.md +119 -0
  167. package/docs/api/tools/wp_create_application_password.md +102 -0
  168. package/docs/api/tools/wp_create_category.md +102 -0
  169. package/docs/api/tools/wp_create_comment.md +128 -0
  170. package/docs/api/tools/wp_create_page.md +135 -0
  171. package/docs/api/tools/wp_create_post.md +147 -0
  172. package/docs/api/tools/wp_create_tag.md +101 -0
  173. package/docs/api/tools/wp_create_user.md +135 -0
  174. package/docs/api/tools/wp_delete_application_password.md +101 -0
  175. package/docs/api/tools/wp_delete_category.md +100 -0
  176. package/docs/api/tools/wp_delete_comment.md +101 -0
  177. package/docs/api/tools/wp_delete_media.md +108 -0
  178. package/docs/api/tools/wp_delete_page.md +108 -0
  179. package/docs/api/tools/wp_delete_post.md +117 -0
  180. package/docs/api/tools/wp_delete_tag.md +100 -0
  181. package/docs/api/tools/wp_delete_user.md +108 -0
  182. package/docs/api/tools/wp_get_application_passwords.md +103 -0
  183. package/docs/api/tools/wp_get_auth_status.md +101 -0
  184. package/docs/api/tools/wp_get_category.md +103 -0
  185. package/docs/api/tools/wp_get_comment.md +103 -0
  186. package/docs/api/tools/wp_get_current_user.md +101 -0
  187. package/docs/api/tools/wp_get_media.md +103 -0
  188. package/docs/api/tools/wp_get_page.md +103 -0
  189. package/docs/api/tools/wp_get_page_revisions.md +103 -0
  190. package/docs/api/tools/wp_get_post.md +112 -0
  191. package/docs/api/tools/wp_get_post_revisions.md +103 -0
  192. package/docs/api/tools/wp_get_site_settings.md +108 -0
  193. package/docs/api/tools/wp_get_tag.md +103 -0
  194. package/docs/api/tools/wp_get_user.md +103 -0
  195. package/docs/api/tools/wp_list_categories.md +111 -0
  196. package/docs/api/tools/wp_list_comments.md +111 -0
  197. package/docs/api/tools/wp_list_media.md +145 -0
  198. package/docs/api/tools/wp_list_pages.md +145 -0
  199. package/docs/api/tools/wp_list_posts.md +156 -0
  200. package/docs/api/tools/wp_list_tags.md +110 -0
  201. package/docs/api/tools/wp_list_users.md +111 -0
  202. package/docs/api/tools/wp_performance_alerts.md +162 -0
  203. package/docs/api/tools/wp_performance_benchmark.md +160 -0
  204. package/docs/api/tools/wp_performance_export.md +162 -0
  205. package/docs/api/tools/wp_performance_history.md +161 -0
  206. package/docs/api/tools/wp_performance_optimize.md +162 -0
  207. package/docs/api/tools/wp_performance_stats.md +160 -0
  208. package/docs/api/tools/wp_search_site.md +99 -0
  209. package/docs/api/tools/wp_spam_comment.md +98 -0
  210. package/docs/api/tools/wp_switch_auth_method.md +122 -0
  211. package/docs/api/tools/wp_test_auth.md +96 -0
  212. package/docs/api/tools/wp_update_category.md +102 -0
  213. package/docs/api/tools/wp_update_comment.md +127 -0
  214. package/docs/api/tools/wp_update_media.md +129 -0
  215. package/docs/api/tools/wp_update_page.md +135 -0
  216. package/docs/api/tools/wp_update_post.md +144 -0
  217. package/docs/api/tools/wp_update_site_settings.md +127 -0
  218. package/docs/api/tools/wp_update_tag.md +102 -0
  219. package/docs/api/tools/wp_update_user.md +134 -0
  220. package/docs/api/tools/wp_upload_media.md +131 -0
  221. package/docs/api/types/WordPressPost.md +39 -0
  222. package/docs/contract-testing.md +183 -0
  223. package/docs/developer/NPM_AUTH_SETUP.md +3 -3
  224. package/docs/wordpress-rest-api-authentication-troubleshooting.md +218 -0
  225. package/package.json +84 -64
  226. package/src/cache/CacheInvalidation.ts +421 -0
  227. package/src/cache/CacheManager.ts +391 -0
  228. package/src/cache/HttpCacheWrapper.ts +372 -0
  229. package/src/cache/__tests__/CacheInvalidation.test.ts +299 -0
  230. package/src/cache/__tests__/CacheManager.test.ts +300 -0
  231. package/src/cache/__tests__/CachedWordPressClient.test.ts +304 -0
  232. package/src/cache/__tests__/HttpCacheWrapper.test.ts +359 -0
  233. package/src/cache/index.ts +26 -0
  234. package/src/client/CachedWordPressClient.ts +442 -0
  235. package/src/config/ConfigurationSchema.ts +246 -0
  236. package/src/config/ServerConfiguration.ts +215 -0
  237. package/src/docs/DocumentationGenerator.ts +952 -0
  238. package/src/docs/MarkdownFormatter.ts +494 -0
  239. package/src/docs/index.ts +21 -0
  240. package/src/index.ts +14 -274
  241. package/src/performance/MetricsCollector.ts +447 -0
  242. package/src/performance/PerformanceAnalytics.ts +762 -0
  243. package/src/performance/PerformanceMonitor.ts +649 -0
  244. package/src/performance/index.ts +28 -0
  245. package/src/security/InputValidator.ts +319 -0
  246. package/src/security/SecurityConfig.ts +301 -0
  247. package/src/server/ConnectionTester.ts +74 -0
  248. package/src/server/ToolRegistry.ts +194 -0
  249. package/src/tools/BaseToolManager.ts +66 -0
  250. package/src/tools/cache.ts +259 -0
  251. package/src/tools/index.ts +2 -0
  252. package/src/tools/performance.ts +948 -0
  253. package/src/types/client.ts +1 -0
  254. package/src/utils/toolWrapper.ts +11 -0
  255. 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;
@@ -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';