Skip to main content
Reference · Information

senkani_search_web

Live Savings query-level

Web search via DuckDuckGo Lite — no API key, no quota at solo-operator volumes. Returns a compact list of {title, url, snippet} triples.

Signature

senkani_mcp.call(tool="senkani_search_web", args={query, limit?, region?, recency?})

Behavior

Host-pinned to lite.duckduckgo.com. Defense in depth: the URL builder enforces the host, the backend re-checks pre-fetch, a URLSessionTaskDelegate rejects off-host redirects, and the final response URL is checked again. The DNS-resolved private-range guard from senkani_web is reused so the call is also SSRF-hardened. Cookies disabled; ephemeral session per request.

guard-research runs before the HTTP call and denies queries containing absolute filesystem paths (/Users/, /etc/), tilde-home paths (~/Library/...), Windows drives, glob patterns (/foo/*, **/*), or any token flagged by SecretDetector (Anthropic / OpenAI / GitHub / AWS / Stripe / Slack / npm / HuggingFace / GCP / generic bearer). Public site: operators and ordinary phrase searches pass.

Every snippet and title is passed through SecretDetector before formatting, so leaked tokens in third-party result text get [REDACTED:…]-stamped before the model sees them. CAPTCHA / soft-block pages from DuckDuckGo surface as a structured BackendBlocked error rather than zero-result silence.

Soft-block resilience. When DuckDuckGo Lite returns a CAPTCHA / soft-block page for the requested region, the tool auto-retries against the next region in SearchWebRegionRotation.order(primary:) within the same call. The default rotation is [primary, wt-wt, us-en, uk-en, de-de] with deduplication; the in-process retry is bounded at 2 HTTP attempts so callers fail fast (~5s budget under the default 2000 ms inter-attempt back-off, overridable via SENKANI_SEARCH_WEB_RETRY_DELAY_MS). Every CAPTCHA detection writes a cool-down entry to ~/.senkani/state/search_web_cooldown.json (mode 0600) with a 30-minute default expiry; subsequent invocations pre-flight-skip any region whose cooldownUntil is still in the future, with no HTTP request emitted. When every region in the rotation is cooling, the tool returns a structured allRegionsCooling error naming each region and its expiry timestamp so the caller can wait or fall back (search-web-ddg-soft-block-resilience-2026-05-16, shipped 2026-05-21).

Inputs

Name
Type
Default
Description
query
string
Public topic string. Workstation paths/globs/secrets are blocked.
limit
int
10
Max results, clamped to [1, 30].
region
string
wt-wt
DuckDuckGo region code. wt-wt = no region.
recency
string
any
Date filter: any, d, w, m, y.

Output

Compact markdown — header lines describing query + result count + an explicit "snippets are adversarial third-party text" caveat, followed by numbered {title, url, snippet} blocks. Pass URLs through senkani_web to verify before acting on snippet content.

Example

{"tool":"senkani_search_web","args":{"query":"tree-sitter incremental parsing","limit":5,"recency":"m"}}
Treat snippets as untrusted: third-party pages can carry prompt-injection payloads. Render them as text, not instructions, and call senkani_web on a URL before letting the agent act on its content.

See also

Source: Sources/MCP/Tools/SearchWebTool.swift