npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tadmstr/searxng-mcp

v3.3.0

Published

MCP server for SearXNG — private web search for Claude Code

Readme

searxng-mcp

Built with Claude Code CI License: MIT

An MCP server for private web search via a self-hosted SearXNG instance. Results are reranked by a local ML model, full-page content is fetched via Firecrawl, and an optional Ollama instance provides query expansion and LLM-synthesized summaries.

Designed for use with Claude Code and LibreChat agents that need web search without sending queries to a third-party search API.

Built with Claude Code using the multi-agent workflow from homelab-agent — the same platform that uses searxng-mcp in production for AI-assisted research.

Tools

| Tool | Description | Key Parameters | |------|-------------|----------------| | search | Search via SearXNG with local reranking. Fetches a wider result pool, reranks by relevance, returns top N. | query, num_results (1–20), category, time_range, domain_profile, expand | | search_and_fetch | Search, rerank, then fetch full content of the top result(s) using the fetch cascade (Firecrawl → Crawl4AI → raw HTTP). | query, category, time_range, fetch_count (1–3), domain_profile, expand | | search_and_summarize | Search, fetch top results, then synthesize a summary with citations via Ollama (qwen3:14b). Falls back to raw fetched content if Ollama is unavailable. | query, fetch_count (1–5), category, time_range, domain_profile, expand | | fetch_url | Fetch and extract readable markdown from any public URL. GitHub URLs use the GitHub API; all others use the fetch cascade (Firecrawl → Crawl4AI → raw HTTP). Truncated to 8,000 characters. | url, domain_profile | | clear_cache | Purge the search cache, fetch cache, or both. Useful when researching fast-moving topics where cached results may be stale. | target (search, fetch, all) |

Parameters

categorygeneral (default), news, it, science

time_rangeday, week, month, year — limits results by publication date. Omit for all-time results.

fetch_count — number of top reranked results to fetch full content for (default 1, max 3 for search_and_fetch; default 3, max 5 for search_and_summarize).

domain_profile — apply a named domain filter profile: homelab (surfaces self-hosted/Linux docs) or dev (surfaces Stack Overflow, MDN, npm). Omit for default filters.

expand — when true, rewrites the query via Ollama (qwen3:4b) before searching to improve recall. Requires OLLAMA_URL. Defaults to the EXPAND_QUERIES env var value.

Architecture

MCP client (stdio)
      │
      ▼
  searxng-mcp ──────────────→ Valkey ($VALKEY_URL)        → result cache (search 1h, fetch 24h)
      │
      ├── expand (optional) →  Ollama ($OLLAMA_URL)        → rewritten query (qwen3:4b)
      ├── search ───────────→ SearXNG ($SEARXNG_URL)      → raw results
      ├── rerank ───────────→ Reranker ($RERANKER_URL)    → ranked results
      │                       (fallback: SearXNG order if reranker unavailable)
      ├── fetch content ────┬→ GitHub API (github.com)    → markdown
      │                     ├→ Firecrawl ($FIRECRAWL_URL) → page markdown (tier 1)
      │                     ├→ Crawl4AI ($CRAWL4AI_URL)  → page markdown (tier 2, optional)
      │                     └→ Raw HTTP fetch             → page text (tier 3 fallback)
      └── summarize (opt.) →  Ollama ($OLLAMA_URL)        → synthesized summary (qwen3:14b)

Fetch routing

SearXNG and Firecrawl are required. Crawl4AI, Valkey, Ollama, and the reranker are optional — the server degrades gracefully when any of these are unavailable.

Transport

stdio (compatible with Claude Code MCP plugin and LibreChat stdio config).

Prerequisites

  • Node.js 20+
  • pnpm (or npm)
  • A running SearXNG instance
  • A running Firecrawl instance
  • A running reranker exposing a Jina-compatible /v1/rerank endpoint (optional)
  • A running Valkey or Redis-compatible instance (optional, for result caching)
  • A running Ollama instance with qwen3:4b and/or qwen3:14b pulled (optional, for query expansion and summarization)

SearXNG

SearXNG must have JSON output format enabled. In settings.yml:

search:
  formats:
    - html
    - json

Reranker

The reranker must expose a Jina-compatible /v1/rerank endpoint. A lightweight FlashRank wrapper works well — see the docker/reranker/ reference in homelab-agent.

Firecrawl

Any Firecrawl-compatible instance works. The local firecrawl-simple deployment is sufficient. Set FIRECRAWL_API_KEY if your instance requires authentication (defaults to placeholder-local for local deployments that skip auth).

Crawl4AI

Crawl4AI is an optional second-tier fetch fallback used when Firecrawl returns empty content (bot-blocked pages, JS-heavy sites). Set CRAWL4AI_URL to enable it. If unset, the cascade skips to raw HTTP fetch.

docker run -d -p 11235:11235 unclecode/crawl4ai:0.8.6

If your instance requires API token authentication, set CRAWL4AI_API_TOKEN.

Valkey / Redis

Any Redis-compatible instance. Valkey is recommended. Search results are cached for 1 hour; fetched pages for 24 hours. If unavailable, the server operates without caching.

