This guide assumes that you already operate a SearXNG service. mcp-searxng connects to that service; it does not install SearXNG or read SearXNG's private configuration. The examples below use non-secret placeholders. Adapt them to your deployment and apply changes with the normal reload, restart, or rollout procedure for your packaging or orchestrator.
| Concern | SearXNG | mcp-searxng | Shared boundary |
|---|---|---|---|
| Deployment and capabilities | Runs the metasearch service and exposes its configured formats, categories, providers, locales, and plugins. | Consumes the public /search and /config endpoints. |
A capability must exist upstream before an MCP request can rely on it. |
| Request construction | Applies server defaults and forwards supported filters to upstream providers. | Initially builds upstream search requests with format=json, plus caller or operator defaults. |
Language, safe search, categories, and engine filters can be set at both layers. |
| Results | Produces answers, results, suggestions, corrections, and provider error metadata. | Filters, limits, formats, deduplicates, and caches returned data. | Poor or empty output can originate upstream or from MCP-side filters, limits, or cache state. |
| Availability | Owns its process, storage, provider connectivity, and local recovery. | Selects configured replicas and performs ordered failover or optional fan-out. | Timeouts and partial failures must be diagnosed at both layers. |
| Network security | Owns ingress TLS, any front-end authentication, the limiter, Valkey, and reverse-proxy trust. | Owns MCP transport security, outbound proxy selection, credentials used for SearXNG, and Node.js CA trust. | Authentication, TLS, forwarded client identity, egress policy, and rate limiting require compatible settings on both sides. |
The two output controls have different jobs. format=json requests upstream SearXNG JSON.
response_format only controls the MCP-returned payload.
response_format does not enable upstream SearXNG JSON.
Keep the operator overlay small and inherit maintained defaults:
use_default_settings: true
search:
safe_search: 1
default_lang: "en"
formats:
- html
- json
server:
secret_key: "replace-with-a-generated-secret"
base_url: "https://search.example.com/"
limiter: true
valkey:
url: "valkey://valkey:6379/0"Store this as the deployment's SearXNG settings overlay, commonly
/etc/searxng/settings.yml. Generate a unique server.secret_key and inject it
through the secret mechanism supported by your deployment; the literal
placeholder is not safe for service use. server.base_url, the language, the
safe-search level, and the Valkey address are deployment decisions. The Valkey
hostname must resolve on the network where SearXNG runs.
The search.formats list must contain json because mcp-searxng uses JSON as
its primary search path. When SEARXNG_HTML_FALLBACK=true, a denied or
non-JSON response may be retried without format=json. Keeping html also
preserves the ordinary browser interface.
The language and safe-search values are defaults, not guarantees: a caller can
override them, and an upstream provider may not support every filter.
With use_default_settings: true, SearXNG merges the local overlay with its
maintained defaults. Entries under engines are merged by the exact name
field, so an override must match the configured name exactly.
disabled: true keeps an entry available for a user to activate, while
inactive: true removes it from the available settings surface. Some entries
that require credentials start inactive until their required configuration is
present. A single entry can belong to multiple categories, and each provider
can differ in language, safe-search, paging, and time-range support.
Treat the inventory as deployment-specific. Do not copy a static list from this guide. Inspect the active SearXNG preferences and public capability response, then make targeted overrides based on the service's purpose, provider terms, and observed health.
An Internet-facing SearXNG service needs deliberate protection:
- Set
server.limiter: true. - Confirm that SearXNG can connect to the configured Valkey database.
- Forward the real client identity through the reverse proxy as documented by SearXNG.
- Keep
trusted_proxieslimited to the proxy hops that actually terminate traffic for the service.
server.public_instance: true activates public-instance features but does not
turn on the limiter by itself. Incorrect forwarded headers can collapse many
clients into one identity or allow spoofed identities. An overly broad
trusted_proxies list weakens that boundary.
Terminate TLS with a valid certificate at the intended ingress. If a front-end
proxy provides HTTP Basic authentication, mcp-searxng must send credentials for
that endpoint. The SearXNG server.secret_key is a separate cryptographic
secret and is not an HTTP authentication password.
Follow the official limiter documentation and the proxy example matching your ingress, such as NGINX or Apache. Also apply the mcp-searxng security policy and deployment guidance.
Run these checks once after a configuration change, at low rate, from a host that follows the same authentication, DNS, proxy, and TLS path as mcp-searxng:
curl --fail-with-body --silent --show-error \
"https://search.example.com/config"
curl --fail-with-body --silent --show-error --get \
"https://search.example.com/search" \
--data-urlencode "q=operator verification" \
--data-urlencode "format=json"The first response inventories public categories, configured entries,
defaults, locales, and plugins. A successful response from
https://search.example.com/config does not prove that JSON search is enabled;
only the second request verifies the JSON path. Require an HTTP success status
and a parseable JSON body. Do not treat an HTML error page as JSON.
Interpret failures conservatively:
- HTTP 401 points to missing or rejected front-end credentials.
- HTTP 403 means that the requested capability was denied somewhere in the request path. It does not identify one specific setting by itself.
- HTTP 429 means stop and back off. Do not bypass or load-test the protection.
- HTTP 5xx points to SearXNG, a reverse proxy, or an upstream dependency.
- A successful response can still report partial provider degradation; inspect its error metadata before declaring the search path healthy.
For one controlled service, set one base URL:
SEARXNG_URL=https://search.example.com
SEARXNG_FANOUT=false
For interchangeable controlled replicas, separate base URLs with semicolons:
SEARXNG_URL=https://search-a.example.com;https://search-b.example.com
SEARXNG_FANOUT=false
The default mode tries replicas in order. A hard failure is recorded for cooldown; an empty successful response can lead to the next replica without marking the first one unhealthy. Only group services whose policies, credentials, capabilities, and expected data are interchangeable.
SEARXNG_FANOUT=true queries all healthy replicas in parallel, deduplicates by
canonical URL, and merges results. It can improve availability or coverage, but
it multiplies request load and can reach upstream limits sooner. Enable it only
after accounting for capacity, quotas, latency, and privacy at every replica.
The most relevant existing controls are:
| Setting | Operator effect |
|---|---|
SEARXNG_URL |
One base URL or a semicolon-separated replica set. URL userinfo can carry per-replica HTTP Basic credentials. |
SEARXNG_FANOUT |
Chooses ordered failover or parallel fan-out. |
AUTH_USERNAME, AUTH_PASSWORD |
Legacy global Basic Auth fallback only when a URL entry has no userinfo. |
SEARXNG_TIMEOUT_MS |
Bounds each SearXNG search response wait; default 10000. |
SEARXNG_DEFAULT_LANGUAGE |
Supplies the MCP request language when the caller omits it; default all. |
SEARXNG_DEFAULT_SAFESEARCH |
Supplies safe search when the caller omits it; otherwise the instance default applies. |
SEARXNG_MAX_RESULTS, SEARXNG_MAX_RESULT_CHARS |
Apply operator ceilings to returned result count and snippet length. |
SEARCH_CACHE_TTL_MS, SEARCH_CACHE_MAX_ENTRIES |
Control the per-process in-memory search cache; defaults are 86400000 and 200. |
SEARXNG_HTML_FALLBACK |
Optionally retries certain denied, missing, or non-JSON responses as HTML with reduced metadata; default false. |
SEARCH_USER_AGENT, USER_AGENT |
Set the search-specific identity or its global fallback. |
SEARCH_HTTP_PROXY, SEARCH_HTTPS_PROXY |
Override the global HTTP_PROXY and HTTPS_PROXY for SearXNG traffic. |
NO_PROXY |
Bypasses proxying for explicitly listed destinations. |
NODE_EXTRA_CA_CERTS |
Adds a PEM CA bundle to Node.js trust when the deployment requires it. |
Keep credentials, TLS trust, and egress rules separate for the SearXNG service and the MCP service. The complete variable reference, including URL-reader and HTTP transport settings, is in CONFIGURATION.md.
Invoke searxng_instance_info after direct verification. With
includeEngines=true, it reports enabled names; includeDisabled=true adds
disabled names; category narrows the view; and refresh=true bypasses the
process capability cache.
For multiple replicas:
categories.commonandengines.common.enabledare the intersection across reachable replicas and are the safest filter choices for consistent results.categories.availableandengines.available.enabledare the union and can work on only part of the replica set.- Reachable and unreachable replica summaries expose capability drift without revealing URL credentials.
- Defaults, locales, and plugins come from the primary reachable replica and can differ elsewhere.
The tool aggregates the public capability response. It cannot prove JSON support, reveal secrets, show private settings, or certify provider health. Compare it with the direct JSON search instead of treating it as a complete configuration dump.
STDIO is the simplest transport when the MCP server and client run in the same local trust boundary. When MCP HTTP transport is reachable over a network, follow Hardened HTTP Mode and the public HTTP deployment guidance. Configure authentication, origin checks, trusted proxy handling, rate limits, and TLS at that MCP boundary as well as at SearXNG.
Outbound proxy settings do not secure inbound MCP traffic. Likewise, SearXNG's limiter does not rate-limit the MCP HTTP endpoint. Each layer needs its own narrowly scoped controls.
Work in this order so cache or replica behavior does not hide the failing layer:
- HTTP status: Repeat the two direct low-rate checks. Resolve authentication, denial, throttling, or server errors before changing MCP filters.
- Invalid JSON: Confirm that
search.formatsstill includesjson, that the search request succeeds, and that a proxy is not replacing the body with HTML.SEARXNG_HTML_FALLBACKis a compatibility measure, not proof of a healthy JSON API. - Partial degradation: Inspect the JSON error metadata and SearXNG logs. A useful result set can coexist with unavailable providers.
- Empty or poor results: Compare the same query directly and through
searxng_web_search. Repeat without optional category, engine, language, time, safe-search, score, or result-count filters to isolate the constraint. - Capability drift: Call
searxng_instance_infowithrefresh=trueand compare its inventory with the direct capability response after SearXNG configuration changes. - Replica differences: Run the direct checks against each configured base URL. Compare common and available capability sets before relying on a replica-specific filter.
- Timeouts: Compare SearXNG provider timeouts, reverse-proxy timeouts, and
SEARXNG_TIMEOUT_MS. Increasing only the outer timeout cannot repair an upstream denial or broken dependency. - Cache effects: Search results are cached in each MCP process. A repeated
request can reflect earlier data until
SEARCH_CACHE_TTL_MSexpires. Capability refresh does not clear the search-result cache. If an intentional process restart is needed, perform it through the deployment's normal controlled procedure.