mcp-wordpress 1.2.0 → 1.2.3
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 +268 -14
- package/dist/security/SecurityConfig.d.ts +5 -5
- package/dist/security/SecurityConfig.d.ts.map +1 -1
- package/dist/security/SecurityConfig.js +92 -92
- package/dist/security/SecurityConfig.js.map +1 -1
- package/dist/tools/BaseToolManager.js +5 -5
- package/docs/DOCKER.md +13 -13
- package/docs/developer/MAINTENANCE.md +2 -2
- package/package.json +11 -5
- package/src/security/SecurityConfig.ts +95 -95
- package/src/tools/BaseToolManager.ts +6 -6
|
@@ -1,66 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Security configuration and constants for MCP WordPress
|
|
3
3
|
*/
|
|
4
|
-
import { randomBytes } from
|
|
4
|
+
import { randomBytes } from 'crypto';
|
|
5
5
|
export const SecurityConfig = {
|
|
6
6
|
// Rate limiting
|
|
7
7
|
rateLimiting: {
|
|
8
8
|
default: {
|
|
9
9
|
windowMs: 60 * 1000, // 1 minute
|
|
10
|
-
maxRequests: 60
|
|
10
|
+
maxRequests: 60
|
|
11
11
|
},
|
|
12
12
|
authentication: {
|
|
13
13
|
windowMs: 5 * 60 * 1000, // 5 minutes
|
|
14
|
-
maxAttempts: 5
|
|
14
|
+
maxAttempts: 5
|
|
15
15
|
},
|
|
16
16
|
upload: {
|
|
17
17
|
windowMs: 60 * 1000, // 1 minute
|
|
18
|
-
maxRequests: 10
|
|
19
|
-
}
|
|
18
|
+
maxRequests: 10
|
|
19
|
+
}
|
|
20
20
|
},
|
|
21
21
|
// File upload restrictions
|
|
22
22
|
fileUpload: {
|
|
23
23
|
maxSizeMB: 10,
|
|
24
24
|
allowedMimeTypes: [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
'image/jpeg',
|
|
26
|
+
'image/png',
|
|
27
|
+
'image/gif',
|
|
28
|
+
'image/webp',
|
|
29
|
+
'image/svg+xml',
|
|
30
|
+
'application/pdf',
|
|
31
|
+
'application/msword',
|
|
32
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
33
|
+
'application/vnd.ms-excel',
|
|
34
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
35
|
+
'text/plain',
|
|
36
|
+
'text/csv'
|
|
37
37
|
],
|
|
38
38
|
// Dangerous file extensions to block
|
|
39
39
|
blockedExtensions: [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
]
|
|
40
|
+
'.exe',
|
|
41
|
+
'.bat',
|
|
42
|
+
'.cmd',
|
|
43
|
+
'.com',
|
|
44
|
+
'.pif',
|
|
45
|
+
'.scr',
|
|
46
|
+
'.vbs',
|
|
47
|
+
'.js',
|
|
48
|
+
'.jar',
|
|
49
|
+
'.zip',
|
|
50
|
+
'.rar',
|
|
51
|
+
'.tar',
|
|
52
|
+
'.php',
|
|
53
|
+
'.php3',
|
|
54
|
+
'.php4',
|
|
55
|
+
'.php5',
|
|
56
|
+
'.phtml',
|
|
57
|
+
'.sh',
|
|
58
|
+
'.bash',
|
|
59
|
+
'.zsh',
|
|
60
|
+
'.fish',
|
|
61
|
+
'.ps1',
|
|
62
|
+
'.psm1'
|
|
63
|
+
]
|
|
64
64
|
},
|
|
65
65
|
// Input validation
|
|
66
66
|
validation: {
|
|
@@ -72,54 +72,54 @@ export const SecurityConfig = {
|
|
|
72
72
|
maxUsernameLength: 60,
|
|
73
73
|
minUsernameLength: 3,
|
|
74
74
|
maxPasswordLength: 128,
|
|
75
|
-
minPasswordLength: 8
|
|
75
|
+
minPasswordLength: 8
|
|
76
76
|
},
|
|
77
77
|
// Request timeouts (milliseconds)
|
|
78
78
|
timeouts: {
|
|
79
79
|
default: 30000, // 30 seconds
|
|
80
80
|
upload: 600000, // 10 minutes
|
|
81
|
-
auth: 10000
|
|
81
|
+
auth: 10000 // 10 seconds
|
|
82
82
|
},
|
|
83
83
|
// Security headers
|
|
84
84
|
headers: {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
'X-Content-Type-Options': 'nosniff',
|
|
86
|
+
'X-Frame-Options': 'DENY',
|
|
87
|
+
'X-XSS-Protection': '1; mode=block',
|
|
88
|
+
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
|
|
89
|
+
'Content-Security-Policy': 'default-src \'self\''
|
|
90
90
|
},
|
|
91
91
|
// Error messages (generic to avoid information disclosure)
|
|
92
92
|
errorMessages: {
|
|
93
|
-
authentication:
|
|
94
|
-
authorization:
|
|
95
|
-
validation:
|
|
96
|
-
rateLimit:
|
|
97
|
-
serverError:
|
|
98
|
-
notFound:
|
|
93
|
+
authentication: 'Authentication failed. Please check your credentials.',
|
|
94
|
+
authorization: 'You do not have permission to perform this action.',
|
|
95
|
+
validation: 'Invalid input provided.',
|
|
96
|
+
rateLimit: 'Too many requests. Please try again later.',
|
|
97
|
+
serverError: 'An error occurred processing your request.',
|
|
98
|
+
notFound: 'The requested resource was not found.'
|
|
99
99
|
},
|
|
100
100
|
// Logging configuration
|
|
101
101
|
logging: {
|
|
102
102
|
// Fields to exclude from logs
|
|
103
103
|
excludeFields: [
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
104
|
+
'password',
|
|
105
|
+
'appPassword',
|
|
106
|
+
'app_password',
|
|
107
|
+
'token',
|
|
108
|
+
'secret',
|
|
109
|
+
'authorization',
|
|
110
|
+
'cookie',
|
|
111
|
+
'session',
|
|
112
|
+
'key',
|
|
113
|
+
'apiKey',
|
|
114
|
+
'api_key'
|
|
115
115
|
],
|
|
116
116
|
// Patterns to redact in log messages
|
|
117
117
|
redactPatterns: [
|
|
118
118
|
/password["\s:=]+["']?([^"'\s]+)["']?/gi,
|
|
119
119
|
/token["\s:=]+["']?([^"'\s]+)["']?/gi,
|
|
120
120
|
/secret["\s:=]+["']?([^"'\s]+)["']?/gi,
|
|
121
|
-
/key["\s:=]+["']?([^"'\s]+)["']?/gi
|
|
122
|
-
]
|
|
121
|
+
/key["\s:=]+["']?([^"'\s]+)["']?/gi
|
|
122
|
+
]
|
|
123
123
|
},
|
|
124
124
|
// Cache configuration
|
|
125
125
|
cache: {
|
|
@@ -135,30 +135,30 @@ export const SecurityConfig = {
|
|
|
135
135
|
semiStatic: 2 * 60 * 60 * 1000, // 2 hours - categories, tags, user profiles
|
|
136
136
|
dynamic: 15 * 60 * 1000, // 15 minutes - posts, pages, comments
|
|
137
137
|
session: 30 * 60 * 1000, // 30 minutes - authentication, current user
|
|
138
|
-
realtime: 60 * 1000
|
|
138
|
+
realtime: 60 * 1000 // 1 minute - real-time data
|
|
139
139
|
},
|
|
140
140
|
// Cache-Control headers by data type
|
|
141
141
|
cacheHeaders: {
|
|
142
|
-
static:
|
|
143
|
-
semiStatic:
|
|
144
|
-
dynamic:
|
|
145
|
-
session:
|
|
146
|
-
realtime:
|
|
142
|
+
static: 'public, max-age=14400', // 4 hours
|
|
143
|
+
semiStatic: 'public, max-age=7200', // 2 hours
|
|
144
|
+
dynamic: 'public, max-age=900', // 15 minutes
|
|
145
|
+
session: 'private, max-age=1800', // 30 minutes
|
|
146
|
+
realtime: 'public, max-age=60' // 1 minute
|
|
147
147
|
},
|
|
148
148
|
// Invalidation settings
|
|
149
149
|
invalidation: {
|
|
150
150
|
enabled: true,
|
|
151
151
|
batchSize: 100, // Max events to process in one batch
|
|
152
152
|
queueTimeout: 5000, // Max time to wait before processing queue (ms)
|
|
153
|
-
enableCascading: true
|
|
153
|
+
enableCascading: true // Allow cascading invalidations
|
|
154
154
|
},
|
|
155
155
|
// Memory management
|
|
156
156
|
cleanup: {
|
|
157
157
|
interval: 60 * 1000, // Cleanup interval in milliseconds (1 minute)
|
|
158
158
|
maxMemoryMB: 50, // Maximum memory usage for cache
|
|
159
|
-
evictionThreshold: 0.8
|
|
160
|
-
}
|
|
161
|
-
}
|
|
159
|
+
evictionThreshold: 0.8 // Start evicting when 80% full
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
162
|
};
|
|
163
163
|
/**
|
|
164
164
|
* Security utility functions
|
|
@@ -168,15 +168,15 @@ export class SecurityUtils {
|
|
|
168
168
|
* Redact sensitive information from objects
|
|
169
169
|
*/
|
|
170
170
|
static redactSensitiveData(obj) {
|
|
171
|
-
if (typeof obj !==
|
|
171
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
172
172
|
return obj;
|
|
173
173
|
}
|
|
174
174
|
const redacted = Array.isArray(obj) ? [...obj] : { ...obj };
|
|
175
175
|
for (const key in redacted) {
|
|
176
176
|
if (SecurityConfig.logging.excludeFields.some((field) => key.toLowerCase().includes(field.toLowerCase()))) {
|
|
177
|
-
redacted[key] =
|
|
177
|
+
redacted[key] = '[REDACTED]';
|
|
178
178
|
}
|
|
179
|
-
else if (typeof redacted[key] ===
|
|
179
|
+
else if (typeof redacted[key] === 'object') {
|
|
180
180
|
redacted[key] = SecurityUtils.redactSensitiveData(redacted[key]);
|
|
181
181
|
}
|
|
182
182
|
}
|
|
@@ -189,7 +189,7 @@ export class SecurityUtils {
|
|
|
189
189
|
let redacted = str;
|
|
190
190
|
for (const pattern of SecurityConfig.logging.redactPatterns) {
|
|
191
191
|
redacted = redacted.replace(pattern, (match, value) => {
|
|
192
|
-
return match.replace(value,
|
|
192
|
+
return match.replace(value, '[REDACTED]');
|
|
193
193
|
});
|
|
194
194
|
}
|
|
195
195
|
return redacted;
|
|
@@ -198,9 +198,9 @@ export class SecurityUtils {
|
|
|
198
198
|
* Generate secure random strings
|
|
199
199
|
*/
|
|
200
200
|
static generateSecureToken(length = 32) {
|
|
201
|
-
const chars =
|
|
201
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
202
202
|
const array = new Uint8Array(length);
|
|
203
|
-
if (typeof crypto !==
|
|
203
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
204
204
|
crypto.getRandomValues(array);
|
|
205
205
|
}
|
|
206
206
|
else {
|
|
@@ -208,7 +208,7 @@ export class SecurityUtils {
|
|
|
208
208
|
const buffer = randomBytes(length);
|
|
209
209
|
array.set(buffer);
|
|
210
210
|
}
|
|
211
|
-
return Array.from(array, (byte) => chars[byte % chars.length]).join(
|
|
211
|
+
return Array.from(array, (byte) => chars[byte % chars.length]).join('');
|
|
212
212
|
}
|
|
213
213
|
/**
|
|
214
214
|
* Check if a file extension is allowed
|
|
@@ -221,10 +221,10 @@ export class SecurityUtils {
|
|
|
221
221
|
* Sanitize log output
|
|
222
222
|
*/
|
|
223
223
|
static sanitizeForLog(data) {
|
|
224
|
-
if (typeof data ===
|
|
224
|
+
if (typeof data === 'string') {
|
|
225
225
|
return SecurityUtils.redactString(data);
|
|
226
226
|
}
|
|
227
|
-
if (typeof data ===
|
|
227
|
+
if (typeof data === 'object') {
|
|
228
228
|
return SecurityUtils.redactSensitiveData(data);
|
|
229
229
|
}
|
|
230
230
|
return data;
|
|
@@ -235,28 +235,28 @@ export class SecurityUtils {
|
|
|
235
235
|
*/
|
|
236
236
|
export function createSecureError(error, fallbackMessage = SecurityConfig.errorMessages.serverError) {
|
|
237
237
|
// Log the actual error for debugging (with sanitization)
|
|
238
|
-
if (process.env.NODE_ENV !==
|
|
239
|
-
console.error(
|
|
238
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
239
|
+
console.error('Secure Error:', SecurityUtils.sanitizeForLog(error));
|
|
240
240
|
}
|
|
241
241
|
// Return generic error to prevent information disclosure
|
|
242
242
|
const secureError = new Error(fallbackMessage);
|
|
243
243
|
// Preserve error code if it's safe
|
|
244
|
-
if (error && typeof error.code ===
|
|
244
|
+
if (error && typeof error.code === 'string' && !error.code.includes('_')) {
|
|
245
245
|
secureError.code = error.code;
|
|
246
246
|
}
|
|
247
247
|
return secureError;
|
|
248
248
|
}
|
|
249
249
|
// Import path for file extension checking
|
|
250
|
-
import * as path from
|
|
250
|
+
import * as path from 'path';
|
|
251
251
|
/**
|
|
252
252
|
* Environment-specific security settings
|
|
253
253
|
*/
|
|
254
254
|
export function getEnvironmentSecurity() {
|
|
255
|
-
const isProduction = process.env.NODE_ENV ===
|
|
255
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
256
256
|
return {
|
|
257
257
|
strictMode: isProduction,
|
|
258
258
|
verboseErrors: !isProduction,
|
|
259
|
-
enforceHttps: isProduction
|
|
259
|
+
enforceHttps: isProduction
|
|
260
260
|
};
|
|
261
261
|
}
|
|
262
262
|
//# sourceMappingURL=SecurityConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityConfig.js","sourceRoot":"","sources":["../../src/security/SecurityConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,gBAAgB;IAChB,YAAY,EAAE;QACZ,OAAO,EAAE;YACP,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,WAAW;YAChC,WAAW,EAAE,EAAE;SAChB;QACD,cAAc,EAAE;YACd,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;YACrC,WAAW,EAAE,CAAC;SACf;QACD,MAAM,EAAE;YACN,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,WAAW;YAChC,WAAW,EAAE,EAAE;SAChB;KACF;IAED,2BAA2B;IAC3B,UAAU,EAAE;QACV,SAAS,EAAE,EAAE;QACb,gBAAgB,EAAE;YAChB,YAAY;YACZ,WAAW;YACX,WAAW;YACX,YAAY;YACZ,eAAe;YACf,iBAAiB;YACjB,oBAAoB;YACpB,yEAAyE;YACzE,0BAA0B;YAC1B,mEAAmE;YACnE,YAAY;YACZ,UAAU;SACX;QACD,qCAAqC;QACrC,iBAAiB,EAAE;YACjB,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,KAAK;YACL,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,OAAO;YACP,OAAO;YACP,OAAO;YACP,QAAQ;YACR,KAAK;YACL,OAAO;YACP,MAAM;YACN,OAAO;YACP,MAAM;YACN,OAAO;SACR;KACF;IAED,mBAAmB;IACnB,UAAU,EAAE;QACV,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,GAAG;QACnB,gBAAgB,EAAE,KAAK;QACvB,gBAAgB,EAAE,GAAG;QACrB,YAAY,EAAE,IAAI;QAClB,iBAAiB,EAAE,EAAE;QACrB,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,GAAG;QACtB,iBAAiB,EAAE,CAAC;KACrB;IAED,kCAAkC;IAClC,QAAQ,EAAE;QACR,OAAO,EAAE,KAAK,EAAE,aAAa;QAC7B,MAAM,EAAE,MAAM,EAAE,aAAa;QAC7B,IAAI,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"SecurityConfig.js","sourceRoot":"","sources":["../../src/security/SecurityConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base utility class for tool managers to reduce code duplication
|
|
3
3
|
*/
|
|
4
|
-
import { getErrorMessage } from
|
|
4
|
+
import { getErrorMessage } from '../utils/error.js';
|
|
5
5
|
export class BaseToolUtils {
|
|
6
6
|
/**
|
|
7
7
|
* Validate required parameters
|
|
@@ -18,7 +18,7 @@ export class BaseToolUtils {
|
|
|
18
18
|
/**
|
|
19
19
|
* Validate ID parameter
|
|
20
20
|
*/
|
|
21
|
-
static validateId(id, name =
|
|
21
|
+
static validateId(id, name = 'id') {
|
|
22
22
|
const numId = Number(id);
|
|
23
23
|
if (!Number.isInteger(numId) || numId <= 0) {
|
|
24
24
|
throw new Error(`Invalid ${name}: must be a positive integer`);
|
|
@@ -36,12 +36,12 @@ export class BaseToolUtils {
|
|
|
36
36
|
* Cache key generation helper
|
|
37
37
|
*/
|
|
38
38
|
static generateCacheKey(operation, params) {
|
|
39
|
-
const site = params.site ||
|
|
39
|
+
const site = params.site || 'default';
|
|
40
40
|
const paramStr = Object.entries(params)
|
|
41
|
-
.filter(([key]) => key !==
|
|
41
|
+
.filter(([key]) => key !== 'site')
|
|
42
42
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
43
43
|
.map(([key, value]) => `${key}:${value}`)
|
|
44
|
-
.join(
|
|
44
|
+
.join('|');
|
|
45
45
|
return `${site}:${operation}:${paramStr}`;
|
|
46
46
|
}
|
|
47
47
|
/**
|
package/docs/DOCKER.md
CHANGED
|
@@ -18,14 +18,14 @@ docker run -d \
|
|
|
18
18
|
-e WORDPRESS_SITE_URL=https://your-site.com \
|
|
19
19
|
-e WORDPRESS_USERNAME=your-username \
|
|
20
20
|
-e WORDPRESS_APP_PASSWORD=your-app-password \
|
|
21
|
-
|
|
21
|
+
docdyhr/mcp-wordpress:latest
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
### Option 2: Docker Compose
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
# Download the compose file
|
|
28
|
-
curl -O https://raw.githubusercontent.com/
|
|
28
|
+
curl -O https://raw.githubusercontent.com/docdyhr/mcp-wordpress/main/docker-compose.yml
|
|
29
29
|
|
|
30
30
|
# Configure environment variables (see below)
|
|
31
31
|
# Start the service
|
|
@@ -36,7 +36,7 @@ docker-compose up -d
|
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
# Clone the repository
|
|
39
|
-
git clone https://github.com/
|
|
39
|
+
git clone https://github.com/docdyhr/mcp-wordpress.git
|
|
40
40
|
cd mcp-wordpress
|
|
41
41
|
|
|
42
42
|
# Build the image
|
|
@@ -68,7 +68,7 @@ For multi-site setups, mount a configuration file:
|
|
|
68
68
|
docker run -d \
|
|
69
69
|
--name mcp-wordpress \
|
|
70
70
|
-v ./mcp-wordpress.config.json:/app/config/mcp-wordpress.config.json:ro \
|
|
71
|
-
|
|
71
|
+
docdyhr/mcp-wordpress:latest
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
**Example `mcp-wordpress.config.json`:**
|
|
@@ -107,7 +107,7 @@ version: '3.8'
|
|
|
107
107
|
|
|
108
108
|
services:
|
|
109
109
|
mcp-wordpress:
|
|
110
|
-
image:
|
|
110
|
+
image: docdyhr/mcp-wordpress:latest
|
|
111
111
|
container_name: mcp-wordpress
|
|
112
112
|
restart: unless-stopped
|
|
113
113
|
environment:
|
|
@@ -153,7 +153,7 @@ version: '3.8'
|
|
|
153
153
|
|
|
154
154
|
services:
|
|
155
155
|
mcp-wordpress:
|
|
156
|
-
image:
|
|
156
|
+
image: docdyhr/mcp-wordpress:latest
|
|
157
157
|
deploy:
|
|
158
158
|
replicas: 2
|
|
159
159
|
restart_policy:
|
|
@@ -201,7 +201,7 @@ spec:
|
|
|
201
201
|
spec:
|
|
202
202
|
containers:
|
|
203
203
|
- name: mcp-wordpress
|
|
204
|
-
image:
|
|
204
|
+
image: docdyhr/mcp-wordpress:latest
|
|
205
205
|
ports:
|
|
206
206
|
- containerPort: 3000
|
|
207
207
|
env:
|
|
@@ -262,7 +262,7 @@ docker inspect --format='{{.State.Health.Status}}' mcp-wordpress
|
|
|
262
262
|
docker exec -it mcp-wordpress /bin/sh
|
|
263
263
|
|
|
264
264
|
# Update to latest version
|
|
265
|
-
docker pull
|
|
265
|
+
docker pull docdyhr/mcp-wordpress:latest
|
|
266
266
|
docker stop mcp-wordpress
|
|
267
267
|
docker rm mcp-wordpress
|
|
268
268
|
# Run with new image...
|
|
@@ -354,7 +354,7 @@ echo \"your-app-password\" | docker secret create wordpress_password -
|
|
|
354
354
|
version: '3.8'
|
|
355
355
|
services:
|
|
356
356
|
mcp-wordpress:
|
|
357
|
-
image:
|
|
357
|
+
image: docdyhr/mcp-wordpress:latest
|
|
358
358
|
secrets:
|
|
359
359
|
- wordpress_url
|
|
360
360
|
- wordpress_user
|
|
@@ -424,7 +424,7 @@ docker exec mcp-wordpress node -e \"
|
|
|
424
424
|
|
|
425
425
|
```bash
|
|
426
426
|
# Run with debug logging
|
|
427
|
-
docker run -e DEBUG=true
|
|
427
|
+
docker run -e DEBUG=true docdyhr/mcp-wordpress:latest
|
|
428
428
|
|
|
429
429
|
# Or with compose
|
|
430
430
|
environment:
|
|
@@ -442,9 +442,9 @@ environment:
|
|
|
442
442
|
|
|
443
443
|
## 🤝 Support
|
|
444
444
|
|
|
445
|
-
- **GitHub Issues**: [Report problems](https://github.com/
|
|
446
|
-
- **Discussions**: [Ask questions](https://github.com/
|
|
447
|
-
- **Documentation**: [Browse guides](https://github.com/
|
|
445
|
+
- **GitHub Issues**: [Report problems](https://github.com/docdyhr/mcp-wordpress/issues)
|
|
446
|
+
- **Discussions**: [Ask questions](https://github.com/docdyhr/mcp-wordpress/discussions)
|
|
447
|
+
- **Documentation**: [Browse guides](https://github.com/docdyhr/mcp-wordpress/tree/main/docs)
|
|
448
448
|
|
|
449
449
|
---
|
|
450
450
|
|
|
@@ -220,9 +220,9 @@ node_modules/
|
|
|
220
220
|
|
|
221
221
|
1. **Immediate Response:**
|
|
222
222
|
```bash
|
|
223
|
-
npm unpublish
|
|
223
|
+
npm unpublish mcp-wordpress@version
|
|
224
224
|
# Or deprecate if unpublish is not allowed
|
|
225
|
-
npm deprecate
|
|
225
|
+
npm deprecate mcp-wordpress@version "Security issue - use newer version"
|
|
226
226
|
```
|
|
227
227
|
|
|
228
228
|
2. **Credential Rotation:**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-wordpress",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Comprehensive Model Context Protocol server for WordPress management with 59 tools, performance monitoring, intelligent caching, auto-generated documentation, Docker support, TypeScript, and production-ready authentication",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"ai",
|
|
12
12
|
"assistant"
|
|
13
13
|
],
|
|
14
|
-
"homepage": "https://github.com/
|
|
14
|
+
"homepage": "https://github.com/docdyhr/mcp-wordpress#readme",
|
|
15
15
|
"bugs": {
|
|
16
|
-
"url": "https://github.com/
|
|
16
|
+
"url": "https://github.com/docdyhr/mcp-wordpress/issues"
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/
|
|
20
|
+
"url": "git+https://github.com/docdyhr/mcp-wordpress.git"
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"author": "Thomas Dyhr",
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
"pre-commit": "lint-staged",
|
|
57
57
|
"prepare": "husky",
|
|
58
58
|
"prepublishOnly": "npm run build && npm run check:ignore",
|
|
59
|
+
"release": "semantic-release",
|
|
60
|
+
"release:dry": "semantic-release --dry-run",
|
|
59
61
|
"security:audit": "npm audit --production",
|
|
60
62
|
"security:check": "node scripts/security-check.js",
|
|
61
63
|
"security:fix": "npm audit fix",
|
|
@@ -78,7 +80,8 @@
|
|
|
78
80
|
"test:security": "npm run build && NODE_OPTIONS=\"--experimental-vm-modules\" jest tests/security/ --config=jest.typescript.config.json",
|
|
79
81
|
"test:security:penetration": "npm run build && NODE_OPTIONS=\"--experimental-vm-modules\" jest tests/security/penetration-tests.test.js --config=jest.typescript.config.json",
|
|
80
82
|
"test:security:validation": "npm run build && NODE_OPTIONS=\"--experimental-vm-modules\" jest tests/security/security-validation.test.js --config=jest.typescript.config.json",
|
|
81
|
-
"test:tools": "node scripts/test-all-tools.js",
|
|
83
|
+
"test:tools": "node scripts/test-all-tools-fixed.js",
|
|
84
|
+
"test:multisite": "node scripts/test-multisite-quick.js",
|
|
82
85
|
"test:typescript": "npm run build && NODE_OPTIONS=\"--experimental-vm-modules\" jest --config=jest.typescript.config.json",
|
|
83
86
|
"test:watch": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --watch --config=jest.typescript.config.json",
|
|
84
87
|
"test:with-env": "bash scripts/start-test-env.sh && npm run test:typescript",
|
|
@@ -109,6 +112,8 @@
|
|
|
109
112
|
"@jest/globals": "^30.0.0",
|
|
110
113
|
"@pact-foundation/pact": "^15.0.1",
|
|
111
114
|
"@pact-foundation/pact-node": "^10.18.0",
|
|
115
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
116
|
+
"@semantic-release/git": "^10.0.1",
|
|
112
117
|
"@types/jest": "^30.0.0",
|
|
113
118
|
"@types/node": "^20.19.1",
|
|
114
119
|
"@typescript-eslint/parser": "^8.35.0",
|
|
@@ -123,6 +128,7 @@
|
|
|
123
128
|
"nock": "^14.0.5",
|
|
124
129
|
"open": "^9.1.0",
|
|
125
130
|
"prettier": "^3.6.2",
|
|
131
|
+
"semantic-release": "^24.8.0",
|
|
126
132
|
"sort-package-json": "^3.3.1",
|
|
127
133
|
"typescript": "^5.8.3"
|
|
128
134
|
},
|