# mcp-searxng: a self-hosted SearXNG search server for Claude, Cursor and other MCP clients

> mcp-searxng is an MCP server that puts an operator-controlled SearXNG instance behind your AI assistant's search tool. It installs with npx or Docker, needs Node 22 or newer, and shifts the privacy question onto whoever runs the SearXNG instance.

**ihor-sokoliuk/mcp-searxng** — Private web search for AI assistants via SearXNG — supports Claude, Cursor, and any MCP client

- Repository: https://github.com/ihor-sokoliuk/mcp-searxng
- Website: https://www.npmjs.com/package/mcp-searxng
- Stars: 1,268 · Forks: 164
- Language: TypeScript
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/ihor-sokoliuk-mcp-searxng

## The gap mcp-searxng fills between an AI assistant and a search engine

An MCP client can call tools, but it cannot search the web unless something exposes a search tool to it. mcp-searxng is that something: a standalone Node.js process that speaks the Model Context Protocol on one side and the SearXNG API on the other. The README describes it as "a separate Node.js process that your AI assistant connects to for web search."

The audience is narrower than the topic list suggests. If you are content to let a vendor's search backend see every query your assistant issues, a hosted search MCP server is simpler. mcp-searxng exists for people who want the query to land on an instance they or a trusted operator control. The README is explicit that this is not anonymity: an operator-controlled instance can avoid trusting a third-party search operator, while a public instance receives the query and may log it. SearXNG and this integration, it states, do not by themselves provide anonymity. That sentence is the honest framing of the whole project, and it should shape who adopts it.

## How the server talks to SearXNG: failover, fan-out and caching

The server holds a list of SearXNG replicas in a single environment variable, SEARXNG_URL, separated by semicolons. By default searches fail over through that list in order. With SEARXNG_FANOUT set, the server queries all healthy replicas in parallel and merges the results. That is a real architectural choice, not a cosmetic one: failover keeps latency predictable and load low, while fan-out trades extra requests for broader result coverage when your replicas hit different engines.

Results are normalised before they reach the model. Text results surface SearXNG answers, corrections, suggestions and infoboxes ahead of the result list, so a client sees the engine's own summary text rather than only links. Output format is selectable per call with response_format, or set as an operator default through SEARXNG_DEFAULT_RESPONSE_FORMAT. A min_score filter drops low-relevance hits before they consume context.

Both search results and fetched URL content are cached in memory with a configurable TTL and least-frequently-used eviction. LFU is an interesting pick over LRU here: a query a model repeats often stays resident even if other one-off queries arrive in between. The trade-off is that a burst of distinct queries can evict a recently useful entry that LRU would have kept.

There is a separate URL reader tool, web_url_read, which converts fetched content to Markdown by content type, extracts bounded text from PDFs, and supports pagination, section filtering, paragraph ranges and heading extraction. It blocks private and internal URLs and redirects by default in all transport modes, which matters because a model can be induced to fetch an internal address.

## Installing mcp-searxng with npx and running a first search

The quickest path is npx. The README gives this configuration for a client such as claude_desktop_config.json, and the same shape works for other MCP clients that accept a command and arguments:

```json
{
  "mcpServers": {
    "searxng": {
      "command": "npx",
      "args": ["-y", "mcp-searxng"],
      "env": {
        "SEARXNG_URL": "YOUR_SEARXNG_INSTANCE_URL"
      }
    }
  }
}
```

Replace YOUR_SEARXNG_INSTANCE_URL with your instance, for example https://searxng.example.com. You can also list interchangeable replicas separated by semicolons, such as https://one.example.com;https://two.example.com. After restarting the client, the searxng server should appear in its MCP server list, and a search tool should be callable from a conversation.

The package requires Node 22 or newer, per the engines field in package.json, so check that before blaming the server for a startup failure.

Docker is the other route. The repository ships a compose file that reads the instance URL from the environment:

```yaml
services:
  mcp-searxng:
    image: isokoliuk/mcp-searxng:latest
    stdin_open: true
    environment:
      - SEARXNG_URL=${SEARXNG_URL:?Set SEARXNG_URL in the environment}
```

The :? syntax means the compose command fails immediately if SEARXNG_URL is unset, which is a better failure than a server that starts and silently cannot search. stdin_open is required because the server communicates over stdio in this mode. Optional measured CPU and memory limits live in docker-compose.resources.yml and are applied by layering the two files with -f.

## Where mcp-searxng is the wrong tool

The dependency is the limitation. mcp-searxng does not search anything by itself; it is a bridge to a SearXNG instance you must operate or select. Without a reachable instance, the server has nothing to call. Public instances are an option, but the README states plainly that a public instance receives the query and may log it, so the privacy argument weakens to the point of disappearing.

A second failure mode is instance configuration. SearXNG instances can reject format=json, which breaks the primary API path. The project offers an HTML fallback that parses results from the HTML page for exactly this case, but it is opt-in, and parsing HTML is inherently more fragile than reading a JSON response.

