Skip to main content
Glama
DanielNMC
by DanielNMC

uvxwebsearchmcp

A zero-config web search and fetch MCP server for LLM agents. Wraps ddgs (multi-backend metasearch) with a persistent rolling cache and structured, retry-friendly error envelopes.

Why

LLM agents need a web search tool that survives bursty query patterns. Single-engine scrapers die on HTTP 429 within minutes. uvxwebsearchmcp solves this by:

  • Multi-backend fan-out via ddgs's backend="auto" — every search tries up to 10 engines.

  • Persistent 15-minute rolling cache — repeated agent queries don't re-hit upstream.

  • Structured error envelopes — agents see retryable: bool, retry_after_seconds, hints, and attempts instead of opaque stack traces.

  • Zero API keys, zero config — install and run.

Related MCP server: webmcp

Install

This package lives in a private Git repository, so you cannot use the plain uvx uvxwebsearchmcp form (that requires PyPI). Use one of these forms instead, depending on your auth:

# SSH key auth (recommended — uses your ssh-agent, no secrets in URL)
uvx --from git+ssh://git@github.com/DanielNMC/web_tools_mcp.git uvxwebsearchmcp

# GitHub PAT auth (works in CI; replace ghp_xxx with your token)
uvx --from "git+https://ghp_xxx@github.com/DanielNMC/web_tools_mcp.git" uvxwebsearchmcp

# Pin to a tag for reproducibility
uvx --from "git+ssh://git@github.com/DanielNMC/web_tools_mcp.git@v0.1.0" uvxwebsearchmcp

uvx creates an ephemeral venv, installs the package + its dependencies (ddgs, diskcache, mcp), runs the server on stdio, and tears down on exit. The cache persists across invocations in ~/.cache/uvxwebsearchmcp/cache.db.

Local development

If you have the repo cloned:

git clone https://github.com/DanielNMC/web_tools_mcp.git
cd web_tools_mcp
uvx .          # runs the server from the current checkout

Tools

web_search(query, max_results=10, backend="auto")

Searches the web via ddgs and returns either {"results": [...]} or {"error": {...}}.

  • query (str, required) — non-empty search query.

  • max_results (int, default 10) — must be 1..50.

  • backend (str, default "auto") — one of:

    • auto — fans out across all configured engines (recommended)

    • bing, duckduckgo, google, grokipedia, mojeek, startpage, yandex, yahoo, wikipedia

    • brave is intentionally NOT supported (would require an API key).

The MCP tool description sent to the LLM lists the allowed backends.

web_fetch(url, max_chars=10000)

Fetches a URL and extracts its content as markdown via ddgs. Returns {"url", "content"} on success or {"error": {...}} on failure.

Errors

Both tools return structured errors instead of raising. The shape is:

{
  "error": {
    "type": "rate_limit" | "backend_failure" | "empty_results" | "invalid_input",
    "message": "human-readable explanation",
    "retryable": true | false,
    "retry_after_seconds": 30,
    "hints": ["Wait and retry", "Or decompose the query"],
    "attempts": [{"backend": "duckduckgo", "outcome": "rate_limit"}]
  }
}

Read retryable before deciding to retry. retry_after_seconds is a concrete wait suggestion, not a vague "later". hints is natural-language guidance for the LLM.

Configuration (all optional)

Env var

Default

Purpose

WEBSEARCH_CACHE_DIR

$XDG_CACHE_HOME/uvxwebsearchmcp (or ~/.cache/uvxwebsearchmcp)

Override the cache location.

XDG_CACHE_HOME

~/.cache

Standard XDG override; honored if WEBSEARCH_CACHE_DIR is unset.

HOME

(system)

Used as last-resort fallback for the cache dir.

If the cache directory cannot be created or written (read-only filesystem, locked-down CI), the server falls back to an in-memory cache and continues to serve. No tool calls will fail because of a cache problem.

Claude Desktop configuration

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "web-search": {
      "command": "uvx",
      "args": [
        "--from", "git+ssh://git@github.com/DanielNMC/web_tools_mcp.git",
        "uvxwebsearchmcp"
      ]
    }
  }
}

Other MCP clients (Cursor, Kilo, etc.) take the same shape — point them at uvx with the --from URL and the package name as the executable.

How it works

   LLM agent
       │
       ▼
   MCP server (stdio)
       │
       ▼
   ┌──────────────┐
   │  Cache       │  diskcache, SQLite-backed
   │  TTL: 15min  │  persists across uvx runs
   │  negative:60s│
   └──────┬───────┘
          │ miss
          ▼
   ┌──────────────┐
   │  ddgs        │  multi-backend metasearch
   │  backend=auto│  (10 engines)
   └──────────────┘

The auto backend tries each engine in random order; if one 429s, ddgs moves to the next. The cache absorbs the rest of the load.

Limitations

  • web_fetch does not cache. Single-URL fetches are typically non-repeating and caching them would just bloat disk.

  • The cache is process-local to the user — no cross-user or cross-host sharing.

  • ddgs scrapes engines without API keys. If every engine de-platforms your IP simultaneously, the tool degrades to error envelopes, not crashes.

Development

git clone https://github.com/DanielNMC/web_tools_mcp.git
cd web_tools_mcp
uv sync
uv run pytest              # 88 tests
uv run ruff check src tests
uv build                   # produces dist/*.whl and dist/*.tar.gz

Releasing a new version

# Bump version in pyproject.toml
git tag v0.2.0
git push origin master --tags

Other users pin to your tag with @v0.2.0 in the --from URL.

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for web search and content extraction using DuckDuckGo or SearXNG, with Playwright-based fetching and LLM-powered data extraction.
    139
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    A minimal MCP server for agent-friendly web extraction and search. Offers two tools: fetching real pages with Playwright and Crawl4AI, and searching across 7 engines with automatic fallback.
    33
    AGPL 3.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    A self-contained web-research MCP server that lets local LLM agents search, fetch, and synthesize web content using tools like web_search, web_fetch, and web_research.
    1
    MIT