Skip to main content
Glama

SearXNG MCP Server

by pwilkin
test-searxng-servers.cjs9.24 kB
#!/usr/bin/env node // Script to test SearXNG servers from searx.space using fetchResults from src/index.ts const fs = require('fs'); const path = require('path'); // Simple log object to match the Log type from src/index.ts const log = { debug: (message, data) => console.log(`[DEBUG] ${message}`, data || ''), error: (message, data) => console.error(`[ERROR] ${message}`, data || ''), info: (message, data) => console.log(`[INFO] ${message}`, data || ''), warn: (message, data) => console.warn(`[WARN] ${message}`, data || '') }; // Function to fetch and parse searx.space async function scrapeSearxSpace() { console.log('Fetching SearXNG servers from searx.space...'); try { // Fetch the instances.json data const response = await fetch('https://searx.space/data/instances.json'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); // Extract HTTPS URLs from the instances const urls = Object.keys(data.instances).filter(url => url.startsWith('https://')). map(url => url.endsWith("/") ? url.substring(0, url.length - 1) : url); console.log(`Found ${urls.length} HTTPS SearXNG servers`); return urls; // Return all URLs, no limit } catch (error) { console.error('Error fetching searx.space data:', error); // Return some default servers if scraping fails return [ 'https://baresearch.org', 'https://copp.gg', 'https://darmarit.org/searx', 'https://etsi.me', 'https://fairsuch.net', 'https://find.xenorio.xyz', 'https://kantan.cat', 'https://opnxng.com', 'https://paulgo.io', 'https://searx.tiekoetter.com', 'https://searxng.world' ]; } } // Function to test a single server with both page 1 and page 2 using fetchResults async function testServer(url) { console.log(`Testing ${url}...`); try { // Test page 1 const page1Result = await testSearchQuery(url, 1); console.log(` Page 1: ${page1Result.success ? '✓' : '✗'} (${page1Result.resultCount} results)`); // Test page 2 const page2Result = await testSearchQuery(url, 2); console.log(` Page 2: ${page2Result.success ? '✓' : '✗'} (${page2Result.resultCount} results)`); // Categorize server based on results if (page1Result.success && page2Result.success) { return { status: 'good', url: url, details: { page1: page1Result, page2: page2Result } }; } else if (page1Result.success && !page2Result.success) { return { status: 'ok', url: url, details: { page1: page1Result, page2: page2Result } }; } else { return { status: 'bad', url: url, details: { page1: page1Result, page2: page2Result } }; } } catch (error) { console.error(` Error testing ${url}:`, error.message); return { status: 'bad', url: url, details: { error: error.message } }; } } // Function to test a search query on a specific server and page using fetchResults async function testSearchQuery(baseUrl, page = 1) { try { // Dynamically import fetchResults from src/index.ts const { fetchResults } = await import('../build/index.js'); // Run a test search query const result = await fetchResults( log, 'test', baseUrl, undefined, 'en', page ); // Parse the results if (result.content && result.content[0] && result.content[0].text) { const results = JSON.parse(result.content[0].text); return { success: results.length > 0, resultCount: results.length, results: results }; } else { return { success: false, resultCount: 0, error: 'No content returned' }; } } catch (error) { return { success: false, resultCount: 0, error: error.message || 'Unknown error' }; } } // Function to generate and write the report function generateReport(goodServers, okServers, badServers) { const timestamp = new Date().toISOString(); const report = ` SearXNG Server Test Report ========================== Generated on: ${timestamp} Summary: - Good servers (both page 1 and 2 work): ${goodServers.length} - OK servers (page 1 works, page 2 fails): ${okServers.length} - Bad servers (both pages fail): ${badServers.length} Good Servers (Recommended for reliable searching) ------------------------------------------------ ${goodServers.map(server => `✓ ${server.url}`).join('\n') || 'None'} OK Servers (May work but pagination issues) ------------------------------------------ ${okServers.map(server => `~ ${server.url}`).join('\n') || 'None'} Bad Servers (Not recommended) ---------------------------- ${badServers.map(server => `✗ ${server.url}`).join('\n') || 'None'} Detailed Results ================ Good Servers: ${goodServers.map(server => ` ${server.url}: Page 1: ${server.details.page1.success ? `✓ ${server.details.page1.resultCount} results` : '✗ Failed'}${server.details.page1.error ? ` (${server.details.page1.error})` : ''} Page 2: ${server.details.page2.success ? `✓ ${server.details.page2.resultCount} results` : '✗ Failed'}${server.details.page2.error ? ` (${server.details.page2.error})` : ''}`).join('\n') || 'None'} OK Servers: ${okServers.map(server => ` ${server.url}: Page 1: ${server.details.page1.success ? `✓ ${server.details.page1.resultCount} results` : '✗ Failed'}${server.details.page1.error ? ` (${server.details.page1.error})` : ''} Page 2: ${server.details.page2.success ? `✓ ${server.details.page2.resultCount} results` : `✗ ${server.details.page2.error || 'Failed'}`}`).join('\n') || 'None'} Bad Servers: ${badServers.map(server => ` ${server.url}: ${server.details.error ? `Error: ${server.details.error}` : ` Page 1: ${server.details.page1.success ? `✓ ${server.details.page1.resultCount} results` : `✗ ${server.details.page1.error || 'Failed'}`} Page 2: ${server.details.page2.success ? `✓ ${server.details.page2.resultCount} results` : `✗ ${server.details.page2.error || 'Failed'}`}`}`).join('\n') || 'None'} `; // Write report to file const reportPath = path.join(__dirname, 'searxng-server-report.txt'); fs.writeFileSync(reportPath, report); console.log(`\nReport written to: ${reportPath}`); // Also output summary to console console.log('\n' + '='.repeat(60)); console.log('SUMMARY'); console.log('='.repeat(60)); console.log(`Good servers: ${goodServers.length}`); console.log(`OK servers: ${okServers.length}`); console.log(`Bad servers: ${badServers.length}`); console.log('\nRecommended servers (Good):'); goodServers.forEach(server => console.log(` ✓ ${server.url}`)); } // Main function to run the tests async function main() { console.log('SearXNG Server Testing Script'); console.log('============================\n'); try { // Get list of servers const urls = await scrapeSearxSpace(); if (urls.length === 0) { console.log('No servers found to test.'); return; } console.log(`\nTesting ${urls.length} SearXNG servers...\n`); // Test all servers const results = []; for (const [index, url] of urls.entries()) { console.log(`Progress: ${index + 1}/${urls.length}`); const result = await testServer(url); results.push(result); console.log(''); // Empty line for readability } // Categorize results const goodServers = results.filter(result => result.status === 'good'); const okServers = results.filter(result => result.status === 'ok'); const badServers = results.filter(result => result.status === 'bad'); // Generate report generateReport(goodServers, okServers, badServers); console.log('\nTesting complete!'); process.exit(0); } catch (error) { console.error('Error during testing:', error); process.exit(1); } } // Run the script if called directly if (require.main === module) { main().catch(error => { console.error('Fatal error:', error); process.exit(1); }); } module.exports = { scrapeSearxSpace, testServer, testSearchQuery, generateReport };

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/pwilkin/mcp-searxng-public'

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