mcp-config
Version:
CLI client to edit MCP server configurations
115 lines (100 loc) • 3.52 kB
text/typescript
import fs from 'fs-extra';
import path from 'path';
import inquirer from 'inquirer';
import { MCPConfig, MCPClientConfig } from '../types/types.js';
import { getPlatformClients as getMCPClients } from '../config/clients.js';
import pc from 'picocolors';
// Active MCP client config (will be set dynamically)
let activeMCPClient: MCPClientConfig | null = null;
/**
* Checks which MCP client configs exist on the system
*/
export const getAvailableMCPClients = async (): Promise<MCPClientConfig[]> => {
const availableClients: MCPClientConfig[] = [];
for (const client of getMCPClients()) {
if (await fs.pathExists(client.path)) {
availableClients.push(client);
}
}
return availableClients;
};
/**
* Prompts the user to select an MCP client
*/
export const promptUserForMCPClient = async (
availableClients: MCPClientConfig[]
): Promise<MCPClientConfig> => {
const clients = availableClients.length > 0 ? availableClients : getMCPClients();
// Create a message based on whether clients were found
const message =
availableClients.length > 0
? 'Select an MCP client:'
: 'No existing MCP clients found. Select a client to create a new configuration:';
// Use inquirer to prompt the user with a list
const { selectedClient } = await inquirer.prompt([
{
type: 'list',
name: 'selectedClient',
message,
choices: clients.map((client) => ({
name: `${client.name} (${client.description})`,
value: client,
})),
default: clients[0],
},
]);
return selectedClient;
};
/**
* Gets the MCP config file, creates it if it doesn't exist
*/
export const getMCPConfig = async (): Promise<MCPConfig> => {
try {
// If we already determined the active client, use it
if (!activeMCPClient) {
const availableClients = await getAvailableMCPClients();
if (availableClients.length === 1) {
// Only one client exists, use it
activeMCPClient = availableClients[0];
console.log(
`Only one MCP client found: ${activeMCPClient.name}. Using its configuration at: ${activeMCPClient.path}`
);
} else {
// Multiple or no clients exist, ask user to select
activeMCPClient = await promptUserForMCPClient(availableClients);
console.log(`Using MCP configuration at: ${pc.dim(activeMCPClient.path)}\n`);
}
}
// Ensure the directory exists
await fs.ensureDir(path.dirname(activeMCPClient.path));
// Check if the file exists
if (await fs.pathExists(activeMCPClient.path)) {
const configContent = await fs.readFile(activeMCPClient.path, 'utf-8');
return JSON.parse(configContent);
} else {
// Create a default config if the file doesn't exist
const defaultConfig: MCPConfig = {
mcpServers: {},
};
await fs.writeFile(activeMCPClient.path, JSON.stringify(defaultConfig, null, 2));
return defaultConfig;
}
} catch (error) {
console.error('Error getting MCP config:', error);
throw error;
}
};
/**
* Updates the MCP config file with new server configurations
*/
export const updateMCPConfig = async (config: MCPConfig): Promise<void> => {
try {
if (!activeMCPClient) {
throw new Error('No active MCP client selected. Call getMCPConfig first.');
}
await fs.writeFile(activeMCPClient.path, JSON.stringify(config, null, 2));
} catch (error) {
console.error('Error updating MCP config:', error);
throw error;
}
};