{
  "markdown": "<div align=\"center\">\n\n# 🔍 SearXNG MCP Server\n\n**Privacy-respecting web search for AI assistants — use an operator-controlled or trusted SearXNG instance with Claude, Cursor, and more.**\n\n[![GitHub Stars](https://img.shields.io/github/stars/ihor-sokoliuk/mcp-searxng?style=flat-square&logo=github&label=stars)](https://github.com/ihor-sokoliuk/mcp-searxng/stargazers)\n[![npm version](https://img.shields.io/npm/v/mcp-searxng?style=flat-square&logo=npm)](https://www.npmjs.com/package/mcp-searxng)\n[![npm downloads](https://img.shields.io/npm/dm/mcp-searxng?style=flat-square&logo=npm&label=downloads%2Fmo)](https://www.npmjs.com/package/mcp-searxng)\n[![Docker Pulls](https://img.shields.io/docker/pulls/isokoliuk/mcp-searxng?style=flat-square&logo=docker)](https://hub.docker.com/r/isokoliuk/mcp-searxng)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/ihor-sokoliuk/mcp-searxng/badge)](https://scorecard.dev/viewer/?uri=github.com/ihor-sokoliuk/mcp-searxng)\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/13143/badge)](https://www.bestpractices.dev/projects/13143)\n[![mcp-searxng MCP server](https://glama.ai/mcp/servers/ihor-sokoliuk/mcp-searxng/badges/score.svg)](https://glama.ai/mcp/servers/ihor-sokoliuk/mcp-searxng)\n[![GitHub MCP Registry](https://img.shields.io/badge/GitHub_MCP_Registry-listed-2da44e?style=flat-square&logo=github&logoColor=white)](https://github.com/mcp/ihor-sokoliuk/mcp-searxng)\n\nAn [MCP server](https://modelcontextprotocol.io/introduction) that integrates the [SearXNG](https://docs.searxng.org) API, giving AI assistants web search capabilities.\n\n✨ Featured in the [GitHub MCP Registry](https://github.com/mcp/ihor-sokoliuk/mcp-searxng).\n\n</div>\n\n## Quick Start\n\nAdd to your MCP client configuration (e.g. `claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"searxng\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-searxng\"],\n      \"env\": {\n        \"SEARXNG_URL\": \"YOUR_SEARXNG_INSTANCE_URL\"\n      }\n    }\n  }\n}\n```\n\nReplace `YOUR_SEARXNG_INSTANCE_URL` with the URL of your SearXNG instance (e.g. `https://searxng.example.com`). You can also provide interchangeable replicas as a semicolon-separated list, e.g. `https://one.example.com;https://two.example.com`.\n\nFor verified Claude Desktop, Claude Code, Codex CLI, Cursor, VS Code, Windsurf,\nCline, and OpenCode recipes, see the\n[MCP client configuration cookbook](docs/client-configurations.md).\n\nFor a bounded, client-neutral method to search, inspect sources, cross-check\nclaims, and cite evidence, see the\n[evidence-focused research workflow](docs/research-workflow.md).\n\nFor measured MCP-process CPU and memory starting points, see\n[measured deployment profiles](docs/deployment-profiles.md).\n\n## Features\n\n- **Web Search**: General, news, and article queries with pagination, time-range/language/safe-search filters, relevance filtering (`min_score`), and formatted-text or raw-JSON output selected per call (`response_format`) or with the operator default (`SEARXNG_DEFAULT_RESPONSE_FORMAT`).\n- **Instance Failover & Fan-out**: Configure interchangeable SearXNG replicas in `SEARXNG_URL`; searches fail over in order by default, or query all healthy replicas in parallel and merge results with `SEARXNG_FANOUT`.\n- **Direct Answers & Metadata**: Text results surface SearXNG answers, corrections, suggestions, and infoboxes before the result list.\n- **Search Suggestions**: Query autocomplete via SearXNG's `/autocompleter` endpoint.\n- **Instance Capability Discovery**: Inspect configured categories, engines, defaults, locales, and plugins from `/config`.\n- **URL Content Reading**: Content-type-aware Markdown conversion, including bounded PDF text extraction, with pagination, section filtering, paragraph ranges, and heading extraction.\n- **Browser Solver Support**: For each uncached URL that passes static URL validation and the HEAD size preflight, optionally acquire a browser session from FlareSolverr, Byparr, or both, then replay the returned user-agent and scoped cookies through the bounded URL reader. In dual-provider mode FlareSolverr is always primary and Byparr is attempted only after a busy or transient-unavailable primary. FlareSolverr 3.5.0 and Byparr 2.1.0 were verified on 2026-07-30.\n- **Intelligent Caching**: Both search results and URL content are cached in memory with configurable TTL and least-frequently-used (LFU) eviction, reducing redundant requests.\n- **SSRF Protection**: `web_url_read` blocks private/internal URLs and redirects by default in all transport modes.\n- **HTTP Transport**: Optional MCP SDK v2 Streamable HTTP mode with opt-in hardening, rate limiting, and bounded stateless compatibility for serverless or horizontally scaled deployments. Modern 2026-07-28 requests and retained legacy clients share the same tool and resource surface.\n- **HTML Fallback**: Optionally parse results from the HTML page for public instances that reject `format=json`.\n- **Lite Tools Mode**: Minimal tool schemas for local models with small context windows.\n- **Proxy Support**: Global or per-tool HTTP/HTTPS proxies for search and URL-reader traffic.\n\nThe verified `linux/amd64` images came from multi-architecture manifests\n`ghcr.io/flaresolverr/flaresolverr:v3.5.0@sha256:139dfee1c6f89249c8d665d1333a42e8ec74ec0a86bc6bb1c8461e10d3a66a47`\nand\n`ghcr.io/thephaseless/byparr:2.1.0@sha256:01a46a2865d9a6db5eb8ead04ec0dd33b8fbe233e8565ae70b50d4cc0af4cfb0`.\nClient cancellation stops local work promptly, but a remote browser may\ncontinue until its configured provider timeout after the HTTP client\ndisconnects. See [browser solver verification](docs/browser-solver-verification.md).\n\n## Why mcp-searxng?\n\nAs of 2026-07-29, the capability comparison below reflects the official\n[Brave MCP](https://github.com/brave/brave-search-mcp-server),\n[Exa MCP](https://github.com/exa-labs/exa-mcp-server), and\n[Firecrawl MCP](https://github.com/mendableai/firecrawl-mcp-server) projects.\n“Pagination” means an exposed page or offset control. “Self-hosted” means the\nsearch service can run under your control. “Free / No API key” means this MCP\nserver does not require a paid search-vendor API key; you still operate or\nselect the underlying SearXNG instance.\n\n| | Brave MCP | Exa MCP | Firecrawl MCP | **mcp-searxng** |\n|--|:---------:|:-------:|:-------------:|:---------------:|\n| Web Search | ✓ | ✓ | ✓ | ✓ |\n| Read URL | ✗ | ✓ | ✓ | ✓ |\n| Pagination | ✓ | ✗ | ✓ | ✓ |\n| Self-hosted | ✗ | ✗ | Partial | ✓ |\n| Free / No API key | ✗ | ✗ | ✗ | ✓ |\n\nPrivacy depends on the SearXNG deployment. An operator-controlled instance can\navoid trusting a third-party search operator, while a public instance receives\nthe query and may log it. SearXNG and this MCP integration do not by themselves\nprovide anonymity.\n\n## How It Works\n\n`mcp-searxng` is a standalone MCP server — a separate Node.js process that your AI assistant connects to for web search. It queries one SearXNG instance, or a semicolon-separated list of interchangeable SearXNG replicas, via the HTTP JSON API.\n\n> **Not a SearXNG plugin:** This project cannot be installed as a native SearXNG plugin. Point it at any existing SearXNG instance, or interchangeable replica list, by setting `SEARXNG_URL`.\n\n```\nAI Assistant (e.g. Claude)\n        │  MCP protocol\n        ▼\n  mcp-searxng  (this project — Node.js process)\n        │  HTTP JSON API  (SEARXNG_URL)\n        ▼\n  SearXNG instance(s)\n```\n\nFor SearXNG deployment, configuration, and troubleshooting, see\n[Operating Self-Hosted SearXNG with mcp-searxng](docs/self-hosted-searxng.md).\n\n## Tools\n\n- **searxng_web_search**\n  - Execute web searches with pagination\n  - Inputs:\n    - `query` (string): The search query. This string is passed to external search services.\n    - `pageno` (number, optional): Search page number, starts at 1 (default 1)\n    - `time_range` (string, optional): Filter results by time range - one of: \"day\", \"week\", \"month\", \"year\" (default: none)\n    - `language` (string, optional): Language code for results (e.g., \"en\", \"fr\", \"de\") or \"all\" (default: \"all\")\n    - `safesearch` (string enum, optional): Safe search filter level, one of `\"0\"` (None), `\"1\"` (Moderate), or `\"2\"` (Strict). Legacy numeric values `0`, `1`, and `2` are still accepted for backward compatibility. (default: instance setting)\n    - `min_score` (number, optional): Minimum relevance score from 0.0 to 1.0. Results below this score are filtered out.\n    - `num_results` (number, optional): Maximum number of results to return, from 1 to 20. `SEARXNG_MAX_RESULTS` applies as an operator ceiling.\n    - `categories` (string, optional): Comma-separated SearXNG categories (e.g. `\"news\"`, `\"it,science\"`). Live `/config` capabilities are aggregated across reachable instances; prefer `searxng_instance_info` `categories.common` for consistent multi-instance results. Known values are trimmed and normalized case-insensitively; unknown values are forwarded trimmed so SearXNG can ignore or honor them. If `/config` is unavailable, values are forwarded as-is with a warning. If omitted, each instance uses its server-side default.\n    - `engines` (string, optional): Comma-separated SearXNG engine names (e.g. `\"google,bing,ddg\"`, `\"semantic scholar\"`). Live `/config` capabilities are aggregated across reachable instances; prefer `searxng_instance_info` `engines.common.enabled` for consistent multi-instance results. Known values are trimmed and normalized case-insensitively, including engines disabled by default; unknown values are forwarded trimmed so SearXNG can ignore or honor them. If `/config` is unavailable, values are forwarded as-is with a warning, except when combined with `time_range`.\n    - When `engines` and `time_range` are both provided, every configured SearXNG instance must return `/config` successfully and every selected engine must explicitly report `time_range_support=true`. If any instance is unreachable or any engine is unsupported or unknown, the request fails before `/search` to avoid a misleading empty result. Omit `time_range` or use an engine-specific query filter instead.\n    - `response_format` (string, optional): Response format, either `\"text\"` for formatted agent-readable output or `\"json\"` for raw SearXNG JSON with filtered/sliced `results`. If omitted, `SEARXNG_DEFAULT_RESPONSE_FORMAT` applies; if unset or invalid, `text` is used. An explicit `response_format` always takes precedence.\n    - `result_detail` (string, optional): `\"full\"` (the default) preserves SearXNG metadata, warnings, provenance, answers, infoboxes, corrections, and suggestions. `\"compact\"` returns only title, URL, and the description/content snippet for every result; compact JSON uses exactly the `title`, `url`, and `content` keys. Use full when those research signals matter.\n    - Clients that explicitly send or auto-inject `response_format=text` continue to override the operator default. If omitted calls still return text after configuring JSON, inspect the arguments emitted by the MCP client.\n\n  Migration: compact text has exactly three lines per result and no cache annotation or preamble. Update line parsers that expect relevance scores or search metadata to request `result_detail=\"full\"` (or accept compact's three-line records).\n\n  Compact deliberately suppresses warnings, provenance, and every other search signal. Full text may add valid optional lines in fixed order: score, engines, category, published date, thumbnail, image source; invalid optional metadata is omitted. Text fields are normalized to single lines. `SEARXNG_MAX_RESULT_CHARS` truncates result content in compact and full text/JSON responses, including full JSON for existing users who already set the variable; compact text normalizes line separators before applying the cap, while JSON caps the original string value.\n\n  With `SEARXNG_LITE_TOOLS=true`, the Lite schema stays query-only, but explicitly supplied optional overrides such as `response_format` and `result_detail` are still validated and honored.\n\n- **searxng_search_suggestions**\n  - Get autocomplete suggestions for refining search queries\n  - Inputs:\n    - `query` (string): Partial or complete query to autocomplete.\n    - `language` (string, optional): Language code for suggestions (e.g., \"en\", \"fr\", \"de\") or \"all\" (default: \"all\")\n\n- **searxng_instance_info**\n  - Discover categories aggregated from reachable configured SearXNG instances, optionally include engine names, and inspect defaults, locales, and plugins from the primary reachable instance. Categories—and engines when requested—report `common` values present on every reachable instance and `available` values present on at least one reachable instance.\n  - Inputs:\n    - `includeEngines` (boolean, optional): Include enabled engine names in the response. (default: false)\n    - `includeDisabled` (boolean, optional): Include disabled engine names when `includeEngines` is true. (default: false)\n    - `category` (string, optional): Filter categories and engines to a single category name.\n    - `refresh` (boolean, optional): Bypass the process cache and fetch fresh `/config` data. (default: false)\n\n- **web_url_read**\n  - Read URL content as markdown with content-type-aware handling and advanced extraction options\n  - Supported readable content:\n    - HTML (`text/html`, `application/xhtml+xml`) is converted to markdown\n    - JSON (`application/json`, `*+json`) is pretty-printed in a fenced block\n    - Plain text, YAML, TOML, XML, and other safe explicit `text/*` responses are returned as readable fenced text\n    - PDF (`application/pdf`) text is extracted in a resource-bounded worker for documents up to 500 pages\n    - Missing or generic content types are read under the existing size cap; non-binary bodies continue through the HTML-to-markdown path for compatibility\n  - PDF input and extracted text are each capped at the lower of `URL_READ_MAX_CONTENT_LENGTH_BYTES` and 16 MiB. OCR is not supported, and scanned/image-only or password-protected PDFs return a short explanation.\n  - A response declared as PDF must begin with the `%PDF-` signature; a mismatch usually indicates an interstitial or error page served with the wrong content type.\n  - PDF parsing has a separate 30-second worker budget after the response body is downloaded. On the direct path, the network fetch and parse take at most the configured fetch budget plus 30 seconds; configured browser-solver preflight and acquisition time is additional.\n  - At most two PDF extractions run concurrently per MCP process. There is no queue; additional concurrent reads return a busy message and may be retried.\n  - Other binary, media, archive, and octet-stream downloads are intentionally rejected with a short hint instead of returning raw bytes\n  - When `FLARESOLVERR_URL` or `BYPARR_URL` is configured, an uncached URL is validated and checked by the HEAD size preflight before `mcp-searxng` attempts browser-session acquisition. With both set, FlareSolverr is attempted first and Byparr is attempted only after a busy slot, network/timeout failure, HTTP 408/429/5xx, or malformed/oversized response. Persistent provider 4xx, cancellation, solution-host validation failure, and solved non-2xx target status stop the chain. If every configured provider is busy or unavailable, one uncached direct fetch runs. Each attempted provider receives the original target URL; challenge success is not guaranteed.\n  - At default limits, dual-provider mode has an additive maximum of 150 seconds across the initial HEAD preflight, both solver attempts (including response grace), and the final direct fetch.\n  - Inputs:\n    - `url` (string): The URL to fetch and process\n    - `startChar` (number, optional): Starting character position for content extraction (default: 0)\n    - `maxLength` (number, optional): Maximum number of characters to return\n    - `section` (string, optional): Extract content under a specific heading (searches for heading text)\n    - `paragraphRange` (string, optional): Return specific paragraph ranges (e.g., '1-5', '3', '10-')\n    - `readHeadings` (boolean, optional): Return only a list of headings instead of full content\n\n## Installation\n\nNode.js 22 or later is required.\n\n<details>\n<summary>NPM (global install)</summary>\n\n```bash\nnpm install -g mcp-searxng\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"searxng\": {\n      \"command\": \"mcp-searxng\",\n      \"env\": {\n        \"SEARXNG_URL\": \"YOUR_SEARXNG_INSTANCE_URL\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary>Docker</summary>\n\n**Pre-built image:**\n\n```bash\ndocker pull isokoliuk/mcp-searxng:latest\n```\n\nImage signatures can be verified with Cosign — see [SECURITY.md](SECURITY.md) for instructions.\n\n```json\n{\n  \"mcpServers\": {\n    \"searxng\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"SEARXNG_URL\",\n        \"isokoliuk/mcp-searxng:latest\"\n      ],\n      \"env\": {\n        \"SEARXNG_URL\": \"YOUR_SEARXNG_INSTANCE_URL\"\n      }\n    }\n  }\n}\n```\n\nTo pass additional env vars, add `-e VAR_NAME` to `args` and the variable to `env`.\nFor browser-solver integration, pass `FLARESOLVERR_URL`, `BYPARR_URL`, or both\nand make the configured services reachable from this container. Dual mode has\na fixed FlareSolverr-first order and no automatic reverse failover. See\n[URL Reader Controls](CONFIGURATION.md#url-reader-controls) for the complete\nbehavior and Docker Compose example.\n\n**Build locally:**\n\n```bash\ndocker build -t mcp-searxng:latest -f Dockerfile .\n```\n\nUse the same config above, replacing `isokoliuk/mcp-searxng:latest` with `mcp-searxng:latest`.\n\n</details>\n\n<details>\n<summary>Docker Compose</summary>\n\n`docker-compose.yml`:\n\n```yaml\nservices:\n  mcp-searxng:\n    image: isokoliuk/mcp-searxng:latest\n    stdin_open: true\n    environment:\n      - SEARXNG_URL=${SEARXNG_URL:?Set SEARXNG_URL in the environment}\n      # Add optional variables as needed — see CONFIGURATION.md\n```\n\nThe tracked Compose file is intentionally STDIO-only and publishes no network ports; MCP clients launch it with an absolute Compose-file path and `docker compose run --rm -T`, not `docker compose up`. The `-T` flag prevents pseudo-TTY allocation so MCP JSON-RPC stays on raw standard input and output. Compose fails before launch unless the MCP client supplies `SEARXNG_URL`.\n\nMCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"searxng\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"compose\",\n        \"-f\", \"/absolute/path/to/docker-compose.yml\",\n        \"run\", \"--rm\", \"-T\", \"mcp-searxng\"\n      ],\n      \"env\": {\n        \"SEARXNG_URL\": \"YOUR_SEARXNG_INSTANCE_URL\"\n      }\n    }\n  }\n}\n```\n\nIf you previously used the tracked file as an HTTP service on port 8080, put the HTTP settings in an untracked `docker-compose.override.yml`:\n\n```yaml\nservices:\n  mcp-searxng:\n    ports:\n      - \"127.0.0.1:8080:8080\"\n    environment:\n      - MCP_HTTP_PORT=8080\n      - MCP_HTTP_HOST=0.0.0.0\n```\n\nHere `0.0.0.0` is the container-side bind address; the host-side port remains loopback-only. This override has no authentication and is only a temporary single-host migration path. Before adding co-located containers or exposing the service beyond the local machine, follow the hardened [deployment guidance](SECURITY.md#deployment-recommendations).\n\n</details>\n\n<details>\n<summary>HTTP Transport</summary>\n\nBy default the server uses STDIO, launched by your MCP client. To use HTTP instead, run `mcp-searxng` as a **standalone process** with `MCP_HTTP_PORT` set. In this mode it serves the MCP protocol over HTTP and does not speak STDIO, so your client connects to it by URL rather than spawning it.\n\n**Start the server:**\n\n```bash\nMCP_HTTP_PORT=3000 SEARXNG_URL=http://localhost:8080 mcp-searxng\n```\n\nOr with Docker (bind to all interfaces so the port is reachable from the host):\n\n```bash\ndocker run --rm -p 3000:3000 \\\n  --add-host=host.docker.internal:host-gateway \\\n  -e MCP_HTTP_PORT=3000 -e MCP_HTTP_HOST=0.0.0.0 \\\n  -e SEARXNG_URL=http://host.docker.internal:8080 \\\n  isokoliuk/mcp-searxng:latest\n```\n\nThe `--add-host` mapping lets the container reach a SearXNG instance on the host via `host.docker.internal`; it resolves automatically on Docker Desktop but needs this flag on native Linux. Point `SEARXNG_URL` at your actual instance if it runs elsewhere.\n\n**Connect an HTTP-capable MCP client** to the `/mcp` endpoint by URL:\n\n```json\n{\n  \"mcpServers\": {\n    \"searxng-http\": {\n      \"type\": \"streamable-http\",\n      \"url\": \"http://localhost:3000/mcp\"\n    }\n  }\n}\n```\n\n**Protocol support:** HTTP and STDIO serve modern MCP `2026-07-28` and the retained legacy revisions `2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05`, and `2024-10-07`. Modern HTTP is sessionless `POST /mcp`; legacy HTTP remains stateful by default (`POST/GET/DELETE /mcp`) or uses the existing POST-only stateless mode.\n\n**Endpoints:** modern `POST /mcp`; legacy `POST/GET/DELETE /mcp` in the stateful default, or legacy `POST /mcp` only with stateless mode; `GET /health`.\n\nFor legacy HTTP clients, stateful sessions remain the default. Set `MCP_HTTP_STATELESS=true` when a deployment cannot preserve in-memory legacy sessions between requests. Modern HTTP remains sessionless regardless of that setting. Every stateless POST creates a fresh MCP server and transport, ignores any incoming session ID, and returns negotiated JSON or an SSE stream within that same POST. Stateless mode is POST-only: `GET /mcp` and `DELETE /mcp` return HTTP 405 with `Allow: POST`, and no cross-request subscriptions, resumability, or server-to-client notifications are preserved.\n\nStateless requests are bounded by global and per-client-IP in-flight limits plus a request lifetime. See [CONFIGURATION.md](CONFIGURATION.md#http-transport) for defaults, overload and timeout responses, proxy-aware fairness, and the complete compatibility contract.\n\n**Origin validation and upgrade notice:** Every present `Origin` on `/mcp` is validated in all modes; an absent `Origin` remains valid for non-browser clients. In non-hardened mode, an unset `MCP_HTTP_ALLOWED_ORIGINS` defaults to the exact HTTP/HTTPS loopback origins `http://127.0.0.1`, `https://127.0.0.1`, `http://localhost`, `https://localhost`, `http://[::1]`, and `https://[::1]`, both portless and with the configured `MCP_HTTP_PORT`. A non-empty `MCP_HTTP_ALLOWED_ORIGINS` replaces those defaults. Entries are trimmed but otherwise literal; matching is exact, case-sensitive literal matching, including scheme and port. Malformed, scheme-less, path-bearing, trailing slash, or differently-cased values silently do not match and must be corrected. Hardened mode still requires an explicit allowlist and adds authentication plus Host enforcement. An invalid present `Origin` on `/mcp` receives a fixed, non-reflecting 403 before parser, authentication, rate limiting, or transport construction. `/health` is outside the MCP 403 boundary but uses the narrowed global CORS allowlist. Before upgrading, existing non-hardened browser deployments using non-loopback Origins must set `MCP_HTTP_ALLOWED_ORIGINS` or receive a fixed 403.\n\n**Test it:**\n\n```bash\ncurl http://localhost:3000/health\n```\n\nThe server binds to `127.0.0.1` by default; set `MCP_HTTP_HOST=0.0.0.0` for remote or containerized deployments. Before exposing it on a network, enable hardened mode (`MCP_HTTP_HARDEN`) and see [CONFIGURATION.md](CONFIGURATION.md) for `MCP_HTTP_TRUST_PROXY` so rate limiting and logs use the correct client IP.\n\n</details>\n\n## Configuration\n\n`SEARXNG_URL` is the only required variable — set it to your SearXNG instance URL (or a semicolon-separated list of interchangeable replicas). Everything else is optional.\n\nUse `SEARXNG_DEFAULT_RESPONSE_FORMAT` to select `text` or `json` when search calls omit `response_format`; explicit per-call values still win.\n\nSee **[CONFIGURATION.md](CONFIGURATION.md)** for the full environment variable reference, including authentication, failover/fan-out, caching, timeouts, proxies, TLS, HTTP transport, and hardening.\n\n## Troubleshooting\n\nFor self-hosted SearXNG configuration, direct verification, and troubleshooting,\nsee [Operating Self-Hosted SearXNG with mcp-searxng](docs/self-hosted-searxng.md).\nIf you do not control the instance, use the separate\n[public SearXNG instance guide](docs/public-searxng-instances.md) instead.\n\nIf HTTPS requests fail behind a TLS-inspecting corporate proxy with certificate errors, see [TLS / Corporate CA](CONFIGURATION.md#tls--corporate-ca).\n\n### 403 Forbidden from SearXNG\n\nYour SearXNG instance likely has JSON format disabled. Edit `settings.yml` (usually `/etc/searxng/settings.yml`):\n\n```yaml\nsearch:\n  formats:\n    - html\n    - json\n```\n\nRestart SearXNG (`docker restart searxng`) then verify:\n\n```bash\ncurl 'http://localhost:8080/search?q=test&format=json'\n```\n\nYou should receive a JSON response. If not, confirm the file is correctly mounted and YAML indentation is valid.\n\nSee also: [SearXNG settings docs](https://docs.searxng.org/admin/settings/settings.html) · [discussion](https://github.com/searxng/searxng/discussions/1789)\n\n### Can't enable JSON? (HTML fallback)\n\nIf you must use a public instance you don't control and it rejects `format=json` (the 403 above), set the opt-in flag instead of editing the server:\n\nBefore enabling it, review the public operator's policy and the\n[public-instance usage guide](docs/public-searxng-instances.md).\n\n```json\n{\n  \"SEARXNG_HTML_FALLBACK\": \"true\"\n}\n```\n\nA search that gets a `403`/`404` or a non-JSON response is then retried automatically **without** `format=json` and parsed from the regular HTML results page.\n\n- **On success:** you get normal results (title, URL, snippet). They are marked `sourceFormat: \"html\"` in JSON mode, and text mode adds the line *\"Note: Results parsed from SearXNG HTML fallback; metadata is limited.\"* Relevance scores and engine names are not available from HTML.\n- **On failure:** parsing is best-effort and varies by the instance's theme/version, so some results may be missed or sparse. If the HTML page itself also fails — still blocked, rate-limited (`429`), auth (`401`), or `5xx` — the **fallback attempt's error is surfaced**, so the search never silently returns empty results. The fallback only triggers on `403`/`404`/non-JSON, never on auth or network errors.\n\nEnabling JSON on an instance you control (above) remains the recommended setup — the fallback is a compatibility aid, not a replacement.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## License\n\nMIT — see [LICENSE](LICENSE) for details.\n",
  "bytes": 26596,
  "sha": "60db5e72aac11d6d062763ed0941c083e01a5db37f352e0f3d90e3e7ab17af84",
  "repo_slug": "ihor-sokoliuk/mcp-searxng",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_ihor_sokoliuk_mcp_searxng_ba9a5b9e/readme"
}