bathys
Summary: Bathys is a local MCP server that gives AI agents deep web research, search, reading, and fact-checking tools without cloud quotas.
deep_research— one-call research: metasearch + parallel page reads + query-tailored distilled digest (with budgets, cache, refresh).web_search— ranked link lists with snippets; supports time range, category, engines, language, JSON output, and automatic retries on blocked/empty results.read_url— read a single page as clean markdown; JS pages via headless browser; optional query-focused distillation, exact substring search over cached raw text, and cache bypass.read_urls— batch-read up to 10 known URLs in parallel under one shared character budget; failed pages cost one line instead of a broken call.library_docs— fetch and distill up-to-date official library documentation from the primary source; supports version pinning and subpage following; repeat calls are cached/offline.source_check— deterministic, no-LLM claim verification against provided URLs or web-found sources, returning SUPPORTED/CONTRADICTED/UNCLEAR/MISSING-EVIDENCE with quoted passages.Operational extras — TTL source cache, robots ethics, metrics/footer compression stats, and swappable internal engines (SearXNG, Crawl4AI).
Uses SearXNG as the search backend to perform web searches and collect raw results, which are then distilled into concise, query-relevant answers.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bathys Deep research: compare SQLite WAL vs PostgreSQL for 2026"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Bathys
A single local deep-research search service for AI agents. This is a standalone product, not a wrapper over someone else's services: Bathys implements the entire pipeline itself — metasearch with deduplication and resilience to blocking, two-tier extraction (an HTTP engine by default, a headless browser only for JS pages), five-stage query-tailored distillation with hard budgets, a TTL source cache, robots ethics, metrics and diagnostics. Metasearch and extraction are packaged as swappable internal engines (SearXNG, Crawl4AI) — they can be replaced, and the product remains Bathys. No cloud quotas; no LLM inside — synthesis stays with the calling agent, and distillation is deterministic (BM25).
The sonar finds the coordinates, the bathyscaphe dives for the full texts, and the distiller hoists on deck only what answers the question.
Navigation: ⚡ Quick start · 🧹 Removal · 🔌 Harness integration · 🧠 Teach your agent · 🧭 Use cases · 🛠 Tools · 📊 Token savings · 📚 Documentation · 📍 Status
⚡ Quick start
Option 1 — install script (recommended; Python ≥ 3.10):
curl -fsSL https://raw.githubusercontent.com/Korrnals/bathys/main/install.sh | bashThe script installs the package from PyPI into a private venv (~/.local/share/bathys/venv, no sudo), adds it to PATH and runs the full setup. Re-running it is a safe update.
Option 2 — pip (the same thing, done manually):
pip install bathys
bathys setupWhat bathys setup does:
Step | Action |
1 | installs the headless browser — needed only for JS pages (regular pages are read by the built-in HTTP engine) |
2 | registers the MCP server in every harness it finds (zcode, Claude, Cursor, the VS Code family and others — 14 in total, see Harness integration) |
3 | copies the researcher subagent into the found harness directories |
4 | prints the summary and hints ( |
SearXNG does not need to be installed separately — the backend starts automatically on the first search: an external instance is checked first, then docker/podman, then native mode (a clone in BATHYS_SEARXNG_HOME).
npm (Node-first environments; the wrapper installs the Python package itself):
npm install -g bathys-mcp
bathys-mcp setupFrom sources (development):
git clone https://github.com/Korrnals/bathys.git && cd bathys
python3.12 -m venv .venv && .venv/bin/pip install -e .
.venv/bin/bathys setupPinning a specific version — an install-script variable:
BATHYS_INSTALL_VERSION=0.7.0 bash install.shA minimal image without ensurepip: the script and setup bootstrap pip themselves via get-pip.py — details in docs/getting-started/install.md.
🧹 Removal
bathys uninstall # detach Bathys from all harnesses
bathys uninstall hermes zcode # pointwise, only the named ones
bathys uninstall --purge # + delete the venv, cache and datauninstall removes only the bathys entries from harness configs (a *.bathys-backup-* backup is created before any change; foreign servers and subagents are not touched). --purge additionally deletes the ~/.local/share/bathys and ~/.cache/bathys directories; remove the bathys/venv/bin line from .profile/.bashrc manually. Details and backup restore — in the runbook.
Related MCP server: myscrape
🔌 Harness integration
Automatically — the whole stack: bathys setup (see above) registers the server in every harness it finds.
Pointwise — when you need it exactly here:
bathys install # auto-detect all installed harnesses
bathys install hermes # Hermes only (a missing config will be created)
bathys install --list # all supported targets with paths
bathys install --print-config # ready-made blocks for manual pastingDetected: zcode, Claude Code, Claude Desktop, Cursor, the VS Code family (Cline / Roo Code / Kilo Code), Gemini CLI, Windsurf, Zed, opencode, goose, Hermes; each has its own format (JSON schemas and YAML outlines for goose/hermes), and writes are idempotent with a backup. For Pi (badlogic pi-mono), which has no MCP config, there is a drop-in into AGENTS.md. Custom integrations live in the integrations/ directory.
Bathys is a stdio MCP server: the mcpServers block is the same everywhere, and only the file it goes into depends on the harness. command is an absolute path to the binary (~ is not expanded inside JSON); BATHYS_SEARXNG_HOME is optional. Ready-made blocks for every client: bathys install --print-config.
{
"mcpServers": {
"bathys": {
"command": "/path/to/bathys",
"env": { "BATHYS_SEARXNG_HOME": "/path/to/searxng-home" }
}
}
}Harness | Guide |
zcode | |
Claude Code / Claude Desktop | |
Cursor | |
Any other MCP client |
🧠 Teach your agent to work effectively
Configuration is only half the job. Out of the box the harness receives an instructions-playbook (a tool-choice matrix), annotations and three strategy prompts — bathys_deep_research, bathys_source_audit, bathys_fresh_scan — so it picks Bathys tools natively. Stronger still is the profile: the agents/bathys-researcher.md subagent with three skills, to which deep research is delegated wholesale; for clients that do not surface MCP instructions, there is the agents/HARNESS-DROPIN.md drop-in for AGENTS.md / CLAUDE.md / .cursor/rules.
The step-by-step path "out of the box → subagent → drop-in" and the footer-signal table — in "Live cases", section C.
🧭 Common use cases
Technology comparison. Asked "which one to pick for heavy load in 2026?", the agent makes a single deep_research, refines the query with terms from what it found, and verifies the conclusion against two sources: one call instead of a "search + N reads" chain, and 7.5k characters reach the context instead of ~35k.
[bathys: 34 raw hits, top 8 considered · dove 3 pages · 35669 ch fetched → 7508 ch returned · 1.3s]Auditing a contested claim. "Is it true that the benchmarks for X dropped?" — the agent takes the bathys_source_audit strategy: reads the links from the discussion in batch, searches for rebuttals, and delivers a verdict with a URL for each thesis. A dead link costs one line, not a broken call.
A fresh snapshot. "What's new in Y in the last two weeks?" — the bathys_fresh_scan strategy: a search with time_range=week, batch reading, a dated summary; a stale cache HIT is cured by a single refresh=true.
A full walkthrough of all the cases — user-facing, autonomous agents and operations — with live dialogues: docs/getting-started/cases.md.
🛠 Tools
Tool | What it does |
| searches, reads the top sources in parallel, returns a merged query-tailored distillate. The first call for any research question. |
| a ranked list of links with snippets, without page content; |
| reads a page (including text PDFs); with |
| up-to-date library documentation from the primary source, distilled to the question; repeat calls are free (cache). |
| batch-reads up to 10 known pages; the budget is split across the successes, and a failed page costs one line, not a broken call. |
| deterministic claim verification without an LLM: sources → parallel dives → verdict |
Search is narrowed by the shared time_range, category, engines, language filters. The live footer of a response shows compression and cache: [bathys: 41 raw hits, top 3 considered · dove 3 pages · 35669 ch fetched → 7508 ch returned · 3.2s].
📊 Token savings
The scale is honest and character-based; tokens ≈ chars/4; every figure is taken from the footer of a real call.
Call | From the network | To the agent | Compression |
| 37,549 chars | 1,986 chars | 18.9× |
| 17,063 chars | 2,325 chars | 7.3× |
| 35,669 chars | 7,508 chars | 4.7× |
Two-tier extraction — regular pages are read by the built-in HTTP engine (milliseconds, no browser) and JS shells by headless Chromium; then query-tailored distillation with hard character budgets.
Source cache before distillation — SQLite stores the raw text, so re-reading a page from a different angle is free and requires no network.
Zero cloud quotas —
deep_researchreplaces a "search + N reads" chain — that is, N+1 quota charges — with a single local call.
The methodology and thresholds — in docs/operations/metrics.md.
📚 Documentation
Section | What's inside | Who it's for |
The hub: the documentation tree and three reading routes | everyone — the entry point | |
Installation · configuration (20 env) · wiring up · live cases | a newcomer | |
Wiring overview · zcode · Claude Code · Cursor · any MCP client | when wiring up a harness | |
a contributor | ||
an integrator | ||
operations | ||
Charter · features · roadmap · competitors | the product owner | |
Six accepted architectural decisions | a contributor | |
docs authors |
Outside docs/: agents/ — the subagent, skills, drop-in · integrations/ — custom integrations (hermes, pi, zcode) · install.sh — the install script · npm/bathys-mcp/ — the NPM wrapper · tests/ — unit tests · CHANGELOG.md — release history.
📍 Status
0.14.1. Release history: v0.2 "Result Quality" (retries, engine health), v0.3 "Parity with Tavily" (read_urls, JSON mode), v0.4 "Operations" (robots ethics, metrics, bathys-doctor), v0.5 "Identity & Harness" (repositioning, prompts, subagent), v0.6 "Native Install" (bathys install), v0.7 "Ship & Setup" (two-tier extraction, bathys setup, the one-liner, uninstall), v0.8 "Engine Orchestration", v0.9 "Borrowed Ideas", v0.10–0.11 "Library Docs" (Phases 1–2), v0.12 "Deep Verdicts" (source_check + Phase 3), v0.13 "GitHub Tier & Deep Audit", v0.14 "Backlog Closed" — summaries in CHANGELOG.md.
Repository: github.com/Korrnals/bathys. Packages published: PyPI bathys (pip install) and bathys-mcp on npm (npm install -g); the install one-liner is above. CI and releases run through the cluster release conveyor (Korrnals/release-pipeline: verify gates → build → SHA256 → SBOM → cosign + GPG signatures → attach to the GitHub Release; all 15 releases shipped this way — the pre-policy versions retroactively re-attached their signature sets). .github/workflows/ci.yml remains the gate description; GitHub Actions itself is disabled account-wide (billing lock), so its failing runs are expected noise. Before 1.0: the first verified run of the Docker image (the Dockerfile ships with the package; the pipeline's docker build phase needs a runner-image update first).
🙏 Acknowledgements
Bathys stands on the shoulders of outstanding open projects — thanks to their authors and communities:
SearXNG — the metasearch engine (AGPL-3.0): Bathys runs it as a separate process and talks to it over a local JSON API; its sources are not modified and are not distributed inside the package.
Crawl4AI — the browser tier of extraction (Apache-2.0).
MCP Python SDK (MIT), httpx (BSD-3), Playwright (Apache-2.0).
Full attributions and license terms for each component — in THIRD_PARTY_NOTICES.md.
⚖️ License
Bathys code is MIT. The components that Bathys installs and uses are licensed separately and listed in THIRD_PARTY_NOTICES.md (in particular, SearXNG is under AGPL-3.0, with its terms honored).
Available Tools
6 toolsdeep_researchARead-only
Search the web AND read the top sources in one shot.
Runs SearXNG metasearch, dives into the top max_sources pages with a real
browser, distills each page down to passages relevant to query, and
returns one merged digest. Best first call for any research question.
Args:
query: research question or keywords (RU/EN both fine)
max_sources: how many top hits to read in full (1-6)
max_results: how many search hits to consider (1-20)
per_source_chars: per-source character budget (300-8000)
time_range: "day" | "week" | "month" | "year"
category: searxng category, e.g. "general", "news", "science", "it"
language: result language, e.g. "ru", "en", "ru-RU"
refresh: ignore cache and re-fetch search results and pages
Inputs: query (required), refresh, category, language, +4 more. Returns: result
library_docsARead-only
Fetch up-to-date official documentation for a library and distill it under your question.
Context7-style, but local and unlimited: the docs site is resolved from a
built-in index (or one live web search), fetched from the primary source,
and distilled to passages relevant to query. Repeated questions about
the same library are instant, offline and free (raw-page cache).
Args:
library: library name, e.g. "fastapi", "react", "postgresql", "crawl4ai"
query: your concrete question about the library (used for distillation)
max_chars: output character budget (300-20000)
refresh: re-fetch the docs page even if cached
subpages: when the docs home is navigational, follow this many
same-site subpages ranked by query relevance (0 disables)
version: pin docs to this version (tag, e.g. "0.115.0", "v3", branch
name). Works for GitHub-backed libraries: docs come from that
exact tag on raw.githubusercontent.com. Doc sites are shown at
their latest with an honest note; wrong/missing tag on GitHub
also falls back to latest with a note in the answer
Inputs: query (required), library (required), refresh, version, +2 more. Returns: result
read_urlARead-only
Read one web page; return its main content as clean, budgeted markdown.
JS-rendered pages are handled by a real headless browser. Boilerplate
(nav, footer, ads) is stripped; if query is given, only passages relevant
to it are returned. Pages are cached — re-reads with a different query are
instant and cost no network.
Args:
url: absolute http(s) URL
query: optional focus; return only passages relevant to it
max_chars: output character budget (300-50000)
refresh: ignore cache and re-fetch the page
find: search the cached RAW text for this exact substring (case-insensitive):
returns matches with counters and context, no network needed. Requires
the page to have been read before; combine with query for first reads.
Inputs: url (required), find, query, refresh, +1 more. Returns: result
read_urlsARead-only
Read several known web pages in one call under one shared character budget.
Pages are fetched in parallel (JS-rendered, boilerplate-stripped) and the combined total_chars budget is split evenly between the pages that came back. Prefer this over N read_url calls when you already hold the URLs: one round-trip, one budget, and a failed page costs one line instead of a failed call. Args: urls: 1-10 absolute http(s) URLs; duplicates (after utm/fragment cleanup) are merged, extras beyond 10 are reported in a Skipped line query: optional focus; each page is distilled to passages relevant to it total_chars: combined output budget across all sections (300-30000) refresh: ignore cache and re-fetch every page
Inputs: urls (required), query, refresh, total_chars. Returns: result
source_checkARead-only
Deterministically verify a claim against web sources; return a verdict with quoted passages.
No LLM involved: sources are read (yours via urls, or found by a web
search on the claim), distilled under the claim, and scored lexically —
polar markers (with negation handling) decide SUPPORTED / CONTRADICTED /
UNCLEAR / MISSING-EVIDENCE. Best for checking a fact, assertion or rumour
when you need a reproducible verdict with citations, not a narrative.
Args:
claim: the statement to verify, in your own words (RU/EN both fine)
urls: optional 1-10 http(s) URLs to check against; without them the
sources are found by a web search on the claim
max_sources: how many sources to consider (1-10)
refresh: ignore cache and re-fetch the search results and pages
Inputs: claim (required), urls, refresh, max_sources. Returns: result
web_searchARead-only
Search the web via SearXNG metasearch; return a compact ranked link list.
Returns title, URL and a short snippet per hit — no page content. Empty or blocked results are retried automatically with other engine sets. To actually read pages, call read_url; to do both at once, call deep_research. Args: query: search query (natural language or keywords) max_results: 1-20 time_range: "day" | "week" | "month" | "year" category: e.g. "general", "news", "science", "it", "files" engines: comma-separated engine names, e.g. "google,bing,duckduckgo" language: e.g. "ru", "en", "ru-RU" refresh: ignore cache and re-run the search as_json: return pure machine-readable JSON {query, count, hits[], answer?} instead of the human-friendly list (no footer line)
Inputs: query (required), as_json, engines, refresh, +4 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
Each tool targets a distinct workflow: search-only, read-one, read-many, combined deep research, library docs, and claim verification. The boundaries between read_url, read_urls, and deep_research are explicitly documented, so an agent can select without ambiguity.
Names mix conventions: read_url and read_urls use verb_noun, while deep_research, web_search, library_docs, and source_check lead with nouns or adjectives. There is no consistent verb-first pattern, making the set feel uneven despite all being snake_case.
Six tools cover the research/reading domain without redundancy or bloat; each adds a distinct capability, from search to verification. The count is well-scoped for a specialized server.
The surface covers the full research loop: search, read single, read many, fetch docs, and verify claims. No critical gap exists for the stated purpose of deep web research.
Maintenance
Related MCP Connectors
Web search API and MCP server for developers building AI agents.
One MCP server for all web data. Scrape, search, crawl, and AI research in one install.
Scrape, crawl and search the web for AI agents via MCP.
A hosted MCP suite providing workflow primitives: web search, content fetching, compression, deduplication, cost/budget management, and agent memory pipelines.
Related MCP Servers
- AlicenseAqualityAmaintenanceProvides local-first web intelligence over MCP with tools for search, fetch, crawl, extract, cache, find-similar, research, and autonomous agent loops, requiring no API keys.101,392 npm5,540AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceA self-contained web-research MCP server that lets local LLM agents search, fetch, and synthesize web content using tools like web_search, web_fetch, and web_research.2MIT
- AlicenseNot gradedqualityFmaintenanceMCP server enabling local-first web search, fetch, extract, and caching with citeable excerpts, no API key required. Supports research workflows for agents and apps.96 npm1MIT
- FlicenseAqualityDmaintenanceExposes web search and page fetching tools via the MCP protocol, allowing integration with AI editors like Cursor for autonomous research workflows.2-