Skip to main content
Glama

Ultra MCP

manager.ts8.05 kB
import { ConfigSchema, Config, defaultConfig, VectorConfig } from './schema'; import { join } from 'path'; import { platform, homedir } from 'os'; import { mkdirSync } from 'fs'; import type Conf from 'conf'; import { logger } from '../utils/logger'; export type { Config }; export class ConfigManager { private store: Conf<Config> | undefined; private initialized: Promise<void>; constructor() { this.initialized = this.init(); } private async init(): Promise<void> { const Conf = (await import('conf')).default; this.store = new Conf<Config>({ projectName: 'ultra-mcp', defaults: defaultConfig, }); } private async ensureInitialized(): Promise<void> { await this.initialized; } // Get the entire configuration async getConfig(): Promise<Config> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } // Handle legacy Azure configuration migration await this.migrateLegacyAzureConfig(); const rawConfig = this.store.store; const result = ConfigSchema.safeParse(rawConfig); if (!result.success) { logger.error('Invalid configuration found, resetting to defaults'); await this.reset(); return defaultConfig; } return result.data; } // Migrate legacy Azure configuration private async migrateLegacyAzureConfig(): Promise<void> { if (!this.store) return; const rawConfig = this.store.store as any; if (rawConfig?.azure && !rawConfig?.azure?.resourceName) { // Check for legacy endpoint or baseURL const legacyUrl = rawConfig.azure.endpoint || rawConfig.azure.baseURL; if (legacyUrl) { // Extract resource name from legacy URL const match = legacyUrl.match(/https:\/\/(.+?)\.openai\.azure\.com/); if (match && match[1]) { // Migrate to new structure this.store.set('azure.resourceName', match[1]); // 'azure.endpoint' doesn't exist in the new schema, just skip // this.store.delete('azure.endpoint'); this.store.delete('azure.baseURL'); logger.log(`Migrated legacy Azure ${rawConfig.azure.endpoint ? 'endpoint' : 'baseURL'} to resourceName: ${match[1]}`); } } } } // Set a specific API key async setApiKey(provider: 'openai' | 'google' | 'azure' | 'xai', apiKey: string | undefined): Promise<void> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } if (!apiKey) { this.store.delete(`${provider}.apiKey`); } else { this.store.set(`${provider}.apiKey`, apiKey); } } // Get a specific API key async getApiKey(provider: 'openai' | 'google' | 'azure' | 'xai'): Promise<string | undefined> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } return this.store.get(`${provider}.apiKey`); } // Set a specific baseURL async setBaseURL(provider: 'openai' | 'google' | 'azure' | 'xai', baseURL: string | undefined): Promise<void> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } if (!baseURL) { this.store.delete(`${provider}.baseURL`); } else { this.store.set(`${provider}.baseURL`, baseURL); } } // Get a specific baseURL async getBaseURL(provider: 'openai' | 'google' | 'azure' | 'xai'): Promise<string | undefined> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } return this.store.get(`${provider}.baseURL`); } // Set Azure baseURL (deprecated, use setBaseURL instead) async setAzureBaseURL(baseURL: string | undefined): Promise<void> { return this.setBaseURL('azure', baseURL); } // Set Azure resource name async setAzureResourceName(resourceName: string | undefined): Promise<void> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } if (!resourceName) { this.store.delete('azure.resourceName'); } else { this.store.set('azure.resourceName', resourceName); } } // Get Azure resource name async getAzureResourceName(): Promise<string | undefined> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } return this.store.get('azure.resourceName'); } // Set vector configuration async setVectorConfig(vectorConfig: VectorConfig): Promise<void> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } this.store.set('vectorConfig', vectorConfig); } // Check if any API keys are configured async hasAnyApiKeys(): Promise<boolean> { const config = await this.getConfig(); return !!( config.openai?.apiKey || config.google?.apiKey || config.azure?.apiKey || config.xai?.apiKey ); } // Get the path to the config file async getConfigPath(): Promise<string> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } return this.store.path; } // Update configuration with partial data async updateConfig(updates: Partial<Config>): Promise<void> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } const currentConfig = await this.getConfig(); const newConfig = { ...currentConfig, ...updates }; // Deep merge for nested objects Object.keys(updates).forEach(key => { if (updates[key as keyof Config] && typeof updates[key as keyof Config] === 'object' && !Array.isArray(updates[key as keyof Config])) { newConfig[key as keyof Config] = { ...currentConfig[key as keyof Config], ...updates[key as keyof Config] } as any; } }); this.store.store = newConfig; } // Reset configuration to defaults async reset(): Promise<void> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } this.store.clear(); } // Validate the current configuration async validate(): Promise<{ valid: boolean; errors?: string[] }> { await this.ensureInitialized(); if (!this.store) { throw new Error('Configuration store not initialized'); } const result = ConfigSchema.safeParse(this.store.store); if (result.success) { return { valid: true }; } const errors = result.error.errors.map(err => `${err.path.join('.')}: ${err.message}` ); return { valid: false, errors }; } // Get the database file path getDatabasePath(): string { const configDir = this.getConfigDir(); return join(configDir, 'usage-v1.db'); } // Get the configuration directory path private getConfigDir(): string { const os = platform(); let configDir: string; if (os === 'win32') { // Windows: %APPDATA%/ultra-mcp-nodejs/ const appData = process.env.APPDATA; if (!appData) { throw new Error('APPDATA environment variable not found'); } configDir = join(appData, 'ultra-mcp-nodejs'); } else { // Unix-like (macOS/Linux): ~/.config/ultra-mcp/ configDir = join(homedir(), '.config', 'ultra-mcp'); } // Ensure directory exists try { mkdirSync(configDir, { recursive: true }); } catch { // Directory might already exist, that's ok } return configDir; } } // Singleton instance let configManagerInstance: ConfigManager | null = null; export async function getConfigManager(): Promise<ConfigManager> { if (!configManagerInstance) { configManagerInstance = new ConfigManager(); } return configManagerInstance; }

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/RealMikeChong/ultra-mcp'

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