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.
- package/README.md +210 -182
- package/dist/cache/CacheInvalidation.d.ts +3 -3
- package/dist/cache/CacheInvalidation.d.ts.map +1 -1
- package/dist/cache/CacheInvalidation.js +119 -119
- package/dist/cache/CacheInvalidation.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +5 -0
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +26 -16
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/HttpCacheWrapper.d.ts +1 -1
- package/dist/cache/HttpCacheWrapper.d.ts.map +1 -1
- package/dist/cache/HttpCacheWrapper.js +29 -29
- package/dist/cache/HttpCacheWrapper.js.map +1 -1
- package/dist/cache/__tests__/CacheInvalidation.test.js +96 -94
- package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -1
- package/dist/cache/__tests__/CacheManager.test.js +113 -113
- package/dist/cache/__tests__/CacheManager.test.js.map +1 -1
- package/dist/cache/__tests__/CachedWordPressClient.test.js +102 -99
- package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -1
- package/dist/cache/__tests__/HttpCacheWrapper.test.js +98 -95
- package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -1
- package/dist/cache/index.d.ts +7 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +4 -4
- package/dist/cache/index.js.map +1 -1
- package/dist/client/CachedWordPressClient.d.ts +4 -4
- package/dist/client/CachedWordPressClient.d.ts.map +1 -1
- package/dist/client/CachedWordPressClient.js +55 -51
- package/dist/client/CachedWordPressClient.js.map +1 -1
- package/dist/client/api.d.ts +10 -10
- package/dist/client/api.js +158 -158
- package/dist/client/api.js.map +1 -1
- package/dist/client/auth.d.ts +2 -2
- package/dist/client/auth.js +72 -72
- package/dist/client/managers/AuthenticationManager.d.ts +2 -2
- package/dist/client/managers/AuthenticationManager.js +46 -46
- package/dist/client/managers/BaseManager.d.ts +1 -1
- package/dist/client/managers/BaseManager.js +9 -9
- package/dist/client/managers/RequestManager.d.ts +5 -3
- package/dist/client/managers/RequestManager.d.ts.map +1 -1
- package/dist/client/managers/RequestManager.js +39 -19
- package/dist/client/managers/RequestManager.js.map +1 -1
- package/dist/client/managers/index.d.ts +3 -3
- package/dist/client/managers/index.js +3 -3
- package/dist/config/ConfigurationSchema.d.ts +2 -2
- package/dist/config/ConfigurationSchema.d.ts.map +1 -1
- package/dist/config/ConfigurationSchema.js +40 -40
- package/dist/config/ConfigurationSchema.js.map +1 -1
- package/dist/config/ServerConfiguration.d.ts +2 -2
- package/dist/config/ServerConfiguration.js +35 -35
- package/dist/config/ServerConfiguration.js.map +1 -1
- package/dist/docs/DocumentationGenerator.d.ts.map +1 -1
- package/dist/docs/DocumentationGenerator.js +296 -255
- package/dist/docs/DocumentationGenerator.js.map +1 -1
- package/dist/docs/MarkdownFormatter.d.ts +1 -1
- package/dist/docs/MarkdownFormatter.d.ts.map +1 -1
- package/dist/docs/MarkdownFormatter.js +60 -51
- package/dist/docs/MarkdownFormatter.js.map +1 -1
- package/dist/docs/index.d.ts +3 -3
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp-wordpress-1.3.0.tgz +0 -0
- package/dist/performance/MetricsCollector.d.ts +3 -3
- package/dist/performance/MetricsCollector.d.ts.map +1 -1
- package/dist/performance/MetricsCollector.js +33 -27
- package/dist/performance/MetricsCollector.js.map +1 -1
- package/dist/performance/PerformanceAnalytics.d.ts +12 -12
- package/dist/performance/PerformanceAnalytics.d.ts.map +1 -1
- package/dist/performance/PerformanceAnalytics.js +200 -154
- package/dist/performance/PerformanceAnalytics.js.map +1 -1
- package/dist/performance/PerformanceMonitor.d.ts +5 -5
- package/dist/performance/PerformanceMonitor.d.ts.map +1 -1
- package/dist/performance/PerformanceMonitor.js +53 -52
- package/dist/performance/PerformanceMonitor.js.map +1 -1
- package/dist/performance/index.d.ts +6 -6
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/performance/index.js +3 -3
- package/dist/security/InputValidator.d.ts +1 -1
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +111 -88
- package/dist/security/InputValidator.js.map +1 -1
- package/dist/security/SecurityConfig.d.ts +5 -5
- package/dist/security/SecurityConfig.js +92 -92
- package/dist/security/SecurityConfig.js.map +1 -1
- package/dist/server/ConnectionTester.d.ts +1 -1
- package/dist/server/ConnectionTester.d.ts.map +1 -1
- package/dist/server/ConnectionTester.js +4 -4
- package/dist/server/ConnectionTester.js.map +1 -1
- package/dist/server/ToolRegistry.d.ts +2 -2
- package/dist/server/ToolRegistry.d.ts.map +1 -1
- package/dist/server/ToolRegistry.js +35 -32
- package/dist/server/ToolRegistry.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/tools/BaseToolManager.js +5 -5
- package/dist/tools/auth.d.ts +2 -2
- package/dist/tools/auth.d.ts.map +1 -1
- package/dist/tools/auth.js +32 -31
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/cache.d.ts +1 -1
- package/dist/tools/cache.d.ts.map +1 -1
- package/dist/tools/cache.js +71 -71
- package/dist/tools/cache.js.map +1 -1
- package/dist/tools/comments.d.ts +2 -2
- package/dist/tools/comments.d.ts.map +1 -1
- package/dist/tools/comments.js +79 -79
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/index.d.ts +10 -10
- package/dist/tools/index.js +10 -10
- package/dist/tools/media.d.ts +2 -2
- package/dist/tools/media.js +80 -80
- package/dist/tools/pages.d.ts +2 -2
- package/dist/tools/pages.d.ts.map +1 -1
- package/dist/tools/pages.js +75 -75
- package/dist/tools/pages.js.map +1 -1
- package/dist/tools/performance.d.ts +1 -1
- package/dist/tools/performance.d.ts.map +1 -1
- package/dist/tools/performance.js +311 -287
- package/dist/tools/performance.js.map +1 -1
- package/dist/tools/posts.d.ts +2 -2
- package/dist/tools/posts.d.ts.map +1 -1
- package/dist/tools/posts.js +94 -94
- package/dist/tools/posts.js.map +1 -1
- package/dist/tools/site.d.ts +2 -2
- package/dist/tools/site.d.ts.map +1 -1
- package/dist/tools/site.js +60 -60
- package/dist/tools/site.js.map +1 -1
- package/dist/tools/taxonomies.d.ts +2 -2
- package/dist/tools/taxonomies.js +89 -89
- package/dist/tools/users.d.ts +2 -2
- package/dist/tools/users.js +68 -68
- package/dist/tools/users.js.map +1 -1
- package/dist/types/client.d.ts +13 -13
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/client.js +12 -12
- package/dist/types/client.js.map +1 -1
- package/dist/types/index.d.ts +19 -19
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -3
- package/dist/types/mcp.d.ts +7 -7
- package/dist/types/wordpress.d.ts +21 -21
- package/dist/types/wordpress.d.ts.map +1 -1
- package/dist/utils/debug.d.ts +2 -2
- package/dist/utils/debug.js +28 -28
- package/dist/utils/error.d.ts.map +1 -1
- package/dist/utils/error.js +13 -13
- package/dist/utils/error.js.map +1 -1
- package/dist/utils/toolWrapper.d.ts.map +1 -1
- package/dist/utils/toolWrapper.js +5 -5
- package/dist/utils/toolWrapper.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +41 -31
- package/dist/utils/validation.js.map +1 -1
- package/docs/CACHING.md +36 -2
- package/docs/DOCKER.md +24 -18
- package/docs/PERFORMANCE_MONITORING.md +49 -1
- package/docs/SECURITY_TESTING.md +30 -1
- package/docs/api/README.md +9 -1
- package/docs/api/summary.json +1 -1
- package/docs/contract-testing.md +24 -3
- package/docs/developer/GITHUB_ACTIONS_SETUP.md +8 -2
- package/docs/developer/MAINTENANCE.md +29 -3
- package/docs/developer/MIGRATION_GUIDE.md +13 -1
- package/docs/developer/NPM_AUTH_SETUP.md +13 -2
- package/docs/developer/REFACTORING.md +31 -1
- package/docs/releases/COMMUNITY_ANNOUNCEMENT_v1.1.2.md +18 -7
- package/docs/releases/RELEASE_NOTES_v1.1.2.md +31 -5
- package/docs/user-guides/DOCKER_SETUP.md +264 -0
- package/docs/user-guides/DTX_SETUP.md +327 -0
- package/docs/user-guides/NPM_SETUP.md +109 -0
- package/docs/user-guides/NPX_SETUP.md +281 -0
- package/docs/wordpress-rest-api-authentication-troubleshooting.md +13 -2
- package/package.json +27 -8
- package/src/cache/CacheInvalidation.ts +140 -132
- package/src/cache/CacheManager.ts +40 -29
- package/src/cache/HttpCacheWrapper.ts +105 -68
- package/src/cache/__tests__/CacheInvalidation.test.ts +123 -118
- package/src/cache/__tests__/CacheManager.test.ts +156 -152
- package/src/cache/__tests__/CachedWordPressClient.test.ts +131 -116
- package/src/cache/__tests__/HttpCacheWrapper.test.ts +118 -115
- package/src/cache/index.ts +13 -13
- package/src/client/CachedWordPressClient.ts +90 -80
- package/src/client/api.ts +205 -205
- package/src/client/auth.ts +80 -80
- package/src/client/managers/AuthenticationManager.ts +61 -61
- package/src/client/managers/BaseManager.ts +11 -11
- package/src/client/managers/RequestManager.ts +79 -47
- package/src/client/managers/index.ts +3 -3
- package/src/config/ConfigurationSchema.ts +44 -44
- package/src/config/ServerConfiguration.ts +39 -39
- package/src/docs/DocumentationGenerator.ts +402 -295
- package/src/docs/MarkdownFormatter.ts +94 -69
- package/src/docs/index.ts +4 -4
- package/src/index.ts +24 -21
- package/src/performance/MetricsCollector.ts +90 -58
- package/src/performance/PerformanceAnalytics.ts +386 -262
- package/src/performance/PerformanceMonitor.ts +152 -118
- package/src/performance/index.ts +9 -9
- package/src/security/InputValidator.ts +148 -91
- package/src/security/SecurityConfig.ts +94 -94
- package/src/server/ConnectionTester.ts +21 -15
- package/src/server/ToolRegistry.ts +64 -51
- package/src/server.ts +2 -2
- package/src/tools/BaseToolManager.ts +6 -6
- package/src/tools/auth.ts +42 -37
- package/src/tools/cache.ts +85 -81
- package/src/tools/comments.ts +93 -91
- package/src/tools/index.ts +10 -10
- package/src/tools/media.ts +89 -89
- package/src/tools/pages.ts +89 -87
- package/src/tools/performance.ts +443 -352
- package/src/tools/posts.ts +109 -107
- package/src/tools/site.ts +86 -77
- package/src/tools/taxonomies.ts +102 -102
- package/src/tools/users.ts +77 -77
- package/src/types/client.ts +157 -60
- package/src/types/index.ts +49 -27
- package/src/types/mcp.ts +15 -15
- package/src/types/wordpress.ts +57 -29
- package/src/utils/debug.ts +37 -37
- package/src/utils/error.ts +47 -25
- package/src/utils/toolWrapper.ts +12 -8
- package/src/utils/validation.ts +116 -65
- package/dist/client/WordPressClient.d.ts +0 -81
- package/dist/client/WordPressClient.d.ts.map +0 -1
- package/dist/client/WordPressClient.js +0 -354
- package/dist/client/WordPressClient.js.map +0 -1
- package/dist/performance/AnomalyDetector.d.ts +0 -63
- package/dist/performance/AnomalyDetector.d.ts.map +0 -1
- package/dist/performance/AnomalyDetector.js +0 -222
- package/dist/performance/AnomalyDetector.js.map +0 -1
- package/dist/performance/BenchmarkAnalyzer.d.ts +0 -67
- package/dist/performance/BenchmarkAnalyzer.d.ts.map +0 -1
- package/dist/performance/BenchmarkAnalyzer.js +0 -301
- package/dist/performance/BenchmarkAnalyzer.js.map +0 -1
- package/dist/performance/TrendAnalyzer.d.ts +0 -69
- package/dist/performance/TrendAnalyzer.d.ts.map +0 -1
- package/dist/performance/TrendAnalyzer.js +0 -203
- package/dist/performance/TrendAnalyzer.js.map +0 -1
- package/dist/tools/BaseToolClass.d.ts +0 -76
- package/dist/tools/BaseToolClass.d.ts.map +0 -1
- package/dist/tools/BaseToolClass.js +0 -104
- package/dist/tools/BaseToolClass.js.map +0 -1
- package/dist/tools/base.d.ts +0 -37
- package/dist/tools/base.d.ts.map +0 -1
- package/dist/tools/base.js +0 -60
- package/dist/tools/base.js.map +0 -1
- package/docs/user-guides/CLAUDE_DESKTOP_SETUP.md +0 -187
|
@@ -2,68 +2,68 @@
|
|
|
2
2
|
* Security configuration and constants for MCP WordPress
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { randomBytes } from
|
|
5
|
+
import { randomBytes } from "crypto";
|
|
6
6
|
|
|
7
7
|
export const SecurityConfig = {
|
|
8
8
|
// Rate limiting
|
|
9
9
|
rateLimiting: {
|
|
10
10
|
default: {
|
|
11
11
|
windowMs: 60 * 1000, // 1 minute
|
|
12
|
-
maxRequests: 60
|
|
12
|
+
maxRequests: 60,
|
|
13
13
|
},
|
|
14
14
|
authentication: {
|
|
15
15
|
windowMs: 5 * 60 * 1000, // 5 minutes
|
|
16
|
-
maxAttempts: 5
|
|
16
|
+
maxAttempts: 5,
|
|
17
17
|
},
|
|
18
18
|
upload: {
|
|
19
19
|
windowMs: 60 * 1000, // 1 minute
|
|
20
|
-
maxRequests: 10
|
|
21
|
-
}
|
|
20
|
+
maxRequests: 10,
|
|
21
|
+
},
|
|
22
22
|
},
|
|
23
23
|
|
|
24
24
|
// File upload restrictions
|
|
25
25
|
fileUpload: {
|
|
26
26
|
maxSizeMB: 10,
|
|
27
27
|
allowedMimeTypes: [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
"image/jpeg",
|
|
29
|
+
"image/png",
|
|
30
|
+
"image/gif",
|
|
31
|
+
"image/webp",
|
|
32
|
+
"image/svg+xml",
|
|
33
|
+
"application/pdf",
|
|
34
|
+
"application/msword",
|
|
35
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
36
|
+
"application/vnd.ms-excel",
|
|
37
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
38
|
+
"text/plain",
|
|
39
|
+
"text/csv",
|
|
40
40
|
],
|
|
41
41
|
// Dangerous file extensions to block
|
|
42
42
|
blockedExtensions: [
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
]
|
|
43
|
+
".exe",
|
|
44
|
+
".bat",
|
|
45
|
+
".cmd",
|
|
46
|
+
".com",
|
|
47
|
+
".pif",
|
|
48
|
+
".scr",
|
|
49
|
+
".vbs",
|
|
50
|
+
".js",
|
|
51
|
+
".jar",
|
|
52
|
+
".zip",
|
|
53
|
+
".rar",
|
|
54
|
+
".tar",
|
|
55
|
+
".php",
|
|
56
|
+
".php3",
|
|
57
|
+
".php4",
|
|
58
|
+
".php5",
|
|
59
|
+
".phtml",
|
|
60
|
+
".sh",
|
|
61
|
+
".bash",
|
|
62
|
+
".zsh",
|
|
63
|
+
".fish",
|
|
64
|
+
".ps1",
|
|
65
|
+
".psm1",
|
|
66
|
+
],
|
|
67
67
|
},
|
|
68
68
|
|
|
69
69
|
// Input validation
|
|
@@ -76,58 +76,58 @@ export const SecurityConfig = {
|
|
|
76
76
|
maxUsernameLength: 60,
|
|
77
77
|
minUsernameLength: 3,
|
|
78
78
|
maxPasswordLength: 128,
|
|
79
|
-
minPasswordLength: 8
|
|
79
|
+
minPasswordLength: 8,
|
|
80
80
|
},
|
|
81
81
|
|
|
82
82
|
// Request timeouts (milliseconds)
|
|
83
83
|
timeouts: {
|
|
84
84
|
default: 30000, // 30 seconds
|
|
85
85
|
upload: 600000, // 10 minutes
|
|
86
|
-
auth: 10000 // 10 seconds
|
|
86
|
+
auth: 10000, // 10 seconds
|
|
87
87
|
},
|
|
88
88
|
|
|
89
89
|
// Security headers
|
|
90
90
|
headers: {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
"X-Content-Type-Options": "nosniff",
|
|
92
|
+
"X-Frame-Options": "DENY",
|
|
93
|
+
"X-XSS-Protection": "1; mode=block",
|
|
94
|
+
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
|
|
95
|
+
"Content-Security-Policy": "default-src 'self'",
|
|
96
96
|
},
|
|
97
97
|
|
|
98
98
|
// Error messages (generic to avoid information disclosure)
|
|
99
99
|
errorMessages: {
|
|
100
|
-
authentication:
|
|
101
|
-
authorization:
|
|
102
|
-
validation:
|
|
103
|
-
rateLimit:
|
|
104
|
-
serverError:
|
|
105
|
-
notFound:
|
|
100
|
+
authentication: "Authentication failed. Please check your credentials.",
|
|
101
|
+
authorization: "You do not have permission to perform this action.",
|
|
102
|
+
validation: "Invalid input provided.",
|
|
103
|
+
rateLimit: "Too many requests. Please try again later.",
|
|
104
|
+
serverError: "An error occurred processing your request.",
|
|
105
|
+
notFound: "The requested resource was not found.",
|
|
106
106
|
},
|
|
107
107
|
|
|
108
108
|
// Logging configuration
|
|
109
109
|
logging: {
|
|
110
110
|
// Fields to exclude from logs
|
|
111
111
|
excludeFields: [
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
112
|
+
"password",
|
|
113
|
+
"appPassword",
|
|
114
|
+
"app_password",
|
|
115
|
+
"token",
|
|
116
|
+
"secret",
|
|
117
|
+
"authorization",
|
|
118
|
+
"cookie",
|
|
119
|
+
"session",
|
|
120
|
+
"key",
|
|
121
|
+
"apiKey",
|
|
122
|
+
"api_key",
|
|
123
123
|
],
|
|
124
124
|
// Patterns to redact in log messages
|
|
125
125
|
redactPatterns: [
|
|
126
126
|
/password["\s:=]+["']?([^"'\s]+)["']?/gi,
|
|
127
127
|
/token["\s:=]+["']?([^"'\s]+)["']?/gi,
|
|
128
128
|
/secret["\s:=]+["']?([^"'\s]+)["']?/gi,
|
|
129
|
-
/key["\s:=]+["']?([^"'\s]+)["']?/gi
|
|
130
|
-
]
|
|
129
|
+
/key["\s:=]+["']?([^"'\s]+)["']?/gi,
|
|
130
|
+
],
|
|
131
131
|
},
|
|
132
132
|
|
|
133
133
|
// Cache configuration
|
|
@@ -145,16 +145,16 @@ export const SecurityConfig = {
|
|
|
145
145
|
semiStatic: 2 * 60 * 60 * 1000, // 2 hours - categories, tags, user profiles
|
|
146
146
|
dynamic: 15 * 60 * 1000, // 15 minutes - posts, pages, comments
|
|
147
147
|
session: 30 * 60 * 1000, // 30 minutes - authentication, current user
|
|
148
|
-
realtime: 60 * 1000 // 1 minute - real-time data
|
|
148
|
+
realtime: 60 * 1000, // 1 minute - real-time data
|
|
149
149
|
},
|
|
150
150
|
|
|
151
151
|
// Cache-Control headers by data type
|
|
152
152
|
cacheHeaders: {
|
|
153
|
-
static:
|
|
154
|
-
semiStatic:
|
|
155
|
-
dynamic:
|
|
156
|
-
session:
|
|
157
|
-
realtime:
|
|
153
|
+
static: "public, max-age=14400", // 4 hours
|
|
154
|
+
semiStatic: "public, max-age=7200", // 2 hours
|
|
155
|
+
dynamic: "public, max-age=900", // 15 minutes
|
|
156
|
+
session: "private, max-age=1800", // 30 minutes
|
|
157
|
+
realtime: "public, max-age=60", // 1 minute
|
|
158
158
|
},
|
|
159
159
|
|
|
160
160
|
// Invalidation settings
|
|
@@ -162,16 +162,16 @@ export const SecurityConfig = {
|
|
|
162
162
|
enabled: true,
|
|
163
163
|
batchSize: 100, // Max events to process in one batch
|
|
164
164
|
queueTimeout: 5000, // Max time to wait before processing queue (ms)
|
|
165
|
-
enableCascading: true // Allow cascading invalidations
|
|
165
|
+
enableCascading: true, // Allow cascading invalidations
|
|
166
166
|
},
|
|
167
167
|
|
|
168
168
|
// Memory management
|
|
169
169
|
cleanup: {
|
|
170
170
|
interval: 60 * 1000, // Cleanup interval in milliseconds (1 minute)
|
|
171
171
|
maxMemoryMB: 50, // Maximum memory usage for cache
|
|
172
|
-
evictionThreshold: 0.8 // Start evicting when 80% full
|
|
173
|
-
}
|
|
174
|
-
}
|
|
172
|
+
evictionThreshold: 0.8, // Start evicting when 80% full
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
175
|
};
|
|
176
176
|
|
|
177
177
|
/**
|
|
@@ -182,7 +182,7 @@ export class SecurityUtils {
|
|
|
182
182
|
* Redact sensitive information from objects
|
|
183
183
|
*/
|
|
184
184
|
static redactSensitiveData(obj: any): any {
|
|
185
|
-
if (typeof obj !==
|
|
185
|
+
if (typeof obj !== "object" || obj === null) {
|
|
186
186
|
return obj;
|
|
187
187
|
}
|
|
188
188
|
|
|
@@ -191,11 +191,11 @@ export class SecurityUtils {
|
|
|
191
191
|
for (const key in redacted) {
|
|
192
192
|
if (
|
|
193
193
|
SecurityConfig.logging.excludeFields.some((field) =>
|
|
194
|
-
key.toLowerCase().includes(field.toLowerCase())
|
|
194
|
+
key.toLowerCase().includes(field.toLowerCase()),
|
|
195
195
|
)
|
|
196
196
|
) {
|
|
197
|
-
redacted[key] =
|
|
198
|
-
} else if (typeof redacted[key] ===
|
|
197
|
+
redacted[key] = "[REDACTED]";
|
|
198
|
+
} else if (typeof redacted[key] === "object") {
|
|
199
199
|
redacted[key] = SecurityUtils.redactSensitiveData(redacted[key]);
|
|
200
200
|
}
|
|
201
201
|
}
|
|
@@ -210,7 +210,7 @@ export class SecurityUtils {
|
|
|
210
210
|
let redacted = str;
|
|
211
211
|
for (const pattern of SecurityConfig.logging.redactPatterns) {
|
|
212
212
|
redacted = redacted.replace(pattern, (match, value) => {
|
|
213
|
-
return match.replace(value,
|
|
213
|
+
return match.replace(value, "[REDACTED]");
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
216
|
return redacted;
|
|
@@ -221,10 +221,10 @@ export class SecurityUtils {
|
|
|
221
221
|
*/
|
|
222
222
|
static generateSecureToken(length: number = 32): string {
|
|
223
223
|
const chars =
|
|
224
|
-
|
|
224
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
225
225
|
const array = new Uint8Array(length);
|
|
226
226
|
|
|
227
|
-
if (typeof crypto !==
|
|
227
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
228
228
|
crypto.getRandomValues(array);
|
|
229
229
|
} else {
|
|
230
230
|
// Fallback for Node.js
|
|
@@ -232,7 +232,7 @@ export class SecurityUtils {
|
|
|
232
232
|
array.set(buffer);
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
return Array.from(array, (byte) => chars[byte % chars.length]).join(
|
|
235
|
+
return Array.from(array, (byte) => chars[byte % chars.length]).join("");
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
/**
|
|
@@ -247,10 +247,10 @@ export class SecurityUtils {
|
|
|
247
247
|
* Sanitize log output
|
|
248
248
|
*/
|
|
249
249
|
static sanitizeForLog(data: any): any {
|
|
250
|
-
if (typeof data ===
|
|
250
|
+
if (typeof data === "string") {
|
|
251
251
|
return SecurityUtils.redactString(data);
|
|
252
252
|
}
|
|
253
|
-
if (typeof data ===
|
|
253
|
+
if (typeof data === "object") {
|
|
254
254
|
return SecurityUtils.redactSensitiveData(data);
|
|
255
255
|
}
|
|
256
256
|
return data;
|
|
@@ -262,18 +262,18 @@ export class SecurityUtils {
|
|
|
262
262
|
*/
|
|
263
263
|
export function createSecureError(
|
|
264
264
|
error: any,
|
|
265
|
-
fallbackMessage: string = SecurityConfig.errorMessages.serverError
|
|
265
|
+
fallbackMessage: string = SecurityConfig.errorMessages.serverError,
|
|
266
266
|
): Error {
|
|
267
267
|
// Log the actual error for debugging (with sanitization)
|
|
268
|
-
if (process.env.NODE_ENV !==
|
|
269
|
-
console.error(
|
|
268
|
+
if (process.env.NODE_ENV !== "production") {
|
|
269
|
+
console.error("Secure Error:", SecurityUtils.sanitizeForLog(error));
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
// Return generic error to prevent information disclosure
|
|
273
273
|
const secureError = new Error(fallbackMessage);
|
|
274
274
|
|
|
275
275
|
// Preserve error code if it's safe
|
|
276
|
-
if (error && typeof error.code ===
|
|
276
|
+
if (error && typeof error.code === "string" && !error.code.includes("_")) {
|
|
277
277
|
(secureError as any).code = error.code;
|
|
278
278
|
}
|
|
279
279
|
|
|
@@ -281,7 +281,7 @@ export function createSecureError(
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
// Import path for file extension checking
|
|
284
|
-
import * as path from
|
|
284
|
+
import * as path from "path";
|
|
285
285
|
|
|
286
286
|
/**
|
|
287
287
|
* Environment-specific security settings
|
|
@@ -291,11 +291,11 @@ export function getEnvironmentSecurity(): {
|
|
|
291
291
|
verboseErrors: boolean;
|
|
292
292
|
enforceHttps: boolean;
|
|
293
293
|
} {
|
|
294
|
-
const isProduction = process.env.NODE_ENV ===
|
|
294
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
295
295
|
|
|
296
296
|
return {
|
|
297
297
|
strictMode: isProduction,
|
|
298
298
|
verboseErrors: !isProduction,
|
|
299
|
-
enforceHttps: isProduction
|
|
299
|
+
enforceHttps: isProduction,
|
|
300
300
|
};
|
|
301
301
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { WordPressClient } from
|
|
2
|
-
import { getErrorMessage } from
|
|
1
|
+
import { WordPressClient } from "../client/api.js";
|
|
2
|
+
import { getErrorMessage } from "../utils/error.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Service for testing WordPress client connections
|
|
@@ -10,27 +10,33 @@ export class ConnectionTester {
|
|
|
10
10
|
* Test connections to all configured WordPress sites
|
|
11
11
|
*/
|
|
12
12
|
public static async testClientConnections(
|
|
13
|
-
wordpressClients: Map<string, WordPressClient
|
|
13
|
+
wordpressClients: Map<string, WordPressClient>,
|
|
14
14
|
): Promise<void> {
|
|
15
|
-
console.error(
|
|
16
|
-
|
|
15
|
+
console.error(
|
|
16
|
+
"INFO: Testing connections to all configured WordPress sites...",
|
|
17
|
+
);
|
|
18
|
+
|
|
17
19
|
const connectionPromises = Array.from(wordpressClients.entries()).map(
|
|
18
20
|
async ([siteId, client]) => {
|
|
19
21
|
try {
|
|
20
22
|
await client.ping();
|
|
21
23
|
console.error(`SUCCESS: Connection to site '${siteId}' successful.`);
|
|
22
24
|
} catch (error) {
|
|
23
|
-
console.error(
|
|
24
|
-
|
|
25
|
+
console.error(
|
|
26
|
+
`ERROR: Failed to connect to site '${siteId}': ${getErrorMessage(error)}`,
|
|
27
|
+
);
|
|
28
|
+
|
|
25
29
|
if (ConnectionTester.isAuthenticationError(error)) {
|
|
26
|
-
console.error(
|
|
30
|
+
console.error(
|
|
31
|
+
`Authentication may have failed for site '${siteId}'. Please check credentials.`,
|
|
32
|
+
);
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
|
-
}
|
|
35
|
+
},
|
|
30
36
|
);
|
|
31
|
-
|
|
37
|
+
|
|
32
38
|
await Promise.all(connectionPromises);
|
|
33
|
-
console.error(
|
|
39
|
+
console.error("INFO: Connection tests complete.");
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
/**
|
|
@@ -40,7 +46,7 @@ export class ConnectionTester {
|
|
|
40
46
|
if (error?.response?.status && [401, 403].includes(error.response.status)) {
|
|
41
47
|
return true;
|
|
42
48
|
}
|
|
43
|
-
return error?.code ===
|
|
49
|
+
return error?.code === "WORDPRESS_AUTH_ERROR";
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
/**
|
|
@@ -60,15 +66,15 @@ export class ConnectionTester {
|
|
|
60
66
|
* Perform health checks for all clients
|
|
61
67
|
*/
|
|
62
68
|
public static async healthCheckAll(
|
|
63
|
-
wordpressClients: Map<string, WordPressClient
|
|
69
|
+
wordpressClients: Map<string, WordPressClient>,
|
|
64
70
|
): Promise<Map<string, boolean>> {
|
|
65
71
|
const results = new Map<string, boolean>();
|
|
66
|
-
|
|
72
|
+
|
|
67
73
|
for (const [siteId, client] of wordpressClients.entries()) {
|
|
68
74
|
const isHealthy = await ConnectionTester.healthCheck(client);
|
|
69
75
|
results.set(siteId, isHealthy);
|
|
70
76
|
}
|
|
71
|
-
|
|
77
|
+
|
|
72
78
|
return results;
|
|
73
79
|
}
|
|
74
80
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { McpServer } from
|
|
2
|
-
import { WordPressClient } from
|
|
3
|
-
import { getErrorMessage } from
|
|
4
|
-
import * as Tools from
|
|
5
|
-
import { z } from
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { WordPressClient } from "../client/api.js";
|
|
3
|
+
import { getErrorMessage } from "../utils/error.js";
|
|
4
|
+
import * as Tools from "../tools/index.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Interface for tool definition
|
|
@@ -27,7 +27,10 @@ export class ToolRegistry {
|
|
|
27
27
|
private server: McpServer;
|
|
28
28
|
private wordpressClients: Map<string, WordPressClient>;
|
|
29
29
|
|
|
30
|
-
constructor(
|
|
30
|
+
constructor(
|
|
31
|
+
server: McpServer,
|
|
32
|
+
wordpressClients: Map<string, WordPressClient>,
|
|
33
|
+
) {
|
|
31
34
|
this.server = server;
|
|
32
35
|
this.wordpressClients = wordpressClients;
|
|
33
36
|
}
|
|
@@ -39,14 +42,17 @@ export class ToolRegistry {
|
|
|
39
42
|
// Register all tools from the tools directory
|
|
40
43
|
Object.values(Tools).forEach((ToolClass) => {
|
|
41
44
|
let toolInstance: any;
|
|
42
|
-
|
|
45
|
+
|
|
43
46
|
// Cache and Performance tools need the clients map
|
|
44
|
-
if (
|
|
47
|
+
if (
|
|
48
|
+
ToolClass.name === "CacheTools" ||
|
|
49
|
+
ToolClass.name === "PerformanceTools"
|
|
50
|
+
) {
|
|
45
51
|
toolInstance = new ToolClass(this.wordpressClients);
|
|
46
52
|
} else {
|
|
47
53
|
toolInstance = new (ToolClass as new () => any)();
|
|
48
54
|
}
|
|
49
|
-
|
|
55
|
+
|
|
50
56
|
const tools = toolInstance.getTools();
|
|
51
57
|
|
|
52
58
|
tools.forEach((tool: ToolDefinition) => {
|
|
@@ -65,8 +71,8 @@ export class ToolRegistry {
|
|
|
65
71
|
.string()
|
|
66
72
|
.optional()
|
|
67
73
|
.describe(
|
|
68
|
-
|
|
69
|
-
)
|
|
74
|
+
"The ID of the WordPress site to target (from mcp-wordpress.config.json). Required if multiple sites are configured.",
|
|
75
|
+
),
|
|
70
76
|
};
|
|
71
77
|
|
|
72
78
|
// Merge with tool-specific parameters
|
|
@@ -75,7 +81,7 @@ export class ToolRegistry {
|
|
|
75
81
|
// Make site parameter required if multiple sites are configured
|
|
76
82
|
if (this.wordpressClients.size > 1) {
|
|
77
83
|
parameterSchema.site = parameterSchema.site.describe(
|
|
78
|
-
|
|
84
|
+
"The ID of the WordPress site to target (from mcp-wordpress.config.json). Required when multiple sites are configured.",
|
|
79
85
|
);
|
|
80
86
|
}
|
|
81
87
|
|
|
@@ -85,19 +91,21 @@ export class ToolRegistry {
|
|
|
85
91
|
parameterSchema,
|
|
86
92
|
async (args: any) => {
|
|
87
93
|
try {
|
|
88
|
-
const siteId = args.site ||
|
|
94
|
+
const siteId = args.site || "default";
|
|
89
95
|
const client = this.wordpressClients.get(siteId);
|
|
90
96
|
|
|
91
97
|
if (!client) {
|
|
92
|
-
const availableSites = Array.from(
|
|
98
|
+
const availableSites = Array.from(
|
|
99
|
+
this.wordpressClients.keys(),
|
|
100
|
+
).join(", ");
|
|
93
101
|
return {
|
|
94
102
|
content: [
|
|
95
103
|
{
|
|
96
|
-
type:
|
|
97
|
-
text: `Error: Site with ID '${siteId}' not found. Available sites: ${availableSites}
|
|
98
|
-
}
|
|
104
|
+
type: "text" as const,
|
|
105
|
+
text: `Error: Site with ID '${siteId}' not found. Available sites: ${availableSites}`,
|
|
106
|
+
},
|
|
99
107
|
],
|
|
100
|
-
isError: true
|
|
108
|
+
isError: true,
|
|
101
109
|
};
|
|
102
110
|
}
|
|
103
111
|
|
|
@@ -107,35 +115,38 @@ export class ToolRegistry {
|
|
|
107
115
|
return {
|
|
108
116
|
content: [
|
|
109
117
|
{
|
|
110
|
-
type:
|
|
111
|
-
text:
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
type: "text" as const,
|
|
119
|
+
text:
|
|
120
|
+
typeof result === "string"
|
|
121
|
+
? result
|
|
122
|
+
: JSON.stringify(result, null, 2),
|
|
123
|
+
},
|
|
124
|
+
],
|
|
114
125
|
};
|
|
115
126
|
} catch (error) {
|
|
116
127
|
if (this.isAuthenticationError(error)) {
|
|
117
128
|
return {
|
|
118
129
|
content: [
|
|
119
130
|
{
|
|
120
|
-
type:
|
|
121
|
-
text: `Authentication failed for site '${args.site ||
|
|
122
|
-
}
|
|
131
|
+
type: "text" as const,
|
|
132
|
+
text: `Authentication failed for site '${args.site || "default"}'. Please check your credentials.`,
|
|
133
|
+
},
|
|
123
134
|
],
|
|
124
|
-
isError: true
|
|
135
|
+
isError: true,
|
|
125
136
|
};
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
return {
|
|
129
140
|
content: [
|
|
130
141
|
{
|
|
131
|
-
type:
|
|
132
|
-
text: `Error: ${getErrorMessage(error)}
|
|
133
|
-
}
|
|
142
|
+
type: "text" as const,
|
|
143
|
+
text: `Error: ${getErrorMessage(error)}`,
|
|
144
|
+
},
|
|
134
145
|
],
|
|
135
|
-
isError: true
|
|
146
|
+
isError: true,
|
|
136
147
|
};
|
|
137
148
|
}
|
|
138
|
-
}
|
|
149
|
+
},
|
|
139
150
|
);
|
|
140
151
|
}
|
|
141
152
|
|
|
@@ -143,23 +154,25 @@ export class ToolRegistry {
|
|
|
143
154
|
* Build Zod parameter schema from tool definition
|
|
144
155
|
*/
|
|
145
156
|
private buildParameterSchema(tool: ToolDefinition, baseSchema: any): any {
|
|
146
|
-
return
|
|
147
|
-
(
|
|
148
|
-
|
|
157
|
+
return (
|
|
158
|
+
tool.parameters?.reduce(
|
|
159
|
+
(schema: any, param: any) => {
|
|
160
|
+
let zodType = this.getZodTypeForParameter(param);
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
162
|
+
if (param.description) {
|
|
163
|
+
zodType = zodType.describe(param.description);
|
|
164
|
+
}
|
|
153
165
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
166
|
+
if (!param.required) {
|
|
167
|
+
zodType = zodType.optional();
|
|
168
|
+
}
|
|
157
169
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
schema[param.name] = zodType;
|
|
171
|
+
return schema;
|
|
172
|
+
},
|
|
173
|
+
{ ...baseSchema },
|
|
174
|
+
) || baseSchema
|
|
175
|
+
);
|
|
163
176
|
}
|
|
164
177
|
|
|
165
178
|
/**
|
|
@@ -167,15 +180,15 @@ export class ToolRegistry {
|
|
|
167
180
|
*/
|
|
168
181
|
private getZodTypeForParameter(param: any): z.ZodType {
|
|
169
182
|
switch (param.type) {
|
|
170
|
-
case
|
|
183
|
+
case "string":
|
|
171
184
|
return z.string();
|
|
172
|
-
case
|
|
185
|
+
case "number":
|
|
173
186
|
return z.number();
|
|
174
|
-
case
|
|
187
|
+
case "boolean":
|
|
175
188
|
return z.boolean();
|
|
176
|
-
case
|
|
189
|
+
case "array":
|
|
177
190
|
return z.array(z.string());
|
|
178
|
-
case
|
|
191
|
+
case "object":
|
|
179
192
|
return z.record(z.any());
|
|
180
193
|
default:
|
|
181
194
|
return z.string();
|
|
@@ -189,6 +202,6 @@ export class ToolRegistry {
|
|
|
189
202
|
if (error?.response?.status && [401, 403].includes(error.response.status)) {
|
|
190
203
|
return true;
|
|
191
204
|
}
|
|
192
|
-
return error?.code ===
|
|
205
|
+
return error?.code === "WORDPRESS_AUTH_ERROR";
|
|
193
206
|
}
|
|
194
207
|
}
|
package/src/server.ts
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Re-exports the main MCP server class for backward compatibility
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export { default as MCPWordPressServer } from
|
|
7
|
-
export { default } from
|
|
6
|
+
export { default as MCPWordPressServer } from "./index.js";
|
|
7
|
+
export { default } from "./index.js";
|