Skip to main content
Glama
tisDDM

SearXNG MCP Server

searxngsearch

Conduct web searches while respecting privacy with customizable parameters like language, time range, and categories. Returns relevant results tailored to your query.

Instructions

Perform web searches using SearXNG, a privacy-respecting metasearch engine. Returns relevant web content with customizable parameters.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
categoriesNoCategories to search in (e.g., 'general', 'images', 'news'). Default: null (all categories).
enginesNoSpecific search engines to use. Default: null (all available engines).
languageNoLanguage code for search results (e.g., 'en', 'de', 'fr'). Default: 'en'en
max_resultsNoMaximum number of search results to return. Range: 1-50. Default: 10.
pagenoNoPage number for results. Must be minimum 1. Default: 1.
queryYesSearch query
safesearchNoSafe search level: 0 (off), 1 (moderate), 2 (strict). Default: 1 (moderate).
time_rangeNoTime range for search results. Options: 'day', 'week', 'month', 'year'. Default: null (no time restriction).

Implementation Reference

  • src/index.ts:155-216 (registration)
    Tool registration in ListToolsRequestSchema handler, defining the searxngsearch tool with name, description, and input schema.
    this.server.setRequestHandler(ListToolsRequestSchema, async () => { // Define available tools const tools: Tool[] = [ { name: "searxngsearch", description: "Perform web searches using SearXNG, a privacy-respecting metasearch engine. Returns relevant web content with customizable parameters.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query" }, language: { type: "string", description: "Language code for search results (e.g., 'en', 'de', 'fr'). Default: 'en'", default: "en" }, time_range: { type: "string", enum: ["day", "week", "month", "year"], description: "Time range for search results. Options: 'day', 'week', 'month', 'year'. Default: null (no time restriction).", default: null }, categories: { type: "array", items: { type: "string" }, description: "Categories to search in (e.g., 'general', 'images', 'news'). Default: null (all categories).", default: null }, engines: { type: "array", items: { type: "string" }, description: "Specific search engines to use. Default: null (all available engines).", default: null }, safesearch: { type: "number", enum: [0, 1, 2], description: "Safe search level: 0 (off), 1 (moderate), 2 (strict). Default: 1 (moderate).", default: 1 }, pageno: { type: "number", description: "Page number for results. Must be minimum 1. Default: 1.", minimum: 1, default: 1 }, max_results: { type: "number", description: "Maximum number of search results to return. Range: 1-50. Default: 10.", default: 10, minimum: 1, maximum: 50 } }, required: ["query"] } } ]; return { tools }; });
  • Input schema for searxngsearch tool, specifying parameters like query (required), language, time_range, categories, engines, safesearch, pageno, and max_results with types, enums, defaults, and constraints.
    type: "object", properties: { query: { type: "string", description: "Search query" }, language: { type: "string", description: "Language code for search results (e.g., 'en', 'de', 'fr'). Default: 'en'", default: "en" }, time_range: { type: "string", enum: ["day", "week", "month", "year"], description: "Time range for search results. Options: 'day', 'week', 'month', 'year'. Default: null (no time restriction).", default: null }, categories: { type: "array", items: { type: "string" }, description: "Categories to search in (e.g., 'general', 'images', 'news'). Default: null (all categories).", default: null }, engines: { type: "array", items: { type: "string" }, description: "Specific search engines to use. Default: null (all available engines).", default: null }, safesearch: { type: "number", enum: [0, 1, 2], description: "Safe search level: 0 (off), 1 (moderate), 2 (strict). Default: 1 (moderate).", default: 1 }, pageno: { type: "number", description: "Page number for results. Must be minimum 1. Default: 1.", minimum: 1, default: 1 }, max_results: { type: "number", description: "Maximum number of search results to return. Range: 1-50. Default: 10.", default: 10, minimum: 1, maximum: 50 } }, required: ["query"] }
  • Core handler logic for executing searxngsearch: validates input, prepares parameters, calls SearXNG /search endpoint via axios, limits results, formats as JSON response, handles errors including auth and API failures.
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { if (request.params.name !== "searxngsearch") { throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } const args = request.params.arguments ?? {}; // Validate required parameters if (!args.query || typeof args.query !== 'string') { throw new McpError( ErrorCode.InvalidParams, "Query parameter is required and must be a string" ); } // Prepare search parameters with defaults const searchParams: SearchParams = { q: args.query, format: 'json', language: typeof args.language === 'string' ? args.language : 'en', safesearch: typeof args.safesearch === 'number' ? args.safesearch : 1, pageno: typeof args.pageno === 'number' ? args.pageno : 1, }; // Add optional parameters if provided if (args.time_range && typeof args.time_range === 'string') searchParams.time_range = args.time_range; if (Array.isArray(args.categories)) searchParams.categories = args.categories; if (Array.isArray(args.engines)) searchParams.engines = args.engines; console.error(`[SearXNG] Searching for: ${args.query}`); // Make request to SearXNG const response = await this.axiosInstance.get('/search', { params: searchParams }); const searchResults: SearXNGResponse = response.data; // Limit results if max_results is specified const maxResults = typeof args.max_results === 'number' ? args.max_results : 10; const limitedResults = searchResults.results.slice(0, maxResults); // Construct a new response object with the limited results const finalResponse: SearXNGResponse = { ...searchResults, // Copy other fields like query, answers, suggestions etc. results: limitedResults, // Use the truncated results list number_of_results: limitedResults.length // Update the count to reflect the truncation }; // Return the modified JSON data return { content: [{ type: "text", text: JSON.stringify(finalResponse, null, 2) }] }; } catch (error: any) { console.error("[SearXNG Error]", error); if (axios.isAxiosError(error)) { // Handle authentication errors if (error.response?.status === 401) { return { content: [{ type: "text", text: "Authentication failed. Please check your SearXNG username and password." }], isError: true, }; } return { content: [{ type: "text", text: `SearXNG API error: ${error.response?.data?.message ?? error.message}` }], isError: true, }; } return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true, }; } }); }
  • Helper function to fetch public list of SearXNG instances and select a random standard (non-onion/hidden) instance for use when no SEARXNG_URL is provided.
    async function getRandomSearXNGInstance(): Promise<string> { try { console.error("[SearXNG] Fetching list of SearXNG instances..."); const response = await axios.get(INSTANCES_LIST_URL); const instancesData = parse(response.data); // Debug the structure console.error("[SearXNG] Instances data structure:", Object.keys(instancesData)); // Filter for standard internet instances (not onion or hidden) const standardInstances: string[] = []; // The instances.yml file has a structure where each key is a URL for (const [url, data] of Object.entries(instancesData)) { const instanceData = data as any; // Check if it's a standard instance (not hidden or onion) if ( instanceData && (!instanceData.comments || (!instanceData.comments.includes("hidden") && !instanceData.comments.includes("onion"))) && (!instanceData.network_type || instanceData.network_type === "normal") ) { standardInstances.push(url); } } console.error(`[SearXNG] Found ${standardInstances.length} standard instances`); if (standardInstances.length === 0) { throw new Error("No standard SearXNG instances found"); } // Select a random instance const randomInstance = standardInstances[Math.floor(Math.random() * standardInstances.length)]; console.error(`[SearXNG] Selected random instance: ${randomInstance}`); return randomInstance; } catch (error) { console.error("[SearXNG] Error fetching instances:", error); throw new Error("Failed to fetch SearXNG instances list"); } }

Other Tools

Related Tools

Latest Blog Posts

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

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