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.
- package/README.md +17 -19
- package/bin/mcp-wordpress.js +3 -3
- package/bin/setup.js +140 -141
- package/bin/status.js +112 -114
- package/dist/client/MockWordPressClient.d.ts.map +1 -1
- package/dist/client/MockWordPressClient.js.map +1 -1
- package/dist/client/SEOWordPressClient.d.ts.map +1 -1
- package/dist/client/SEOWordPressClient.js +16 -14
- package/dist/client/SEOWordPressClient.js.map +1 -1
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.js +6 -6
- package/dist/client/managers/AuthManager.d.ts.map +1 -1
- package/dist/client/managers/AuthManager.js +2 -2
- package/dist/client/managers/AuthManager.js.map +1 -1
- package/dist/client/managers/AuthenticationManager.js +1 -1
- package/dist/client/managers/JWTAuthImplementation.d.ts.map +1 -1
- package/dist/client/managers/JWTAuthImplementation.js +7 -7
- package/dist/client/managers/JWTAuthImplementation.js.map +1 -1
- package/dist/client/managers/composed/MigrationAdapter.js +1 -1
- package/dist/client/managers/composed/index.d.ts +2 -2
- package/dist/client/managers/composed/index.d.ts.map +1 -1
- package/dist/client/managers/composed/index.js +1 -1
- package/dist/client/managers/composed/index.js.map +1 -1
- package/dist/client/managers/implementations/ErrorHandlerImpl.d.ts.map +1 -1
- package/dist/client/managers/implementations/ErrorHandlerImpl.js +2 -4
- package/dist/client/managers/implementations/ErrorHandlerImpl.js.map +1 -1
- package/dist/client/managers/implementations/ParameterValidatorImpl.d.ts.map +1 -1
- package/dist/client/managers/implementations/ParameterValidatorImpl.js +1 -1
- package/dist/client/managers/implementations/ParameterValidatorImpl.js.map +1 -1
- package/dist/client/managers/interfaces/ManagerInterfaces.d.ts.map +1 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +3 -3
- package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
- package/dist/docs/MarkdownFormatter.js +7 -7
- package/dist/docs/MarkdownFormatter.js.map +1 -1
- package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
- package/dist/performance/PerformanceAnalytics.js +3 -1
- package/dist/performance/PerformanceAnalytics.js.map +1 -1
- package/dist/security/InputValidator.js +1 -1
- package/dist/security/SecurityCIPipeline.js +1 -1
- package/dist/security/SecurityCIPipeline.js.map +1 -1
- package/dist/security/SecurityConfig.d.ts.map +1 -1
- package/dist/security/SecurityConfig.js +6 -2
- package/dist/security/SecurityConfig.js.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +2 -2
- package/dist/tools/cache.d.ts.map +1 -1
- package/dist/tools/cache.js.map +1 -1
- package/dist/tools/comments.d.ts.map +1 -1
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/performance.d.ts.map +1 -1
- package/dist/tools/performance.js.map +1 -1
- package/dist/tools/posts/PostHandlers.d.ts.map +1 -1
- package/dist/tools/posts/PostHandlers.js.map +1 -1
- package/dist/tools/seo/SEOTools.d.ts.map +1 -1
- package/dist/tools/seo/SEOTools.js.map +1 -1
- package/dist/tools/seo/analyzers/ContentAnalyzer.d.ts.map +1 -1
- package/dist/tools/seo/analyzers/ContentAnalyzer.js.map +1 -1
- package/dist/types/enhanced.d.ts +17 -17
- package/dist/types/enhanced.d.ts.map +1 -1
- package/dist/types/enhanced.js +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/requests.d.ts +16 -16
- package/dist/types/tools.d.ts +46 -46
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/utils/index.d.ts +7 -7
- package/dist/utils/index.js +7 -7
- package/docs/ARCHITECTURE.md +17 -17
- package/docs/BADGE_UPDATES.md +11 -11
- package/docs/CACHING.md +2 -0
- package/docs/CI_CD_IMPROVEMENTS.md +8 -5
- package/docs/CONFIGURATION.md +76 -46
- package/docs/DOCKER_PUBLISHING_TROUBLESHOOTING.md +11 -2
- package/docs/EVALUATION.md +16 -21
- package/docs/INCREMENTAL_COVERAGE.md +7 -3
- package/docs/INSTALLATION.md +33 -19
- package/docs/PUBLISHING-TROUBLESHOOTING.md +3 -2
- package/docs/SECURITY.md +17 -15
- package/docs/SECURITY_TESTING.md +3 -0
- package/docs/TROUBLESHOOTING.md +85 -36
- package/docs/api/README.md +118 -125
- package/docs/api/categories/auth.md +3 -1
- package/docs/api/categories/cache.md +3 -1
- package/docs/api/categories/comment.md +3 -1
- package/docs/api/categories/media.md +3 -1
- package/docs/api/categories/page.md +3 -1
- package/docs/api/categories/performance.md +3 -1
- package/docs/api/categories/post.md +3 -1
- package/docs/api/categories/site.md +3 -1
- package/docs/api/categories/taxonomy.md +3 -1
- package/docs/api/categories/user.md +3 -1
- package/docs/api/openapi.json +114 -410
- package/docs/api/summary.json +1 -1
- package/docs/api/tools/wp_approve_comment.md +13 -25
- package/docs/api/tools/wp_cache_clear.md +17 -30
- package/docs/api/tools/wp_cache_info.md +16 -29
- package/docs/api/tools/wp_cache_stats.md +16 -29
- package/docs/api/tools/wp_cache_warm.md +16 -29
- package/docs/api/tools/wp_create_application_password.md +14 -26
- package/docs/api/tools/wp_create_category.md +14 -26
- package/docs/api/tools/wp_create_comment.md +18 -31
- package/docs/api/tools/wp_create_page.md +17 -29
- package/docs/api/tools/wp_create_post.md +25 -30
- package/docs/api/tools/wp_create_tag.md +13 -25
- package/docs/api/tools/wp_create_user.md +18 -30
- package/docs/api/tools/wp_delete_application_password.md +14 -26
- package/docs/api/tools/wp_delete_category.md +13 -25
- package/docs/api/tools/wp_delete_comment.md +14 -26
- package/docs/api/tools/wp_delete_media.md +14 -25
- package/docs/api/tools/wp_delete_page.md +14 -25
- package/docs/api/tools/wp_delete_post.md +17 -25
- package/docs/api/tools/wp_delete_tag.md +13 -25
- package/docs/api/tools/wp_delete_user.md +14 -25
- package/docs/api/tools/wp_get_application_passwords.md +13 -25
- package/docs/api/tools/wp_get_auth_status.md +12 -24
- package/docs/api/tools/wp_get_category.md +13 -25
- package/docs/api/tools/wp_get_comment.md +13 -25
- package/docs/api/tools/wp_get_current_user.md +17 -30
- package/docs/api/tools/wp_get_media.md +13 -25
- package/docs/api/tools/wp_get_page.md +13 -25
- package/docs/api/tools/wp_get_page_revisions.md +13 -25
- package/docs/api/tools/wp_get_post.md +16 -25
- package/docs/api/tools/wp_get_post_revisions.md +13 -25
- package/docs/api/tools/wp_get_site_settings.md +12 -23
- package/docs/api/tools/wp_get_tag.md +13 -25
- package/docs/api/tools/wp_get_user.md +13 -25
- package/docs/api/tools/wp_list_categories.md +15 -27
- package/docs/api/tools/wp_list_comments.md +15 -27
- package/docs/api/tools/wp_list_media.md +18 -31
- package/docs/api/tools/wp_list_pages.md +18 -31
- package/docs/api/tools/wp_list_posts.md +29 -41
- package/docs/api/tools/wp_list_tags.md +14 -26
- package/docs/api/tools/wp_list_users.md +20 -34
- package/docs/api/tools/wp_performance_alerts.md +22 -36
- package/docs/api/tools/wp_performance_benchmark.md +20 -34
- package/docs/api/tools/wp_performance_export.md +22 -36
- package/docs/api/tools/wp_performance_history.md +21 -35
- package/docs/api/tools/wp_performance_optimize.md +22 -36
- package/docs/api/tools/wp_performance_stats.md +20 -34
- package/docs/api/tools/wp_search_site.md +18 -32
- package/docs/api/tools/wp_spam_comment.md +13 -25
- package/docs/api/tools/wp_switch_auth_method.md +18 -31
- package/docs/api/tools/wp_test_auth.md +15 -30
- package/docs/api/tools/wp_update_category.md +14 -26
- package/docs/api/tools/wp_update_comment.md +17 -30
- package/docs/api/tools/wp_update_media.md +19 -32
- package/docs/api/tools/wp_update_page.md +18 -30
- package/docs/api/tools/wp_update_post.md +21 -30
- package/docs/api/tools/wp_update_site_settings.md +18 -31
- package/docs/api/tools/wp_update_tag.md +14 -26
- package/docs/api/tools/wp_update_user.md +17 -29
- package/docs/api/tools/wp_upload_media.md +20 -32
- package/docs/api/types/WordPressPost.md +8 -15
- package/docs/code-improvements.md +1 -0
- package/docs/developer/GITHUB_ACTIONS_SETUP.md +2 -2
- package/docs/developer/MAINTENANCE.md +4 -0
- package/docs/developer/NPM_AUTH_SETUP.md +3 -0
- package/docs/developer/RELEASE_PROCESS.md +1 -0
- package/docs/examples/multi-site-setup.md +2 -0
- package/docs/integrations/claude-desktop.md +14 -5
- package/docs/integrations/cline.md +1 -0
- package/docs/user-guides/DTX_SETUP.md +9 -8
- package/docs/user-guides/NPX_SETUP.md +5 -9
- package/docs/user-guides/SMITHERY_SETUP.md +5 -0
- package/docs/v2.2.0-resolution-demo.md +17 -2
- package/package.json +2 -1
- package/src/cache/__tests__/CacheManager.test.ts +4 -8
- package/src/client/MockWordPressClient.ts +5 -1
- package/src/client/SEOWordPressClient.ts +30 -26
- package/src/client/index.ts +6 -6
- package/src/client/managers/AuthManager.ts +16 -8
- package/src/client/managers/AuthenticationManager.ts +2 -2
- package/src/client/managers/JWTAuthImplementation.ts +24 -27
- package/src/client/managers/ManagersIndex.ts +1 -1
- package/src/client/managers/composed/MigrationAdapter.ts +1 -1
- package/src/client/managers/composed/index.ts +7 -7
- package/src/client/managers/implementations/ErrorHandlerImpl.ts +12 -26
- package/src/client/managers/implementations/ParameterValidatorImpl.ts +49 -49
- package/src/client/managers/interfaces/ManagerInterfaces.ts +13 -9
- package/src/config/index.ts +3 -3
- package/src/docs/MarkdownFormatter.ts +13 -9
- package/src/performance/PerformanceAnalytics.ts +9 -3
- package/src/security/InputValidator.ts +1 -1
- package/src/security/SecurityCIPipeline.ts +1 -1
- package/src/security/SecurityConfig.ts +9 -3
- package/src/server/index.ts +2 -2
- package/src/tools/cache.ts +3 -1
- package/src/tools/comments.ts +3 -1
- package/src/tools/performance.ts +7 -3
- package/src/tools/posts/PostHandlers.ts +3 -1
- package/src/tools/seo/SEOTools.ts +6 -2
- package/src/tools/seo/analyzers/ContentAnalyzer.ts +9 -3
- package/src/types/enhanced.ts +34 -34
- package/src/types/index.ts +13 -11
- package/src/types/requests.ts +19 -19
- package/src/types/tools.ts +137 -84
- package/src/utils/index.ts +7 -7
|
@@ -34,10 +34,10 @@ export class JWTAuthImplementation {
|
|
|
34
34
|
private jwtToken: string | null = null;
|
|
35
35
|
private tokenExpiry: number | null = null;
|
|
36
36
|
private refreshTokenValue: string | null = null;
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
constructor(
|
|
39
39
|
private requestManager: RequestManager,
|
|
40
|
-
private authConfig: AuthConfig
|
|
40
|
+
private authConfig: AuthConfig,
|
|
41
41
|
) {}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -49,9 +49,9 @@ export class JWTAuthImplementation {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
try {
|
|
52
|
-
this.logger.info("Starting JWT authentication", {
|
|
52
|
+
this.logger.info("Starting JWT authentication", {
|
|
53
53
|
username: this.authConfig.username,
|
|
54
|
-
endpoint: "jwt-auth/v1/token"
|
|
54
|
+
endpoint: "jwt-auth/v1/token",
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
const response = await this.requestManager.request<JWTTokenResponse>(
|
|
@@ -64,7 +64,7 @@ export class JWTAuthImplementation {
|
|
|
64
64
|
{
|
|
65
65
|
skipAuth: true, // Don't use auth headers for the auth request itself
|
|
66
66
|
timeout: 10000,
|
|
67
|
-
} as RequestOptions & { skipAuth: boolean }
|
|
67
|
+
} as RequestOptions & { skipAuth: boolean },
|
|
68
68
|
);
|
|
69
69
|
|
|
70
70
|
if (!response.token) {
|
|
@@ -73,10 +73,10 @@ export class JWTAuthImplementation {
|
|
|
73
73
|
|
|
74
74
|
// Store the JWT token
|
|
75
75
|
this.jwtToken = response.token;
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
// Calculate token expiry (default to 24 hours if not provided)
|
|
78
|
-
const expiresInSeconds = response.expires_in ||
|
|
79
|
-
this.tokenExpiry = Date.now() +
|
|
78
|
+
const expiresInSeconds = response.expires_in || 24 * 60 * 60;
|
|
79
|
+
this.tokenExpiry = Date.now() + expiresInSeconds * 1000;
|
|
80
80
|
|
|
81
81
|
this.logger.info("JWT authentication successful", {
|
|
82
82
|
user: response.user_nicename,
|
|
@@ -85,14 +85,13 @@ export class JWTAuthImplementation {
|
|
|
85
85
|
|
|
86
86
|
// Test the token by validating it
|
|
87
87
|
await this.validateToken();
|
|
88
|
-
|
|
89
88
|
} catch (error) {
|
|
90
89
|
this.jwtToken = null;
|
|
91
90
|
this.tokenExpiry = null;
|
|
92
91
|
this.logger.error("JWT authentication failed", {
|
|
93
92
|
error: error instanceof Error ? error.message : String(error),
|
|
94
93
|
});
|
|
95
|
-
|
|
94
|
+
|
|
96
95
|
if (error instanceof Error) {
|
|
97
96
|
throw new AuthenticationError(`JWT authentication failed: ${error.message}`, AUTH_METHODS.JWT);
|
|
98
97
|
}
|
|
@@ -118,11 +117,11 @@ export class JWTAuthImplementation {
|
|
|
118
117
|
Authorization: `Bearer ${this.jwtToken}`,
|
|
119
118
|
},
|
|
120
119
|
timeout: 5000,
|
|
121
|
-
}
|
|
120
|
+
},
|
|
122
121
|
);
|
|
123
122
|
|
|
124
123
|
const isValid = response.data.status === 200;
|
|
125
|
-
|
|
124
|
+
|
|
126
125
|
if (!isValid) {
|
|
127
126
|
this.logger.warn("JWT token validation failed", { response });
|
|
128
127
|
this.jwtToken = null;
|
|
@@ -130,7 +129,6 @@ export class JWTAuthImplementation {
|
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
return isValid;
|
|
133
|
-
|
|
134
132
|
} catch (error) {
|
|
135
133
|
this.logger.warn("JWT token validation error", {
|
|
136
134
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -162,14 +160,14 @@ export class JWTAuthImplementation {
|
|
|
162
160
|
Authorization: `Bearer ${this.jwtToken}`,
|
|
163
161
|
},
|
|
164
162
|
timeout: 5000,
|
|
165
|
-
}
|
|
163
|
+
},
|
|
166
164
|
);
|
|
167
165
|
|
|
168
166
|
if (refreshResponse.token) {
|
|
169
167
|
this.jwtToken = refreshResponse.token;
|
|
170
|
-
const expiresInSeconds = refreshResponse.expires_in ||
|
|
171
|
-
this.tokenExpiry = Date.now() +
|
|
172
|
-
|
|
168
|
+
const expiresInSeconds = refreshResponse.expires_in || 24 * 60 * 60;
|
|
169
|
+
this.tokenExpiry = Date.now() + expiresInSeconds * 1000;
|
|
170
|
+
|
|
173
171
|
this.logger.info("JWT token refreshed successfully", {
|
|
174
172
|
expiresAt: new Date(this.tokenExpiry).toISOString(),
|
|
175
173
|
});
|
|
@@ -186,17 +184,16 @@ export class JWTAuthImplementation {
|
|
|
186
184
|
|
|
187
185
|
this.logger.debug("Re-authenticating to refresh JWT token");
|
|
188
186
|
await this.authenticateJWT();
|
|
189
|
-
|
|
190
187
|
} catch (error) {
|
|
191
188
|
this.jwtToken = null;
|
|
192
189
|
this.tokenExpiry = null;
|
|
193
190
|
this.logger.error("JWT token refresh failed", {
|
|
194
191
|
error: error instanceof Error ? error.message : String(error),
|
|
195
192
|
});
|
|
196
|
-
|
|
193
|
+
|
|
197
194
|
throw new AuthenticationError(
|
|
198
|
-
`JWT token refresh failed: ${error instanceof Error ? error.message :
|
|
199
|
-
AUTH_METHODS.JWT
|
|
195
|
+
`JWT token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
196
|
+
AUTH_METHODS.JWT,
|
|
200
197
|
);
|
|
201
198
|
}
|
|
202
199
|
}
|
|
@@ -208,10 +205,10 @@ export class JWTAuthImplementation {
|
|
|
208
205
|
if (!this.tokenExpiry) {
|
|
209
206
|
return true;
|
|
210
207
|
}
|
|
211
|
-
|
|
208
|
+
|
|
212
209
|
// Consider token expired if it expires within 5 minutes (300000ms)
|
|
213
210
|
const buffer = 5 * 60 * 1000;
|
|
214
|
-
return Date.now() >=
|
|
211
|
+
return Date.now() >= this.tokenExpiry - buffer;
|
|
215
212
|
}
|
|
216
213
|
|
|
217
214
|
/**
|
|
@@ -245,7 +242,7 @@ export class JWTAuthImplementation {
|
|
|
245
242
|
if (!this.jwtToken) {
|
|
246
243
|
return {};
|
|
247
244
|
}
|
|
248
|
-
|
|
245
|
+
|
|
249
246
|
return {
|
|
250
247
|
Authorization: `Bearer ${this.jwtToken}`,
|
|
251
248
|
};
|
|
@@ -294,9 +291,9 @@ export class JWTAuthImplementation {
|
|
|
294
291
|
{
|
|
295
292
|
headers: this.getAuthHeaders(),
|
|
296
293
|
timeout: 5000,
|
|
297
|
-
}
|
|
294
|
+
},
|
|
298
295
|
);
|
|
299
|
-
|
|
296
|
+
|
|
300
297
|
this.logger.info("JWT token invalidated on server");
|
|
301
298
|
} catch (error) {
|
|
302
299
|
this.logger.warn("Failed to invalidate JWT token on server", {
|
|
@@ -323,4 +320,4 @@ export class JWTAuthImplementation {
|
|
|
323
320
|
expiresIn: this.tokenExpiry ? Math.max(0, this.tokenExpiry - Date.now()) : null,
|
|
324
321
|
};
|
|
325
322
|
}
|
|
326
|
-
}
|
|
323
|
+
}
|
|
@@ -245,7 +245,7 @@ import { MigrationAdapter } from '@/client/managers/composed';
|
|
|
245
245
|
const USE_COMPOSITION = process.env.USE_COMPOSED_MANAGERS === 'true';
|
|
246
246
|
|
|
247
247
|
const { requestManager, authManager } = await MigrationAdapter.createManagers(
|
|
248
|
-
config,
|
|
248
|
+
config,
|
|
249
249
|
USE_COMPOSITION
|
|
250
250
|
);
|
|
251
251
|
\`\`\`
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Composed Managers Export
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* This module provides composition-based alternatives to the inheritance-based managers.
|
|
5
5
|
* The composed managers offer better testability, flexibility, and adherence to SOLID principles.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* ```typescript
|
|
9
9
|
* import { createComposedWordPressClient } from '@/client/managers/composed';
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
11
|
* const client = await createComposedWordPressClient(config);
|
|
12
12
|
* const posts = await client.getPosts();
|
|
13
13
|
* ```
|
|
@@ -23,7 +23,7 @@ export type {
|
|
|
23
23
|
BaseManagerContract,
|
|
24
24
|
ComposedManager,
|
|
25
25
|
ManagerFactory,
|
|
26
|
-
ManagerCompositionConfig
|
|
26
|
+
ManagerCompositionConfig,
|
|
27
27
|
} from "../interfaces/ManagerInterfaces.js";
|
|
28
28
|
|
|
29
29
|
// Implementations
|
|
@@ -36,12 +36,12 @@ export { ComposedAuthenticationManager } from "../ComposedAuthenticationManager.
|
|
|
36
36
|
export { ComposedRequestManager } from "../ComposedRequestManager.js";
|
|
37
37
|
|
|
38
38
|
// Factory and Client
|
|
39
|
-
export {
|
|
39
|
+
export {
|
|
40
40
|
ComposedManagerFactory,
|
|
41
41
|
ComposedWordPressClient,
|
|
42
42
|
createComposedWordPressClient,
|
|
43
|
-
type ComposedWordPressClientDependencies
|
|
43
|
+
type ComposedWordPressClientDependencies,
|
|
44
44
|
} from "../ComposedManagerFactory.js";
|
|
45
45
|
|
|
46
46
|
// Migration utilities (for gradual migration from inheritance to composition)
|
|
47
|
-
export { MigrationAdapter } from "./MigrationAdapter.js";
|
|
47
|
+
export { MigrationAdapter } from "./MigrationAdapter.js";
|
|
@@ -28,18 +28,14 @@ export class ErrorHandlerImpl implements ErrorHandler {
|
|
|
28
28
|
|
|
29
29
|
if (isErrorLike(error)) {
|
|
30
30
|
if (error.name === "AbortError" || error.code === "ABORT_ERR") {
|
|
31
|
-
throw new WordPressAPIError(
|
|
32
|
-
`Request timeout after ${this.configProvider.config.timeout}ms`,
|
|
33
|
-
408,
|
|
34
|
-
"timeout"
|
|
35
|
-
);
|
|
31
|
+
throw new WordPressAPIError(`Request timeout after ${this.configProvider.config.timeout}ms`, 408, "timeout");
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
if (error.code === "ECONNREFUSED" || error.code === "ENOTFOUND") {
|
|
39
35
|
throw new WordPressAPIError(
|
|
40
|
-
`Cannot connect to WordPress site: ${this.configProvider.config.baseUrl}`,
|
|
41
|
-
503,
|
|
42
|
-
"connection_failed"
|
|
36
|
+
`Cannot connect to WordPress site: ${this.configProvider.config.baseUrl}`,
|
|
37
|
+
503,
|
|
38
|
+
"connection_failed",
|
|
43
39
|
);
|
|
44
40
|
}
|
|
45
41
|
}
|
|
@@ -60,27 +56,21 @@ export class ErrorHandlerImpl implements ErrorHandler {
|
|
|
60
56
|
*/
|
|
61
57
|
handleAuthError(error: unknown, operation: string): never {
|
|
62
58
|
logError(`Authentication failed during ${operation}:`, error as Record<string, unknown>);
|
|
63
|
-
|
|
59
|
+
|
|
64
60
|
if (error instanceof WordPressAPIError) {
|
|
65
61
|
throw error;
|
|
66
62
|
}
|
|
67
63
|
|
|
68
64
|
const message = getErrorMessage(error);
|
|
69
|
-
throw new WordPressAPIError(
|
|
70
|
-
`Authentication failed during ${operation}: ${message}`,
|
|
71
|
-
401,
|
|
72
|
-
"auth_failed"
|
|
73
|
-
);
|
|
65
|
+
throw new WordPressAPIError(`Authentication failed during ${operation}: ${message}`, 401, "auth_failed");
|
|
74
66
|
}
|
|
75
67
|
|
|
76
68
|
/**
|
|
77
69
|
* Handle rate limit errors specifically
|
|
78
70
|
*/
|
|
79
71
|
handleRateLimitError(retryAfter?: number): never {
|
|
80
|
-
const message = retryAfter
|
|
81
|
-
|
|
82
|
-
: "Rate limit exceeded.";
|
|
83
|
-
|
|
72
|
+
const message = retryAfter ? `Rate limit exceeded. Retry after ${retryAfter} seconds.` : "Rate limit exceeded.";
|
|
73
|
+
|
|
84
74
|
throw new WordPressAPIError(message, 429, "rate_limited");
|
|
85
75
|
}
|
|
86
76
|
|
|
@@ -91,12 +81,8 @@ export class ErrorHandlerImpl implements ErrorHandler {
|
|
|
91
81
|
const message = getErrorMessage(baseError);
|
|
92
82
|
const contextString = Object.entries(context)
|
|
93
83
|
.map(([key, value]) => `${key}=${String(value)}`)
|
|
94
|
-
.join(
|
|
95
|
-
|
|
96
|
-
return new WordPressAPIError(
|
|
97
|
-
`${message} (Context: ${contextString})`,
|
|
98
|
-
500,
|
|
99
|
-
"contextual_error"
|
|
100
|
-
);
|
|
84
|
+
.join(", ");
|
|
85
|
+
|
|
86
|
+
return new WordPressAPIError(`${message} (Context: ${contextString})`, 500, "contextual_error");
|
|
101
87
|
}
|
|
102
|
-
}
|
|
88
|
+
}
|
|
@@ -42,12 +42,16 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
42
42
|
/**
|
|
43
43
|
* Validate string parameters
|
|
44
44
|
*/
|
|
45
|
-
validateString(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
validateString(
|
|
46
|
+
value: unknown,
|
|
47
|
+
fieldName: string,
|
|
48
|
+
options?: {
|
|
49
|
+
required?: boolean;
|
|
50
|
+
minLength?: number;
|
|
51
|
+
maxLength?: number;
|
|
52
|
+
pattern?: RegExp;
|
|
53
|
+
},
|
|
54
|
+
): string {
|
|
51
55
|
if (options?.required && (value === undefined || value === null || value === "")) {
|
|
52
56
|
throw new WordPressAPIError(`${fieldName} is required`, 400, "missing_parameter");
|
|
53
57
|
}
|
|
@@ -62,26 +66,22 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
62
66
|
|
|
63
67
|
if (options?.minLength && value.length < options.minLength) {
|
|
64
68
|
throw new WordPressAPIError(
|
|
65
|
-
`${fieldName} must be at least ${options.minLength} characters`,
|
|
66
|
-
400,
|
|
67
|
-
"parameter_too_short"
|
|
69
|
+
`${fieldName} must be at least ${options.minLength} characters`,
|
|
70
|
+
400,
|
|
71
|
+
"parameter_too_short",
|
|
68
72
|
);
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
if (options?.maxLength && value.length > options.maxLength) {
|
|
72
76
|
throw new WordPressAPIError(
|
|
73
|
-
`${fieldName} must be no more than ${options.maxLength} characters`,
|
|
74
|
-
400,
|
|
75
|
-
"parameter_too_long"
|
|
77
|
+
`${fieldName} must be no more than ${options.maxLength} characters`,
|
|
78
|
+
400,
|
|
79
|
+
"parameter_too_long",
|
|
76
80
|
);
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
if (options?.pattern && !options.pattern.test(value)) {
|
|
80
|
-
throw new WordPressAPIError(
|
|
81
|
-
`${fieldName} format is invalid`,
|
|
82
|
-
400,
|
|
83
|
-
"invalid_parameter_format"
|
|
84
|
-
);
|
|
84
|
+
throw new WordPressAPIError(`${fieldName} format is invalid`, 400, "invalid_parameter_format");
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
return value;
|
|
@@ -90,12 +90,16 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
90
90
|
/**
|
|
91
91
|
* Validate numeric parameters
|
|
92
92
|
*/
|
|
93
|
-
validateNumber(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
validateNumber(
|
|
94
|
+
value: unknown,
|
|
95
|
+
fieldName: string,
|
|
96
|
+
options?: {
|
|
97
|
+
required?: boolean;
|
|
98
|
+
min?: number;
|
|
99
|
+
max?: number;
|
|
100
|
+
integer?: boolean;
|
|
101
|
+
},
|
|
102
|
+
): number {
|
|
99
103
|
if (options?.required && (value === undefined || value === null)) {
|
|
100
104
|
throw new WordPressAPIError(`${fieldName} is required`, 400, "missing_parameter");
|
|
101
105
|
}
|
|
@@ -115,19 +119,11 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
if (options?.min !== undefined && numValue < options.min) {
|
|
118
|
-
throw new WordPressAPIError(
|
|
119
|
-
`${fieldName} must be at least ${options.min}`,
|
|
120
|
-
400,
|
|
121
|
-
"parameter_too_small"
|
|
122
|
-
);
|
|
122
|
+
throw new WordPressAPIError(`${fieldName} must be at least ${options.min}`, 400, "parameter_too_small");
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
if (options?.max !== undefined && numValue > options.max) {
|
|
126
|
-
throw new WordPressAPIError(
|
|
127
|
-
`${fieldName} must be no more than ${options.max}`,
|
|
128
|
-
400,
|
|
129
|
-
"parameter_too_large"
|
|
130
|
-
);
|
|
126
|
+
throw new WordPressAPIError(`${fieldName} must be no more than ${options.max}`, 400, "parameter_too_large");
|
|
131
127
|
}
|
|
132
128
|
|
|
133
129
|
return numValue;
|
|
@@ -136,12 +132,16 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
136
132
|
/**
|
|
137
133
|
* Validate array parameters
|
|
138
134
|
*/
|
|
139
|
-
validateArray<T>(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
135
|
+
validateArray<T>(
|
|
136
|
+
value: unknown,
|
|
137
|
+
fieldName: string,
|
|
138
|
+
options?: {
|
|
139
|
+
required?: boolean;
|
|
140
|
+
minLength?: number;
|
|
141
|
+
maxLength?: number;
|
|
142
|
+
itemValidator?: (item: unknown) => T;
|
|
143
|
+
},
|
|
144
|
+
): T[] {
|
|
145
145
|
if (options?.required && (value === undefined || value === null)) {
|
|
146
146
|
throw new WordPressAPIError(`${fieldName} is required`, 400, "missing_parameter");
|
|
147
147
|
}
|
|
@@ -156,17 +156,17 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
156
156
|
|
|
157
157
|
if (options?.minLength && value.length < options.minLength) {
|
|
158
158
|
throw new WordPressAPIError(
|
|
159
|
-
`${fieldName} must contain at least ${options.minLength} items`,
|
|
160
|
-
400,
|
|
161
|
-
"array_too_short"
|
|
159
|
+
`${fieldName} must contain at least ${options.minLength} items`,
|
|
160
|
+
400,
|
|
161
|
+
"array_too_short",
|
|
162
162
|
);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
if (options?.maxLength && value.length > options.maxLength) {
|
|
166
166
|
throw new WordPressAPIError(
|
|
167
|
-
`${fieldName} must contain no more than ${options.maxLength} items`,
|
|
168
|
-
400,
|
|
169
|
-
"array_too_long"
|
|
167
|
+
`${fieldName} must contain no more than ${options.maxLength} items`,
|
|
168
|
+
400,
|
|
169
|
+
"array_too_long",
|
|
170
170
|
);
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -179,7 +179,7 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
179
179
|
throw new WordPressAPIError(
|
|
180
180
|
`${fieldName}[${index}] validation failed: ${getErrorMessage(error)}`,
|
|
181
181
|
400,
|
|
182
|
-
"array_item_invalid"
|
|
182
|
+
"array_item_invalid",
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
185
|
});
|
|
@@ -190,7 +190,7 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
190
190
|
throw new WordPressAPIError(
|
|
191
191
|
`${fieldName} validation failed: ${getErrorMessage(error)}`,
|
|
192
192
|
400,
|
|
193
|
-
"array_validation_failed"
|
|
193
|
+
"array_validation_failed",
|
|
194
194
|
);
|
|
195
195
|
}
|
|
196
196
|
}
|
|
@@ -205,7 +205,7 @@ export class ParameterValidatorImpl implements ParameterValidator {
|
|
|
205
205
|
const id = this.validateNumber(value, fieldName, {
|
|
206
206
|
required: true,
|
|
207
207
|
min: 1,
|
|
208
|
-
integer: true
|
|
208
|
+
integer: true,
|
|
209
209
|
});
|
|
210
210
|
|
|
211
211
|
return id;
|
|
@@ -218,4 +218,4 @@ function getErrorMessage(error: unknown): string {
|
|
|
218
218
|
return error.message;
|
|
219
219
|
}
|
|
220
220
|
return String(error);
|
|
221
|
-
}
|
|
221
|
+
}
|
|
@@ -10,7 +10,7 @@ import type { WordPressClientConfig } from "@/types/client.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export interface ConfigurationProvider {
|
|
12
12
|
readonly config: WordPressClientConfig;
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
/**
|
|
15
15
|
* Get configuration value by path
|
|
16
16
|
*/
|
|
@@ -49,12 +49,16 @@ export interface ParameterValidator {
|
|
|
49
49
|
/**
|
|
50
50
|
* Validate string parameters
|
|
51
51
|
*/
|
|
52
|
-
validateString(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
validateString(
|
|
53
|
+
value: unknown,
|
|
54
|
+
fieldName: string,
|
|
55
|
+
options?: {
|
|
56
|
+
required?: boolean;
|
|
57
|
+
minLength?: number;
|
|
58
|
+
maxLength?: number;
|
|
59
|
+
pattern?: RegExp;
|
|
60
|
+
},
|
|
61
|
+
): string;
|
|
58
62
|
|
|
59
63
|
/**
|
|
60
64
|
* Validate WordPress ID parameters
|
|
@@ -148,7 +152,7 @@ export interface ManagerFactory {
|
|
|
148
152
|
export interface ManagerCompositionConfig {
|
|
149
153
|
/** WordPress client configuration */
|
|
150
154
|
clientConfig: WordPressClientConfig;
|
|
151
|
-
|
|
155
|
+
|
|
152
156
|
/** Optional custom implementations */
|
|
153
157
|
customErrorHandler?: ErrorHandler;
|
|
154
158
|
customValidator?: ParameterValidator;
|
|
@@ -168,4 +172,4 @@ export interface ComposedManager extends BaseManagerContract, RequestHandler, Au
|
|
|
168
172
|
* Cleanup resources
|
|
169
173
|
*/
|
|
170
174
|
dispose(): void;
|
|
171
|
-
}
|
|
175
|
+
}
|
package/src/config/index.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// Main Configuration System
|
|
7
|
-
export { Config, ConfigHelpers, config } from
|
|
7
|
+
export { Config, ConfigHelpers, config } from "./Config.js";
|
|
8
8
|
|
|
9
9
|
// Configuration Schema and Validation
|
|
10
|
-
export * from
|
|
10
|
+
export * from "./ConfigurationSchema.js";
|
|
11
11
|
|
|
12
12
|
// Server Configuration (legacy)
|
|
13
|
-
export * from
|
|
13
|
+
export * from "./ServerConfiguration.js";
|
|
@@ -25,10 +25,12 @@ ${this.generateBadges()}
|
|
|
25
25
|
|
|
26
26
|
## Overview
|
|
27
27
|
|
|
28
|
-
The WordPress MCP Server provides **${summary.totalTools} tools** across **${
|
|
28
|
+
The WordPress MCP Server provides **${summary.totalTools} tools** across **${
|
|
29
|
+
summary.totalCategories
|
|
30
|
+
} categories** for comprehensive WordPress management through the Model Context Protocol.
|
|
29
31
|
|
|
30
|
-
**Last Updated:** ${new Date(summary.lastUpdated).toLocaleDateString()}
|
|
31
|
-
**Version:** ${summary.version}
|
|
32
|
+
**Last Updated:** ${new Date(summary.lastUpdated).toLocaleDateString()}
|
|
33
|
+
**Version:** ${summary.version}
|
|
32
34
|
**Coverage:** ${summary.coverage.toolsWithExamples}/${summary.totalTools} tools with examples
|
|
33
35
|
|
|
34
36
|
## Quick Start
|
|
@@ -66,7 +68,7 @@ ${this.generateToolsTable(tools)}
|
|
|
66
68
|
|
|
67
69
|
All tools support multiple authentication methods:
|
|
68
70
|
- **Application Passwords** (recommended)
|
|
69
|
-
- **JWT Authentication**
|
|
71
|
+
- **JWT Authentication**
|
|
70
72
|
- **Basic Authentication** (development only)
|
|
71
73
|
- **API Key Authentication**
|
|
72
74
|
|
|
@@ -214,7 +216,7 @@ wp_list_${category.name.toLowerCase()}
|
|
|
214
216
|
# Get specific item
|
|
215
217
|
wp_get_${category.name.toLowerCase().slice(0, -1)} --id=123
|
|
216
218
|
|
|
217
|
-
# Create new item
|
|
219
|
+
# Create new item
|
|
218
220
|
wp_create_${category.name.toLowerCase().slice(0, -1)} --title="Example"
|
|
219
221
|
\`\`\`
|
|
220
222
|
|
|
@@ -272,7 +274,9 @@ ${type.examples.length > 1 ? this.generateAdditionalExamples(type.examples.slice
|
|
|
272
274
|
const defaultVal = param.defaultValue !== undefined ? `\`${param.defaultValue}\`` : "-";
|
|
273
275
|
const required = param.required ? "✅" : "❌";
|
|
274
276
|
|
|
275
|
-
return `| \`${param.name}\` | \`${param.type}\` | ${required} | ${param.description} | ${defaultVal} | ${
|
|
277
|
+
return `| \`${param.name}\` | \`${param.type}\` | ${required} | ${param.description} | ${defaultVal} | ${
|
|
278
|
+
examples || "-"
|
|
279
|
+
} |`;
|
|
276
280
|
});
|
|
277
281
|
|
|
278
282
|
return [headers, separator, ...rows].join("\n");
|
|
@@ -375,7 +379,7 @@ ${permissions.map((perm) => `- \`${perm}\``).join("\n")}
|
|
|
375
379
|
return `### Common Errors
|
|
376
380
|
|
|
377
381
|
- **Authentication Error**: Invalid credentials or insufficient permissions
|
|
378
|
-
- **Validation Error**: Invalid or missing required parameters
|
|
382
|
+
- **Validation Error**: Invalid or missing required parameters
|
|
379
383
|
- **Not Found Error**: Requested resource does not exist
|
|
380
384
|
- **Server Error**: Internal WordPress or network error
|
|
381
385
|
|
|
@@ -386,8 +390,8 @@ See [Error Handling Guide](../error-handling.md) for complete error reference.`;
|
|
|
386
390
|
.map(
|
|
387
391
|
(error) => `### ${(error as Record<string, unknown>).code}
|
|
388
392
|
|
|
389
|
-
**Message:** ${(error as Record<string, unknown>).message}
|
|
390
|
-
**Description:** ${(error as Record<string, unknown>).description}
|
|
393
|
+
**Message:** ${(error as Record<string, unknown>).message}
|
|
394
|
+
**Description:** ${(error as Record<string, unknown>).description}
|
|
391
395
|
**Resolution:** ${(error as Record<string, unknown>).resolution}
|
|
392
396
|
`,
|
|
393
397
|
)
|
|
@@ -196,7 +196,9 @@ export class PerformanceAnalytics {
|
|
|
196
196
|
category: "optimization",
|
|
197
197
|
priority: "high",
|
|
198
198
|
title: "Improve Cache Hit Rate",
|
|
199
|
-
description: `Current cache hit rate is ${(currentMetrics.cache.hitRate * 100).toFixed(
|
|
199
|
+
description: `Current cache hit rate is ${(currentMetrics.cache.hitRate * 100).toFixed(
|
|
200
|
+
1,
|
|
201
|
+
)}%, which is below optimal performance.`,
|
|
200
202
|
impact: "performance",
|
|
201
203
|
recommendation: "Implement cache warming strategies and optimize TTL values for frequently accessed data.",
|
|
202
204
|
estimatedImprovement: "20-40% reduction in response times",
|
|
@@ -212,7 +214,9 @@ export class PerformanceAnalytics {
|
|
|
212
214
|
category: "optimization",
|
|
213
215
|
priority: "high",
|
|
214
216
|
title: "Reduce Response Times",
|
|
215
|
-
description: `Average response time of ${currentMetrics.requests.averageResponseTime.toFixed(
|
|
217
|
+
description: `Average response time of ${currentMetrics.requests.averageResponseTime.toFixed(
|
|
218
|
+
0,
|
|
219
|
+
)}ms is above recommended threshold.`,
|
|
216
220
|
impact: "user_experience",
|
|
217
221
|
recommendation: "Enable aggressive caching, optimize database queries, or consider upgrading server resources.",
|
|
218
222
|
estimatedImprovement: "50-70% reduction in response times",
|
|
@@ -249,7 +253,9 @@ export class PerformanceAnalytics {
|
|
|
249
253
|
category: "optimization",
|
|
250
254
|
priority: "low",
|
|
251
255
|
title: "Optimize Frequently Used Tools",
|
|
252
|
-
description: `Most used tools: ${mostUsed
|
|
256
|
+
description: `Most used tools: ${mostUsed
|
|
257
|
+
.map(([tool]) => tool)
|
|
258
|
+
.join(", ")}. Consider optimizing these workflows.`,
|
|
253
259
|
impact: "performance",
|
|
254
260
|
recommendation: "Create cached workflows or batch operations for frequently used tools.",
|
|
255
261
|
estimatedImprovement: "10-20% reduction in API calls",
|
|
@@ -175,7 +175,7 @@ export function validateSecurity(schema: z.ZodSchema) {
|
|
|
175
175
|
logger.info(`Security validation passed for ${propertyName}`, {
|
|
176
176
|
timestamp: new Date().toISOString(),
|
|
177
177
|
method: propertyName,
|
|
178
|
-
paramCount: typeof validatedParams ===
|
|
178
|
+
paramCount: typeof validatedParams === "object" && validatedParams ? Object.keys(validatedParams).length : 0,
|
|
179
179
|
});
|
|
180
180
|
|
|
181
181
|
// Call original method with validated params
|
|
@@ -237,7 +237,7 @@ export class SecurityCIPipeline {
|
|
|
237
237
|
try {
|
|
238
238
|
const scanPromise = scanner.scanCodeForVulnerabilities
|
|
239
239
|
? scanner.scanCodeForVulnerabilities()
|
|
240
|
-
:
|
|
240
|
+
: scanner.performScan?.() ?? Promise.resolve({ vulnerabilities: [], riskScore: 0 });
|
|
241
241
|
|
|
242
242
|
if (opts.timeout && opts.timeout > 0) {
|
|
243
243
|
const res = await Promise.race([
|
|
@@ -190,7 +190,9 @@ export class SecurityUtils {
|
|
|
190
190
|
return obj;
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
const working: Record<string, unknown> | unknown[] = Array.isArray(obj)
|
|
193
|
+
const working: Record<string, unknown> | unknown[] = Array.isArray(obj)
|
|
194
|
+
? [...obj]
|
|
195
|
+
: { ...(obj as Record<string, unknown>) };
|
|
194
196
|
|
|
195
197
|
if (Array.isArray(working)) {
|
|
196
198
|
return working.map((val) => (typeof val === "object" ? SecurityUtils.redactSensitiveData(val) : val));
|
|
@@ -276,8 +278,12 @@ export function createSecureError(
|
|
|
276
278
|
const secureError = new Error(fallbackMessage);
|
|
277
279
|
|
|
278
280
|
// Preserve error code if it's safe
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
+
if (
|
|
282
|
+
error &&
|
|
283
|
+
typeof (error as { code?: unknown }).code === "string" &&
|
|
284
|
+
!(error as { code: string }).code.includes("_")
|
|
285
|
+
) {
|
|
286
|
+
(secureError as unknown as Record<string, unknown>).code = (error as { code: string }).code;
|
|
281
287
|
}
|
|
282
288
|
|
|
283
289
|
return secureError;
|