mcp-wordpress 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +568 -0
  3. package/bin/mcp-wordpress.js +12 -0
  4. package/bin/setup.js +302 -0
  5. package/bin/status.js +359 -0
  6. package/dist/client/WordPressClient.d.ts +81 -0
  7. package/dist/client/WordPressClient.d.ts.map +1 -0
  8. package/dist/client/WordPressClient.js +354 -0
  9. package/dist/client/WordPressClient.js.map +1 -0
  10. package/dist/client/api.d.ts +140 -0
  11. package/dist/client/api.d.ts.map +1 -0
  12. package/dist/client/api.js +727 -0
  13. package/dist/client/api.js.map +1 -0
  14. package/dist/client/auth.d.ts +121 -0
  15. package/dist/client/auth.d.ts.map +1 -0
  16. package/dist/client/auth.js +430 -0
  17. package/dist/client/auth.js.map +1 -0
  18. package/dist/client/managers/AuthenticationManager.d.ts +39 -0
  19. package/dist/client/managers/AuthenticationManager.d.ts.map +1 -0
  20. package/dist/client/managers/AuthenticationManager.js +159 -0
  21. package/dist/client/managers/AuthenticationManager.js.map +1 -0
  22. package/dist/client/managers/BaseManager.d.ts +22 -0
  23. package/dist/client/managers/BaseManager.d.ts.map +1 -0
  24. package/dist/client/managers/BaseManager.js +47 -0
  25. package/dist/client/managers/BaseManager.js.map +1 -0
  26. package/dist/client/managers/RequestManager.d.ts +45 -0
  27. package/dist/client/managers/RequestManager.d.ts.map +1 -0
  28. package/dist/client/managers/RequestManager.js +161 -0
  29. package/dist/client/managers/RequestManager.js.map +1 -0
  30. package/dist/client/managers/index.d.ts +8 -0
  31. package/dist/client/managers/index.d.ts.map +1 -0
  32. package/dist/client/managers/index.js +8 -0
  33. package/dist/client/managers/index.js.map +1 -0
  34. package/dist/index.d.ts +19 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +264 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/server.d.ts +7 -0
  39. package/dist/server.d.ts.map +1 -0
  40. package/dist/server.js +7 -0
  41. package/dist/server.js.map +1 -0
  42. package/dist/tools/auth.d.ts +44 -0
  43. package/dist/tools/auth.d.ts.map +1 -0
  44. package/dist/tools/auth.js +126 -0
  45. package/dist/tools/auth.js.map +1 -0
  46. package/dist/tools/base.d.ts +37 -0
  47. package/dist/tools/base.d.ts.map +1 -0
  48. package/dist/tools/base.js +60 -0
  49. package/dist/tools/base.js.map +1 -0
  50. package/dist/tools/comments.d.ts +33 -0
  51. package/dist/tools/comments.d.ts.map +1 -0
  52. package/dist/tools/comments.js +228 -0
  53. package/dist/tools/comments.js.map +1 -0
  54. package/dist/tools/index.d.ts +9 -0
  55. package/dist/tools/index.d.ts.map +1 -0
  56. package/dist/tools/index.js +9 -0
  57. package/dist/tools/index.js.map +1 -0
  58. package/dist/tools/media.d.ts +29 -0
  59. package/dist/tools/media.d.ts.map +1 -0
  60. package/dist/tools/media.js +208 -0
  61. package/dist/tools/media.js.map +1 -0
  62. package/dist/tools/pages.d.ts +30 -0
  63. package/dist/tools/pages.d.ts.map +1 -0
  64. package/dist/tools/pages.js +211 -0
  65. package/dist/tools/pages.js.map +1 -0
  66. package/dist/tools/posts.d.ts +30 -0
  67. package/dist/tools/posts.d.ts.map +1 -0
  68. package/dist/tools/posts.js +240 -0
  69. package/dist/tools/posts.js.map +1 -0
  70. package/dist/tools/site.d.ts +31 -0
  71. package/dist/tools/site.d.ts.map +1 -0
  72. package/dist/tools/site.js +192 -0
  73. package/dist/tools/site.js.map +1 -0
  74. package/dist/tools/taxonomies.d.ts +37 -0
  75. package/dist/tools/taxonomies.d.ts.map +1 -0
  76. package/dist/tools/taxonomies.js +280 -0
  77. package/dist/tools/taxonomies.js.map +1 -0
  78. package/dist/tools/users.d.ts +28 -0
  79. package/dist/tools/users.d.ts.map +1 -0
  80. package/dist/tools/users.js +201 -0
  81. package/dist/tools/users.js.map +1 -0
  82. package/dist/types/client.d.ts +215 -0
  83. package/dist/types/client.d.ts.map +1 -0
  84. package/dist/types/client.js +72 -0
  85. package/dist/types/client.js.map +1 -0
  86. package/dist/types/index.d.ts +157 -0
  87. package/dist/types/index.d.ts.map +1 -0
  88. package/dist/types/index.js +12 -0
  89. package/dist/types/index.js.map +1 -0
  90. package/dist/types/mcp.d.ts +178 -0
  91. package/dist/types/mcp.d.ts.map +1 -0
  92. package/dist/types/mcp.js +7 -0
  93. package/dist/types/mcp.js.map +1 -0
  94. package/dist/types/wordpress.d.ts +443 -0
  95. package/dist/types/wordpress.d.ts.map +1 -0
  96. package/dist/types/wordpress.js +7 -0
  97. package/dist/types/wordpress.js.map +1 -0
  98. package/dist/utils/debug.d.ts +63 -0
  99. package/dist/utils/debug.d.ts.map +1 -0
  100. package/dist/utils/debug.js +195 -0
  101. package/dist/utils/debug.js.map +1 -0
  102. package/dist/utils/error.d.ts +19 -0
  103. package/dist/utils/error.d.ts.map +1 -0
  104. package/dist/utils/error.js +71 -0
  105. package/dist/utils/error.js.map +1 -0
  106. package/dist/utils/toolWrapper.d.ts +36 -0
  107. package/dist/utils/toolWrapper.d.ts.map +1 -0
  108. package/dist/utils/toolWrapper.js +90 -0
  109. package/dist/utils/toolWrapper.js.map +1 -0
  110. package/package.json +115 -0
  111. package/src/client/api.ts +1043 -0
  112. package/src/client/auth.ts +527 -0
  113. package/src/client/managers/AuthenticationManager.ts +190 -0
  114. package/src/client/managers/BaseManager.ts +73 -0
  115. package/src/client/managers/RequestManager.ts +214 -0
  116. package/src/client/managers/index.ts +8 -0
  117. package/src/index.ts +337 -0
  118. package/src/server.ts +7 -0
  119. package/src/tools/auth.ts +153 -0
  120. package/src/tools/comments.ts +263 -0
  121. package/src/tools/index.ts +8 -0
  122. package/src/tools/media.ts +240 -0
  123. package/src/tools/pages.ts +246 -0
  124. package/src/tools/posts.ts +277 -0
  125. package/src/tools/site.ts +227 -0
  126. package/src/tools/taxonomies.ts +322 -0
  127. package/src/tools/users.ts +233 -0
  128. package/src/types/client.ts +304 -0
  129. package/src/types/index.ts +207 -0
  130. package/src/types/mcp.ts +247 -0
  131. package/src/types/wordpress.ts +491 -0
  132. package/src/utils/debug.ts +258 -0
  133. package/src/utils/error.ts +88 -0
  134. package/src/utils/toolWrapper.ts +105 -0
