BMAD-METHOD/_bmad/scripts/memtrace/inject-mcp-config.mjs

131 lines
3.8 KiB
JavaScript

import fs from 'node:fs/promises';
import path from 'node:path';
import os from 'node:os';
const args = process.argv.slice(2);
const modeArgIndex = args.indexOf('--mode');
const mode = modeArgIndex !== -1 ? args[modeArgIndex + 1] : null;
if (!mode || (mode !== 'claude' && mode !== 'opencode')) {
console.error('Error: Please specify --mode as "claude" or "opencode"');
process.exit(1);
}
// Helper to ensure parent directories exist
async function ensureDir(filePath) {
const dir = path.dirname(filePath);
try {
await fs.mkdir(dir, { recursive: true });
} catch (err) {
// Ignore if already exists or other error handled later
}
}
// Injects config for Claude Desktop
async function injectClaude() {
let configPath = process.env.TEST_CLAUDE_CONFIG_PATH || '';
if (!configPath) {
const homedir = os.homedir();
if (process.platform === 'win32') {
const appdata = process.env.APPDATA;
if (!appdata) {
console.warn('Warning: APPDATA environment variable not set. Cannot resolve Claude Desktop config path on Windows.');
return;
}
configPath = path.join(appdata, 'Claude', 'claude_desktop_config.json');
} else if (process.platform === 'darwin') {
configPath = path.join(homedir, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
} else {
// Linux/fallback
configPath = path.join(homedir, '.config', 'Claude', 'claude_desktop_config.json');
}
}
console.log(`Targeting Claude Desktop Config: ${configPath}`);
let configObj = {};
try {
const data = await fs.readFile(configPath, 'utf8');
configObj = JSON.parse(data);
} catch (err) {
if (err.code === 'ENOENT') {
console.log('Claude Desktop config file does not exist. Creating a new one...');
} else {
console.error(`Error reading or parsing Claude Desktop config: ${err.message}`);
console.warn('Attempting to overwrite with clean skeleton...');
}
}
// Inject or overwrite memtrace server
if (!configObj.mcpServers) {
configObj.mcpServers = {};
}
configObj.mcpServers.memtrace = {
command: 'memtrace',
args: ['mcp']
};
try {
await ensureDir(configPath);
await fs.writeFile(configPath, JSON.stringify(configObj, null, 2), 'utf8');
console.log('Successfully configured Memtrace MCP server in Claude Desktop config!');
} catch (err) {
console.error(`Failed to write Claude Desktop config: ${err.message}`);
}
}
// Injects config for OpenCode
async function injectOpenCode() {
const configPath = process.env.TEST_OPENCODE_CONFIG_PATH || path.resolve(process.cwd(), 'opencode.json');
console.log(`Targeting OpenCode Config: ${configPath}`);
let configObj = {};
try {
const data = await fs.readFile(configPath, 'utf8');
configObj = JSON.parse(data);
} catch (err) {
if (err.code === 'ENOENT') {
console.log('opencode.json does not exist. Creating a new one...');
} else {
console.error(`Error reading or parsing opencode.json: ${err.message}`);
console.warn('Attempting to overwrite with clean skeleton...');
}
}
// Inject or overwrite memtrace server
if (!configObj.mcp) {
configObj.mcp = {};
}
configObj.mcp.memtrace = {
type: 'local',
command: ['memtrace', 'mcp'],
enabled: true,
environment: {}
};
try {
await fs.writeFile(configPath, JSON.stringify(configObj, null, 2), 'utf8');
console.log('Successfully configured Memtrace MCP server in opencode.json!');
} catch (err) {
console.error(`Failed to write opencode.json: ${err.message}`);
}
}
async function run() {
if (mode === 'claude') {
await injectClaude();
} else if (mode === 'opencode') {
await injectOpenCode();
}
}
run().catch((err) => {
console.error(`Fatal execution error: ${err.message}`);
process.exit(1);
});