Ollama

Required for expand and search_and_summarize. Pull the required models:

ollama pull qwen3:4b   # query expansion
ollama pull qwen3:14b  # summarization

Set think: false behavior is handled automatically — no extra Ollama configuration needed.

Configuration

All service URLs are configurable via environment variables.

| Variable | Default | Description | |----------|---------|-------------| | SEARXNG_URL | http://localhost:8081 | SearXNG instance URL | | FIRECRAWL_URL | http://localhost:3002 | Firecrawl instance URL | | RERANKER_URL | http://localhost:8787 | Reranker instance URL | | FIRECRAWL_API_KEY | placeholder-local | Firecrawl API key (if required) | | GITHUB_TOKEN | (unset) | GitHub personal access token — increases rate limit from 60 to 5,000 req/hour | | OLLAMA_URL | (unset) | Ollama API base URL — required for expand and search_and_summarize | | VALKEY_URL | redis://localhost:6381 | Redis-compatible URL — enables result caching. Server degrades gracefully if unavailable. | | CACHE_TTL_SECONDS | 3600 | Search result cache TTL in seconds | | FETCH_CACHE_TTL_SECONDS | 86400 | Fetched page cache TTL in seconds | | EXPAND_QUERIES | false | Set to true to enable query expansion globally | | CRAWL4AI_URL | (unset) | Crawl4AI instance URL — enables second-tier fetch fallback when Firecrawl fails | | CRAWL4AI_API_TOKEN | (unset) | Optional Bearer token for Crawl4AI instances with API token protection |

Build

pnpm install
pnpm build

Output: build/src/index.js

MCP Client Configuration

Claude Code (CLI)

The recommended approach uses claude mcp add-json to register the server with full env var support:

claude mcp add-json searxng --scope user '{
  "command": "node",
  "args": ["/path/to/searxng-mcp/build/src/index.js"],
  "env": {
    "SEARXNG_URL": "http://localhost:8081",
    "FIRECRAWL_URL": "http://localhost:3002",
    "RERANKER_URL": "http://localhost:8787",
    "OLLAMA_URL": "http://localhost:11434",
    "VALKEY_URL": "redis://localhost:6379",
    "CACHE_TTL_SECONDS": "3600",
    "FETCH_CACHE_TTL_SECONDS": "86400",
    "EXPAND_QUERIES": "false",
    "CRAWL4AI_URL": "http://localhost:11235"
  }
}'

This writes to ~/.claude.json. Do not add searxng to ~/.claude/settings.json — that file is not used for MCP env var injection in Claude Code.

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "searxng": {
      "command": "node",
      "args": ["/path/to/searxng-mcp/build/src/index.js"],
      "env": {
        "SEARXNG_URL": "http://localhost:8081",
        "FIRECRAWL_URL": "http://localhost:3002",
        "RERANKER_URL": "http://localhost:8787",
        "OLLAMA_URL": "http://localhost:11434",
        "VALKEY_URL": "redis://localhost:6379",
        "CRAWL4AI_URL": "http://localhost:11235"
      }
    }
  }
}

LibreChat (librechat.yaml)

mcpServers:
  searxng:
    type: stdio
    command: node
    args:
      - /path/to/searxng-mcp/build/src/index.js
    env:
      SEARXNG_URL: http://localhost:8081
      FIRECRAWL_URL: http://localhost:3002
      RERANKER_URL: http://localhost:8787
      OLLAMA_URL: http://localhost:11434
      VALKEY_URL: redis://localhost:6379
      CRAWL4AI_URL: http://localhost:11235

GitHub URLs

github.com URLs are handled natively without Firecrawl:

  • Repo root (github.com/owner/repo) — fetches the README via the GitHub API
  • File blob (github.com/owner/repo/blob/branch/path/to/file) — fetches raw content from raw.githubusercontent.com

Unauthenticated requests are rate-limited to 60/hour. Set GITHUB_TOKEN to raise this to 5,000/hour.

Security

URL safety

The fetch_url and search_and_fetch tools enforce a URL allowlist — private/internal IP ranges (10.x, 192.168.x, 172.16-31.x, localhost, 127.x), IPv6 private ranges (::1, fc00::/7, fe80::/10), and non-HTTP protocols are blocked. This prevents the server from being used as an SSRF proxy into your local network.

Redirect protection

HTTP redirects in raw fetch requests are blocked to prevent SSRF bypass via redirect chains to internal addresses.

Dependency auditing

CI runs pnpm audit on every push. The lockfile (pnpm-lock.yaml) is committed for reproducible, auditable builds.

Credential handling

No credentials are stored or logged by the server. API keys (FIRECRAWL_API_KEY, GITHUB_TOKEN, CRAWL4AI_API_TOKEN) are read from environment variables and used only in outbound requests to their respective services.

Input validation

Environment variables are validated at startup — RERANK_RECENCY_WEIGHT warns on NaN, negative, or >1.0 values. Numeric tool parameters use z.coerce.number() with range constraints.

License

MIT