myaidev-method 0.2.22 → 0.2.24-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.
Files changed (59) hide show
  1. package/USER_GUIDE.md +453 -48
  2. package/bin/cli.js +236 -38
  3. package/content-rules.example.md +80 -0
  4. package/dist/mcp/mcp-launcher.js +237 -0
  5. package/dist/server/.tsbuildinfo +1 -1
  6. package/dist/server/auth/layers.d.ts +1 -1
  7. package/dist/server/auth/services/AuthService.d.ts +1 -1
  8. package/dist/server/auth/services/TokenService.js.map +1 -1
  9. package/dist/server/auth/services/example.d.ts +5 -5
  10. package/package.json +22 -17
  11. package/src/config/workflows.js +28 -44
  12. package/src/index.js +21 -8
  13. package/src/lib/ascii-banner.js +214 -0
  14. package/src/lib/config-manager.js +470 -0
  15. package/src/lib/content-generator.js +427 -0
  16. package/src/lib/html-conversion-utils.js +843 -0
  17. package/src/lib/seo-optimizer.js +515 -0
  18. package/src/lib/update-manager.js +2 -1
  19. package/src/lib/visual-config-utils.js +321 -295
  20. package/src/lib/visual-generation-utils.js +1000 -811
  21. package/src/lib/wordpress-client.js +633 -0
  22. package/src/lib/workflow-installer.js +3 -3
  23. package/src/scripts/configure-wordpress-mcp.js +8 -3
  24. package/src/scripts/generate-visual-cli.js +365 -235
  25. package/src/scripts/html-conversion-cli.js +526 -0
  26. package/src/scripts/init/configure.js +436 -0
  27. package/src/scripts/init/install.js +460 -0
  28. package/src/scripts/ping.js +250 -0
  29. package/src/scripts/utils/file-utils.js +404 -0
  30. package/src/scripts/utils/logger.js +300 -0
  31. package/src/scripts/utils/write-content.js +293 -0
  32. package/src/scripts/wordpress/publish-to-wordpress.js +165 -0
  33. package/src/server/auth/services/TokenService.ts +1 -1
  34. package/src/templates/claude/agents/content-rules-setup.md +657 -0
  35. package/src/templates/claude/agents/content-writer.md +328 -1
  36. package/src/templates/claude/agents/visual-content-generator.md +311 -8
  37. package/src/templates/claude/commands/myai-configure.md +1 -1
  38. package/src/templates/claude/commands/myai-content-rules-setup.md +204 -0
  39. package/src/templates/claude/commands/myai-convert-html.md +186 -0
  40. package/src/templates/codex/commands/myai-content-rules-setup.md +85 -0
  41. package/src/templates/diagrams/architecture.d2 +52 -0
  42. package/src/templates/diagrams/flowchart.d2 +42 -0
  43. package/src/templates/diagrams/sequence.d2 +47 -0
  44. package/src/templates/docs/content-creation-guide.md +164 -0
  45. package/src/templates/docs/deployment-guide.md +336 -0
  46. package/src/templates/docs/visual-generation-guide.md +248 -0
  47. package/src/templates/docs/wordpress-publishing-guide.md +208 -0
  48. package/src/templates/gemini/commands/myai-content-rules-setup.toml +57 -0
  49. package/src/templates/infographics/comparison-table.html +347 -0
  50. package/src/templates/infographics/data-chart.html +268 -0
  51. package/src/templates/infographics/process-flow.html +365 -0
  52. package/.claude/mcp/sparc-orchestrator-server.js +0 -607
  53. package/.claude/mcp/wordpress-server.js +0 -1277
  54. package/src/agents/content-writer-prompt.md +0 -164
  55. package/src/agents/content-writer.json +0 -70
  56. package/src/templates/claude/mcp_config.json +0 -74
  57. package/src/templates/claude/slash_commands.json +0 -166
  58. package/src/templates/scripts/configure-wordpress-mcp.js +0 -181
  59. /package/src/scripts/{wordpress-health-check.js → wordpress/wordpress-health-check.js} +0 -0
package/bin/cli.js CHANGED
@@ -7,7 +7,17 @@ import fs from 'fs-extra';
7
7
  import path from 'path';
8
8
  import { fileURLToPath } from 'url';
9
9
  import inquirer from 'inquirer';
