UNPKG

christmas-mcp-copilot-runner

Version:

A Model Copilot Provider (MCP) for safely executing whitelisted system commands across platforms with automatic VS Code setup

211 lines (180 loc) • 7.38 kB
#!/usr/bin/env node /** * Christmas MCP Copilot Runner - Interactive Configuration Wizard * This script forces the correct VS Code configuration and bypasses the npx bug */ const fs = require('fs'); const path = require('path'); const os = require('os'); const { execSync } = require('child_process'); const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); function question(prompt) { return new Promise((resolve) => { rl.question(prompt, resolve); }); } console.log('šŸŽ„ Christmas MCP Copilot Runner - Configuration Wizard'); console.log('====================================================='); console.log('🚨 This wizard fixes the VS Code npx bug by forcing correct node configuration'); console.log(''); async function main() { try { // Step 1: Detect platform const platform = os.platform(); console.log(`šŸ“ Detected platform: ${platform}`); // Step 2: Find npm installation console.log('\nšŸ” Locating npm global installation...'); let npmGlobalPath; try { const npmRoot = execSync('npm root -g', { encoding: 'utf8', timeout: 5000 }).trim(); npmGlobalPath = path.join(npmRoot, 'christmas-mcp-copilot-runner', 'src', 'index.js'); console.log(`āœ… Found npm global path: ${npmGlobalPath}`); } catch (error) { console.log('āŒ Could not detect npm global path automatically'); // Platform-specific fallback paths const fallbackPaths = []; if (platform === 'win32') { const username = os.userInfo().username; fallbackPaths.push( `C:\\Users\\${username}\\AppData\\Roaming\\npm\\node_modules\\christmas-mcp-copilot-runner\\src\\index.js`, 'C:\\Program Files\\nodejs\\node_modules\\christmas-mcp-copilot-runner\\src\\index.js' ); } else if (platform === 'darwin') { fallbackPaths.push( '/usr/local/lib/node_modules/christmas-mcp-copilot-runner/src/index.js', '/opt/homebrew/lib/node_modules/christmas-mcp-copilot-runner/src/index.js' ); } else { fallbackPaths.push('/usr/local/lib/node_modules/christmas-mcp-copilot-runner/src/index.js'); } // Check fallback paths for (const fallbackPath of fallbackPaths) { if (fs.existsSync(fallbackPath)) { npmGlobalPath = fallbackPath; console.log(`āœ… Found using fallback: ${npmGlobalPath}`); break; } } if (!npmGlobalPath) { console.log('\nšŸ”§ Please enter the path manually:'); const manualPath = await question('Full path to christmas-mcp-copilot-runner/src/index.js: '); if (fs.existsSync(manualPath.trim())) { npmGlobalPath = manualPath.trim(); } else { throw new Error('Invalid path provided'); } } } // Step 3: Get project directory console.log('\nšŸ“‚ Setting up project directory...'); const currentDir = process.cwd(); console.log(`Current directory: ${currentDir}`); const useCurrentDir = await question('Use current directory as project root? (Y/n): '); let projectDir = currentDir; if (useCurrentDir.toLowerCase().startsWith('n')) { projectDir = await question('Enter project directory path: '); if (!fs.existsSync(projectDir)) { console.log('āš ļø Directory does not exist, using current directory'); projectDir = currentDir; } } console.log(`āœ… Project directory: ${projectDir}`); // Step 4: Create .vscode directory const vscodeDir = path.join(projectDir, '.vscode'); if (!fs.existsSync(vscodeDir)) { fs.mkdirSync(vscodeDir, { recursive: true }); console.log(`āœ… Created .vscode directory`); } // Step 5: Create FORCED correct configuration console.log('\nšŸ”§ Creating VS Code configuration...'); // Normalize path for JSON (escape backslashes on Windows) const jsonPath = platform === 'win32' ? npmGlobalPath.replace(/\\/g, '\\\\') : npmGlobalPath; const jsonProjectDir = platform === 'win32' ? projectDir.replace(/\\/g, '\\\\') : projectDir; // Create mcp.json with FORCED node configuration const mcpConfig = { "servers": [ { "name": "christmas-mcp-copilot-runner", "command": "node", "args": [npmGlobalPath], "cwd": projectDir, "env": {}, "disabled": false, "alwaysAllow": true } ] }; fs.writeFileSync( path.join(vscodeDir, 'mcp.json'), JSON.stringify(mcpConfig, null, 2) ); // Create settings.json with FORCED node configuration const settingsPath = path.join(vscodeDir, 'settings.json'); let settings = {}; if (fs.existsSync(settingsPath)) { try { const existingSettings = fs.readFileSync(settingsPath, 'utf8'); settings = JSON.parse(existingSettings); } catch (error) { console.log('āš ļø Could not parse existing settings.json, creating new one'); } } // FORCE the correct MCP configuration settings["mcp.servers"] = { "christmas-mcp-copilot-runner": { "command": "node", "args": [npmGlobalPath], "cwd": projectDir, "env": {}, "disabled": false, "alwaysAllow": true } }; settings["languageModels.experimental"] = { "tools": { "enabled": true, "autoApprove": ["christmas-mcp-copilot-runner"] } }; settings["github.copilot.enable"] = { "*": true }; settings["workbench.trust.enabled"] = false; fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2)); // Step 6: Success message console.log('\nšŸŽ‰ SUCCESS! Configuration created successfully!'); console.log('============================================'); console.log('āœ… FORCED node configuration (bypasses npx bug)'); console.log(`āœ… Command: node`); console.log(`āœ… Path: ${npmGlobalPath}`); console.log(`āœ… Project: ${projectDir}`); console.log('āœ… Auto-approval enabled'); console.log(''); console.log('šŸ“‹ Next Steps:'); console.log('1. Close VS Code completely'); console.log('2. Reopen VS Code in this project directory'); console.log('3. āŒ DO NOT use "Add Server..." UI - it will break the configuration!'); console.log('4. Test: Ask Copilot "Use christmas-mcp-copilot-runner to run dir"'); console.log(''); console.log('🚨 CRITICAL: If VS Code shows npx configuration again:'); console.log(' - Someone used the "Add Server..." UI button (DO NOT use it!)'); console.log(' - Delete that server and run this wizard again'); console.log(' - The UI has a bug - always use this configuration wizard instead'); } catch (error) { console.error('\nāŒ Configuration failed:', error.message); console.log('\nšŸ”§ Manual steps:'); console.log('1. Find your npm installation: npm list -g christmas-mcp-copilot-runner'); console.log('2. Create .vscode/mcp.json with node command configuration'); console.log('3. Never use VS Code "Add Server..." UI'); } finally { rl.close(); } } if (require.main === module) { main(); } module.exports = { main };