searxng-mcp
Connects an MCP server to a SearXNG metasearch instance, letting agents run privacy-friendly web, news, image and video searches across the instance's engines, get autocomplete suggestions, inspect instance categories/enabled engines, and fetch/extract clean readable page content with structural filtering (headers, footers, nav, sidebars, comments, and noise like cookie banners and ads removed by default and re-includable per call).
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@searxng-mcpsearch the web for recent news about AI regulation in Europe"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
searxng-mcp
MCP (Model Context Protocol) server that plugs a SearXNG metasearch instance into AI agents: privacy-friendly web, news, image and video search, plus clean page content extraction with structural filtering (no headers, footers, navbars or sidebars unless the agent asks for them).
Why
Metasearch — one query fans out to many engines (Google, Bing, Brave, DuckDuckGo, Wikipedia, news outlets, ...) while your identity stays with your instance.
Bring your own instance — works with any SearXNG deployment (local Docker, LAN server, public instance). The only configuration is the instance URL.
Agent-friendly output — results are rendered as compact structured text, not raw HTML.
Content extraction with filtering — the agent can fetch any page and decide it does not need the site chrome: headers, footers, navigation menus, sidebars, cookie banners, ads and comment sections are stripped by default and can be re-included per call.
Related MCP server: SearXNG MCP Server
Tools
Tool | What it does |
| General search on any SearXNG category, with language, pagination, time range, SafeSearch, engine selection and domain filters |
| News search ( |
| Image search — includes full image URL + thumbnail |
| Video search — includes page URL + thumbnail |
| Query suggestions from the instance's autocomplete provider |
| Instance overview: categories + enabled engines grouped by category |
| Fetch a page and extract readable text with structural filtering |
Requirements
Node.js >= 18 (or Bun >= 1.x) on the machine running the MCP server
A running SearXNG instance with the JSON format enabled
Enable JSON output on your SearXNG instance
The API returns 403 unless json is in search.formats:
# settings.yml
search:
formats:
- html
- jsonRestart SearXNG after editing. Verify with:
curl 'http://localhost:8888/search?q=test&format=json' | head -c 200Installation
npm (global)
npm install -g @aplix39/searxng-mcp
searxng-mcp --url http://localhost:8888npx (zero install, run on demand)
npx --yes @aplix39/searxng-mcp --url http://localhost:8888Bun (global)
bun install -g @aplix39/searxng-mcp
searxng-mcp --url http://localhost:8888Or straight from GitHub (the dist/ bundle is committed, no build step needed):
bun install -g github:STIFLEUR390/searxng-mcpFrom GitHub with npm
npm does not reliably link global binaries from git dependencies (npm 10 keeps the package as a symlink to an ephemeral cache clone), so pack the repo first, then install the tarball:
npm pack github:STIFLEUR390/searxng-mcp
npm install -g ./aplix39-searxng-mcp-*.tgzFrom source
git clone https://github.com/STIFLEUR390/searxng-mcp.git
cd searxng-mcp
bun install
bun run build # produces the self-contained dist/index.js
node dist/index.js --url http://localhost:8888All install flows (npm registry, npx, bun registry, bun GitHub, npm pack+tgz, source) are validated against the published v1.0.0 release, including a Node 18 runtime check.
Configuration
The SearXNG URL is resolved in this order:
Precedence | Source | Example |
1 |
|
|
2 |
|
|
3 | Built-in default |
|
Trailing slashes and a pasted /search suffix are normalized automatically. If the host is
localhost and the connection fails (Node resolves it to IPv6 ::1 first), the server retries
once on 127.0.0.1.
Environment variables:
Variable | Default | Description |
|
| Base URL of the SearXNG instance (see precedence above) |
|
| Per-request timeout in ms (min 500, max 300000) — raise it for slow instances |
CLI flags: --help, --version.
Client setup
Claude Code
claude mcp add searxng --env SEARXNG_URL=http://localhost:8888 -- npx --yes @aplix39/searxng-mcpClaude Desktop / Cursor / generic MCP client
{
"mcpServers": {
"searxng": {
"command": "npx",
"args": ["--yes", "@aplix39/searxng-mcp"],
"env": { "SEARXNG_URL": "http://localhost:8888" }
}
}
}With a global install, command can simply be searxng-mcp with no args (the default URL is
http://localhost:8888), or pass --url in args.
Tools reference
searxng_search
Parameter | Type | Description |
| string (required) | Search query, engine syntax supported |
| string[] | e.g. |
| string | Language code: |
| int 1–50 | Results page |
|
| Restrict to recent results |
| int 0–2 | 0=off, 1=moderate, 2=strict |
| string[] | Restrict to engines by name/shortcut, e.g. |
| int 1–50 | Max results rendered (default 10) |
| string[] | Keep only results on these domains |
| string[] | Drop results on these domains |
Output: numbered results (title, URL, snippet, engines, category, publication date), plus answers, infoboxes, corrections, related searches and unresponsive-engine notes when present.
searxng_search_news, searxng_search_images and searxng_search_videos are the same tool
pinned to their category (images/videos also surface image + thumbnail URLs).
searxng_autocomplete
Parameter | Type | Description |
| string (required) | Partial query |
| string | Language code for suggestions, e.g. |
searxng_config
Parameter | Type | Default | Description |
| bool |
| Set |
Returns categories and enabled engines grouped by category — useful to discover what the instance can search before picking categories/engines.
searxng_extract_content
Fetches a page (typically a URL found with the search tools) and returns clean, readable text.
Parameter | Type | Default | Description |
| string (required) | — | Absolute http(s) URL |
| bool |
| Keep site header/banner blocks |
| bool |
| Keep site footer blocks |
| bool |
| Keep menus, topbars, breadcrumbs |
| bool |
| Keep sidebars / widgets |
| bool |
| Keep comment sections |
| bool |
| Render links as markdown |
| bool |
| Render images as markdown |
| bool |
| Extract only the main content area ( |
| string | — | Advanced: extract only nodes matching this CSS selector |
| int 500–200000 |
| Truncate the content to this many characters |
| int ≥ 0 |
| Start the output window at this character offset (page through long content with |
| bool |
| Return only the heading outline (h1–h6) instead of the full text |
HTML pages go through the structural filtering described below. JSON bodies are returned
pretty-printed in a fenced ```json block, other text/* bodies as fenced text; binary files
(PDF, images, archives) are refused with an explicit error.
Always removed regardless of options: script, style, noscript, iframe, forms, and noise
banners (cookies, consent, popups, ads, newsletter boxes). The response reports which sections
were removed so the agent can re-include them on the next call.
Sections kept via include_* that live outside the main content area (nav/header/footer usually
sit outside <main>) are appended to the output, so the opt-in is honored with the default
content_only too. With selector, extraction stays exact (nothing is appended).
Example: the agent found a page but only wants the article body:
{ "name": "searxng_extract_content", "arguments": { "url": "https://example.org/post/1" } }It needs the footer legal notice too:
{
"name": "searxng_extract_content",
"arguments": { "url": "https://example.org/post/1", "include_footer": true }
}Example session
User: what are the latest news about SearXNG?
Agent →
searxng_search_news { "q": "searxng", "time_range": "month", "limit": 5 }User: open the first result and summarize it
Agent →
searxng_extract_content { "url": "…" }(header/footer/nav already filtered out)
Troubleshooting
Symptom | Cause & fix |
| JSON format disabled → add |
| Instance rate limiter ( |
| Instance not running, wrong URL, or IPv6/IPv4 mismatch — the server already retries |
| The extractor handles HTML, JSON and plain text; binary files (PDF, images) are refused |
Empty results | Some engines may be down on the instance — check |
Development
bun install # install dependencies
bun run dev # run the server from source (TypeScript)
bun test # 106 unit + integration tests (bun:test)
bunx tsc --noEmit # strict typecheck
bun run build # bundle to dist/index.js (node target)Project layout:
index.ts # CLI entry point (stdio MCP server)
src/config.ts # CLI/env parsing, URL normalization
src/client.ts # SearXNG HTTP client (/search, /autocompleter, /config)
src/extract.ts # HTML fetch + structural filtering + text rendering
src/format.ts # SearXNG response → agent-friendly text
src/server.ts # MCP tool registration
src/types.ts # SearXNG API types
test/ # bun:test suitesPublishing to npm
Note: the unscoped name
searxng-mcpis already taken on npm by an unrelated project, so this package uses the scoped name@aplix39/searxng-mcp(scope = the maintainer's npm username). Nothing changes for GitHub installs, and the CLI binary stayssearxng-mcp.
The package is published: npmjs.com/package/@aplix39/searxng-mcp
(latest: v1.0.4, public, MIT). prepublishOnly runs typecheck + 106 tests + build on every
publish; the published v1.0.0 tarball was validated byte-identical to the committed dist/ bundle,
and the published v1.0.3/v1.0.4 tarballs were re-validated the same way (shasum match, --version reporting
the published version, isolated npm i + MCP handshake). npm version now rebuilds dist/ too, so the tag, the
commit and the published bundle always carry the same version string.
Future releases:
npm version patch # bumps package.json AND src/version.ts (auto-sync script),
# commits + tags — never bump package.json by hand
git push --follow-tags
npm publish --access public # with a token configured: no interactive 2FA promptTo publish without confirming 2FA in the browser every time, create a token on npmjs.com
(avatar → Access Tokens → Generate New Token → Granular Access Token, packages: @aplix39
read-and-write; copy it once) and reference it through an environment variable so it never sits
in plaintext in ~/.npmrc:
export NPM_TOKEN=npm_xxx # persist in ~/.bashrc or ~/.zshrc
npm config set '//registry.npmjs.org/:_authToken' '${NPM_TOKEN}'
npm whoami # must print the npm username owning the scopeIf npm still prompts for a 2FA code with a granular token on your account, create a classic
Automation token instead (same npm config set line): it is designed to bypass publish 2FA.
Keep account 2FA enabled; tokens are expirable and revocable from the same Access Tokens page.
License
MIT © STIFLEUR390
This server cannot be deployed
Maintenance
Related MCP Connectors
Google search, news, maps, scholar and public webpages for AI agents, with Markdown results.
Web search, agentic search, news, page retrieval, sitemaps, and trending topics through Search1API.
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Fetch pages as markdown, search web and news, extract structured data. For AI agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to perform privacy-respecting web searches through SearXNG, with support for multiple search engines, categories, and advanced filtering options.153 npm27MIT
- AlicenseAqualityDmaintenanceEnables web search, image search, and news search through a self-hosted SearXNG instance. Provides privacy-focused meta-search capabilities aggregating results from multiple search engines.3153 npm1MIT
- FlicenseAqualityDmaintenanceEnables privacy-respecting web, image, video, and news searches through SearxNG metasearch engine, with options for URL fetching and time filtering.594 PyPI-
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to perform web searches and page fetching/crawling through self-hosted SearXNG and Crawl4AI, without depending on commercial search or scraping APIs.-