#!/usr/bin/env node
/**
* SQLx MCP 测试脚本
* 用于启动数据库和测试 MCP 服务器连接
*/
const { execSync, spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
// 颜色输出
const colors = {
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
reset: '\x1b[0m',
bold: '\x1b[1m'
};
function log(message, color = colors.reset) {
console.log(`${color}${message}${colors.reset}`);
}
function checkDockerInstalled() {
try {
execSync('docker --version', { stdio: 'pipe' });
execSync('docker-compose --version', { stdio: 'pipe' });
return true;
} catch (error) {
return false;
}
}
function startDatabases() {
log('🚀 启动数据库容器...', colors.blue);
try {
// 停止并移除旧容器
try {
execSync('docker-compose down', { stdio: 'pipe' });
} catch (e) {
// 忽略错误,可能是第一次运行
}
// 启动数据库
execSync('docker-compose up -d', { stdio: 'inherit' });
log('✅ 数据库容器启动成功!', colors.green);
log('📊 PostgreSQL: localhost:5432', colors.yellow);
log('📊 MySQL: localhost:3306', colors.yellow);
return true;
} catch (error) {
log(`❌ 启动数据库失败: ${error.message}`, colors.red);
return false;
}
}
function waitForDatabases() {
log('⏳ 等待数据库启动...', colors.yellow);
const maxAttempts = 30;
let attempts = 0;
while (attempts < maxAttempts) {
try {
// 检查 PostgreSQL
execSync('docker exec sqlx-mcp-postgres pg_isready -U testuser -d testdb', { stdio: 'pipe' });
// 检查 MySQL
execSync('docker exec sqlx-mcp-mysql mysqladmin ping -h localhost -u testuser -ptestpass', { stdio: 'pipe' });
log('✅ 数据库就绪!', colors.green);
return true;
} catch (error) {
attempts++;
process.stdout.write('.');
if (attempts >= maxAttempts) {
log('\n❌ 数据库启动超时', colors.red);
return false;
}
// 等待1秒
require('child_process').execSync('timeout 1 2>nul || sleep 1', { stdio: 'pipe' });
}
}
return false;
}
function testMCPServer(dbType, databaseUrl) {
log(`🔧 测试 ${dbType} MCP 服务器...`, colors.blue);
return new Promise((resolve) => {
const child = spawn('npx', ['@sqlx-mcp/sqlx-mcp'], {
env: { ...process.env, DATABASE_URL: databaseUrl },
stdio: ['pipe', 'pipe', 'pipe']
});
let output = '';
let hasStarted = false;
child.stdout.on('data', (data) => {
output += data.toString();
process.stdout.write(data);
});
child.stderr.on('data', (data) => {
const str = data.toString();
output += str;
// 检查是否成功启动
if (str.includes('MCP server running') || str.includes('Server initialized')) {
hasStarted = true;
log(`✅ ${dbType} MCP 服务器启动成功!`, colors.green);
child.kill();
resolve(true);
} else if (str.includes('Error') || str.includes('Failed')) {
log(`❌ ${dbType} MCP 服务器启动失败`, colors.red);
child.kill();
resolve(false);
}
});
// 5秒超时
setTimeout(() => {
if (!hasStarted) {
log(`⏰ ${dbType} MCP 服务器测试超时`, colors.yellow);
child.kill();
resolve(false);
}
}, 5000);
});
}
function showUsageInstructions() {
log('\\n📋 使用说明:', colors.bold);
log('\\n1. Claude Desktop 配置:');
log(' 将 claude-desktop-config.json 中的内容复制到你的 Claude Desktop 配置文件中');
log('\\n2. 手动测试 MCP 服务器:');
log(' # PostgreSQL:', colors.blue);
log(' DATABASE_URL="postgresql://testuser:testpass@localhost:5432/testdb" npx @sqlx-mcp/sqlx-mcp');
log('\\n # MySQL:', colors.blue);
log(' DATABASE_URL="mysql://testuser:testpass@localhost:3306/testdb" npx @sqlx-mcp/sqlx-mcp');
log('\\n3. 停止数据库:');
log(' docker-compose down', colors.blue);
log('\\n4. 查看数据库日志:');
log(' docker-compose logs postgres', colors.blue);
log(' docker-compose logs mysql', colors.blue);
}
async function main() {
log('🧪 SQLx MCP 测试环境设置', colors.bold);
log('=' .repeat(50), colors.blue);
// 检查 Docker
if (!checkDockerInstalled()) {
log('❌ Docker 或 Docker Compose 未安装', colors.red);
log('请先安装 Docker Desktop: https://www.docker.com/products/docker-desktop');
process.exit(1);
}
// 启动数据库
if (!startDatabases()) {
process.exit(1);
}
// 等待数据库就绪
if (!waitForDatabases()) {
process.exit(1);
}
// 测试 MCP 服务器
log('\\n🔧 测试 MCP 服务器连接...', colors.blue);
const postgresResult = await testMCPServer(
'PostgreSQL',
'postgresql://testuser:testpass@localhost:5432/testdb'
);
const mysqlResult = await testMCPServer(
'MySQL',
'mysql://testuser:testpass@localhost:3306/testdb'
);
// 显示结果
log('\\n📊 测试结果:', colors.bold);
log(`PostgreSQL MCP: ${postgresResult ? '✅ 成功' : '❌ 失败'}`, postgresResult ? colors.green : colors.red);
log(`MySQL MCP: ${mysqlResult ? '✅ 成功' : '❌ 失败'}`, mysqlResult ? colors.green : colors.red);
showUsageInstructions();
}
if (require.main === module) {
main().catch(console.error);
}