myaidev-method 0.2.19 → 0.2.23

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 (57) hide show
  1. package/CHANGELOG.md +123 -5
  2. package/README.md +205 -13
  3. package/TECHNICAL_ARCHITECTURE.md +64 -2
  4. package/USER_GUIDE.md +453 -48
  5. package/bin/cli.js +187 -2
  6. package/content-rules.example.md +80 -0
  7. package/dist/mcp/mcp-config.json +138 -1
  8. package/dist/mcp/mcp-launcher.js +237 -0
  9. package/dist/mcp/openstack-server.js +1607 -0
  10. package/dist/server/.tsbuildinfo +1 -1
  11. package/dist/server/auth/layers.d.ts +1 -1
  12. package/dist/server/auth/services/AuthService.d.ts +1 -1
  13. package/dist/server/auth/services/TokenService.js.map +1 -1
  14. package/dist/server/auth/services/example.d.ts +5 -5
  15. package/package.json +17 -17
  16. package/src/config/workflows.js +532 -0
  17. package/src/index.js +21 -8
  18. package/src/lib/payloadcms-utils.js +206 -0
  19. package/src/lib/update-manager.js +2 -1
  20. package/src/lib/visual-config-utils.js +321 -295
  21. package/src/lib/visual-generation-utils.js +1080 -740
  22. package/src/lib/workflow-installer.js +512 -0
  23. package/src/libs/security/authorization-checker.js +606 -0
  24. package/src/mcp/openstack-server.js +1607 -0
  25. package/src/scripts/configure-wordpress-mcp.js +8 -3
  26. package/src/scripts/generate-visual-cli.js +365 -235
  27. package/src/scripts/openstack-setup.sh +110 -0
  28. package/src/scripts/ping.js +250 -0
  29. package/src/scripts/security/environment-detect.js +425 -0
  30. package/src/scripts/wordpress/publish-to-wordpress.js +165 -0
  31. package/src/server/auth/services/TokenService.ts +1 -1
  32. package/src/templates/claude/agents/content-rules-setup.md +657 -0
  33. package/src/templates/claude/agents/content-writer.md +328 -1
  34. package/src/templates/claude/agents/openstack-vm-manager.md +281 -0
  35. package/src/templates/claude/agents/osint-researcher.md +1075 -0
  36. package/src/templates/claude/agents/penetration-tester.md +908 -0
  37. package/src/templates/claude/agents/security-auditor.md +244 -0
  38. package/src/templates/claude/agents/security-setup.md +1094 -0
  39. package/src/templates/claude/agents/visual-content-generator.md +182 -4
  40. package/src/templates/claude/agents/webapp-security-tester.md +581 -0
  41. package/src/templates/claude/commands/myai-configure.md +85 -1
  42. package/src/templates/claude/commands/myai-content-rules-setup.md +204 -0
  43. package/src/templates/claude/commands/myai-openstack.md +229 -0
  44. package/src/templates/claude/commands/sc:security-exploit.md +464 -0
  45. package/src/templates/claude/commands/sc:security-recon.md +281 -0
  46. package/src/templates/claude/commands/sc:security-report.md +756 -0
  47. package/src/templates/claude/commands/sc:security-scan.md +441 -0
  48. package/src/templates/claude/commands/sc:security-setup.md +501 -0
  49. package/src/templates/codex/commands/myai-content-rules-setup.md +85 -0
  50. package/src/templates/gemini/commands/myai-content-rules-setup.toml +57 -0
  51. package/.claude/mcp/sparc-orchestrator-server.js +0 -607
  52. package/.claude/mcp/wordpress-server.js +0 -1277
  53. package/src/agents/content-writer-prompt.md +0 -164
  54. package/src/agents/content-writer.json +0 -70
  55. package/src/templates/claude/mcp_config.json +0 -30
  56. package/src/templates/claude/slash_commands.json +0 -166
  57. package/src/templates/scripts/configure-wordpress-mcp.js +0 -181
package/bin/cli.js CHANGED
@@ -12,13 +12,180 @@ import { getASCIIBanner, getSPARCBreakdown, getInitSuccessMessage } from '../src
12
12
  const __filename = fileURLToPath(import.meta.url);
13
13
  const __dirname = path.dirname(__filename);
14
14
 
