#!/usr/bin/env node
/**
* Test script to validate configuration wizard output
*/
import fs from 'fs';
import path from 'path';
function parseEnvFile(filePath) {
if (!fs.existsSync(filePath)) {
return null;
}
const content = fs.readFileSync(filePath, 'utf-8');
const env = {};
content.split('\n').forEach(line => {
line = line.trim();
if (line && !line.startsWith('#')) {
const [key, ...valueParts] = line.split('=');
if (key && valueParts.length > 0) {
let value = valueParts.join('=');
// Remove quotes if present
if ((value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'"))) {
value = value.slice(1, -1);
}
env[key.trim()] = value;
}
}
});
return env;
}
function validateConfiguration(env) {
const errors = [];
const warnings = [];
// Required fields
if (!env.NDB_BASE_URL) {
errors.push('Missing required field: NDB_BASE_URL');
} else if (!env.NDB_BASE_URL.startsWith('http')) {
warnings.push('NDB_BASE_URL should start with http:// or https://');
}
// Authentication
if (!env.NDB_TOKEN && (!env.NDB_USERNAME || !env.NDB_PASSWORD)) {
errors.push('Missing authentication: Either NDB_TOKEN or (NDB_USERNAME + NDB_PASSWORD) required');
}
// Custom instructions validation
if (env.NDB_CUSTOM_INSTRUCTIONS) {
const instructions = env.NDB_CUSTOM_INSTRUCTIONS.split('|');
if (instructions.length > 10) {
warnings.push(`High number of custom instructions (${instructions.length}). Consider consolidating.`);
}
instructions.forEach((instr, i) => {
if (instr.trim().length < 10) {
warnings.push(`Custom instruction ${i + 1} is very short: "${instr.trim()}"`);
}
});
}
// Boolean validation
const booleanFields = ['NDB_VERIFY_SSL', 'NDB_CONFIRM_CHANGES', 'NDB_PAUSE_ON_ERROR'];
booleanFields.forEach(field => {
if (env[field] && !['true', 'false'].includes(env[field].toLowerCase())) {
warnings.push(`${field} should be "true" or "false", got "${env[field]}"`);
}
});
// Response style validation
if (env.NDB_RESPONSE_STYLE) {
const validStyles = ['concise', 'verbose', 'structured'];
if (!validStyles.includes(env.NDB_RESPONSE_STYLE.toLowerCase())) {
errors.push(`Invalid NDB_RESPONSE_STYLE: "${env.NDB_RESPONSE_STYLE}". Must be one of: ${validStyles.join(', ')}`);
}
}
return { errors, warnings };
}
function displayConfigurationSummary(env) {
console.log('๐ Configuration Summary');
console.log('========================');
// Connection settings
console.log('\n๐ Connection Settings:');
console.log(` Base URL: ${env.NDB_BASE_URL || 'NOT SET'}`);
console.log(` SSL Verification: ${env.NDB_VERIFY_SSL || 'true'}`);
console.log(` Authentication: ${env.NDB_TOKEN ? 'Token-based' : env.NDB_USERNAME ? 'Basic (username/password)' : 'NOT CONFIGURED'}`);
// Custom instructions
console.log('\n๐ Custom Instructions:');
if (env.NDB_CUSTOM_INSTRUCTIONS) {
const instructions = env.NDB_CUSTOM_INSTRUCTIONS.split('|');
console.log(` Total: ${instructions.length} instructions`);
instructions.forEach((instr, i) => {
console.log(` ${i + 1}. ${instr.trim()}`);
});
} else {
console.log(' None configured');
}
// Behavior settings
console.log('\nโ๏ธ Behavior Settings:');
console.log(` Confirm High-Impact Changes: ${env.NDB_CONFIRM_CHANGES || 'false'}`);
console.log(` Pause on Errors: ${env.NDB_PAUSE_ON_ERROR || 'false'}`);
console.log(` Response Style: ${env.NDB_RESPONSE_STYLE || 'concise'}`);
}
async function main() {
console.log('๐งช Testing NDB MCP Server Configuration');
console.log('=======================================\n');
// Check for .env files
const envFiles = ['.env', '.env.production', '.env.development', '.env.test'];
const foundEnvFiles = envFiles.filter(file => fs.existsSync(path.resolve(process.cwd(), file)));
if (foundEnvFiles.length === 0) {
console.log('โ No .env files found. Run "npm run configure" to create one.');
return;
}
console.log(`๐ Found environment files: ${foundEnvFiles.join(', ')}\n`);
// Test each env file
for (const envFile of foundEnvFiles) {
console.log(`๐ Testing ${envFile}:`);
console.log(''.padEnd(50, '-'));
const env = parseEnvFile(path.resolve(process.cwd(), envFile));
if (!env) {
console.log(`โ Could not parse ${envFile}`);
continue;
}
const { errors, warnings } = validateConfiguration(env);
if (errors.length === 0) {
console.log('โ
Configuration is valid!');
} else {
console.log('โ Configuration has errors:');
errors.forEach(error => console.log(` โข ${error}`));
}
if (warnings.length > 0) {
console.log('โ ๏ธ Warnings:');
warnings.forEach(warning => console.log(` โข ${warning}`));
}
displayConfigurationSummary(env);
console.log('\n');
}
// Test custom instructions loading
console.log('๐งช Testing Custom Instructions Loading:');
console.log(''.padEnd(50, '-'));
try {
// Dynamically import the custom instructions module
const { loadCustomInstructions, generateSystemPrompt } = await import('../dist/custom_instructions.js');
// Temporarily set environment variables for testing
const testEnv = parseEnvFile(path.resolve(process.cwd(), foundEnvFiles[0]));
Object.keys(testEnv).forEach(key => {
process.env[key] = testEnv[key];
});
const config = loadCustomInstructions();
console.log('โ
Custom instructions loaded successfully:');
console.log(' Instructions:', config.instructions.length > 0 ? config.instructions : 'None');
console.log(' Confirm Changes:', config.confirmChanges);
console.log(' Pause on Error:', config.pauseOnError);
console.log(' Response Style:', config.responseStyle);
const systemPrompt = generateSystemPrompt(config);
console.log('\n๐ Generated System Prompt Preview:');
console.log(''.padEnd(50, '-'));
console.log(systemPrompt.substring(0, 300) + (systemPrompt.length > 300 ? '...' : ''));
} catch (error) {
console.log('โ Error testing custom instructions:');
console.log(` ${error.message}`);
console.log(' Make sure to run "npm run build" first.');
}
console.log('\n๐ฏ Next Steps:');
console.log('1. If you see errors, run "npm run configure" to fix them');
console.log('2. Test NDB connection: npm run test:connection');
console.log('3. Test MCP functionality: npm run test:custom-instructions');
console.log('4. Configure Claude Desktop: npm run configure:claude');
}
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch(console.error);
}