mcp-wordpress 2.10.0 → 2.10.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 (198) hide show
  1. package/README.md +17 -19
  2. package/bin/mcp-wordpress.js +3 -3
  3. package/bin/setup.js +140 -141
  4. package/bin/status.js +112 -114
  5. package/dist/client/MockWordPressClient.d.ts.map +1 -1
  6. package/dist/client/MockWordPressClient.js.map +1 -1
  7. package/dist/client/SEOWordPressClient.d.ts.map +1 -1
  8. package/dist/client/SEOWordPressClient.js +16 -14
  9. package/dist/client/SEOWordPressClient.js.map +1 -1
  10. package/dist/client/index.d.ts +6 -6
  11. package/dist/client/index.js +6 -6
  12. package/dist/client/managers/AuthManager.d.ts.map +1 -1
  13. package/dist/client/managers/AuthManager.js +2 -2
  14. package/dist/client/managers/AuthManager.js.map +1 -1
  15. package/dist/client/managers/AuthenticationManager.js +1 -1
  16. package/dist/client/managers/JWTAuthImplementation.d.ts.map +1 -1
  17. package/dist/client/managers/JWTAuthImplementation.js +7 -7
  18. package/dist/client/managers/JWTAuthImplementation.js.map +1 -1
  19. package/dist/client/managers/composed/MigrationAdapter.js +1 -1
  20. package/dist/client/managers/composed/index.d.ts +2 -2
  21. package/dist/client/managers/composed/index.d.ts.map +1 -1
  22. package/dist/client/managers/composed/index.js +1 -1
  23. package/dist/client/managers/composed/index.js.map +1 -1
  24. package/dist/client/managers/implementations/ErrorHandlerImpl.d.ts.map +1 -1
  25. package/dist/client/managers/implementations/ErrorHandlerImpl.js +2 -4
  26. package/dist/client/managers/implementations/ErrorHandlerImpl.js.map +1 -1
  27. package/dist/client/managers/implementations/ParameterValidatorImpl.d.ts.map +1 -1
  28. package/dist/client/managers/implementations/ParameterValidatorImpl.js +1 -1
  29. package/dist/client/managers/implementations/ParameterValidatorImpl.js.map +1 -1
  30. package/dist/client/managers/interfaces/ManagerInterfaces.d.ts.map +1 -1
  31. package/dist/config/index.d.ts +3 -3
  32. package/dist/config/index.js +3 -3
  33. package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
  34. package/dist/docs/MarkdownFormatter.js +7 -7
  35. package/dist/docs/MarkdownFormatter.js.map +1 -1
  36. package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
  37. package/dist/performance/PerformanceAnalytics.js +3 -1
  38. package/dist/performance/PerformanceAnalytics.js.map +1 -1
  39. package/dist/security/InputValidator.js +1 -1
  40. package/dist/security/SecurityCIPipeline.js +1 -1
  41. package/dist/security/SecurityCIPipeline.js.map +1 -1
  42. package/dist/security/SecurityConfig.d.ts.map +1 -1
  43. package/dist/security/SecurityConfig.js +6 -2
  44. package/dist/security/SecurityConfig.js.map +1 -1
  45. package/dist/server/index.d.ts +2 -2
  46. package/dist/server/index.js +2 -2
  47. package/dist/tools/cache.d.ts.map +1 -1
  48. package/dist/tools/cache.js.map +1 -1
  49. package/dist/tools/comments.d.ts.map +1 -1
  50. package/dist/tools/comments.js.map +1 -1
  51. package/dist/tools/performance.d.ts.map +1 -1
  52. package/dist/tools/performance.js.map +1 -1
  53. package/dist/tools/posts/PostHandlers.d.ts.map +1 -1
  54. package/dist/tools/posts/PostHandlers.js.map +1 -1
  55. package/dist/tools/seo/SEOTools.d.ts.map +1 -1
  56. package/dist/tools/seo/SEOTools.js.map +1 -1
  57. package/dist/tools/seo/analyzers/ContentAnalyzer.d.ts.map +1 -1
  58. package/dist/tools/seo/analyzers/ContentAnalyzer.js.map +1 -1
  59. package/dist/types/enhanced.d.ts +17 -17
  60. package/dist/types/enhanced.d.ts.map +1 -1
  61. package/dist/types/enhanced.js +2 -2
  62. package/dist/types/index.d.ts +2 -2
  63. package/dist/types/index.d.ts.map +1 -1
  64. package/dist/types/requests.d.ts +16 -16
  65. package/dist/types/tools.d.ts +46 -46
  66. package/dist/types/tools.d.ts.map +1 -1
  67. package/dist/utils/index.d.ts +7 -7
  68. package/dist/utils/index.js +7 -7
  69. package/docs/ARCHITECTURE.md +17 -17
  70. package/docs/BADGE_UPDATES.md +11 -11
  71. package/docs/CACHING.md +2 -0
  72. package/docs/CI_CD_IMPROVEMENTS.md +8 -5
  73. package/docs/CONFIGURATION.md +76 -46
  74. package/docs/DOCKER_PUBLISHING_TROUBLESHOOTING.md +11 -2
  75. package/docs/EVALUATION.md +16 -21
  76. package/docs/INCREMENTAL_COVERAGE.md +7 -3
  77. package/docs/INSTALLATION.md +33 -19
  78. package/docs/PUBLISHING-TROUBLESHOOTING.md +3 -2
  79. package/docs/SECURITY.md +17 -15
  80. package/docs/SECURITY_TESTING.md +3 -0
  81. package/docs/TROUBLESHOOTING.md +85 -36
  82. package/docs/api/README.md +118 -125
  83. package/docs/api/categories/auth.md +3 -1
  84. package/docs/api/categories/cache.md +3 -1
  85. package/docs/api/categories/comment.md +3 -1
  86. package/docs/api/categories/media.md +3 -1
  87. package/docs/api/categories/page.md +3 -1
  88. package/docs/api/categories/performance.md +3 -1
  89. package/docs/api/categories/post.md +3 -1
  90. package/docs/api/categories/site.md +3 -1
  91. package/docs/api/categories/taxonomy.md +3 -1
  92. package/docs/api/categories/user.md +3 -1
  93. package/docs/api/openapi.json +114 -410
  94. package/docs/api/summary.json +1 -1
  95. package/docs/api/tools/wp_approve_comment.md +13 -25
  96. package/docs/api/tools/wp_cache_clear.md +17 -30
  97. package/docs/api/tools/wp_cache_info.md +16 -29
  98. package/docs/api/tools/wp_cache_stats.md +16 -29
  99. package/docs/api/tools/wp_cache_warm.md +16 -29
  100. package/docs/api/tools/wp_create_application_password.md +14 -26
  101. package/docs/api/tools/wp_create_category.md +14 -26
  102. package/docs/api/tools/wp_create_comment.md +18 -31
  103. package/docs/api/tools/wp_create_page.md +17 -29
  104. package/docs/api/tools/wp_create_post.md +25 -30
  105. package/docs/api/tools/wp_create_tag.md +13 -25
  106. package/docs/api/tools/wp_create_user.md +18 -30
  107. package/docs/api/tools/wp_delete_application_password.md +14 -26
  108. package/docs/api/tools/wp_delete_category.md +13 -25
  109. package/docs/api/tools/wp_delete_comment.md +14 -26
  110. package/docs/api/tools/wp_delete_media.md +14 -25
  111. package/docs/api/tools/wp_delete_page.md +14 -25
  112. package/docs/api/tools/wp_delete_post.md +17 -25
  113. package/docs/api/tools/wp_delete_tag.md +13 -25
  114. package/docs/api/tools/wp_delete_user.md +14 -25
  115. package/docs/api/tools/wp_get_application_passwords.md +13 -25
  116. package/docs/api/tools/wp_get_auth_status.md +12 -24
  117. package/docs/api/tools/wp_get_category.md +13 -25
  118. package/docs/api/tools/wp_get_comment.md +13 -25
  119. package/docs/api/tools/wp_get_current_user.md +17 -30
  120. package/docs/api/tools/wp_get_media.md +13 -25
  121. package/docs/api/tools/wp_get_page.md +13 -25
  122. package/docs/api/tools/wp_get_page_revisions.md +13 -25
  123. package/docs/api/tools/wp_get_post.md +16 -25
  124. package/docs/api/tools/wp_get_post_revisions.md +13 -25
  125. package/docs/api/tools/wp_get_site_settings.md +12 -23
  126. package/docs/api/tools/wp_get_tag.md +13 -25
  127. package/docs/api/tools/wp_get_user.md +13 -25
  128. package/docs/api/tools/wp_list_categories.md +15 -27
  129. package/docs/api/tools/wp_list_comments.md +15 -27
  130. package/docs/api/tools/wp_list_media.md +18 -31
  131. package/docs/api/tools/wp_list_pages.md +18 -31
  132. package/docs/api/tools/wp_list_posts.md +29 -41
  133. package/docs/api/tools/wp_list_tags.md +14 -26
  134. package/docs/api/tools/wp_list_users.md +20 -34
  135. package/docs/api/tools/wp_performance_alerts.md +22 -36
  136. package/docs/api/tools/wp_performance_benchmark.md +20 -34
  137. package/docs/api/tools/wp_performance_export.md +22 -36
  138. package/docs/api/tools/wp_performance_history.md +21 -35
  139. package/docs/api/tools/wp_performance_optimize.md +22 -36
  140. package/docs/api/tools/wp_performance_stats.md +20 -34
  141. package/docs/api/tools/wp_search_site.md +18 -32
  142. package/docs/api/tools/wp_spam_comment.md +13 -25
  143. package/docs/api/tools/wp_switch_auth_method.md +18 -31
  144. package/docs/api/tools/wp_test_auth.md +15 -30
  145. package/docs/api/tools/wp_update_category.md +14 -26
  146. package/docs/api/tools/wp_update_comment.md +17 -30
  147. package/docs/api/tools/wp_update_media.md +19 -32
  148. package/docs/api/tools/wp_update_page.md +18 -30
  149. package/docs/api/tools/wp_update_post.md +21 -30
  150. package/docs/api/tools/wp_update_site_settings.md +18 -31
  151. package/docs/api/tools/wp_update_tag.md +14 -26
  152. package/docs/api/tools/wp_update_user.md +17 -29
  153. package/docs/api/tools/wp_upload_media.md +20 -32
  154. package/docs/api/types/WordPressPost.md +8 -15
  155. package/docs/code-improvements.md +1 -0
  156. package/docs/developer/GITHUB_ACTIONS_SETUP.md +2 -2
  157. package/docs/developer/MAINTENANCE.md +4 -0
  158. package/docs/developer/NPM_AUTH_SETUP.md +3 -0
  159. package/docs/developer/RELEASE_PROCESS.md +1 -0
  160. package/docs/examples/multi-site-setup.md +2 -0
  161. package/docs/integrations/claude-desktop.md +14 -5
  162. package/docs/integrations/cline.md +1 -0
  163. package/docs/user-guides/DTX_SETUP.md +9 -8
  164. package/docs/user-guides/NPX_SETUP.md +5 -9
  165. package/docs/user-guides/SMITHERY_SETUP.md +5 -0
  166. package/docs/v2.2.0-resolution-demo.md +17 -2
  167. package/package.json +2 -1
  168. package/src/cache/__tests__/CacheManager.test.ts +4 -8
  169. package/src/client/MockWordPressClient.ts +5 -1
  170. package/src/client/SEOWordPressClient.ts +30 -26
  171. package/src/client/index.ts +6 -6
  172. package/src/client/managers/AuthManager.ts +16 -8
  173. package/src/client/managers/AuthenticationManager.ts +2 -2
  174. package/src/client/managers/JWTAuthImplementation.ts +24 -27
  175. package/src/client/managers/ManagersIndex.ts +1 -1
  176. package/src/client/managers/composed/MigrationAdapter.ts +1 -1
  177. package/src/client/managers/composed/index.ts +7 -7
  178. package/src/client/managers/implementations/ErrorHandlerImpl.ts +12 -26
  179. package/src/client/managers/implementations/ParameterValidatorImpl.ts +49 -49
  180. package/src/client/managers/interfaces/ManagerInterfaces.ts +13 -9
  181. package/src/config/index.ts +3 -3
  182. package/src/docs/MarkdownFormatter.ts +13 -9
  183. package/src/performance/PerformanceAnalytics.ts +9 -3
  184. package/src/security/InputValidator.ts +1 -1
  185. package/src/security/SecurityCIPipeline.ts +1 -1
  186. package/src/security/SecurityConfig.ts +9 -3
  187. package/src/server/index.ts +2 -2
  188. package/src/tools/cache.ts +3 -1
  189. package/src/tools/comments.ts +3 -1
  190. package/src/tools/performance.ts +7 -3
  191. package/src/tools/posts/PostHandlers.ts +3 -1
  192. package/src/tools/seo/SEOTools.ts +6 -2
  193. package/src/tools/seo/analyzers/ContentAnalyzer.ts +9 -3
  194. package/src/types/enhanced.ts +34 -34
  195. package/src/types/index.ts +13 -11
  196. package/src/types/requests.ts +19 -19
  197. package/src/types/tools.ts +137 -84
  198. package/src/utils/index.ts +7 -7
