All environment variables for mcp-searxng, organized by concern. All variables are optional unless marked required.
| Variable | Required | Default | Description |
|---|---|---|---|
SEARXNG_URL |
Yes | — | URL of your SearXNG instance, or a semicolon-separated list of interchangeable replica base URLs. Single URL behavior is unchanged. Format: <protocol>://<hostname>[:<port>] (e.g. http://localhost:8080 or https://one.example.com;https://two.example.com) |
SEARXNG_FANOUT |
No | false |
Set to true to query all healthy configured SearXNG instances in parallel and merge results. Default failover mode tries instances in order until one returns results. |
When SEARXNG_URL contains multiple semicolon-separated URLs, they are treated as interchangeable replicas. Default mode fails over in order when an instance hard-fails or returns no results. A reachable 200 OK response with an empty results array is considered healthy and does not trigger cooldown. Instances with 3 consecutive hard failures are skipped for 60 seconds.
With SEARXNG_FANOUT=true, all healthy instances are queried in parallel. Results are deduplicated by canonical URL, the copy with the highest score is kept, and merged results are ordered by descending score. Capability discovery and filter guidance aggregate /config data from all reachable configured instances; common categories/engines work everywhere reachable, while available values are best-effort. A /config endpoint that fails is skipped for about 60 seconds before retry, or retried immediately when searxng_instance_info is called with refresh=true. Search suggestions use the first configured instance.
| Variable | Required | Default | Description |
|---|---|---|---|
AUTH_USERNAME |
No | — | HTTP Basic Auth username for password-protected SearXNG instances |
AUTH_PASSWORD |
No | — | HTTP Basic Auth password for password-protected SearXNG instances |
| Variable | Required | Default | Description |
|---|---|---|---|
SEARXNG_TIMEOUT_MS |
No | 10000 |
Maximum time in milliseconds to wait for a SearXNG search response. The request is aborted and a network error is returned if the server does not respond within this window. |
FETCH_TIMEOUT_MS |
No | 10000 |
Maximum time in milliseconds to wait for a web_url_read fetch. The request is aborted and an error is returned if the server does not respond within this window. |
| Variable | Required | Default | Description |
|---|---|---|---|
SEARXNG_LITE_TOOLS |
No | false |
Set to true to register minimal tool schemas with only query / url parameters. Reduces per-call token overhead for local models with small context windows. Extra parameters (e.g. language, maxLength) passed by the caller are still accepted and forwarded. |
Operator-level defaults applied when the caller omits the corresponding per-call parameter.
| Variable | Required | Default | Description |
|---|---|---|---|
SEARXNG_DEFAULT_LANGUAGE |
No | all |
Default language for all searches when language is not passed per call (e.g. en, fr, de). |
SEARXNG_DEFAULT_SAFESEARCH |
No | — | Default safe-search level: 0 (off), 1 (moderate), 2 (strict). Invalid values are ignored with a warning. When unset, the SearXNG instance default applies. |
| Variable | Required | Default | Description |
|---|---|---|---|
SEARXNG_MAX_RESULTS |
No | — | Operator-level maximum number of search results to return per call (1-20). Invalid values are ignored. Recommended: 10 for smaller context windows. |
SEARXNG_MAX_RESULT_CHARS |
No | — | Maximum characters to include in each search result snippet. Longer snippets are truncated and marked with …. Invalid values are ignored. Recommended: 500 for smaller context windows. |
Self-hosting SearXNG with JSON output enabled remains the recommended setup. The HTML fallback is best-effort for public instances that reject format=json; HTML theme differences may limit parsed metadata.
| Variable | Required | Default | Description |
|---|---|---|---|
SEARXNG_HTML_FALLBACK |
No | false |
Set to true to retry 403/404 or non-JSON search responses as an HTML search page and parse title, URL, and snippet only. HTML fallback results are marked with sourceFormat: "html" in JSON output. |
| Variable | Required | Default | Description |
|---|---|---|---|
URL_READ_MAX_CHARS |
No | — | Default maximum characters returned by web_url_read when the caller omits maxLength. Explicit maxLength always wins. Invalid values are ignored. |
URL_READ_MAX_CONTENT_LENGTH_BYTES |
No | 5242880 |
Maximum decompressed response-body bytes web_url_read will read while streaming a page. A HEAD Content-Length preflight may reject oversized pages before GET, but the streaming cap is authoritative. Invalid values fall back to the default. |
CACHE_TTL_MS |
No | 86400000 |
URL cache TTL in milliseconds. Invalid or non-positive values fall back to the default (24 hours). |
CACHE_MAX_ENTRIES |
No | 500 |
Maximum number of cached URLs. When the cache exceeds this size, the least frequently used entry is evicted, with oldest entry used as the tie-breaker. Invalid or non-positive values fall back to the default. |
| Variable | Required | Default | Description |
|---|---|---|---|
USER_AGENT |
No | — | Global User-Agent header for all outgoing requests (e.g. MyBot/1.0) |
URL_READER_USER_AGENT |
No | — | User-Agent for web_url_read only — overrides USER_AGENT for URL reads |
Interface-specific proxies take priority over global proxies for their respective tools.
| Variable | Required | Default | Description |
|---|---|---|---|
HTTP_PROXY / HTTPS_PROXY |
No | — | Global proxy for all traffic. Format: http://[user:pass@]host:port |
SEARCH_HTTP_PROXY / SEARCH_HTTPS_PROXY |
No | — | Proxy for searxng_web_search only |
URL_READER_HTTP_PROXY / URL_READER_HTTPS_PROXY |
No | — | Proxy for web_url_read only |
NO_PROXY |
No | — | Comma-separated bypass list (e.g. localhost,.internal,example.com) |
By default the server communicates over STDIO. Set MCP_HTTP_PORT to enable HTTP mode instead.
| Variable | Required | Default | Description |
|---|---|---|---|
MCP_HTTP_PORT |
No | — | Port number to enable HTTP transport (e.g. 3000) |
MCP_HTTP_HOST |
No | 127.0.0.1 |
Interface address to bind to. Defaults to localhost-only for security. Set 0.0.0.0 for all interfaces (required for Docker and remote deployments), or a specific IP. Works in pair with MCP_HTTP_PORT only. Breaking change from v1.2.1: previous default was 0.0.0.0. |
HTTP endpoints (when HTTP mode is active):
POST/GET/DELETE /mcp— MCP protocolGET /health— health check
Rate limiting is always active in HTTP mode to prevent resource exhaustion. Two separate limits protect different request types.
| Variable | Required | Default | Description |
|---|---|---|---|
MCP_RATE_WINDOW_MS |
No | 60000 |
Sliding window duration in milliseconds for all rate limits |
MCP_RATE_INIT_MAX |
No | 20 |
Max POST /mcp requests per window (applied to all POSTs, guards against session-init flooding) |
MCP_RATE_SESSION_MAX |
No | 300 |
Max GET/DELETE /mcp requests per window (per-session calls; intentionally generous for AI agents) |
Requests exceeding a limit receive HTTP 429 with a JSON-RPC error body (code: -32029). /health has a fixed limit of 60 requests per minute. Standard RateLimit-* headers are included on all responses.
The in-memory store is per-process; for horizontally scaled deployments replace it with a shared Redis store via express-rate-limit's store option.
Opt-in security layer for when you expose the HTTP transport on a network. Default HTTP behavior is unchanged — hardening must be explicitly enabled with MCP_HTTP_HARDEN=true.
| Variable | Required | Default | Description |
|---|---|---|---|
MCP_HTTP_HARDEN |
No | false |
Set to true to enable all hardening features |
MCP_HTTP_AUTH_TOKEN |
No | — | Required bearer token for all HTTP requests in hardened mode |
MCP_HTTP_ALLOWED_ORIGINS |
No | — | Comma-separated CORS origin allowlist (e.g. https://app.example.com) |
MCP_HTTP_ALLOWED_HOSTS |
No | — | Comma-separated DNS rebinding protection allowlist override |
MCP_HTTP_ALLOW_PRIVATE_URLS |
No | false |
Allow web_url_read to fetch internal/private URLs, including hostnames that DNS-resolve to private/internal addresses. Private URL reads are blocked by default in all modes. |
MCP_HTTP_EXPOSE_FULL_CONFIG |
No | false |
Expose full config details in /health response (for debugging) |
web_url_read blocks private/internal URLs by default in all transport modes. This includes localhost, loopback addresses, private IPv4 ranges, link-local addresses, 0.0.0.0/8, IPv6 loopback/ULA/link-local addresses, and IPv4-mapped IPv6 private addresses.
Redirects are also checked before they are followed. A public URL that redirects to a private/internal URL is blocked.
For direct URL-reader requests without a proxy, DNS answers are validated before connecting. A public-looking hostname that resolves to a private/internal address is blocked, and the connection is pinned to the validated DNS answer to prevent DNS rebinding between validation and connection.
When a URL-reader proxy is configured (URL_READER_HTTP_PROXY, URL_READER_HTTPS_PROXY, HTTP_PROXY, or HTTPS_PROXY), the proxy performs DNS resolution. Client-side DNS-answer validation cannot inspect proxied resolutions, so proxied deployments should rely on proxy, firewall, and egress controls.
URL_READ_MAX_CONTENT_LENGTH_BYTES is enforced while streaming the response body, including chunked responses and responses whose GET body is larger than the HEAD Content-Length value. The limit is measured after transparent response decompression.
Set MCP_HTTP_ALLOW_PRIVATE_URLS=true only when internal URL reads are intentional for your deployment. This also allows hostnames that DNS-resolve to private/internal addresses.
Complete MCP client configuration with every variable. Mix and match as needed — all optional variables can be used independently or together.
{
"mcpServers": {
"searxng": {
"command": "npx",
"args": ["-y", "mcp-searxng"],
"env": {
"SEARXNG_URL": "YOUR_SEARXNG_INSTANCE_URL",
"SEARXNG_FANOUT": "false",
"SEARXNG_TIMEOUT_MS": "10000",
"FETCH_TIMEOUT_MS": "10000",
"SEARXNG_LITE_TOOLS": "false",
"SEARXNG_DEFAULT_LANGUAGE": "en",
"SEARXNG_DEFAULT_SAFESEARCH": "0",
"SEARXNG_MAX_RESULTS": "10",
"SEARXNG_MAX_RESULT_CHARS": "500",
"SEARXNG_HTML_FALLBACK": "false",
"URL_READ_MAX_CHARS": "2000",
"URL_READ_MAX_CONTENT_LENGTH_BYTES": "5242880",
"CACHE_TTL_MS": "86400000",
"CACHE_MAX_ENTRIES": "500",
"AUTH_USERNAME": "your_username",
"AUTH_PASSWORD": "your_password",
"USER_AGENT": "MyBot/1.0",
"URL_READER_USER_AGENT": "Mozilla/5.0 (compatible; MyBot/1.0)",
"SEARCH_HTTP_PROXY": "http://search-proxy.company.com:8080",
"SEARCH_HTTPS_PROXY": "http://search-proxy.company.com:8080",
"URL_READER_HTTP_PROXY": "http://reader-proxy.company.com:8080",
"URL_READER_HTTPS_PROXY": "http://reader-proxy.company.com:8080",
"HTTP_PROXY": "http://global-proxy.company.com:8080",
"HTTPS_PROXY": "http://global-proxy.company.com:8080",
"NO_PROXY": "localhost,127.0.0.1,.local,.internal",
"MCP_HTTP_PORT": "3000",
"MCP_HTTP_HOST": "0.0.0.0",
"MCP_HTTP_HARDEN": "true",
"MCP_HTTP_AUTH_TOKEN": "replace-me",
"MCP_HTTP_ALLOWED_ORIGINS": "https://app.example.com",
"MCP_HTTP_ALLOWED_HOSTS": "app.example.com",
"MCP_HTTP_ALLOW_PRIVATE_URLS": "false",
"MCP_HTTP_EXPOSE_FULL_CONFIG": "false"
}
}
}
}