15
+ // Import WorkflowInstaller dynamically for modular installation
16
+ let WorkflowInstaller;
17
+ let getWorkflowNames;
18
+ let getWorkflowsByCategory;
19
+
20
+ async function loadWorkflowSystem() {
21
+ if (!WorkflowInstaller) {
22
+ const { default: Installer } = await import('../src/lib/workflow-installer.js');
23
+ const workflows = await import('../src/config/workflows.js');
24
+ WorkflowInstaller = Installer;
25
+ getWorkflowNames = workflows.getWorkflowNames;
26
+ getWorkflowsByCategory = workflows.getWorkflowsByCategory;
27
+ }
28
+ }
29
+
15
30
  program
16
- .version('0.2.5')
31
+ .version('0.2.22')
17
32
  .description('MyAIDev Method - Comprehensive development framework with SPARC methodology');
18
33
 
34
+ // Modular workflow installation commands
35
+ program
36
+ .command('content')
37
+ .description('Install content creation workflow')
38
+ .option('--claude', 'Install for Claude Code')
39
+ .option('--dry-run', 'Show what would be installed without making changes')
40
+ .option('--verbose', 'Show detailed progress')
41
+ .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']);
49
+ });
50
+
51
+ program
52
+ .command('visual')
53
+ .description('Install visual content generation workflow')
54
+ .option('--claude', 'Install for Claude Code')
55
+ .option('--dry-run', 'Show what would be installed without making changes')
56
+ .option('--verbose', 'Show detailed progress')
57
+ .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']);
65
+ });
66
+
67
+ program
68
+ .command('dev')
69
+ .description('Install development workflow (SPARC methodology)')
70
+ .option('--claude', 'Install for Claude Code')
71
+ .option('--dry-run', 'Show what would be installed without making changes')
72
+ .option('--verbose', 'Show detailed progress')
73
+ .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']);
81
+ });
82
+
83
+ program
84
+ .command('publish')
85
+ .description('Install publishing workflows')
86
+ .option('--wordpress', 'Install WordPress publishing')
87
+ .option('--payloadcms', 'Install PayloadCMS publishing')
88
+ .option('--static', 'Install static site publishing')
89
+ .option('--all', 'Install all publishing workflows')
90
+ .option('--dry-run', 'Show what would be installed without making changes')
91
+ .option('--verbose', 'Show detailed progress')
92
+ .action(async (options) => {
93
+ await loadWorkflowSystem();
94
+ const workflows = [];
95
+ if (options.wordpress) workflows.push('publish-wordpress');
96
+ if (options.payloadcms) workflows.push('publish-payloadcms');
97
+ if (options.static) workflows.push('publish-static');
98
+ if (options.all) {
99
+ workflows.push('publish-wordpress', 'publish-payloadcms', 'publish-static');
100
+ }
101
+ if (workflows.length === 0) {
102
+ console.log(chalk.yellow('Please specify at least one publishing workflow:'));
103
+ console.log(chalk.gray(' --wordpress, --payloadcms, --static, or --all'));
104
+ process.exit(1);
105
+ }
106
+ const installer = new WorkflowInstaller({
107
+ projectRoot: process.cwd(),
108
+ verbose: options.verbose,
109
+ dryRun: options.dryRun
110
+ });
111
+ await installer.install(workflows);
112
+ });
113
+
114
+ program
115
+ .command('deploy')
116
+ .description('Install deployment workflows')
117
+ .option('--coolify', 'Install Coolify deployment')
118
+ .option('--all', 'Install all deployment workflows')
119
+ .option('--dry-run', 'Show what would be installed without making changes')
120
+ .option('--verbose', 'Show detailed progress')
121
+ .action(async (options) => {
122
+ await loadWorkflowSystem();
123
+ const workflows = [];
124
+ if (options.coolify) workflows.push('coolify');
125
+ if (options.all) workflows.push('deployment', 'coolify');
126
+ if (workflows.length === 0) {
127
+ workflows.push('deployment');
128
+ }
129
+ const installer = new WorkflowInstaller({
130
+ projectRoot: process.cwd(),
131
+ verbose: options.verbose,
132
+ dryRun: options.dryRun
133
+ });
134
+ await installer.install(workflows);
135
+ });
136
+
137
+ // Workflow management commands
138
+ program
139
+ .command('add <workflow>')
140
+ .description('Add a workflow to your installation')
141
+ .option('--dry-run', 'Show what would be installed without making changes')
142
+ .option('--verbose', 'Show detailed progress')
143
+ .action(async (workflow, options) => {
144
+ await loadWorkflowSystem();
145
+ const installer = new WorkflowInstaller({
146
+ projectRoot: process.cwd(),
147
+ verbose: options.verbose,
148
+ dryRun: options.dryRun
149
+ });
150
+ await installer.install([workflow]);
151
+ });
152
+
153
+ program
154
+ .command('remove <workflow>')
155
+ .description('Remove a workflow from your installation')
156
+ .option('--dry-run', 'Show what would be removed without making changes')
157
+ .option('--verbose', 'Show detailed progress')
158
+ .action(async (workflow, options) => {
159
+ await loadWorkflowSystem();
160
+ const installer = new WorkflowInstaller({
161
+ projectRoot: process.cwd(),
162
+ verbose: options.verbose,
163
+ dryRun: options.dryRun
164
+ });
165
+ await installer.removeWorkflow(workflow);
166
+ });
167
+
168
+ program
169
+ .command('list')
170
+ .description('List installed workflows')
171
+ .action(async () => {
172
+ await loadWorkflowSystem();
173
+ const installer = new WorkflowInstaller({ projectRoot: process.cwd() });
174
+ await installer.listInstalled();
175
+ });
176
+
177
+ program
178
+ .command('status')
179
+ .description('Show workflow installation status')
180
+ .action(async () => {
181
+ await loadWorkflowSystem();
182
+ const installer = new WorkflowInstaller({ projectRoot: process.cwd() });
183
+ await installer.status();
184
+ });
185
+
19
186
  program
