Skip to main content
Glama
config.ts5.68 kB
/** * Specter MCP Configuration * Environment-based configuration management */ /** * Configuration options for the MCP server */ export interface SpecterConfig { /** Server name */ serverName: string; /** Server version */ serverVersion: string; /** Enable debug logging */ debug: boolean; /** Log level: 'error' | 'warn' | 'info' | 'debug' */ logLevel: 'error' | 'warn' | 'info' | 'debug'; /** Default timeout for shell commands (ms) */ defaultTimeout: number; /** Maximum concurrent queue operations */ maxConcurrency: number; /** Android SDK path */ androidSdkPath?: string; /** Xcode path */ xcodePath?: string; /** Default Android device ID */ defaultAndroidDevice?: string; /** Default iOS simulator ID */ defaultIOSDevice?: string; /** Maestro binary path */ maestroPath?: string; /** Detekt config path */ detektConfigPath?: string; /** Enable AI model routing */ enableModelRouting: boolean; /** Primary AI model ID */ primaryModel: string; /** Worker AI model ID for lightweight tasks */ workerModel: string; /** Vision AI model ID for UI analysis */ visionModel: string; /** Anthropic API key (for model routing) */ anthropicApiKey?: string; } /** * Default configuration values */ const DEFAULT_CONFIG: SpecterConfig = { serverName: 'specter-mcp', serverVersion: '1.0.0', debug: false, logLevel: 'info', defaultTimeout: 60000, maxConcurrency: 1, enableModelRouting: false, primaryModel: 'claude-3-5-sonnet-20241022', workerModel: 'claude-3-haiku-20240307', visionModel: 'claude-3-5-sonnet-20241022', }; /** * Load configuration from environment variables */ function loadFromEnv(): Partial<SpecterConfig> { const env = process.env; return { debug: env.SPECTER_DEBUG === 'true' || env.DEBUG === 'true', logLevel: parseLogLevel(env.SPECTER_LOG_LEVEL || env.LOG_LEVEL), defaultTimeout: parseNumber(env.SPECTER_TIMEOUT, DEFAULT_CONFIG.defaultTimeout), maxConcurrency: parseNumber(env.SPECTER_CONCURRENCY, DEFAULT_CONFIG.maxConcurrency), androidSdkPath: env.ANDROID_SDK_ROOT || env.ANDROID_HOME, xcodePath: env.XCODE_PATH, defaultAndroidDevice: env.SPECTER_ANDROID_DEVICE, defaultIOSDevice: env.SPECTER_IOS_DEVICE, maestroPath: env.MAESTRO_PATH, detektConfigPath: env.DETEKT_CONFIG, enableModelRouting: env.SPECTER_MODEL_ROUTING === 'true', primaryModel: env.SPECTER_PRIMARY_MODEL || DEFAULT_CONFIG.primaryModel, workerModel: env.SPECTER_WORKER_MODEL || DEFAULT_CONFIG.workerModel, visionModel: env.SPECTER_VISION_MODEL || DEFAULT_CONFIG.visionModel, anthropicApiKey: env.ANTHROPIC_API_KEY, }; } /** * Parse log level from string */ function parseLogLevel(value?: string): 'error' | 'warn' | 'info' | 'debug' { const level = value?.toLowerCase(); if (level === 'error' || level === 'warn' || level === 'info' || level === 'debug') { return level; } return DEFAULT_CONFIG.logLevel; } /** * Parse number from string */ function parseNumber(value: string | undefined, defaultValue: number): number { if (!value) return defaultValue; const parsed = parseInt(value, 10); return isNaN(parsed) ? defaultValue : parsed; } // Singleton configuration instance let configInstance: SpecterConfig | null = null; /** * Get the global configuration instance */ export function getConfig(): SpecterConfig { if (!configInstance) { configInstance = { ...DEFAULT_CONFIG, ...loadFromEnv(), }; } return configInstance; } /** * Override configuration (useful for testing) */ export function setConfig(config: Partial<SpecterConfig>): void { configInstance = { ...getConfig(), ...config, }; } /** * Reset configuration to defaults (useful for testing) */ export function resetConfig(): void { configInstance = null; } /** * Check if running in debug mode */ export function isDebug(): boolean { return getConfig().debug; } /** * Get effective timeout for operations */ export function getTimeout(override?: number): number { return override ?? getConfig().defaultTimeout; } /** * Log message based on log level */ export function log(level: 'error' | 'warn' | 'info' | 'debug', message: string, ...args: unknown[]): void { const config = getConfig(); const levels = { error: 0, warn: 1, info: 2, debug: 3 }; if (levels[level] <= levels[config.logLevel]) { const prefix = `[specter-mcp:${level}]`; if (level === 'error') { console.error(prefix, message, ...args); } else if (level === 'warn') { console.warn(prefix, message, ...args); } else { console.error(prefix, message, ...args); // MCP uses stderr for logging } } } /** * Validate configuration and return warnings */ export function validateConfig(): string[] { const config = getConfig(); const warnings: string[] = []; // Check for Android SDK if (!config.androidSdkPath) { warnings.push('ANDROID_SDK_ROOT not set - Android tools may not work'); } // Check for model routing requirements if (config.enableModelRouting && !config.anthropicApiKey) { warnings.push('Model routing enabled but ANTHROPIC_API_KEY not set'); } return warnings; } /** * Print configuration summary (for debugging) */ export function printConfigSummary(): void { const config = getConfig(); log('info', 'Configuration:'); log('info', ` Debug: ${config.debug}`); log('info', ` Log Level: ${config.logLevel}`); log('info', ` Timeout: ${config.defaultTimeout}ms`); log('info', ` Android SDK: ${config.androidSdkPath || 'not set'}`); log('info', ` Model Routing: ${config.enableModelRouting}`); }

Latest Blog Posts

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/abd3lraouf/specter-mcp'

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