Skip to main content
Glama

1MCP Server

configUtils.ts9.14 kB
import fs from 'fs'; import path from 'path'; import ConfigContext from '@src/config/configContext.js'; import { McpConfigManager } from '@src/config/mcpConfigManager.js'; import { MCPServerParams } from '@src/core/types/index.js'; import logger from '@src/logger/logger.js'; /** * Configuration file utilities for server management commands */ /** * Initialize the configuration context with CLI options * This should be called at the beginning of each command */ export function initializeConfigContext(configPath?: string, configDir?: string): void { const configContext = ConfigContext.getInstance(); if (configPath) { configContext.setConfigPath(configPath); } else if (configDir) { configContext.setConfigDir(configDir); } else { configContext.reset(); // Use defaults } } export interface ServerConfig { mcpServers: Record<string, MCPServerParams>; } /** * Load the MCP configuration from a file * Uses ConfigContext to resolve the appropriate config file path */ export function loadConfig(configPath?: string): ServerConfig { const configContext = ConfigContext.getInstance(); const filePath = configPath || configContext.getResolvedConfigPath(); try { if (!fs.existsSync(filePath)) { throw new Error(`Configuration file not found: ${filePath}`); } const configData = JSON.parse(fs.readFileSync(filePath, 'utf8')); // Ensure mcpServers exists if (!configData.mcpServers) { configData.mcpServers = {}; } return configData; } catch (error) { if (error instanceof SyntaxError) { throw new Error(`Invalid JSON in configuration file: ${filePath}`); } throw error; } } /** * Save the MCP configuration to a file * Uses ConfigContext to resolve the appropriate config file path */ export function saveConfig(config: ServerConfig): void { const configContext = ConfigContext.getInstance(); const filePath = configContext.getResolvedConfigPath(); try { // Ensure directory exists const fileDir = path.dirname(filePath); if (!fs.existsSync(fileDir)) { fs.mkdirSync(fileDir, { recursive: true }); } // Write configuration with pretty formatting fs.writeFileSync(filePath, JSON.stringify(config, null, 2)); logger.info(`Configuration saved to: ${filePath}`); } catch (error) { throw new Error(`Failed to save configuration to ${filePath}: ${error}`); } } /** * Check if a server exists in the configuration */ export function serverExists(serverName: string): boolean { try { const config = loadConfig(); return serverName in config.mcpServers; } catch (_error) { return false; } } /** * Get a specific server configuration */ export function getServer(serverName: string): MCPServerParams | null { try { const config = loadConfig(); return config.mcpServers[serverName] || null; } catch (_error) { return null; } } /** * Add or update a server in the configuration */ export function setServer(serverName: string, serverConfig: MCPServerParams): void { const configContext = ConfigContext.getInstance(); const filePath = configContext.getResolvedConfigPath(); let config: ServerConfig; // Check if config file exists before trying to load it if (!fs.existsSync(filePath)) { // Create a new config if it doesn't exist config = { mcpServers: {} }; } else { // Load existing config (will throw on invalid JSON or other errors) config = loadConfig(); } config.mcpServers[serverName] = serverConfig; saveConfig(config); } /** * Remove a server from the configuration */ export function removeServer(serverName: string): boolean { try { const config = loadConfig(); if (!(serverName in config.mcpServers)) { return false; } delete config.mcpServers[serverName]; saveConfig(config); return true; } catch (error) { throw new Error(`Failed to remove server ${serverName}: ${error}`); } } /** * Get all servers in the configuration */ export function getAllServers(): Record<string, MCPServerParams> { try { const config = loadConfig(); return config.mcpServers; } catch (_error) { return {}; } } /** * Parse environment variables from key=value format */ export function parseEnvVars(envArray?: string[]): Record<string, string> { if (!envArray || envArray.length === 0) { return {}; } const env: Record<string, string> = {}; for (const envVar of envArray) { const equalIndex = envVar.indexOf('='); if (equalIndex === -1) { throw new Error(`Invalid environment variable format: ${envVar}. Expected key=value`); } const key = envVar.substring(0, equalIndex).trim(); const value = envVar.substring(equalIndex + 1); if (!key) { throw new Error(`Invalid environment variable format: ${envVar}. Key cannot be empty`); } env[key] = value; } return env; } /** * Parse headers from key=value format */ export function parseHeaders(headersArray?: string[]): Record<string, string> { if (!headersArray || headersArray.length === 0) { return {}; } const headers: Record<string, string> = {}; for (const header of headersArray) { const colonIndex = header.indexOf('='); if (colonIndex === -1) { throw new Error(`Invalid header format: ${header}. Expected key=value`); } const key = header.substring(0, colonIndex).trim(); const value = header.substring(colonIndex + 1); if (!key) { throw new Error(`Invalid header format: ${header}. Key cannot be empty`); } headers[key] = value; } return headers; } /** * Parse tags from comma-separated string */ export function parseTags(tagsString?: string): string[] { if (!tagsString) { return []; } return tagsString .split(',') .map((tag) => tag.trim()) .filter((tag) => tag.length > 0); } /** * Validate configuration file path */ export function validateConfigPath(configPath?: string): string { const configContext = ConfigContext.getInstance(); const filePath = configPath || configContext.getResolvedConfigPath(); try { // Check if file exists if (!fs.existsSync(filePath)) { throw new Error(`Configuration file not found: ${filePath}`); } // Check if file is readable fs.accessSync(filePath, fs.constants.R_OK); // Check if file is writable fs.accessSync(filePath, fs.constants.W_OK); return filePath; } catch (error) { if (error instanceof Error && error.message.includes('not found')) { throw error; } throw new Error(`Cannot access configuration file: ${filePath}. ${error}`); } } /** * Create a backup of the configuration file */ export function backupConfig(): string { const configContext = ConfigContext.getInstance(); const filePath = configContext.getResolvedConfigPath(); const timestamp = Date.now(); const backupPath = `${filePath}.backup.${timestamp}`; try { fs.copyFileSync(filePath, backupPath); logger.info(`Configuration backed up to: ${backupPath}`); return backupPath; } catch (error) { throw new Error(`Failed to create backup: ${error}`); } } /** * Validate server configuration against schema */ export function validateServerConfig(serverConfig: MCPServerParams): void { // Basic validation - type is required if (!serverConfig.type) { throw new Error('Server type is required'); } // Validate based on type switch (serverConfig.type) { case 'stdio': if (!serverConfig.command) { throw new Error('Command is required for stdio servers'); } break; case 'http': case 'sse': if (!serverConfig.url) { throw new Error(`URL is required for ${serverConfig.type} servers`); } try { new URL(serverConfig.url); } catch (_error) { throw new Error(`Invalid URL format: ${serverConfig.url}`); } break; default: throw new Error(`Unsupported server type: ${serverConfig.type}`); } // Validate timeout if provided if (serverConfig.timeout !== undefined) { if (typeof serverConfig.timeout !== 'number' || serverConfig.timeout < 0) { throw new Error('Timeout must be a positive number'); } } // Validate tags if provided if (serverConfig.tags !== undefined) { if (!Array.isArray(serverConfig.tags)) { throw new Error('Tags must be an array'); } for (const tag of serverConfig.tags) { if (typeof tag !== 'string' || tag.trim().length === 0) { throw new Error('All tags must be non-empty strings'); } } } } /** * Reload MCP config manager after configuration changes */ export function reloadMcpConfig(): void { try { const configContext = ConfigContext.getInstance(); const filePath = configContext.getResolvedConfigPath(); // Get the config manager instance and reload it const configManager = McpConfigManager.getInstance(filePath); configManager.reloadConfig(); logger.info('MCP configuration reloaded'); } catch (error) { logger.warn(`Failed to reload MCP configuration: ${error}`); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/1mcp-app/agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server