Skip to content

Add searxng-search plugin: self-hosted SearXNG web search Skill - #1

Open
Fectivnfy112357 wants to merge 1 commit into
MiniMax-AI:mainfrom
Fectivnfy112357:feat/searxng-search
Open

Add searxng-search plugin: self-hosted SearXNG web search Skill#1
Fectivnfy112357 wants to merge 1 commit into
MiniMax-AI:mainfrom
Fectivnfy112357:feat/searxng-search

Conversation

@Fectivnfy112357

@Fectivnfy112357 Fectivnfy112357 commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

What this PR adds

A new Skill plugin, searxng-search, that lets the agent run a web
search 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_VAR so 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 /pluginsLocal and configuring your
instance (see skills/searxng-search/references/configuration.md),
ask the agent:

search the web for the latest SearXNG documentation

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:

python3 scripts/search.py -c news -t day "latest tech news"
python3 scripts/search.py -e google,duckduckgo -p 2 "rust programming"
python3 scripts/search.py -l zh-CN -n 10 "开源搜索引擎"

Dependencies and supported platforms

  • Python 3.11+ at runtime (uses tomllib; legacy JSON config still
    works on older Python). Zero pip dependencies.
  • A self-hosted SearXNG instance reachable over HTTP(S) — you
    provide it; no public instance is bundled.
  • Tested on Windows (Python 3.13) and POSIX. The node --test bridge
    in test/searxng-search.test.mjs uses the platform-appropriate
    interpreter discovery order (py -3pythonpython3 on
    Windows; python3python on POSIX) and validates each candidate
    with --version before running, so it does not produce a false
    pass on a host that has no usable Python.

Network and data behavior

This skill has two levels of network destinations; both matter.

  • Direct (this script): the script makes a single request to the
    configured base_url. HTTPS by default; plain HTTP is allowed only
    for loopback hosts (127.0.0.1, ::1, localhost) or for non-loopback
    hosts with an explicit allow_insecure_http = true opt-in, which
    emits 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_url directly at the final endpoint, or
    front the instance with a same-origin reverse proxy.
  • Downstream (your SearXNG instance): the instance then forwards
    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

  • No credentials, private endpoints, or personal data in the repo
    or in the test fixtures. The test suite is fully offline (no
    network, no gh binary, no real SearXNG instance).
  • No installer. The script does not write to ~/.dsh,
    ~/.minimax, ~/.pi, or any other user configuration directory.
    It only reads the local config file at
    ~/.config/agents/searxng.toml (or .json).
  • No symlinks in the plugin tree.
  • No native binaries. The script uses Python's standard library
    only (urllib, tomllib, json, argparse, base64).
  • No hidden side effects. No file generation outside the user's
    own config; no MCP server; no commands besides the single Skill
    that calls python3 scripts/search.py.
  • All error paths route through a redact_secrets pipeline
    (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 headers values use
    the same $ENV_VAR resolution and redaction registration as
    auth.*.
  • Response body is capped at 10 MiB to prevent runaway reads on
    a misbehaving or hijacked endpoint.

Test evidence

  • py -3 skills/searxng-search/scripts/run_tests.py77 pass, 2
    skipped (POSIX-only, expected on Windows), 0 fail
    . The suite
    covers:
    • URL validation (HTTPS pass; loopback HTTP pass; non-loopback HTTP
      reject; opt-in warning; non-http(s) schemes reject)
    • HTTP redirect handling (all 3xx codes blocked; diagnostic strips
      query and fragment from Location:; opener installs the safe
      handler exactly once and no default redirect handler; integration
      through main() does not echo the Authorization header)
    • Auth header construction (bearer / basic; env-var resolution;
      token never leaks into the URL; custom headers values follow
      the same env-var + redaction rules as auth.*; User-Agent
      override; non-string header values rejected)
    • Config loading (missing file, invalid TOML / JSON, missing
      base_url, env-var resolution, numeric type validation,
      POSIX-mode warning with Windows skip)
    • Credential redaction (5 shape patterns, exact-value registry,
      short / non-shape tokens, substring-first ordering, reset,
      empty-value no-op, idempotency, stderr redaction)
    • Invalid response handling (non-JSON, structured error,
      HTTPError body redacted, URL error, timeout, 401 / 403 / 407
      body suppressed
      , JSON-array root, non-UTF-8, oversized
      response, oversized error body)
    • Timeout configuration (default 30s, custom value pass-through)
  • node --test test/searxng-search.test.mjs1 pass, 0 fail.
    The Node bridge spawns the first usable Python interpreter with
    --version validation and asserts python run_tests.py exits 0,
    so the repo's node --test discoverer picks this up under
    npm test.
  • node scripts/validate.mjsOK plugin Fectivnfy112357/searxng-search. The package shape (manifest
    fields, SKILL.md frontmatter, LICENSE, README, no symlinks, no
    BOM, no TODO residue) is clean.

Files (18, +2379 / -0)

plugin.json
README.md
LICENSE
skills/searxng-search/SKILL.md
skills/searxng-search/.gitignore
skills/searxng-search/references/configuration.md
skills/searxng-search/scripts/search.py
skills/searxng-search/scripts/run_tests.py
skills/searxng-search/scripts/tests/__init__.py
skills/searxng-search/scripts/tests/_fixtures.py
skills/searxng-search/scripts/tests/test_auth_header.py
skills/searxng-search/scripts/tests/test_config.py
skills/searxng-search/scripts/tests/test_invalid_response.py
skills/searxng-search/scripts/tests/test_redaction.py
skills/searxng-search/scripts/tests/test_redirect.py
skills/searxng-search/scripts/tests/test_timeout.py
skills/searxng-search/scripts/tests/test_url_validation.py
test/searxng-search.test.mjs

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant