wigolo
wigolo is a local-first web intelligence MCP server for searching, fetching, crawling, extracting, caching, researching, and monitoring web content for AI agents.
Search the web with multi-engine results, parallel query variants, domain/time filters, categories, images, citations, telemetry, and explainable evidence scores.
Fetch a URL as clean markdown with JS rendering, section extraction, truncation/token budgets, auth sessions, browser actions, screenshots, and site-specific data.
Crawl sites via BFS, DFS, sitemap, or URL-only map mode with depth/page limits, regex filters, deduplication, and cached pages.
Extract structured data using CSS selectors, tables, metadata/JSON-LD, custom JSON Schema, named schemas, or brand identity extraction.
Use the local cache to search previously fetched content via FTS or hybrid semantic search, view stats, clear entries, and detect changed pages.
Find similar pages to a URL or concept using local cache, embeddings, keyword search, and optional live web expansion.
Run deep research that decomposes questions, searches/fetches sources, and returns cited reports or structured briefs.
Run autonomous data gathering from natural-language prompts with planning, parallel fetching, optional schema extraction, time budgets, and step logs.
Diff and watch content by comparing markdown/URL versions and scheduling persistent URL change checks with optional webhook delivery.
Adds Brave Search as a search engine adapter, improving retrieval diversity and result consensus.
Integrates GitHub code search with an API token, increasing rate limits and enabling private repository results.
Supports Google as an optional cloud LLM provider for synthesis, configured via GOOGLE_API_KEY.
Supports local LLM inference via Ollama for synthesis, keeping all processing on-device.
Integrates SearXNG as an optional fallback search backend for enhanced engine coverage.
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., "@wigoloResearch the benefits of local-first web intelligence"
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.
Local-first web intelligence for AI agents — no keys, no cloud, no metered bill.
works with Claude Code · Cursor · Codex · Gemini CLI · OpenCode · VS Code · Windsurf · Zed · Antigravity and beyond LangChain · CrewAI · LlamaIndex · Vercel AI SDK · n8n & self-hosted agents · any MCP client · plain REST
sponsored by
Quickstart · Tools · Why wigolo · Discord · Sponsors · Benchmark · Docs · Examples · Licensing · Feedback · FAQ
Join the community on Discord — questions, help, and what's being built next.
New features and updates ship steadily. Follow @yourtowhid on X for all of it and new ways to use wigolo, and reach out there for collaborations or feedback · also on LinkedIn
wigolo gives an AI agent one surface for everything web-related: search, fetch, crawl, extract, cache, find-similar, research, and autonomous gather loops. It runs wherever your agent runs — as an MCP server next to your coding agent, as a REST/MCP endpoint on the box where your self-hosted agents live, or embedded through an SDK inside your own app. The core tools need no API keys, nothing it touches leaves ~/.wigolo/, and no bill grows with how much your agent thinks.
Quickstart
npx wigolo init # set up the local engine — any system
npx wigolo init --agents=claude-code,cursor # …or set up + wire your day-to-day agents in one commandRequires Node ≥ 20 and ~1.5 GB of free disk on macOS, Linux, or Windows. Bare init sets up the local engine: it downloads the browser engine and on-device models, runs a health check, and reports each component. Adding --agents wires the named agents in the same run, so a coding agent you use daily is ready in one command.
Supported agents —
--agentstakes any ofclaude-code·cursor·codex·gemini-cli·opencode·vscode·windsurf·zed·antigravity(comma-separated); wigolo writes the MCP config and, where supported, instructions for each.Any other setup — any MCP client, agent framework, or self-hosted agent registers
npx -y wigoloin its own MCP config. The installation guide has the exact config block for every client, plus Docker, Homebrew, and single-file-binary channels.More on the way — the supported list keeps growing, and a PR to add your agent is welcome; see CONTRIBUTING.md.
Interactive setup —
--interactiveis a plain-text flow;--wizardis the full terminal TUI.Defer downloads —
--no-warmupwaits until first use. A failed component download never fails setup; init reports what's not ready with the exact fix and still completes.
init is unattended by default, so it's safe in scripts and CI, and any setup problem surfaces right here in the per-component report, before your agent's first call. Search, fetch, crawl, extract, cache, and find-similar work with no API key. Check it's healthy anytime:
npx wigolo doctorTo remove everything cleanly, run npx wigolo config --uninstall --yes. You can also paste the installation guide into any AI assistant and let it do the setup; it's written to be self-contained.
Recommended — a free key for research & agent
Search, fetch, crawl, extract, cache, and find-similar are fully keyless. research, agent, and search format=answer use an LLM to write the synthesized, cited answer. Without one they hand back a raw brief and evidence for your agent to assemble. A free Gemini key turns that into a finished answer:
export WIGOLO_LLM_PROVIDER=gemini
export GEMINI_API_KEY=<free-key> # grab one at aistudio.google.com/apikey — the free tier is plentyAny provider works (anthropic · openai · groq), or stay fully local and keyless with WIGOLO_LLM_PROVIDER=ollama (or any OpenAI-compatible URL). Set it in your shell or your agent's MCP env block. Providers, models, and the keyless local-model ladder are in the configuration guide.
Related MCP server: Lookout
What your agent gets back
Every search result is evidence the agent can act on. It carries a verbatim excerpt pinned to its exact position in the source, a citation ID the agent can quote, and a score it can inspect (abridged real shape):
{
"results": [{
"title": "Logical replication - PostgreSQL docs",
"url": "https://www.postgresql.org/docs/current/logical-replication.html",
"excerpt": "Logical replication is a method of replicating data objects…",
"citation_id": "src-1",
"source_span": { "start": 1042, "end": 1305 }, // byte-exact provenance
"evidence_score": { "final": 0.86, "semantic": 0.91, "lexical": 0.78, "engine_consensus": 3 }
}],
"citations": [{ "id": "src-1", "url": "…" }],
"freshness_signal": { "published": "2026-05-12", "confidence": "high" }
}Weak results get flagged as junk by wigolo's own scorer. Failed engines are reported and stale cache is labeled, so the agent always knows what it's standing on. Full response contracts per tool are in the tools reference.
Tools
Tool | What it does |
🔎 | Multi-engine web search (18 direct adapters) with rank fusion, ML reranking, and an explainable per-result score. Pass a query array for parallel breadth. Scope by domain and time range, match an exact phrase, or return image results. |
📄 | Load one URL through a tiered router that auto-escalates from plain HTTP to a headless browser engine on anti-bot challenges or SPA shells. Clean markdown + metadata + links. Handles PDFs, a single-heading |
🕸️ | Multi-page crawl — BFS, DFS, sitemap, or map-only. Per-domain rate limits, robots.txt respect, boilerplate dedup. |
🧩 | Structured data from a page: tables, metadata, JSON-LD, brand identity, named schemas (Article / Recipe / Product / …), or any custom JSON Schema. |
💾 | Query everything already seen — keyword or hybrid semantic. Plus stats, clear, and change detection. |
🧲 | Pages similar to a URL or a concept, via 3-way fusion of keyword + semantic + live web. |
🧠 | Decompose a question → fan out sub-queries → fetch sources → synthesize a cited report (or a structured brief the host LLM writes from). |
🤖 | Autonomous gather loop: plan → search → fetch → extract → synthesize, with a step log, time budget, and optional output schema. |
🔁 | See exactly what changed on a page since last visit; re-check on demand and deliver changes to a webhook. |
Every tool also runs from the terminal (wigolo search "…" --json), from an interactive shell with NDJSON piping (wigolo shell), over REST, and through the SDKs — CLI reference. Per-tool guides with the full parameter set are in docs/tools.md; runnable examples are in examples/.
Why it's different
wigolo isn't a free stand-in for the paid tools — it's built to match them. It's a focused web layer for your agents: an MCP and REST surface they call directly, with the search and extraction quality the paid services charge for. What separates it:
Built for agents. One MCP call fans out many queries across many engines in parallel, which a serial host tool-loop can't replicate. Every result carries transparent per-result scoring, and output is budget-aware.
Honest output. Stale cache, failed fetches, degraded backends, and truncation are surfaced in the result. When a bot-protected page can't be read, you get a labeled
blocked_by_challengefailure, not a challenge shell returned as content.$0 per query, free to re-query. Default search talks to public engines through direct adapters; the reranker and embeddings run on-device. Every response is cached, so asking again is instant and costs nothing.
Private by default. Cache, embeddings, models, and config live under
~/.wigolo/. Nothing reaches a third party unless you explicitly opt into an LLM for synthesis.
Here's what one real result looks like, dissected. It includes the failed engine and the weak result, because those are part of the answer too:
Benchmark
All four tools converged on the same core answer, and only one of them handed back verbatim, byte-pinned evidence while doing it.
One cold query ran live inside a single Claude Fable 5 session, fanned out to four web tools on equal footing (built-in WebSearch, wigolo, Tavily, Exa), and was judged by the agent on the evidence alone. All four converged on the same answer and the same top source, so the parity is demonstrated on-screen. wigolo alone returned verbatim excerpts pinned to byte-offset source spans, an explainable score decomposition, and live per-engine telemetry, and its own scorer flagged two weak results as junk. The cloud tools earn their place too: Exa rendered the official docs' comparison matrix in full. Run your own query and you'll see the same shape.
How it compares
wigolo | Firecrawl | Exa | Tavily | |
Multi-engine web search | ✅ | ✅ | ✅ | ✅ |
Fetch & structured extraction | ✅ | ✅ | ✅ | ✅ |
Whole-site crawl & map | ✅ | ✅ | — | ✅ |
Verbatim excerpts pinned to byte-offset source spans | ✅ | — | — | — |
Explainable per-result score decomposition | ✅ | — | — | — |
Persistent local memory — re-query instantly, offline | ✅ | — | — | — |
Query data stays on your machine | ✅ | — | — | — |
API key / account | none | required | required | required |
Cost per query | $0 | metered | metered | metered |
Feature standing as of July 2026 — check each vendor's docs for current state.
That last row compounds, because agents ask in bursts:
Beyond your editor
The same ten tools serve every kind of agent, over whichever surface fits: MCP for coding agents, REST for everything else, SDKs to embed, and framework wrappers to drop in.
REST API — wigolo serve
One process exposes a plain-JSON REST API next to the MCP transport. No MCP client needed, just curl:
wigolo serve # 127.0.0.1:3333 — loopback is open; off-loopback requires a token
curl -sX POST http://127.0.0.1:3333/v1/search \
-H 'Content-Type: application/json' \
-d '{"query":"local-first software","max_results":5}'POST /v1/{tool} covers all ten tools, GET /openapi.json is the OpenAPI 3.1 contract, and /mcp + /sse serve remote MCP clients from the same port. Bind past loopback and a bearer token is required, so the server fails closed by default. Point n8n, a Hermes-style assistant, or any self-hosted agent at it. → REST API
SDKs — TypeScript & Python
Thin, typed clients with an embedded local mode that finds or starts the daemon for you. No separate serve step.
TypeScript — npm install wigolo-sdk (zero-dep; Node / Bun / Deno / edge):
import { createLocalClient } from 'wigolo-sdk/local';
const { client, close } = await createLocalClient(); // reuse a running daemon, or spawn one
const res = await client.search({ query: 'local-first web search', max_results: 5 });
console.log(res.results.map((r) => r.title));
await close(); // stops the daemon only if this call spawned itPython — pip install wigolo (standard library only; sync + async):
from wigolo import local_client
with local_client() as client: # reuse a healthy daemon, or spawn one
res = client.search(query="local-first web search", max_results=5)
for r in res["results"]:
print(r["title"], r["url"])Framework integrations
Drop wigolo's tools into the framework you already use. You get the full ten-tool surface, including the cache / find_similar / research / agent that most framework web-tools don't ship:
Framework | Package | What you get |
LangChain |
| each tool as a |
CrewAI |
|
|
LlamaIndex |
| a |
Vercel AI SDK |
| tool factories for |
Docker
# stdio MCP — wire it into any MCP client as command: docker
docker run -i --rm -v wigolo-data:/data ghcr.io/knockoutez/wigolo
# HTTP server for remote / multi-client use
docker run -p 3333:3333 -v wigolo-data:/data \
-e WIGOLO_API_TOKEN=a-long-random-secret \
ghcr.io/knockoutez/wigolo serve --host 0.0.0.0The slim image lazy-loads models into the volume; ghcr.io/knockoutez/wigolo:latest-full preinstalls the browser engine. Versioned releases use the same -full suffix (for example, 0.3.1-full). Also on Docker Hub as towhid69420/wigolo. → installation & all channels
Agent skills
An 11-pack skill catalog teaches your coding agent to drive each tool well. It's installed by init and managed with wigolo skills add|list|remove. → skills
One note for self-hosters: some challenge-protected sites score IP reputation, so a datacenter IP won't clear walls a home connection would. wigolo labels those failures, and the self-hosting guide covers the opt-in proxy answer.
Star history
Refreshed daily from the GitHub API. Add a ⭐ if wigolo is useful to you.
Architecture
A single Node process speaks MCP (JSON-RPC over stdio). Everything heavy is local and lazy-loaded, so a zero-key install pays nothing for the parts it isn't using.
flowchart TD
A["🤖 AI agent<br/>any MCP client · REST · SDK"]
A -->|MCP over stdio| B["<b>wigolo</b><br/>10 tools · dynamic instructions<br/>in-process browser pool + cache + models"]
B --> C{"Tool layer"}
C --> T1["search · fetch · crawl · extract"]
C --> T2["cache · find_similar · research · agent"]
T1 --> F["⚙️ Fetch router<br/>tiered escalation, learned per domain"]
T1 --> S["⚙️ Search<br/>18 engines → rank fusion → ML rerank<br/><i>explainable evidence score</i>"]
T2 --> DB[("🗄️ Local cache<br/>keyword + vector index")]
T2 --> ML["🧠 On-device ML<br/>embeddings + reranker"]
F -.->|optional| LLM["☁️ LLM<br/>synthesis only · opt-in"]
S -.->|optional| SX["🔀 Aggregator backend<br/>opt-in legacy / hybrid"]
F --> WEB["🌍 Public web"]
S --> WEB
style B fill:#7c3aed,stroke:#5b21b6,color:#fff
style WEB fill:#0ea5e9,stroke:#0369a1,color:#fff
style DB fill:#1e293b,stroke:#334155,color:#fff
style LLM stroke-dasharray: 5 5
style SX stroke-dasharray: 5 5Code beats model. Deterministic work stays off the LLM: canonicalization, rank fusion, dedup, and schema matching. The model is reserved for judgment, opt-in, and capped per request. LLM-filled fields are checked against the source and nulled if absent.
Signal-driven routing. The fetch ladder escalates to a real browser on observable signals, not domain guesses: SPA markers, challenge bodies, thin content. It learns per domain, unlearns when a site stops needing it, and
wigolo tune listshows you exactly what it learned.Reads pages the way a browser does. Tiered fetching waits out interstitial challenges and reuses clearances per domain, politely: robots.txt respected, per-domain rate limits, research-grade volumes. When a wall stays up, the failure is labeled and reported.
Configuration
A clean install works out of the box. Three settings raise output quality:
# 1. Synthesis — the biggest lever (research / agent / search-answer write real prose)
export WIGOLO_LLM_PROVIDER=gemini # or anthropic / openai / groq / ollama (keyless)
export GEMINI_API_KEY=<your-key>
# 2. Wider retrieval funnel
export WIGOLO_SEARCH=hybrid # core engines + aggregator fallback
export WIGOLO_GITHUB_TOKEN=... # GitHub code search 10 → 30 req/min
# 3. Land more fetches, stay warm
export WIGOLO_TLS_TIER=auto # per-domain learned fetch hardening
export WIGOLO_EAGER_WARMUP=1 # pay the ~1s model load up frontPer-call habits that pay off: query arrays (["a","b","c"]) for parallel breadth · search_depth: "deep" for queries that matter · include_domains as a hard filter for docs lookups. The full reference covers every environment variable, config-file key, search backend, cache TTL, and serve limit; it's in the configuration guide.
Docs & examples
docs/ — the complete manual: getting started · installation & channels · configuration · tools reference · CLI & shell · REST API · SDKs & integrations · self-hosting · agent skills · plugins · troubleshooting & FAQ · privacy & security
examples/ — runnable, each with a README (and most with a terminal recording): one-shot CLI, NDJSON shell pipelines, REST via curl, TypeScript & Python SDKs, Vercel AI SDK tools, pointing self-hosted n8n at a remote wigolo, watch-with-webhook, and writing your own search-engine plugin. The docs are also rendered on the site at wigolo.app/docs.
Beta & feedback
wigolo is in public beta. Everything documented here works and is held to a 7,600-test suite; it's stable, and beta is about the polish bar. It stays beta until enough people have used it, kicked it, and starred it that calling it v1 means something. Your feedback shapes what comes next, and every report is read, usually the same day:
🐛 Report a bug — broke, misbehaved, surprised you
💡 Request a feature — something it should do
💬 Ask anything — questions, setups, show & tell
If wigolo earns a place in your setup, three things keep it going: a ⭐ star (it's how open source gets found), a ☕ coffee (the open-source version is the full product; commercial licenses fund it, not gated features), or an email that goes straight to the one developer who wrote the code.
Troubleshooting
wigolo doctor names any broken component and the exact env var or command that fixes it; wigolo doctor --fix repairs the common cases, and wigolo verify health-checks every component. A component failing during init doesn't break wigolo: init still exits 0, and core search / fetch / crawl / extract / cache work with no models and no browser. Quick hits:
Slow or failed downloads — re-run
wigolo warmup --all(or--browser/--embeddings/--reranker); they resume and retry.Browser won't launch on Linux —
wigolo warmup --browserinstalls the OS libraries (or prints the exact command).Native build error / unusual Node — use an LTS — Node 22 or 24 — or Node 26 (supported; Current until it becomes LTS).
Behind a proxy —
USE_PROXY=true+PROXY_URL; addNODE_EXTRA_CA_CERTSfor TLS-inspecting proxies.Your agent asks permission on every call — allow the tools in your client, then restart it; rules are read at session start. Details.
The full guide covers per-symptom fixes, a "what still works when X fails" map, platform notes (incl. linux-arm64), and offline installs: docs/troubleshooting.md.
FAQ
No catch by design. The expensive parts (ranking, embeddings, the browser engine) run on your hardware, so there's no per-query cost to recover and no reason for a meter. It's funded by commercial licenses and sponsors, and the AGPL legally prevents a switch into a closed hosted product.
The benchmark section above is a live 4-way run you can reproduce: everyday agent queries land at parity, the paid tools still win some deep-extraction edge cases, and crawling is where wigolo is strongest. Every result shows its scoring, so you don't have to take anyone's word for it.
It's engineered for exactly that: 18 engines fused with rank fusion (any one failing barely moves results), a tiered fetch ladder with per-domain learning, and an optional aggregator fallback. Degraded backends are reported in the output, and the local cache means everything already seen keeps working regardless.
wigolo reads the public web the way a browser does: robots.txt respected by default, per-domain rate limits, and research-grade volumes for one agent on one machine. It sits deliberately at the polite end of the spectrum.
Yes. If you're a company or building a commercial product on wigolo, please take a commercial license or sponsor the project. See LICENSING.md.
That's the on-device brain: a full browser engine plus the ranking and embedding models the cloud services run on their side and bill you for. Once it's on disk, every query uses it for free.
Available on
npm —
wigolo(primary channel — the Quickstart above)PyPI —
wigolo(Python SDK)Docker —
ghcr.io/knockoutez/wigolo·towhid69420/wigoloOfficial MCP Registry —
io.github.KnockOutEZ/wigolo
Homebrew, curl | sh, and the single-file binary are covered in the installation guide. Use one channel per machine; they all share ~/.wigolo.
Sponsors
Thank you to the sponsors below, who help keep wigolo maintained and free for everyone to use. Their support goes straight into the work.
TestMu AI (formerly LambdaTest) is the world's first full-stack agentic AI quality engineering platform, trusted by 18,000+ enterprises.
wigolo is free for everyone. If you or your company would like to help keep it maintained, there's room for more sponsors — reach out at ktowhid20@gmail.com, or see what sponsorship includes and the terms in SPONSORS.md. A one-off via Buy Me a Coffee is welcome too.
Contributing
Bug reports, feature requests, and PRs are all welcome; see CONTRIBUTING.md. Keep tool handlers thin, add tests, and run the suite before opening a PR. The friendliest entry point is the plugin system for custom search engines and extractors: add a search engine in ~100 lines, with a template in examples/plugin-search-engine.
License
Free and open source under the GNU AGPL-3.0, and it'll stay that way. If you're a company, or you're making money with wigolo, please take a commercial license or sponsor the project. That's what keeps it maintained. See LICENSING.md.
See SECURITY.md to report a vulnerability and TRADEMARK.md for use of the name.
wigolo is open source, free, and actively maintained. If it saves you a metered search bill, a ⭐, a sharp issue, or a ☕ coffee helps keep it sustainable.
Built and maintained by @KnockOutEZ · ktowhid20@gmail.com · X · LinkedIn
Available Tools
10 toolsagentARead-onlyIdempotent
Natural-language data gathering across sources. Plans queries + URLs from a prompt, executes in parallel, optionally extracts structured fields, synthesizes. Full step transparency.
LLM-optional: with a synthesis LLM configured it writes the summary; without one it returns gathered evidence + a step log (plus schema-shaped fields when a schema is given) — YOU write the summary from the returned evidence, never present the raw step log as a poor result. For best agent results configure a free LLM key (e.g. Gemini).
Key parameters:
prompt: NL description of what to gather (e.g. "pricing for the top 5 CRM tools").
urls: optional seed URLs.
schema: optional JSON Schema — extracts matching fields from each page and merges.
max_pages: default 10.
max_time_ms: default 60000.
stream: progress notifications per step.
max_tokens_out / include_full_markdown / citation_format: budget + shape controls.
Pipeline: plan → search+fetch in parallel within budget → optional schema extraction → synthesize. steps[] exposes every action with timing. Uses MCP sampling when supported; falls back to keyword extraction otherwise.
Returns result, sources[], pages_fetched, steps[], total_time_ms, sampling_supported.
| Name | Required | Description | Default |
|---|---|---|---|
| urls | No | Specific URLs to include in the data gathering | |
| prompt | Yes | Natural-language description of what data to gather | |
| schema | No | Optional JSON Schema -- extract structured data matching this schema from each page | |
| stream | No | Send progress notifications as each step completes | |
| max_pages | No | Maximum pages to fetch (default 10, max 100) | |
| max_time_ms | No | Maximum execution time in milliseconds (default 60000) | |
| max_tokens_out | No | Token-budget cap on total output. Uses cl100k-base BPE; non-OpenAI tokenizer counts may drift ~5-15%. When both max_tokens_out and max_chars are set, max_tokens_out wins. | |
| citation_format | No | Citation rendering style. 'numbered' (default) inline [N] markers; 'json' returns a citations[] array; 'anthropic_tags' wraps sources in <source id='...'> tags. | |
| include_full_markdown | No | Include full markdown body in the response. Default false on multi-result tools (returns evidence excerpts only); set true to restore. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, openWorld, idempotent, non-destructive), and the description layers real operational detail on top: the exact pipeline stages, parallel execution within budget, per-step timing via steps[], MCP sampling with a keyword-extraction fallback, and a warning not to surface the raw step log as a result. This is the kind of behavior the annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in one sentence, then organized into step-transparency, parameter, pipeline, and return sections — appropriate density for a 9-parameter tool. Minor redundancy: "Full step transparency" and the steps[] sentence in the pipeline block make the same point twice.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description discharges that burden by enumerating the return shape (result, sources[], pages_fetched, steps[], total_time_ms, sampling_supported) and explaining degraded-mode output. What's missing is failure/partial-result behavior and any notion of source-quality limits when the budget is exhausted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 and the schema already explains every param including citation_format's enum values. The description mostly restates defaults already present in the schema (max_pages 10, max_time_ms 60000) and adds only a single illustrative example for prompt, so it does not meaningfully exceed the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line states a specific resource and action: natural-language data gathering across sources, with the plan → fetch → extract → synthesize pipeline spelled out. An agent understands exactly what it gets back. However, it never names a sibling (research, search, crawl, fetch) to differentiate itself, despite 'research' sounding functionally close.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied through the example prompt ("pricing for the top 5 CRM tools") and the guidance on when synthesis is vs. isn't available, plus the instruction that the caller must write the summary from returned evidence. But there is no explicit when-not-to-use-this and no routing statement against the near-siblings 'research', 'search', or 'crawl'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cacheADestructive
Search previously fetched content without hitting the network. Run this BEFORE any search/fetch — cache hits return instantly with full markdown.
Key parameters:
query: FTS5 full-text search over cached markdown + titles (supports AND, OR, NOT, "phrase").
url_pattern: glob filter on URLs (e.g. "example.com").
since: ISO date — only entries cached after this date.
stats: true to get cache size, entry count, oldest/newest dates.
clear: true to delete matching entries.
Persists across sessions. No remote round-trip.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Search strategy when query is provided. "fts" (default) runs keyword-only BM25 over the FTS5 index. "hybrid" additionally runs semantic vector search and fuses both rankings with reciprocal rank fusion for higher-recall lookups; falls back to FTS when the embedding index is empty or unavailable. | |
| clear | No | Clear matching cache entries (requires at least one filter: query, url_pattern, or since) | |
| limit | No | Maximum number of results to return (default 20). | |
| query | No | Full-text search over cached content | |
| since | No | ISO date — only results cached after this date | |
| stats | No | Return cache statistics (total URLs, size, date range) | |
| url_pattern | No | Filter by URL glob pattern (e.g., "*example.com*") | |
| check_changes | No | Re-fetch all matching cached URLs and report which ones have changed. Returns a list of URLs with changed/unchanged status and diff summaries. Use with query or url_pattern to scope which cached entries to check. | |
| max_tokens_out | No | Token-budget cap on total output (cl100k-base BPE). Caps the aggregate size of all returned markdown bodies; bodies past the budget are truncated or dropped. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, openWorldHint=true, and readOnlyHint=false, so safety characteristics are conveyed. The description adds useful behavioral context — instant cache hits with full markdown, persistence across sessions, and no remote round-trip — but doesn't elaborate on what exactly gets deleted by clear or the irreversibility of that action. It's still helpful beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, followed immediately by usage guidance, then a bulleted list of key parameters. Every sentence earns its place, and there is no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (9 parameters, no output schema, destructive clear operation), the description is complete enough for correct invocation. It explains the tool's role, when to prefer it, key parameter semantics, and persistence. Missing details about some parameters are fully covered by the schema descriptions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all parameters. The description adds operational meaning for key parameters: FTS5 syntax support (AND, OR, NOT, phrases) for query, a glob example for url_pattern, and the ISO date format for since. This goes beyond the schema's terse descriptions, though it doesn't mention mode, limit, check_changes, or max_tokens_out.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Search previously fetched content without hitting the network.' It immediately distinguishes itself from the sibling tools search and fetch by positioning itself as a local cache lookup rather than a live network operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance: 'Run this BEFORE any search/fetch — cache hits return instantly with full markdown.' This directly tells the agent when to choose this tool over its siblings, leaving little inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
crawlARead-onlyIdempotent
Crawl a site from a seed URL and return content from many pages. Use for indexing docs, wikis, multi-page references. Built for offline reuse: every page lands in the local cache.
Key parameters:
strategy: "bfs" (default) | "dfs" | "sitemap" (fastest for doc sites) | "map" (URL-only discovery).
max_depth: link-following depth (default 2).
max_pages: page cap (default 20).
include_patterns / exclude_patterns: regex filters on URLs.
max_tokens_out / include_full_markdown / citation_format: budget + shape controls.
Returns pages[] with title, evidence, depth, and content_completeness (per page — full/partial/shell, so you can skip un-rendered shell pages). Content is deduplicated across pages (anchor-fragment aware). All pages are cached for later cache / find_similar queries.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Seed URL to start crawling from | |
| strategy | No | Crawl strategy: bfs (breadth-first), dfs (depth-first), sitemap (use sitemap.xml), map (URL-only discovery — returns list of URLs without content, faster than full crawl) | |
| use_auth | No | Use stored auth credentials (default: false) | |
| max_depth | No | Maximum link depth from seed (default: 2) | |
| max_pages | No | Maximum pages to crawl (default: 20) | |
| extract_links | No | Return link graph between pages (default: false) | |
| max_tokens_out | No | Token-budget cap on total output. Uses cl100k-base BPE; non-OpenAI tokenizer counts may drift ~5-15%. When both max_tokens_out and max_chars are set, max_tokens_out wins. | |
| citation_format | No | Citation rendering style. 'numbered' (default) inline [N] markers; 'json' returns a citations[] array; 'anthropic_tags' wraps sources in <source id='...'> tags. | |
| max_total_chars | No | Max total chars across all pages (default: 100000) | |
| exclude_patterns | No | URL regex blacklist — skip matching URLs | |
| include_patterns | No | URL regex whitelist — only crawl matching URLs | |
| include_full_markdown | No | Include full markdown body in the response. Default false on multi-result tools (returns evidence excerpts only); set true to restore. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses that every page is written to the local cache and reusable via cache/find_similar, that content is deduplicated anchor-fragment aware, and that per-page content_completeness flags let the agent skip un-rendered shells. These are meaningful side effects and data-quality traits not captured by readOnly/openWorld hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose in one sentence, then uses a compact parameter list and a return-shape paragraph. Some bullets restate defaults already in the schema, which is minor waste but not damaging.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter open-world tool with no output schema, it explains the return payload (pages[] with title, evidence, depth, content_completeness) and key controls. It omits mention of use_auth, extract_links, and max_total_chars, but those are documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 12 parameters and enum meanings. The description adds modest value (marking sitemap as fastest for doc sites, noting map is URL-only discovery, restating defaults) but largely mirrors what is already structured.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (crawl a site from a seed URL, return content from many pages) and scopes it with concrete use cases like indexing docs, wikis, and multi-page references. The 'many pages' framing implicitly separates it from the single-page fetch sibling, but it never names fetch/search explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use for indexing docs, wikis, multi-page references' gives clear positive context for selection. It stops short of explicit exclusions or naming alternatives like fetch for single pages or search for targeted lookups.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diffARead-onlyIdempotent
Compute a diff between two markdown bodies or two URL fetches.
Key parameters:
old: { url?, markdown?, content_hash? } — left-hand side. URL form reads from cache; cache miss returns a structured
cache_misserror (no network re-fetch).new: { url?, markdown? } — right-hand side. Same cache rules as
old.output: 'unified' (default, git-style patch) | 'hunks' (structured array) | 'summary' (line counts only).
granularity: 'line' (default) | 'word' | 'section'. Section walks H1/H2/H3 boundaries and tags each hunk with
section_title.
Returns { changed, summary, unified_diff?|hunks?, truncated? }. summary always present (added/removed/modified lines + total_changed_chars). Above the 5000-line cap the engine emits truncated: true plus an approximate summary — never silently degrades.
| Name | Required | Description | Default |
|---|---|---|---|
| new | No | Right-hand side of the diff. Requires one of { url, markdown }. | |
| old | No | Left-hand side of the diff. Requires one of { url, markdown, content_hash }. | |
| output | No | Diff output shape. unified=git-style patch, hunks=structured per-section, summary=counts only (added_lines / removed_lines / modified_lines / total_changed_chars where total_changed_chars = sum of added_line_chars + removed_line_chars across the LCS edit script). Default: unified. | |
| granularity | No | Diff granularity. line=per-line LCS (default). word=token-level LCS — hunks contain only the changed tokens, tighter than line for intra-line edits. section walks H1/H2/H3 boundaries. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses important behavior: URL inputs read from cache, cache misses return a structured `cache_miss` error with no network re-fetch, and diffs over 5000 lines are truncated with an approximate summary rather than silently degrading. These are meaningful operational details not covered by the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then uses compact bullet points for parameters, output modes, and return shape. Every section carries operational value without repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the nested parameters, lack of an output schema, and read-only annotations, the description is complete enough to invoke the tool correctly. It covers input forms, cache miss behavior, output modes, truncation limits, and return shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds useful meaning beyond the schema, especially that `old.url` reads from cache and can produce a structured `cache_miss` error, and that `section` granularity tags hunks with `section_title`.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Compute a diff between two markdown bodies or two URL fetches.' This clearly distinguishes it from sibling tools such as fetch, crawl, and extract, and an agent can identify its operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear contextual guidance for invoking the tool, including cache behavior for URL inputs and how to choose output and granularity. It does not explicitly name alternatives or say when not to use this tool, so it falls short of the full when/when-not/alternatives standard.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extractARead-onlyIdempotent
Extract structured data from a URL or raw HTML. Use for specific data points (tables, prices, schema fields) rather than whole-page markdown.
Key parameters:
mode: "selector" (CSS → text) | "tables" | "metadata" (title/author/date/og_* + JSON-LD) | "schema" (pass a JSON Schema) | "structured" (one-shot: tables + definitions + JSON-LD + chart hints + key-value pairs) | "brand" (name/tagline/description/logo_url/favicon_url/og_image_url/social_links/fonts + CSS-var colors, each with explainable provenance).
css_selector: required for mode="selector".
schema: required for mode="schema".
multiple: return all matches (mode="selector" only).
Prefer mode="structured" over chaining multiple extract calls — one response carries { tables, definitions, jsonld, chart_hints, key_value_pairs }. chart_hints surfaces SVG titles, aria-labels, figcaptions for charts whose data is JS-rendered. Metadata parity with fetch (same og_/canonical_url shape). mode: "brand" walks JSON-LD Organization/Brand/WebSite → OG/Twitter Card meta → <link rel=icon> → CSS custom properties → heuristic header/footer DOM; provenance records the winning source. Provenance enums: logo ∈ {json-ld, og:logo, link[rel=icon], heuristic, unknown}; colors ∈ {css-vars, palette-extraction, unknown}; fonts ∈ {css-vars, css-rule, inline-style, google-fonts-link, unknown}. Honesty: name and logo_url are unset when no explicit source emits them — favicons never promote to logo_url. mode: "schema" is evidence-only: LLM-sourced fields not present in source text are returned as null with a warning.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | URL to fetch and extract from | |
| html | No | Raw HTML to extract from (url takes priority if both provided) | |
| mode | No | selector | tables | metadata | schema (LLM-sourced fields verified against source; hallucinated values returned as null) | structured | brand (logo/favicon/colors/fonts/social_links with provenance; favicons never promote to logo_url) | |
| schema | No | JSON Schema defining fields to extract. Field names are matched against page content via CSS classes, ARIA labels, microdata, and JSON-LD. Required when mode="schema". | |
| multiple | No | Return array of all matches instead of first (default: false, only for mode="selector") | |
| css_selector | No | CSS selector to match (required when mode="selector") | |
| named_schema | No | Extract page data into a strict named schema (heuristic only; no LLM required). Mutually exclusive with `schema`. | |
| max_tokens_out | No | Token-budget cap on extracted output (cl100k-base BPE). Trims structured/table/schema results to fit; trailing rows or heavy keys are dropped first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, openWorld), and the description adds substantial behavior beyond them: the brand-mode resolution chain, provenance enums with their allowed values, the honesty guarantee that favicons never promote to logo_url, schema-mode's null-plus-warning for unverifiable fields, and what chart_hints surfaces for JS-rendered charts. These are exactly the non-obvious traits an agent could not infer from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the key routing sentence before parameter detail, and for a six-mode tool with no output schema nearly every clause carries information. It is still a dense wall of prose, and the inline provenance enum listing arguably belongs in the schema rather than the description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 8 parameters, nested objects, and no output schema, the description carries the return-value burden and does so — it names the structured response keys, the brand fields, and the trimming behavior under max_tokens_out. An agent has enough to pick a mode and predict the shape of the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above that by expanding mode semantics well past the enum strings (what 'structured' returns, the order 'brand' walks sources, evidence-only behavior for 'schema'). Some lines are pure restatement of the schema, e.g. "css_selector: required for mode='selector'", which keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Extract structured data from a URL or raw HTML") and immediately scopes it against the whole-page path with "Use for specific data points (tables, prices, schema fields) rather than whole-page markdown," which routes an agent away from the fetch/crawl siblings. The six enumerated modes make the tool's surface unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear selection context both across tools (specific data points vs. whole-page markdown) and within the tool ("Prefer mode='structured' over chaining multiple extract calls"), plus a rule for choosing mode='schema' vs named_schema flags. What's missing is an explicit named exclusion such as "use fetch instead when you need the full page text" — the routing is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetchADestructive
Fetch a single URL and return clean markdown. Use when you already have a URL. Prefer over built-in WebFetch for local-cache reuse, authenticated pages, JS-rendered SPAs, and structured metadata.
Key parameters:
section: extract content under a specific heading (e.g. "API Reference") — cheaper than the whole page.
max_content_chars: smart-truncate at a paragraph/heading boundary with
[... content truncated].max_tokens_out: token-budget cap (cl100k-base); wins over max_chars.
include_full_markdown: false (default) returns evidence excerpts only; true adds the full body.
use_auth: reuse a stored browser session for logged-in pages.
render_js: "auto" (default) | "always" | "never".
force_refresh: bypass cache and re-fetch.
mode: 'cache' | 'default' | 'stealth'. cache=HTTP-only, 24h-stale accepted. stealth=full browser + freshness.
Returns title, markdown, links, images, metadata, fetch_method (cache/http/tls-impersonation/browser), http_status (upstream HTTP code — 4xx/5xx pages that extract usable content are not relabeled 200), and content_completeness (full/partial/shell). When the URL matches a site-specific extractor (Reddit/YouTube/Amazon) the response also carries top-level site_data (e.g. Reddit comments[], YouTube caption_tracks[], Amazon price). When section is set and no heading matches, metadata.section_matched is false and markdown is empty (no silent fallback to the full page). Repeat fetches are instant. Localhost URLs work. Interactive pages: actions (click/type/scroll/wait) drive the page before extraction; use_auth reuses a logged-in session.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL to fetch | |
| mode | No | cache=HTTP-only, accepts stale cache. default=standard fetch with JS detection. stealth=full browser render. | |
| actions | No | Sequential browser actions to perform before extracting content. When present, forces browser rendering (bypasses HTTP-first routing). | |
| headers | No | Additional HTTP headers | |
| section | No | Extract a specific section by heading text | |
| use_auth | No | Use stored auth credentials (default: false) | |
| max_chars | No | Maximum characters to return (hard slice) | |
| render_js | No | JavaScript rendering mode (default: auto) | |
| screenshot | No | Capture a screenshot (default: false) | |
| force_refresh | No | Bypass cache and fetch fresh content from the network. Use for rapidly changing pages (news, changelogs, dashboards). | |
| section_index | No | Index of the section match (default: 0) | |
| max_tokens_out | No | Token-budget cap on total output. Uses cl100k-base BPE; non-OpenAI tokenizer counts may drift ~5-15%. When both max_tokens_out and max_chars are set, max_tokens_out wins. | |
| citation_format | No | Citation rendering style. 'numbered' (default) inline [N] markers; 'json' returns a citations[] array; 'anthropic_tags' wraps sources in <source id='...'> tags. | |
| max_content_chars | No | Smart truncate markdown to N chars at paragraph/heading boundary with [... content truncated] marker. Preferred over max_chars for AI agents. | |
| include_full_markdown | No | Include full markdown body in the response. Default false on multi-result tools (returns evidence excerpts only); set true to restore. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No output schema exists, yet the description discloses return fields (title, markdown, links, metadata, fetch_method, http_status, content_completeness), site-specific site_data, cache staleness semantics, and the explicit no-match behavior for `section`. It does not address the destructiveHint=true side — that `actions` (click/type) can mutate the target page — nor rate limits, which is a real gap for a tool annotated destructive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and routing, then a bulleted parameter list and a returns paragraph — easy to scan. Several bullets restate schema descriptions verbatim (mode, render_js, use_auth), which is waste given 100% schema coverage, but nothing is buried or redundant in a harmful way.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 15-parameter, nested-object, open-world tool with no output schema, the description still covers return shape, cache/freshness behavior, auth session reuse, JS rendering, failure semantics for `section`, and repeat-fetch speed. An agent has enough to call it correctly on first attempt.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds genuine decision guidance beyond the schema: `section` is cheaper than the whole page, `max_content_chars` truncates smartly vs `max_chars` hard slicing, `max_tokens_out` wins, and `include_full_markdown: false` returns excerpts only. It omits any mention of `citation_format`, `headers`, `screenshot`, or `section_index`.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Fetch a single URL and return clean markdown') and immediately delimits scope with 'Use when you already have a URL', which separates it from sibling search/crawl tools. An agent can pick it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear selection condition ('when you already have a URL') and names an alternative it beats (built-in WebFetch) with four concrete reasons. It never states when *not* to use it or routes to siblings like crawl/extract, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_similarARead-onlyIdempotent
Find content related to a URL or concept. Best after a successful crawl/fetch — the local cache makes recommendations cheap. Concept-only queries on a cold cache often return 0-2 weak matches; warm the cache first via crawl / fetch for materially better results.
Key parameters:
url: known-good page; its content + embeddings drive similarity.
concept: free-text alternative to url. Thin cache → expect
cold_startto fire.max_results: default 5.
include_cached: true (default) to search cache first; false = web only.
threshold: minimum fused score (0-1, default 0.5).
include_ranking_debug: opt-in per-result
ranking_debug{ fts5_rank, embedding_rank, web_rank, rrf_score } so you can audit which signal won.max_tokens_out / include_full_markdown / citation_format: budget + shape controls.
Pass either url or concept. Three signals fused via RRF: keyword (FTS5), embeddings, optional live web. Each result carries match_signals with embedding_rank, fts5_rank, fused_score. When local signals are weak (cache empty, no hits, or concept mode returns only 1-2 cache matches), the response carries cold_start — pass it verbatim to the user (tune WIGOLO_FIND_SIMILAR_COLD_START_THRESHOLD to adjust).
Returns results[], method ("hybrid" | "embedding" | "fts5" | "search"), cache_hits, search_hits, embedding_available, total_time_ms.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Find pages similar to this URL. The page is fetched (or read from cache) and its content analyzed for key terms. | |
| mode | No | Retrieval strategy: cache (local hybrid), web-expansion (key terms + web search), crawl-rank (1-hop crawl from seed URL + embed + cosine rank), or auto. | auto |
| concept | No | Find pages related to this concept or topic description. Use when you don't have a specific URL. | |
| threshold | No | Hard post-filter on match_signals.fused_score. Results below this raw fused score are dropped (empty array is correct when nothing qualifies). Default 0 (no filtering). Note: filters on the raw RRF/embedding score, not the normalized relevance_score. | |
| include_web | No | Supplement with web search if needed (default: true) | |
| max_results | No | Maximum results to return (default 10, max 50) | |
| include_cache | No | Search local cache for similar pages (default: true) | |
| max_tokens_out | No | Token-budget cap on total output. Uses cl100k-base BPE; non-OpenAI tokenizer counts may drift ~5-15%. When both max_tokens_out and max_chars are set, max_tokens_out wins. | |
| citation_format | No | Citation rendering style. 'numbered' (default) inline [N] markers; 'json' returns a citations[] array; 'anthropic_tags' wraps sources in <source id='...'> tags. | |
| exclude_domains | No | Never return results from these domains | |
| include_domains | No | Only return results from these domains | |
| include_full_markdown | No | Include full markdown body in the response. Default false on multi-result tools (returns evidence excerpts only); set true to restore. | |
| include_ranking_debug | No | Attach per-result ranking_debug { fts5_rank, embedding_rank, web_rank, rrf_score } so callers can audit disagreement between the three ranking sources. Off by default. Concept-mode results improve materially with a warm cache — run wigolo_crawl on the relevant docs before relying on concept-only retrieval. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/openWorld, and the description adds substantial behavior beyond them: the RRF fusion of three signals, the `cold_start` response flag and how to surface it, the cache-warming effect on cost and quality, and an env-var tuning hook. This is the kind of context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the usage condition and keeps parameter notes in a scannable bullet list. The cold-start/cache-warming point is repeated three times (main paragraph, concept bullet, ranking-debug bullet), which costs space without adding information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 13 parameters and no output schema, the description does the necessary work of enumerating the return fields (results[], method, cache_hits, match_signals, cold_start), which an agent could not get elsewhere. The value is undercut by the incorrect default values and the missing `mode` parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline would be 3, but the description actively misstates structured data: it says `max_results` default 5 (schema: 10), `threshold` default 0.5 (schema: 0), and names a parameter `include_cached` that does not exist (schema: `include_cache`). It also omits the `mode`, `include_domains`, and `exclude_domains` parameters entirely, so an agent trusting it would pass wrong defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Find content related to a URL or concept,' with the two supported input modes named up front. It doesn't explicitly contrast itself with the `search` sibling, so an agent must infer the difference, which keeps it at 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use guidance ('Best after a successful crawl/fetch') and explicitly names the alternative tools (`crawl`/`fetch`) as prerequisites for warm-cache usage. It also warns when results will be poor (concept-only on cold cache) and tells the agent what to do instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
researchARead-onlyIdempotent
Multi-step research on a complex question. Decomposes into sub-queries, searches in parallel, fetches sources, synthesizes a cited report. Beats chaining search + fetch manually for multi-source synthesis.
LLM-optional: with a synthesis LLM configured, the returned report is a written answer. Without one it returns a structured, cited brief (key_findings/highlights/sections) — YOU write the final answer from it; do not hand the user the raw structure as a weak result. For the best research quality a free Gemini API key (or any provider) is strongly recommended.
Key parameters:
question: the research question.
depth: 'quick' (~15s, 2 sub-queries) | 'standard' (~40s, 4 sub-queries, default) | 'comprehensive' (~80s, 7 sub-queries).
max_sources: override per-depth source count.
include_domains / exclude_domains: scope.
schema: optional JSON Schema — structures the report.
stream: progress notifications per phase.
max_tokens_out / include_full_markdown / citation_format: budget + shape controls.
Returns report (markdown with [N]), citations[], sources[], sub_queries[], depth, total_time_ms, sampling_supported, and brief with topics, highlights, key_findings, sections (overview.cross_references, comparison, gaps — gaps lists any named sub-entity research could not corroborate).
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | Research depth: quick (~15s), standard (~40s, default), comprehensive (~80s) | |
| schema | No | Optional JSON Schema -- structure the report to extract these fields | |
| stream | No | Send progress notifications as each research phase completes | |
| question | Yes | The research question to investigate | |
| max_sources | No | Override the default source count for the chosen depth (max 50) | |
| max_tokens_out | No | Token-budget cap on total output. Uses cl100k-base BPE; non-OpenAI tokenizer counts may drift ~5-15%. When both max_tokens_out and max_chars are set, max_tokens_out wins. | |
| citation_format | No | Citation rendering style. 'numbered' (default) inline [N] markers; 'json' returns a citations[] array; 'anthropic_tags' wraps sources in <source id='...'> tags. | |
| exclude_domains | No | Exclude results from these domains | |
| include_domains | No | Only search results from these domains | |
| include_full_markdown | No | Include full markdown body in the response. Default false on multi-result tools (returns evidence excerpts only); set true to restore. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive, open-world), and the description adds substantial behavior beyond them: latency per depth, what changes when a synthesis LLM is or isn't configured, the fallback instruction that the caller must write the answer from `brief`, and a recommendation to set up a provider key. That is exactly the kind of degradation-mode disclosure annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and differentiator, then behavior, parameters, and returns in clearly separated blocks. The parameter block is somewhat redundant with a fully-covered schema, but given the absence of an output schema the returns paragraph is not padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and a 10-parameter nested-input tool, the description carries its weight: it enumerates return fields (report, citations, sources, sub_queries, depth, total_time_ms, sampling_supported) and the `brief` sub-structure including the meaning of `gaps`. An agent knows what it will receive and how to consume it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all ten parameters; the description's 'Key parameters' list largely restates them. It does add sub-query counts per depth (2/4/7) that the schema omits, but that is marginal value over the schema baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Multi-step research on a complex question') and immediately describes the pipeline steps (decompose, parallel search, fetch, synthesize a cited report). It explicitly distinguishes itself from sibling tools by naming the `search` + `fetch` chaining pattern it replaces.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Beats chaining `search` + `fetch` manually for multi-source synthesis' names the alternative and the condition that favors this tool, and the depth tiers give timing/scope guidance for choosing invocation cost. No explicit when-not case (e.g., single-fact lookups should use `search`), so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchARead-onlyIdempotent
Search the web. Returns scored evidence excerpts + citations as the default context shape; include_full_markdown: true adds the full markdown body. Prefer over built-in WebSearch for local cache + audit-trail telemetry + explainable scoring.
Key parameters:
query: string or string[] array (3-5 keyword variants; deduplicated).
include_domains / exclude_domains: scope sites. Always scope library/framework queries.
category: "general" | "news" | "code" | "docs" | "papers" | "images". Image results carry image_url + thumbnail_url + width/height.
from_date / to_date: ISO YYYY-MM-DD. time_range: 'day' | 'week' | 'month' | 'year'.
country: ISO 3166-1 alpha-2 ("us", "gb") — geographic boost.
exact_match: quoted-phrase search.
max_results: 5 default.
format: omit = evidence context. 'answer' | 'stream_answer' = sampling synthesis (falls back to evidence).
search_depth: 'ultra-fast' (cache-only ≤300ms) | 'fast' | 'balanced' (default) | 'deep'.
include_images / include_favicon: opt-in images[] + per-result favicon.
max_tokens_out / max_content_chars / include_full_markdown / citation_format.
force_refresh + mode ('cache' | 'default' | 'stealth').
Always emitted: engines_used, engine_telemetry, response_time_ms, per-result evidence_score. Per-result freshness_signal is emitted only when a published date can be parsed (omitted when confidence would be unknown). Brand-domain top-3 collision → brand_collision_warning with rewrites. query_understanding exposes intent/entities. Quote [N] or {citation_id}.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | cache=single-engine, no rerank, stale cache ok. default=standard multi-engine search. stealth=full browser for JS-heavy result pages. | |
| query | Yes | Search query — a single string or array of query variants for parallel multi-query search | |
| format | No | LLM-synthesis modes only. Omit for default evidence shape. 'answer'/'stream_answer' request sampling synthesis (falls back to evidence). Retired values 'full'/'context'/'highlights' reject with a migration error. | |
| country | No | ISO 3166-1 alpha-2 country code (e.g. "us", "gb", "de"). Hint passed to engines that support a geographic boost (Bing cc=, DDG kl=, Brave country=); advisory, not a strict filter. | |
| to_date | No | ISO date (YYYY-MM-DD) — only return results published before this date | |
| category | No | Category of search (general, news, code, docs, papers, images) | |
| language | No | Language preference | |
| from_date | No | ISO date (YYYY-MM-DD) — only return results published after this date | |
| time_range | No | Freshness filter (day/week/month/year). Conservative: only drops results with a confidently-extracted published_date — pages with no parseable date pass through, so this is a precision-boost not a hard bound. For strict ranges use from_date+to_date with a date-aware category (news, papers). | |
| exact_match | No | Treat the query as a quoted phrase. Engines that honour `"..."` filter to phrase matches, and results without the exact phrase in title or snippet are dropped. | |
| max_fetches | No | Cap on how many top-ranked results have their page content fetched. Defaults to max_results. Set lower (e.g. 3) to keep snippet-only listings cheap and only deep-read the most relevant. | |
| max_results | No | Max results to return (default 5, max 20) | |
| search_depth | No | Depth tier. ultra-fast=cache-only (≤300ms); on miss emits notice and empty results. fast=engines only, no content fetch / rerank (≤1s). balanced (default)=full pipeline. deep=balanced + full enrichment. | |
| agent_context | No | Optional agent context for ranking + dedup. text is concatenated with the query before embedding; recent_urls are dropped from results. | |
| force_refresh | No | Bypass all caches (search results and page content). Use when you need the most current information. | |
| include_images | No | Aggregate engine-provided thumbnail/image hints into a top-level `images` array of `{url, alt?, source_url}`. Empty array if no engine surfaced one. | |
| max_highlights | No | Maximum highlights to return (default 10). Highlights are 1-3 sentence passages scored by relevance to the query. | |
| max_tokens_out | No | Token-budget cap on total output. Uses cl100k-base BPE; non-OpenAI tokenizer counts may drift ~5-15%. When both max_tokens_out and max_chars are set, max_tokens_out wins. | |
| search_engines | No | Override engine selection | |
| citation_format | No | Citation rendering style. 'numbered' (default) inline [N] markers; 'json' returns a citations[] array; 'anthropic_tags' wraps sources in <source id='...'> tags. | |
| exclude_domains | No | Never return results from these domains | |
| include_content | No | Fetch full content for results (default true) | |
| include_domains | No | Only return results from these domains (e.g. ["react.dev", "github.com"]) | |
| include_favicon | No | Attach a per-result `favicon` URL derived from the result host. Cached per-domain across the call. | |
| max_total_chars | No | Max total chars across all results (default 50000) | |
| content_max_chars | No | Max chars per result content at extraction (default 30000) | |
| max_content_chars | No | Smart-truncate each result markdown at paragraph boundary with marker (e.g. 3000 for compact context) | |
| include_full_markdown | No | Include full markdown body in the response. Default false on multi-result tools (returns evidence excerpts only); set true to restore. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/openWorld/idempotent, and the description goes well beyond them: default response shape, always-emitted fields (engines_used, evidence_score, response_time_ms), the conditional emission of freshness_signal, brand_collision_warning behavior, cache bypass via force_refresh, the fallback path when format=answer, and the fact that retired format values reject with a migration error. Latency budgets for ultra-fast (≤300ms) and fast (≤1s) plus the ultra-fast empty-result-on-miss behavior are exactly the kind of traps an agent needs disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded — the first sentence carries the core value proposition and the response shape before the parameter list. However, several bullets are near-verbatim restatements of schema descriptions that already have 100% coverage (from_date/to_date, category enum, max_results default 5, force_refresh, include_images), which costs tokens without adding information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 28-parameter tool with no output schema, the description carries the full burden of explaining return values and it does: default evidence shape, opt-in full markdown, conditional fields, citation rendering, and truncation controls. Combined with the mode/search_depth fallback semantics, an agent has enough to call this correctly on the first attempt.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine guidance beyond the schema: 3-5 query variants with deduplication, the instruction to always scope library/framework queries, and the note that image results carry image_url/thumbnail_url/dimensions. Some bullets merely restate schema text (from_date/to_date ISO format, category enum, max_results default), which keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ("Search the web") and immediately defines the default output shape (scored evidence excerpts + citations), which lets an agent predict the return contract. It positions itself against the built-in WebSearch, but says nothing about when to pick it over siblings like research, find_similar, or extract, so sibling differentiation is incomplete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete operational guidance: "Always scope library/framework queries" to include_domains, 3-5 keyword variants for the array form, omit format for the evidence shape, and search_depth tiers with latency expectations. It stops short of naming conditions that select a sibling tool (e.g. research vs search vs find_similar), so there is no explicit when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
watchADestructive
Schedule lazy re-checks of a URL and surface diffs on change. Persistent across sessions — jobs survive MCP server restarts.
LAZY EXECUTION — NOT CRON. There is no background daemon. Checks fire ONLY when:
You explicitly call
watch({ action: 'check', job_id }), ORAny OTHER wigolo tool runs and the job's interval has elapsed (overdue jobs are triggered fire-and-forget in the background). A job on an idle MCP server will not fire until the next tool call. Do not expect cron-like accuracy.
Key parameters:
action: 'create' | 'list' | 'check' | 'pause' | 'resume' | 'delete'.
url (create-only): must be a public http/https URL. Loopback, RFC 1918 ranges, link-local, and non-http(s) schemes are rejected at registration.
interval_seconds (create-only): minimum 60 — sub-minute polling is refused to respect target-site rate limits.
selector (create-only, optional): CSS selector for future selector-scoped diffs. Persisted now for forward compatibility; the diff is currently full-page.
notification (create-only, optional): 'inline' (default — change reports come back on the next
action: 'check') or a public webhook URL. Same SSRF guard asurl. Webhook delivery is best-effort POST — no retry / no queue / no backoff.job_id (check/pause/resume/delete).
list returns each job's staleness_seconds so you can see how overdue each check is: negative = not yet due, positive = overdue by N seconds. Pair with action: 'check' to force one immediately.
Idempotent create: identical url + interval + selector returns the existing job_id — does not duplicate the row.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Single-URL create: the URL to watch. Response carries `job` (singular) and `jobs:[job]` (legacy). Mutually exclusive with `urls`. | |
| urls | No | Batch create: register multiple jobs in one call. Response carries `jobs[]` only (no `job`). Mutually exclusive with `url`. | |
| action | Yes | Watch-job action. | |
| job_id | No | Required for action=check|pause|resume|delete. | |
| selector | No | Optional CSS selector to scope the diff to a subtree (create-only). | |
| notification | No | "inline" (return on next check) or a webhook URL. Default: inline. | |
| interval_seconds | No | Required for action=create. Minimum check interval (min 60). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Rich disclosure beyond annotations: persistence across restarts, fire-and-forget triggering on sibling tool calls, SSRF rejection at registration, a 60-second floor for target-site rate limits, and best-effort webhook delivery with no retry/queue/backoff. One nuance conflicts with annotations — the description says `create` is idempotent while `idempotentHint=false` — though that hint remains defensible for `check`/`delete`, so this is a clarification rather than a hard contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the single most important fact ('LAZY EXECUTION — NOT CRON') before any parameter detail, and the bulleted parameter block is scannable. A few lines merely restate the schema's action enum and create-only flags, which is the only mild redundancy in an otherwise dense, purposeful text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given seven parameters, six actions, no output schema, and an unusual lazy-execution model, the description covers lifecycle, trigger conditions, failure modes, idempotency, and the one return field that matters (`staleness_seconds`). An agent could invoke every action correctly from this text alone.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline would be 3; the description goes well past it by adding constraints (public http/https only, loopback/RFC 1918/link-local rejected, interval min 60), the forward-compatibility caveat that `selector` is persisted but diffs are currently full-page, and the meaning of `staleness_seconds` (negative = not due, positive = overdue by N).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+outcome: 'Schedule lazy re-checks of a URL and surface diffs on change,' which immediately separates it from the one-shot `fetch`, `crawl`, and `diff` siblings. It does not, however, explicitly name any sibling and contrast itself with `diff` (which presumably does a one-shot comparison), leaving a small inference gap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when checks fire ('ONLY when: 1... 2...'), what does NOT happen ('no background daemon', 'not cron'), and pairs `list` with `check` to force immediate execution. The action enumerations are each given a context of use rather than left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.3.0- Added
crawl - Added
extract - Added
watch
6 tool updates
v0.2.1- Added
agent - Added
diff - Added
fetch - Added
find_similar - Added
research - Added
search
2 tool updates
v0.2.0- Added
cache - Removed
crawl
9 tool updates
v0.2.0- Removed
agent - Removed
cache - Removed
diff - Removed
extract - Removed
fetch - Removed
find_similar - Removed
research - Removed
search - Removed
watch
10 tool updates
- First observed
agent - First observed
cache - First observed
crawl - First observed
diff - First observed
extract - First observed
fetch - First observed
find_similar - First observed
research - First observed
search - First observed
watch
TDQS
Scored across 10 tools
Core acquisition tools (fetch, crawl, search, cache) have clearly distinct roles, and descriptions explicitly steer between them (e.g. 'prefer over built-in WebFetch', 'run cache BEFORE any search'). However, `research` and `agent` overlap substantially — both plan queries, fetch sources in parallel, optionally apply a schema, and synthesize with optional LLM — and `find_similar` vs `cache` both search local cached content, so a few tools could be misselected without careful reading.
Mostly consistent single-word verb naming (fetch, crawl, search, extract, research, diff, watch), which reads predictably. Minor deviations: nouns used as tools (`cache`, `agent`) and one verb_adjective form (`find_similar`), but nothing chaotic.
Ten tools is well within a healthy scope for a web acquisition/research server, and each maps to a recognizable capability. The count is slightly inflated by pairs of near-variants (research/agent, cache/find_similar) that could arguably be consolidated into one tool each.
Strong lifecycle coverage for the domain: discovery (search), retrieval (fetch/crawl), offline reuse (cache), structured extraction (extract), comparison (diff), change monitoring with full job CRUD (watch), and synthesis (research/agent). Minor gaps: no explicit multi-URL batch fetch outside `agent`, and no declared handling for PDFs/documents or sitemap-only listing as a standalone operation.
Maintenance
Related MCP Connectors
Scrape, crawl and search the web for AI agents via MCP.
One MCP server for all web data. Scrape, search, crawl, and AI research in one install.
Scrape, map, crawl, search and monitor the web. Runs locally with no API key, cites every source.
Web search API and MCP server for developers building AI agents.
Related MCP Servers
- AlicenseAqualityAmaintenanceA local-first, no-API-key MCP server that enables LLMs to search the web, fetch pages, and read documents using multiple engines and smart fallbacks.11169MIT
- 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.65 npm1MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to perform local-first web search, fetch, crawl, extract, cache, research, and autonomous information gathering through MCP, with no API keys or cloud dependencies.1,154 npmAGPL 3.0
- AlicenseAqualityAmaintenanceEnables AI agents to run local deep-research workflows via a single MCP stdio server, combining web search, page extraction, query-aware distillation, and caching without cloud quotas. It exposes tools for deep research, search, and single or batch URL reading.6MIT