Skip to main content
Glama
check-examples.tsโ€ข8 kB
#!/usr/bin/env npx tsx /** * Test diagnostics for all example projects */ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; import { existsSync } from "fs"; import { join, resolve } from "path"; import { fileURLToPath } from "url"; import { dirname } from "path"; import { execSync } from "child_process"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); interface TestResult { language: string; project: string; success: boolean; errors: number; warnings: number; message?: string; } interface LanguageConfig { language: string; testFiles: string[]; lspCommand?: string; checkCommand?: string; // Command to check if dependency is installed installHint?: string; // How to install the dependency preTestCommand?: string; // Command to run before testing (e.g., to initialize project) } const LANGUAGE_CONFIGS: Record<string, LanguageConfig> = { typescript: { language: "typescript", testFiles: ["test-diagnostics.ts"], // TypeScript LSP is bundled with the project, no external dependency }, "rust-project": { language: "rust-analyzer", testFiles: ["src/test_diagnostics.rs"], lspCommand: "rust-analyzer", checkCommand: "rust-analyzer --version", installHint: "Install with: rustup component add rust-analyzer", }, "moonbit-project": { language: "moonbit", testFiles: ["src/test/test_diagnostics.mbt"], lspCommand: "npx @moonbit/moonbit-lsp", checkCommand: "npx @moonbit/moonbit-lsp --version", installHint: "MoonBit LSP is installed via npm", preTestCommand: "moon check --deny-warn || true", // Initialize project before testing // Note: MoonBit LSP might fail with exit code 7 if project is not properly initialized }, "fsharp-project": { language: "fsharp", testFiles: ["Calculator.fs"], lspCommand: "fsautocomplete", checkCommand: "fsautocomplete --version", installHint: "Install with: dotnet tool install -g fsautocomplete", }, }; /** * Check if a command is available in the system */ function isCommandAvailable(command: string): boolean { try { execSync(command, { stdio: "ignore" }); return true; } catch { return false; } } async function testProjectDiagnostics( projectPath: string, config: LanguageConfig, ): Promise<TestResult> { const projectName = dirname(projectPath); console.log(`\n๐Ÿ“ Testing ${config.language} in ${projectName}...`); const transport = new StdioClientTransport({ command: "node", args: [join(__dirname, "../dist/lsmcp.js"), "--preset", config.language], cwd: projectPath, env: { ...process.env, ...(config.lspCommand && { LSP_COMMAND: config.lspCommand }), }, }); const client = new Client( { name: "test-client", version: "1.0.0" }, { capabilities: {} }, ); try { // Run pre-test command if specified if (config.preTestCommand) { try { execSync(config.preTestCommand, { cwd: projectPath, stdio: "ignore" }); } catch (e) { // Ignore errors from pre-test command (might be expected to fail) } } await client.connect(transport); let totalErrors = 0; let totalWarnings = 0; // Test each configured test file for (const testFile of config.testFiles) { const filePath = join(projectPath, testFile); // Skip if test file doesn't exist yet if (!existsSync(filePath)) { console.log(` โš ๏ธ Test file ${testFile} not found, skipping...`); continue; } try { const result = (await client.callTool({ name: "lsp_get_diagnostics", arguments: { root: projectPath, relativePath: testFile, }, })) as { content: Array<{ type: string; text: string }> }; const text = result.content[0].text; console.log(` ๐Ÿ“„ ${testFile}:`); // Parse errors and warnings from result const errorMatch = text.match(/(\d+) errors?/); const warningMatch = text.match(/(\d+) warnings?/); const errors = errorMatch ? parseInt(errorMatch[1]) : 0; const warnings = warningMatch ? parseInt(warningMatch[1]) : 0; totalErrors += errors; totalWarnings += warnings; console.log(` โœ“ Found ${errors} errors, ${warnings} warnings`); // Show first few diagnostics const lines = text.split("\n"); const diagnosticLines = lines .filter( (line: string) => line.startsWith("ERROR:") || line.startsWith("WARNING:"), ) .slice(0, 3); diagnosticLines.forEach((line: string) => { console.log(` ${line}`); }); if ( diagnosticLines.length < lines.filter( (line: string) => line.startsWith("ERROR:") || line.startsWith("WARNING:"), ).length ) { console.log(` ... and more`); } } catch (error) { console.error(` โŒ Error testing ${testFile}: ${error.message}`); throw error; } } await client.close(); return { language: config.language, project: projectName, success: true, errors: totalErrors, warnings: totalWarnings, }; } catch (error) { return { language: config.language, project: projectName, success: false, errors: 0, warnings: 0, message: error.message, }; } } async function main() { console.log("๐Ÿงช Testing diagnostics for all example projects\n"); const results: TestResult[] = []; const skipped: Array<{ project: string; reason: string }> = []; // Test each project for (const [projectDir, config] of Object.entries(LANGUAGE_CONFIGS)) { const projectPath = resolve(__dirname, "../examples", projectDir); if (!existsSync(projectPath)) { console.log(`โš ๏ธ Project ${projectDir} not found, skipping...`); continue; } // Check if dependencies are available if (config.checkCommand && !isCommandAvailable(config.checkCommand)) { console.log(`\n๐Ÿ“ Testing ${config.language} in ${projectDir}...`); console.log( ` โš ๏ธ Dependency not found: ${ config.lspCommand || config.language } LSP server`, ); console.log(` โ„น๏ธ ${config.installHint}`); console.log(` โญ๏ธ Skipping ${config.language} tests\n`); skipped.push({ project: projectDir, reason: `${config.lspCommand || config.language} not installed`, }); continue; } const result = await testProjectDiagnostics(projectPath, config); results.push(result); } // Summary console.log("\n๐Ÿ“Š Summary:"); console.log("โ•".repeat(60)); const successCount = results.filter((r) => r.success).length; console.log(`Total projects: ${results.length + skipped.length}`); console.log(`Tested: ${results.length}`); console.log(`Successful: ${successCount}`); console.log(`Failed: ${results.length - successCount}`); console.log(`Skipped: ${skipped.length}`); if (results.length > 0) { console.log("\nTest results:"); for (const result of results) { const status = result.success ? "โœ…" : "โŒ"; const details = result.success ? `${result.errors} errors, ${result.warnings} warnings` : `Failed: ${result.message}`; console.log(`${status} ${result.language.padEnd(15)} - ${details}`); } } if (skipped.length > 0) { console.log("\nSkipped projects:"); for (const skip of skipped) { console.log(`โญ๏ธ ${skip.project.padEnd(15)} - ${skip.reason}`); } } // Exit with error code if any tests failed (but not if only skipped) if (results.length > 0 && successCount < results.length) { process.exit(1); } } main().catch(console.error);

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/mizchi/typescript-mcp'

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