andrew-dataverse-mcp
Version:
A Model Context Protocol server for Microsoft Dataverse with comprehensive CRUD operations
122 lines (121 loc) • 5.28 kB
JavaScript
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;
}