Skip to main content
Glama
server.py6.92 kB
"""Main server implementation for SearXNG MCP.""" import logging import sys from typing import Optional, Annotated, Literal from mcp.server.fastmcp import FastMCP from pydantic import Field from .config import load_config from .tools import SearchTools # Tool descriptions SEARCH_DESC = """Quick search for web or news content. Use this when: - User asks for a simple web search or lookup - Need quick information, not comprehensive research - Looking for news articles on a topic This runs a SINGLE search and returns up to max_results (default 10). For comprehensive research with multiple sources, use research_topic instead. Parameters: query* - What to search for category - "general" for web search, "news" for news articles (default: general) engines - Optional: Specific engines (e.g., "google,bing") max_results - Number of results (default: 10, max: 50) Returns: Search results with titles, URLs, and snippets""" SEARCH_MEDIA_DESC = """Search for images or videos. Use this when: - User wants to find images or photos - Looking for video content - "show me pictures of..." or "find videos about..." Parameters: query* - What to find media_type - "images" or "videos" (default: images) engines - Optional: Specific engines max_results - Number of results (default: 10, max: 50) Returns: Media URLs with thumbnails and sources""" RESEARCH_TOPIC_DESC = """Deep research with multiple searches and source validation. Use this when: - User wants comprehensive research or briefing - Need to validate information across multiple sources - Looking for in-depth analysis - User asks to "research", "investigate", or "give me a briefing" This tool runs 2-6 searches automatically using different strategies: - Searches multiple engines (Google, Bing, DuckDuckGo, Brave, Wikipedia) - Searches both general web and news sources - Deduplicates results across all searches - Returns 15-50 UNIQUE sources depending on depth Perfect for creating comprehensive briefings with validated information. Parameters: query* - Research topic depth - Research thoroughness: • "quick" - 2 searches, ~15 unique sources • "standard" - 4 searches, ~30 unique sources (recommended) • "deep" - 6 searches, ~50 unique sources CRITICAL - After receiving sources, you MUST: 1. Read and analyze ALL sources provided (titles, URLs, content snippets) 2. Cross-reference claims across multiple sources 3. Identify facts confirmed by many sources (high confidence) 4. Note contradictions or single-source claims (lower confidence) 5. Synthesize findings into a comprehensive briefing with: • Executive summary of key findings • Main facts/developments (note how many sources confirm each) • Contradictions or uncertainties • Source quality assessment (which engines found what) 6. DO NOT just list the sources - you must analyze, validate, and synthesize them into actionable intelligence Returns: Research briefing with analyzed, validated, cross-referenced information""" class SearxngMCPServer: """Main server class for SearXNG MCP.""" def __init__(self, config_path: Optional[str] = None): """Initialize the server. Args: config_path: Path to configuration file """ self.config = load_config(config_path) self._setup_logging() # Initialize search tools self.search_tools = SearchTools( self.config.searxng.url, self.config.searxng.timeout ) # Initialize MCP server self.mcp = FastMCP("SearxngMCP") self._setup_tools() def _setup_logging(self) -> None: """Configure logging.""" handlers = [] # Console handler console_handler = logging.StreamHandler() console_handler.setFormatter( logging.Formatter(self.config.logging.format) ) handlers.append(console_handler) # File handler if specified if self.config.logging.file: file_handler = logging.FileHandler(self.config.logging.file) file_handler.setFormatter( logging.Formatter(self.config.logging.format) ) handlers.append(file_handler) # Configure root logger logging.basicConfig( level=getattr(logging, self.config.logging.level.upper()), handlers=handlers, force=True ) self.logger = logging.getLogger("searxng-mcp") self.logger.info("SearXNG MCP Server initialized") self.logger.info(f"SearXNG URL: {self.config.searxng.url}") def _setup_tools(self) -> None: """Register MCP tools with the server.""" @self.mcp.tool(description=SEARCH_DESC) def search( query: Annotated[str, Field(description="Search query")], category: Annotated[Literal["general", "news"], Field(description="Search category")] = "general", engines: Annotated[Optional[str], Field(description="Comma-separated engine list")] = None, max_results: Annotated[int, Field(description="Maximum results", ge=1, le=50)] = 10 ): return self.search_tools.search(query, category, engines, max_results) @self.mcp.tool(description=SEARCH_MEDIA_DESC) def search_media( query: Annotated[str, Field(description="Media search query")], media_type: Annotated[Literal["images", "videos"], Field(description="Type of media")] = "images", engines: Annotated[Optional[str], Field(description="Comma-separated engine list")] = None, max_results: Annotated[int, Field(description="Maximum results", ge=1, le=50)] = 10 ): return self.search_tools.search_media(query, media_type, engines, max_results) @self.mcp.tool(description=RESEARCH_TOPIC_DESC) def research_topic( query: Annotated[str, Field(description="Research topic or question")], depth: Annotated[Literal["quick", "standard", "deep"], Field(description="Research depth")] = "standard" ): return self.search_tools.research_topic(query, depth) async def run(self): """Run the MCP server.""" await self.mcp.run_stdio_async() def main(): """Main entry point for the SearXNG MCP server.""" import argparse import anyio parser = argparse.ArgumentParser(description='SearXNG MCP Server') parser.add_argument( '--config', help='Path to configuration file' ) args = parser.parse_args() async def run_server(): try: server = SearxngMCPServer(config_path=args.config) await server.run() except Exception as e: print(f"Error: {e}", file=sys.stderr) sys.exit(1) try: anyio.run(run_server) except KeyboardInterrupt: sys.exit(0) if __name__ == "__main__": main()

Implementation Reference

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/netixc/SearxngMCP'

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