mcp-wordpress 1.5.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +332 -61
  2. package/dist/cache/CacheInvalidation.d.ts.map +1 -1
  3. package/dist/cache/CacheInvalidation.js +4 -4
  4. package/dist/cache/CacheInvalidation.js.map +1 -1
  5. package/dist/client/MockWordPressClient.d.ts +55 -0
  6. package/dist/client/MockWordPressClient.d.ts.map +1 -0
  7. package/dist/client/MockWordPressClient.js +369 -0
  8. package/dist/client/MockWordPressClient.js.map +1 -0
  9. package/dist/client/api.d.ts +1 -0
  10. package/dist/client/api.d.ts.map +1 -1
  11. package/dist/client/api.js +26 -60
  12. package/dist/client/api.js.map +1 -1
  13. package/dist/client/managers/AuthenticationManager.d.ts.map +1 -1
  14. package/dist/client/managers/AuthenticationManager.js +4 -3
  15. package/dist/client/managers/AuthenticationManager.js.map +1 -1
  16. package/dist/config/ConfigurationSchema.d.ts +3 -3
  17. package/dist/config/ConfigurationSchema.d.ts.map +1 -1
  18. package/dist/config/ConfigurationSchema.js +7 -24
  19. package/dist/config/ConfigurationSchema.js.map +1 -1
  20. package/dist/config/ServerConfiguration.d.ts +8 -0
  21. package/dist/config/ServerConfiguration.d.ts.map +1 -1
  22. package/dist/config/ServerConfiguration.js +80 -31
  23. package/dist/config/ServerConfiguration.js.map +1 -1
  24. package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
  25. package/dist/docs/DocumentationGenerator.js +5 -7
  26. package/dist/docs/DocumentationGenerator.js.map +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +33 -29
  29. package/dist/index.js.map +1 -1
  30. package/dist/security/InputValidator.d.ts.map +1 -1
  31. package/dist/security/InputValidator.js +3 -11
  32. package/dist/security/InputValidator.js.map +1 -1
  33. package/dist/server/ToolRegistry.d.ts +4 -0
  34. package/dist/server/ToolRegistry.d.ts.map +1 -1
  35. package/dist/server/ToolRegistry.js +71 -8
  36. package/dist/server/ToolRegistry.js.map +1 -1
  37. package/dist/tools/auth.d.ts.map +1 -1
  38. package/dist/tools/auth.js +8 -3
  39. package/dist/tools/auth.js.map +1 -1
  40. package/dist/tools/posts.d.ts.map +1 -1
  41. package/dist/tools/posts.js +287 -20
  42. package/dist/tools/posts.js.map +1 -1
  43. package/dist/tools/site.d.ts.map +1 -1
  44. package/dist/tools/site.js +47 -9
  45. package/dist/tools/site.js.map +1 -1
  46. package/dist/tools/users.d.ts.map +1 -1
  47. package/dist/tools/users.js +113 -10
  48. package/dist/tools/users.js.map +1 -1
  49. package/dist/utils/enhancedError.d.ts +61 -0
  50. package/dist/utils/enhancedError.d.ts.map +1 -0
  51. package/dist/utils/enhancedError.js +221 -0
  52. package/dist/utils/enhancedError.js.map +1 -0
  53. package/dist/utils/streaming.d.ts +104 -0
  54. package/dist/utils/streaming.d.ts.map +1 -0
  55. package/dist/utils/streaming.js +312 -0
  56. package/dist/utils/streaming.js.map +1 -0
  57. package/dist/utils/validation.d.ts +19 -3
  58. package/dist/utils/validation.d.ts.map +1 -1
  59. package/dist/utils/validation.js +174 -24
  60. package/dist/utils/validation.js.map +1 -1
  61. package/docs/ARCHITECTURE.md +850 -0
  62. package/docs/CACHING.md +20 -17
  63. package/docs/CONFIGURATION.md +660 -0
  64. package/docs/DOCKER.md +61 -60
  65. package/docs/EVALUATION.md +397 -0
  66. package/docs/INSTALLATION.md +423 -0
  67. package/docs/PERFORMANCE_MONITORING.md +17 -15
  68. package/docs/SECURITY.md +621 -0
  69. package/docs/SECURITY_TESTING.md +22 -26
  70. package/docs/TEST_SITE_SETUP.md +136 -0
  71. package/docs/TROUBLESHOOTING.md +578 -0
  72. package/docs/api/README.md +76 -91
  73. package/docs/api/categories/auth.md +0 -2
  74. package/docs/api/categories/cache.md +0 -2
  75. package/docs/api/categories/comment.md +0 -2
  76. package/docs/api/categories/media.md +0 -2
  77. package/docs/api/categories/page.md +0 -2
  78. package/docs/api/categories/performance.md +0 -2
  79. package/docs/api/categories/post.md +0 -2
  80. package/docs/api/categories/site.md +0 -2
  81. package/docs/api/categories/taxonomy.md +0 -2
  82. package/docs/api/categories/user.md +0 -2
  83. package/docs/api/summary.json +1 -1
  84. package/docs/api/tools/wp_approve_comment.md +11 -3
  85. package/docs/api/tools/wp_cache_clear.md +14 -5
  86. package/docs/api/tools/wp_cache_info.md +14 -5
  87. package/docs/api/tools/wp_cache_stats.md +14 -5
  88. package/docs/api/tools/wp_cache_warm.md +14 -5
  89. package/docs/api/tools/wp_create_application_password.md +11 -3
  90. package/docs/api/tools/wp_create_category.md +11 -3
  91. package/docs/api/tools/wp_create_comment.md +14 -5
  92. package/docs/api/tools/wp_create_page.md +13 -5
  93. package/docs/api/tools/wp_create_post.md +14 -7
  94. package/docs/api/tools/wp_create_tag.md +11 -3
  95. package/docs/api/tools/wp_create_user.md +13 -5
  96. package/docs/api/tools/wp_delete_application_password.md +11 -3
  97. package/docs/api/tools/wp_delete_category.md +11 -3
  98. package/docs/api/tools/wp_delete_comment.md +11 -3
  99. package/docs/api/tools/wp_delete_media.md +10 -3
  100. package/docs/api/tools/wp_delete_page.md +10 -3
  101. package/docs/api/tools/wp_delete_post.md +11 -5
  102. package/docs/api/tools/wp_delete_tag.md +11 -3
  103. package/docs/api/tools/wp_delete_user.md +10 -3
  104. package/docs/api/tools/wp_get_application_passwords.md +11 -3
  105. package/docs/api/tools/wp_get_auth_status.md +11 -3
  106. package/docs/api/tools/wp_get_category.md +11 -3
  107. package/docs/api/tools/wp_get_comment.md +11 -3
  108. package/docs/api/tools/wp_get_current_user.md +11 -3
  109. package/docs/api/tools/wp_get_media.md +11 -3
  110. package/docs/api/tools/wp_get_page.md +11 -3
  111. package/docs/api/tools/wp_get_page_revisions.md +11 -3
  112. package/docs/api/tools/wp_get_post.md +12 -5
  113. package/docs/api/tools/wp_get_post_revisions.md +11 -3
  114. package/docs/api/tools/wp_get_site_settings.md +10 -3
  115. package/docs/api/tools/wp_get_tag.md +11 -3
  116. package/docs/api/tools/wp_get_user.md +11 -3
  117. package/docs/api/tools/wp_list_categories.md +11 -3
  118. package/docs/api/tools/wp_list_comments.md +11 -3
  119. package/docs/api/tools/wp_list_media.md +14 -5
  120. package/docs/api/tools/wp_list_pages.md +14 -5
  121. package/docs/api/tools/wp_list_posts.md +15 -7
  122. package/docs/api/tools/wp_list_tags.md +11 -3
  123. package/docs/api/tools/wp_list_users.md +11 -3
  124. package/docs/api/tools/wp_performance_alerts.md +17 -7
  125. package/docs/api/tools/wp_performance_benchmark.md +17 -7
  126. package/docs/api/tools/wp_performance_export.md +17 -7
  127. package/docs/api/tools/wp_performance_history.md +17 -7
  128. package/docs/api/tools/wp_performance_optimize.md +17 -7
  129. package/docs/api/tools/wp_performance_stats.md +17 -7
  130. package/docs/api/tools/wp_search_site.md +11 -3
  131. package/docs/api/tools/wp_spam_comment.md +11 -3
  132. package/docs/api/tools/wp_switch_auth_method.md +14 -5
  133. package/docs/api/tools/wp_test_auth.md +11 -3
  134. package/docs/api/tools/wp_update_category.md +11 -3
  135. package/docs/api/tools/wp_update_comment.md +14 -5
  136. package/docs/api/tools/wp_update_media.md +14 -5
  137. package/docs/api/tools/wp_update_page.md +13 -5
  138. package/docs/api/tools/wp_update_post.md +14 -7
  139. package/docs/api/tools/wp_update_site_settings.md +14 -5
  140. package/docs/api/tools/wp_update_tag.md +11 -3
  141. package/docs/api/tools/wp_update_user.md +13 -5
  142. package/docs/api/tools/wp_upload_media.md +13 -5
  143. package/docs/api/types/WordPressPost.md +2 -0
  144. package/docs/code-improvements.md +40 -0
  145. package/docs/contract-testing.md +1 -1
  146. package/docs/developer/API_REFERENCE.md +19 -59
  147. package/docs/developer/ARCHITECTURE.md +8 -11
  148. package/docs/developer/BUILD_SYSTEM.md +2 -2
  149. package/docs/developer/CONTRIBUTING.md +3 -5
  150. package/docs/developer/GITHUB_ACTIONS_SETUP.md +2 -2
  151. package/docs/developer/MIGRATION_GUIDE.md +5 -6
  152. package/docs/developer/README.md +2 -1
  153. package/docs/developer/REFACTORING.md +9 -15
  154. package/docs/developer/RELEASE_PROCESS.md +4 -3
  155. package/docs/developer/TESTING.md +2 -2
  156. package/docs/examples/claude-desktop-config.md +8 -0
  157. package/docs/integrations/claude-desktop.md +426 -0
  158. package/docs/integrations/cline.md +537 -0
  159. package/docs/integrations/vs-code.md +515 -0
  160. package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +30 -23
  161. package/docs/releases/RELEASE_NOTES_v1.1.2.md +7 -6
  162. package/docs/testing-configurations.md +11 -0
  163. package/docs/user-guides/DOCKER_NPM_DTX_SETUP.md +3 -2
  164. package/docs/user-guides/DOCKER_SETUP.md +3 -2
  165. package/docs/user-guides/DTX_SETUP.md +6 -5
  166. package/docs/user-guides/DXT_INSTALLATION.md +4 -4
  167. package/docs/user-guides/NPM_SETUP.md +4 -2
  168. package/docs/user-guides/NPX_SETUP.md +4 -2
  169. package/docs/user-guides/SMITHERY_SETUP.md +402 -0
  170. package/docs/wordpress-rest-api-authentication-troubleshooting.md +45 -42
  171. package/package.json +12 -2
  172. package/src/cache/CacheInvalidation.ts +7 -18
  173. package/src/client/MockWordPressClient.ts +398 -0
  174. package/src/client/api.ts +77 -237
  175. package/src/client/managers/AuthenticationManager.ts +19 -56
  176. package/src/config/ConfigurationSchema.ts +14 -45
  177. package/src/config/ServerConfiguration.ts +98 -71
  178. package/src/docs/DocumentationGenerator.ts +39 -123
  179. package/src/dxt-entry.cjs +4 -1
  180. package/src/index.ts +35 -54
  181. package/src/security/InputValidator.ts +15 -57
  182. package/src/server/ToolRegistry.ts +88 -17
  183. package/src/tools/auth.ts +15 -22
  184. package/src/tools/posts.ts +347 -64
  185. package/src/tools/site.ts +69 -46
  186. package/src/tools/users.ts +142 -44
  187. package/src/utils/enhancedError.ts +248 -0
  188. package/src/utils/streaming.ts +428 -0
  189. package/src/utils/validation.ts +253 -92
  190. package/dist/mcp-wordpress-1.5.2.tgz +0 -0
