UNPKG

mcp-crawl4ai-ts

Version:

TypeScript MCP server for Crawl4AI - web crawling and content extraction

269 lines โ€ข 10.2 kB
import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; async function testMCPServer() { console.log('๐Ÿงช Testing Crawl4AI MCP Server...\n'); const transport = new StdioClientTransport({ command: 'tsx', args: ['src/index.ts'], }); const client = new Client({ name: 'test-client', version: '1.0.0', }, { capabilities: {}, }); let passedTests = 0; let failedTests = 0; async function runTest(name, testFn) { process.stdout.write(`Testing ${name}... `); try { const result = await testFn(); if (result) { console.log('โœ… PASSED'); passedTests++; } else { console.log('โŒ FAILED'); failedTests++; } return result; } catch (error) { console.log(`โŒ ERROR: ${error}`); failedTests++; return false; } } try { await client.connect(transport); console.log('โœ… Connected to MCP server\n'); // List available tools const tools = await client.listTools(); console.log(`๐Ÿ“‹ Found ${tools.tools.length} tools\n`); // Test 1: crawl_page await runTest('crawl_page', async () => { const result = await client.callTool({ name: 'crawl_page', arguments: { url: 'https://www.google.com', remove_images: true, bypass_cache: true, }, }); return result.content[0].type === 'text' && result.content[0].text.length > 100; }); // Test 2: capture_screenshot await runTest('capture_screenshot', async () => { const result = await client.callTool({ name: 'capture_screenshot', arguments: { url: 'https://www.google.com', full_page: true, }, }); return result.content[0].type === 'image'; }); // Test 3: generate_pdf await runTest('generate_pdf', async () => { const result = await client.callTool({ name: 'generate_pdf', arguments: { url: 'https://www.google.com', }, }); return result.content[0].type === 'text' && result.content[0].text.includes('PDF generated'); }); // Test 4: execute_js await runTest('execute_js', async () => { const result = await client.callTool({ name: 'execute_js', arguments: { url: 'https://www.google.com', js_code: 'document.title', wait_after_js: 500, }, }); return (result.content[0].type === 'text' && result.content[0].text.includes('JavaScript executed')); }); // Test 5: batch_crawl await runTest('batch_crawl', async () => { const result = await client.callTool({ name: 'batch_crawl', arguments: { urls: ['https://www.google.com', 'https://www.github.com'], max_concurrent: 2, }, }); return result.content[0].type === 'text' && result.content[0].text.includes('Processed 2 URLs'); }); // Test 6: smart_crawl await runTest('smart_crawl', async () => { const result = await client.callTool({ name: 'smart_crawl', arguments: { url: 'https://www.google.com', max_depth: 1, }, }); return (result.content[0].type === 'text' && result.content[0].text.includes('Smart crawl detected')); }); // Test 7: get_html await runTest('get_html', async () => { const result = await client.callTool({ name: 'get_html', arguments: { url: 'https://www.google.com', }, }); return (result.content[0].type === 'text' && (result.content[0].text.includes('<html') || result.content[0].text.includes('<!DOCTYPE'))); }); // Test 8: extract_links await runTest('extract_links', async () => { const result = await client.callTool({ name: 'extract_links', arguments: { url: 'https://www.google.com', categorize: true, }, }); return result.content[0].type === 'text' && result.content[0].text.includes('Link analysis'); }); // Test 9: crawl_recursive await runTest('crawl_recursive', async () => { const result = await client.callTool({ name: 'crawl_recursive', arguments: { url: 'https://www.google.com', max_depth: 1, max_pages: 5, }, }); return (result.content[0].type === 'text' && result.content[0].text.includes('Recursive crawl completed')); }); // Test 10: parse_sitemap await runTest('parse_sitemap', async () => { // Test with a known sitemap const result = await client.callTool({ name: 'parse_sitemap', arguments: { url: 'https://www.sitemaps.org/sitemap.xml', }, }); return (result.content[0].type === 'text' && (result.content[0].text.includes('Sitemap parsed') || result.content[0].text.includes('Error'))); // Allow error as sitemap might not exist }); // Test 11: crawl_with_config (basic) await runTest('crawl_with_config (basic)', async () => { const result = await client.callTool({ name: 'crawl_with_config', arguments: { url: 'https://www.google.com', cache_mode: 'BYPASS', excluded_tags: ['script', 'style'], word_count_threshold: 50, }, }); return result.content[0].type === 'text'; }); // Test 12: crawl_with_config (advanced) await runTest('crawl_with_config (advanced)', async () => { const result = await client.callTool({ name: 'crawl_with_config', arguments: { url: 'https://www.google.com', viewport_width: 1920, viewport_height: 1080, user_agent: 'Test Bot 1.0', js_code: 'console.log("test")', wait_for: '.content', screenshot: true, cache_mode: 'DISABLED', }, }); return result.content[0].type === 'text'; }); // Test 13: create_session await runTest('create_session', async () => { const result = await client.callTool({ name: 'create_session', arguments: { session_id: 'test-session-' + Date.now(), browser_type: 'chromium', }, }); return (result.content[0].type === 'text' && result.content[0].text.includes('Session created successfully')); }); // Test 14: list_sessions await runTest('list_sessions', async () => { const result = await client.callTool({ name: 'list_sessions', arguments: {}, }); return result.content[0].type === 'text'; }); // Test 15: clear_session (will fail if no session exists, which is ok) await runTest('clear_session', async () => { try { await client.callTool({ name: 'clear_session', arguments: { session_id: 'test-session-nonexistent', }, }); return true; // Success or error, both are valid } catch { return true; // Expected to possibly fail } }); // Test error handling console.log('\n๐Ÿ” Testing error handling...\n'); await runTest('invalid URL handling', async () => { const result = await client.callTool({ name: 'crawl_page', arguments: { url: 'not-a-valid-url', }, }); return result.content[0].text.includes('Error'); }); await runTest('unknown tool handling', async () => { try { await client.callTool({ name: 'non_existent_tool', arguments: {}, }); return false; } catch { return true; // Expected to fail } }); // Summary console.log('\n' + '='.repeat(50)); console.log(`\n๐Ÿ“Š Test Summary:`); console.log(` โœ… Passed: ${passedTests}`); console.log(` โŒ Failed: ${failedTests}`); console.log(` ๐Ÿ“ˆ Success Rate: ${((passedTests / (passedTests + failedTests)) * 100).toFixed(1)}%`); if (failedTests === 0) { console.log('\n๐ŸŽ‰ All tests passed! The MCP server is working correctly.'); } else { console.log('\nโš ๏ธ Some tests failed. Please check the implementation.'); } } catch (error) { console.error('โŒ Test suite failed:', error); } finally { await client.close(); process.exit(failedTests > 0 ? 1 : 0); } } // Run tests testMCPServer().catch(console.error); //# sourceMappingURL=test.js.map