@@ -23,8 +23,7 @@ command line, no configuration files - just click and configure.
23
23
 
24
24
  **Option A: Direct Download**
25
25
 
26
- - Click here:
27
- [`mcp-wordpress.dxt`](https://github.com/docdyhr/mcp-wordpress/releases/latest/download/mcp-wordpress.dxt)
26
+ - Click here: [`mcp-wordpress.dxt`](https://github.com/docdyhr/mcp-wordpress/releases/latest/download/mcp-wordpress.dxt)
28
27
  (3.4MB)
29
28
 
30
29
  **Option B: Command Line**
@@ -48,10 +47,12 @@ curl -L -o mcp-wordpress.dxt \
48
47
  ### Step 3: Configure WordPress Connection
49
48
 
50
49
  1. **Extension Settings**
50
+
51
51
  - Find "WordPress MCP Server" in your extensions list
52
52
  - Click the settings/configuration button
53
53
 
54
54
  2. **Enter WordPress Details**
55
+
55
56
  - **Site URL**: Your WordPress site URL (e.g., `https://yoursite.com`)
56
57
  - **Username**: Your WordPress username
57
58
  - **Application Password**: Generated WordPress app password
@@ -66,10 +67,12 @@ curl -L -o mcp-wordpress.dxt \
66
67
  ### Creating Application Password
67
68
 
68
69
  1. **Log into WordPress Admin**
70
+
69
71
  - Go to your WordPress admin panel
70
72
  - Navigate to **Users** → **Your Profile**
71
73
 
72
74
  2. **Generate Application Password**
75
+
73
76
  - Scroll down to **Application Passwords** section
74
77
  - In the "New Application Password Name" field, enter: `Claude Desktop MCP`
75
78
  - Click **Add New Application Password**
@@ -114,6 +117,7 @@ For advanced users, the DXT extension supports:
114
117
  ### Basic Functionality Test
115
118
 
116
119
  1. **Restart Claude Desktop**
120
+
117
121
  - Close and reopen Claude Desktop after configuration
118
122
  - This ensures the extension loads properly
119
123
 
@@ -228,6 +232,7 @@ curl -L -o mcp-wordpress.dxt \
228
232
  ```
229
233
 
230
234
  2. **Check Application Password**
235
+
231
236
  - Ensure password includes spaces: `AbCd EfGh IjKl MnOp`
232
237
  - Regenerate if unsure about format
233
238
  - Verify WordPress user has sufficient permissions
@@ -273,6 +278,7 @@ curl -L -o mcp-wordpress.dxt \
273
278
  **Solutions:**
274
279
 
275
280
  1. **Enable Caching**
281
+
276
282
  - DXT extension has built-in caching
277
283
  - Check cache statistics: `"Show WordPress cache stats"`
278
284
 
@@ -286,6 +292,7 @@ curl -L -o mcp-wordpress.dxt \
286
292
  Enable debug mode for detailed troubleshooting:
287
293
 
288
294
  1. **In DXT Configuration**
295
+
289
296
  - Set "Debug Mode" to `true`
290
297
  - Save configuration
291
298
 
@@ -308,6 +315,7 @@ The DXT extension includes automatic update capabilities:
308
315
  To manually update:
309
316
 
310
317
  1. **Download Latest Version**
318
+
311
319
  - Get newest `mcp-wordpress.dxt` from GitHub
312
320
  - Check release notes for changes
313
321
 
@@ -400,11 +408,13 @@ DXT combines with Claude's knowledge for enhanced assistance:
400
408
  ### Support Resources
401
409
 
402
410
  1. **Documentation**
411
+
403
412
  - [Complete Documentation](../README.md)
404
413
  - [Troubleshooting Guide](../TROUBLESHOOTING.md)
405
414
  - [API Reference](../api/README.md)
406
415
 
407
416
  2. **Community Support**
417
+
408
418
  - [GitHub Discussions](https://github.com/docdyhr/mcp-wordpress/discussions)
409
419
  - [Issue Tracker](https://github.com/docdyhr/mcp-wordpress/issues)
410
420
 
@@ -426,6 +436,5 @@ When reporting DXT-related issues, include:
426
436
  ---
427
437
 
428
438
  **Ready to get started?**
429
- [Download the DXT extension](https://github.com/docdyhr/mcp-wordpress/releases/latest/download/mcp-wordpress.dxt)
430
- and transform your
431
- WordPress management experience!
439
+ [Download the DXT extension](https://github.com/docdyhr/mcp-wordpress/releases/latest/download/mcp-wordpress.dxt) and
440
+ transform your WordPress management experience!
@@ -70,6 +70,7 @@ code --list-extensions | grep cline
70
70
  ### Basic Configuration
71
71
 
72
72
  1. **Open Cline Settings**
73
+
73
74
  - Open Command Palette (Ctrl+Shift+P)
74
75
  - Type "Cline: Open Settings"
75
76
  - Or navigate to File > Preferences > Settings > Extensions > Cline
@@ -58,18 +58,22 @@ After installation, Claude Desktop will prompt you to configure:
58
58
  The DTX GUI interface supports single-site configuration:
59
59
 
60
60
  1. **WordPress Site URL**
61
+
61
62
  - Enter your full WordPress site URL
62
63
  - Example: `https://yoursite.com`
63
64
 
64
65
  2. **WordPress Username**
66
+
65
67
  - Your WordPress admin username
66
68
  - Must have appropriate permissions
67
69
 
68
70
  3. **WordPress Application Password**
71
+
69
72
  - Generate in WordPress: Admin → Users → Profile → Application Passwords
70
73
  - Format: `xxxx xxxx xxxx xxxx xxxx xxxx`
71
74
 
72
75
  4. **Authentication Method** (Optional)
76
+
73
77
  - **Application Password** (Recommended)
74
78
  - JWT Authentication
75
79
  - Basic Authentication
@@ -113,6 +117,7 @@ The DTX package supports multi-site configuration, but requires manual setup:
113
117
  ```
114
118
 
115
119
  1. **Place the file in one of these locations:**
120
+
116
121
  - **macOS/Linux**: `~/mcp-wordpress.config.json`
117
122
  - **Windows**: `%USERPROFILE%\mcp-wordpress.config.json`
118
123
  - **DTX Install Directory**: Next to the DTX package files
@@ -256,17 +261,13 @@ The DTX includes 59 tools across:
256
261
 
257
262
  ### DTX Advantages
258
263
 
259
- ✅ **One-click installation** through Claude Desktop
260
- ✅ **Secure credential storage** in OS keychain
261
- ✅ **Built-in documentation** and prompts
262
- ✅ **No command line required**
263
- ✅ **Automatic dependency management**
264
+ ✅ **One-click installation** through Claude Desktop ✅ **Secure credential storage** in OS keychain ✅ **Built-in
265
+ documentation** and prompts ✅ **No command line required** **Automatic dependency management**
264
266
 
265
267
  ### DTX Limitations
266
268
 
267
- ❌ **Less flexibility** than manual configuration
268
- **Limited customization** options
269
- ❌ **Requires DTX-compatible Claude Desktop**
269
+ ❌ **Less flexibility** than manual configuration ❌ **Limited customization** options ❌ **Requires DTX-compatible
270
+ Claude Desktop**
270
271
 
271
272
  ### When to Use DTX
272
273
 
@@ -161,18 +161,14 @@ npx --ignore-existing mcp-wordpress
161
161
 
162
162
  ### NPX Advantages
163
163
 
164
- ✅ **No installation required** - Just configure and use
165
- ✅ **Always latest version** - Automatic updates
166
- **No maintenance** - No local files to manage
167
- ✅ **Quick setup** - Under 30 seconds
168
- ✅ **Cross-platform** - Works everywhere Node.js works
164
+ ✅ **No installation required** - Just configure and use ✅ **Always latest version** - Automatic updates ✅ **No
165
+ maintenance** - No local files to manage ✅ **Quick setup** - Under 30 seconds ✅ **Cross-platform** - Works everywhere
166
+ Node.js works
169
167
 
170
168
  ### NPX Limitations
171
169
 
172
- ❌ **Requires internet** - Downloads package on first run
173
- ❌ **Slower startup** - Initial download takes time
174
- ❌ **No customization** - Can't modify the code
175
- ❌ **No offline work** - Needs internet connection
170
+ ❌ **Requires internet** - Downloads package on first run ❌ **Slower startup** - Initial download takes time ❌ **No
171
+ customization** - Can't modify the code ❌ **No offline work** - Needs internet connection
176
172
 
177
173
  ### When to Use NPX
178
174
 
@@ -73,15 +73,18 @@ The configuration wizard will prompt for:
73
73
  ### Creating Application Password
74
74
 
75
75
  1. **Log into WordPress Admin**
76
+
76
77
  - Navigate to your WordPress admin dashboard
77
78
  - Go to **Users** → **Your Profile**
78
79
 
79
80
  2. **Generate Application Password**
81
+
80
82
  - Scroll to **Application Passwords** section
81
83
  - Application Name: `Smithery MCP WordPress`
82
84
  - Click **Add New Application Password**
83
85
 
84
86
  3. **Copy the Password**
87
+
85
88
  - WordPress displays: `AbCd EfGh IjKl MnOp QrSt UvWx`
86
89
  - **Important**: Copy exactly with spaces
87
90
  - Store securely - you won't see it again
@@ -349,11 +352,13 @@ smithery backup list
349
352
  ### Best Practices
350
353
 
351
354
  1. **Secure Credentials**
355
+
352
356
  - Use Application Passwords (not main password)
353
357
  - Regenerate passwords regularly
354
358
  - Use minimal WordPress user permissions
355
359
 
356
360
  2. **Network Security**
361
+
357
362
  - Use HTTPS for WordPress sites
358
363
  - Configure firewall rules if needed
359
364
  - Monitor access logs
@@ -3,6 +3,7 @@
3
3
  This document demonstrates how to resolve the v2.2.0 Docker publishing issue using the improved tooling.
4
4
 
5
5
  ## Current Situation
6
+
6
7
  - ✅ NPM: v2.2.0 published successfully
7
8
  - ❌ Docker Hub: v2.2.0 missing from registry
8
9
  - 🎯 Goal: Publish missing Docker image for v2.2.0
@@ -10,6 +11,7 @@ This document demonstrates how to resolve the v2.2.0 Docker publishing issue usi
10
11
  ## Resolution Options
11
12
 
12
13
  ### Option 1: Automated Retry Workflow (Recommended)
14
+
13
15
  ```bash
14
16
  # Trigger the new retry workflow
15
17
  gh workflow run docker-publish-retry.yml \
@@ -18,6 +20,7 @@ gh workflow run docker-publish-retry.yml \
18
20
  ```
19
21
 
20
22
  **What it does:**
23
+
21
24
  1. Checks if v2.2.0 tag exists in git ✅
22
25
  2. Verifies if Docker image already exists (it doesn't) ❌
23
26
  3. Builds Docker image with enhanced Dockerfile:
@@ -32,12 +35,14 @@ gh workflow run docker-publish-retry.yml \
32
35
  9. Verifies successful publication
33
36
 
34
37
  ### Option 2: Manual Script (For Immediate Resolution)
38
+
35
39
  ```bash
36
40
  # Run the manual publishing script
37
41
  ./scripts/manual-docker-publish.sh
38
42
  ```
39
43
 
40
44
  **Interactive process:**
45
+
41
46
  1. Script validates environment and git state
42
47
  2. Checks out v2.2.0 tag
43
48
  3. Builds Docker image locally with enhanced robustness
@@ -47,6 +52,7 @@ gh workflow run docker-publish-retry.yml \
47
52
  7. Provides verification links
48
53
 
49
54
  ### Option 3: GitHub Web Interface
55
+
50
56
  1. Go to: https://github.com/docdyhr/mcp-wordpress/actions/workflows/docker-publish-retry.yml
51
57
  2. Click "Run workflow"
52
58
  3. Enter version: `2.2.0`
@@ -56,6 +62,7 @@ gh workflow run docker-publish-retry.yml \
56
62
  ## Expected Results
57
63
 
58
64
  After successful execution:
65
+
59
66
  - ✅ Docker image available: `docdyhr/mcp-wordpress:2.2.0`
60
67
  - ✅ Docker image available: `docdyhr/mcp-wordpress:v2.2.0`
61
68
  - ✅ Verification link: https://hub.docker.com/r/docdyhr/mcp-wordpress/tags?name=2.2.0
@@ -63,6 +70,7 @@ After successful execution:
63
70
  ## Verification
64
71
 
65
72
  ### Verify Docker Image Exists
73
+
66
74
  ```bash
67
75
  # Pull the image to verify it exists
68
76
  docker pull docdyhr/mcp-wordpress:2.2.0
@@ -75,9 +83,11 @@ docker manifest inspect docdyhr/mcp-wordpress:2.2.0
75
83
  ```
76
84
 
77
85
  ### Verify on Docker Hub
86
+
78
87
  Visit: https://hub.docker.com/r/docdyhr/mcp-wordpress/tags?name=2.2.0
79
88
 
80
89
  Should show:
90
+
81
91
  - Tag: `2.2.0`
82
92
  - Tag: `v2.2.0`
83
93
  - Size information
@@ -89,17 +99,20 @@ Should show:
89
99
  The enhanced workflows now include:
90
100
 
91
101
  ### Automatic Protection
102
+
92
103
  1. **Enhanced Dockerfile**: Multiple Alpine mirrors with fallback
93
104
  2. **Retry Logic**: Release workflow automatically retries failed Docker builds
94
105
  3. **Extended Verification**: 3-minute propagation wait + multiple verification methods
95
106
  4. **Auto-Retry**: Verification failure automatically triggers retry workflow
96
107
 
97
108
  ### Manual Tools
109
+
98
110
  1. **Retry Workflow**: Available for any version via GitHub Actions
99
111
  2. **Manual Script**: Local building and publishing with safety checks
100
112
  3. **Force Rebuild**: Option to rebuild existing versions if needed
101
113
 
102
114
  ### Monitoring
115
+
103
116
  1. **GitHub Issues**: Automatic issue creation for publishing failures
104
117
  2. **Detailed Logs**: Enhanced debugging information in all workflows
105
118
  3. **Success Notifications**: Confirmation when publishing succeeds
@@ -112,8 +125,10 @@ To resolve the v2.2.0 issue immediately:
112
125
  2. **Most Control**: Run manual script locally if you have Docker Hub credentials
113
126
  3. **Automated**: Let the verification workflow detect and auto-retry
114
127
 
115
- All methods use the enhanced Dockerfile that addresses the root cause (Alpine repository connectivity issues) that caused the original v2.2.0 publishing failure.
128
+ All methods use the enhanced Dockerfile that addresses the root cause (Alpine repository connectivity issues) that
129
+ caused the original v2.2.0 publishing failure.
116
130
 
117
131
  ---
118
132
 
119
- *This solution ensures v2.2.0 is properly published while establishing robust processes to prevent similar issues in future releases.*
133
+ _This solution ensures v2.2.0 is properly published while establishing robust processes to prevent similar issues in
134
+ future releases._
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-wordpress",
3
- "version": "2.10.0",
3
+ "version": "2.10.2",
4
4
  "description": "Comprehensive Model Context Protocol server for WordPress management with composition-based architecture, 59 tools, SEO toolkit, performance monitoring, intelligent caching, and production-ready authentication",
5
5
  "keywords": [
6
6
  "mcp",
@@ -94,6 +94,7 @@
94
94
  "test:performance:ci": "npm run build && NODE_OPTIONS=\"--max-old-space-size=4096\" vitest run tests/performance/ --reporter=json --outputFile=performance-results.json",
95
95
  "test:safe": "node scripts/run-tests-safe.cjs",
96
96
  "test:security": "npm run build && vitest run tests/security/",
97
+ "test:security:validation": "npm run build && vitest run tests/security/penetration-tests.test.js",
97
98
  "test:tools": "node scripts/test-all-tools-fixed.js",
98
99
  "test:typescript": "npm run build && npm run typecheck",
99
100
  "test:ui": "npm run build && vitest --ui",
@@ -209,7 +209,7 @@ describe("CacheManager", () => {
209
209
  test("should store and retrieve ETags", () => {
210
210
  const key = "etag-test";
211
211
  const value = { data: "test" };
212
- const etag = "\"abc123\"";
212
+ const etag = '"abc123"';
213
213
 
214
214
  cacheManager.set(key, value, 1000, etag);
215
215
 
@@ -219,7 +219,7 @@ describe("CacheManager", () => {
219
219
 
220
220
  test("should support conditional request headers", () => {
221
221
  const key = "conditional-test";
222
- const etag = "\"abc123\"";
222
+ const etag = '"abc123"';
223
223
  const lastModified = "Wed, 21 Oct 2015 07:28:00 GMT";
224
224
 
225
225
  cacheManager.set(key, { data: "test" }, 1000, etag, lastModified);
@@ -290,12 +290,8 @@ describe("CacheManager", () => {
290
290
  describe("Cache Presets", () => {
291
291
  test("should have predefined cache presets", () => {
292
292
  expect(CachePresets.STATIC.ttl).toBeGreaterThan(CachePresets.DYNAMIC.ttl);
293
- expect(CachePresets.SEMI_STATIC.ttl).toBeGreaterThan(
294
- CachePresets.DYNAMIC.ttl,
295
- );
296
- expect(CachePresets.SESSION.ttl).toBeGreaterThan(
297
- CachePresets.DYNAMIC.ttl,
298
- );
293
+ expect(CachePresets.SEMI_STATIC.ttl).toBeGreaterThan(CachePresets.DYNAMIC.ttl);
294
+ expect(CachePresets.SESSION.ttl).toBeGreaterThan(CachePresets.DYNAMIC.ttl);
299
295
 
300
296
  expect(CachePresets.STATIC.cacheControl).toContain("public");
301
297
  expect(CachePresets.SESSION.cacheControl).toContain("private");
@@ -334,7 +334,11 @@ export class MockWordPressClient extends WordPressClient {
334
334
  /**
335
335
  * Mock search
336
336
  */
337
- async search(query: string, types?: string[], subtype?: string): Promise<import("../types/wordpress.js").WordPressSearchResult[]> {
337
+ async search(
338
+ query: string,
339
+ types?: string[],
340
+ subtype?: string,
341
+ ): Promise<import("../types/wordpress.js").WordPressSearchResult[]> {
338
342
  if (!query) {
339
343
  return [];
340
344
  }
@@ -186,7 +186,7 @@ export class SEOWordPressClient extends WordPressClient {
186
186
  try {
187
187
  // Get list of installed plugins
188
188
  const plugins = await this.get("/wp/v2/plugins");
189
-
189
+
190
190
  if (!Array.isArray(plugins)) {
191
191
  this.logger.debug("Could not retrieve plugins list");
192
192
  return;
@@ -194,19 +194,19 @@ export class SEOWordPressClient extends WordPressClient {
194
194
 
195
195
  // Check for active SEO plugins in order of preference
196
196
  const activePlugins = (plugins as WordPressPlugin[]).filter((plugin) => plugin.status === "active");
197
-
197
+
198
198
  // Check for Yoast SEO
199
199
  if (activePlugins.some((plugin) => plugin.slug === "wordpress-seo")) {
200
200
  this.detectedPlugin = "yoast";
201
201
  return;
202
202
  }
203
-
203
+
204
204
  // Check for RankMath
205
205
  if (activePlugins.some((plugin) => plugin.slug === "seo-by-rank-math")) {
206
206
  this.detectedPlugin = "rankmath";
207
207
  return;
208
208
  }
209
-
209
+
210
210
  // Check for SEOPress
211
211
  if (activePlugins.some((plugin) => plugin.slug === "wp-seopress")) {
212
212
  this.detectedPlugin = "seopress";
@@ -246,7 +246,7 @@ export class SEOWordPressClient extends WordPressClient {
246
246
 
247
247
  // Get raw plugin data for debugging
248
248
  const raw = this.getRawPluginData(content);
249
-
249
+
250
250
  // For malformed plugin data (detected plugin but no actual data), return null for title/description
251
251
  const pluginDetected = this.detectedPlugin !== "none";
252
252
  const pluginDataMalformed = pluginDetected && !this.hasPluginData(content);
@@ -259,10 +259,12 @@ export class SEOWordPressClient extends WordPressClient {
259
259
  canonical: metadata.canonical || null,
260
260
  focusKeyword: metadata.focusKeyword || null,
261
261
  openGraph: metadata.openGraph || { title: null, description: null },
262
- twitter: metadata.twitterCard ? {
263
- title: metadata.twitterCard.title || null,
264
- description: metadata.twitterCard.description || null
265
- } : { title: null, description: null },
262
+ twitter: metadata.twitterCard
263
+ ? {
264
+ title: metadata.twitterCard.title || null,
265
+ description: metadata.twitterCard.description || null,
266
+ }
267
+ : { title: null, description: null },
266
268
  schema,
267
269
  raw,
268
270
  lastModified: content.modified || content.date || new Date().toISOString(),
@@ -533,17 +535,17 @@ export class SEOWordPressClient extends WordPressClient {
533
535
  // Extract OpenGraph and Twitter data based on plugin
534
536
  if (this.detectedPlugin === "yoast" && meta.yoast_head_json) {
535
537
  const yoastData = meta.yoast_head_json as Record<string, unknown>;
536
-
538
+
537
539
  metadata.openGraph = {
538
540
  title: (yoastData.og_title as string) || metadata.title,
539
541
  description: (yoastData.og_description as string) || metadata.description,
540
542
  type: content.type === "page" ? "website" : "article",
541
543
  url: content.link,
542
544
  };
543
-
545
+
544
546
  const twitterTitle = yoastData.twitter_title as string;
545
547
  const twitterDescription = yoastData.twitter_description as string;
546
-
548
+
547
549
  metadata.twitterCard = {
548
550
  card: "summary",
549
551
  ...(twitterTitle && { title: twitterTitle }),
@@ -646,19 +648,19 @@ export class SEOWordPressClient extends WordPressClient {
646
648
  if (!fieldName) {
647
649
  return null;
648
650
  }
649
-
651
+
650
652
  // For Yoast, check yoast_head_json first
651
653
  if (this.detectedPlugin === "yoast" && meta.yoast_head_json) {
652
654
  const yoastData = meta.yoast_head_json as Record<string, unknown>;
653
-
655
+
654
656
  // Map field names to yoast_head_json properties
655
657
  const yoastFieldMap: Record<string, string> = {
656
- '_yoast_wpseo_title': 'title',
657
- '_yoast_wpseo_metadesc': 'description',
658
- '_yoast_wpseo_canonical': 'canonical',
659
- '_yoast_wpseo_focuskw': 'focuskw'
658
+ _yoast_wpseo_title: "title",
659
+ _yoast_wpseo_metadesc: "description",
660
+ _yoast_wpseo_canonical: "canonical",
661
+ _yoast_wpseo_focuskw: "focuskw",
660
662
  };
661
-
663
+
662
664
  const yoastField = yoastFieldMap[fieldName];
663
665
  if (yoastField && yoastData[yoastField]) {
664
666
  return yoastData[yoastField] as string;
@@ -805,7 +807,7 @@ export class SEOWordPressClient extends WordPressClient {
805
807
  };
806
808
  } {
807
809
  const hasPlugin = this.detectedPlugin !== "none";
808
-
810
+
809
811
  return {
810
812
  hasPlugin,
811
813
  plugin: this.detectedPlugin,
@@ -830,8 +832,10 @@ export class SEOWordPressClient extends WordPressClient {
830
832
  switch (this.detectedPlugin) {
831
833
  case "yoast":
832
834
  // Check for yoast_head_json or individual meta fields
833
- return (meta.yoast_head_json !== null && meta.yoast_head_json !== undefined) ||
834
- (meta._yoast_wpseo_title !== null && meta._yoast_wpseo_title !== undefined);
835
+ return (
836
+ (meta.yoast_head_json !== null && meta.yoast_head_json !== undefined) ||
837
+ (meta._yoast_wpseo_title !== null && meta._yoast_wpseo_title !== undefined)
838
+ );
835
839
  case "rankmath":
836
840
  return meta.rank_math_title !== null && meta.rank_math_title !== undefined;
837
841
  case "seopress":
@@ -854,8 +858,8 @@ export class SEOWordPressClient extends WordPressClient {
854
858
  case "rankmath":
855
859
  // Extract RankMath specific fields
856
860
  const rankMathData: Record<string, unknown> = {};
857
- Object.keys(meta).forEach(key => {
858
- if (key.startsWith('rank_math_')) {
861
+ Object.keys(meta).forEach((key) => {
862
+ if (key.startsWith("rank_math_")) {
859
863
  rankMathData[key] = meta[key];
860
864
  }
861
865
  });
@@ -863,8 +867,8 @@ export class SEOWordPressClient extends WordPressClient {
863
867
  case "seopress":
864
868
  // Extract SEOPress specific fields
865
869
  const seopressData: Record<string, unknown> = {};
866
- Object.keys(meta).forEach(key => {
867
- if (key.startsWith('_seopress_')) {
870
+ Object.keys(meta).forEach((key) => {
871
+ if (key.startsWith("_seopress_")) {
868
872
  seopressData[key] = meta[key];
869
873
  }
870
874
  });
@@ -4,13 +4,13 @@
4
4
  */
5
5
 
6
6
  // Main Client Classes
7
- export { WordPressClient } from './api.js';
8
- export { CachedWordPressClient } from './CachedWordPressClient.js';
9
- export { SEOWordPressClient } from './SEOWordPressClient.js';
10
- export { MockWordPressClient } from './MockWordPressClient.js';
7
+ export { WordPressClient } from "./api.js";
8
+ export { CachedWordPressClient } from "./CachedWordPressClient.js";
9
+ export { SEOWordPressClient } from "./SEOWordPressClient.js";
10
+ export { MockWordPressClient } from "./MockWordPressClient.js";
11
11
 
12
12
  // Authentication utilities
13
- export * from './auth.js';
13
+ export * from "./auth.js";
14
14
 
15
15
  // Manager exports (already has its own index)
16
- export * from './managers/index.js';
16
+ export * from "./managers/index.js";
@@ -22,7 +22,7 @@ export class AuthManager {
22
22
 
23
23
  constructor(
24
24
  private client: WordPressClient,
25
- private authConfig: AuthConfig
25
+ private authConfig: AuthConfig,
26
26
  ) {}
27
27
 
28
28
  /**
@@ -44,12 +44,15 @@ export class AuthManager {
44
44
  case "api-key":
45
45
  return this.authenticateWithAPIKey();
46
46
  default:
47
- throw new AuthenticationError(`Unsupported authentication method: ${this.authConfig.method}`, this.authConfig.method);
47
+ throw new AuthenticationError(
48
+ `Unsupported authentication method: ${this.authConfig.method}`,
49
+ this.authConfig.method,
50
+ );
48
51
  }
49
52
  } catch (error) {
50
- this.logger.error("Authentication failed", {
53
+ this.logger.error("Authentication failed", {
51
54
  method: this.authConfig.method,
52
- error: error instanceof Error ? error.message : String(error)
55
+ error: error instanceof Error ? error.message : String(error),
53
56
  });
54
57
  throw error;
55
58
  }
@@ -65,7 +68,9 @@ export class AuthManager {
65
68
  case "app-password":
66
69
  case "basic":
67
70
  if (this.authConfig.username && this.authConfig.appPassword) {
68
- const credentials = Buffer.from(`${this.authConfig.username}:${this.authConfig.appPassword}`).toString("base64");
71
+ const credentials = Buffer.from(`${this.authConfig.username}:${this.authConfig.appPassword}`).toString(
72
+ "base64",
73
+ );
69
74
  headers.Authorization = `Basic ${credentials}`;
70
75
  }
71
76
  break;
@@ -96,7 +101,10 @@ export class AuthManager {
96
101
  */
97
102
  private async authenticateWithJWT(): Promise<boolean> {
98
103
  if (!this.authConfig.username || !this.authConfig.password) {
99
- throw new AuthenticationError("Username and password are required for JWT authentication", this.authConfig.method);
104
+ throw new AuthenticationError(
105
+ "Username and password are required for JWT authentication",
106
+ this.authConfig.method,
107
+ );
100
108
  }
101
109
 
102
110
  try {
@@ -115,7 +123,7 @@ export class AuthManager {
115
123
  }
116
124
 
117
125
  // Calculate expiration time (typically 24 hours for JWT)
118
- const expiresAt = Date.now() + (24 * 60 * 60 * 1000); // 24 hours
126
+ const expiresAt = Date.now() + 24 * 60 * 60 * 1000; // 24 hours
119
127
 
120
128
  this.jwtToken = {
121
129
  token: response.token,
@@ -172,4 +180,4 @@ export class AuthManager {
172
180
  getAuthMethod(): AuthMethod {
173
181
  return this.authConfig.method;
174
182
  }
175
- }
183
+ }
@@ -48,9 +48,9 @@ export class AuthenticationManager extends BaseManager {
48
48
  } catch {
49
49
  throw new AuthenticationError("Invalid site URL", AUTH_METHODS.APP_PASSWORD);
50
50
  }
51
-
51
+
52
52
  // Normalize URL by removing trailing slash
53
- const normalizedSiteUrl = config.siteUrl.replace(/\/$/, '');
53
+ const normalizedSiteUrl = config.siteUrl.replace(/\/$/, "");
54
54
  config.siteUrl = normalizedSiteUrl;
55
55
 
56
56
  // Validate auth method using centralized constants