@civic/nexus-bridge
Version:
Stdio <-> HTTP/SSE MCP bridge with Civic auth handling
106 lines • 4.05 kB
JavaScript
/**
* claude-desktop.ts
*
* Installer for Claude Desktop application
*/
import * as fs from 'fs/promises';
import * as path from 'path';
import * as os from 'os';
import inquirer from "inquirer";
import { extractCommandInfo } from './util.js';
/**
* Get the path to the Claude Desktop config file
* Currently supports macOS only
*/
function getClaudeDesktopConfigPath() {
const homedir = os.homedir();
// macOS configuration path
return path.join(homedir, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
}
/**
* Install Nexus Bridge for Claude Desktop
*/
export async function installForClaudeDesktop() {
console.log('Installing Nexus Bridge for Claude Desktop...');
// Get config file path
const configPath = getClaudeDesktopConfigPath();
console.log(`Looking for Claude Desktop config at: ${configPath}`);
try {
// Check if the config file exists
const result = await fs
.access(configPath)
.then(() => true)
.catch((error) => {
if (error.code === "ENOENT") {
console.log("Existing Claude Desktop config found, updating...");
return false;
}
else {
throw error;
}
});
// We need to ask the user with a Y/N if they want to create the config file
if (!result) {
const answer = await inquirer.prompt([
{
type: "confirm",
name: "createConfig",
message: "No config file found, would you like to create one?",
},
]);
if (!answer.createConfig) {
throw new Error("No config file found, and user declined to create one");
}
if (answer.createConfig) {
console.log("Creating config file...");
await fs.writeFile(configPath, JSON.stringify({}, null, 2), "utf-8");
}
}
console.log('Existing Claude Desktop config found, updating...');
// Read and parse the existing config
const configContent = await fs.readFile(configPath, 'utf-8');
let config;
try {
config = JSON.parse(configContent);
}
catch (parseError) {
console.error(`Error parsing config file: ${parseError}`);
throw new Error(`The Claude Desktop config file exists but is not valid JSON. Please check the file at ${configPath}`);
}
// Initialize mcpServers if it doesn't exist
if (!config.mcpServers) {
config.mcpServers = {};
}
// Only add Civic if it doesn't already exist
const mcpServers = config.mcpServers;
if (!mcpServers.Civic) {
console.log('Adding Civic MCP server to configuration...');
// Extract the command that was used to run this installer
const { command, args } = extractCommandInfo();
mcpServers.Civic = {
command,
args
};
}
else {
console.log('Civic MCP server already configured, skipping...');
// No changes needed, exit without writing to the file
return;
}
// Write the updated config back to file
try {
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
console.log(`Configuration updated successfully at ${configPath}`);
}
catch (writeError) {
console.error(`Error writing config file: ${writeError}`);
throw writeError;
}
}
catch {
// If file doesn't exist or can't be accessed
console.error(`Claude Desktop config file not found at ${configPath}`);
throw new Error(`Could not find Claude Desktop configuration. Please make sure Claude Desktop is installed and you have a config file at ${configPath}`);
}
}
//# sourceMappingURL=claude-desktop.js.map