mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
284 lines (278 loc) • 10.2 kB
JavaScript
/**
* 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