UNPKG

andrew-dataverse-mcp

Version:

A Model Context Protocol server for Microsoft Dataverse with comprehensive CRUD operations

122 lines (121 loc) 5.28 kB
import dotenv from 'dotenv'; // Load environment variables from .env file dotenv.config(); let config = null; let configLoaded = false; /** * Initialize configuration from CLI arguments or environment variables */ export function initializeConfig(args = {}) { if (configLoaded) return; // Load from CLI arguments (highest priority) const cliConfig = { DATAVERSE_CLIENT_ID: args.clientId, DATAVERSE_CLIENT_SECRET: args.clientSecret, DATAVERSE_TENANT_ID: args.tenantId, DATAVERSE_ENVIRONMENT_URL: args.environmentUrl, LOG_LEVEL: args.logLevel, RATE_LIMIT_REQUESTS_PER_MINUTE: args.rateLimit, }; // Load from environment variables (fallback) const envConfig = { DATAVERSE_CLIENT_ID: process.env.DATAVERSE_CLIENT_ID, DATAVERSE_CLIENT_SECRET: process.env.DATAVERSE_CLIENT_SECRET, DATAVERSE_TENANT_ID: process.env.DATAVERSE_TENANT_ID, DATAVERSE_ENVIRONMENT_URL: process.env.DATAVERSE_ENVIRONMENT_URL, LOG_LEVEL: process.env.LOG_LEVEL, RATE_LIMIT_REQUESTS_PER_MINUTE: process.env.RATE_LIMIT_REQUESTS_PER_MINUTE, }; // Merge configurations (CLI takes precedence over env) const mergedConfig = { ...envConfig }; Object.entries(cliConfig).forEach(([key, value]) => { if (value) { mergedConfig[key] = value; } }); // Debug: Log what we received console.error('[Config] CLI arguments received:', args); console.error('[Config] Merged config (clientId only):', mergedConfig.DATAVERSE_CLIENT_ID ? 'present' : 'missing'); // Determine configuration source for logging const hasCliArgs = Object.values(cliConfig).some(v => v); const hasEnvVars = Object.values(envConfig).some(v => v); let configSource = 'defaults'; if (hasCliArgs && hasEnvVars) { configSource = 'CLI arguments + environment'; } else if (hasCliArgs) { configSource = 'CLI arguments'; } else if (hasEnvVars) { configSource = 'environment variables'; } // Check for personal auth mode const usePersonalAuth = !mergedConfig.DATAVERSE_CLIENT_SECRET || mergedConfig.DATAVERSE_CLIENT_SECRET?.toLowerCase() === 'personal'; // Validate required configuration const missing = []; if (!mergedConfig.DATAVERSE_CLIENT_ID) missing.push('DATAVERSE_CLIENT_ID (--clientId)'); if (!usePersonalAuth && !mergedConfig.DATAVERSE_CLIENT_SECRET) missing.push('DATAVERSE_CLIENT_SECRET (--clientSecret)'); if (!mergedConfig.DATAVERSE_TENANT_ID) missing.push('DATAVERSE_TENANT_ID (--tenantId)'); if (!mergedConfig.DATAVERSE_ENVIRONMENT_URL) missing.push('DATAVERSE_ENVIRONMENT_URL (--environmentUrl)'); if (missing.length > 0) { const authMode = usePersonalAuth ? 'personal authentication' : 'application authentication'; console.error(`\n❌ Missing required configuration for ${authMode}:`); missing.forEach(key => { console.error(` ${key}`); }); if (usePersonalAuth) { console.error(`\n💡 Personal authentication mode detected (no client secret provided)`); console.error(` You'll be prompted to sign in with your Microsoft account when the server starts`); console.error(` Required arguments: --clientId, --tenantId, --environmentUrl`); } else { console.error(`\n💡 Application authentication mode detected`); console.error(` Required arguments: --clientId, --clientSecret, --tenantId, --environmentUrl`); } console.error(`\nExample usage:`); if (usePersonalAuth) { console.error(` node index.js --clientId "your-app-id" --tenantId "your-tenant-id" --environmentUrl "https://yourorg.crm.dynamics.com"`); } else { console.error(` node index.js --clientId "your-app-id" --clientSecret "your-secret" --tenantId "your-tenant-id" --environmentUrl "https://yourorg.crm.dynamics.com"`); } process.exit(1); } // Set the configuration config = { dataverse: { clientId: mergedConfig.DATAVERSE_CLIENT_ID, clientSecret: mergedConfig.DATAVERSE_CLIENT_SECRET || '', tenantId: mergedConfig.DATAVERSE_TENANT_ID, environmentUrl: mergedConfig.DATAVERSE_ENVIRONMENT_URL, }, logging: { level: mergedConfig.LOG_LEVEL || 'info', }, rateLimit: { requestsPerMinute: parseInt(mergedConfig.RATE_LIMIT_REQUESTS_PER_MINUTE || '60'), }, configSource, }; configLoaded = true; console.error('[Setup] Configuration loaded successfully'); console.error(`[Setup] Authentication mode: ${usePersonalAuth ? 'Personal account' : 'Application credentials'}`); console.error(`[Setup] Dataverse URL: ${config.dataverse.environmentUrl}`); console.error(`[Setup] Log Level: ${config.logging.level}`); console.error(`[Setup] Configuration source: ${configSource}`); } /** * Get the current configuration */ export function getConfig() { if (!config) { throw new Error('Configuration not initialized. Call initializeConfig() first.'); } return config; }