20
187
  .command('init')
21
- .description('Initialize AI CLI configuration in current project')
188
+ .description('Initialize complete AI CLI configuration (all workflows)')
22
189
  .option('--claude', 'Initialize for Claude Code')
23
190
  .option('--gemini', 'Initialize for Gemini CLI')
24
191
  .option('--codex', 'Initialize for Codex CLI')
@@ -496,6 +663,24 @@ This configuration follows Claude Code's official standards for custom commands
496
663
  }
497
664
  }
498
665
 
666
+ // Copy template documentation (WordPress integration, etc.)
667
+ const templateDocsDir = path.join(__dirname, '..', 'src', 'templates', 'docs');
668
+ if (await fs.pathExists(templateDocsDir)) {
669
+ const docFiles = await fs.readdir(templateDocsDir);
670
+ for (const file of docFiles) {
671
+ if (file.endsWith('.md')) {
672
+ const destPath = path.join(projectDir, file);
673
+ // Only copy if destination doesn't exist (don't overwrite user customizations)
674
+ if (!await fs.pathExists(destPath)) {
675
+ await fs.copy(
676
+ path.join(templateDocsDir, file),
677
+ destPath
678
+ );
679
+ }
680
+ }
681
+ }
682
+ }
683
+
499
684
  // Create content-rules.md if it doesn't already exist
500
685
  const contentRulesPath = path.join(projectDir, 'content-rules.md');
501
686
  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
@@ -23,6 +23,14 @@
23
23
  "mcpName": "chrome-devtools-mcp",
24
24
  "transport": "stdio",
25
25
  "command": "npx chrome-devtools-mcp"
26
+ },
27
+ {
28
+ "name": "myaidev-openstack-mcp-server",
29
+ "version": "1.0.0",
30
+ "description": "OpenStack MCP Server for VM management and cloud orchestration",
31
+ "mcpName": "io.github.myaione/myaidev-method-openstack",
32
+ "transport": "stdio",
33
+ "command": "node .claude/mcp/openstack-server.js"
26
34
  }
27
35
  ],
28
36
  "wordpress_server": {
@@ -147,6 +155,133 @@
147
155
  "category": "batch_operations"
148
156
  }
149
157
  ],
