Add searxng-search plugin: self-hosted SearXNG web search Skill - #1
Open
Fectivnfy112357 wants to merge 1 commit into
Open
Add searxng-search plugin: self-hosted SearXNG web search Skill#1Fectivnfy112357 wants to merge 1 commit into
Fectivnfy112357 wants to merge 1 commit into
Conversation
A zero-dependency Python Skill that lets the agent run search queries
against the user's own self-hosted SearXNG instance. Supports bearer /
basic auth, TOML or JSON config, and the standard SearXNG filters
(categories, engines, time range, language, safe search, pagination).
Solves: web search inside an agent usually means a vendor API with
credentials and quotas. Operators that already run SearXNG (a
privacy-respecting metasearch engine) get a first-class search tool
against their own instance — one config file, no vendor SDK, no
tracking.
Security model (matched to mcode-plugin-guide red lines):
- HTTPS by default. Plain HTTP is accepted only for loopback hosts
(127.0.0.1, ::1, localhost) or for non-loopback hosts when the
config contains an explicit `allow_insecure_http = true` opt-in,
which emits a strong warning.
- Auth values can be referenced via `$ENV_VAR` / `${ENV_VAR}` in the
config so the plaintext never lives in the file. On POSIX the
script warns when the file is readable beyond the owner.
- HTTP redirects are blocked entirely (custom `HTTPRedirectHandler`).
The default urllib handler would forward the `Authorization` header
to the redirect target, which can leak the token to a different
origin and silently downgrade HTTPS to HTTP. Point `base_url`
directly at the final endpoint, or front the instance with a
same-origin reverse proxy.
- 401 / 403 / 407 response bodies are not echoed to stderr because
they frequently reflect back the credentials the server saw.
Other 4xx / 5xx bodies run through a two-pass redactor: an
exact-value secret registry (per request) plus shape-based
fallbacks (Bearer / Basic / github_pat_ / gh[pousr]_ / token= /
common env-var names).
- Numeric config fields are type-validated at load time
(`timeout = "30"` etc. fail fast with a clear message instead of
surfacing a raw TypeError from urllib).
- Response body is capped at 10 MiB to prevent runaway reads on a
misbehaving or hijacked endpoint.
Network (two levels, both disclosed in README, SKILL.md, and
plugin.json):
- Direct: the script makes a single request to the user's
configured `base_url`. Nothing else.
- Downstream: the user's SearXNG instance then forwards the query,
language code, and selected categories to its own configured
upstream engines (Google, Bing, DuckDuckGo, Brave, Baidu, etc., as
enabled by the instance operator). The script does not see or
control that hop.
Tested:
- `py -3 skills/searxng-search/scripts/run_tests.py` → 77 pass,
2 POSIX-only skipped (expected on Windows).
- `node --test test/searxng-search.test.mjs` → 1 pass, 0 fail
(the Node bridge that the repo's `npm test` will discover).
- `node scripts/validate.mjs` → `OK plugin
Fectivnfy112357/searxng-search`.
Files (28):
- `plugin.json`, `README.md`, `LICENSE` (MIT)
- `skills/searxng-search/SKILL.md` and `.gitignore`
- `skills/searxng-search/references/configuration.md`
- `skills/searxng-search/scripts/search.py` (the runtime)
- `skills/searxng-search/scripts/run_tests.py` (unittest entry)
- `skills/searxng-search/scripts/tests/` (7 test modules + fixtures)
- `test/searxng-search.test.mjs` (Node bridge for the repo's
`node --test` discoverer)
No installer. No write operations outside reading the local config
file. No telemetry. No third-party services run by this script.
No symlinks. No native binaries. No credentials or private endpoints
are committed; the test suite is fully offline.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR adds
A new Skill plugin,
searxng-search, that lets the agent run a websearch query against the user's own self-hosted SearXNG instance via a
zero-dependency Python script. Operators that already self-host SearXNG
(a privacy-respecting metasearch engine) get a first-class search tool
without going through a vendor API or installing another binary.
Filters supported out of the box: categories, engines, time range,
language, safe search, pagination. Bearer and basic auth, with secrets
referenced as
$ENV_VARso plaintext never lives in the config file.The problem it solves
Web search inside an agent usually means a vendor API with credentials
and quotas. If you already run SearXNG, this skill gives the agent a
direct search tool against it — one config file, no vendor SDK, no
tracking.
Try it
After installing from
/plugins→ Local and configuring yourinstance (see
skills/searxng-search/references/configuration.md),ask the agent:
Expected result: a formatted list of results (title, URL, snippet)
from your SearXNG instance, filtered by the requested category / time
range / language.
Direct usage from the skill directory:
Dependencies and supported platforms
tomllib; legacy JSON config stillworks on older Python). Zero pip dependencies.
provide it; no public instance is bundled.
node --testbridgein
test/searxng-search.test.mjsuses the platform-appropriateinterpreter discovery order (
py -3→python→python3onWindows;
python3→pythonon POSIX) and validates each candidatewith
--versionbefore running, so it does not produce a falsepass on a host that has no usable Python.
Network and data behavior
This skill has two levels of network destinations; both matter.
configured
base_url. HTTPS by default; plain HTTP is allowed onlyfor loopback hosts (127.0.0.1, ::1, localhost) or for non-loopback
hosts with an explicit
allow_insecure_http = trueopt-in, whichemits a strong warning because Authorization headers and search
queries would travel in cleartext. The script never follows HTTP
redirects: a 30x response is an error, because following a redirect
could forward the Authorization header to a host the user did not
configure. Point
base_urldirectly at the final endpoint, orfront the instance with a same-origin reverse proxy.
the query, language code, and selected categories to
the upstream engines it has been configured with (Google, Bing,
DuckDuckGo, Brave, Baidu, etc., as enabled by the instance
operator). Those engines receive the request content from the
instance — the script does not see or control that hop. If query
contents reaching the upstream engines is a concern, configure
your instance to use engines you trust, or self-host engines
locally.
No telemetry. No third-party services run by this script.
Authorization headers and search queries are sent only to the
configured
base_url; the script never sends them anywhere else.Compliance declarations
or in the test fixtures. The test suite is fully offline (no
network, no
ghbinary, no real SearXNG instance).~/.dsh,~/.minimax,~/.pi, or any other user configuration directory.It only reads the local config file at
~/.config/agents/searxng.toml(or.json).only (
urllib,tomllib,json,argparse,base64).own config; no MCP server; no commands besides the single Skill
that calls
python3 scripts/search.py.redact_secretspipeline(exact-value registry + shape-based fallback). 401 / 403 / 407
response bodies are not echoed because they frequently reflect
back the credentials the server saw. Custom
headersvalues usethe same
$ENV_VARresolution and redaction registration asauth.*.a misbehaving or hijacked endpoint.
Test evidence
py -3 skills/searxng-search/scripts/run_tests.py→ 77 pass, 2skipped (POSIX-only, expected on Windows), 0 fail. The suite
covers:
reject; opt-in warning; non-
http(s)schemes reject)query and fragment from
Location:; opener installs the safehandler exactly once and no default redirect handler; integration
through
main()does not echo the Authorization header)token never leaks into the URL; custom
headersvalues followthe same env-var + redaction rules as
auth.*; User-Agentoverride; non-string header values rejected)
base_url, env-var resolution, numeric type validation,POSIX-mode warning with Windows skip)
short / non-shape tokens, substring-first ordering, reset,
empty-value no-op, idempotency, stderr redaction)
error,HTTPError body redacted, URL error, timeout, 401 / 403 / 407
body suppressed, JSON-array root, non-UTF-8, oversized
response, oversized error body)
node --test test/searxng-search.test.mjs→ 1 pass, 0 fail.The Node bridge spawns the first usable Python interpreter with
--versionvalidation and assertspython run_tests.pyexits 0,so the repo's
node --testdiscoverer picks this up undernpm test.node scripts/validate.mjs→OK plugin Fectivnfy112357/searxng-search. The package shape (manifestfields, SKILL.md frontmatter, LICENSE, README, no symlinks, no
BOM, no TODO residue) is clean.
Files (18, +2379 / -0)
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.