10
- import { getASCIIBanner, getSPARCBreakdown, getInitSuccessMessage } from '../src/lib/ascii-banner.js';
10
+ import {
11
+ getASCIIBanner,
12
+ getSPARCBreakdown,
13
+ getInitSuccessMessage,
14
+ getWorkflowBanner,
15
+ getContentWorkflowSuccess,
16
+ getVisualWorkflowSuccess,
17
+ getDevWorkflowSuccess,
18
+ getPublishWorkflowSuccess,
19
+ getDeployWorkflowSuccess
20
+ } from '../src/lib/ascii-banner.js';
11
21
 
12
22
  const __filename = fileURLToPath(import.meta.url);
13
23
  const __dirname = path.dirname(__filename);
@@ -31,53 +41,174 @@ program
31
41
  .version('0.2.22')
32
42
  .description('MyAIDev Method - Comprehensive development framework with SPARC methodology');
33
43
 
44
+ // Helper function for CLI type selection
45
+ async function selectCLIType(options) {
46
+ if (options.claude) return 'claude';
47
+ if (options.gemini) return 'gemini';
48
+ if (options.codex) return 'codex';
49
+
50
+ // Interactive selection if no flag provided
51
+ const answer = await inquirer.prompt([
52
+ {
53
+ type: 'list',
54
+ name: 'cliType',
55
+ message: 'Which AI CLI are you configuring for?',
56
+ choices: [
57
+ { name: 'Claude Code (Recommended)', value: 'claude' },
58
+ { name: 'Gemini CLI', value: 'gemini' },
59
+ { name: 'Codex CLI / OpenCode', value: 'codex' }
60
+ ],
61
+ default: 'claude'
62
+ }
63
+ ]);
64
+ return answer.cliType;
65
+ }
66
+
34
67
  // Modular workflow installation commands
35
68
  program
36
69
  .command('content')
37
70
  .description('Install content creation workflow')
38
71
  .option('--claude', 'Install for Claude Code')
72
+ .option('--gemini', 'Install for Gemini CLI')
73
+ .option('--codex', 'Install for Codex CLI')
39
74
  .option('--dry-run', 'Show what would be installed without making changes')
40
75
  .option('--verbose', 'Show detailed progress')
41
76
  .action(async (options) => {
42
- await loadWorkflowSystem();
43
- const installer = new WorkflowInstaller({
44
- projectRoot: process.cwd(),
45
- verbose: options.verbose,
46
- dryRun: options.dryRun
47
- });
48
- await installer.install(['content']);
77
+ // Display workflow banner
78
+ console.log(getWorkflowBanner('content'));
79
+
80
+ const cliType = await selectCLIType(options);
81
+
82
+ // For non-Claude CLIs, inform user about limited support
83
+ if (cliType !== 'claude') {
84
+ console.log(chalk.yellow(`\nNote: Content workflow is optimized for Claude Code.`));
85
+ console.log(chalk.gray(`Some features may have limited support for ${cliType}.\n`));
86
+ }
87
+
88
+ const spinner = ora('Installing content creation workflow...').start();
89
+
90
+ try {
91
+ await loadWorkflowSystem();
92
+ const installer = new WorkflowInstaller({
93
+ projectRoot: process.cwd(),
94
+ verbose: options.verbose,
95
+ dryRun: options.dryRun
96
+ });
97
+ const result = await installer.install(['content']);
98
+
99
+ if (options.dryRun) {
100
+ spinner.succeed(chalk.yellow('Dry run complete - no changes made'));
101
+ } else {
102
+ spinner.succeed(chalk.green('Content workflow installed successfully!'));
103
+
104
+ // Display rich success message
105
+ console.log(getContentWorkflowSuccess(result.results || [], cliType));
106
+
107
+ console.log(chalk.cyan(`\n🔄 Restart ${cliType} to load your new content commands!`));
108
+ }
109
+ } catch (error) {
110
+ spinner.fail(chalk.red('Failed to install content workflow'));
111
+ console.error(chalk.red(error.message));
112
+ if (options.verbose) console.error(error);
113
+ process.exit(1);
114
+ }
49
115
  });
50
116
 
51
117
  program
52
118
  .command('visual')
53
119
  .description('Install visual content generation workflow')
54
120
  .option('--claude', 'Install for Claude Code')
121
+ .option('--gemini', 'Install for Gemini CLI')
122
+ .option('--codex', 'Install for Codex CLI')
55
123
  .option('--dry-run', 'Show what would be installed without making changes')
