myaidev-method 0.0.1
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/.env.example +9 -0
- package/LICENSE +21 -0
- package/README.md +744 -0
- package/bin/cli.js +228 -0
- package/package.json +59 -0
- package/src/agents/content-writer-prompt.md +164 -0
- package/src/agents/content-writer.json +70 -0
- package/src/index.js +21 -0
- package/src/mcp/ssh-integration.js +488 -0
- package/src/mcp/wordpress-admin-mcp.js +397 -0
- package/src/mcp/wordpress-integration.js +218 -0
- package/src/mcp/wordpress-mcp.json +148 -0
- package/src/templates/claude/agents/content-writer.md +155 -0
- package/src/templates/claude/agents/wordpress-admin.md +240 -0
- package/src/templates/claude/commands/myai-configure.md +104 -0
- package/src/templates/claude/commands/myai-content-writer.md +78 -0
- package/src/templates/claude/commands/myai-wordpress-admin.md +148 -0
- package/src/templates/claude/commands/myai-wordpress-publish.md +55 -0
- package/src/templates/claude/mcp_config.json +30 -0
- package/src/templates/claude/slash_commands.json +166 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
import { WordPressMCP } from './wordpress-integration.js';
|
|
3
|
+
|
|
4
|
+
export class WordPressAdminMCP extends WordPressMCP {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
super(config);
|
|
7
|
+
this.adminCapabilities = {
|
|
8
|
+
security: true,
|
|
9
|
+
performance: true,
|
|
10
|
+
health: true,
|
|
11
|
+
administration: true
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Security Operations
|
|
16
|
+
async securityScan() {
|
|
17
|
+
try {
|
|
18
|
+
const results = {
|
|
19
|
+
wordpress_version: await this.getWordPressVersion(),
|
|
20
|
+
plugins: await this.getPluginSecurityStatus(),
|
|
21
|
+
themes: await this.getThemeSecurityStatus(),
|
|
22
|
+
users: await this.getUserSecurityAudit(),
|
|
23
|
+
files: await this.getFilePermissionsScan(),
|
|
24
|
+
ssl: await this.getSSLStatus(),
|
|
25
|
+
security_headers: await this.getSecurityHeaders()
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
success: true,
|
|
30
|
+
scan_type: 'comprehensive_security',
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
findings: this.analyzeSecurity(results),
|
|
33
|
+
recommendations: this.getSecurityRecommendations(results),
|
|
34
|
+
priority_issues: this.getPrioritySecurityIssues(results)
|
|
35
|
+
};
|
|
36
|
+
} catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
error: error.message,
|
|
40
|
+
scan_type: 'security_scan_failed'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async malwareCheck() {
|
|
46
|
+
try {
|
|
47
|
+
const suspiciousPatterns = [
|
|
48
|
+
'eval\\(', 'base64_decode\\(', 'shell_exec\\(',
|
|
49
|
+
'system\\(', 'exec\\(', 'passthru\\(',
|
|
50
|
+
'\\.php\\?[a-zA-Z0-9]+=\\w+', 'c99shell',
|
|
51
|
+
'r57shell', 'wso\\.php'
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const results = await Promise.all([
|
|
55
|
+
this.scanPluginsForMalware(suspiciousPatterns),
|
|
56
|
+
this.scanThemesForMalware(suspiciousPatterns),
|
|
57
|
+
this.scanUploadsForMalware(suspiciousPatterns),
|
|
58
|
+
this.checkDatabaseForMalware()
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
success: true,
|
|
63
|
+
scan_type: 'malware_detection',
|
|
64
|
+
timestamp: new Date().toISOString(),
|
|
65
|
+
threats_found: results.filter(r => r.threats.length > 0),
|
|
66
|
+
clean_areas: results.filter(r => r.threats.length === 0),
|
|
67
|
+
recommendations: this.getMalwareRecommendations(results)
|
|
68
|
+
};
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: error.message
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async userSecurityAudit() {
|
|
78
|
+
try {
|
|
79
|
+
const users = await this.request('/users?per_page=100&context=edit');
|
|
80
|
+
|
|
81
|
+
const audit = users.map(user => ({
|
|
82
|
+
id: user.id,
|
|
83
|
+
username: user.username,
|
|
84
|
+
email: user.email,
|
|
85
|
+
roles: user.roles,
|
|
86
|
+
capabilities: user.capabilities,
|
|
87
|
+
last_login: user.meta?.last_login || 'unknown',
|
|
88
|
+
registration_date: user.registered_date,
|
|
89
|
+
security_flags: this.analyzeUserSecurity(user)
|
|
90
|
+
}));
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
success: true,
|
|
94
|
+
audit_type: 'user_security',
|
|
95
|
+
timestamp: new Date().toISOString(),
|
|
96
|
+
total_users: users.length,
|
|
97
|
+
admin_users: audit.filter(u => u.roles.includes('administrator')),
|
|
98
|
+
suspicious_users: audit.filter(u => u.security_flags.length > 0),
|
|
99
|
+
recommendations: this.getUserSecurityRecommendations(audit)
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
error: error.message
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Performance Operations
|
|
110
|
+
async performanceAnalysis() {
|
|
111
|
+
try {
|
|
112
|
+
const metrics = await Promise.all([
|
|
113
|
+
this.analyzePageSpeed(),
|
|
114
|
+
this.analyzeDatabasePerformance(),
|
|
115
|
+
this.analyzePluginPerformance(),
|
|
116
|
+
this.analyzeMediaOptimization(),
|
|
117
|
+
this.analyzeCachingStatus()
|
|
118
|
+
]);
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
success: true,
|
|
122
|
+
analysis_type: 'performance_comprehensive',
|
|
123
|
+
timestamp: new Date().toISOString(),
|
|
124
|
+
overall_score: this.calculatePerformanceScore(metrics),
|
|
125
|
+
metrics: metrics,
|
|
126
|
+
recommendations: this.getPerformanceRecommendations(metrics),
|
|
127
|
+
priority_actions: this.getPerformancePriorityActions(metrics)
|
|
128
|
+
};
|
|
129
|
+
} catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
success: false,
|
|
132
|
+
error: error.message
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async databaseOptimization() {
|
|
138
|
+
try {
|
|
139
|
+
const operations = [];
|
|
140
|
+
|
|
141
|
+
// Get database statistics
|
|
142
|
+
const stats = await this.getDatabaseStats();
|
|
143
|
+
|
|
144
|
+
// Cleanup operations
|
|
145
|
+
const cleanupResults = await Promise.all([
|
|
146
|
+
this.cleanupRevisions(),
|
|
147
|
+
this.cleanupSpam(),
|
|
148
|
+
this.cleanupTrash(),
|
|
149
|
+
this.cleanupExpiredTransients(),
|
|
150
|
+
this.optimizeDatabaseTables()
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
success: true,
|
|
155
|
+
operation: 'database_optimization',
|
|
156
|
+
timestamp: new Date().toISOString(),
|
|
157
|
+
before_stats: stats.before,
|
|
158
|
+
after_stats: await this.getDatabaseStats(),
|
|
159
|
+
operations_performed: cleanupResults,
|
|
160
|
+
space_saved: this.calculateSpaceSaved(stats),
|
|
161
|
+
recommendations: this.getDatabaseRecommendations()
|
|
162
|
+
};
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
error: error.message
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Health Operations
|
|
172
|
+
async healthCheck() {
|
|
173
|
+
try {
|
|
174
|
+
const healthChecks = await Promise.all([
|
|
175
|
+
this.checkWordPressUpdates(),
|
|
176
|
+
this.checkPluginUpdates(),
|
|
177
|
+
this.checkThemeUpdates(),
|
|
178
|
+
this.checkFilePermissions(),
|
|
179
|
+
this.checkDiskSpace(),
|
|
180
|
+
this.checkMemoryUsage(),
|
|
181
|
+
this.checkDatabaseHealth(),
|
|
182
|
+
this.checkCronJobs(),
|
|
183
|
+
this.checkErrorLogs()
|
|
184
|
+
]);
|
|
185
|
+
|
|
186
|
+
const overallHealth = this.calculateHealthScore(healthChecks);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
success: true,
|
|
190
|
+
check_type: 'comprehensive_health',
|
|
191
|
+
timestamp: new Date().toISOString(),
|
|
192
|
+
overall_health: overallHealth,
|
|
193
|
+
checks: healthChecks,
|
|
194
|
+
critical_issues: healthChecks.filter(c => c.status === 'critical'),
|
|
195
|
+
warnings: healthChecks.filter(c => c.status === 'warning'),
|
|
196
|
+
recommendations: this.getHealthRecommendations(healthChecks)
|
|
197
|
+
};
|
|
198
|
+
} catch (error) {
|
|
199
|
+
return {
|
|
200
|
+
success: false,
|
|
201
|
+
error: error.message
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async errorLogAnalysis() {
|
|
207
|
+
try {
|
|
208
|
+
// This would require server-level access or plugin integration
|
|
209
|
+
const errorSources = [
|
|
210
|
+
'php_errors',
|
|
211
|
+
'wordpress_debug',
|
|
212
|
+
'plugin_errors',
|
|
213
|
+
'theme_errors',
|
|
214
|
+
'database_errors'
|
|
215
|
+
];
|
|
216
|
+
|
|
217
|
+
const errorAnalysis = await Promise.all(
|
|
218
|
+
errorSources.map(source => this.analyzeErrorSource(source))
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
success: true,
|
|
223
|
+
analysis_type: 'error_log',
|
|
224
|
+
timestamp: new Date().toISOString(),
|
|
225
|
+
error_summary: this.summarizeErrors(errorAnalysis),
|
|
226
|
+
critical_errors: errorAnalysis.filter(e => e.severity === 'critical'),
|
|
227
|
+
frequent_errors: this.getFrequentErrors(errorAnalysis),
|
|
228
|
+
recommendations: this.getErrorRecommendations(errorAnalysis)
|
|
229
|
+
};
|
|
230
|
+
} catch (error) {
|
|
231
|
+
return {
|
|
232
|
+
success: false,
|
|
233
|
+
error: error.message
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Admin Operations
|
|
239
|
+
async pluginManagement(operation, pluginSlug = null) {
|
|
240
|
+
try {
|
|
241
|
+
switch (operation) {
|
|
242
|
+
case 'list':
|
|
243
|
+
return await this.getInstalledPlugins();
|
|
244
|
+
|
|
245
|
+
case 'security_check':
|
|
246
|
+
return await this.checkPluginsSecurity();
|
|
247
|
+
|
|
248
|
+
case 'update_available':
|
|
249
|
+
return await this.getPluginUpdates();
|
|
250
|
+
|
|
251
|
+
case 'activate':
|
|
252
|
+
return await this.activatePlugin(pluginSlug);
|
|
253
|
+
|
|
254
|
+
case 'deactivate':
|
|
255
|
+
return await this.deactivatePlugin(pluginSlug);
|
|
256
|
+
|
|
257
|
+
case 'delete':
|
|
258
|
+
return await this.deletePlugin(pluginSlug);
|
|
259
|
+
|
|
260
|
+
default:
|
|
261
|
+
throw new Error(`Unknown plugin operation: ${operation}`);
|
|
262
|
+
}
|
|
263
|
+
} catch (error) {
|
|
264
|
+
return {
|
|
265
|
+
success: false,
|
|
266
|
+
error: error.message
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async contentCleanup() {
|
|
272
|
+
try {
|
|
273
|
+
const cleanup = await Promise.all([
|
|
274
|
+
this.cleanupSpamComments(),
|
|
275
|
+
this.cleanupDraftPosts(),
|
|
276
|
+
this.cleanupUnusedMedia(),
|
|
277
|
+
this.cleanupOrphanedMetadata(),
|
|
278
|
+
this.cleanupExpiredTransients()
|
|
279
|
+
]);
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
success: true,
|
|
283
|
+
operation: 'content_cleanup',
|
|
284
|
+
timestamp: new Date().toISOString(),
|
|
285
|
+
cleanup_results: cleanup,
|
|
286
|
+
total_items_cleaned: cleanup.reduce((sum, result) => sum + result.items_cleaned, 0),
|
|
287
|
+
space_freed: cleanup.reduce((sum, result) => sum + result.space_freed, 0)
|
|
288
|
+
};
|
|
289
|
+
} catch (error) {
|
|
290
|
+
return {
|
|
291
|
+
success: false,
|
|
292
|
+
error: error.message
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Helper methods for analysis
|
|
298
|
+
analyzeSecurity(results) {
|
|
299
|
+
const findings = {
|
|
300
|
+
critical: [],
|
|
301
|
+
warnings: [],
|
|
302
|
+
passed: []
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// Analyze WordPress version
|
|
306
|
+
if (results.wordpress_version.outdated) {
|
|
307
|
+
findings.critical.push('WordPress version is outdated');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Analyze plugins
|
|
311
|
+
results.plugins.vulnerable.forEach(plugin => {
|
|
312
|
+
findings.critical.push(`Vulnerable plugin detected: ${plugin.name}`);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Analyze users
|
|
316
|
+
results.users.admin_accounts.forEach(user => {
|
|
317
|
+
if (user.weak_password) {
|
|
318
|
+
findings.warnings.push(`Weak password for admin user: ${user.username}`);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
return findings;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
getSecurityRecommendations(results) {
|
|
326
|
+
const recommendations = [];
|
|
327
|
+
|
|
328
|
+
if (results.wordpress_version.outdated) {
|
|
329
|
+
recommendations.push({
|
|
330
|
+
priority: 'high',
|
|
331
|
+
action: 'Update WordPress to latest version',
|
|
332
|
+
impact: 'Critical security patches'
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return recommendations;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
calculateHealthScore(checks) {
|
|
340
|
+
const totalChecks = checks.length;
|
|
341
|
+
const passedChecks = checks.filter(c => c.status === 'passed').length;
|
|
342
|
+
const warningChecks = checks.filter(c => c.status === 'warning').length;
|
|
343
|
+
|
|
344
|
+
// Weighted scoring: passed = 1, warning = 0.5, critical = 0
|
|
345
|
+
const score = ((passedChecks * 1) + (warningChecks * 0.5)) / totalChecks * 100;
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
score: Math.round(score),
|
|
349
|
+
grade: this.getHealthGrade(score),
|
|
350
|
+
total_checks: totalChecks,
|
|
351
|
+
passed: passedChecks,
|
|
352
|
+
warnings: warningChecks,
|
|
353
|
+
critical: checks.filter(c => c.status === 'critical').length
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
getHealthGrade(score) {
|
|
358
|
+
if (score >= 90) return 'A';
|
|
359
|
+
if (score >= 80) return 'B';
|
|
360
|
+
if (score >= 70) return 'C';
|
|
361
|
+
if (score >= 60) return 'D';
|
|
362
|
+
return 'F';
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Placeholder methods (would need actual implementation based on access level)
|
|
366
|
+
async getWordPressVersion() {
|
|
367
|
+
// Implementation would check WP version against latest
|
|
368
|
+
return { current: '6.3.1', latest: '6.4.0', outdated: true };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async getPluginSecurityStatus() {
|
|
372
|
+
// Implementation would check plugins against vulnerability databases
|
|
373
|
+
return { total: 15, vulnerable: [], outdated: [] };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async scanPluginsForMalware(patterns) {
|
|
377
|
+
// Implementation would scan plugin files for suspicious patterns
|
|
378
|
+
return { location: 'plugins', threats: [], files_scanned: 0 };
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
async checkDatabaseForMalware() {
|
|
382
|
+
// Implementation would scan database for malicious content
|
|
383
|
+
return { location: 'database', threats: [], tables_scanned: 0 };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
async analyzePageSpeed() {
|
|
387
|
+
// Implementation would use external APIs like PageSpeed Insights
|
|
388
|
+
return { score: 85, metrics: {} };
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
async getDatabaseStats() {
|
|
392
|
+
// Implementation would query database size and optimization stats
|
|
393
|
+
return { size_mb: 125, tables: 50, optimized: false };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export default WordPressAdminMCP;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
|
|
3
|
+
export class WordPressMCP {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.baseUrl = config.endpoint.url;
|
|
6
|
+
this.apiPath = `/wp-json/${config.endpoint.api_version}`;
|
|
7
|
+
this.auth = Buffer.from(`${config.endpoint.authentication.username}:${config.endpoint.authentication.password}`).toString('base64');
|
|
8
|
+
this.defaults = config.defaults;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async request(endpoint, method = 'GET', data = null) {
|
|
12
|
+
const options = {
|
|
13
|
+
method,
|
|
14
|
+
headers: {
|
|
15
|
+
'Authorization': `Basic ${this.auth}`,
|
|
16
|
+
'Content-Type': 'application/json'
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
if (data && method !== 'GET') {
|
|
21
|
+
options.body = JSON.stringify(data);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const response = await fetch(`${this.baseUrl}${this.apiPath}${endpoint}`, options);
|
|
25
|
+
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const error = await response.text();
|
|
28
|
+
throw new Error(`WordPress API Error: ${response.status} - ${error}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return response.json();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async createPost(params) {
|
|
35
|
+
const postData = {
|
|
36
|
+
title: params.title,
|
|
37
|
+
content: params.content,
|
|
38
|
+
status: params.status || this.defaults.post_status,
|
|
39
|
+
categories: params.categories || [],
|
|
40
|
+
tags: params.tags || [],
|
|
41
|
+
format: params.format || this.defaults.format,
|
|
42
|
+
comment_status: params.comment_status || this.defaults.comment_status,
|
|
43
|
+
ping_status: params.ping_status || this.defaults.ping_status
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
if (params.excerpt) {
|
|
47
|
+
postData.excerpt = params.excerpt;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (params.featured_media) {
|
|
51
|
+
postData.featured_media = params.featured_media;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (params.meta) {
|
|
55
|
+
postData.meta = params.meta;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (params.slug) {
|
|
59
|
+
postData.slug = params.slug;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return this.request('/posts', 'POST', postData);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async updatePost(id, params) {
|
|
66
|
+
const updateData = {};
|
|
67
|
+
|
|
68
|
+
if (params.title) updateData.title = params.title;
|
|
69
|
+
if (params.content) updateData.content = params.content;
|
|
70
|
+
if (params.status) updateData.status = params.status;
|
|
71
|
+
if (params.categories) updateData.categories = params.categories;
|
|
72
|
+
if (params.tags) updateData.tags = params.tags;
|
|
73
|
+
if (params.excerpt) updateData.excerpt = params.excerpt;
|
|
74
|
+
if (params.featured_media) updateData.featured_media = params.featured_media;
|
|
75
|
+
if (params.slug) updateData.slug = params.slug;
|
|
76
|
+
|
|
77
|
+
return this.request(`/posts/${id}`, 'POST', updateData);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async getPost(id, context = 'view') {
|
|
81
|
+
return this.request(`/posts/${id}?context=${context}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async listPosts(params = {}) {
|
|
85
|
+
const queryParams = new URLSearchParams();
|
|
86
|
+
|
|
87
|
+
if (params.per_page) queryParams.append('per_page', params.per_page);
|
|
88
|
+
if (params.page) queryParams.append('page', params.page);
|
|
89
|
+
if (params.status) queryParams.append('status', params.status);
|
|
90
|
+
if (params.search) queryParams.append('search', params.search);
|
|
91
|
+
if (params.categories) queryParams.append('categories', params.categories.join(','));
|
|
92
|
+
if (params.tags) queryParams.append('tags', params.tags.join(','));
|
|
93
|
+
|
|
94
|
+
const query = queryParams.toString();
|
|
95
|
+
return this.request(`/posts${query ? `?${query}` : ''}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async uploadMedia(file, metadata = {}) {
|
|
99
|
+
const formData = new FormData();
|
|
100
|
+
formData.append('file', file);
|
|
101
|
+
|
|
102
|
+
if (metadata.title) formData.append('title', metadata.title);
|
|
103
|
+
if (metadata.alt_text) formData.append('alt_text', metadata.alt_text);
|
|
104
|
+
if (metadata.caption) formData.append('caption', metadata.caption);
|
|
105
|
+
if (metadata.description) formData.append('description', metadata.description);
|
|
106
|
+
|
|
107
|
+
const response = await fetch(`${this.baseUrl}${this.apiPath}/media`, {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: {
|
|
110
|
+
'Authorization': `Basic ${this.auth}`
|
|
111
|
+
},
|
|
112
|
+
body: formData
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
const error = await response.text();
|
|
117
|
+
throw new Error(`Media Upload Error: ${response.status} - ${error}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return response.json();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async createCategory(params) {
|
|
124
|
+
const categoryData = {
|
|
125
|
+
name: params.name,
|
|
126
|
+
slug: params.slug || params.name.toLowerCase().replace(/\s+/g, '-'),
|
|
127
|
+
description: params.description || ''
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
if (params.parent) {
|
|
131
|
+
categoryData.parent = params.parent;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return this.request('/categories', 'POST', categoryData);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async createTag(params) {
|
|
138
|
+
const tagData = {
|
|
139
|
+
name: params.name,
|
|
140
|
+
slug: params.slug || params.name.toLowerCase().replace(/\s+/g, '-'),
|
|
141
|
+
description: params.description || ''
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return this.request('/tags', 'POST', tagData);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async getCategories() {
|
|
148
|
+
return this.request('/categories');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async getTags() {
|
|
152
|
+
return this.request('/tags');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Helper method to publish content from content-writer agent
|
|
156
|
+
async publishContent(contentData) {
|
|
157
|
+
try {
|
|
158
|
+
// Create tags if they don't exist
|
|
159
|
+
const tags = [];
|
|
160
|
+
if (contentData.tags && contentData.tags.length > 0) {
|
|
161
|
+
for (const tagName of contentData.tags) {
|
|
162
|
+
try {
|
|
163
|
+
const tag = await this.createTag({ name: tagName });
|
|
164
|
+
tags.push(tag.id);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
// Tag might already exist, try to find it
|
|
167
|
+
const existingTags = await this.getTags();
|
|
168
|
+
const found = existingTags.find(t => t.name.toLowerCase() === tagName.toLowerCase());
|
|
169
|
+
if (found) tags.push(found.id);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Create category if it doesn't exist
|
|
175
|
+
let categoryId = null;
|
|
176
|
+
if (contentData.category) {
|
|
177
|
+
try {
|
|
178
|
+
const category = await this.createCategory({ name: contentData.category });
|
|
179
|
+
categoryId = category.id;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
// Category might already exist
|
|
182
|
+
const existingCategories = await this.getCategories();
|
|
183
|
+
const found = existingCategories.find(c => c.name.toLowerCase() === contentData.category.toLowerCase());
|
|
184
|
+
if (found) categoryId = found.id;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Prepare post data
|
|
189
|
+
const postParams = {
|
|
190
|
+
title: contentData.title,
|
|
191
|
+
content: contentData.content,
|
|
192
|
+
excerpt: contentData.meta_description,
|
|
193
|
+
slug: contentData.slug,
|
|
194
|
+
status: 'draft', // Always create as draft for review
|
|
195
|
+
tags: tags,
|
|
196
|
+
categories: categoryId ? [categoryId] : []
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Create the post
|
|
200
|
+
const post = await this.createPost(postParams);
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
success: true,
|
|
204
|
+
post_id: post.id,
|
|
205
|
+
post_url: post.link,
|
|
206
|
+
edit_url: `${this.baseUrl}/wp-admin/post.php?post=${post.id}&action=edit`,
|
|
207
|
+
message: `Draft post created successfully. ID: ${post.id}`
|
|
208
|
+
};
|
|
209
|
+
} catch (error) {
|
|
210
|
+
return {
|
|
211
|
+
success: false,
|
|
212
|
+
error: error.message
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export default WordPressMCP;
|