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
package/src/index.ts CHANGED
@@ -1,32 +1,22 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import dotenv from 'dotenv';
4
- import * as fs from 'fs';
5
- import * as path from 'path';
6
3
  import { fileURLToPath } from 'url';
7
4
  import { WordPressClient } from './client/api.js';
8
- import { AuthMethod, WordPressClientConfig } from './types/client.js';
9
- import * as Tools from './tools/index.js';
5
+ import { ServerConfiguration, SiteConfig } from './config/ServerConfiguration.js';
6
+ import { ToolRegistry } from './server/ToolRegistry.js';
7
+ import { ConnectionTester } from './server/ConnectionTester.js';
10
8
  import { getErrorMessage } from './utils/error.js';
11
- import { z } from 'zod';
12
9
 
13
10
  // --- Constants ---
14
- const __filename = fileURLToPath(import.meta.url);
15
- const __dirname = path.dirname(__filename);
16
- const rootDir = path.resolve(__dirname, '..');
17
- const envPath = path.resolve(rootDir, '.env');
18
- dotenv.config({ path: envPath });
19
-
20
- const SERVER_VERSION = '1.1.7'; // Docker containerization and automated publishing
11
+ const SERVER_VERSION = '1.1.8'; // Technical debt resolution and modular architecture
21
12
 
22
13
  // --- Main Server Class ---
23
14
  class MCPWordPressServer {
24
15
  private server: McpServer;
25
- // MODIFICATION: Manages multiple WordPress clients, keyed by site ID.
26
16
  private wordpressClients: Map<string, WordPressClient> = new Map();
27
17
  private initialized: boolean = false;
28
- // MODIFICATION: Stores the configurations for all loaded sites.
29
- private siteConfigs: any[] = [];
18
+ private siteConfigs: SiteConfig[] = [];
19
+ private toolRegistry: ToolRegistry;
30
20
 
31
21
  constructor(mcpConfig?: any) {
32
22
  this.loadConfiguration(mcpConfig);
@@ -43,277 +33,27 @@ class MCPWordPressServer {
43
33
  version: SERVER_VERSION
44
34
  });
45
35
 
36
+ this.toolRegistry = new ToolRegistry(this.server, this.wordpressClients);
46
37
  this.setupTools();
47
38
  }
48
39
 
