MCP Server
by mokemoke0821
Verified
- MCP
- mcp-server
/**
* MCPサーバー統合テスト (test-mcp-server.js)
* MCPサーバー第3フェーズ改善のテスト用スクリプト
*/
// 必要なモジュールをインポート
const fs = require('fs').promises;
const path = require('path');
const { execFile } = require('child_process');
const util = require('util');
const execFilePromise = util.promisify(execFile);
// 非同期関数でテストを実行
async function runTests() {
console.log('========================================');
console.log('MCPサーバー統合テスト 開始');
console.log('========================================\n');
const testResults = {
searchGlob: false,
listFiles: false,
japaneseSearch: false,
powershellCommand: false,
specialCharsCommand: false,
serverStatus: false
};
try {
// テスト1: searchGlob関数テスト
console.log('テスト1: searchGlob関数テスト');
try {
const searchResult = await testSearchGlob('.', '*.js');
testResults.searchGlob = searchResult.success;
console.log(`結果: ${JSON.stringify(searchResult.files)}`);
console.log(`テスト結果: ${testResults.searchGlob ? '成功' : '失敗'}`);
} catch (err) {
console.error(`searchGlobテストエラー: ${err.message}`);
}
console.log('----------------------------------------\n');
// テスト2: listFiles関数テスト
console.log('テスト2: listFiles関数テスト');
try {
const listResult = await testListFiles('.');
testResults.listFiles = listResult.success;
console.log(`ディレクトリ: ${listResult.directory}`);
console.log(`ファイル数: ${listResult.filesCount}`);
console.log(`ディレクトリ数: ${listResult.directoriesCount}`);
console.log(`テスト結果: ${testResults.listFiles ? '成功' : '失敗'}`);
} catch (err) {
console.error(`listFilesテストエラー: ${err.message}`);
}
console.log('----------------------------------------\n');
// テスト3: 日本語ファイル名検索テスト
console.log('テスト3: 日本語ファイル名検索テスト');
try {
// 日本語テストファイルを作成
await createJapaneseTestFile();
const searchResult = await testSearchGlob('.', '日本語*.txt');
testResults.japaneseSearch = searchResult.success && searchResult.files.some(file => file.includes('日本語テスト'));
console.log(`検索結果: ${JSON.stringify(searchResult.files)}`);
console.log(`テスト結果: ${testResults.japaneseSearch ? '成功' : '失敗'}`);
} catch (err) {
console.error(`日本語ファイル検索テストエラー: ${err.message}`);
}
console.log('----------------------------------------\n');
// テスト4: PowerShellコマンド実行テスト
console.log('テスト4: PowerShellコマンド実行テスト');
try {
const cmdResult = await testExecuteCommand('powershell', 'Write-Output "こんにちは、世界!"');
testResults.powershellCommand = cmdResult.success && cmdResult.stdout.includes('こんにちは');
console.log(`出力: ${cmdResult.stdout}`);
console.log(`テスト結果: ${testResults.powershellCommand ? '成功' : '失敗'}`);
} catch (err) {
console.error(`PowerShellコマンドテストエラー: ${err.message}`);
}
console.log('----------------------------------------\n');
// テスト5: 特殊文字を含むコマンド実行テスト
console.log('テスト5: 特殊文字を含むコマンド実行テスト');
try {
const cmdResult = await testExecuteCommand('powershell', 'Get-Process | Select-Object -First 3');
testResults.specialCharsCommand = cmdResult.success && cmdResult.stdout.length > 0;
console.log(`出力: ${cmdResult.stdout.substring(0, 200)}...`); // 出力が長い場合は省略
console.log(`テスト結果: ${testResults.specialCharsCommand ? '成功' : '失敗'}`);
} catch (err) {
console.error(`特殊文字コマンドテストエラー: ${err.message}`);
}
console.log('----------------------------------------\n');
// テスト6: サーバーステータス確認テスト
console.log('テスト6: サーバーステータス確認テスト');
try {
const statusResult = await checkServerStatus();
testResults.serverStatus = statusResult.success;
console.log(`サーバーステータス: ${JSON.stringify(statusResult.status)}`);
console.log(`テスト結果: ${testResults.serverStatus ? '成功' : '失敗'}`);
} catch (err) {
console.error(`サーバーステータステストエラー: ${err.message}`);
}
console.log('----------------------------------------\n');
// テスト結果の集計
const totalTests = Object.keys(testResults).length;
const passedTests = Object.values(testResults).filter(result => result).length;
console.log('========================================');
console.log('テスト結果サマリー');
console.log('========================================');
console.log(`合計テスト数: ${totalTests}`);
console.log(`成功したテスト: ${passedTests}`);
console.log(`失敗したテスト: ${totalTests - passedTests}`);
console.log(`成功率: ${Math.round((passedTests / totalTests) * 100)}%`);
if (passedTests === totalTests) {
console.log('\n✓ 全てのテストが成功しました!');
} else {
console.log('\n✗ 一部のテストが失敗しました。');
// 失敗したテストを表示
Object.entries(testResults).forEach(([test, result]) => {
if (!result) {
console.log(` - ${test}: 失敗`);
}
});
}
// テスト後の後片付け
await cleanupTestFiles();
} catch (error) {
console.error('テスト実行中にエラーが発生しました:', error);
}
}
// searchGlob関数をテストする関数
async function testSearchGlob(basePath, pattern) {
try {
// MCPサーバーがglobalスコープに公開している関数を使用
// 実際の環境では以下のようにサーバーのAPIを呼び出すか
// または適切な方法でアクセスします
const files = global.searchGlob ? await global.searchGlob(basePath, pattern) :
await mockSearchGlob(basePath, pattern);
return {
success: Array.isArray(files),
files: Array.isArray(files) ? files : [],
error: null
};
} catch (err) {
return {
success: false,
files: [],
error: err.message
};
}
}
// listFiles関数をテストする関数
async function testListFiles(dirPath) {
try {
// MCPサーバーがglobalスコープに公開している関数を使用
const result = global.listFiles ? await global.listFiles(dirPath) :
await mockListFiles(dirPath);
return {
success: !!result && Array.isArray(result.files) && Array.isArray(result.directories),
directory: result ? result.directory : null,
filesCount: result && result.files ? result.files.length : 0,
directoriesCount: result && result.directories ? result.directories.length : 0,
error: null
};
} catch (err) {
return {
success: false,
directory: null,
filesCount: 0,
directoriesCount: 0,
error: err.message
};
}
}
// executeCommand関数をテストする関数
async function testExecuteCommand(shell, command) {
try {
// MCPサーバーがglobalスコープに公開している関数を使用
const result = global.executeCommand ?
await global.executeCommand({ shell, command }) :
await mockExecuteCommand(shell, command);
return {
success: result && result.exitCode === 0,
stdout: result ? result.stdout : '',
stderr: result ? result.stderr : '',
exitCode: result ? result.exitCode : 1,
error: null
};
} catch (err) {
return {
success: false,
stdout: '',
stderr: err.message,
exitCode: 1,
error: err.message
};
}
}
// サーバーステータスを確認する関数
async function checkServerStatus() {
try {
// 実際の環境ではHTTPリクエストなどでサーバーの/healthエンドポイントを呼び出す
// ここではモック実装
const status = await mockServerStatus();
return {
success: status && status.status === 'ok',
status,
error: null
};
} catch (err) {
return {
success: false,
status: null,
error: err.message
};
}
}
// 日本語テストファイルを作成する関数
async function createJapaneseTestFile() {
try {
const fileName = '日本語テスト.txt';
const content = 'これは日本語のテストファイルです。\nThis is a Japanese test file.';
await fs.writeFile(fileName, content, 'utf8');
console.log(`テストファイル "${fileName}" を作成しました。`);
return true;
} catch (err) {
console.error(`テストファイル作成エラー: ${err.message}`);
return false;
}
}
// テストファイルの後片付けをする関数
async function cleanupTestFiles() {
try {
const fileName = '日本語テスト.txt';
try {
await fs.access(fileName);
await fs.unlink(fileName);
console.log(`テストファイル "${fileName}" を削除しました。`);
} catch (err) {
// ファイルが存在しない場合は無視
}
return true;
} catch (err) {
console.error(`テストファイル後片付けエラー: ${err.message}`);
return false;
}
}
// モック関数(実際のMCPサーバー関数が利用できない場合に使用)
async function mockSearchGlob(basePath, pattern) {
// テスト用のダミー実装
const fs = require('fs').promises;
const path = require('path');
try {
const files = await fs.readdir(basePath);
return files.filter(file => {
// 単純なワイルドカードマッチング
if (pattern === '*.*') return true;
if (pattern === '*.js') return file.endsWith('.js');
if (pattern.startsWith('日本語')) return file.startsWith('日本語');
return false;
}).map(file => path.join(basePath, file));
} catch (err) {
console.error(`mockSearchGlob エラー: ${err.message}`);
return [];
}
}
async function mockListFiles(dirPath) {
// テスト用のダミー実装
const fs = require('fs').promises;
const path = require('path');
try {
const files = await fs.readdir(dirPath);
const result = {
directory: dirPath,
files: [],
directories: []
};
for (const file of files) {
const filePath = path.join(dirPath, file);
try {
const stats = await fs.stat(filePath);
if (stats.isDirectory()) {
result.directories.push({
name: file,
path: filePath
});
} else {
result.files.push({
name: file,
path: filePath,
size: stats.size
});
}
} catch (err) {
// ファイルアクセスエラーは無視
}
}
return result;
} catch (err) {
console.error(`mockListFiles エラー: ${err.message}`);
throw err;
}
}
async function mockExecuteCommand(shell, command) {
// テスト用のダミー実装
try {
let stdout = '';
let exitCode = 0;
if (shell === 'powershell') {
if (command.includes('こんにちは')) {
stdout = 'こんにちは、世界!';
} else if (command.includes('Get-Process')) {
stdout = 'Name CPU\n---- ---\nSvcHost 1.2\nChrome 3.4';
} else {
stdout = 'Dummy PowerShell output';
}
} else if (shell === 'cmd') {
stdout = 'Dummy CMD output';
} else if (shell === 'gitbash') {
stdout = 'Dummy GitBash output';
}
return {
stdout,
stderr: '',
exitCode
};
} catch (err) {
console.error(`mockExecuteCommand エラー: ${err.message}`);
return {
stdout: '',
stderr: err.message,
exitCode: 1
};
}
}
async function mockServerStatus() {
// テスト用のダミー実装
return {
status: 'ok',
version: '1.0.0',
uptime: 12345
};
}
// テストを実行
runTests();