@openmemory/install
Version:
OpenMemory MCP server installation tool
188 lines (183 loc) • 6.66 kB
JavaScript
// src/client-config.ts
import fs from "fs";
import os from "os";
import path from "path";
import process from "process";
// src/logger.ts
import { createConsola } from "consola";
var logger = createConsola({});
var verbose = (msg) => logger.verbose(msg);
// src/client-config.ts
var homeDir = os.homedir();
var platformPaths = {
win32: {
baseDir: process.env.APPDATA || path.join(homeDir, "AppData", "Roaming"),
vscodePath: path.join("Code", "User", "globalStorage")
},
darwin: {
baseDir: path.join(homeDir, "Library", "Application Support"),
vscodePath: path.join("Code", "User", "globalStorage")
},
linux: {
baseDir: process.env.XDG_CONFIG_HOME || path.join(homeDir, ".config"),
vscodePath: path.join("Code/User/globalStorage")
}
};
var platform = process.platform;
var { baseDir, vscodePath } = platformPaths[platform];
var defaultClaudePath = path.join(baseDir, "Claude", "claude_desktop_config.json");
var clientPaths = {
claude: { type: "file", path: defaultClaudePath },
cline: {
type: "file",
path: path.join(baseDir, vscodePath, "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json")
},
roocline: {
type: "file",
path: path.join(baseDir, vscodePath, "rooveterinaryinc.roocline", "settings", "mcp_settings.json")
},
windsurf: {
type: "file",
path: path.join(homeDir, ".codeium", "windsurf", "mcp_config.json")
},
witsy: { type: "file", path: path.join(baseDir, "Witsy", "settings.json") },
enconvo: {
type: "file",
path: path.join(homeDir, ".config", "enconvo", "mcp_config.json")
},
cursor: {
type: "file",
path: path.join(homeDir, ".cursor", "mcp.json"),
localPath: path.join(process.cwd(), ".cursor", "mcp.json")
},
augment: {
type: "file",
path: "[vscode-settings]"
}
};
var clientNames = Object.keys(clientPaths);
function getConfigPath(client, local) {
const normalizedClient = client?.toLowerCase() || "claude";
verbose(`Getting config path for client: ${normalizedClient}${local ? " (local)" : ""}`);
const configTarget = clientPaths[normalizedClient];
if (!configTarget) {
return {
type: "file",
path: path.join(path.dirname(defaultClaudePath), "..", client || "claude", `${normalizedClient}_config.json`)
};
}
if (local && configTarget.localPath) {
verbose(`Using local config path for ${normalizedClient}: ${configTarget.localPath}`);
return { ...configTarget, path: configTarget.localPath };
}
verbose(`Using default config path for ${normalizedClient}: ${configTarget.path}`);
return configTarget;
}
function readConfig(client, local) {
verbose(`Reading config for client: ${client}${local ? " (local)" : ""}`);
try {
const configPath = getConfigPath(client, local);
verbose(`Checking if config file exists at: ${configPath.path}`);
if (!fs.existsSync(configPath.path)) {
verbose("Config file not found, returning default empty config");
return { mcpServers: {} };
}
verbose("Reading config file content");
const rawConfig = JSON.parse(fs.readFileSync(configPath.path, "utf8"));
verbose(`Config loaded successfully: ${JSON.stringify(rawConfig, null, 2)}`);
return {
...rawConfig,
mcpServers: rawConfig.mcpServers || {}
};
} catch (error) {
verbose(`Error reading config: ${error instanceof Error ? error.stack : JSON.stringify(error)}`);
return { mcpServers: {} };
}
}
function writeConfig(config, client, local) {
verbose(`Writing config for client: ${client || "default"}${local ? " (local)" : ""}`);
verbose(`Config data: ${JSON.stringify(config, null, 2)}`);
if (!config.mcpServers || typeof config.mcpServers !== "object") {
verbose("Invalid mcpServers structure in config");
throw new Error("Invalid mcpServers structure");
}
const configPath = getConfigPath(client, local);
writeConfigFile(config, configPath);
}
function writeConfigFile(config, target) {
const configDir = path.dirname(target.path);
verbose(`Ensuring config directory exists: ${configDir}`);
if (!fs.existsSync(configDir)) {
verbose(`Creating directory: ${configDir}`);
fs.mkdirSync(configDir, { recursive: true });
}
let existingConfig = { mcpServers: {} };
try {
if (fs.existsSync(target.path)) {
verbose("Reading existing config file for merging");
existingConfig = JSON.parse(fs.readFileSync(target.path, "utf8"));
verbose(`Existing config loaded: ${JSON.stringify(existingConfig, null, 2)}`);
}
} catch (error) {
verbose(`Error reading existing config for merge: ${error instanceof Error ? error.message : String(error)}`);
}
verbose("Merging configs");
const mergedConfig = {
...existingConfig,
...config
};
verbose(`Merged config: ${JSON.stringify(mergedConfig, null, 2)}`);
verbose(`Writing config to file: ${target.path}`);
fs.writeFileSync(target.path, JSON.stringify(mergedConfig, null, 2));
verbose("Config successfully written");
}
function getVSCodeUserSettingsPath() {
let settingsPath;
if (platform === "win32") {
settingsPath = path.join(process.env.APPDATA || "", "Code", "User", "settings.json");
} else if (platform === "darwin") {
settingsPath = path.join(homeDir, "Library", "Application Support", "Code", "User", "settings.json");
} else {
settingsPath = path.join(homeDir, ".config", "Code", "User", "settings.json");
}
return settingsPath;
}
function writeAugmentVSCodeSettingsFromObject(server) {
const settingsPath = getVSCodeUserSettingsPath();
verbose(`Augment: Updating VS Code settings at ${settingsPath}`);
let settings = {};
try {
if (fs.existsSync(settingsPath)) {
settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
verbose(`Loaded VS Code settings: ${JSON.stringify(settings, null, 2)}`);
}
} catch (e) {
verbose(`Failed to read VS Code settings: ${e.message}`);
}
const key = "augment.advanced";
if (!settings[key]) {
settings[key] = {};
}
if (!Array.isArray(settings[key].mcpServers)) {
settings[key].mcpServers = [];
}
settings[key].mcpServers = settings[key].mcpServers.filter(
(s) => s.name !== server.name
);
settings[key].mcpServers.push(server);
const settingsDir = path.dirname(settingsPath);
if (!fs.existsSync(settingsDir)) {
fs.mkdirSync(settingsDir, { recursive: true });
}
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
verbose(`VS Code settings under "${key}" updated successfully.`);
}
export {
logger,
clientNames,
getConfigPath,
readConfig,
writeConfig,
writeAugmentVSCodeSettingsFromObject
};