Skip to main content
Glama
config.ts4.98 kB
/** * Configuration management utilities */ import { readFile } from 'fs/promises'; import { existsSync } from 'fs'; import { join } from 'path'; import { Configuration } from '../types/config.js'; const DEFAULT_CONFIG: Configuration = { server: { name: 'shortcut-mcp', version: '1.0.0', description: 'macOS Shortcuts MCP Server' }, shortcuts: { allowedPrefixes: [], blockedShortcuts: [], maxExecutionTime: 30000, defaultTimeout: 10000, cacheTimeout: 300000, enableCache: true }, security: { requireConfirmation: false, logExecutions: true, allowSystemShortcuts: false, sandboxMode: false, maxInputSize: 1048576, enableRateLimit: true, allowedPrefixes: [], blockedShortcuts: [], rateLimit: { windowMs: 60000, maxRequests: 100 } }, logging: { level: 'info', console: true, format: 'text', enableDebug: false }, performance: { enableCaching: true, cacheSize: 1000, cacheTTL: 300, maxConcurrentExecutions: 5, enableMetrics: true } }; export async function loadConfig(configPath?: string): Promise<Configuration> { const config = { ...DEFAULT_CONFIG }; // Try to load from file if (configPath && existsSync(configPath)) { try { const fileContent = await readFile(configPath, 'utf-8'); const fileConfig = JSON.parse(fileContent); mergeConfig(config, fileConfig); } catch (error) { console.warn(`Failed to load config from ${configPath}:`, error); } } else { // Try default locations const defaultPaths = [ './config/default.json', './config.json', join(process.cwd(), 'config/default.json') ]; for (const path of defaultPaths) { if (existsSync(path)) { try { const fileContent = await readFile(path, 'utf-8'); const fileConfig = JSON.parse(fileContent); mergeConfig(config, fileConfig); break; } catch (error) { console.warn(`Failed to load config from ${path}:`, error); } } } } // Override with environment variables applyEnvironmentOverrides(config); // Validate configuration validateConfig(config); return config; } function mergeConfig(target: any, source: any): void { for (const key in source) { if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) { if (!target[key]) target[key] = {}; mergeConfig(target[key], source[key]); } else { target[key] = source[key]; } } } function applyEnvironmentOverrides(config: Configuration): void { // Server overrides if (process.env.SERVER_NAME) { config.server.name = process.env.SERVER_NAME; } if (process.env.SERVER_PORT) { config.server.port = parseInt(process.env.SERVER_PORT, 10); } // Logging overrides if (process.env.LOG_LEVEL) { config.logging.level = process.env.LOG_LEVEL as any; } if (process.env.LOG_FILE) { config.logging.file = process.env.LOG_FILE; } if (process.env.DEBUG === 'true') { config.logging.level = 'debug'; config.logging.enableDebug = true; } // Security overrides if (process.env.ALLOW_SYSTEM_SHORTCUTS === 'true') { config.security.allowSystemShortcuts = true; } if (process.env.REQUIRE_CONFIRMATION === 'true') { config.security.requireConfirmation = true; } if (process.env.MAX_EXECUTION_TIME) { config.shortcuts.maxExecutionTime = parseInt(process.env.MAX_EXECUTION_TIME, 10); } // Performance overrides if (process.env.ENABLE_CACHE === 'false') { config.shortcuts.enableCache = false; config.performance.enableCaching = false; } } function validateConfig(config: Configuration): void { // Validate server config if (!config.server.name || !config.server.version) { throw new Error('Server name and version are required'); } // Validate timeouts if (config.shortcuts.maxExecutionTime < 1000) { throw new Error('maxExecutionTime must be at least 1000ms'); } if (config.shortcuts.defaultTimeout < 1000) { throw new Error('defaultTimeout must be at least 1000ms'); } // Validate security config if (config.security.maxInputSize < 1024) { throw new Error('maxInputSize must be at least 1024 bytes'); } // Validate rate limiting if (config.security.enableRateLimit) { if (config.security.rateLimit.windowMs < 1000) { throw new Error('Rate limit window must be at least 1000ms'); } if (config.security.rateLimit.maxRequests < 1) { throw new Error('Rate limit max requests must be at least 1'); } } // Validate logging level const validLevels = ['debug', 'info', 'warn', 'error']; if (!validLevels.includes(config.logging.level)) { throw new Error(`Invalid log level: ${config.logging.level}`); } } export function getDefaultConfig(): Configuration { return JSON.parse(JSON.stringify(DEFAULT_CONFIG)); }

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/aezizhu/shortcut-mcp'

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