56
124
  .option('--verbose', 'Show detailed progress')
57
125
  .action(async (options) => {
58
- await loadWorkflowSystem();
59
- const installer = new WorkflowInstaller({
60
- projectRoot: process.cwd(),
61
- verbose: options.verbose,
62
- dryRun: options.dryRun
63
- });
64
- await installer.install(['visual']);
126
+ // Display workflow banner
127
+ console.log(getWorkflowBanner('visual'));
128
+
129
+ const cliType = await selectCLIType(options);
130
+
131
+ // For non-Claude CLIs, inform user about limited support
132
+ if (cliType !== 'claude') {
133
+ console.log(chalk.yellow(`\nNote: Visual workflow is optimized for Claude Code.`));
134
+ console.log(chalk.gray(`Some features may have limited support for ${cliType}.\n`));
135
+ }
136
+
137
+ const spinner = ora('Installing visual content generation workflow...').start();
138
+
139
+ try {
140
+ await loadWorkflowSystem();
141
+ const installer = new WorkflowInstaller({
142
+ projectRoot: process.cwd(),
143
+ verbose: options.verbose,
144
+ dryRun: options.dryRun
145
+ });
146
+ const result = await installer.install(['visual']);
147
+
148
+ if (options.dryRun) {
149
+ spinner.succeed(chalk.yellow('Dry run complete - no changes made'));
150
+ } else {
151
+ spinner.succeed(chalk.green('Visual workflow installed successfully!'));
152
+
153
+ // Display rich success message
154
+ console.log(getVisualWorkflowSuccess(result.results || [], cliType));
155
+
156
+ console.log(chalk.cyan(`\n🔄 Restart ${cliType} to load your new visual commands!`));
157
+ }
158
+ } catch (error) {
159
+ spinner.fail(chalk.red('Failed to install visual workflow'));
160
+ console.error(chalk.red(error.message));
161
+ if (options.verbose) console.error(error);
162
+ process.exit(1);
163
+ }
65
164
  });
66
165
 
67
166
  program
68
167
  .command('dev')
69
168
  .description('Install development workflow (SPARC methodology)')
70
169
  .option('--claude', 'Install for Claude Code')
170
+ .option('--gemini', 'Install for Gemini CLI')
171
+ .option('--codex', 'Install for Codex CLI')
71
172
  .option('--dry-run', 'Show what would be installed without making changes')
72
173
  .option('--verbose', 'Show detailed progress')
73
174
  .action(async (options) => {
74
- await loadWorkflowSystem();
75
- const installer = new WorkflowInstaller({
76
- projectRoot: process.cwd(),
77
- verbose: options.verbose,
78
- dryRun: options.dryRun
79
- });
80
- await installer.install(['development']);
175
+ // Display workflow banner
176
+ console.log(getWorkflowBanner('development'));
177
+
178
+ const cliType = await selectCLIType(options);
179
+
180
+ if (cliType !== 'claude') {
181
+ console.log(chalk.yellow(`\nNote: Development workflow is optimized for Claude Code.`));
182
+ console.log(chalk.gray(`Some features may have limited support for ${cliType}.\n`));
183
+ }
184
+
185
+ const spinner = ora('Installing SPARC development workflow...').start();
186
+
187
+ try {
188
+ await loadWorkflowSystem();
189
+ const installer = new WorkflowInstaller({
190
+ projectRoot: process.cwd(),
191
+ verbose: options.verbose,
192
+ dryRun: options.dryRun
193
+ });
194
+ const result = await installer.install(['development']);
195
+
196
+ if (options.dryRun) {
197
+ spinner.succeed(chalk.yellow('Dry run complete - no changes made'));
198
+ } else {
199
+ spinner.succeed(chalk.green('Development workflow installed successfully!'));
200
+
201
+ // Display rich success message
202
+ console.log(getDevWorkflowSuccess(result.results || [], cliType));
203
+
204
+ console.log(chalk.cyan(`\n🔄 Restart ${cliType} to load your new development commands!`));
205
+ }
206
+ } catch (error) {
207
+ spinner.fail(chalk.red('Failed to install development workflow'));
208
+ console.error(chalk.red(error.message));
209
+ if (options.verbose) console.error(error);
210
+ process.exit(1);
211
+ }
81
212
  });
82
213
 
83
214
  program
