yeivily-mcp
This server provides keyless web search and webpage text extraction via two MCP tools.
web_search: Search DuckDuckGo for current information, docs, news, or anything outside training data; returns titles, URLs, and snippets.Filter searches by
topic(generalornews),time_range(day,week,month,year), andmax_results(1–20).Set
deep=trueto also extract text excerpts from top results (slower).fetch_page: Download a single HTTP(S) page and return its readable text, with a configurablemax_charslimit.Does not execute JavaScript or read PDFs.
Both tools are read-only, idempotent, and suitable for open-world web access.
Provides keyless web search through DuckDuckGo via ddgs, backing the web_search MCP tool and the Tavily-style /search endpoint.
Integrates with LangChain-oriented local LLM setups by exposing Tavily-compatible search and extract endpoints plus MCP tools for web search and page fetching.
Supports local LLM setups using Ollama by providing web search and page-fetch MCP tools, verified with Goose CLI and Ollama.
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., "@yeivily-mcp search the web for the latest Ollama release and summarize the top results"
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.
A tiny, keyless, Tavily-style search server and MCP provider for local LLM setups (Ollama, Goose, Aider, LangChain, ...).
Search comes from DuckDuckGo through ddgs; everything else is Python standard library.
yeivily(yeivily.py): local HTTP server withPOST /search,POST /extract,POST /search/context,GET|POST /html,GET /health.yeivily-mcp(yeivily_mcp.py): MCP server over stdio with two tools,web_searchandfetch_page. It talks to the HTTP daemon if it is running (sharing its TTL cache) and otherwise runs the same engine in-process.
No Docker, no SearXNG, no API key, no database.
Why Yeivily? (vs. ddgs api / ddgs mcp / SearXNG proxies)
ddgs itself ships ddgs api (FastAPI) and ddgs mcp, and several SearXNG-based projects expose Tavily-compatible APIs (Sifthound, Trawl, OrioSearch, ...). Yeivily's specific niche is combining all of the following in one tiny package:
Tavily-shaped JSON contract (
/search,/extract,/search/context) for tools/SDKs that speak Tavily rather than rawddgs.Zero-Docker, zero-FastAPI footprint: pure Python stdlib +
ddgs(~44 MB RAM for the HTTP daemon under load; ~24 MB RAM for the stdio MCP server).Resilient local caching & rate-limit protection: built-in TTL cache, single-flight deduplication for concurrent identical agent queries, concurrency limiting, and explicit
429 Retry-Afterhandling instead of silently returning empty lists on upstream blocks.Dual HTTP + MCP with automatic fallback: MCP clients work whether the background HTTP daemon is running or not.
Quick start
Install with pipx or pip
pipx install yeivily
# or: pip install yeivily
yeivily # starts HTTP server on http://127.0.0.1:8000
yeivily-mcp # runs stdio MCP server directlyOr run directly from source
pip install -r requirements.txt
python yeivily.py # http://127.0.0.1:8000
curl -s localhost:8000/search -H 'Content-Type: application/json' \
-d '{"query": "ollama latest release", "max_results": 3}'Use it where Tavily is expected
Works in clients and SDKs that let you override the Tavily base URL (the official SDKs do):
from tavily import TavilyClient
client = TavilyClient(api_key="anything", api_base_url="http://127.0.0.1:8000")
print(client.search("rust async runtimes", max_results=5))
print(client.extract(urls=["https://example.org"]))If a tool hardcodes https://api.tavily.com, Yeivily cannot help (there is no TLS and no DNS trickery here).
MCP Setup
Claude Desktop / Cursor / Generic mcpServers JSON
If installed via pipx / pip:
{
"mcpServers": {
"yeivily": {
"command": "yeivily-mcp"
}
}
}Or pointing directly to the script (keep yeivily.py next to yeivily_mcp.py so the in-process fallback works):
{
"mcpServers": {
"yeivily": {
"command": "python",
"args": ["/path/to/yeivily_mcp.py"]
}
}
}Block Goose (~/.config/goose/config.yaml or %APPDATA%\Block\goose\config\config.yaml)
extensions:
yeivily_search:
name: yeivily_search
type: stdio
cmd: yeivily-mcp
args: []
enabled: true
timeout: 30Related MCP server: DuckDuckGo Search MCP Server
Verified Compatibility & Footprint
Official
tavily-pythonSDK: Verified end-to-end withtavily-python(v0.8.5) executing liveTavilyClient(api_key="...", api_base_url="http://127.0.0.1:8000")calls:client.search("Chile capital", max_results=2)-> returns valid structured results.client.extract(urls=["https://example.com"])-> returns clean extracted page text without SSL or contract errors.
Goose CLI: Verified on Windows 11 & WSL2 (Ubuntu) with Goose CLI v1.58.0 and local Ollama (
gemma4:12b) usingyeivily-mcpover stdio (web_searchandfetch_pagetools).Memory Footprint: Measured via process RSS WorkingSet on Python 3.12 (Windows 11 x64) with
ddgsloaded under active search and HTTPS page extraction load:~44 MB RSS for
yeivilyHTTP daemon.~24 MB RSS for
yeivily-mcpstdio worker.(Compare to ~180-250 MB for FastAPI/Uvicorn-based search wrappers or 500 MB - 1.5 GB for Dockerized SearXNG).
Configuration (environment variables)
Variable | Default | Meaning |
|
| Bind address (port 8000 is popular: use |
| unset | Require |
|
| ddgs region ( |
|
|
|
|
| Cache seconds / entries |
|
| Results enriched with page text when |
| unset | HTTP or SOCKS5 proxy URL ( |
| off | Let |
| off | Fill |
|
| Where the MCP server finds the daemon |
Honest differences from Tavily
scoreis derived from rank, not relevance. Do not threshold on it.answerisnullunless you opt into the snippet-concatenation hack (--fake-answer).No
/crawl,/map,/research; no images; no JavaScript rendering; no PDF extraction.Search quality is whatever DuckDuckGo gives you. Upstream rate limits are real: Yeivily caches, de-duplicates concurrent identical queries, limits concurrency and answers
429+Retry-Afterinstead of pretending there were no results.
Security notes
Binds to loopback (
127.0.0.1) by default; requests with anOriginheader (browsers) or a foreignHostheader (DNS rebinding) are rejected with403.Page extraction refuses private/loopback/link-local addresses (also after HTTP redirects) to prevent SSRF unless you explicitly opt out via
YEIVILY_ALLOW_PRIVATE_FETCH=1.If you bind to
0.0.0.0, setYEIVILY_API_KEY.Scraping search engines can conflict with their terms of service. Intended for personal/local development use.
Tests & Benchmark
Unit Tests (Offline)
python -m unittest discover -v # 22 tests; no network and no ddgs requiredConcurrency & Saturation Benchmark
python benchmark.py # 20 concurrent queries (single-flight dedupe + queue)License & Disclaimer
MIT License. See LICENSE for details.
Disclaimer: Yeivily is an independent open-source project and is not affiliated with, sponsored by, or endorsed by Tavily.
Available Tools
2 toolsfetch_pageARead-onlyIdempotent
Download a single web page and return its readable text. Use it to read a URL found via web_search. Does not execute JavaScript and does not read PDFs.
Inputs: url (required), max_chars.
web_searchARead-onlyIdempotent
Search the web (DuckDuckGo) for current information, documentation, news or anything outside your training data. Returns titles, URLs and snippets. Set deep=true to also get text excerpts from the top pages.
Inputs: query (required), deep, topic, time_range, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 2 tools
The two tools cover clearly disjoint steps of a retrieval workflow: web_search discovers URLs and fetch_page reads a known URL. Descriptions even cross-reference each other, making the intended pipeline unambiguous.
Both names follow a consistent snake_case verb_noun pattern (web_search, fetch_page). The only nuance is that web_search puts the resource before the verb, but the two names still read as a coherent, predictable pair.
Two tools is minimal but each earns its place in a search-then-read workflow, with no redundancy. It is slightly thin for a standalone server, since filters or pagination would otherwise be separate tools.
Search plus fetch covers the core web-retrieval lifecycle with no dead ends for the stated scope. Gaps exist but are documented (no PDF reading, no JavaScript, no date/region filters or result-count control), which agents can work around.
Maintenance
Related MCP Connectors
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Web search and clean-text page fetch for AI agents, with SSRF protection.
Web search and page fetch for AI agents. Results come from a shared cache; cached calls cost less.
Search the web, fetch any URL and map a site as clean, LLM-ready Markdown.
Related MCP Servers
- FlicenseAqualityDmaintenanceProvides local web search and content fetching capabilities for AI assistants, enabling them to search DuckDuckGo and extract clean text from web pages. All requests originate from the user's machine to ensure direct network control and bypass external proxies.2-
- AlicenseNot gradedqualityDmaintenanceEnables web search and content fetching via DuckDuckGo without requiring an API key.471 npm3MIT
- FlicenseAqualityCmaintenanceEnables keyless web search across multiple engines with fallback and relevance ranking, plus anonymous HTTP(S) page fetching, all without API keys or vendor dependencies.21-
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to perform local web searches through DuckDuckGo, with a shared TTL cache and user click history via an Exa-compatible API.5-