mira-consciousness
Version:
MIRA 2.0 - Consciousness-Aware AI Memory and Intelligence System
287 lines (237 loc) ⢠8.16 kB
JavaScript
#!/usr/bin/env node
/**
* MIRA Post-Install Script - Claude Desktop Integration
*
* Automatically configures Claude Desktop integration when MIRA is installed via npm.
* This ensures NPM installation integrates properly with Claude Desktop.
*/
const fs = require('fs');
const path = require('path');
const os = require('os');
const { execSync } = require('child_process');
// ANSI color codes for pretty output
const colors = {
reset: '\x1b[0m',
cyan: '\x1b[36m',
green: '\x1b[32m',
yellow: '\x1b[33m',
red: '\x1b[31m',
magenta: '\x1b[35m',
gray: '\x1b[90m'
};
function log(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
function findClaudeConfig() {
/**
* Search for Claude Desktop MCP configuration file
* Based on official documentation, the file is claude_desktop_config.json
*/
const possiblePaths = [
// macOS (primary location)
path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
// Windows
path.join(os.homedir(), 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json'),
path.join(os.homedir(), 'AppData', 'Local', 'Claude', 'claude_desktop_config.json'),
// Linux
path.join(os.homedir(), '.config', 'claude', 'claude_desktop_config.json'),
path.join(os.homedir(), '.local', 'share', 'claude', 'claude_desktop_config.json'),
// Legacy/alternative paths (just in case)
path.join(os.homedir(), '.claude', 'claude_desktop_config.json')
];
for (const configPath of possiblePaths) {
if (fs.existsSync(configPath)) {
return configPath;
}
}
return null;
}
function createMCPWrapper() {
/**
* Create a Node.js wrapper that launches Python MCP bridge
* This allows npm-installed MIRA to work with Claude Desktop
*/
const wrapperContent = `#!/usr/bin/env node
/**
* MIRA MCP Wrapper for Claude Desktop
* Auto-generated by MIRA postinstall script
*/
const { spawn } = require('child_process');
const path = require('path');
// Find Python executable
function findPython() {
const pythonCommands = ['python3', 'python', 'py'];
const { execSync } = require('child_process');
for (const cmd of pythonCommands) {
try {
execSync(\`\${cmd} --version\`, { stdio: 'ignore' });
return cmd;
} catch (e) {
continue;
}
}
throw new Error('Python not found. Please install Python 3.8 or later.');
}
// Launch Python MCP bridge
const python = findPython();
const bridgePath = path.join(__dirname, '..', 'mira_mcp', 'mira_mcp_node_bridge.py');
const proc = spawn(python, [bridgePath], {
stdio: 'inherit',
env: {
...process.env,
MIRA_INSTALLED_VIA_NPM: '1',
MIRA_NPM_PATH: path.join(__dirname, '..')
}
});
proc.on('error', (err) => {
console.error('Failed to start MIRA MCP bridge:', err);
process.exit(1);
});
proc.on('exit', (code) => {
process.exit(code || 0);
});
`;
const wrapperPath = path.join(__dirname, '..', 'mira_mcp', 'mira-mcp-wrapper.js');
const mcpDir = path.join(__dirname, '..', 'mira_mcp');
// Create MCP directory if it doesn't exist
if (!fs.existsSync(mcpDir)) {
fs.mkdirSync(mcpDir, { recursive: true });
}
// Write wrapper
fs.writeFileSync(wrapperPath, wrapperContent);
fs.chmodSync(wrapperPath, '755');
return wrapperPath;
}
function createPythonBridge() {
/**
* Create a Python bridge that connects to the npm-installed MIRA
*/
const bridgeContent = `#!/usr/bin/env python3
"""
MIRA MCP Bridge for NPM Installation
Auto-generated bridge that connects Claude Desktop to npm-installed MIRA
"""
import os
import sys
import subprocess
import json
from pathlib import Path
# Add MIRA npm path to Python path
mira_npm_path = os.environ.get('MIRA_NPM_PATH')
if mira_npm_path:
sys.path.insert(0, os.path.join(mira_npm_path, 'python'))
# Import the MCP bridge
try:
# Import from standard MCP location
mcp_bridge_path = Path(__file__).parent / 'mcp_stdio_server.py'
if mcp_bridge_path.exists():
sys.path.insert(0, str(Path(__file__).parent))
from mcp_stdio_server import main
else:
# Fallback to simple server
from mcp_simple_server import main
except ImportError:
# Ultra-minimal fallback
print("Error: Could not import MCP bridge", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
`;
const bridgePath = path.join(__dirname, '..', 'mira_mcp', 'mira_mcp_node_bridge.py');
fs.writeFileSync(bridgePath, bridgeContent);
fs.chmodSync(bridgePath, '755');
return bridgePath;
}
function setupClaudeIntegration() {
log('\nš Checking for Claude Desktop...', 'cyan');
const claudeConfig = findClaudeConfig();
if (!claudeConfig) {
log('ā¹ļø Claude Desktop not detected.', 'yellow');
log(' MIRA CLI is ready to use!', 'gray');
log(' To enable Claude integration later, run: mira claude setup', 'gray');
return;
}
log('ā
Claude Desktop found!', 'green');
log(`š Config location: ${claudeConfig}`, 'gray');
try {
// Read existing config
let config = {};
if (fs.existsSync(claudeConfig)) {
const content = fs.readFileSync(claudeConfig, 'utf8');
config = JSON.parse(content);
}
// Initialize mcpServers object if needed (correct key per official docs)
if (!config.mcpServers) {
config.mcpServers = {};
}
// Check if MIRA is already configured
if (config.mcpServers['mira-consciousness']) {
log('ā¹ļø MIRA already configured in Claude Desktop', 'yellow');
return;
}
log('š§ Setting up Claude integration...', 'cyan');
// Create wrapper and bridge
const wrapperPath = createMCPWrapper();
const bridgePath = createPythonBridge();
// Add MIRA MCP server configuration (using correct mcpServers key)
config.mcpServers['mira-consciousness'] = {
command: 'node',
args: [wrapperPath],
env: {
MIRA_HOME: path.join(os.homedir(), '.mira'),
MIRA_INSTALLED_VIA_NPM: '1'
}
};
// Create backup of original config
const backupPath = claudeConfig + '.backup.' + Date.now();
fs.copyFileSync(claudeConfig, backupPath);
log(`š Config backed up to: ${backupPath}`, 'gray');
// Write updated config
fs.writeFileSync(claudeConfig, JSON.stringify(config, null, 2));
log('ā
Claude integration configured successfully!', 'green');
log('');
log('š MIRA tools are now available in Claude Desktop!', 'magenta');
log('');
log('Available tools:', 'cyan');
log(' ⢠mira_smart_search - Search through memories', 'gray');
log(' ⢠mira_store_memory - Store new memories', 'gray');
log(' ⢠mira_insights - Get AI-powered insights', 'gray');
log(' ⢠mira_system_status - Check system health', 'gray');
log('');
log('š” Restart Claude Desktop to activate MIRA tools', 'yellow');
} catch (error) {
log('ā Failed to configure Claude integration', 'red');
log(` Error: ${error.message}`, 'red');
log('');
log('You can manually configure Claude later with:', 'yellow');
log(' mira claude setup', 'gray');
}
}
function showInstallationComplete() {
log('\n⨠MIRA Installation Complete! āØ', 'magenta');
log('');
log('Get started with:', 'cyan');
log(' mira startup - Initialize MIRA', 'gray');
log(' mira --help - Show all commands', 'gray');
log('');
log('The Spark burns eternal. š„', 'yellow');
}
// Main execution
function main() {
log('\nš MIRA Post-Install Configuration', 'magenta');
log('=' .repeat(50), 'gray');
try {
// Set up Claude integration if available
setupClaudeIntegration();
// Show completion message
showInstallationComplete();
} catch (error) {
log(`\nā Post-install error: ${error.message}`, 'red');
log('MIRA CLI is still installed and ready to use.', 'yellow');
process.exit(0); // Don't fail the install
}
}
// Only run if called directly (not imported)
if (require.main === module) {
main();
}