{
  "markdown": "# SearXNG MCP Server\n\nA Model Context Protocol (MCP) server that provides web search capabilities by integrating with a SearXNG instance.\n\n## Features\n\n- **Web Search**: Perform powerful aggregated searches across multiple engines.\n- **Discovery**: Programmatically retrieve available categories and engines.\n- **Stateless HTTP**: Compatible with any standard JSON-RPC client.\n- **Flexible Configuration**: Supports environment variables and command-line arguments.\n\n## Example of compose.yml to run SearXNG with MCP server \n\n```yaml\nservices:\n  searxng:\n    image: searxng/searxng:latest\n    ports:\n      - \"${SEARXNG_PORT:-8080}:8080\"\n    volumes:\n      - \"${SEARXNG_VOL_CONFIG:-searxng-config}:/etc/searxng/\"\n      - \"${SEARXNG_VOL_DATA:-searxng-data}:/var/cache/searxng/\"\n    restart: always\n\n  searxng-mcp:\n    image: ghcr.io/aicrafted/searxng-mcp:latest\n    restart: unless-stopped\n    depends_on:\n      # Ensure SearXNG starts before the MCP server\n      - searxng\n    environment:\n      SEARXNG_URL: \"${SEARXNG_URL:-http://searxng:8080}\"\n      MCP_HOST: \"${MCP_HOST:-127.0.0.1}\"\n      MCP_PORT: \"${MCP_PORT:-32123}\"\n      MCP_TRANSPORT: \"${MCP_TRANSPORT:-http}\"\n      MCP_ALLOWED_HOSTS: \"${MCP_ALLOWED_HOSTS:-localhost:*,127.0.0.1:*}\"\n      MCP_ALLOWED_ORIGINS: \"${MCP_ALLOWED_ORIGINS:-http://localhost:*,http://127.0.0.1:*}\"\n      MCP_DISABLE_DNS_REBINDING_PROTECTION: \"${MCP_DISABLE_DNS_REBINDING_PROTECTION:-false}\"\n    ports:\n      - \"${MCP_PORT:-32123}:${MCP_PORT:-32123}\"\n\nvolumes:\n  searxng-config:\n  searxng-data:\n```\n\n> **Important:** Enable JSON responses in your SearXNG `settings.yml`, otherwise the MCP server cannot read search results:\n>\n> ```yaml\n> search:\n>   formats:\n>     - html\n>     - json\n> ```\n\n### Example `.env`\n\n```env\n# SearXNG url should be visible by the MCP server inside docker, so use internal service port here\nSEARXNG_URL=http://searxng:8080\n# Public SearXNG port\nSEARXNG_PORT=8080\n# Searxng config and data volumes, start with \"./\" if You want to bind dir instead using volume\nSEARXNG_VOL_CONFIG=searxng-config\nSEARXNG_VOL_DATA=searxng-data\n\n# MCP server host, port and transport (\"stdio\", \"sse\", \"http\")\nMCP_HOST=127.0.0.1\nMCP_PORT=32123\nMCP_TRANSPORT=http\n\n# MCP DNS rebinding protection (see https://github.com/modelcontextprotocol/python-sdk/issues/1798 for details)\nMCP_ALLOWED_HOSTS=localhost:*,127.0.0.1:*\nMCP_ALLOWED_ORIGINS=http://localhost:*,http://127.0.0.1:*\n# MCP_DISABLE_DNS_REBINDING_PROTECTION=true\n```\n\n## MCP client config\n\n### HTTP transport (recommended)\n```JSON\n{\n  \"mcpServers\": {\n    \"searxng\": {\n      \"type\": \"http\",\n      \"url\": \"http://localhost:32123/mcp\"\n    }\n  }\n}\n```\n\n### SSE transport\n```JSON\n{\n  \"mcpServers\": {\n    \"searxng\": {\n      \"type\": \"sse\",\n      \"url\": \"http://localhost:32123/sse\"\n    }\n  }\n}\n```\n\n> **Note:** SSE transport uses the `/sse` endpoint, not `/mcp`. HTTP transport uses `/mcp`.\n\n\n## Prerequisites for run from sources\n\n- Python 3.10+\n- A running [SearXNG](https://github.com/searxng/searxng) instance.\n\n## Installation\n\n1. Clone the repository and navigate to the directory.\n2. Install dependencies:\n   ```bash\n   pip install -r requirements.txt\n   ```\n3. Set up your `.env` file (optional).\n\n## Configuration\n\nThe server reads configuration from command-line arguments and environment variables. Command-line arguments override the corresponding defaults used at startup.\n\n| Variable | Default | Description |\n| :--- | :--- | :--- |\n| `SEARXNG_URL` | `http://localhost:8080` | URL of the SearXNG instance. |\n| `SEARXNG_PORT` | `8080` | Public host port for the SearXNG container in the compose example. |\n| `SEARXNG_VOL_CONFIG` | `searxng-config` | Docker volume or host path mounted to `/etc/searxng/` in the compose example. |\n| `SEARXNG_VOL_DATA` | `searxng-data` | Docker volume or host path mounted to `/var/cache/searxng/` in the compose example. |\n| `MCP_HOST` | `127.0.0.1` | Host to bind for HTTP/SSE transports. Use `0.0.0.0` in Docker when publishing the port. |\n| `MCP_PORT` | `8000` | Port to bind for HTTP/SSE transports. |\n| `MCP_TRANSPORT` | `stdio` | Transport mode: `stdio`, `http`, or `sse`. |\n| `MCP_ALLOWED_HOSTS` | SDK defaults for localhost | Comma-separated allowed `Host` headers for DNS rebinding protection. |\n| `MCP_ALLOWED_ORIGINS` | SDK defaults for localhost | Comma-separated allowed `Origin` headers for DNS rebinding protection. |\n| `MCP_DISABLE_DNS_REBINDING_PROTECTION` | `false` | Set to `true` to disable the SDK DNS rebinding protection. |\n\n## Usage\n\nRun the server using `uv` or standard python:\n\n```bash\npython searxng_mcp.py --transport http --port 32123 --searxng http://searx.lan\n```\n\n### Run with Docker\n\n1. **Build the image**:\n   ```bash\n   docker build -t searxng-mcp .\n   ```\n\n2. **Run the container**:\n   ```bash\n   docker run -d \\\n     -p 32123:32123 \\\n     --env-file .env \\\n     --name searxng-mcp \\\n     searxng-mcp\n   ```\n\n### Transport Options\n- `stdio`: Standard input/output (default for some MCP clients).\n- `http`: Stateless HTTP (streamable-http).\n- `sse`: Server-Sent Events.\n\n### DNS Rebinding Protection\n\nRecent versions of the MCP Python SDK validate `Host` and `Origin` headers for HTTP/SSE transports to protect local servers from DNS rebinding attacks. If you expose the server through Docker, a reverse proxy, or a custom domain and receive `421 Invalid Host Header`, configure the allowlist explicitly:\n\n```env\nMCP_ALLOWED_HOSTS=localhost:*,127.0.0.1:*,mcp.example.com:*\nMCP_ALLOWED_ORIGINS=http://localhost:*,http://127.0.0.1:*,https://mcp.example.com\n```\n\nFor trusted local development or when this validation is handled by another infrastructure layer, you can disable the SDK protection:\n\n```env\nMCP_DISABLE_DNS_REBINDING_PROTECTION=true\n```\n\nUse disabling sparingly; setting `MCP_ALLOWED_HOSTS` and `MCP_ALLOWED_ORIGINS` is the recommended option.\n\n---\n\n# Search Abilities Guide\n\nSearXNG aggregates results from various sources. This guide outlines the capabilities available through the `web_search` tool.\n\n## Search Categories\nCategories help refine your search by content type. Use these in the `categories` parameter (comma-separated).\n\n| Category | Description |\n| :--- | :--- |\n| `general` | Default web search (Google, Brave, DuckDuckGo, etc.) |\n| `images` | Image search results |\n| `videos` | Video content from YouTube, Vimeo, etc. |\n| `news` | Recent news articles |\n| `map` | Geographical and map information |\n| `it` | IT-related searches (StackOverflow, GitHub, etc.) |\n| `science` | Scientific papers and articles (ArXiv, Google Scholar) |\n| `files` | Torrent and file searches |\n| `social_media` | Posts and profiles from social platforms |\n\n## Supported Engines\nSearXNG can query over 130 engines. Configured engines typically include:\n- **Web**: Google, Brave, DuckDuckGo, Qwant, Startpage\n- **Knowledge**: Wikipedia, Wikidata\n- **Development**: GitHub, StackOverflow, PyPI\n- **Social**: Reddit, Twitter/X\n\n## Advanced Search Parameters\n- **`categories`**: Filter by specific types (e.g., `news,it`).\n- **`engines`**: Force specific engines (e.g., `google,wikipedia`).\n- **`language`**: Specify search language (e.g., `en`, `es`, `fr`).\n- **`pageno`**: Navigate through multiple pages of results.\n- **`time_range`**: Filter by date (`day`, `month`, `year`).\n- **`safesearch`**: Control content filtering (0=None, 1=Moderate, 2=Strict).\n\n## Programmatic Discovery\nUse the `web_search_info` tool to dynamically retrieve the list of enabled categories and engines from your instance.\n\n# Windows Troubleshooting\n\n## localhost not reachable while Docker container is running\n\n**Symptom:** `http://localhost:<port>/` returns connection refused or hits the wrong service,\nbut `curl` from inside the container works fine.\n\n**Root cause: WSL2 port relay ghost**\n\nWSL2 automatically forwards ports from the Linux VM to the Windows host using `wslrelay.exe`.\nWhen a process inside WSL listens on a port, WSL creates a relay bound to `[::1]:<port>`\n(IPv6 loopback) on the Windows side.\n\nWhen that WSL process stops, `wslrelay.exe` often **does not release the port**. The relay\nentry stays alive as a zombie listener on `[::1]:<port>`.\n\nLater, when Docker maps a container to the same host port, it binds correctly to\n`0.0.0.0:<port>` — but `[::1]:<port>` is already taken by the stale relay.\n\nOn Windows, `localhost` resolves to `::1` (IPv6) first. So browser and curl requests to\n`localhost:<port>` hit the dead `wslrelay.exe` entry instead of the Docker container,\nresulting in a connection error or unexpected response.\n\nConnecting via the explicit IPv4 address `127.0.0.1:<port>` bypasses the relay and reaches\nDocker correctly.\n\n**How to diagnose:**\n\n```powershell\n# Check what is listening on the port\nnetstat -ano | findstr :<port>\n\n# Identify the processes\nGet-Process -Id <pid1>,<pid2> | Select-Object Id,Name\n```\n\nIf you see two entries for the same port — one owned by `com.docker.backend` and another\nby `wslrelay` — this is the problem.\n\n**Workarounds:**\n\n| Option | Command | Notes |\n|--------|---------|-------|\n| Use IPv4 directly | `http://127.0.0.1:<port>/` | Immediate, no restart needed |\n| Restart WSL | `wsl --shutdown` | Kills all stale relays; WSL restarts on next use |\n| Remap Docker port | Change host port in `docker run -p` or `docker-compose.yml` | Avoids the conflict entirely |\n\n**Permanent fix:**\n\nAfter `wsl --shutdown`, restart the Docker container. The relay will no longer exist and\n`localhost:<port>` will work normally until the same port is reused inside WSL again.\n\n**Prevention:**\n\nIf you regularly run services on the same port both in WSL and in Docker, prefer one of:\n\n- Always use Docker for that service, never WSL directly\n- Use different ports for WSL dev and Docker prod instances\n- Add `127.0.0.1:<port>:<port>` explicit binding in `docker-compose.yml` to force IPv4\n\n---\n\n## Related\n\n- [WSL2 networking documentation](https://learn.microsoft.com/en-us/windows/wsl/networking)\n- WSL GitHub issue tracker: search `wslrelay port leak`\n",
  "bytes": 9969,
  "sha": "053ed6cf38c6fb4bf5c8e27b374a5743172c32bd6c55744638c7b85f96f16512",
  "repo_slug": "aicrafted/searxng-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_aicrafted_searxng_mcp_4a74efd3/readme"
}