49
40
  private loadConfiguration(mcpConfig?: any) {
50
- const configPath = path.resolve(rootDir, 'mcp-wordpress.config.json');
51
-
52
- if (fs.existsSync(configPath)) {
53
- if (process.env.NODE_ENV !== 'test') {
54
- console.error(
55
- 'INFO: Found mcp-wordpress.config.json, loading multi-site configuration.'
56
- );
57
- }
58
- this.loadMultiSiteConfig(configPath);
59
- } else {
60
- if (process.env.NODE_ENV !== 'test') {
61
- console.error(
62
- 'INFO: mcp-wordpress.config.json not found, falling back to environment variables for single-site mode.'
63
- );
64
- }
65
- this.loadSingleSiteFromEnv(mcpConfig);
66
- }
67
- }
68
-
69
- private loadMultiSiteConfig(configPath: string) {
70
- try {
71
- const configFile = fs.readFileSync(configPath, 'utf-8');
72
- const config = JSON.parse(configFile);
73
-
74
- if (!config.sites || !Array.isArray(config.sites)) {
75
- throw new Error('Configuration file must have a "sites" array.');
76
- }
77
-
78
- this.siteConfigs = config.sites;
79
- for (const site of this.siteConfigs) {
80
- if (site.id && site.name && site.config) {
81
- const clientConfig: WordPressClientConfig = {
82
- baseUrl: site.config.WORDPRESS_SITE_URL,
83
- auth: {
84
- method:
85
- (site.config.WORDPRESS_AUTH_METHOD as AuthMethod) ||
86
- 'app-password',
87
- username: site.config.WORDPRESS_USERNAME,
88
- appPassword: site.config.WORDPRESS_APP_PASSWORD
89
- }
90
- };
91
- const client = new WordPressClient(clientConfig);
92
- this.wordpressClients.set(site.id, client);
93
- if (process.env.NODE_ENV !== 'test') {
94
- console.error(
95
- `INFO: Initialized client for site: ${site.name} (ID: ${site.id})`
96
- );
97
- }
98
- } else {
99
- console.warn(
100
- 'WARN: Skipping invalid site entry in config. Must have id, name, and config.',
101
- site
102
- );
103
- }
104
- }
105
- } catch (error) {
106
- console.error(
107
- `FATAL: Error reading or parsing mcp-wordpress.config.json: ${getErrorMessage(error)}`
108
- );
109
- process.exit(1);
110
- }
111
- }
112
-
113
- private loadSingleSiteFromEnv(mcpConfig?: any) {
114
- const siteUrl =
115
- mcpConfig?.wordpressSiteUrl || process.env.WORDPRESS_SITE_URL;
116
- const username =
117
- mcpConfig?.wordpressUsername || process.env.WORDPRESS_USERNAME;
118
- const password =
119
- mcpConfig?.wordpressAppPassword || process.env.WORDPRESS_APP_PASSWORD;
120
- const authMethod = (mcpConfig?.wordpressAuthMethod ||
121
- process.env.WORDPRESS_AUTH_METHOD ||
122
- 'app-password') as AuthMethod;
123
-
124
- if (!siteUrl || !username || !password) {
125
- console.error(
126
- 'ERROR: Missing required credentials for single-site mode.'
127
- );
128
- console.error(
129
- 'Please set WORDPRESS_SITE_URL, WORDPRESS_USERNAME, and WORDPRESS_APP_PASSWORD environment variables.'
130
- );
131
- return;
132
- }
133
-
134
- const singleSiteConfig: WordPressClientConfig = {
135
- baseUrl: siteUrl,
136
- auth: { method: authMethod, username, appPassword: password }
137
- };
138
- const client = new WordPressClient(singleSiteConfig);
139
- this.wordpressClients.set('default', client);
140
- this.siteConfigs.push({
141
- id: 'default',
142
- name: 'Default Site',
143
- config: singleSiteConfig
144
- });
145
- console.error(
146
- 'INFO: Initialized client for default site in single-site mode.'
147
- );
41
+ const serverConfig = ServerConfiguration.getInstance();
42
+ const { clients, configs } = serverConfig.loadClientConfigurations(mcpConfig);
43
+
44
+ this.wordpressClients = clients;
45
+ this.siteConfigs = configs;
148
46
  }
149
47
 
