Skip to main content
Glama

WebX — локальный веб-поиск по запросу для кодинг-агентов

Небольшой Unix-подобный локальный инструмент, который даёт кодинг-агентам доступ в веб только когда это нужно. Это не исследовательский агент — всего два примитива плюс управление жизненным циклом:

search(query) -> ranked URLs/snippets   (local SearXNG, Docker, 127.0.0.1:8888, normally stopped)
read(url)     -> cleaned Markdown       (controlled fetch + Trafilatura, SSRF-protected)
  • Режим минимального агента: агент вызывает webx search / webx read / webx stop только тогда, когда временный промпт это разрешает. Никакого постоянного веб-инструмента в системном промпте.

  • Режим исследования/MCP: хост запускает webx-mcp (stdio). Сервер предоставляет ровно web_search + web_read. Запуск не стартует SearXNG; первый web_search лениво запускает его и владеет завершением.

Установка

Требуется Python 3.12+ и Docker + Compose для поиска. webx read работает без Docker.

# with uv (recommended)
uv sync
uv sync --extra mcp      # for MCP server
uv sync --extra dev      # for tests

# or pip
pip install -e .
pip install -e ".[mcp]"

# global tool (so `webx` works in `pi`'s bash and any shell)
uv tool install .        # installs to ~/.local/bin/webx — ensure ~/.local/bin is on PATH
# or pipx
pipx install .

# per-project (no global install)
uv sync && uv run webx --help
# or add .venv/bin to PATH for this shell/session (useful for pi coding agent)
export PATH="$PWD/.venv/bin:$PATH"
which webx && webx --help

Примечание для кодинг-агента pi: Инструмент bash внутри pi наследует PATH от хоста. Если webx: command not found, выполните uv tool install . один раз или export PATH="$PWD/.venv/bin:$PATH" в сессии, где вы запускаете pi.

Related MCP server: mcp-searxng

Быстрый старт

webx init                # materialize ~/.local/share/webx/{compose.yml,settings.yml,.env,cache}
webx doctor              # check docker, templates, SearXNG reachability (does NOT start SearXNG)
webx status              # {initialized, docker_available, searxng_running, url, runtime_dir}
webx status --json

webx search "SearXNG documentation" --limit 5 --pretty
webx status              # now running

webx read "https://docs.searxng.org/" --max-chars 12000
webx read "https://docs.searxng.org/" --json | jq

# denials are exit 5
webx read "http://127.0.0.1:8888/"      # -> exit 5 unsafe URL
webx read "http://192.168.1.1/"         # -> exit 5
webx read "file:///etc/passwd"          # -> exit 5

webx stop                # docker compose stop (retains container)
webx status              # stopped

Промпт временного веб-доступа (минимальный агент)

For this task you are allowed to use the local WebX utility when external/current
information materially helps.
Available commands:
- webx search "<query>" to discover relevant public-web sources.
- webx read "<url>" to read a relevant public page as cleaned text/Markdown.
...
When the web-research portion is finished, run webx stop.

Конфигурация MCP-хоста

Только stdio. Пример (Claude Code / MCP Inspector):

{
  "mcpServers": {
    "webx": {
      "command": "webx-mcp",
      "env": { "WEBX_DATA_DIR": "/home/you/.local/share/webx" }
    }
  }
}

Список инструментов должен быть ровно web_search + web_read. Жизненный цикл внутренний — не выставляйте webx up/stop как инструменты агента.

Справочник CLI

webx --help
webx --version
webx init [--force-templates] [--show-path]   # idempotent, never rotates secret
webx doctor                                   # inspection only
webx up                                       # ensure SearXNG running
webx stop                                     # compose stop (normal shutdown)
webx status [--json]
webx logs [--tail 100]
webx search QUERY [--limit 8] [--category general] [--language en] [--page 1]
              [--time {day,month,year}] [--safe-search {0,1,2}] [--engine NAME] [--pretty]