The browser solver path has its own caveats. For uncached URLs that pass static URL validation and a HEAD size preflight, the server can acquire a session from FlareSolverr, Byparr, or both, then replay the returned user-agent and scoped cookies through the URL reader. In dual-provider mode FlareSolverr is primary and Byparr is attempted only after a busy or transient-unavailable primary. The verification notes record that client cancellation stops local work promptly, but a remote browser may continue until its configured provider timeout after the HTTP client disconnects. That is a real cost on a shared solver instance.

Finally, the HTTP transport is optional and comes with hardening, rate limiting and bounded stateless compatibility. Running it that way is a deliberate deployment decision, not a default you inherit.

## How mcp-searxng differs from Brave, Exa and Firecrawl MCP servers

The README carries a capability comparison dated 2026-07-29 covering the official Brave, Exa and Firecrawl MCP servers. All four do web search and pagination. The differences are in the other rows: Exa and Firecrawl read URLs, Brave does not, and mcp-searxng does. Self-hosting is marked as supported only for mcp-searxng, with Firecrawl listed as partial. Free or no-API-key operation is also unique to mcp-searxng in that table.

The practical difference is where the query goes and who pays. Brave, Exa and Firecrawl are hosted services reached with a vendor API key. mcp-searxng has no vendor key requirement because you supply the search backend. If your constraint is that queries must not leave infrastructure you control, the hosted options cannot satisfy it regardless of features. If your constraint is that search must work without you running anything, mcp-searxng is the wrong shape entirely. The comparison is the project's own, so treat the row values as its claims rather than an independent audit.

## Maintenance, licensing and what upgrades cost

The repository is not archived, and the last push was on 2026-09-09, the same day as the v2.2.0 release. Releases in the current line are v2.2.0, v2.1.0 and v2.0.0, dated 2026-09-09, 2026-08-25 and 2026-08-21. The v2.0.0 to v2.2.0 span is short, which suggests feature work is landing quickly; it also means configuration surface can move between minor versions, so pin a version in production rather than tracking latest.

The licence is MIT, declared in package.json and shown as an MIT badge in the README. MIT permits commercial use and modification with the copyright notice retained; it provides no patent grant and no warranty. That is a general description of the licence text, not legal advice for your situation.

Upgrade cost is mostly environmental. The Dockerfile pins node:lts-alpine by digest in both the builder and release stages, runs npm ci --ignore-scripts --omit=dev, and drops to USER 1000. If you build your own image from that file, the digest pin means base-image updates are manual. The package requires Node 22 or newer, so a host on an older runtime needs upgrading before the server will run. There are also compose files for HTTP transport and for measured resource limits, which implies the maintainer expects deployments to tune those separately from the default stdio setup.

## Conclusion

Adopt mcp-searxng if you already run a SearXNG instance, or are willing to, and you want the same search tool inside Claude Desktop, Cursor, VS Code or OpenCode. Skip it if you have no instance to point at, if you need anonymity rather than query control, or if you want a hosted search API with a support contract. Before rolling it out, confirm your instance allows format=json, check that Node 22 or newer is available on the machine running the server, and decide whether SEARXNG_FANOUT matters for your replica set.

## FAQ

### What is an MCP server and what does mcp-searxng's server actually do?

MCP is the Model Context Protocol, and an MCP server exposes tools to an AI assistant over that protocol. mcp-searxng is a standalone Node.js process that connects to a SearXNG instance and gives clients web search, URL reading and search suggestions.

### What does MCP stand for in mcp-searxng?

MCP stands for Model Context Protocol. The README links to the protocol's introduction page and describes mcp-searxng as an MCP server that integrates the SearXNG API.

### Can I run mcp-searxng with Docker?

Yes. The repository includes a docker-compose.yml using the image isokoliuk/mcp-searxng:latest with stdin_open set to true, and it requires SEARXNG_URL to be set in the environment or the compose command fails.

### Does mcp-searxng need a paid search API key?

No. The README's capability table marks it as free and no-API-key, meaning the MCP server itself requires no paid search-vendor key. You still need to operate or select the underlying SearXNG instance.

### Can I point mcp-searxng at several SearXNG instances?

Yes. SEARXNG_URL accepts a semicolon-separated list of interchangeable replicas. Searches fail over through the list in order by default, or query all healthy replicas in parallel and merge results when SEARXNG_FANOUT is set.

## Sources

- [ihor-sokoliuk/mcp-searxng on GitHub](https://github.com/ihor-sokoliuk/mcp-searxng)
- [License: MIT](https://github.com/ihor-sokoliuk/mcp-searxng/blob/main/LICENSE)
- [Project website](https://www.npmjs.com/package/mcp-searxng)
- [README](https://github.com/ihor-sokoliuk/mcp-searxng/blob/main/README.md)
- [Releases](https://github.com/ihor-sokoliuk/mcp-searxng/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ihor-sokoliuk-mcp-searxng
