Skip to main content
Glama
test-sapmv45a-large-program.jsโ€ข14.6 kB
#!/usr/bin/env node /** * Test script for SAPMV45A - large SAP program with many includes * Tests individual operations: program reading, includes list, enhancements */ const { spawn } = require('child_process'); const path = require('path'); const PROGRAM_NAME = 'SAPMV45A'; // Test scenarios for SAPMV45A const testScenarios = [ { name: "1. Read program source code", tool: "get_program", args: { program_name: PROGRAM_NAME }, timeout: 30000, // 30 seconds description: "Retrieve the main program source code" }, { name: "2. Get includes list (without recursion)", tool: "get_includes_list", args: { object_name: PROGRAM_NAME, object_type: "program", recursive: false // Non-recursive to be faster }, timeout: 60000, // 1 minute description: "Get direct includes only (non-recursive)" }, { name: "3. Get includes list (with recursion - risky)", tool: "get_includes_list", args: { object_name: PROGRAM_NAME, object_type: "program", recursive: true // Full recursive - might timeout }, timeout: 120000, // 2 minutes description: "Get all includes recursively (might timeout due to size)" }, { name: "4. Get enhancements (main program only)", tool: "get_enhancements", args: { object_name: PROGRAM_NAME, include_nested: false // Only main program }, timeout: 45000, // 45 seconds description: "Get enhancements from main program only" }, { name: "5. Get enhancements (limited nested - 5 includes)", tool: "get_enhancements", args: { object_name: PROGRAM_NAME, include_nested: true, max_includes: 5, // Very limited timeout_per_include: 10000, // 10 seconds per include total_timeout: 90000 // 1.5 minutes total }, timeout: 120000, // 2 minutes test timeout description: "Get enhancements with very limited nested search" }, { name: "6. Get enhancements (medium nested - 20 includes)", tool: "get_enhancements", args: { object_name: PROGRAM_NAME, include_nested: true, max_includes: 20, // Medium limit timeout_per_include: 15000, // 15 seconds per include total_timeout: 180000 // 3 minutes total }, timeout: 240000, // 4 minutes test timeout description: "Get enhancements with medium nested search" } ]; async function runSingleTest(scenario) { console.log(`\n๐Ÿงช ${scenario.name}`); console.log(`๐Ÿ“‹ ${scenario.description}`); console.log(`๐Ÿ”ง Tool: ${scenario.tool}`); console.log(`๐Ÿ“ Args:`, JSON.stringify(scenario.args, null, 2)); return new Promise((resolve) => { const startTime = Date.now(); // Prepare the MCP request const mcpRequest = { jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: scenario.tool, arguments: scenario.args } }; // Path to the compiled JavaScript file const scriptPath = path.join(__dirname, '..', 'dist', 'index.js'); // Spawn the MCP server const child = spawn('node', [scriptPath], { stdio: ['pipe', 'pipe', 'pipe'] }); let stdout = ''; let stderr = ''; let completed = false; child.stdout.on('data', (data) => { stdout += data.toString(); }); child.stderr.on('data', (data) => { stderr += data.toString(); }); child.on('close', (code) => { if (completed) return; // Avoid double resolution completed = true; const endTime = Date.now(); const duration = endTime - startTime; console.log(`โฑ๏ธ Completed in ${duration}ms (${(duration/1000).toFixed(1)}s)`); if (code === 0) { try { // Parse the JSON response const lines = stdout.trim().split('\n'); const responseLine = lines.find(line => { try { const parsed = JSON.parse(line); return parsed.result; } catch { return false; } }); if (responseLine) { const response = JSON.parse(responseLine); if (response.result && response.result.content) { const resultText = response.result.content[0].text; // Try to parse as JSON for structured results let parsedResult; try { parsedResult = JSON.parse(resultText); } catch { parsedResult = { raw: resultText }; } let summary = ''; if (scenario.tool === 'get_program') { const lines = resultText.split('\n').length; summary = `๐Ÿ“„ Program has ${lines} lines`; } else if (scenario.tool === 'get_includes_list') { if (typeof parsedResult === 'object' && parsedResult.includes) { summary = `๐Ÿ“ Found ${parsedResult.includes.length} includes`; } else { const includesMatch = resultText.match(/Found (\d+) includes/); summary = includesMatch ? `๐Ÿ“ Found ${includesMatch[1]} includes` : '๐Ÿ“ Includes listed'; } } else if (scenario.tool === 'get_enhancements') { if (typeof parsedResult === 'object') { const total = parsedResult.total_enhancements_found || 0; const objects = parsedResult.total_objects_analyzed || 1; const partial = parsedResult.partial_result ? ' (partial)' : ''; summary = `๐Ÿ”ง Found ${total} enhancements in ${objects} objects${partial}`; } else { summary = '๐Ÿ”ง Enhancements retrieved'; } } console.log(`โœ… Success! ${summary}`); resolve({ success: true, duration: duration, summary: summary, dataSize: resultText.length }); } else { console.log(`โŒ No content in response`); resolve({ success: false, duration: duration, error: 'No content in response' }); } } else { console.log(`โŒ No valid JSON response found`); console.log(`๐Ÿ“ค First 200 chars of STDOUT:`, stdout.slice(0, 200)); resolve({ success: false, duration: duration, error: 'No valid JSON response' }); } } catch (error) { console.log(`โŒ Failed to parse response:`, error.message); console.log(`๐Ÿ“ค First 200 chars of STDOUT:`, stdout.slice(0, 200)); resolve({ success: false, duration: duration, error: error.message }); } } else { console.log(`โŒ Process exited with code ${code}`); if (stderr) { console.log(`๐Ÿ“ค STDERR:`, stderr.slice(0, 300)); } resolve({ success: false, duration: duration, error: `Process exited with code ${code}` }); } }); child.on('error', (error) => { if (completed) return; completed = true; const endTime = Date.now(); const duration = endTime - startTime; console.log(`โŒ Process error:`, error.message); resolve({ success: false, duration: duration, error: error.message }); }); // Send the request child.stdin.write(JSON.stringify(mcpRequest) + '\n'); child.stdin.end(); // Set scenario-specific timeout setTimeout(() => { if (!completed && !child.killed) { completed = true; console.log(`โฐ Test timed out after ${scenario.timeout}ms, killing process`); child.kill('SIGTERM'); setTimeout(() => { if (!child.killed) { console.log(`๐Ÿ’€ Force killing process with SIGKILL`); child.kill('SIGKILL'); } }, 5000); resolve({ success: false, duration: scenario.timeout, error: `Test timeout (${scenario.timeout}ms)` }); } }, scenario.timeout); }); } async function main() { console.log('๐Ÿš€ Starting SAPMV45A Large Program Tests'); console.log('=' .repeat(70)); console.log(`๐ŸŽฏ Target Program: ${PROGRAM_NAME}`); console.log(`๐Ÿ“Š Total Tests: ${testScenarios.length}`); console.log(''); // Build the project first console.log('๐Ÿ”จ Building project...'); const buildResult = await new Promise((resolve) => { const isWindows = process.platform === 'win32'; const npmCommand = isWindows ? 'npm.cmd' : 'npm'; const buildProcess = spawn(npmCommand, ['run', 'build'], { cwd: path.join(__dirname, '..'), stdio: 'inherit', shell: isWindows }); buildProcess.on('close', (code) => { resolve(code === 0); }); }); if (!buildResult) { console.log('โŒ Build failed, aborting tests'); process.exit(1); } console.log('โœ… Build successful\n'); const results = []; // Run each test scenario for (const scenario of testScenarios) { const result = await runSingleTest(scenario); results.push({ scenario: scenario.name, tool: scenario.tool, ...result }); // Wait between tests to let connections close console.log('โณ Waiting 3 seconds before next test...'); await new Promise(resolve => setTimeout(resolve, 3000)); } // Summary console.log('\n๐Ÿ“Š SAPMV45A Test Results Summary'); console.log('=' .repeat(70)); let totalDuration = 0; results.forEach((result, index) => { totalDuration += result.duration; console.log(`\n${index + 1}. ${result.scenario}`); console.log(` Tool: ${result.tool}`); console.log(` Status: ${result.success ? 'โœ… Success' : 'โŒ Failed'}`); console.log(` Duration: ${result.duration}ms (${(result.duration/1000).toFixed(1)}s)`); if (result.success) { if (result.summary) { console.log(` Result: ${result.summary}`); } if (result.dataSize) { console.log(` Data Size: ${result.dataSize} characters`); } } else { console.log(` Error: ${result.error}`); } }); const successCount = results.filter(r => r.success).length; console.log(`\n๐ŸŽฏ Overall Results:`); console.log(` Tests Passed: ${successCount}/${results.length}`); console.log(` Total Duration: ${totalDuration}ms (${(totalDuration/1000).toFixed(1)}s)`); console.log(` Average per Test: ${Math.round(totalDuration/results.length)}ms`); // Specific analysis console.log(`\n๐Ÿ“ˆ Analysis:`); const programTest = results.find(r => r.tool === 'get_program'); if (programTest?.success) { console.log(` โœ… Program source readable (${(programTest.duration/1000).toFixed(1)}s)`); } else { console.log(` โŒ Program source failed`); } const includesTests = results.filter(r => r.tool === 'get_includes_list'); const includesSuccess = includesTests.filter(r => r.success).length; console.log(` ๐Ÿ“ Includes list: ${includesSuccess}/${includesTests.length} successful`); const enhancementTests = results.filter(r => r.tool === 'get_enhancements'); const enhancementSuccess = enhancementTests.filter(r => r.success).length; console.log(` ๐Ÿ”ง Enhancement searches: ${enhancementSuccess}/${enhancementTests.length} successful`); if (successCount === results.length) { console.log(`\n๐ŸŽ‰ All tests passed! SAPMV45A handling is working correctly.`); } else if (successCount > 0) { console.log(`\nโš ๏ธ Partial success. Some operations work, others need optimization.`); } else { console.log(`\n๐Ÿ’ฅ All tests failed. Need to investigate connection/authentication issues.`); } } main().catch(console.error).finally(() => { console.log('\n๐Ÿ Forcing process exit...'); setTimeout(() => { process.exit(0); }, 1000); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fr0ster/mcp-abap-adt'

If you have feedback or need assistance with the MCP directory API, please join our Discord server