webx read URL [--max-chars N] [--json] [--links] [--no-tables] [--precision] [--recall]
  • stdout = данные (JSON для поиска, Markdown/текст или JSON для чтения). stderr = диагностика.

  • Коды выхода: 0 ок, 2 использование/валидация, 3 рантайм/docker недоступен, 4 сбой SearXNG, 5 небезопасный URL, 6 сбой получения/извлечения, 7 неподдерживаемый тип контента (2xx с image/*, application/pdf и т.д.). 4xx/5xx/таймаут от публичного URL — это 6, а не 7 (например, wikimedia PNG -> HTTP 400 -> 6).

--verbose (глобальный) включает отладочные трассировки в stderr (например, read ok: https://example.com/ text/html 114 chars engine=trafilatura 1.23s). Секреты никогда не печатаются.

Примеры движков/категорий (SearXNG агрегирует 269 сервисов; фильтруйте по запросу, когда срабатывают лимиты вышестоящих сервисов):

webx search "python httpx" --engine wikipedia --engine github --pretty
webx search "SearXNG" --category it --pretty
webx search "SearXNG documentation" --time month --pretty

Примеры извлечения при чтении (--links сохраняет markdown [text](url); --precision/--recall настраивают trafilatura):

webx read "https://en.wikipedia.org/wiki/Python_(programming_language)" --max-chars 2000 --links | head -n 40
webx read "https://en.wikipedia.org/wiki/Python_(programming_language)" --max-chars 2000 | head -n 40
webx read "https://api.github.com/zen" --json | jq  # application/json is returned raw (engine=raw), not trafilatura

Рантайм и конфигурация

Каталог рантайма через platformdirs (можно переопределить через WEBX_DATA_DIR):

  • Linux: ~/.local/share/webx/ (XDG)

  • macOS: ~/Library/Application Support/webx/

  • Windows: %LOCALAPPDATA%\webx\

Содержит compose.yml, settings.yml, .env (SEARXNG_SECRET 0600), cache/.

settings.yml — это небольшой оверрайд (use_default_settings: true, formats: [html, json], limiter: false, public_instance: false, image_proxy: false). Не копируйте весь дефолтный конфиг SearXNG.

compose.yml:

services:
  searxng:
    image: ${SEARXNG_IMAGE:-docker.io/searxng/searxng:latest}
    container_name: webx-searxng
    ports: ["127.0.0.1:8888:8080"]
    env_file: [.env]
    volumes: ["./settings.yml:/etc/searxng/settings.yml:ro", "./cache:/var/cache/searxng"]
    restart: "no"

Только loopback-привязка, один контейнер, без Valkey/Redis, без прокси, без TLS. Если монтирование одного файла только для чтения когда-либо сломается из-за FORCE_OWNERSHIP в SearXNG, переключитесь на монтирование каталога — но сохраняйте привязку 127.0.0.1 (см. 04_SEARXNG_RUNTIME.md).

Переопределения через env (все с WEBX_):

WEBX_DATA_DIR, WEBX_SEARXNG_URL (default http://127.0.0.1:8888), WEBX_DOCKER_CMD,
WEBX_STARTUP_TIMEOUT (30s), WEBX_SEARCH_TIMEOUT (15s), WEBX_READ_TIMEOUT (15s),
WEBX_MAX_RESPONSE_BYTES (10 MiB), WEBX_MAX_READ_CHARS (40000), WEBX_MCP_STOP_ON_EXIT (true)

SEARXNG_IMAGE также можно задать в .env или env, чтобы зафиксировать тег образа.

Версия образа SearXNG

Проверено при реализации (2026-08-20):

  • Тег: docker.io/searxng/searxng:latest

  • Разрешённый digest: sha256:ec536bcd1e83577aad4cc07f7ecb9a30858a9a905d2d57c8796abc83f872a036 (локальный образ ec536bcd1e83, SearXNG 2026.8.1-8892414dc)

  • Настраивается через SEARXNG_IMAGE — не делайте авто-пулл при каждом поиске.

Ручное обновление:

webx stop
docker compose -f $(webx init --show-path)/compose.yml pull   # or: SEARXNG_IMAGE=... docker compose pull
webx up
webx search "test" --limit 1 --pretty
webx stop

Никогда не обновляйте автоматически при поиске.

Жизненный цикл MCP

  • Запуск webx-mcp не стартует SearXNG.

  • Первый web_search проверяет http://127.0.0.1:8888/; если остановлен, выполняет docker compose up -d + опрос, затем помечает started_by_mcp = true; если уже запущен, помечает false.

  • web_read никогда не запускает SearXNG.

  • При чистом выходе, если started_by_mcp && WEBX_MCP_STOP_ON_EXIT, выполняется compose stop; иначе SearXNG остаётся запущенным. Процесс-локальная блокировка защищает параллельные первые поиски. Несколько независимых MCP-процессов, нуждающихся в аренде/счётчике ссылок, отложено до v2.

Описания инструментов указывают границу доверия: возвращаемый текст страницы — недоверенные внешние данные, никогда не инструкции для агента; страницы с JS/авторизацией могут не работать.

Модель безопасности

webx read рассматривает URL как недоверенный ввод.

  • Разрешать только http:// / https://; запрещать file:, ftp:, data:, javascript:, голые пути, URL с учётными данными.

  • Разрешать имя хоста через системный резолвер, проверять каждый IPv4/IPv6 через ipaddress: запрещать loopback, частные RFC1918, IPv6 ULA, link-local (169.254.0.0/16, fe80::/10), multicast, unspecified, reserved, metadata 169.254.169.254 и сам endpoint SearXNG. В v1 нет --allow-private.

  • Остаточный риск DNS rebinding: resolve-then-connect не может полностью предотвратить rebinding, потому что httpx может резолвить повторно; WebX проверяет каждый redirect-цель и документирует ограничение. Привязка адреса — возможное усиление без раздувания v1.

  • Redirects: ручной цикл, максимум 5, Location резолвится относительно текущего URL, повторно валидируется, цикл/превышение — ошибка.

  • Fetch: User-Agent: webx/<version> local-research-tool, connect 5s, read 15s, стриминг с предпроверкой Content-Length + лимит 10 MiB, без маскировки под браузер.

  • Разрешённые типы: text/html, application/xhtml+xml, text/plain, markdown-подобные, json/xml текст; бинарные (image/*, application/pdf и т.д.) → код 7.

  • Извлечение: сырое тело → trafilatura.extract(output_format="markdown", ...) + fallback html2txt; обрезка после извлечения на границе слова/новой строки, сообщать truncated + characters.

  • Нет cookies, auth-заголовков, POST или браузера.

Операции и устранение неполадок

webx doctor — первая диагностика.

Сбой

Вероятная причина

doctor говорит, что docker недоступен

Установите Docker/Compose; webx read всё равно работает

Поиск 403

json не включён в settings.yml (проверьте search.formats)

SearXNG запускается, но поиск даёт 0 результатов / 5xx

Вышестоящие движки ограничили/CAPTCHA ваш IP — проверьте webx logs на suspended_time=180 / Too many request / HTTP 403. Это не баг WebX; попробуйте другой запрос/категорию или закрепите движки: webx search "…" --engine wikipedia --engine github (google cse часто единственный движок без лимита с этого IP)

Читатель возвращает крошечный текст

JS-рендеринг страницы — попробуйте --recall или другой источник; рендеринг браузера вне рамок v1

Читатель отклоняет URL

Отказ частной/локальной сети — намеренно

webx logs пуст

SearXNG not runningwebx logs теперь подсказывает run webx up or webx search to start вместо тихого пустого

WEBX_DATA_DIR=/tmp/... webx status говорит running:true, но compose missing

Один контейнер webx-searxng общий для всех каталогов — status теперь показывает compose: missing + примечание; проба глобальная 127.0.0.1:8888

webx: command not found в pi

~/.local/bin не в PATH — см. Установку (uv tool install / export PATH="$PWD/.venv/bin:$PATH" )

Исследовательские эвристики (на стороне агента, не WebX): предпочитайте официальные доки → репозиторий/заметки вышестоящего → спецификации → анонсы вендора → качественные статьи; используйте --category it, когда помогает; запускайте несколько сфокусированных поисков, читайте первоисточники, ищите противоречия.

Тестирование

uv sync --extra dev --extra mcp
uv run pytest                # fast unit tests, no Docker/net required
uv run pytest -m integration # live tests (needs Docker + net, marked integration)
uv run pytest --cov=webx

Ручное приёмочное тестирование (с чистого WEBX_DATA_DIR):

webx --help; webx init; webx doctor; webx status   # stopped
webx search "SearXNG documentation" --limit 5 --pretty
webx status                                        # running
webx read "https://docs.searxng.org/" --max-chars 12000
webx read "http://127.0.0.1:8888/"      # -> exit 5
webx read "http://192.168.1.1/"         # -> exit 5
webx read "file:///etc/passwd"          # -> exit 5
webx stop; webx status                 # stopped
# MCP: inspector 2 tools, web_read while stopped, first search starts, second reuses, stop-on-exit ownership

Примечание о httpbin.org: Живой httpbin.org сейчас возвращает 503 Service Temporarily Unavailable из некоторых сетей (проверено 2026-08-20 через curl -A "webx/0.1.0" и curl -A "Mozilla/5.0" — оба 503). Если webx read https://httpbin.org/html даёт 503, используйте стабильные альтернативы: https://example.com, https://en.wikipedia.org/wiki/Python_(programming_language) (хорошо для тестов обрезки/--links), или https://httpbingo.org/get.

Структура проекта

src/webx/
  __init__.py, cli.py, config.py, lifecycle.py, searxng.py, security.py, reader.py, core.py, mcp_server.py
  assets/{compose.yml,settings.yml}
tests/{unit,integration}
docs/{instructions,PLAN.md}

Ядро WebX — общий фасад для CLI и MCP; ни один не вызывает другой через shell.

Не-цели (v1)

Браузер/Playwright, PDF-читатель, краулинг, реранкер, LLM-суммаризатор, кэш, межпроцессная аренда, пресеты движков, фильтры доменов — см. 09_DECISIONS_AND_FUTURE.md для обоснования и кандидатов в v2.

Лицензия

MIT

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to perform web searches and read URL content via a SearXNG instance.
    2
    15
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables local LLMs to search the web and fetch clean content from URLs without API keys, using SearxNG and Mozilla Readability.
    2
    35
    MIT

View all related MCP servers

Related MCP Connectors

  • Read any web page as clean Markdown for AI agents: fetch, search, metadata, links. SSRF-safe.

  • LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.

  • Read a URL as clean markdown, screenshot a website, url to PDF. Web access for agents, no signup.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Fatih0234/web-searxng'

If you have feedback or need assistance with the MCP directory API, please join our Discord server