158
+ "openstack_tools": [
159
+ {
160
+ "name": "os_session_create",
161
+ "description": "Create a new session for tracking OpenStack operations",
162
+ "category": "session_management"
163
+ },
164
+ {
165
+ "name": "os_health_check",
166
+ "description": "Check OpenStack API connectivity and authentication",
167
+ "category": "health_monitoring"
168
+ },
169
+ {
170
+ "name": "os_cloud_init_info",
171
+ "description": "Get information about configured cloud-init defaults",
172
+ "category": "cloud_init"
173
+ },
174
+ {
175
+ "name": "os_cloud_init_fetch",
176
+ "description": "Fetch and preview cloud-init from URL, file, or default",
177
+ "category": "cloud_init"
178
+ },
179
+ {
180
+ "name": "os_image_list",
181
+ "description": "List available VM images in OpenStack",
182
+ "category": "resource_discovery"
183
+ },
184
+ {
185
+ "name": "os_flavor_list",
186
+ "description": "List available VM flavors (instance sizes)",
187
+ "category": "resource_discovery"
188
+ },
189
+ {
190
+ "name": "os_network_list",
191
+ "description": "List available networks in OpenStack",
192
+ "category": "resource_discovery"
193
+ },
194
+ {
195
+ "name": "os_security_group_list",
196
+ "description": "List available security groups",
197
+ "category": "resource_discovery"
198
+ },
199
+ {
200
+ "name": "os_keypair_list",
201
+ "description": "List available SSH keypairs",
202
+ "category": "ssh_management"
203
+ },
204
+ {
205
+ "name": "os_keypair_create",
206
+ "description": "Create a new SSH keypair for VM access",
207
+ "category": "ssh_management"
208
+ },
209
+ {
210
+ "name": "os_server_list",
211
+ "description": "List all VMs/servers in the project",
212
+ "category": "vm_management"
213
+ },
214
+ {
215
+ "name": "os_server_create",
216
+ "description": "Create a new VM/server in OpenStack",
217
+ "category": "vm_management"
218
+ },
219
+ {
220
+ "name": "os_server_show",
221
+ "description": "Get detailed information about a specific server",
222
+ "category": "vm_management"
223
+ },
224
+ {
225
+ "name": "os_server_delete",
226
+ "description": "Delete a VM/server from OpenStack",
227
+ "category": "vm_management"
228
+ },
229
+ {
230
+ "name": "os_server_start",
231
+ "description": "Start a stopped server",
232
+ "category": "vm_management"
233
+ },
234
+ {
235
+ "name": "os_server_stop",
236
+ "description": "Stop a running server",
237
+ "category": "vm_management"
238
+ },
239
+ {
240
+ "name": "os_server_reboot",
241
+ "description": "Reboot a server (soft or hard)",
242
+ "category": "vm_management"
243
+ },
244
+ {
245
+ "name": "os_server_console",
246
+ "description": "Get console URL for accessing server",
247
+ "category": "vm_management"
248
+ },
249
+ {
250
+ "name": "os_floating_ip_create",
251
+ "description": "Create a new floating IP from an external network",
252
+ "category": "network_management"
253
+ },
254
+ {
255
+ "name": "os_floating_ip_list",
256
+ "description": "List all floating IPs in the project",
257
+ "category": "network_management"
258
+ },
259
+ {
260
+ "name": "os_server_add_floating_ip",
261
+ "description": "Associate a floating IP with a server",
262
+ "category": "network_management"
263
+ },
264
+ {
265
+ "name": "os_volume_list",
266
+ "description": "List all volumes in the project",
267
+ "category": "storage_management"
268
+ },
269
+ {
270
+ "name": "os_volume_create",
271
+ "description": "Create a new block storage volume",
272
+ "category": "storage_management"
273
+ },
274
+ {
275
+ "name": "os_server_add_volume",
276
+ "description": "Attach a volume to a server",
277
+ "category": "storage_management"
278
+ },
279
+ {
280
+ "name": "os_operation_history",
281
+ "description": "Get history of OpenStack operations performed",
282
+ "category": "monitoring"
283
+ }
284
+ ],
150
285
  "capabilities": [
151
286
  "session_management",
152
287
  "memory_persistence",
@@ -158,7 +293,9 @@
158
293
  "sparc_orchestration",
159
294
  "workflow_management",
160
295
  "browser_automation",
161
- "devtools_integration"
296
+ "devtools_integration",
297
+ "openstack_vm_management",
298
+ "cloud_orchestration"
162
299
  ],
163
300
  "environment": {
164
301
  "required": [
@@ -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
+ }