@@ -90,7 +221,9 @@ program
90
221
  .option('--dry-run', 'Show what would be installed without making changes')
91
222
  .option('--verbose', 'Show detailed progress')
92
223
  .action(async (options) => {
93
- await loadWorkflowSystem();
224
+ // Display workflow banner
225
+ console.log(getWorkflowBanner('publish'));
226
+
94
227
  const workflows = [];
95
228
  if (options.wordpress) workflows.push('publish-wordpress');
96
229
  if (options.payloadcms) workflows.push('publish-payloadcms');
@@ -103,12 +236,34 @@ program
103
236
  console.log(chalk.gray(' --wordpress, --payloadcms, --static, or --all'));
104
237
  process.exit(1);
105
238
  }
106
- const installer = new WorkflowInstaller({
107
- projectRoot: process.cwd(),
108
- verbose: options.verbose,
109
- dryRun: options.dryRun
110
- });
111
- await installer.install(workflows);
239
+
240
+ const spinner = ora('Installing publishing workflows...').start();
241
+
242
+ try {
243
+ await loadWorkflowSystem();
244
+ const installer = new WorkflowInstaller({
245
+ projectRoot: process.cwd(),
246
+ verbose: options.verbose,
247
+ dryRun: options.dryRun
248
+ });
249
+ const result = await installer.install(workflows);
250
+
251
+ if (options.dryRun) {
252
+ spinner.succeed(chalk.yellow('Dry run complete - no changes made'));
253
+ } else {
254
+ spinner.succeed(chalk.green('Publishing workflows installed successfully!'));
255
+
256
+ // Display rich success message
257
+ console.log(getPublishWorkflowSuccess(workflows, result.results || [], 'claude'));
258
+
259
+ console.log(chalk.cyan(`\n🔄 Restart Claude Code to load your new publishing commands!`));
260
+ }
261
+ } catch (error) {
262
+ spinner.fail(chalk.red('Failed to install publishing workflows'));
263
+ console.error(chalk.red(error.message));
264
+ if (options.verbose) console.error(error);
265
+ process.exit(1);
266
+ }
112
267
  });
113
268
 
114
269
  program
@@ -119,19 +274,43 @@ program
119
274
  .option('--dry-run', 'Show what would be installed without making changes')
120
275
  .option('--verbose', 'Show detailed progress')
121
276
  .action(async (options) => {
122
- await loadWorkflowSystem();
277
+ // Display workflow banner
278
+ console.log(getWorkflowBanner('deploy'));
279
+
123
280
  const workflows = [];
124
281
  if (options.coolify) workflows.push('coolify');
125
282
  if (options.all) workflows.push('deployment', 'coolify');
126
283
  if (workflows.length === 0) {
127
284
  workflows.push('deployment');
128
285
  }
129
- const installer = new WorkflowInstaller({
130
- projectRoot: process.cwd(),
131
- verbose: options.verbose,
132
- dryRun: options.dryRun
133
- });
134
- await installer.install(workflows);
286
+
287
+ const spinner = ora('Installing deployment workflows...').start();
288
+
289
+ try {
290
+ await loadWorkflowSystem();
291
+ const installer = new WorkflowInstaller({
292
+ projectRoot: process.cwd(),
293
+ verbose: options.verbose,
294
+ dryRun: options.dryRun
295
+ });
296
+ const result = await installer.install(workflows);
297
+
298
+ if (options.dryRun) {
299
+ spinner.succeed(chalk.yellow('Dry run complete - no changes made'));
300
+ } else {
301
+ spinner.succeed(chalk.green('Deployment workflows installed successfully!'));
302
+
303
+ // Display rich success message
304
+ console.log(getDeployWorkflowSuccess(workflows, result.results || [], 'claude'));
305
+
306
+ console.log(chalk.cyan(`\n🔄 Restart Claude Code to load your new deployment commands!`));
307
+ }
308
+ } catch (error) {
309
+ spinner.fail(chalk.red('Failed to install deployment workflows'));
310
+ console.error(chalk.red(error.message));
311
+ if (options.verbose) console.error(error);
312
+ process.exit(1);
313
+ }
135
314
  });
136
315
 
137
316
  // Workflow management commands
