websearch
Searches the web through Brave as a primary keyless search engine, returning title/URL/snippet result blocks.
Searches the web through DuckDuckGo as a primary keyless search engine, returning title/URL/snippet result blocks.
Fetches GitHub repository READMEs as Markdown by rewriting github.com/o/r URLs to the GitHub README API, avoiding the repository UI chrome.
Provides fallback web search through Google when the primary keyless search tier returns no results.
Searches the web through Mojeek as a primary keyless search engine, returning title/URL/snippet result blocks.
Searches the web through Startpage as a primary keyless search engine, returning title/URL/snippet result blocks.
Searches Wikipedia as one of the primary keyless search tiers, returning result titles, URLs, and snippets.
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., "@websearchsearch the web for the latest Python 3.14 release notes"
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.
mcp-websearch
web_search as an external MCP tool for Qwen Code, ported from Unsloth Studio's server-side tool
loop. Same engine tiers, same SSRF and domain-policy gates, same result format. No API key needed.
If ~/.qwen/websearch-keys.json holds a SerpApi key, a sweep that fails on all free tiers falls back
to it; an honest empty sweep never does.
Qwen Code ─MCP/stdio→ server.py → ddgs → tier 1: wikipedia brave duckduckgo mojeek startpage
└────→ tier 2: grokipedia google yahoo (only if tier 1 is empty)
└────→ tier 3: serpapi.com (only if both tiers fail, key set)Engines outside those tiers — Yandex, Bing, the mullvad mirrors — are never contacted. Tier 3 is this fork's own paid fallback, not upstream, and is inert without a key.
Install
cd mcp-websearch
python3 -m venv .venv
.venv/bin/python -m pip install --require-hashes --no-deps -r requirements.lock
.venv/bin/python -m pip install --no-deps -e .
python3 scripts/build_port.py # generate the verbatim surface from tools.py
.venv/bin/python scripts/align.py --bump
.venv/bin/python -m pytest -q tests-m pip and -m pytest, never .venv/bin/pip: a venv is not relocatable, so its script
shebangs break the moment the directory moves.
Related MCP server: websearch-skill
Supply chain
requirements.lock is the boundary. 45 exact pins, 778 sha256 digests, installed with
--require-hashes --no-deps — so a compromised PyPI release cannot be adopted silently, and a new
or changed dependency only enters by a diff you commit.
pyproject.tomlpinsmcp==2.2.0, not a range. An open bound means every install silently takes the newest SDK.tests/test_supply_chain.pyfails if any pin is unhashed, if any installed dist is not named by the lock, or if a*exporter*telemetry package appears anywhere in the set.opentelemetry-apiis unavoidable (mcprequiresopentelemetry-api>=1.28.0). API only, no exporter installed, so nothing exports — recorded here so its presence is a decision, not a discovery. An exporter appearing is a hard finding.
Egress gate
scripts/check_egress_mcp.py is the MCP-side mirror of the fork's §18. A CONNECT-only proxy on
loopback records which hosts the tiers actually reach — the tunnel is never decrypted, so no CA is
installed and nothing is a man in the middle. Test-time only: normal operation has no proxy.
.venv/bin/python scripts/check_egress_mcp.pyExit 0 = every destination inside the tiers · 1 = a host outside them · 2 = the detector is
blind (self-test canary missed, or primp bypassed the proxy). The allowlist is derived from
_SEARCH_ENGINE_TIERS through ENGINE_HOSTS, so adding an engine without mapping its host fails
the build rather than widening egress silently.
Run it: every release · every requirements.lock bump · after realignment · after any change to
fetch.py or the tier list. It issues one live query.
Verified on primp 2.0.1 / ddgs 9.14.4: the tiers do honour HTTPS_PROXY — all eight
engine hosts arrive as CONNECT records and the search still succeeds. The proxy is a real control
point here, not a dead one.
Add to Qwen Code
qwen mcp add websearch "$(pwd)/.venv/bin/python" "$(pwd)/server.py" \
-t stdio -s user --description "Keyless web search, ported from Unsloth Studio"-s user → ~/.qwen/settings.json; -s project → .qwen/settings.json. Restart the session, then
/mcp should list websearch with one tool, web_search. The model sees it as
mcp__websearch__web_search — the mcp__<server>__ prefix is forced by the client and cannot be
overridden. Hand-edits preferred:
qwen-mcp-snippet.json.
Do not pass --trust. url mode fetches a page whose host the model chose; the client's
per-call confirmation is the gate that makes that safe, mirroring upstream's _web_search_fetches_url
prompt. Trusting the server removes it.
Use
call | what happens |
| tiered search → |
| one page → Markdown ( |
| rewritten to the GitHub README API — you get the README, not the repo's UI chrome |
| pushed in as |
| refused at policy time |
Env
var | default | |
|
| fetched-page cap |
|
| results per search |
|
|
|
| unset |
|
| auto-detected | path to an unsloth clone, for |
How the port is built
58 of the 63 ported symbols are machine-generated from upstream's AST, so they cannot drift by transcription:
tools.py ──build_port.py──▶ upstream_verbatim.py (GENERATED) ──import──▶ fetch.py · search.py
└── 5 hand-adapted functionssurface | ||
|
| AST-extracted from |
|
| byte-exact |
|
| the only places local judgement was applied |
Faithful: engine tier allowlist + registry resolution, non-public-IP refusal, DNS pinning with correct SNI, one wall-clock budget across tiers and redirect hops, capped chunked body read, binary rejection by MIME then magic, HTML→Markdown, GitHub README routing, every model-facing string.
Not here (by choice): image search + thumbnail registry, PDF text extraction, <meta refresh>,
WHATWG charset prescan, context-window page sizing. Reasoning per item: ALIGNMENT.md.
Stay aligned
scripts/align.py --diffReads only the pinned symbols, never all of tools.py. Reports SYNCED / REVIEW / DRIFTED / BROKEN
and prints the upstream body to apply. Full contract: ALIGNMENT.md.
Layout
server.py MCP stdio entrypoint (mcp SDK v1 FastMCP and v2 MCPServer both work)
unsloth_search/
upstream_verbatim.py GENERATED — 58 symbols extracted from tools.py, do not edit
web_access_policy.py vendored byte-exact
_html_to_md.py vendored byte-exact, stdlib-only
fetch.py adapted fetch layer
search.py adapted tier loop + approved_engines()
__init__.py package edge
.align/manifest.json the sync contract (committed)
scripts/build_port.py generates upstream_verbatim.py
scripts/align.py the drift checker
tests/ tiers (mirrored upstream) + guards + fidelityAGPL-3.0-only, matching upstream (COPYING / studio/LICENSE.AGPL-3.0 in unslothai/unsloth).
This server cannot be deployed
Maintenance
Related MCP Connectors
Free web search for AI agents. No API key required. Hosted MCP in active development.
Live AI-native web search with citations. One tool for every MCP client. Flat per-request pricing.
Docs: https://docs.keenable.ai/mcp-server Keenable is a free, remote MCP server that gives agents access to the web index. Search the web with ranked results and date/site filters, then fetch any indexed page as clean markdown. Works out of the box with no account or API key.
Search the agentic web. 4,100+ sites, 11 tools incl. check_url + verify_mcp for probe-before-use.
Related MCP Servers
AlicenseNot gradedqualityDmaintenanceEnables web search, scraping, extraction, and crawling through an MCP interface, allowing coding agents to access real-time web data.1MIT- AlicenseAqualityBmaintenanceEnables AI agents to perform multi-engine web search, fetch web pages, and extract clean Markdown content via MCP, with no API keys required.352 PyPI8MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to search the live web and extract readable page content as MCP tools, with ranked results, domain filters, and news support.29 npmMIT
- AlicenseBqualityBmaintenanceEnables AI agents to perform web searches and extract full-text content from web pages via standard MCP tools, with fallback search and semantic reranking.22MIT