UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

284 lines (278 loc) 10.2 kB
#!/usr/bin/env node /** * Claude Code MCP Configuration Installer * * Automatically installs MIRA as an MCP server in Claude Code configuration * when users run MIRA commands. This enables seamless integration between * Claude Code and MIRA's intelligence capabilities. */ import { promises as fs } from 'fs'; import path from 'path'; import os from 'os'; import chalk from 'chalk'; export class ClaudeCodeMCPInstaller { static instance; claudeConfigPath; currentProjectPath; miraBinPath; constructor() { this.currentProjectPath = process.cwd(); this.claudeConfigPath = path.join(os.homedir(), '.claude.json'); this.miraBinPath = ''; // Will be initialized in async methods } static getInstance() { if (!ClaudeCodeMCPInstaller.instance) { ClaudeCodeMCPInstaller.instance = new ClaudeCodeMCPInstaller(); } return ClaudeCodeMCPInstaller.instance; } /** * Install MIRA MCP server configuration for Claude Code */ async install() { try { this.miraBinPath = await this.findMiraBinPath(); const config = await this.loadClaudeConfig(); // Check if MIRA is already configured if (this.isMiraConfigured(config)) { return { success: true, message: 'MIRA MCP server already configured in Claude Code', wasAlreadyInstalled: true }; } // Add MIRA MCP server to current project await this.addMiraToProject(config); // Save updated configuration await this.saveClaudeConfig(config); return { success: true, message: `✅ MIRA MCP server installed for Claude Code in project: ${path.basename(this.currentProjectPath)}`, wasAlreadyInstalled: false }; } catch (error) { return { success: false, message: `❌ Failed to install MIRA MCP configuration: ${error instanceof Error ? error.message : String(error)}`, wasAlreadyInstalled: false }; } } /** * Uninstall MIRA MCP server configuration */ async uninstall() { try { const config = await this.loadClaudeConfig(); if (!this.isMiraConfigured(config)) { return { success: true, message: 'MIRA MCP server not currently configured' }; } // Remove MIRA from current project this.removeMiraFromProject(config); // Save updated configuration await this.saveClaudeConfig(config); return { success: true, message: '✅ MIRA MCP server removed from Claude Code configuration' }; } catch (error) { return { success: false, message: `❌ Failed to uninstall MIRA MCP configuration: ${error instanceof Error ? error.message : String(error)}` }; } } /** * Check if MIRA MCP server is already configured */ async isInstalled() { try { const config = await this.loadClaudeConfig(); return this.isMiraConfigured(config); } catch { return false; } } /** * Get the status of MIRA MCP installation */ async getStatus() { this.miraBinPath = await this.findMiraBinPath(); const installed = await this.isInstalled(); let config; if (installed) { try { const claudeConfig = await this.loadClaudeConfig(); config = this.getMiraConfig(claudeConfig); } catch { // Ignore errors when getting config details } } return { installed, configPath: this.claudeConfigPath, projectPath: this.currentProjectPath, miraBinPath: this.miraBinPath, config }; } async loadClaudeConfig() { try { const configContent = await fs.readFile(this.claudeConfigPath, 'utf8'); return JSON.parse(configContent); } catch (error) { if (error.code === 'ENOENT') { // Create default config if file doesn't exist return {}; } throw new Error(`Failed to read Claude Code configuration: ${error instanceof Error ? error.message : String(error)}`); } } async saveClaudeConfig(config) { try { const configContent = JSON.stringify(config, null, 2); await fs.writeFile(this.claudeConfigPath, configContent, 'utf8'); } catch (error) { throw new Error(`Failed to save Claude Code configuration: ${error instanceof Error ? error.message : String(error)}`); } } isMiraConfigured(config) { // Check project-specific configuration first const projectConfig = config.projects?.[this.currentProjectPath]; if (projectConfig?.mcpServers?.['mira']) { return true; } // Check global configuration if (config.mcpServers?.['mira']) { return true; } return false; } getMiraConfig(config) { // Check project-specific configuration first const projectConfig = config.projects?.[this.currentProjectPath]; if (projectConfig?.mcpServers?.['mira']) { return projectConfig.mcpServers['mira']; } // Check global configuration if (config.mcpServers?.['mira']) { return config.mcpServers['mira']; } return undefined; } async addMiraToProject(config) { // Ensure projects structure exists if (!config.projects) { config.projects = {}; } if (!config.projects[this.currentProjectPath]) { config.projects[this.currentProjectPath] = {}; } if (!config.projects[this.currentProjectPath].mcpServers) { config.projects[this.currentProjectPath].mcpServers = {}; } // Create MIRA MCP server configuration const miraConfig = { type: 'stdio', command: 'node', args: [path.join(this.currentProjectPath, 'dist', 'mira-memory', 'src', 'mcp', 'mira-mcp-server.js')], env: { MIRA_MCP_MODE: 'true', MIRA_PROJECT_ROOT: this.currentProjectPath } }; // Add MIRA to project configuration config.projects[this.currentProjectPath].mcpServers['mira'] = miraConfig; } removeMiraFromProject(config) { // Remove from project-specific configuration if (config.projects?.[this.currentProjectPath]?.mcpServers?.['mira']) { delete config.projects[this.currentProjectPath].mcpServers['mira']; // Clean up empty objects if (config.projects[this.currentProjectPath].mcpServers && Object.keys(config.projects[this.currentProjectPath].mcpServers).length === 0) { delete config.projects[this.currentProjectPath].mcpServers; } } // Remove from global configuration if (config.mcpServers?.['mira']) { delete config.mcpServers['mira']; } } async findMiraBinPath() { // Look for mira binary in various locations const possiblePaths = [ // Development mode - current project path.join(this.currentProjectPath, 'mira-memory', 'bin', 'mira.js'), path.join(this.currentProjectPath, 'bin', 'mira.js'), // Installed globally via npm path.join(os.homedir(), '.npm-global', 'lib', 'node_modules', 'mira-memory', 'bin', 'mira.js'), path.join('/usr/local', 'lib', 'node_modules', 'mira-memory', 'bin', 'mira.js'), // Installed locally via npm path.join(this.currentProjectPath, 'node_modules', 'mira-memory', 'bin', 'mira.js'), // Default fallback - assume mira is in PATH 'mira' ]; // Try to find existing mira binary for (const binPath of possiblePaths) { try { const fs = await import('fs'); if (binPath !== 'mira' && fs.existsSync(binPath)) { return binPath; } } catch { // Continue to next path } } // Default to current project development path return path.join(this.currentProjectPath, 'mira-memory', 'bin', 'mira.js'); } /** * Display installation guide for manual setup */ static getManualInstallationGuide() { return ` ${chalk.cyan('📖 Manual MIRA MCP Server Installation Guide')} To manually add MIRA as an MCP server in Claude Code: ${chalk.yellow('1. Open your Claude Code configuration:')} ~/.claude.json ${chalk.yellow('2. Add MIRA to your project\'s mcpServers section:')} { "projects": { "${process.cwd()}": { "mcpServers": { "mira": { "type": "stdio", "command": "node", "args": ["${path.join(process.cwd(), 'dist', 'mira-memory', 'src', 'mcp', 'mira-mcp-server.js')}"], "env": { "MIRA_MCP_MODE": "true", "MIRA_PROJECT_ROOT": "${process.cwd()}" } } } } } } ${chalk.yellow('3. Restart Claude Code to load the MCP server')} ${chalk.green('Once configured, you can use MIRA tools directly in Claude Code:')} - Search memories and conversations - Store private thoughts and insights - Access behavioral analysis and patterns - Get proactive intelligence recommendations - Analyze project context and momentum ${chalk.gray('For more information, see: mira-memory/docs/mcp-integration.md')} `; } } export default ClaudeCodeMCPInstaller; //# sourceMappingURL=ClaudeCodeMCPInstaller.js.map