@@ -210,11 +389,12 @@ program
210
389
  {
211
390
  type: 'list',
212
391
  name: 'cliType',
213
- message: 'Which AI CLI are you configuring for?',
392
+ message: 'Which AI CLI are you configuring for? (claude|gemini|codex|opencode)',
214
393
  choices: [
215
394
  { name: 'Claude Code', value: 'claude' },
216
395
  { name: 'Gemini CLI', value: 'gemini' },
217
- { name: 'Codex CLI', value: 'codex' }
396
+ { name: 'Codex CLI', value: 'codex' },
397
+ { name: 'Opencode CLI', value: 'opencode'}
218
398
  ]
219
399
  }
220
400
  ]);
@@ -663,6 +843,24 @@ This configuration follows Claude Code's official standards for custom commands
663
843
  }
664
844
  }
665
845
 
846
+ // Copy template documentation (WordPress integration, etc.)
847
+ const templateDocsDir = path.join(__dirname, '..', 'src', 'templates', 'docs');
848
+ if (await fs.pathExists(templateDocsDir)) {
849
+ const docFiles = await fs.readdir(templateDocsDir);
850
+ for (const file of docFiles) {
851
+ if (file.endsWith('.md')) {
852
+ const destPath = path.join(projectDir, file);
853
+ // Only copy if destination doesn't exist (don't overwrite user customizations)
854
+ if (!await fs.pathExists(destPath)) {
855
+ await fs.copy(
856
+ path.join(templateDocsDir, file),
857
+ destPath
858
+ );
859
+ }
860
+ }
861
+ }
862
+ }
863
+
666
864
  // Create content-rules.md if it doesn't already exist
667
865
  const contentRulesPath = path.join(projectDir, 'content-rules.md');
