Atlas / MCP servers / ihor-sokoliuk / SearXNG

SearXNGSAFE

mcp/ihor-sokoliuk/searxng

Private web search for AI assistants via SearXNG — supports Claude, Cursor, and any MCP client

Verdict
SAFE
Grade
B
Trust score
86 /100
Exposed tools
4 4r · 0w · 0d
Transport
stdio · streamable-http
License
MIT
Stars
1,260
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Privacy-respecting web search for AI assistants — use an operator-controlled or trusted SearXNG instance with Claude, Cursor, and more.

[](https://github.com/ihor-sokoliuk/mcp-searxng/stargazers) [](https://www.npmjs.com/package/mcp-searxng) [](https://www.npmjs.com/package/mcp-searxng) [](https://hub.docker.com/r/isokoliuk/mcp-searxng) [](LICENSE) [](https://scorecard.dev/viewer/?uri=github.com/ihor-sokoliuk/mcp-searxng) [](https://www.bestpractices.dev/projects/13143) [](https://glama.ai/mcp/servers/ihor-sokoliuk/mcp-searxng) [](https://github.com/mcp/ihor-sokoliuk/mcp-searxng)

An MCP server that integrates the SearXNG API, giving AI assistants web search capabilities.

✨ Featured in the GitHub MCP Registry.

Quick Start

You need an existing SearXNG instance with JSON search enabled. This project connects an MCP client to SearXNG; it does not install SearXNG. Use an instance you operate or

Read from source at commit 9f1716c8a2dbOBSERVED · 2026-09-25
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (npm)
claude mcp add mcp-searxng --env SEARXNG_URL=${SEARXNG_URL} --env AUTH_USERNAME=${AUTH_USERNAME} --env AUTH_PASSWORD=${AUTH_PASSWORD} -- npx -y [email protected]
03

Exposed tools (4)

4 read · 0 write · 0 destructive.

ToolRiskDescription
searxng_instance_inforeadDiscovers capabilities from all reachable configured SearXNG instances via /config, including categories.common/available, engines.common/available, defaults, locales, and plugins.
searxng_search_suggestionsreadReturns autocomplete suggestions from the configured SearXNG instance.
searxng_web_searchreadSearches the web using SearXNG and returns a list of results, each with a title, URL, and content snippet.
web_url_readreadFetches a URL and returns readable content as markdown.
04

Trust audit

SAFEgrade B · trust 86/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
not all pinned
Secrets in source
none-found

Findings (23)

MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
scripts/verify-packed-consumer.mjs:171
'JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFszIDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAyIDA
LOWInventory / provenance · inv.hidden_file · CWE-1104
.env.e2e.example
.env.e2e.example
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
__tests__/e2e/http-transport.e2e.ts:9
import { packageVersion } from '../../src/version.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
__tests__/fuzz/search-params.fuzz.ts:4
import { isWebUrlReadArgs } from "../../src/index.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
__tests__/fuzz/search-params.fuzz.ts:5
import { isSearXNGWebSearchArgs } from "../../src/types.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
__tests__/helpers/mock-fetch.ts:7
import { searchCache } from '../../src/search-cache.js';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
__tests__/helpers/mock-fetch.ts:8
import { setSearxngFetchForTesting } from '../../src/proxy.js';
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
CHANGELOG.md:336
- **DNS-resolved private-address SSRF in `web_url_read` blocked (GHSA-mrvx-jmjw-vggc):** The URL reader previously validated only the literal hostname string, so a public-looking hostname that DNS-res
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
__tests__/unit/url-reader.test.ts:2371
'metadata.example': [{ address: '169.254.169.254', family: 4 }],
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
__tests__/unit/url-security.test.ts:65
assert.equal(isPrivateIpv4('169.254.169.254'), true);
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
__tests__/unit/url-security.test.ts:95
'0.0.0.0', '10.0.0.1', '100.64.0.1', '127.0.0.1', '169.254.169.254',
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
CONFIGURATION.md:471
Every present `Origin` on `/mcp` is validated in all modes; an absent `Origin` remains valid for non-browser clients. In non-hardened mode, an unset `MCP_HTTP_ALLOWED_ORIGINS` defaults to the exact HT
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
SECURITY.md:210
When an `/mcp` request includes an `Origin`, the server validates it against the applicable allowlist in hardened and non-hardened modes; requests without `Origin` follow the accepted non-browser path
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
__tests__/e2e/browser-solver.e2e.ts:38
url: `http://127.0.0.1:${address.port}`,
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
__tests__/e2e/helpers/spawn-server.ts:120
SEARXNG_URL: 'http://127.0.0.1:1',
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
__tests__/e2e/helpers/spawn-server.ts:252
return { child, url: new URL(`http://127.0.0.1:${port}/mcp`), output, close: createChildCloser(child, output) };
LOWObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
__tests__/helpers/pdf-fixtures.ts:49
"JVBERi0xLjMKJeLjz9MKMSAwIG9iago8PAovUHJvZHVjZXIgPDM1YzY5Y2I1ZTA+Cj4+CmVuZG9iagoyIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovQ291bnQgMQovS2lkcyBbIDQgMCBSIF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1R5cGUgL0NhdGFsb2cKL1BhZ2V
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@types/cors, @types/express, cors, express, node-html-markdown, @types/supertest, cross-env, eslint-plugin-security
Why it matters. 10 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:102
- **Modern MCP protocol serving with the official split SDK v2 packages:** HTTP and STDIO now support the modern `2026-07-28` protocol while retaining the documented legacy transports, tool and resour
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:116
- **Bounded SearXNG response-body consumption:** Search JSON and HTML fallback, `/config`, and suggestions now share a streaming response reader with a configurable `SEARXNG_MAX_RESPONSE_BYTES` ceilin
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:215
- **Established HTTP sessions now receive the configured session rate limit:** Each `POST /mcp` request now passes through exactly one limiter. Requests with a currently live `mcp-session-id` use the 
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CONFIGURATION.md:383
In stateless mode, every POST creates a fresh MCP server and transport, ignores incoming `mcp-session-id` headers, and never emits a response session ID. A POST can return negotiated JSON or an SSE st
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CONFIGURATION.md:387
Rate limiting is always active in HTTP mode to prevent resource exhaustion. Before the MCP handler runs, each request is counted by resolved client IP against exactly one limit. In stateful mode, reta
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-09-25 · audit v0.4.1 · source sha 9f1716c8a2dbfull audit observations/trust-audit/mcp-server/ihor-sokoliuk__searxng.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-09-259f1716c8a2dbSAFEB86first audit
06

Questions

What is the SearXNG MCP server?

Private web search for AI assistants via SearXNG — supports Claude, Cursor, and any MCP client

What tools does SearXNG expose?

4 in total: 4 read-only, 0 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.

Is SearXNG safe to connect to an agent?

The audit found nothing in the source that contradicts what it says it does, and graded it B (86/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean server reads B.

What credentials does SearXNG need?

It reads AUTH_PASSWORD, AUTH_USERNAME, MCP_HTTP_AUTH_MODE, MCP_HTTP_AUTH_TOKEN, MCP_HTTP_OAUTH_ISSUER, MCP_HTTP_OAUTH_SCOPES and SEARXNG_URL from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does SearXNG run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as mcp-searxng at 2.4.0.

How current is this page?

The grade is for one exact copy of the source (9f1716c8a2db), read on 2026-09-25. The repository is watched and re-audited when it changes.

Advertisement