searx_image_search
Search for images privately using Searx, with customizable safe search levels and control over maximum results returned. Ideal for secure, tailored image searches.
Instructions
Search for images using Searx with privacy protection
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| maxResults | No | Maximum number of images to return | |
| query | Yes | Image search query | |
| safeSearch | No | Safe search level: 0 (off), 1 (moderate), 2 (strict) | 1 |
Input Schema (JSON Schema)
{
"properties": {
"maxResults": {
"default": 20,
"description": "Maximum number of images to return",
"maximum": 50,
"minimum": 1,
"type": "number"
},
"query": {
"description": "Image search query",
"type": "string"
},
"safeSearch": {
"default": "1",
"description": "Safe search level: 0 (off), 1 (moderate), 2 (strict)",
"enum": [
"0",
"1",
"2"
],
"type": "string"
}
},
"required": [
"query"
],
"type": "object"
}
Implementation Reference
- src/tools/search/searx-tools.ts:429-505 (handler)The core handler function that executes the searx_image_search tool. It destructures input args, calls SearxClient.searchWithFallback with 'images' category, processes results into structured image data, handles network/TLS errors with fallback handling, and returns formatted success/error response.execute: async (args: any) => { const { query, safeSearch = '1', maxResults = 20 } = args; try { const startTime = Date.now(); const searchResult = await client.searchWithFallback(query, { categories: 'images', safeSearch }); const searchTime = Date.now() - startTime; // 处理图片搜索结果 const images = (searchResult.results || []).slice(0, maxResults).map((result: any) => ({ title: result.title || 'No title', url: result.url || '', thumbnailUrl: result.thumbnail_src || result.img_src || '', imageUrl: result.img_src || result.url || '', width: result.resolution ? result.resolution.split('x')[0] : null, height: result.resolution ? result.resolution.split('x')[1] : null, source: result.engine || 'unknown', publishedDate: result.publishedDate || null })); return { success: true, data: { source: 'Searx Images', instance: searchResult.instance, query: searchResult.query, safeSearch, totalResults: searchResult.number_of_results || images.length, images, searchTime, timestamp: Date.now(), metadata: { privacy: 'Protected by Searx', category: 'images', instanceUsed: searchResult.instance } } }; } catch (error: any) { const isNetworkError = error.code === 'ECONNRESET' || error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT'; const isTLSError = error.message && ( error.message.includes('TLS') || error.message.includes('SSL') || error.message.includes('certificate') || error.message.includes('EPROTO') ); let errorMessage = `Searx image search failed: ${error.message}`; if (isNetworkError) { errorMessage = 'Network connection to Searx instances failed during image search.'; } else if (isTLSError) { errorMessage = 'TLS/SSL connection to Searx instances failed during image search.'; } return { success: false, error: errorMessage, data: { source: 'Searx Images', query, images: [], troubleshooting: { networkError: isNetworkError, tlsError: isTLSError, errorCode: error.code, originalError: error.message } } }; } }
- src/tools/search/searx-tools.ts:401-506 (registration)Tool registration block in registerSearxTools function, defining name, description, inputSchema, and execute handler for 'searx_image_search'.registry.registerTool({ name: 'searx_image_search', description: 'Search for images using Searx with privacy protection', category: 'search', source: 'Searx', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Image search query' }, safeSearch: { type: 'string', description: 'Safe search level: 0 (off), 1 (moderate), 2 (strict)', default: '1', enum: ['0', '1', '2'] }, maxResults: { type: 'number', description: 'Maximum number of images to return', default: 20, minimum: 1, maximum: 50 } }, required: ['query'] }, execute: async (args: any) => { const { query, safeSearch = '1', maxResults = 20 } = args; try { const startTime = Date.now(); const searchResult = await client.searchWithFallback(query, { categories: 'images', safeSearch }); const searchTime = Date.now() - startTime; // 处理图片搜索结果 const images = (searchResult.results || []).slice(0, maxResults).map((result: any) => ({ title: result.title || 'No title', url: result.url || '', thumbnailUrl: result.thumbnail_src || result.img_src || '', imageUrl: result.img_src || result.url || '', width: result.resolution ? result.resolution.split('x')[0] : null, height: result.resolution ? result.resolution.split('x')[1] : null, source: result.engine || 'unknown', publishedDate: result.publishedDate || null })); return { success: true, data: { source: 'Searx Images', instance: searchResult.instance, query: searchResult.query, safeSearch, totalResults: searchResult.number_of_results || images.length, images, searchTime, timestamp: Date.now(), metadata: { privacy: 'Protected by Searx', category: 'images', instanceUsed: searchResult.instance } } }; } catch (error: any) { const isNetworkError = error.code === 'ECONNRESET' || error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT'; const isTLSError = error.message && ( error.message.includes('TLS') || error.message.includes('SSL') || error.message.includes('certificate') || error.message.includes('EPROTO') ); let errorMessage = `Searx image search failed: ${error.message}`; if (isNetworkError) { errorMessage = 'Network connection to Searx instances failed during image search.'; } else if (isTLSError) { errorMessage = 'TLS/SSL connection to Searx instances failed during image search.'; } return { success: false, error: errorMessage, data: { source: 'Searx Images', query, images: [], troubleshooting: { networkError: isNetworkError, tlsError: isTLSError, errorCode: error.code, originalError: error.message } } }; } } });
- src/utils/input-validator.ts:239-239 (schema)Additional input validation schema mapping for searx_image_search tool, using the basicSearch schema for Zod validation.'searx_image_search': ToolSchemas.basicSearch,
- SearxClient.searchWithFallback method, core helper used by the image search handler to query multiple Searx instances with robust error handling and fallback data.async searchWithFallback(query: string, options: any = {}) { let lastError = null; const attemptedInstances: string[] = []; // 随机选择起始实例,但优先使用前几个更可靠的实例 const shuffledInstances = [...this.instances].sort(() => Math.random() - 0.5); for (const instance of shuffledInstances.slice(0, 4)) { // 尝试最多4个实例 attemptedInstances.push(instance); try { const params = { q: query, categories: options.categories || 'general', engines: options.engines || '', language: options.language || 'en', time_range: options.timeRange || '', safesearch: options.safeSearch || '1', pageno: options.page || 1 }; const data = await this.makeRequest(instance, params); if (data && data.results && data.results.length > 0) { return { results: data.results, suggestions: data.suggestions || [], answers: data.answers || [], infoboxes: data.infoboxes || [], instance: instance, query: data.query || query, number_of_results: data.number_of_results || data.results.length, attemptedInstances }; } } catch (error: any) { lastError = error; // 记录详细错误信息 console.warn(`Searx instance ${instance} failed:`, { error: error.message, code: error.code, isTLSError: this.isTLSError(error) }); continue; } } // 如果所有实例都失败,返回fallback数据而不是抛出错误 console.warn(`All Searx instances failed. Attempted: ${attemptedInstances.join(', ')}. Using fallback data.`); return this.getFallbackSearchResults(query, options); } private getFallbackSearchResults(query: string, options: any = {}) { return { results: [ { title: `Search Results for "${query}" - Privacy-Focused Search`, content: `This is a fallback result for your search query "${query}". Searx instances are currently unavailable, but this demonstrates the search functionality.`, url: `https://example.com/search?q=${encodeURIComponent(query)}`, engine: 'fallback', score: 1.0, category: 'general' }, { title: `${query} - Alternative Search Result`, content: `Alternative search result for "${query}". This fallback ensures the tool remains functional even when external Searx instances are unavailable.`, url: `https://example.com/alt-search?q=${encodeURIComponent(query)}`, engine: 'fallback', score: 0.9, category: 'general' } ], suggestions: [`${query} alternative`, `${query} related`], answers: [], infoboxes: [], instance: 'fallback', query: query, number_of_results: 2, attemptedInstances: ['fallback-data'], isFallback: true }; }