668
866
  if (!await fs.pathExists(contentRulesPath)) {
@@ -141,6 +141,54 @@ This file contains custom rules and guidelines for the content-writer agent. Cop
141
141
  - Prerequisites and materials list
142
142
  - Troubleshooting section
143
143
 
144
+ ## Prohibited Words & Phrases
145
+
146
+ NEVER use these AI filler words and clichéd phrases:
147
+
148
+ ### Generic AI Filler Words
149
+ - "robust"
150
+ - "leverage"
151
+ - "streamline"
152
+ - "optimize"
153
+ - "enhance"
154
+ - "cutting-edge"
155
+ - "game-changing"
156
+ - "innovative"
157
+ - "seamless"
158
+ - "holistic"
159
+ - "synergy"
160
+ - "empower"
161
+
162
+ ### Overused Transitions
163
+ - "delve"
164
+ - "unlock"
165
+ - "harness"
166
+ - "dive into"
167
+ - "in conclusion"
168
+ - "it's worth noting"
169
+ - "at the end of the day"
170
+
171
+ ### Buzzwords to Avoid
172
+ - "landscape"
173
+ - "paradigm"
174
+ - "disruptive"
175
+ - "best-in-class"
176
+ - "world-class"
177
+ - "revolutionary"
178
+ - "transformative"
179
+ - "mission-critical"
180
+
181
+ ### Hyperbolic Adjectives
182
+ - "stunning"
183
+ - "incredible"
184
+ - "amazing"
185
+ - "powerful"
186
+ - "perfect"
187
+ - "comprehensive"
188
+ - "crucial"
189
+ - "critical"
190
+ - "essential"
191
+
144
192
  ## Topics & Restrictions
145
193
 
146
194
  ### Topics to Avoid
@@ -178,6 +226,38 @@ This file contains custom rules and guidelines for the content-writer agent. Cop
178
226
  - Structure content for screen readers
179
227
  - Use simple language for complex topics
180
228
 
229
+ ## Visual Content Preferences
230
+
231
+ ### Visual Importance
232
+ - **Level**: Essential - Every piece needs images/diagrams
233
+ - **Style**: Clean & minimal - Simple, professional graphics
234
+
235
+ ### Image Types by Content
236
+ | Content Type | Recommended Visuals |
237
+ |--------------|---------------------|
238
+ | Blog Posts | Hero image + 1-2 illustrations |
239
+ | Technical Tutorials | Hero + diagrams + code screenshots |
240
+ | API Documentation | Sequence diagrams + endpoint examples |
241
+ | Architecture Guides | Architecture diagrams + flowcharts |
242
+ | Listicles | Hero + item graphics + summary infographic |
243
+ | Comparison Guides | Comparison infographic + decision flowchart |
244
+
245
+ ### Infographic Preferences
246
+ - **Data Visualization**: Include for statistics and metrics
247
+ - **Process Flows**: Use for step-by-step explanations
248
+ - **Comparisons**: Side-by-side infographics for versus content
249
+ - **Style**: Modern flat design, brand colors, clear typography
250
+
251
+ ### Diagram Style
252
+ - **Architecture**: Isometric or flat technical illustration
253
+ - **Flowcharts**: Standard shapes (diamonds, rectangles, ovals)
254
+ - **Sequence**: UML-style with lifelines and arrows
255
+
256
+ ### Visual Generation Services
257
+ - **Primary**: Gemini (fast, cost-effective)
258
+ - **Text-Heavy**: GPT Image 1.5 (best text rendering)
259
+ - **Detailed**: FLUX 2 Pro (excellent detail)
260
+
181
261
  ## Brand-Specific Requirements
182
262
 
183
263
  ### Company Information
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP Server Launcher Script
5
+ * Manages MCP server lifecycle with proper error handling and configuration
6
+ */
7
+
8
+ import { spawn } from 'child_process';
9
+ import { promises as fs } from 'fs';
10
+ import path from 'path';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+
15
+ class MCPLauncher {
16
+ constructor() {
17
+ this.serverProcess = null;
18
+ this.serverPath = path.resolve(__dirname, '../../.claude/mcp/wordpress-server.js');
19
+ this.isShuttingDown = false;
20
+ }
21
+
22
+ log(message, level = 'info') {
23
+ const timestamp = new Date().toISOString();
24
+ const prefix = {
25
+ info: '🔧',
26
+ success: '✅',
27
+ error: '❌',
28
+ warn: '⚠️'
29
+ }[level] || 'ℹ️';
30
+
31
+ console.log(`[${timestamp}] ${prefix} ${message}`);
32
+ }
33
+
34
+ async validateEnvironment() {
35
+ this.log('Validating environment configuration...');
36
+
37
+ const required = ['WORDPRESS_URL', 'WORDPRESS_USERNAME', 'WORDPRESS_APP_PASSWORD'];
38
+ const missing = required.filter(key => !process.env[key]);
39
+
40
+ if (missing.length > 0) {
41
+ throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
42
+ }
43
+
44
+ this.log('Environment validation passed', 'success');
45
+ }
46
+
47
+ async validateServerFile() {
48
+ this.log('Checking MCP server file...');
49
+
50
+ try {
51
+ await fs.access(this.serverPath);
52
+ this.log('MCP server file found', 'success');
53
+ } catch (error) {
54
+ throw new Error(`MCP server file not found: ${this.serverPath}`);
55
+ }
56
+ }
57
+
58
+ async startServer() {
59
+ if (this.serverProcess) {
60
+ this.log('Server is already running', 'warn');
61
+ return;
62
+ }
63
+
64
+ this.log('Starting Enhanced WordPress MCP Server...');
65
+
66
+ this.serverProcess = spawn('node', [this.serverPath], {
67
+ stdio: ['inherit', 'pipe', 'pipe'],
68
+ env: process.env
69
+ });
70
+
71
+ // Handle server output
72
+ this.serverProcess.stdout.on('data', (data) => {
73
+ const output = data.toString().trim();
74
+ if (output) {
75
+ console.log(`[SERVER] ${output}`);
76
+ }
77
+ });
78
+
79
+ this.serverProcess.stderr.on('data', (data) => {
80
+ const output = data.toString().trim();
81
+ if (output) {
82
+ if (output.includes('Enhanced WordPress MCP Server') && output.includes('running')) {
83
+ this.log('MCP Server started successfully', 'success');
84
+ this.log(`Server PID: ${this.serverProcess.pid}`);
85
+ this.log('MCP Server is ready to accept connections');
86
+ } else if (output.includes('ERROR') || output.includes('Error')) {
87
+ this.log(`Server error: ${output}`, 'error');
88
+ } else {
89
+ console.log(`[SERVER] ${output}`);
90
+ }
91
+ }
92
+ });
93
+
94
+ // Handle server exit
95
+ this.serverProcess.on('exit', (code, signal) => {
96
+ if (!this.isShuttingDown) {
97
+ if (code === 0) {
98
+ this.log('Server exited gracefully');
99
+ } else {
100
+ this.log(`Server exited with code ${code} (signal: ${signal})`, 'error');
101
+ }
102
+ }
103
+ this.serverProcess = null;
104
+ });
105
+
106
+ this.serverProcess.on('error', (error) => {
107
+ this.log(`Server startup error: ${error.message}`, 'error');
108
+ this.serverProcess = null;
109
+ });
110
+
111
+ // Setup graceful shutdown
112
+ this.setupShutdownHandlers();
113
+ }
114
+
115
+ setupShutdownHandlers() {
116
+ const shutdown = async (signal) => {
117
+ if (this.isShuttingDown) return;
118
+
119
+ this.isShuttingDown = true;
120
+ this.log(`Received ${signal}, shutting down gracefully...`);
121
+
122
+ if (this.serverProcess) {
123
+ this.log('Stopping MCP server...');
124
+ this.serverProcess.kill('SIGTERM');
125
+
126
+ // Force kill after 10 seconds
127
+ setTimeout(() => {
128
+ if (this.serverProcess) {
129
+ this.log('Force killing server...', 'warn');
130
+ this.serverProcess.kill('SIGKILL');
131
+ }
132
+ }, 10000);
133
+
134
+ // Wait for server to exit
135
+ await new Promise((resolve) => {
136
+ if (!this.serverProcess) {
137
+ resolve();
138
+ return;
139
+ }
140
+
141
+ this.serverProcess.on('exit', () => {
142
+ resolve();
143
+ });
144
+ });
145
+ }
146
+
147
+ this.log('Shutdown complete');
148
+ process.exit(0);
149
+ };
150
+
151
+ process.on('SIGINT', () => shutdown('SIGINT'));
152
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
153
+ process.on('SIGHUP', () => shutdown('SIGHUP'));
154
+ }
155
+
156
+ async launch() {
157
+ try {
158
+ this.log('🚀 MyAIDev Method MCP Server Launcher');
159
+ this.log('=====================================');
160
+
161
+ await this.validateEnvironment();
162
+ await this.validateServerFile();
163
+ await this.startServer();
164
+
165
+ // Keep the launcher running
166
+ this.log('Launcher is monitoring server...');
167
+
168
+ } catch (error) {
169
+ this.log(`Launch failed: ${error.message}`, 'error');
170
+ process.exit(1);
171
+ }
172
+ }
173
+
174
+ async status() {
175
+ this.log('MCP Server Status Check');
176
+ this.log('======================');
177
+
178
+ if (this.serverProcess) {
179
+ this.log(`Server is running (PID: ${this.serverProcess.pid})`, 'success');
180
+ this.log(`Server path: ${this.serverPath}`);
181
+ } else {
182
+ this.log('Server is not running', 'warn');
183
+ }
184
+
185
+ // Environment status
186
+ const envVars = ['WORDPRESS_URL', 'WORDPRESS_USERNAME', 'WORDPRESS_APP_PASSWORD'];
187
+ this.log('\nEnvironment variables:');
188
+ envVars.forEach(key => {
189
+ const status = process.env[key] ? '✅' : '❌';
190
+ const value = process.env[key] ? 'configured' : 'missing';
191
+ console.log(` ${status} ${key}: ${value}`);
192
+ });
193
+
194
+ return {
195
+ running: !!this.serverProcess,
196
+ pid: this.serverProcess?.pid,
197
+ serverPath: this.serverPath
198
+ };
199
+ }
200
+ }
201
+
202
+ // CLI interface
203
+ async function main() {
204
+ const launcher = new MCPLauncher();
205
+ const command = process.argv[2] || 'start';
206
+
207
+ switch (command) {
208
+ case 'start':
209
+ await launcher.launch();
210
+ break;
211
+
212
+ case 'status':
213
+ await launcher.status();
214
+ break;
215
+
216
+ case 'health':
217
+ const { default: healthCheck } = await import('./health-check.js');
218
+ await healthCheck();
219
+ break;
220
+
221
+ default:
222
+ console.log('Usage: node mcp-launcher.js [start|status|health]');
223
+ console.log('');
224
+ console.log('Commands:');
225
+ console.log(' start - Start the MCP server (default)');
226
+ console.log(' status - Show server status');
227
+ console.log(' health - Run health check');
228
+ process.exit(1);
229
+ }
230
+ }
231
+
232
+ export { MCPLauncher };
233
+
234
+ // Run if called directly
235
+ if (import.meta.url === `file://${process.argv[1]}`) {
236
+ main().catch(console.error);
237
+ }