150
48
  private setupTools() {
151
- // Register all tools from the tools directory
152
- Object.values(Tools).forEach((ToolClass) => {
153
- const toolInstance = new ToolClass();
154
- const tools = toolInstance.getTools();
155
-
156
- tools.forEach((tool) => {
157
- this.registerTool(tool);
158
- });
159
- });
160
- }
161
-
162
- private registerTool(tool: any) {
163
- // Create base parameter schema with site parameter
164
- const baseSchema = {
165
- site: z
166
- .string()
167
- .optional()
168
- .describe(
169
- 'The ID of the WordPress site to target (from mcp-wordpress.config.json). Required if multiple sites are configured.'
170
- )
171
- };
172
-
173
- // Merge with tool-specific parameters
174
- const parameterSchema =
175
- tool.parameters?.reduce(
176
- (schema: any, param: any) => {
177
- let zodType;
178
-
179
- switch (param.type) {
180
- case 'string':
181
- zodType = z.string();
182
- break;
183
- case 'number':
184
- zodType = z.number();
185
- break;
186
- case 'boolean':
187
- zodType = z.boolean();
188
- break;
189
- case 'array':
190
- zodType = z.array(z.string());
191
- break;
192
- case 'object':
193
- zodType = z.record(z.any());
194
- break;
195
- default:
196
- zodType = z.string();
197
- }
198
-
199
- if (param.description) {
200
- zodType = zodType.describe(param.description);
201
- }
202
-
203
- if (!param.required) {
204
- zodType = zodType.optional();
205
- }
206
-
207
- schema[param.name] = zodType;
208
- return schema;
209
- },
210
- { ...baseSchema }
211
- ) || baseSchema;
212
-
213
- // Make site parameter required if multiple sites are configured
214
- if (this.wordpressClients.size > 1) {
215
- parameterSchema.site = parameterSchema.site.describe(
216
- 'The ID of the WordPress site to target (from mcp-wordpress.config.json). Required when multiple sites are configured.'
217
- );
218
- }
219
-
220
- this.server.tool(
221
- tool.name,
222
- tool.description || `WordPress tool: ${tool.name}`,
223
- parameterSchema,
224
- async (args: any) => {
225
- try {
226
- const siteId = args.site || 'default';
227
- const client = this.wordpressClients.get(siteId);
228
-
229
- if (!client) {
230
- const availableSites = Array.from(
231
- this.wordpressClients.keys()
232
- ).join(', ');
233
- return {
234
- content: [
235
- {
236
- type: 'text' as const,
237
- text: `Error: Site with ID '${siteId}' not found. Available sites: ${availableSites}`
238
- }
239
- ],
240
- isError: true
241
- };
242
- }
243
-
244
- // Call the tool handler with the client and parameters
245
- const result = await tool.handler(client, args);
246
-
247
- return {
248
- content: [
249
- {
250
- type: 'text' as const,
251
- text:
252
- typeof result === 'string'
253
- ? result
254
- : JSON.stringify(result, null, 2)
255
- }
256
- ]
257
- };
258
- } catch (error) {
259
- if (this.isAuthenticationError(error)) {
260
- return {
261
- content: [
262
- {
263
- type: 'text' as const,
264
- text: `Authentication failed for site '${args.site || 'default'}'. Please check your credentials.`
265
- }
266
- ],
267
- isError: true
268
- };
269
- }
270
-
271
- return {
272
- content: [
273
- {
274
- type: 'text' as const,
275
- text: `Error: ${getErrorMessage(error)}`
276
- }
277
- ],
278
- isError: true
279
- };
280
- }
281
- }
282
- );
49
+ this.toolRegistry.registerAllTools();
283
50
  }
284
51
 
285
52
  private async testClientConnections(): Promise<void> {
286
- console.error(
287
- 'INFO: Testing connections to all configured WordPress sites...'
288
- );
289
- const connectionPromises = Array.from(this.wordpressClients.entries()).map(
290
- async ([siteId, client]) => {
291
- try {
292
- await client.ping();
293
- console.error(`SUCCESS: Connection to site '${siteId}' successful.`);
294
- } catch (error) {
295
- console.error(
296
- `ERROR: Failed to connect to site '${siteId}': ${getErrorMessage(error)}`
297
- );
298
- if (this.isAuthenticationError(error)) {
299
- console.error(
300
- `Authentication may have failed for site '${siteId}'. Please check credentials.`
301
- );
302
- }
303
- }
304
- }
305
- );
306
- await Promise.all(connectionPromises);
53
+ await ConnectionTester.testClientConnections(this.wordpressClients);
307
54
  this.initialized = true;
308
- console.error('INFO: Connection tests complete.');
309
55
  }
310
56
 
311
- private isAuthenticationError(error: any): boolean {
312
- if (error?.response?.status && [401, 403].includes(error.response.status)) {
313
- return true;
314
- }
315
- return error?.code === 'WORDPRESS_AUTH_ERROR';
316
- }
317
57
 
318
58
  async run() {
319
59
  if (!this.initialized) {