143 lines
5.3 KiB
JavaScript
143 lines
5.3 KiB
JavaScript
|
|
#!/usr/bin/env node
|
|||
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
const os = require('os');
|
|||
|
|
const { execSync } = require('child_process');
|
|||
|
|
|
|||
|
|
console.log('╔════════════════════════════════════════════════════════╗');
|
|||
|
|
console.log('║ MCP Configuration Wizard - System Detection ║');
|
|||
|
|
console.log('╚════════════════════════════════════════════════════════╝\n');
|
|||
|
|
|
|||
|
|
// 检测系统信息
|
|||
|
|
const detection = {
|
|||
|
|
timestamp: new Date().toISOString(),
|
|||
|
|
system: {
|
|||
|
|
platform: os.platform(),
|
|||
|
|
username: os.userInfo().username,
|
|||
|
|
homedir: os.homedir(),
|
|||
|
|
nodeVersion: process.version
|
|||
|
|
},
|
|||
|
|
claude: {
|
|||
|
|
configDir: null,
|
|||
|
|
configFile: null,
|
|||
|
|
hasExistingConfig: false,
|
|||
|
|
existingMcpServers: []
|
|||
|
|
},
|
|||
|
|
environment: {
|
|||
|
|
variables: {},
|
|||
|
|
mcpRelated: []
|
|||
|
|
},
|
|||
|
|
npm: {
|
|||
|
|
globalPackages: [],
|
|||
|
|
mcpPackages: []
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 1. 检测 Claude Code 配置目录
|
|||
|
|
console.log('🔍 Detecting Claude Code configuration...');
|
|||
|
|
const possibleConfigDirs = [
|
|||
|
|
path.join(os.homedir(), '.claude'),
|
|||
|
|
path.join(os.homedir(), 'AppData', 'Roaming', 'Claude'),
|
|||
|
|
path.join(os.homedir(), 'Library', 'Application Support', 'Claude')
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
for (const dir of possibleConfigDirs) {
|
|||
|
|
if (fs.existsSync(dir)) {
|
|||
|
|
detection.claude.configDir = dir;
|
|||
|
|
console.log(` ✓ Found: ${dir}`);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!detection.claude.configDir) {
|
|||
|
|
console.log(' ⚠ Claude config directory not found, will create on apply');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检测现有配置文件
|
|||
|
|
const configFile = path.join(os.homedir(), '.claude.json');
|
|||
|
|
if (fs.existsSync(configFile)) {
|
|||
|
|
detection.claude.configFile = configFile;
|
|||
|
|
detection.claude.hasExistingConfig = true;
|
|||
|
|
try {
|
|||
|
|
const config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));
|
|||
|
|
if (config.mcpServers) {
|
|||
|
|
detection.claude.existingMcpServers = Object.keys(config.mcpServers);
|
|||
|
|
console.log(` ✓ Existing config found with ${detection.claude.existingMcpServers.length} MCP servers`);
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.log(' ⚠ Config file exists but cannot be parsed');
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
console.log(' ℹ No existing .claude.json found');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 检测环境变量
|
|||
|
|
console.log('\n🔍 Detecting environment variables...');
|
|||
|
|
const mcpEnvVars = [
|
|||
|
|
'GITHUB_PERSONAL_ACCESS_TOKEN',
|
|||
|
|
'SLACK_BOT_TOKEN', 'SLACK_TEAM_ID',
|
|||
|
|
'LINEAR_API_KEY',
|
|||
|
|
'BROWSERBASE_PROJECT_ID', 'BROWSERBASE_API_KEY',
|
|||
|
|
'CLOUDFLARE_API_TOKEN',
|
|||
|
|
'FIRECRAWL_API_KEY',
|
|||
|
|
'SUPABASE_URL', 'SUPABASE_SERVICE_ROLE_KEY',
|
|||
|
|
'SENTRY_AUTH_TOKEN',
|
|||
|
|
'NOTION_API_KEY',
|
|||
|
|
'VERCEL_TOKEN',
|
|||
|
|
'FIREBASE_PROJECT_ID', 'FIREBASE_PRIVATE_KEY', 'FIREBASE_CLIENT_EMAIL'
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
mcpEnvVars.forEach(varName => {
|
|||
|
|
const value = process.env[varName];
|
|||
|
|
if (value) {
|
|||
|
|
detection.environment.mcpRelated.push(varName);
|
|||
|
|
detection.environment.variables[varName] = value.substring(0, 10) + '...'; // 只保存前缀用于检测
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
console.log(` ✓ Found ${detection.environment.mcpRelated.length} MCP-related environment variables`);
|
|||
|
|
detection.environment.mcpRelated.forEach(v => console.log(` - ${v}`));
|
|||
|
|
|
|||
|
|
// 3. 检测已安装的 npm 包
|
|||
|
|
console.log('\n🔍 Detecting installed npm packages...');
|
|||
|
|
try {
|
|||
|
|
const globalList = execSync('npm list -g --depth=0 --json', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|||
|
|
const packages = JSON.parse(globalList);
|
|||
|
|
if (packages.dependencies) {
|
|||
|
|
detection.npm.globalPackages = Object.keys(packages.dependencies);
|
|||
|
|
|
|||
|
|
// 筛选 MCP 相关包
|
|||
|
|
const mcpKeywords = ['mcp', 'modelcontextprotocol', 'claude'];
|
|||
|
|
detection.npm.mcpPackages = detection.npm.globalPackages.filter(pkg =>
|
|||
|
|
mcpKeywords.some(kw => pkg.toLowerCase().includes(kw))
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (detection.npm.mcpPackages.length > 0) {
|
|||
|
|
console.log(` ✓ Found ${detection.npm.mcpPackages.length} MCP packages installed globally`);
|
|||
|
|
detection.npm.mcpPackages.forEach(p => console.log(` - ${p}`));
|
|||
|
|
} else {
|
|||
|
|
console.log(' ℹ No MCP packages found (will use npx)');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.log(' ⚠ Cannot detect npm packages (npm may not be installed)');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 保存检测结果
|
|||
|
|
const outputFile = path.join(__dirname, 'detection-result.json');
|
|||
|
|
fs.writeFileSync(outputFile, JSON.stringify(detection, null, 2));
|
|||
|
|
|
|||
|
|
console.log('\n╔════════════════════════════════════════════════════════╗');
|
|||
|
|
console.log('║ Detection Complete ║');
|
|||
|
|
console.log('╚════════════════════════════════════════════════════════╝');
|
|||
|
|
console.log(`\n📄 Results saved to: ${outputFile}`);
|
|||
|
|
console.log('\n📊 Summary:');
|
|||
|
|
console.log(` Platform: ${detection.system.platform}`);
|
|||
|
|
console.log(` User: ${detection.system.username}`);
|
|||
|
|
console.log(` Claude Config: ${detection.claude.configDir || 'Not found'}`);
|
|||
|
|
console.log(` Existing MCP Servers: ${detection.claude.existingMcpServers.length}`);
|
|||
|
|
console.log(` Environment Variables: ${detection.environment.mcpRelated.length}`);
|
|||
|
|
console.log(` MCP Packages: ${detection.npm.mcpPackages.length}`);
|
|||
|
|
|
|||
|
|
console.log('\n💡 Next step: Run "node wizard.js" to configure MCP services');
|