The source list distinguishes a page read in full from one where only metadata was fetched — the distinction models lose first when they compose a citation far from the tool call that produced it. Long documents are windowed at 100k characters with the exact next `start_index` returned, and the extracted text stays cached, so paging through a large PDF costs one upstream fetch rather than one per page. Reaching an internal wiki is opt-in through `FETCH_ALLOWED_HOSTS` or `FETCH_ALLOWED_CIDRS`, and both require an explicit port.
A search relay for environments where queries are not allowed to leave infrastructure you control. It fronts a self-hosted SearXNG instance, fetches and extracts pages itself, and keeps a per-caller record of what it retrieved — so a claim about sources can be checked against a list rather than trusted to a model's recall.
- Web search through your SearXNG instance with control over language, category, time range, safe-search level and result count, and the backend engines that surfaced each result named on it — `searxng_web_search`
- A URL fetched and converted to structured Markdown with headings, lists, tables and code blocks preserved; PDFs and Office documents (DOCX, XLSX, PPTX plus legacy DOC, XLS, PPT) are extracted too, and images come back as image content for vision models — `searxng_read_url`
- Title, author, publish date, language, site name, description, image, categories and tags for a URL as JSON, for choosing between candidate links before paying for a full read — `searxng_url_metadata`
- The URLs this relay genuinely fetched for the caller, newest first, each marked with how much was read: full text, one window of a longer document, metadata only, or a failed fetch — `searxng_session_sources`
A running SearXNG instance with the JSON output format enabled in its `settings.yml`, and its base URL in `SEARXNG_URL` — the server refuses to start without it. Docker (`ghcr.io/littleoffice/mcp-searxng-relay:latest`) or Go 1.26+ to build from source. With `MCP_PORT` set it speaks Streamable HTTP and requires a bearer token via `MCP_AUTH_TOKEN`, `MCP_AUTH_TOKENS` or `MCP_AUTH_TOKEN_FILE`; with `MCP_PORT` unset it runs over stdio.
One command — docker run -d \ -e SEARXNG_URL=https://your-searxng-instance.example.com \ -e MCP_PORT=8080 \ -e MCP_AUTH_TOKEN=$(openssl rand -hex 32) \ -p 8080:8080 \ ghcr.io/littleoffice/mcp-searxng-relay:latest