package/bin/setup.js ADDED
@@ -0,0 +1,302 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { writeFileSync, existsSync } from 'fs';
4
+ import { createInterface } from 'readline/promises';
5
+ import { fileURLToPath } from 'url';
6
+ import { dirname, join } from 'path';
7
+ import { execSync } from 'child_process';
8
+ import open from 'open';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ const rootDir = join(__dirname, '..');
13
+
14
+ class WordPressSetup {
15
+ constructor() {
16
+ this.rl = createInterface({
17
+ input: process.stdin,
18
+ output: process.stdout
19
+ });
20
+ this.config = {};
21
+ this.envPath = join(rootDir, '.env');
22
+ }
23
+
24
+ async run() {
25
+ try {
26
+ console.log('šŸ”§ WordPress MCP Server Setup');
27
+ console.log('==============================\n');
28
+
29
+ await this.detectExistingConfig();
30
+ await this.gatherConfiguration();
31
+ await this.testConnection();
32
+ await this.saveConfiguration();
33
+ await this.showNextSteps();
34
+
35
+ } catch (error) {
36
+ console.error('āŒ Setup failed:', error.message);
37
+ process.exit(1);
38
+ } finally {
39
+ this.rl.close();
40
+ }
41
+ }
42
+
43
+ async detectExistingConfig() {
44
+ if (existsSync(this.envPath)) {
45
+ const answer = await this.rl.question('āš ļø Existing configuration found. Overwrite? (y/N): ');
46
+ if (answer.toLowerCase() !== 'y') {
47
+ console.log('Setup cancelled.');
48
+ process.exit(0);
49
+ }
50
+ }
51
+ }
52
+
53
+ async gatherConfiguration() {
54
+ console.log('šŸ“ WordPress Site Configuration\n');
55
+
56
+ // WordPress URL
57
+ this.config.WORDPRESS_URL = await this.rl.question('WordPress Site URL (e.g., https://example.com): ');
58
+ if (!this.config.WORDPRESS_URL.startsWith('http')) {
59
+ this.config.WORDPRESS_URL = 'https://' + this.config.WORDPRESS_URL;
60
+ }
61
+ this.config.WORDPRESS_URL = this.config.WORDPRESS_URL.replace(/\/$/, '');
62
+
63
+ // Authentication method
64
+ console.log('\nšŸ” Authentication Method:');
65
+ console.log('1. Application Password (Recommended)');
66
+ console.log('2. Basic Authentication (Username/Password)');
67
+ console.log('3. JWT Token');
68
+ console.log('4. API Key');
69
+
70
+ const authChoice = await this.rl.question('Choose authentication method (1-4): ');
71
+
72
+ switch (authChoice) {
73
+ case '1':
74
+ await this.setupApplicationPassword();
75
+ break;
76
+ case '2':
77
+ await this.setupBasicAuth();
78
+ break;
79
+ case '3':
80
+ await this.setupJWT();
81
+ break;
82
+ case '4':
83
+ await this.setupAPIKey();
84
+ break;
85
+ default:
86
+ console.log('Invalid choice, defaulting to Application Password');
87
+ await this.setupApplicationPassword();
88
+ }
89
+
90
+ // Optional settings
91
+ console.log('\nāš™ļø Optional Settings:');
92
+
93
+ const debugAnswer = await this.rl.question('Enable debug logging? (y/N): ');
94
+ this.config.DEBUG = debugAnswer.toLowerCase() === 'y' ? 'true' : 'false';
95
+
96
+ const cacheAnswer = await this.rl.question('Enable caching? (Y/n): ');
97
+ this.config.ENABLE_CACHE = cacheAnswer.toLowerCase() === 'n' ? 'false' : 'true';
98
+
99
+ const rateLimit = await this.rl.question('Rate limit (requests per minute, default 60): ');
100
+ this.config.RATE_LIMIT = rateLimit || '60';
101
+ }
102
+
103
+ async setupApplicationPassword() {
104
+ this.config.AUTH_METHOD = 'app-password';
105
+ this.config.USERNAME = await this.rl.question('WordPress Username: ');
106
+
107
+ console.log('\nšŸ“± Application Password Setup:');
108
+ console.log('1. Go to your WordPress admin dashboard');
109
+ console.log('2. Navigate to Users > Profile');
110
+ console.log('3. Scroll to "Application Passwords"');
111
+ console.log('4. Enter "MCP WordPress Server" as the name');
112
+ console.log('5. Click "Add New Application Password"');
113
+ console.log('6. Copy the generated password (it will only be shown once)');
114
+
115
+ const openBrowser = await this.rl.question('\nOpen WordPress admin in browser? (Y/n): ');
116
+ if (openBrowser.toLowerCase() !== 'n') {
117
+ try {
118
+ await open(`${this.config.WORDPRESS_URL}/wp-admin/profile.php#application-passwords-section`);
119
+ } catch {
120
+ console.log('Could not open browser automatically');
121
+ }
122
+ }
123
+
124
+ this.config.APPLICATION_PASSWORD = await this.rl.question('\nPaste Application Password: ');
125
+ }
126
+
127
+ async setupBasicAuth() {
128
+ this.config.AUTH_METHOD = 'basic';
129
+ this.config.USERNAME = await this.rl.question('WordPress Username: ');
130
+ this.config.PASSWORD = await this.rl.question('WordPress Password: ');
131
+
132
+ console.log('\nāš ļø Note: Basic authentication may require additional plugin setup');
133
+ }
134
+
135
+ async setupJWT() {
136
+ this.config.AUTH_METHOD = 'jwt';
137
+ this.config.JWT_SECRET = await this.rl.question('JWT Secret Key: ');
138
+ this.config.USERNAME = await this.rl.question('WordPress Username: ');
139
+ this.config.PASSWORD = await this.rl.question('WordPress Password: ');
140
+
141
+ console.log('\nāš ļø Note: JWT authentication requires JWT Authentication plugin');
142
+ }
143
+
144
+ async setupAPIKey() {
145
+ this.config.AUTH_METHOD = 'api-key';
146
+ this.config.API_KEY = await this.rl.question('API Key: ');
147
+ this.config.API_SECRET = await this.rl.question('API Secret (if required): ');
148
+ }
149
+
150
+ async ensureBuild() {
151
+ console.log('šŸ”Ø Building TypeScript project...');
152
+ try {
153
+ execSync('npm run build', { cwd: rootDir, stdio: 'pipe' });
154
+ console.log('āœ… Build successful!');
155
+ } catch (error) {
156
+ throw new Error('TypeScript build failed. Please run "npm run build" manually.');
157
+ }
158
+ }
159
+
160
+ async testConnection() {
161
+ console.log('\nšŸ”„ Testing WordPress connection...');
162
+
163
+ // Ensure TypeScript is compiled
164
+ await this.ensureBuild();
165
+
166
+ try {
167
+ // Create a temporary client to test connection
168
+ const { WordPressClient } = await import('../dist/client/api.js');
169
+ const client = new WordPressClient({
170
+ baseUrl: this.config.WORDPRESS_URL,
171
+ auth: this.getAuthConfig()
172
+ });
173
+
174
+ await client.authenticate();
175
+ const sites = await client.get('/wp/v2/');
176
+
177
+ console.log('āœ… Connection successful!');
178
+ console.log(` Site: ${sites.name || 'WordPress Site'}`);
179
+ console.log(` URL: ${this.config.WORDPRESS_URL}`);
180
+
181
+ } catch (error) {
182
+ console.log('āŒ Connection failed:', error.message);
183
+ const retry = await this.rl.question('Retry with different settings? (y/N): ');
184
+ if (retry.toLowerCase() === 'y') {
185
+ await this.gatherConfiguration();
186
+ return this.testConnection();
187
+ }
188
+ throw error;
189
+ }
190
+ }
191
+
192
+ getAuthConfig() {
193
+ switch (this.config.AUTH_METHOD) {
194
+ case 'app-password':
195
+ return {
196
+ method: 'app-password',
197
+ username: this.config.USERNAME,
198
+ appPassword: this.config.APPLICATION_PASSWORD
199
+ };
200
+ case 'basic':
201
+ return {
202
+ method: 'basic',
203
+ username: this.config.USERNAME,
204
+ password: this.config.PASSWORD
205
+ };
206
+ case 'jwt':
207
+ return {
208
+ method: 'jwt',
209
+ secret: this.config.JWT_SECRET,
210
+ username: this.config.USERNAME,
211
+ password: this.config.PASSWORD
212
+ };
213
+ case 'api-key':
214
+ return {
215
+ method: 'api-key',
216
+ apiKey: this.config.API_KEY,
217
+ secret: this.config.API_SECRET
218
+ };
219
+ default:
220
+ throw new Error('Invalid authentication method');
221
+ }
222
+ }
223
+
224
+ async saveConfiguration() {
225
+ console.log('\nšŸ’¾ Saving configuration...');
226
+
227
+ // Map config keys to environment variable names
228
+ const envVars = {
229
+ 'WORDPRESS_SITE_URL': this.config.WORDPRESS_URL,
230
+ 'WORDPRESS_USERNAME': this.config.USERNAME,
231
+ 'WORDPRESS_AUTH_METHOD': this.config.AUTH_METHOD
232
+ };
233
+
234
+ if (this.config.APPLICATION_PASSWORD) {
235
+ envVars['WORDPRESS_APP_PASSWORD'] = this.config.APPLICATION_PASSWORD;
236
+ }
237
+ if (this.config.PASSWORD) {
238
+ envVars['WORDPRESS_PASSWORD'] = this.config.PASSWORD;
239
+ }
240
+ if (this.config.JWT_SECRET) {
241
+ envVars['WORDPRESS_JWT_SECRET'] = this.config.JWT_SECRET;
242
+ }
243
+ if (this.config.API_KEY) {
244
+ envVars['WORDPRESS_API_KEY'] = this.config.API_KEY;
245
+ }
246
+ if (this.config.API_SECRET) {
247
+ envVars['WORDPRESS_API_SECRET'] = this.config.API_SECRET;
248
+ }
249
+
250
+ const envContent = Object.entries(envVars)
251
+ .map(([key, value]) => `${key}=${value}`)
252
+ .join('\n');
253
+
254
+ writeFileSync(this.envPath, envContent);
255
+ console.log('āœ… Configuration saved to .env file');
256
+ }
257
+
258
+ async showNextSteps() {
259
+ console.log('\nšŸŽ‰ Setup Complete!');
260
+ console.log('==================');
261
+ console.log('\nNext steps:');
262
+ console.log('1. Test the server: npm run status');
263
+ console.log('2. Run integration tests: npm test');
264
+ console.log('3. Start the MCP server: npm start');
265
+ console.log('\nFor Claude Desktop integration:');
266
+ console.log('Add this to your Claude Desktop MCP settings:');
267
+ console.log(`
268
+ {
269
+ "mcpServers": {
270
+ "wordpress": {
271
+ "command": "node",
272
+ "args": ["${join(rootDir, 'dist/index.js')}"],
273
+ "env": {
274
+ "WORDPRESS_SITE_URL": "${this.config.WORDPRESS_URL}",
275
+ "WORDPRESS_AUTH_METHOD": "${this.config.AUTH_METHOD}",
276
+ ${this.getEnvVarsForClaudeConfig()}
277
+ }
278
+ }
279
+ }
280
+ }
281
+ `);
282
+ }
283
+
284
+ getEnvVarsForClaudeConfig() {
285
+ const envVars = [];
286
+ if (this.config.USERNAME) envVars.push(`"WORDPRESS_USERNAME": "${this.config.USERNAME}"`);
287
+ if (this.config.APPLICATION_PASSWORD) envVars.push(`"WORDPRESS_APP_PASSWORD": "${this.config.APPLICATION_PASSWORD}"`);
288
+ if (this.config.PASSWORD) envVars.push(`"WORDPRESS_PASSWORD": "${this.config.PASSWORD}"`);
289
+ if (this.config.JWT_SECRET) envVars.push(`"WORDPRESS_JWT_SECRET": "${this.config.JWT_SECRET}"`);
290
+ if (this.config.API_KEY) envVars.push(`"WORDPRESS_API_KEY": "${this.config.API_KEY}"`);
291
+ if (this.config.API_SECRET) envVars.push(`"WORDPRESS_API_SECRET": "${this.config.API_SECRET}"`);
292
+ return envVars.join(',\n ');
293
+ }
294
+ }
295
+
296
+ // Run setup if called directly
297
+ if (import.meta.url === `file://${process.argv[1]}`) {
298
+ const setup = new WordPressSetup();
299
+ setup.run();
300
+ }
301
+
302
+ export { WordPressSetup };
package/bin/status.js ADDED
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync } from 'fs';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+ import { execSync } from 'child_process';
7
+ import dotenv from 'dotenv';
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+ const rootDir = join(__dirname, '..');
12
+
13
+ class WordPressStatus {
14
+ constructor() {
15
+ this.envPath = join(rootDir, '.env');
16
+ this.loadConfig();
17
+ }
18
+
19
+ loadConfig() {
20
+ if (existsSync(this.envPath)) {
21
+ dotenv.config({ path: this.envPath });
22
+ }
23
+ }
24
+
25
+ async run() {
26
+ console.log('šŸ” WordPress MCP Server Status');
27
+ console.log('==============================\n');
28
+
29
+ await this.checkConfiguration();
30
+ await this.checkWordPressConnection();
31
+ await this.checkMCPServer();
32
+ await this.showSummary();
33
+ }
34
+
35
+ async checkConfiguration() {
36
+ console.log('šŸ“‹ Configuration Check');
37
+ console.log('----------------------');
38
+
39
+ const requiredVars = ['WORDPRESS_SITE_URL'];
40
+ const missingVars = [];
41
+
42
+ for (const varName of requiredVars) {
43
+ if (process.env[varName]) {
44
+ console.log(`āœ… ${varName}: ${this.maskSensitive(varName, process.env[varName])}`);
45
+ } else {
46
+ console.log(`āŒ ${varName}: Missing`);
47
+ missingVars.push(varName);
48
+ }
49
+ }
50
+
51
+ // Check auth credentials (at least one method should be configured)
52
+ const authMethods = [
53
+ { name: 'Application Password', vars: ['WORDPRESS_USERNAME', 'WORDPRESS_APP_PASSWORD'] },
54
+ { name: 'JWT', vars: ['WORDPRESS_JWT_SECRET', 'WORDPRESS_JWT_USERNAME', 'WORDPRESS_JWT_PASSWORD'] },
55
+ { name: 'OAuth', vars: ['WORDPRESS_OAUTH_CLIENT_ID', 'WORDPRESS_OAUTH_CLIENT_SECRET'] },
56
+ { name: 'Cookie', vars: ['WORDPRESS_COOKIE_NONCE'] }
57
+ ];
58
+
59
+ let authConfigured = false;
60
+ for (const method of authMethods) {
61
+ const hasAllVars = method.vars.every(varName => process.env[varName]);
62
+ if (hasAllVars) {
63
+ console.log(`āœ… ${method.name} Authentication: Configured`);
64
+ authConfigured = true;
65
+ method.vars.forEach(varName => {
66
+ console.log(` ${varName}: ${this.maskSensitive(varName, process.env[varName])}`);
67
+ });
68
+ break;
69
+ }
70
+ }
71
+
72
+ if (!authConfigured) {
73
+ console.log('āŒ Authentication: No valid authentication method configured');
74
+ missingVars.push('Authentication credentials');
75
+ }
76
+
77
+ // Optional variables
78
+ const optionalVars = ['DEBUG', 'WORDPRESS_DEBUG', 'CACHE_ENABLED', 'WORDPRESS_TIMEOUT'];
79
+ for (const varName of optionalVars) {
80
+ if (process.env[varName]) {
81
+ console.log(`ā„¹ļø ${varName}: ${process.env[varName]}`);
82
+ }
83
+ }
84
+
85
+ if (missingVars.length > 0) {
86
+ console.log(`\nāŒ Missing required variables: ${missingVars.join(', ')}`);
87
+ console.log('Run: npm run setup');
88
+ return false;
89
+ }
90
+
91
+ console.log('\nāœ… Configuration is complete');
92
+ return true;
93
+ }
94
+
95
+ getAuthVars(authMethod) {
96
+ switch (authMethod) {
97
+ case 'application_password':
98
+ return ['USERNAME', 'APPLICATION_PASSWORD'];
99
+ case 'basic':
100
+ return ['USERNAME', 'PASSWORD'];
101
+ case 'jwt':
102
+ return ['USERNAME', 'PASSWORD', 'JWT_SECRET'];
103
+ case 'api_key':
104
+ return ['API_KEY'];
105
+ default:
106
+ return [];
107
+ }
108
+ }
109
+
110
+ maskSensitive(varName, value) {
111
+ const sensitiveVars = ['PASSWORD', 'APPLICATION_PASSWORD', 'JWT_SECRET', 'API_KEY', 'API_SECRET'];
112
+ if (sensitiveVars.includes(varName)) {
113
+ return value.length > 4 ? value.substring(0, 4) + '...' : '***';
114
+ }
115
+ return value;
116
+ }
117
+
118
+ async checkWordPressConnection() {
119
+ console.log('\n🌐 WordPress Connection Check');
120
+ console.log('-----------------------------');
121
+
122
+ if (!process.env.WORDPRESS_SITE_URL) {
123
+ console.log('āŒ Cannot test connection - WORDPRESS_SITE_URL not configured');
124
+ return false;
125
+ }
126
+
127
+ try {
128
+ const { WordPressClient } = await import('../dist/client/api.js');
129
+ const client = new WordPressClient({
130
+ baseUrl: process.env.WORDPRESS_SITE_URL,
131
+ auth: this.getAuthConfig()
132
+ });
133
+
134
+ // Test basic connectivity
135
+ console.log('šŸ”„ Testing basic connectivity...');
136
+ const response = await fetch(process.env.WORDPRESS_SITE_URL);
137
+ if (response.ok) {
138
+ console.log('āœ… WordPress site is reachable');
139
+ } else {
140
+ console.log(`āŒ WordPress site returned status: ${response.status}`);
141
+ }
142
+
143
+ // Test REST API
144
+ console.log('šŸ”„ Testing REST API...');
145
+ const apiResponse = await fetch(`${process.env.WORDPRESS_SITE_URL}/wp-json/wp/v2/`);
146
+ if (apiResponse.ok) {
147
+ console.log('āœ… WordPress REST API is available');
148
+ } else {
149
+ console.log(`āŒ WordPress REST API returned status: ${apiResponse.status}`);
150
+ }
151
+
152
+ // Test authentication
153
+ console.log('šŸ”„ Testing authentication...');
154
+ const authConfig = this.getAuthConfig();
155
+ console.log('Debug: Auth config:', authConfig);
156
+ await client.authenticate();
157
+ console.log('āœ… Authentication successful');
158
+
159
+ // Test basic API call
160
+ console.log('šŸ”„ Testing API access...');
161
+ const posts = await client.get('posts', { per_page: 1 });
162
+ console.log(`āœ… API access successful (found ${posts.length} posts)`);
163
+
164
+ // Test permissions
165
+ console.log('šŸ”„ Testing permissions...');
166
+ try {
167
+ await client.get('users/me');
168
+ console.log('āœ… User permissions verified');
169
+ } catch (error) {
170
+ console.log(`āš ļø Limited permissions: ${error.message}`);
171
+ }
172
+
173
+ return true;
174
+
175
+ } catch (error) {
176
+ console.log(`āŒ Connection failed: ${error.message}`);
177
+ return false;
178
+ }
179
+ }
180
+
181
+ getAuthConfig() {
182
+ // Use explicit auth method if set
183
+ const authMethod = process.env.WORDPRESS_AUTH_METHOD;
184
+
185
+ if (authMethod === 'app-password' && process.env.WORDPRESS_USERNAME && process.env.WORDPRESS_APP_PASSWORD) {
186
+ return {
187
+ method: 'app-password',
188
+ username: process.env.WORDPRESS_USERNAME,
189
+ appPassword: process.env.WORDPRESS_APP_PASSWORD
190
+ };
191
+ }
192
+
193
+ if (authMethod === 'jwt' && process.env.WORDPRESS_JWT_SECRET) {
194
+ return {
195
+ method: 'jwt',
196
+ secret: process.env.WORDPRESS_JWT_SECRET,
197
+ username: process.env.WORDPRESS_USERNAME,
198
+ password: process.env.WORDPRESS_PASSWORD
199
+ };
200
+ }
201
+
202
+ if (authMethod === 'basic' && process.env.WORDPRESS_USERNAME && process.env.WORDPRESS_PASSWORD) {
203
+ return {
204
+ method: 'basic',
205
+ username: process.env.WORDPRESS_USERNAME,
206
+ password: process.env.WORDPRESS_PASSWORD
207
+ };
208
+ }
209
+
210
+ if (authMethod === 'api-key' && process.env.WORDPRESS_API_KEY) {
211
+ return {
212
+ method: 'api-key',
213
+ apiKey: process.env.WORDPRESS_API_KEY
214
+ };
215
+ }
216
+
217
+ if (authMethod === 'cookie' && process.env.WORDPRESS_COOKIE_NONCE) {
218
+ return {
219
+ method: 'cookie',
220
+ nonce: process.env.WORDPRESS_COOKIE_NONCE
221
+ };
222
+ }
223
+
224
+ // Fallback: Try Application Password if available
225
+ if (process.env.WORDPRESS_USERNAME && process.env.WORDPRESS_APP_PASSWORD) {
226
+ return {
227
+ method: 'app-password',
228
+ username: process.env.WORDPRESS_USERNAME,
229
+ appPassword: process.env.WORDPRESS_APP_PASSWORD
230
+ };
231
+ }
232
+
233
+ return null;
234
+ }
235
+
236
+ async checkMCPServer() {
237
+ console.log('\nšŸ”§ MCP Server Check');
238
+ console.log('-------------------');
239
+
240
+ try {
241
+ // Check if main server file exists
242
+ const serverPath = join(rootDir, 'dist/index.js');
243
+ if (existsSync(serverPath)) {
244
+ console.log('āœ… Main server file exists');
245
+ } else {
246
+ console.log('šŸ”Ø Building TypeScript project...');
247
+ try {
248
+ execSync('npm run build', { cwd: rootDir, stdio: 'pipe' });
249
+ if (existsSync(serverPath)) {
250
+ console.log('āœ… Build successful - server file created');
251
+ } else {
252
+ console.log('āŒ Build failed - server file still missing');
253
+ return false;
254
+ }
255
+ } catch (error) {
256
+ console.log('āŒ TypeScript build failed');
257
+ return false;
258
+ }
259
+ }
260
+
261
+ // Check tool files
262
+ const toolFiles = [
263
+ 'dist/tools/posts.js',
264
+ 'dist/tools/pages.js',
265
+ 'dist/tools/media.js',
266
+ 'dist/tools/users.js',
267
+ 'dist/tools/comments.js',
268
+ 'dist/tools/taxonomies.js',
269
+ 'dist/tools/site.js',
270
+ 'dist/tools/auth.js'
271
+ ];
272
+
273
+ let missingTools = 0;
274
+ for (const toolFile of toolFiles) {
275
+ if (existsSync(join(rootDir, toolFile))) {
276
+ console.log(`āœ… ${toolFile}`);
277
+ } else {
278
+ console.log(`āŒ ${toolFile} missing`);
279
+ missingTools++;
280
+ }
281
+ }
282
+
283
+ if (missingTools > 0) {
284
+ console.log(`āŒ ${missingTools} tool files missing`);
285
+ return false;
286
+ }
287
+
288
+ // Try to import and count tools
289
+ console.log('šŸ”„ Checking tool definitions...');
290
+ const toolCounts = {};
291
+ let totalTools = 0;
292
+
293
+ for (const toolFile of toolFiles) {
294
+ try {
295
+ const module = await import(`../${toolFile}`);
296
+ const toolNames = Object.keys(module).filter(name =>
297
+ !name.startsWith('handle') && typeof module[name] === 'object'
298
+ );
299
+ toolCounts[toolFile] = toolNames.length;
300
+ totalTools += toolNames.length;
301
+ } catch (error) {
302
+ console.log(`āŒ Error loading ${toolFile}: ${error.message}`);
303
+ return false;
304
+ }
305
+ }
306
+
307
+ console.log(`āœ… ${totalTools} tools loaded successfully`);
308
+ for (const [file, count] of Object.entries(toolCounts)) {
309
+ console.log(` ${file}: ${count} tools`);
310
+ }
311
+
312
+ return true;
313
+
314
+ } catch (error) {
315
+ console.log(`āŒ MCP server check failed: ${error.message}`);
316
+ return false;
317
+ }
318
+ }
319
+
320
+ async showSummary() {
321
+ console.log('\nšŸ“Š Status Summary');
322
+ console.log('=================');
323
+
324
+ const checks = [
325
+ await this.checkConfiguration(),
326
+ await this.checkWordPressConnection(),
327
+ await this.checkMCPServer()
328
+ ];
329
+
330
+ const passed = checks.filter(Boolean).length;
331
+ const total = checks.length;
332
+
333
+ if (passed === total) {
334
+ console.log('šŸŽ‰ All systems operational!');
335
+ console.log('\nReady to use with Claude Desktop or other MCP clients.');
336
+ console.log('\nUseful commands:');
337
+ console.log('• npm start - Start the MCP server');
338
+ console.log('• npm test - Run integration tests');
339
+ console.log('• npm run setup - Reconfigure settings');
340
+ } else {
341
+ console.log(`āŒ ${total - passed} of ${total} checks failed`);
342
+ console.log('\nPlease fix the issues above before using the server.');
343
+ console.log('\nHelp:');
344
+ console.log('• npm run setup - Run setup wizard');
345
+ console.log('• npm run status - Check status again');
346
+ }
347
+ }
348
+ }
349
+
350
+ // Run status check if called directly
351
+ if (import.meta.url === `file://${process.argv[1]}`) {
352
+ const status = new WordPressStatus();
353
+ status.run().catch(error => {
354
+ console.error('Status check failed:', error);
355
+ process.exit(1);
356
+ });
357
+ }
358
+
359
+ export { WordPressStatus };