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
JavaScript
/**
* 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 };