mcp-wordpress 1.2.2 → 1.3.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 (251) hide show
  1. package/README.md +210 -182
  2. package/dist/cache/CacheInvalidation.d.ts +3 -3
  3. package/dist/cache/CacheInvalidation.d.ts.map +1 -1
  4. package/dist/cache/CacheInvalidation.js +119 -119
  5. package/dist/cache/CacheInvalidation.js.map +1 -1
  6. package/dist/cache/CacheManager.d.ts +5 -0
  7. package/dist/cache/CacheManager.d.ts.map +1 -1
  8. package/dist/cache/CacheManager.js +26 -16
  9. package/dist/cache/CacheManager.js.map +1 -1
  10. package/dist/cache/HttpCacheWrapper.d.ts +1 -1
  11. package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
  12. package/dist/cache/HttpCacheWrapper.js +29 -29
  13. package/dist/cache/HttpCacheWrapper.js.map +1 -1
  14. package/dist/cache/__tests__/CacheInvalidation.test.js +96 -94
  15. package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -1
  16. package/dist/cache/__tests__/CacheManager.test.js +113 -113
  17. package/dist/cache/__tests__/CacheManager.test.js.map +1 -1
  18. package/dist/cache/__tests__/CachedWordPressClient.test.js +102 -99
  19. package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -1
  20. package/dist/cache/__tests__/HttpCacheWrapper.test.js +98 -95
  21. package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
  22. package/dist/cache/index.d.ts +7 -7
  23. package/dist/cache/index.d.ts.map +1 -1
  24. package/dist/cache/index.js +4 -4
  25. package/dist/cache/index.js.map +1 -1
  26. package/dist/client/CachedWordPressClient.d.ts +4 -4
  27. package/dist/client/CachedWordPressClient.d.ts.map +1 -1
  28. package/dist/client/CachedWordPressClient.js +55 -51
  29. package/dist/client/CachedWordPressClient.js.map +1 -1
  30. package/dist/client/api.d.ts +10 -10
  31. package/dist/client/api.js +158 -158
  32. package/dist/client/api.js.map +1 -1
  33. package/dist/client/auth.d.ts +2 -2
  34. package/dist/client/auth.js +72 -72
  35. package/dist/client/managers/AuthenticationManager.d.ts +2 -2
  36. package/dist/client/managers/AuthenticationManager.js +46 -46
  37. package/dist/client/managers/BaseManager.d.ts +1 -1
  38. package/dist/client/managers/BaseManager.js +9 -9
  39. package/dist/client/managers/RequestManager.d.ts +5 -3
  40. package/dist/client/managers/RequestManager.d.ts.map +1 -1
  41. package/dist/client/managers/RequestManager.js +39 -19
  42. package/dist/client/managers/RequestManager.js.map +1 -1
  43. package/dist/client/managers/index.d.ts +3 -3
  44. package/dist/client/managers/index.js +3 -3
  45. package/dist/config/ConfigurationSchema.d.ts +2 -2
  46. package/dist/config/ConfigurationSchema.d.ts.map +1 -1
  47. package/dist/config/ConfigurationSchema.js +40 -40
  48. package/dist/config/ConfigurationSchema.js.map +1 -1
  49. package/dist/config/ServerConfiguration.d.ts +2 -2
  50. package/dist/config/ServerConfiguration.js +35 -35
  51. package/dist/config/ServerConfiguration.js.map +1 -1
  52. package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
  53. package/dist/docs/DocumentationGenerator.js +296 -255
  54. package/dist/docs/DocumentationGenerator.js.map +1 -1
  55. package/dist/docs/MarkdownFormatter.d.ts +1 -1
  56. package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
  57. package/dist/docs/MarkdownFormatter.js +60 -51
  58. package/dist/docs/MarkdownFormatter.js.map +1 -1
  59. package/dist/docs/index.d.ts +3 -3
  60. package/dist/docs/index.d.ts.map +1 -1
  61. package/dist/docs/index.js +2 -2
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +16 -16
  64. package/dist/index.js.map +1 -1
  65. package/dist/mcp-wordpress-1.3.0.tgz +0 -0
  66. package/dist/performance/MetricsCollector.d.ts +3 -3
  67. package/dist/performance/MetricsCollector.d.ts.map +1 -1
  68. package/dist/performance/MetricsCollector.js +33 -27
  69. package/dist/performance/MetricsCollector.js.map +1 -1
  70. package/dist/performance/PerformanceAnalytics.d.ts +12 -12
  71. package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
  72. package/dist/performance/PerformanceAnalytics.js +200 -154
  73. package/dist/performance/PerformanceAnalytics.js.map +1 -1
  74. package/dist/performance/PerformanceMonitor.d.ts +5 -5
  75. package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
  76. package/dist/performance/PerformanceMonitor.js +53 -52
  77. package/dist/performance/PerformanceMonitor.js.map +1 -1
  78. package/dist/performance/index.d.ts +6 -6
  79. package/dist/performance/index.d.ts.map +1 -1
  80. package/dist/performance/index.js +3 -3
  81. package/dist/security/InputValidator.d.ts +1 -1
  82. package/dist/security/InputValidator.d.ts.map +1 -1
  83. package/dist/security/InputValidator.js +111 -88
  84. package/dist/security/InputValidator.js.map +1 -1
  85. package/dist/security/SecurityConfig.d.ts +5 -5
  86. package/dist/security/SecurityConfig.js +92 -92
  87. package/dist/security/SecurityConfig.js.map +1 -1
  88. package/dist/server/ConnectionTester.d.ts +1 -1
  89. package/dist/server/ConnectionTester.d.ts.map +1 -1
  90. package/dist/server/ConnectionTester.js +4 -4
  91. package/dist/server/ConnectionTester.js.map +1 -1
  92. package/dist/server/ToolRegistry.d.ts +2 -2
  93. package/dist/server/ToolRegistry.d.ts.map +1 -1
  94. package/dist/server/ToolRegistry.js +35 -32
  95. package/dist/server/ToolRegistry.js.map +1 -1
  96. package/dist/server.d.ts +2 -2
  97. package/dist/server.js +2 -2
  98. package/dist/tools/BaseToolManager.js +5 -5
  99. package/dist/tools/auth.d.ts +2 -2
  100. package/dist/tools/auth.d.ts.map +1 -1
  101. package/dist/tools/auth.js +32 -31
  102. package/dist/tools/auth.js.map +1 -1
  103. package/dist/tools/cache.d.ts +1 -1
  104. package/dist/tools/cache.d.ts.map +1 -1
  105. package/dist/tools/cache.js +71 -71
  106. package/dist/tools/cache.js.map +1 -1
  107. package/dist/tools/comments.d.ts +2 -2
  108. package/dist/tools/comments.d.ts.map +1 -1
  109. package/dist/tools/comments.js +79 -79
  110. package/dist/tools/comments.js.map +1 -1
  111. package/dist/tools/index.d.ts +10 -10
  112. package/dist/tools/index.js +10 -10
  113. package/dist/tools/media.d.ts +2 -2
  114. package/dist/tools/media.js +80 -80
  115. package/dist/tools/pages.d.ts +2 -2
  116. package/dist/tools/pages.d.ts.map +1 -1
  117. package/dist/tools/pages.js +75 -75
  118. package/dist/tools/pages.js.map +1 -1
  119. package/dist/tools/performance.d.ts +1 -1
  120. package/dist/tools/performance.d.ts.map +1 -1
  121. package/dist/tools/performance.js +311 -287
  122. package/dist/tools/performance.js.map +1 -1
  123. package/dist/tools/posts.d.ts +2 -2
  124. package/dist/tools/posts.d.ts.map +1 -1
  125. package/dist/tools/posts.js +94 -94
  126. package/dist/tools/posts.js.map +1 -1
  127. package/dist/tools/site.d.ts +2 -2
  128. package/dist/tools/site.d.ts.map +1 -1
  129. package/dist/tools/site.js +60 -60
  130. package/dist/tools/site.js.map +1 -1
  131. package/dist/tools/taxonomies.d.ts +2 -2
  132. package/dist/tools/taxonomies.js +89 -89
  133. package/dist/tools/users.d.ts +2 -2
  134. package/dist/tools/users.js +68 -68
  135. package/dist/tools/users.js.map +1 -1
  136. package/dist/types/client.d.ts +13 -13
  137. package/dist/types/client.d.ts.map +1 -1
  138. package/dist/types/client.js +12 -12
  139. package/dist/types/client.js.map +1 -1
  140. package/dist/types/index.d.ts +19 -19
  141. package/dist/types/index.d.ts.map +1 -1
  142. package/dist/types/index.js +3 -3
  143. package/dist/types/mcp.d.ts +7 -7
  144. package/dist/types/wordpress.d.ts +21 -21
  145. package/dist/types/wordpress.d.ts.map +1 -1
  146. package/dist/utils/debug.d.ts +2 -2
  147. package/dist/utils/debug.js +28 -28
  148. package/dist/utils/error.d.ts.map +1 -1
  149. package/dist/utils/error.js +13 -13
  150. package/dist/utils/error.js.map +1 -1
  151. package/dist/utils/toolWrapper.d.ts.map +1 -1
  152. package/dist/utils/toolWrapper.js +5 -5
  153. package/dist/utils/toolWrapper.js.map +1 -1
  154. package/dist/utils/validation.d.ts.map +1 -1
  155. package/dist/utils/validation.js +41 -31
  156. package/dist/utils/validation.js.map +1 -1
  157. package/docs/CACHING.md +36 -2
  158. package/docs/DOCKER.md +24 -18
  159. package/docs/PERFORMANCE_MONITORING.md +49 -1
  160. package/docs/SECURITY_TESTING.md +30 -1
  161. package/docs/api/README.md +9 -1
  162. package/docs/api/summary.json +1 -1
  163. package/docs/contract-testing.md +24 -3
  164. package/docs/developer/GITHUB_ACTIONS_SETUP.md +8 -2
  165. package/docs/developer/MAINTENANCE.md +29 -3
  166. package/docs/developer/MIGRATION_GUIDE.md +13 -1
  167. package/docs/developer/NPM_AUTH_SETUP.md +13 -2
  168. package/docs/developer/REFACTORING.md +31 -1
  169. package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +18 -7
  170. package/docs/releases/RELEASE_NOTES_v1.1.2.md +31 -5
  171. package/docs/user-guides/DOCKER_SETUP.md +264 -0
  172. package/docs/user-guides/DTX_SETUP.md +327 -0
  173. package/docs/user-guides/NPM_SETUP.md +109 -0
  174. package/docs/user-guides/NPX_SETUP.md +281 -0
  175. package/docs/wordpress-rest-api-authentication-troubleshooting.md +13 -2
  176. package/package.json +27 -8
  177. package/src/cache/CacheInvalidation.ts +140 -132
  178. package/src/cache/CacheManager.ts +40 -29
  179. package/src/cache/HttpCacheWrapper.ts +105 -68
  180. package/src/cache/__tests__/CacheInvalidation.test.ts +123 -118
  181. package/src/cache/__tests__/CacheManager.test.ts +156 -152
  182. package/src/cache/__tests__/CachedWordPressClient.test.ts +131 -116
  183. package/src/cache/__tests__/HttpCacheWrapper.test.ts +118 -115
  184. package/src/cache/index.ts +13 -13
  185. package/src/client/CachedWordPressClient.ts +90 -80
  186. package/src/client/api.ts +205 -205
  187. package/src/client/auth.ts +80 -80
  188. package/src/client/managers/AuthenticationManager.ts +61 -61
  189. package/src/client/managers/BaseManager.ts +11 -11
  190. package/src/client/managers/RequestManager.ts +79 -47
  191. package/src/client/managers/index.ts +3 -3
  192. package/src/config/ConfigurationSchema.ts +44 -44
  193. package/src/config/ServerConfiguration.ts +39 -39
  194. package/src/docs/DocumentationGenerator.ts +402 -295
  195. package/src/docs/MarkdownFormatter.ts +94 -69
  196. package/src/docs/index.ts +4 -4
  197. package/src/index.ts +24 -21
  198. package/src/performance/MetricsCollector.ts +90 -58
  199. package/src/performance/PerformanceAnalytics.ts +386 -262
  200. package/src/performance/PerformanceMonitor.ts +152 -118
  201. package/src/performance/index.ts +9 -9
  202. package/src/security/InputValidator.ts +148 -91
  203. package/src/security/SecurityConfig.ts +94 -94
  204. package/src/server/ConnectionTester.ts +21 -15
  205. package/src/server/ToolRegistry.ts +64 -51
  206. package/src/server.ts +2 -2
  207. package/src/tools/BaseToolManager.ts +6 -6
  208. package/src/tools/auth.ts +42 -37
  209. package/src/tools/cache.ts +85 -81
  210. package/src/tools/comments.ts +93 -91
  211. package/src/tools/index.ts +10 -10
  212. package/src/tools/media.ts +89 -89
  213. package/src/tools/pages.ts +89 -87
  214. package/src/tools/performance.ts +443 -352
  215. package/src/tools/posts.ts +109 -107
  216. package/src/tools/site.ts +86 -77
  217. package/src/tools/taxonomies.ts +102 -102
  218. package/src/tools/users.ts +77 -77
  219. package/src/types/client.ts +157 -60
  220. package/src/types/index.ts +49 -27
  221. package/src/types/mcp.ts +15 -15
  222. package/src/types/wordpress.ts +57 -29
  223. package/src/utils/debug.ts +37 -37
  224. package/src/utils/error.ts +47 -25
  225. package/src/utils/toolWrapper.ts +12 -8
  226. package/src/utils/validation.ts +116 -65
  227. package/dist/client/WordPressClient.d.ts +0 -81
  228. package/dist/client/WordPressClient.d.ts.map +0 -1
  229. package/dist/client/WordPressClient.js +0 -354
  230. package/dist/client/WordPressClient.js.map +0 -1
  231. package/dist/performance/AnomalyDetector.d.ts +0 -63
  232. package/dist/performance/AnomalyDetector.d.ts.map +0 -1
  233. package/dist/performance/AnomalyDetector.js +0 -222
  234. package/dist/performance/AnomalyDetector.js.map +0 -1
  235. package/dist/performance/BenchmarkAnalyzer.d.ts +0 -67
  236. package/dist/performance/BenchmarkAnalyzer.d.ts.map +0 -1
  237. package/dist/performance/BenchmarkAnalyzer.js +0 -301
  238. package/dist/performance/BenchmarkAnalyzer.js.map +0 -1
  239. package/dist/performance/TrendAnalyzer.d.ts +0 -69
  240. package/dist/performance/TrendAnalyzer.d.ts.map +0 -1
  241. package/dist/performance/TrendAnalyzer.js +0 -203
  242. package/dist/performance/TrendAnalyzer.js.map +0 -1
  243. package/dist/tools/BaseToolClass.d.ts +0 -76
  244. package/dist/tools/BaseToolClass.d.ts.map +0 -1
  245. package/dist/tools/BaseToolClass.js +0 -104
  246. package/dist/tools/BaseToolClass.js.map +0 -1
  247. package/dist/tools/base.d.ts +0 -37
  248. package/dist/tools/base.d.ts.map +0 -1
  249. package/dist/tools/base.js +0 -60
  250. package/dist/tools/base.js.map +0 -1
  251. package/docs/user-guides/CLAUDE_DESKTOP_SETUP.md +0 -187