@@ -138,7 +138,7 @@ export class DocumentationGenerator {
138
138
  * Generate complete documentation for all tools and types
139
139
  */
140
140
  async generateFullDocumentation(): Promise<DocumentationOutput> {
141
- console.log("🚀 Starting API documentation generation...");
141
+ console.error("🚀 Starting API documentation generation...");
142
142
 
143
143
  const tools = await this.extractAllToolDocumentation();
144
144
  const categories = this.generateCategoryDocumentation(tools);
@@ -162,9 +162,7 @@ export class DocumentationGenerator {
162
162
  // Write documentation to files
163
163
  await this.writeDocumentationFiles(output);
164
164
 
165
- console.log(
166
- `✅ Documentation generation complete! ${tools.length} tools documented.`,
167
- );
165
+ console.error(`✅ Documentation generation complete! ${tools.length} tools documented.`);
168
166
  return output;
169
167
  }
170
168
 
@@ -190,18 +188,11 @@ export class DocumentationGenerator {
190
188
  const category = this.extractCategoryFromClassName(className);
191
189
 
192
190
  for (const toolDef of toolDefinitions) {
193
- const doc = await this.extractToolDocumentation(
194
- toolDef,
195
- category,
196
- className,
197
- );
191
+ const doc = await this.extractToolDocumentation(toolDef, category, className);
198
192
  toolDocs.push(doc);
199
193
  }
200
194
  } catch (error) {
201
- console.warn(
202
- `⚠️ Failed to extract documentation for ${className}:`,
203
- error,
204
- );
195
+ console.warn(`⚠️ Failed to extract documentation for ${className}:`, error);
205
196
  }
206
197
  }
207
198
 
@@ -216,9 +207,7 @@ export class DocumentationGenerator {
216
207
  category: string,
217
208
  className: string,
218
209
  ): Promise<ToolDocumentation> {
219
- const parameters = this.extractParameterDocumentation(
220
- toolDef.parameters || [],
221
- );
210
+ const parameters = this.extractParameterDocumentation(toolDef.parameters || []);
222
211
  const examples = this.generateToolExamples(toolDef, category);
223
212
  const wordpressEndpoint = this.wordpressEndpoints.get(toolDef.name);
224
213
  const returnType = this.inferReturnType(toolDef.name, category);
@@ -242,9 +231,7 @@ export class DocumentationGenerator {
242
231
  /**
243
232
  * Extract parameter documentation
244
233
  */
245
- private extractParameterDocumentation(
246
- parameters: any[],
247
- ): ParameterDocumentation[] {
234
+ private extractParameterDocumentation(parameters: any[]): ParameterDocumentation[] {
248
235
  return parameters.map((param) => ({
249
236
  name: param.name,
250
237
  type: param.type || "string",
@@ -259,10 +246,7 @@ export class DocumentationGenerator {
259
246
  /**
260
247
  * Generate usage examples for tools
261
248
  */
262
- private generateToolExamples(
263
- toolDef: ToolDefinition,
264
- category: string,
265
- ): ExampleUsage[] {
249
+ private generateToolExamples(toolDef: ToolDefinition, category: string): ExampleUsage[] {
266
250
  const examples: ExampleUsage[] = [];
267
251
 
268
252
  // Basic usage example
@@ -291,10 +275,7 @@ export class DocumentationGenerator {
291
275
  /**
292
276
  * Generate basic usage example
293
277
  */
294
- private generateBasicExample(
295
- toolDef: ToolDefinition,
296
- category: string,
297
- ): ExampleUsage | null {
278
+ private generateBasicExample(toolDef: ToolDefinition, category: string): ExampleUsage | null {
298
279
  const toolName = toolDef.name;
299
280
  const basicParams: Record<string, any> = {};
300
281
 
@@ -310,11 +291,7 @@ export class DocumentationGenerator {
310
291
  description: `Simple example of using ${toolName}`,
311
292
  command: toolName,
312
293
  parameters: basicParams,
313
- expectedResponse: this.generateExpectedResponse(
314
- toolName,
315
- category,
316
- "basic",
317
- ),
294
+ expectedResponse: this.generateExpectedResponse(toolName, category, "basic"),
318
295
  errorExample: {
319
296
  scenario: "Authentication failure",
320
297
  error: {
@@ -328,10 +305,7 @@ export class DocumentationGenerator {
328
305
  /**
329
306
  * Generate multi-site example
330
307
  */
331
- private generateMultiSiteExample(
332
- toolDef: ToolDefinition,
333
- category: string,
334
- ): ExampleUsage | null {
308
+ private generateMultiSiteExample(toolDef: ToolDefinition, category: string): ExampleUsage | null {
335
309
  const params = { site: "site1", ...this.getExampleParameters(toolDef, 1) };
336
310
 
337
311
  return {
@@ -339,21 +313,14 @@ export class DocumentationGenerator {
339
313
  description: `Using ${toolDef.name} with specific site targeting`,
340
314
  command: toolDef.name,
341
315
  parameters: params,
342
- expectedResponse: this.generateExpectedResponse(
343
- toolDef.name,
344
- category,
345
- "multisite",
346
- ),
316
+ expectedResponse: this.generateExpectedResponse(toolDef.name, category, "multisite"),
347
317
  };
348
318
  }
349
319
 
350
320
  /**
351
321
  * Generate advanced example with all parameters
352
322
  */
353
- private generateAdvancedExample(
354
- toolDef: ToolDefinition,
355
- category: string,
356
- ): ExampleUsage | null {
323
+ private generateAdvancedExample(toolDef: ToolDefinition, category: string): ExampleUsage | null {
357
324
  const allParams = this.getExampleParameters(toolDef, "all");
358
325
 
359
326
  if (Object.keys(allParams).length <= 2) {
@@ -365,20 +332,14 @@ export class DocumentationGenerator {
365
332
  description: "Comprehensive example using all available parameters",
366
333
  command: toolDef.name,
367
334
  parameters: allParams,
368
- expectedResponse: this.generateExpectedResponse(
369
- toolDef.name,
370
- category,
371
- "advanced",
372
- ),
335
+ expectedResponse: this.generateExpectedResponse(toolDef.name, category, "advanced"),
373
336
  };
374
337
  }
375
338
 
376
339
  /**
377
340
  * Generate category documentation
378
341
  */
379
- private generateCategoryDocumentation(
380
- tools: ToolDocumentation[],
381
- ): CategoryDocumentation[] {
342
+ private generateCategoryDocumentation(tools: ToolDocumentation[]): CategoryDocumentation[] {
382
343
  const categories = new Map<string, ToolDocumentation[]>();
383
344
 
384
345
  // Group tools by category
@@ -389,15 +350,13 @@ export class DocumentationGenerator {
389
350
  categories.get(tool.category)!.push(tool);
390
351
  }
391
352
 
392
- return Array.from(categories.entries()).map(
393
- ([categoryName, categoryTools]) => ({
394
- name: categoryName,
395
- description: this.getCategoryDescription(categoryName),
396
- toolCount: categoryTools.length,
397
- tools: categoryTools.map((t) => t.name).sort(),
398
- usagePatterns: this.generateUsagePatterns(categoryName, categoryTools),
399
- }),
400
- );
353
+ return Array.from(categories.entries()).map(([categoryName, categoryTools]) => ({
354
+ name: categoryName,
355
+ description: this.getCategoryDescription(categoryName),
356
+ toolCount: categoryTools.length,
357
+ tools: categoryTools.map((t) => t.name).sort(),
358
+ usagePatterns: this.generateUsagePatterns(categoryName, categoryTools),
359
+ }));
401
360
  }
402
361
 
403
362
  /**
@@ -446,10 +405,7 @@ export class DocumentationGenerator {
446
405
  /**
447
406
  * Generate OpenAPI specification
448
407
  */
449
- private generateOpenAPISpecification(
450
- tools: ToolDocumentation[],
451
- types: TypeDocumentation[],
452
- ): OpenAPISpecification {
408
+ private generateOpenAPISpecification(tools: ToolDocumentation[], types: TypeDocumentation[]): OpenAPISpecification {
453
409
  const paths: Record<string, any> = {};
454
410
  const components: Record<string, any> = {
455
411
  schemas: {},
@@ -524,9 +480,7 @@ export class DocumentationGenerator {
524
480
  /**
525
481
  * Write all documentation files
526
482
  */
527
- private async writeDocumentationFiles(
528
- output: DocumentationOutput,
529
- ): Promise<void> {
483
+ private async writeDocumentationFiles(output: DocumentationOutput): Promise<void> {
530
484
  const outputDir = this.config.outputDir;
531
485
 
532
486
  // Ensure output directory exists
@@ -560,19 +514,13 @@ export class DocumentationGenerator {
560
514
 
561
515
  // Write OpenAPI specification
562
516
  if (output.openApiSpec) {
563
- await fs.promises.writeFile(
564
- path.join(outputDir, "openapi.json"),
565
- JSON.stringify(output.openApiSpec, null, 2),
566
- );
517
+ await fs.promises.writeFile(path.join(outputDir, "openapi.json"), JSON.stringify(output.openApiSpec, null, 2));
567
518
  }
568
519
 
569
520
  // Write summary
570
- await fs.promises.writeFile(
571
- path.join(outputDir, "summary.json"),
572
- JSON.stringify(output.summary, null, 2),
573
- );
521
+ await fs.promises.writeFile(path.join(outputDir, "summary.json"), JSON.stringify(output.summary, null, 2));
574
522
 
575
- console.log(`📁 Documentation written to ${outputDir}/`);
523
+ console.error(`📁 Documentation written to ${outputDir}/`);
576
524
  }
577
525
 
578
526
  // Helper methods for specific documentation tasks...
@@ -624,8 +572,7 @@ export class DocumentationGenerator {
624
572
  version: "1.2.0",
625
573
  coverage: {
626
574
  toolsWithExamples: tools.filter((t) => t.examples.length > 0).length,
627
- toolsWithWordPressMapping: tools.filter((t) => t.wordpressEndpoint)
628
- .length,
575
+ toolsWithWordPressMapping: tools.filter((t) => t.wordpressEndpoint).length,
629
576
  typesDocumented: types.length,
630
577
  },
631
578
  };
@@ -709,11 +656,7 @@ export class DocumentationGenerator {
709
656
  return exampleValues[param.name] || "example_value";
710
657
  }
711
658
 
712
- private generateExpectedResponse(
713
- toolName: string,
714
- category: string,
715
- type: string,
716
- ): any {
659
+ private generateExpectedResponse(toolName: string, category: string, type: string): any {
717
660
  if (toolName.includes("list")) {
718
661
  return {
719
662
  success: true,
@@ -781,10 +724,7 @@ export class DocumentationGenerator {
781
724
  };
782
725
  }
783
726
 
784
- private getExampleParameters(
785
- toolDef: ToolDefinition,
786
- type: string | number,
787
- ): Record<string, any> {
727
+ private getExampleParameters(toolDef: ToolDefinition, type: string | number): Record<string, any> {
788
728
  const params: Record<string, any> = {};
789
729
  const parameters = toolDef.parameters || [];
790
730
 
@@ -816,16 +756,10 @@ export class DocumentationGenerator {
816
756
  cache: "Performance caching and optimization tools",
817
757
  performance: "Performance monitoring and analytics tools",
818
758
  };
819
- return (
820
- descriptions[categoryName.toLowerCase()] ||
821
- `${categoryName} management tools`
822
- );
759
+ return descriptions[categoryName.toLowerCase()] || `${categoryName} management tools`;
823
760
  }
824
761
 
825
- private generateUsagePatterns(
826
- categoryName: string,
827
- tools: ToolDocumentation[],
828
- ): string[] {
762
+ private generateUsagePatterns(categoryName: string, tools: ToolDocumentation[]): string[] {
829
763
  const patterns: Record<string, string[]> = {
830
764
  posts: [
831
765
  "Create and publish blog posts",
@@ -865,8 +799,7 @@ export class DocumentationGenerator {
865
799
  return {
866
800
  id: 123,
867
801
  title: "Welcome to WordPress",
868
- content:
869
- "<p>This is your first post. Edit or delete it to get started!</p>",
802
+ content: "<p>This is your first post. Edit or delete it to get started!</p>",
870
803
  status: "publish",
871
804
  date: "2024-01-01T00:00:00Z",
872
805
  author: 1,
@@ -953,8 +886,7 @@ export class DocumentationGenerator {
953
886
  code: "AUTHENTICATION_FAILED",
954
887
  message: "Authentication failed",
955
888
  description: "Invalid credentials or insufficient permissions",
956
- resolution:
957
- "Check your authentication credentials and user permissions",
889
+ resolution: "Check your authentication credentials and user permissions",
958
890
  },
959
891
  {
960
892
  code: "VALIDATION_ERROR",
@@ -972,8 +904,7 @@ export class DocumentationGenerator {
972
904
  code: "PERMISSION_DENIED",
973
905
  message: "Insufficient permissions",
974
906
  description: "The user does not have permission to perform this action",
975
- resolution:
976
- "Contact an administrator to grant the necessary permissions",
907
+ resolution: "Contact an administrator to grant the necessary permissions",
977
908
  },
978
909
  ];
979
910
  }
@@ -1012,10 +943,7 @@ export class DocumentationGenerator {
1012
943
  const formatter = new MarkdownFormatter();
1013
944
  const content = formatter.generateApiOverview(output);
1014
945
 
1015
- await fs.promises.writeFile(
1016
- path.join(this.config.outputDir, "README.md"),
1017
- content,
1018
- );
946
+ await fs.promises.writeFile(path.join(this.config.outputDir, "README.md"), content);
1019
947
  }
1020
948
 
1021
949
  private async writeToolDocumentation(tool: ToolDocumentation): Promise<void> {
@@ -1023,25 +951,16 @@ export class DocumentationGenerator {
1023
951
  const formatter = new MarkdownFormatter();
1024
952
  const content = formatter.generateToolDocumentation(tool);
1025
953
 
1026
- await fs.promises.writeFile(
1027
- path.join(this.config.outputDir, "tools", `${tool.name}.md`),
1028
- content,
1029
- );
954
+ await fs.promises.writeFile(path.join(this.config.outputDir, "tools", `${tool.name}.md`), content);
1030
955
  }
1031
956
 
1032
- private async writeCategoryDocumentation(
1033
- category: CategoryDocumentation,
1034
- ): Promise<void> {
957
+ private async writeCategoryDocumentation(category: CategoryDocumentation): Promise<void> {
1035
958
  const { MarkdownFormatter } = await import("./MarkdownFormatter.js");
1036
959
  const formatter = new MarkdownFormatter();
1037
960
  const content = formatter.generateCategoryDocumentation(category);
1038
961
 
1039
962
  await fs.promises.writeFile(
1040
- path.join(
1041
- this.config.outputDir,
1042
- "categories",
1043
- `${category.name.toLowerCase()}.md`,
1044
- ),
963
+ path.join(this.config.outputDir, "categories", `${category.name.toLowerCase()}.md`),
1045
964
  content,
1046
965
  );
1047
966
  }
@@ -1051,9 +970,6 @@ export class DocumentationGenerator {
1051
970
  const formatter = new MarkdownFormatter();
1052
971
  const content = formatter.generateTypeDocumentation(type);
1053
972
 
1054
- await fs.promises.writeFile(
1055
- path.join(this.config.outputDir, "types", `${type.name}.md`),
1056
- content,
1057
- );
973
+ await fs.promises.writeFile(path.join(this.config.outputDir, "types", `${type.name}.md`), content);
1058
974
  }
1059
975
  }
package/src/dxt-entry.cjs CHANGED
@@ -16,6 +16,9 @@ console.error(`DEBUG: Current working directory: ${process.cwd()}`);
16
16
  console.error(`DEBUG: __dirname: ${__dirname}`);
17
17
  console.error(`DEBUG: Node version: ${process.version}`);
18
18
 
19
+ // Set DXT mode environment variable
20
+ process.env.NODE_ENV = "dxt";
21
+
19
22
  console.error("DEBUG: Environment variables passed from DXT:");
20
23
  console.error(` WORDPRESS_SITE_URL: ${process.env.WORDPRESS_SITE_URL ? 'SET' : 'NOT SET'}`);
21
24
  console.error(` WORDPRESS_USERNAME: ${process.env.WORDPRESS_USERNAME ? 'SET' : 'NOT SET'}`);
@@ -30,7 +33,7 @@ async function startDXTServer() {
30
33
  console.error("DEBUG: Creating MCPWordPressServer instance from DXT entry point...");
31
34
  const server = new MCPWordPressServer();
32
35
 
33
- console.error("DEBUG: Starting server...");
36
+ console.error("DEBUG: Starting server (DXT mode - fast startup)...");
34
37
  await server.run();
35
38
 
36
39
  // Handle graceful shutdown
package/src/index.ts CHANGED
@@ -1,19 +1,12 @@
1
- console.error("DEBUG: MCP WordPress Server module loading started...");
2
-
3
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
3
  import { fileURLToPath } from "url";
6
4
  import { WordPressClient } from "./client/api.js";
7
- import {
8
- ServerConfiguration,
9
- SiteConfig,
10
- } from "./config/ServerConfiguration.js";
5
+ import { ServerConfiguration, SiteConfig } from "./config/ServerConfiguration.js";
11
6
  import { ToolRegistry } from "./server/ToolRegistry.js";
12
7
  import { ConnectionTester } from "./server/ConnectionTester.js";
13
8
  import { getErrorMessage } from "./utils/error.js";
14
9
 
15
- console.error("DEBUG: All imports completed successfully");
16
-
17
10
  // --- Constants ---
18
11
  const SERVER_VERSION = "1.1.8"; // Technical debt resolution and modular architecture
19
12
 
@@ -26,20 +19,6 @@ class MCPWordPressServer {
26
19
  private toolRegistry: ToolRegistry;
27
20
 
28
21
  constructor(mcpConfig?: any) {
29
- // Add debugging output for DXT troubleshooting
30
- console.error("DEBUG: Starting MCP WordPress Server initialization...");
31
- console.error("DEBUG: Environment variables:");
32
- console.error(
33
- ` WORDPRESS_SITE_URL: ${process.env.WORDPRESS_SITE_URL ? "SET" : "NOT SET"}`,
34
- );
35
- console.error(
36
- ` WORDPRESS_USERNAME: ${process.env.WORDPRESS_USERNAME ? "SET" : "NOT SET"}`,
37
- );
38
- console.error(
39
- ` WORDPRESS_APP_PASSWORD: ${process.env.WORDPRESS_APP_PASSWORD ? "SET" : "NOT SET"}`,
40
- );
41
- console.error(` Working directory: ${process.cwd()}`);
42
-
43
22
  this.loadConfiguration(mcpConfig);
44
23
 
45
24
  if (this.wordpressClients.size === 0) {
@@ -64,8 +43,7 @@ class MCPWordPressServer {
64
43
 
65
44
  private loadConfiguration(mcpConfig?: any) {
66
45
  const serverConfig = ServerConfiguration.getInstance();
67
- const { clients, configs } =
68
- serverConfig.loadClientConfigurations(mcpConfig);
46
+ const { clients, configs } = serverConfig.loadClientConfigurations(mcpConfig);
69
47
 
70
48
  this.wordpressClients = clients;
71
49
  this.siteConfigs = configs;
@@ -81,21 +59,45 @@ class MCPWordPressServer {
81
59
  }
82
60
 
83
61
  async run() {
84
- if (!this.initialized) {
85
- await this.testClientConnections();
62
+ // Skip connection testing in DXT environment to prevent timeouts
63
+ const isDXTMode = process.env.NODE_ENV === "dxt" || process.argv[0]?.includes("dxt-entry");
64
+
65
+ if (!this.initialized && !isDXTMode) {
66
+ console.error("INFO: Testing connections to configured WordPress sites...");
67
+ try {
68
+ await this.testClientConnections();
69
+ } catch (error) {
70
+ console.error(`WARNING: Connection test failed: ${getErrorMessage(error)}`);
71
+ console.error("INFO: Continuing with server startup. Tools will be available but connections may fail.");
72
+ }
73
+ } else if (isDXTMode) {
74
+ console.error("INFO: DXT mode detected - skipping connection tests for faster startup");
75
+ this.initialized = true;
86
76
  }
77
+
87
78
  console.error("INFO: Starting MCP WordPress Server...");
88
79
 
89
- // Connect to stdio transport
80
+ // Connect to stdio transport with timeout
90
81
  const transport = new StdioServerTransport();
91
- await this.server.connect(transport);
92
82
 
93
- console.error(
94
- `INFO: Server started and connected. Tools available for ${this.wordpressClients.size} site(s).`,
95
- );
83
+ // Add timeout protection for server connection
84
+ const connectionTimeout = setTimeout(() => {
85
+ console.error("ERROR: Server connection timed out after 30 seconds");
86
+ process.exit(1);
87
+ }, 30000);
88
+
89
+ try {
90
+ await this.server.connect(transport);
91
+ clearTimeout(connectionTimeout);
92
+
93
+ console.error(`INFO: Server started and connected. Tools available for ${this.wordpressClients.size} site(s).`);
96
94
 
97
- // Keep the process alive
98
- process.stdin.resume();
95
+ // Keep the process alive
96
+ process.stdin.resume();
97
+ } catch (error) {
98
+ clearTimeout(connectionTimeout);
99
+ throw error;
100
+ }
99
101
  }
100
102
 
101
103
  async shutdown() {
@@ -107,16 +109,8 @@ class MCPWordPressServer {
107
109
 
108
110
  // --- Main Execution ---
109
111
  async function main() {
110
- console.error("DEBUG: main() function started");
111
- console.error(`DEBUG: process.argv: ${JSON.stringify(process.argv)}`);
112
- console.error(
113
- `DEBUG: fileURLToPath(import.meta.url): ${fileURLToPath(import.meta.url)}`,
114
- );
115
-
116
112
  try {
117
- console.error("DEBUG: Creating MCPWordPressServer instance...");
118
113
  const mcpServer = new MCPWordPressServer();
119
- console.error("DEBUG: MCPWordPressServer created, calling run()...");
120
114
  await mcpServer.run();
121
115
 
122
116
  const shutdown = async () => {
@@ -128,18 +122,10 @@ async function main() {
128
122
  process.on("SIGTERM", shutdown);
129
123
  } catch (error) {
130
124
  console.error(`FATAL: Failed to start server: ${getErrorMessage(error)}`);
131
- console.error(`FATAL: Error stack: ${(error as Error).stack}`);
132
125
  process.exit(1);
133
126
  }
134
127
  }
135
128
 
136
- console.error(
137
- `DEBUG: Checking if should run main - process.argv[1]: ${process.argv[1]}`,
138
- );
139
- console.error(
140
- `DEBUG: fileURLToPath(import.meta.url): ${fileURLToPath(import.meta.url)}`,
141
- );
142
-
143
129
  // Check if running as main module - handle both direct execution and DXT entry point
144
130
  const isMainModule =
145
131
  process.argv[1] === fileURLToPath(import.meta.url) ||
@@ -148,12 +134,7 @@ const isMainModule =
148
134
  !process.argv[1]; // When run through DXT, process.argv[1] might be undefined
149
135
 
150
136
  if (isMainModule) {
151
- console.error("DEBUG: Running main function...");
152
137
  main();
153
- } else {
154
- console.error(
155
- "DEBUG: Not running main function - module imported, not executed directly",
156
- );
157
138
  }
158
139
 
159
140
  export default MCPWordPressServer;
@@ -10,8 +10,7 @@ const URL_PATTERN = /^https?:\/\/[^\s<>'"{}|\\^`\[\]]+$/;
10
10
  const EMAIL_PATTERN = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
11
11
  const SLUG_PATTERN = /^[a-z0-9-]+$/;
12
12
  const SCRIPT_PATTERN = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi;
13
- const SQL_INJECTION_PATTERN =
14
- /('|(\\')|(;)|(\\x00)|(\\n)|(\\r)|(\\x1a)|(\\x22)|(\\x27)|(\\x5c)|(\\x60))/i;
13
+ const SQL_INJECTION_PATTERN = /('|(\\')|(;)|(\\x00)|(\\n)|(\\r)|(\\x1a)|(\\x22)|(\\x27)|(\\x5c)|(\\x60))/i;
15
14
 
16
15
  /**
17
16
  * Security validation schemas
@@ -22,10 +21,7 @@ export const SecuritySchemas = {
22
21
  .string()
23
22
  .max(10000, "String too long")
24
23
  .refine((val) => !SCRIPT_PATTERN.test(val), "Script tags not allowed")
25
- .refine(
26
- (val) => !val.includes("javascript:"),
27
- "JavaScript URLs not allowed",
28
- )
24
+ .refine((val) => !val.includes("javascript:"), "JavaScript URLs not allowed")
29
25
  .refine((val) => !val.includes("data:"), "Data URLs not allowed")
30
26
  .refine((val) => !val.includes("onerror="), "Event handlers not allowed")
31
27
  .refine((val) => !val.includes("onload="), "Event handlers not allowed")
@@ -36,10 +32,7 @@ export const SecuritySchemas = {
36
32
  .string()
37
33
  .max(100000, "Content too long")
38
34
  .refine((val) => !SCRIPT_PATTERN.test(val), "Script tags not allowed")
39
- .refine(
40
- (val) => !val.includes("javascript:"),
41
- "JavaScript URLs not allowed",
42
- )
35
+ .refine((val) => !val.includes("javascript:"), "JavaScript URLs not allowed")
43
36
  .refine((val) => !val.includes("on[a-z]+="), "Event handlers not allowed"),
44
37
 
45
38
  // URL validation
@@ -47,10 +40,7 @@ export const SecuritySchemas = {
47
40
  .string()
48
41
  .url("Invalid URL format")
49
42
  .regex(URL_PATTERN, "URL contains invalid characters")
50
- .refine(
51
- (val) => !val.includes("javascript:"),
52
- "JavaScript URLs not allowed",
53
- )
43
+ .refine((val) => !val.includes("javascript:"), "JavaScript URLs not allowed")
54
44
  .refine((val) => !val.includes("data:"), "Data URLs not allowed"),
55
45
 
56
46
  // Email validation
@@ -65,49 +55,30 @@ export const SecuritySchemas = {
65
55
  .string()
66
56
  .min(1, "Slug cannot be empty")
67
57
  .max(100, "Slug too long")
68
- .regex(
69
- SLUG_PATTERN,
70
- "Slug can only contain lowercase letters, numbers, and hyphens",
71
- ),
58
+ .regex(SLUG_PATTERN, "Slug can only contain lowercase letters, numbers, and hyphens"),
72
59
 
73
60
  // WordPress post/page content
74
61
  wpContent: z
75
62
  .string()
76
63
  .max(1000000, "Content too long")
77
- .refine(
78
- (val) => !SCRIPT_PATTERN.test(val),
79
- "Script tags not allowed in content",
80
- )
81
- .refine(
82
- (val) => !val.includes("javascript:"),
83
- "JavaScript URLs not allowed",
84
- ),
64
+ .refine((val) => !SCRIPT_PATTERN.test(val), "Script tags not allowed in content")
65
+ .refine((val) => !val.includes("javascript:"), "JavaScript URLs not allowed"),
85
66
 
86
67
  // Site ID validation
87
68
  siteId: z
88
69
  .string()
89
70
  .min(1, "Site ID cannot be empty")
90
71
  .max(50, "Site ID too long")
91
- .regex(
92
- /^[a-zA-Z0-9\-_]+$/,
93
- "Site ID can only contain letters, numbers, hyphens, and underscores",
94
- ),
72
+ .regex(/^[a-zA-Z0-9\-_]+$/, "Site ID can only contain letters, numbers, hyphens, and underscores"),
95
73
 
96
74
  // WordPress ID (numeric)
97
- wpId: z
98
- .number()
99
- .int("ID must be an integer")
100
- .positive("ID must be positive")
101
- .max(999999999, "ID too large"),
75
+ wpId: z.number().int("ID must be an integer").positive("ID must be positive").max(999999999, "ID too large"),
102
76
 
103
77
  // Search query with SQL injection protection
104
78
  searchQuery: z
105
79
  .string()
106
80
  .max(500, "Search query too long")
107
- .refine(
108
- (val) => !SQL_INJECTION_PATTERN.test(val),
109
- "Invalid characters in search query",
110
- )
81
+ .refine((val) => !SQL_INJECTION_PATTERN.test(val), "Invalid characters in search query")
111
82
  .refine((val) => !val.includes("--"), "SQL comments not allowed")
112
83
  .refine((val) => !val.includes("/*"), "SQL comments not allowed"),
113
84
 
@@ -188,11 +159,7 @@ export class InputSanitizer {
188
159
  * Security validation decorator for tool methods
189
160
  */
190
161
  export function validateSecurity(schema: z.ZodSchema) {
191
- return function (
192
- target: any,
193
- propertyName: string,
194
- descriptor: PropertyDescriptor,
195
- ) {
162
+ return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
196
163
  const method = descriptor.value;
197
164
 
198
165
  descriptor.value = async function (...args: any[]) {
@@ -202,7 +169,7 @@ export function validateSecurity(schema: z.ZodSchema) {
202
169
  const validatedParams = schema.parse(params);
203
170
 
204
171
  // Log security validation (without sensitive data)
205
- console.log(`Security validation passed for ${propertyName}`, {
172
+ console.error(`Security validation passed for ${propertyName}`, {
206
173
  timestamp: new Date().toISOString(),
207
174
  method: propertyName,
208
175
  paramCount: Object.keys(validatedParams).length,
@@ -215,12 +182,7 @@ export function validateSecurity(schema: z.ZodSchema) {
215
182
  console.error(`Security validation failed for ${propertyName}`, {
216
183
  timestamp: new Date().toISOString(),
217
184
  method: propertyName,
218
- error:
219
- error instanceof z.ZodError
220
- ? error.errors
221
- : error instanceof Error
222
- ? error.message
223
- : String(error),
185
+ error: error instanceof z.ZodError ? error.errors : error instanceof Error ? error.message : String(error),
224
186
  });
225
187
 
226
188
  throw new SecurityValidationError(
@@ -229,8 +191,7 @@ export function validateSecurity(schema: z.ZodSchema) {
229
191
  ? error.errors
230
192
  : [
231
193
  {
232
- message:
233
- error instanceof Error ? error.message : String(error),
194
+ message: error instanceof Error ? error.message : String(error),
234
195
  },
235
196
  ],
236
197
  );
@@ -328,10 +289,7 @@ export const ToolSchemas = {
328
289
  * Rate limiting and DoS protection
329
290
  */
330
291
  export class SecurityLimiter {
331
- private static requestCounts = new Map<
332
- string,
333
- { count: number; resetTime: number }
334
- >();
292
+ private static requestCounts = new Map<string, { count: number; resetTime: number }>();
335
293
  private static readonly RATE_LIMIT = 1000; // requests per window
336
294
  private static readonly WINDOW_MS = 60 * 1000; // 1 minute
337
295