@@ -2,12 +2,12 @@
2
2
  * WordPress API Client
3
3
  * Handles all REST API communication with WordPress
4
4
  */
5
- import fetch from 'node-fetch';
6
- import FormData from 'form-data';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import { WordPressAPIError, AuthenticationError, RateLimitError } from '../types/client.js';
10
- import { debug, logError, startTimer } from '../utils/debug.js';
5
+ import fetch from "node-fetch";
6
+ import FormData from "form-data";
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import { WordPressAPIError, AuthenticationError, RateLimitError, } from "../types/client.js";
10
+ import { debug, logError, startTimer } from "../utils/debug.js";
11
11
  export class WordPressClient {
12
12
  baseUrl;
13
13
  apiUrl;
@@ -21,16 +21,16 @@ export class WordPressClient {
21
21
  jwtToken = null;
22
22
  _stats;
23
23
  constructor(options = {}) {
24
- this.baseUrl = options.baseUrl || process.env.WORDPRESS_SITE_URL || '';
25
- this.apiUrl = '';
24
+ this.baseUrl = options.baseUrl || process.env.WORDPRESS_SITE_URL || "";
25
+ this.apiUrl = "";
26
26
  this.timeout =
27
- options.timeout || parseInt(process.env.WORDPRESS_TIMEOUT || '30000');
27
+ options.timeout || parseInt(process.env.WORDPRESS_TIMEOUT || "30000");
28
28
  this.maxRetries =
29
- options.maxRetries || parseInt(process.env.WORDPRESS_MAX_RETRIES || '3');
29
+ options.maxRetries || parseInt(process.env.WORDPRESS_MAX_RETRIES || "3");
30
30
  // Authentication configuration
31
31
  this.auth = options.auth || this.getAuthFromEnv();
32
32
  // Rate limiting
33
- this.requestInterval = 60000 / parseInt(process.env.RATE_LIMIT || '60');
33
+ this.requestInterval = 60000 / parseInt(process.env.RATE_LIMIT || "60");
34
34
  // Initialize stats
35
35
  this._stats = {
36
36
  totalRequests: 0,
@@ -38,7 +38,7 @@ export class WordPressClient {
38
38
  failedRequests: 0,
39
39
  averageResponseTime: 0,
40
40
  rateLimitHits: 0,
41
- authFailures: 0
41
+ authFailures: 0,
42
42
  };
43
43
  // Validate configuration
44
44
  this.validateConfig();
@@ -48,7 +48,7 @@ export class WordPressClient {
48
48
  baseUrl: this.baseUrl,
49
49
  auth: this.auth,
50
50
  timeout: this.timeout,
51
- maxRetries: this.maxRetries
51
+ maxRetries: this.maxRetries,
52
52
  };
53
53
  }
54
54
  get isAuthenticated() {
@@ -60,21 +60,21 @@ export class WordPressClient {
60
60
  getAuthFromEnv() {
61
61
  const authMethod = process.env.WORDPRESS_AUTH_METHOD;
62
62
  // Use explicit auth method if set
63
- if (authMethod === 'app-password' &&
63
+ if (authMethod === "app-password" &&
64
64
  process.env.WORDPRESS_USERNAME &&
65
65
  process.env.WORDPRESS_APP_PASSWORD) {
66
66
  return {
67
- method: 'app-password',
67
+ method: "app-password",
68
68
  username: process.env.WORDPRESS_USERNAME,
69
- appPassword: process.env.WORDPRESS_APP_PASSWORD
69
+ appPassword: process.env.WORDPRESS_APP_PASSWORD,
70
70
  };
71
71
  }
72
72
  // Try Application Password first (fallback)
73
73
  if (process.env.WORDPRESS_USERNAME && process.env.WORDPRESS_APP_PASSWORD) {
74
74
  return {
75
- method: 'app-password',
75
+ method: "app-password",
76
76
  username: process.env.WORDPRESS_USERNAME,
77
- appPassword: process.env.WORDPRESS_APP_PASSWORD
77
+ appPassword: process.env.WORDPRESS_APP_PASSWORD,
78
78
  };
79
79
  }
80
80
  // Try JWT
@@ -82,41 +82,41 @@ export class WordPressClient {
82
82
  process.env.WORDPRESS_USERNAME &&
83
83
  process.env.WORDPRESS_PASSWORD) {
84
84
  return {
85
- method: 'jwt',
85
+ method: "jwt",
86
86
  secret: process.env.WORDPRESS_JWT_SECRET,
87
87
  username: process.env.WORDPRESS_USERNAME,
88
- password: process.env.WORDPRESS_PASSWORD
88
+ password: process.env.WORDPRESS_PASSWORD,
89
89
  };
90
90
  }
91
91
  // Try API Key
92
92
  if (process.env.WORDPRESS_API_KEY) {
93
93
  return {
94
- method: 'api-key',
95
- apiKey: process.env.WORDPRESS_API_KEY
94
+ method: "api-key",
95
+ apiKey: process.env.WORDPRESS_API_KEY,
96
96
  };
97
97
  }
98
98
  // Try Cookie
99
99
  if (process.env.WORDPRESS_COOKIE_NONCE) {
100
100
  return {
101
- method: 'cookie',
102
- nonce: process.env.WORDPRESS_COOKIE_NONCE
101
+ method: "cookie",
102
+ nonce: process.env.WORDPRESS_COOKIE_NONCE,
103
103
  };
104
104
  }
105
105
  // Default to basic authentication
106
106
  return {
107
- method: 'basic',
108
- username: process.env.WORDPRESS_USERNAME || '',
107
+ method: "basic",
108
+ username: process.env.WORDPRESS_USERNAME || "",
109
109
  password: process.env.WORDPRESS_PASSWORD ||
110
110
  process.env.WORDPRESS_APP_PASSWORD ||
111
- ''
111
+ "",
112
112
  };
113
113
  }
114
114
  validateConfig() {
115
115
  if (!this.baseUrl) {
116
- throw new Error('WordPress configuration is incomplete: baseUrl is required');
116
+ throw new Error("WordPress configuration is incomplete: baseUrl is required");
117
117
  }
118
118
  // Ensure URL doesn't end with slash and add API path
119
- this.baseUrl = this.baseUrl.replace(/\/$/, '');
119
+ this.baseUrl = this.baseUrl.replace(/\/$/, "");
120
120
  this.apiUrl = `${this.baseUrl}/wp-json/wp/v2`;
121
121
  debug.log(`WordPress API Client initialized for: ${this.apiUrl}`);
122
122
  }
@@ -126,7 +126,7 @@ export class WordPressClient {
126
126
  async disconnect() {
127
127
  this.authenticated = false;
128
128
  this.jwtToken = null;
129
- debug.log('WordPress client disconnected');
129
+ debug.log("WordPress client disconnected");
130
130
  }
131
131
  /**
132
132
  * Add authentication headers to request
@@ -134,31 +134,31 @@ export class WordPressClient {
134
134
  addAuthHeaders(headers) {
135
135
  const method = this.auth.method?.toLowerCase();
136
136
  switch (method) {
137
- case 'app-password':
137
+ case "app-password":
138
138
  if (this.auth.username && this.auth.appPassword) {
139
- const credentials = Buffer.from(`${this.auth.username}:${this.auth.appPassword}`).toString('base64');
140
- headers['Authorization'] = `Basic ${credentials}`;
139
+ const credentials = Buffer.from(`${this.auth.username}:${this.auth.appPassword}`).toString("base64");
140
+ headers["Authorization"] = `Basic ${credentials}`;
141
141
  }
142
142
  break;
143
- case 'basic':
143
+ case "basic":
144
144
  if (this.auth.username && this.auth.password) {
145
- const credentials = Buffer.from(`${this.auth.username}:${this.auth.password}`).toString('base64');
146
- headers['Authorization'] = `Basic ${credentials}`;
145
+ const credentials = Buffer.from(`${this.auth.username}:${this.auth.password}`).toString("base64");
146
+ headers["Authorization"] = `Basic ${credentials}`;
147
147
  }
148
148
  break;
149
- case 'jwt':
149
+ case "jwt":
150
150
  if (this.jwtToken) {
151
- headers['Authorization'] = `Bearer ${this.jwtToken}`;
151
+ headers["Authorization"] = `Bearer ${this.jwtToken}`;
152
152
  }
153
153
  break;
154
- case 'api-key':
154
+ case "api-key":
155
155
  if (this.auth.apiKey) {
156
- headers['X-API-Key'] = this.auth.apiKey;
156
+ headers["X-API-Key"] = this.auth.apiKey;
157
157
  }
158
158
  break;
159
- case 'cookie':
159
+ case "cookie":
160
160
  if (this.auth.nonce) {
161
- headers['X-WP-Nonce'] = this.auth.nonce;
161
+ headers["X-WP-Nonce"] = this.auth.nonce;
162
162
  }
163
163
  break;
164
164
  }
@@ -185,14 +185,14 @@ export class WordPressClient {
185
185
  const method = this.auth.method?.toLowerCase();
186
186
  try {
187
187
  switch (method) {
188
- case 'app-password':
189
- case 'basic':
188
+ case "app-password":
189
+ case "basic":
190
190
  return await this.authenticateWithBasic();
191
- case 'jwt':
191
+ case "jwt":
192
192
  return await this.authenticateWithJWT();
193
- case 'cookie':
193
+ case "cookie":
194
194
  return await this.authenticateWithCookie();
195
- case 'api-key':
195
+ case "api-key":
196
196
  // API key auth doesn't require separate authentication step
197
197
  this.authenticated = true;
198
198
  return true;
@@ -211,19 +211,19 @@ export class WordPressClient {
211
211
  */
212
212
  async authenticateWithBasic() {
213
213
  const hasCredentials = this.auth.username &&
214
- (this.auth.method === 'app-password'
214
+ (this.auth.method === "app-password"
215
215
  ? this.auth.appPassword
216
216
  : this.auth.password);
217
217
  if (!hasCredentials) {
218
- const methodName = this.auth.method === 'app-password' ? 'Application Password' : 'Basic';
219
- const passwordField = this.auth.method === 'app-password' ? 'app password' : 'password';
218
+ const methodName = this.auth.method === "app-password" ? "Application Password" : "Basic";
219
+ const passwordField = this.auth.method === "app-password" ? "app password" : "password";
220
220
  throw new AuthenticationError(`Username and ${passwordField} are required for ${methodName} authentication`, this.auth.method);
221
221
  }
222
222
  try {
223
223
  // Test authentication by getting current user
224
- await this.request('GET', 'users/me');
224
+ await this.request("GET", "users/me");
225
225
  this.authenticated = true;
226
- debug.log('Basic/Application Password authentication successful');
226
+ debug.log("Basic/Application Password authentication successful");
227
227
  return true;
228
228
  }
229
229
  catch (error) {
@@ -235,18 +235,18 @@ export class WordPressClient {
235
235
  */
236
236
  async authenticateWithJWT() {
237
237
  if (!this.auth.secret || !this.auth.username || !this.auth.password) {
238
- throw new AuthenticationError('JWT secret, username, and password are required for JWT authentication', this.auth.method);
238
+ throw new AuthenticationError("JWT secret, username, and password are required for JWT authentication", this.auth.method);
239
239
  }
240
240
  try {
241
241
  const response = await fetch(`${this.baseUrl}/wp-json/jwt-auth/v1/token`, {
242
- method: 'POST',
242
+ method: "POST",
243
243
  headers: {
244
- 'Content-Type': 'application/json'
244
+ "Content-Type": "application/json",
245
245
  },
246
246
  body: JSON.stringify({
247
247
  username: this.auth.username,
248
- password: this.auth.password
249
- })
248
+ password: this.auth.password,
249
+ }),
250
250
  });
251
251
  if (!response.ok) {
252
252
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -254,7 +254,7 @@ export class WordPressClient {
254
254
  const data = (await response.json());
255
255
  this.jwtToken = data.token;
256
256
  this.authenticated = true;
257
- debug.log('JWT authentication successful');
257
+ debug.log("JWT authentication successful");
258
258
  return true;
259
259
  }
260
260
  catch (error) {
@@ -266,10 +266,10 @@ export class WordPressClient {
266
266
  */
267
267
  async authenticateWithCookie() {
268
268
  if (!this.auth.nonce) {
269
- throw new AuthenticationError('Nonce is required for cookie authentication', this.auth.method);
269
+ throw new AuthenticationError("Nonce is required for cookie authentication", this.auth.method);
270
270
  }
271
271
  this.authenticated = true;
272
- debug.log('Cookie authentication configured');
272
+ debug.log("Cookie authentication configured");
273
273
  return true;
274
274
  }
275
275
  /**
@@ -279,14 +279,14 @@ export class WordPressClient {
279
279
  const timer = startTimer();
280
280
  this._stats.totalRequests++;
281
281
  // Handle endpoint properly - remove leading slash if present to avoid double slashes
282
- const cleanEndpoint = endpoint.replace(/^\/+/, '');
283
- const url = endpoint.startsWith('http')
282
+ const cleanEndpoint = endpoint.replace(/^\/+/, "");
283
+ const url = endpoint.startsWith("http")
284
284
  ? endpoint
285
285
  : `${this.apiUrl}/${cleanEndpoint}`;
286
286
  const headers = {
287
- 'Content-Type': 'application/json',
288
- 'User-Agent': 'MCP-WordPress/1.0.0',
289
- ...options.headers
287
+ "Content-Type": "application/json",
288
+ "User-Agent": "MCP-WordPress/1.0.0",
289
+ ...options.headers,
290
290
  };
291
291
  // Add authentication headers
292
292
  this.addAuthHeaders(headers);
@@ -295,24 +295,24 @@ export class WordPressClient {
295
295
  const requestTimeout = options.timeout || this.timeout;
296
296
  const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
297
297
  const fetchOptions = {
298
+ ...options, // Spread options first
298
299
  method,
299
- headers,
300
+ headers, // Headers come after to ensure auth headers aren't overridden
300
301
  signal: controller.signal,
301
- ...options
302
302
  };
303
303
  // Add body for POST/PUT/PATCH requests
304
- if (data && ['POST', 'PUT', 'PATCH'].includes(method)) {
304
+ if (data && ["POST", "PUT", "PATCH"].includes(method)) {
305
305
  if (data instanceof FormData ||
306
- (data && typeof data.append === 'function')) {
306
+ (data && typeof data.append === "function")) {
307
307
  // For FormData, don't set Content-Type (let fetch set it with boundary)
308
- delete headers['Content-Type'];
308
+ delete headers["Content-Type"];
309
309
  fetchOptions.body = data;
310
310
  }
311
311
  else if (Buffer.isBuffer(data)) {
312
312
  // For Buffer data (manual multipart), keep Content-Type from headers
313
313
  fetchOptions.body = data;
314
314
  }
315
- else if (typeof data === 'string') {
315
+ else if (typeof data === "string") {
316
316
  fetchOptions.body = data;
317
317
  }
318
318
  else {
@@ -321,10 +321,10 @@ export class WordPressClient {
321
321
  }
322
322
  // Rate limiting
323
323
  await this.rateLimit();
324
- let lastError = new Error('Unknown error');
324
+ let lastError = new Error("Unknown error");
325
325
  for (let attempt = 0; attempt < this.maxRetries; attempt++) {
326
326
  try {
327
- debug.log(`API Request: ${method} ${url}${attempt > 0 ? ` (attempt ${attempt + 1})` : ''}`);
327
+ debug.log(`API Request: ${method} ${url}${attempt > 0 ? ` (attempt ${attempt + 1})` : ""}`);
328
328
  const response = await fetch(url, fetchOptions);
329
329
  clearTimeout(timeoutId);
330
330
  // Handle different response types
@@ -347,20 +347,20 @@ export class WordPressClient {
347
347
  }
348
348
  // Handle permission errors specifically for uploads
349
349
  if (response.status === 403 &&
350
- endpoint.includes('media') &&
351
- method === 'POST') {
352
- throw new AuthenticationError('Media upload blocked: WordPress REST API media uploads appear to be disabled or restricted by a plugin/security policy. ' +
350
+ endpoint.includes("media") &&
351
+ method === "POST") {
352
+ throw new AuthenticationError("Media upload blocked: WordPress REST API media uploads appear to be disabled or restricted by a plugin/security policy. " +
353
353
  `Error: ${errorMessage}. ` +
354
- 'Common causes: W3 Total Cache, security plugins, or custom REST API restrictions. ' +
355
- 'Please check WordPress admin settings or contact your system administrator.', this.auth.method);
354
+ "Common causes: W3 Total Cache, security plugins, or custom REST API restrictions. " +
355
+ "Please check WordPress admin settings or contact your system administrator.", this.auth.method);
356
356
  }
357
357
  // Handle general upload permission errors
358
- if (errorMessage.includes('Beiträge zu erstellen') &&
359
- endpoint.includes('media')) {
358
+ if (errorMessage.includes("Beiträge zu erstellen") &&
359
+ endpoint.includes("media")) {
360
360
  throw new AuthenticationError(`WordPress REST API media upload restriction detected: ${errorMessage}. ` +
361
- 'This typically indicates that media uploads via REST API are disabled by WordPress configuration, ' +
362
- 'a security plugin (like W3 Total Cache, Borlabs Cookie), or server policy. ' +
363
- 'User has sufficient permissions but WordPress/plugins are blocking the upload.', this.auth.method);
361
+ "This typically indicates that media uploads via REST API are disabled by WordPress configuration, " +
362
+ "a security plugin (like W3 Total Cache, Borlabs Cookie), or server policy. " +
363
+ "User has sufficient permissions but WordPress/plugins are blocking the upload.", this.auth.method);
364
364
  }
365
365
  throw new WordPressAPIError(errorMessage, response.status);
366
366
  }
@@ -381,7 +381,7 @@ export class WordPressClient {
381
381
  }
382
382
  catch (parseError) {
383
383
  // For authentication requests, malformed JSON should be an error
384
- if (endpoint.includes('users/me') || endpoint.includes('jwt-auth')) {
384
+ if (endpoint.includes("users/me") || endpoint.includes("jwt-auth")) {
385
385
  throw new WordPressAPIError(`Invalid JSON response: ${parseError.message}`);
386
386
  }
387
387
  this._stats.successfulRequests++;
@@ -394,20 +394,20 @@ export class WordPressClient {
394
394
  clearTimeout(timeoutId);
395
395
  lastError = error;
396
396
  // Handle timeout errors
397
- if (error.name === 'AbortError') {
397
+ if (error.name === "AbortError") {
398
398
  lastError = new Error(`Request timeout after ${requestTimeout}ms`);
399
399
  }
400
400
  // Handle network errors
401
- if (lastError.message.includes('socket hang up') ||
402
- lastError.message.includes('ECONNRESET')) {
401
+ if (lastError.message.includes("socket hang up") ||
402
+ lastError.message.includes("ECONNRESET")) {
403
403
  lastError = new Error(`Network connection lost during upload: ${lastError.message}`);
404
404
  }
405
405
  debug.log(`Request failed (attempt ${attempt + 1}): ${lastError.message}`);
406
406
  // Don't retry on authentication errors, timeouts, or critical network errors
407
- if (lastError.message.includes('401') ||
408
- lastError.message.includes('403') ||
409
- lastError.message.includes('timeout') ||
410
- lastError.message.includes('Network connection lost')) {
407
+ if (lastError.message.includes("401") ||
408
+ lastError.message.includes("403") ||
409
+ lastError.message.includes("timeout") ||
410
+ lastError.message.includes("Network connection lost")) {
411
411
  break;
412
412
  }
413
413
  if (attempt < this.maxRetries - 1) {
@@ -428,33 +428,33 @@ export class WordPressClient {
428
428
  }
429
429
  // HTTP method helpers
430
430
  async get(endpoint, options) {
431
- return this.request('GET', endpoint, null, options);
431
+ return this.request("GET", endpoint, null, options);
432
432
  }
433
433
  async post(endpoint, data, options) {
434
- return this.request('POST', endpoint, data, options);
434
+ return this.request("POST", endpoint, data, options);
435
435
  }
436
436
  async put(endpoint, data, options) {
437
- return this.request('PUT', endpoint, data, options);
437
+ return this.request("PUT", endpoint, data, options);
438
438
  }
439
439
  async patch(endpoint, data, options) {
440
- return this.request('PATCH', endpoint, data, options);
440
+ return this.request("PATCH", endpoint, data, options);
441
441
  }
442
442
  async delete(endpoint, options) {
443
- return this.request('DELETE', endpoint, null, options);
443
+ return this.request("DELETE", endpoint, null, options);
444
444
  }
445
445
  // WordPress API Methods
446
446
  // Posts
447
447
  async getPosts(params) {
448
448
  const queryString = params
449
- ? '?' + new URLSearchParams(params).toString()
450
- : '';
449
+ ? "?" + new URLSearchParams(params).toString()
450
+ : "";
451
451
  return this.get(`posts${queryString}`);
452
452
  }
453
- async getPost(id, context = 'view') {
453
+ async getPost(id, context = "view") {
454
454
  return this.get(`posts/${id}?context=${context}`);
455
455
  }
456
456
  async createPost(data) {
457
- return this.post('posts', data);
457
+ return this.post("posts", data);
458
458
  }
459
459
  async updatePost(data) {
460
460
  const { id, ...updateData } = data;
@@ -469,15 +469,15 @@ export class WordPressClient {
469
469
  // Pages
470
470
  async getPages(params) {
471
471
  const queryString = params
472
- ? '?' + new URLSearchParams(params).toString()
473
- : '';
472
+ ? "?" + new URLSearchParams(params).toString()
473
+ : "";
474
474
  return this.get(`pages${queryString}`);
475
475
  }
476
- async getPage(id, context = 'view') {
476
+ async getPage(id, context = "view") {
477
477
  return this.get(`pages/${id}?context=${context}`);
478
478
  }
479
479
  async createPage(data) {
480
- return this.post('pages', data);
480
+ return this.post("pages", data);
481
481
  }
482
482
  async updatePage(data) {
483
483
  const { id, ...updateData } = data;
@@ -492,11 +492,11 @@ export class WordPressClient {
492
492
  // Media
493
493
  async getMedia(params) {
494
494
  const queryString = params
495
- ? '?' + new URLSearchParams(params).toString()
496
- : '';
495
+ ? "?" + new URLSearchParams(params).toString()
496
+ : "";
497
497
  return this.get(`media${queryString}`);
498
498
  }
499
- async getMediaItem(id, context = 'view') {
499
+ async getMediaItem(id, context = "view") {
500
500
  return this.get(`media/${id}?context=${context}`);
501
501
  }
502
502
  async uploadMedia(data) {
@@ -520,30 +520,30 @@ export class WordPressClient {
520
520
  const formData = new FormData();
521
521
  formData.setMaxListeners(20);
522
522
  // Add file with correct options
523
- formData.append('file', fileData, {
523
+ formData.append("file", fileData, {
524
524
  filename,
525
- contentType: mimeType
525
+ contentType: mimeType,
526
526
  });
527
527
  // Add metadata
528
528
  if (meta.title)
529
- formData.append('title', meta.title);
529
+ formData.append("title", meta.title);
530
530
  if (meta.alt_text)
531
- formData.append('alt_text', meta.alt_text);
531
+ formData.append("alt_text", meta.alt_text);
532
532
  if (meta.caption)
533
- formData.append('caption', meta.caption);
533
+ formData.append("caption", meta.caption);
534
534
  if (meta.description)
535
- formData.append('description', meta.description);
535
+ formData.append("description", meta.description);
536
536
  if (meta.post)
537
- formData.append('post', meta.post.toString());
537
+ formData.append("post", meta.post.toString());
538
538
  // Use longer timeout for file uploads
539
539
  const uploadTimeout = options?.timeout !== undefined ? options.timeout : 600000; // 10 minutes default
540
540
  const uploadOptions = {
541
541
  ...options,
542
- timeout: uploadTimeout
542
+ timeout: uploadTimeout,
543
543
  };
544
544
  debug.log(`Upload prepared with FormData, timeout: ${uploadTimeout}ms`);
545
545
  // Use the regular post method which handles FormData correctly
546
- return this.post('media', formData, uploadOptions);
546
+ return this.post("media", formData, uploadOptions);
547
547
  }
548
548
  async updateMedia(data) {
549
549
  const { id, ...updateData } = data;
@@ -555,15 +555,15 @@ export class WordPressClient {
555
555
  // Users
556
556
  async getUsers(params) {
557
557
  const queryString = params
558
- ? '?' + new URLSearchParams(params).toString()
559
- : '';
558
+ ? "?" + new URLSearchParams(params).toString()
559
+ : "";
560
560
  return this.get(`users${queryString}`);
561
561
  }
562
- async getUser(id, context = 'view') {
562
+ async getUser(id, context = "view") {
563
563
  return this.get(`users/${id}?context=${context}`);
564
564
  }
565
565
  async createUser(data) {
566
- return this.post('users', data);
566
+ return this.post("users", data);
567
567
  }
568
568
  async updateUser(data) {
569
569
  const { id, ...updateData } = data;
@@ -572,24 +572,24 @@ export class WordPressClient {
572
572
  async deleteUser(id, reassign) {
573
573
  const params = reassign
574
574
  ? `?reassign=${reassign}&force=true`
575
- : '?force=true';
575
+ : "?force=true";
576
576
  return this.delete(`users/${id}${params}`);
577
577
  }
578
578
  async getCurrentUser() {
579
- return this.getUser('me');
579
+ return this.getUser("me");
580
580
  }
581
581
  // Comments
582
582
  async getComments(params) {
583
583
  const queryString = params
584
- ? '?' + new URLSearchParams(params).toString()
585
- : '';
584
+ ? "?" + new URLSearchParams(params).toString()
585
+ : "";
586
586
  return this.get(`comments${queryString}`);
587
587
  }
588
- async getComment(id, context = 'view') {
588
+ async getComment(id, context = "view") {
589
589
  return this.get(`comments/${id}?context=${context}`);
590
590
  }
591
591
  async createComment(data) {
592
- return this.post('comments', data);
592
+ return this.post("comments", data);
593
593
  }
594
594
  async updateComment(data) {
595
595
  const { id, ...updateData } = data;
@@ -599,28 +599,28 @@ export class WordPressClient {
599
599
  return this.delete(`comments/${id}?force=${force}`);
600
600
  }
601
601
  async approveComment(id) {
602
- return this.put(`comments/${id}`, { status: 'approved' });
602
+ return this.put(`comments/${id}`, { status: "approved" });
603
603
  }
604
604
  async rejectComment(id) {
605
605
  return this.put(`comments/${id}`, {
606
- status: 'unapproved'
606
+ status: "unapproved",
607
607
  });
608
608
  }
609
609
  async spamComment(id) {
610
- return this.put(`comments/${id}`, { status: 'spam' });
610
+ return this.put(`comments/${id}`, { status: "spam" });
611
611
  }
612
612
  // Taxonomies
613
613
  async getCategories(params) {
614
614
  const queryString = params
615
- ? '?' + new URLSearchParams(params).toString()
616
- : '';
615
+ ? "?" + new URLSearchParams(params).toString()
616
+ : "";
617
617
  return this.get(`categories${queryString}`);
618
618
  }
619
619
  async getCategory(id) {
620
620
  return this.get(`categories/${id}`);
621
621
  }
622
622
  async createCategory(data) {
623
- return this.post('categories', data);
623
+ return this.post("categories", data);
624
624
  }
625
625
  async updateCategory(data) {
626
626
  const { id, ...updateData } = data;
@@ -631,15 +631,15 @@ export class WordPressClient {
631
631
  }
632
632
  async getTags(params) {
633
633
  const queryString = params
634
- ? '?' + new URLSearchParams(params).toString()
635
- : '';
634
+ ? "?" + new URLSearchParams(params).toString()
635
+ : "";
636
636
  return this.get(`tags${queryString}`);
637
637
  }
638
638
  async getTag(id) {
639
639
  return this.get(`tags/${id}`);
640
640
  }
641
641
  async createTag(data) {
642
- return this.post('tags', data);
642
+ return this.post("tags", data);
643
643
  }
644
644
  async updateTag(data) {
645
645
  const { id, ...updateData } = data;
@@ -650,16 +650,16 @@ export class WordPressClient {
650
650
  }
651
651
  // Site Management
652
652
  async getSiteSettings() {
653
- return this.get('settings');
653
+ return this.get("settings");
654
654
  }
655
655
  async updateSiteSettings(settings) {
656
- return this.post('settings', settings);
656
+ return this.post("settings", settings);
657
657
  }
658
658
  async getSiteInfo() {
659
- return this.get('');
659
+ return this.get("");
660
660
  }
661
661
  // Application Passwords
662
- async getApplicationPasswords(userId = 'me') {
662
+ async getApplicationPasswords(userId = "me") {
663
663
  return this.get(`users/${userId}/application-passwords`);
664
664
  }
665
665
  async createApplicationPassword(userId, name, appId) {
@@ -675,15 +675,15 @@ export class WordPressClient {
675
675
  async search(query, types, subtype) {
676
676
  const params = new URLSearchParams({ search: query });
677
677
  if (types)
678
- params.append('type', types.join(','));
678
+ params.append("type", types.join(","));
679
679
  if (subtype)
680
- params.append('subtype', subtype);
680
+ params.append("subtype", subtype);
681
681
  return this.get(`search?${params.toString()}`);
682
682
  }
683
683
  // Utility Methods
684
684
  async ping() {
685
685
  try {
686
- await this.get('');
686
+ await this.get("");
687
687
  return true;
688
688
  }
689
689
  catch {
@@ -691,13 +691,13 @@ export class WordPressClient {
691
691
  }
692
692
  }
693
693
  async getServerInfo() {
694
- return this.get('');
694
+ return this.get("");
695
695
  }
696
696
  validateEndpoint(endpoint) {
697
697
  return /^[a-zA-Z0-9\/\-_]+$/.test(endpoint);
698
698
  }
699
699
  buildUrl(endpoint, params) {
700
- const url = `${this.apiUrl}/${endpoint.replace(/^\/+/, '')}`;
700
+ const url = `${this.apiUrl}/${endpoint.replace(/^\/+/, "")}`;
701
701
  if (params) {
702
702
  const searchParams = new URLSearchParams(params);
703
703
  return `${url}?${searchParams.toString()}`;
@@ -707,21 +707,21 @@ export class WordPressClient {
707
707
  getMimeType(filePath) {
708
708
  const ext = path.extname(filePath).toLowerCase();
709
709
  const mimeTypes = {
710
- '.jpg': 'image/jpeg',
711
- '.jpeg': 'image/jpeg',
712
- '.png': 'image/png',
713
- '.gif': 'image/gif',
714
- '.webp': 'image/webp',
715
- '.svg': 'image/svg+xml',
716
- '.pdf': 'application/pdf',
717
- '.doc': 'application/msword',
718
- '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
719
- '.txt': 'text/plain',
720
- '.mp4': 'video/mp4',
721
- '.mp3': 'audio/mpeg',
722
- '.wav': 'audio/wav'
710
+ ".jpg": "image/jpeg",
711
+ ".jpeg": "image/jpeg",
712
+ ".png": "image/png",
713
+ ".gif": "image/gif",
714
+ ".webp": "image/webp",
715
+ ".svg": "image/svg+xml",
716
+ ".pdf": "application/pdf",
717
+ ".doc": "application/msword",
718
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
719
+ ".txt": "text/plain",
720
+ ".mp4": "video/mp4",
721
+ ".mp3": "audio/mpeg",
722
+ ".wav": "audio/wav",
723
723
  };
724
- return mimeTypes[ext] || 'application/octet-stream';
724
+ return mimeTypes[ext] || "application/octet-stream";
725
725
  }
726
726
  }
727
727
  //# sourceMappingURL=api.js.map