search-mcp
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., "@search-mcpwhat happened in the Champions League final last night?"
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.
search-mcp
An MCP server with one tool: broad web search for current,
time-sensitive information. It returns short snippets (title, url, snippet), not full pages. It is backed by
the keyless multi-engine ddgs library, which fans out across several web search
engines with fallback (its encyclopedia engines, Wikipedia and Grokipedia, are left out: encyclopedic hits are
the wrong answer for current events).
It is deliberately small. It is meant to sit next to other, non-overlapping tools (an offline encyclopedia, a curated news feed, structured local data), so a small local model can pick the right tool from the docstrings alone. Design rationale: CLAUDE.md.
Tool
web_search(query, max_results=10, region=None)
arg | |
| sent to the engines verbatim, never rewritten |
| 1–25, default 10 |
|
|
Every result is one JSON text block with a status field. Callers branch on it, never on prose:
{"status":"ok","query":"...","backend":"auto-web","region":"wt-wt","safesearch":"moderate","max_results":10,
"attempts":1,"count":2,"results":[{"title":"...","url":"https://...","snippet":"..."}]}ok: the search ran and returned results. (results:[]is reserved for a backend that can prove a search was empty; ddgs can't, see below.)refused: input the caller can fix (blank query,max_resultsout of range, malformed region), withreasonandadvice. It is returned as a normal result, never raised.error: the search backend failed (blocked, rate-limited, timed out, network down), withkindanddetail. A backend outage is always reported as an error, never as an empty result. A failed search is retried server-side first (SEARCH_ATTEMPTS, default 2), because a second try with a different engine order often succeeds. Every result echoesattempts, so anerrorhas already been retried.kind:"empty_or_blocked"means no engine returned anything: ddgs counts an engine that blocks or rate-limits it as "no results", so it can't tell an obscure query from a blocked server. One reworded retry is reasonable; otherwise treat search as unavailable.
All resolved parameters are echoed back, so a result is reproducible. The tool declares a title and all four
MCP hints: read-only, non-destructive, idempotent, open-world.
Related MCP server: DuckDuckGo MCP Server
Run
uv sync
uv run search-mcp serve # stdio, for a local MCP client
SEARCH_MCP_TOKEN=secret uv run search-mcp serve --transport http --host 0.0.0.0 --port 8000 # streamable-http at /mcp
uv run pytest # no network: the backend is fakedenv | default | |
| unset | bearer token required on HTTP ( |
|
| seconds ddgs waits on each batch of engines |
|
| backend calls per search before reporting an error (each reshuffles the engines) |
| unset | optional outbound proxy for ddgs (read by the library itself) |
TLS note: behind a TLS-inspecting proxy,
uvmay reportUnknownIssuer. Pass--system-certs(or setUV_NATIVE_TLS=1) so it trusts the OS certificate store.
Claude Desktop / Claude Code (stdio)
{
"mcpServers": {
"search": { "command": "uv", "args": ["--directory", "/path/to/search-mcp", "run", "search-mcp", "serve"] }
}
}Docker
docker build -t search-mcp .
docker run --rm -p 8000:8000 -e SEARCH_MCP_TOKEN=... search-mcpThe server is stateless: no database, no volume. It needs outbound HTTPS to the public search engines.
Auth and exposure
Auth is deliberately simple: stdio, or streamable-HTTP with a single bearer token (SEARCH_MCP_TOKEN) on a
private network, for example behind mcpo. There is no OAuth, no users
and no audit log, by design. To publish it more widely, put a management layer in front of it: an MCP
gateway or auth proxy that handles OAuth, users and audit for all your servers at once.
A note on the backend
ddgs gets its results by scraping search-engine result pages. It needs no API key, but it is not a sanctioned
API, and engines may rate-limit or block it. That shows up here as status:"error". The backend sits behind a
single function (src/search_mcp/backend.py), so a sanctioned API (Brave, Mojeek) or a self-hosted SearXNG can
replace it by editing that one file.
AI assistance
search-mcp is developed openly with the help of Claude (Anthropic). Commits Claude helped write carry a
Co-Authored-By: Claude trailer. The code and design are open source so the work can be inspected, reused, and
given back.
License
MPL-2.0 © Daniel Núñez.
Available Tools
1 toolweb_searchWeb searchARead-onlyIdempotent
Search the web for CURRENT information: news, current events, anything recent/latest/today/this week, weather, prices, time-sensitive facts. Do NOT use for general knowledge like recipes, definitions, or history — those have better tools. Returns snippets (title, url, snippet), not full pages.
Args:
query: what to search for, sent to the search engines exactly as written.
max_results: how many results (default 10, allowed 1-25).
region: optional region code `country-lang`, e.g. "us-en", "es-es", "de-de"; default "wt-wt" (no region).
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| region | No | ||
| max_results | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, openWorld, non-destructive), so the description's added value is in return shape: 'Returns snippets (title, url, snippet), not full pages.' That is a genuinely useful capability limit — the agent knows it cannot get page content here. It doesn't mention rate limits or result quality/failure modes, keeping it short of a 5.
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 purpose and exclusions, then a compact Args block for the three parameters — no filler sentences. The Args formatting is slightly verbose relative to the description's otherwise terse style, but every element carries 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 3-parameter read-only search tool with no output schema, the description supplies return format, parameter constraints, and default behavior. Nothing needed to invoke it correctly is missing.
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 0%, so the description carries the full burden and does so: query is sent verbatim to the search engines, max_results has a default of 10 and a hard range of 1-25, and region has a concrete `country-lang` format with examples and the 'wt-wt' default. Each parameter's semantics and constraints are documented beyond the bare types.
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 (search) and resource (the web) plus the information class it serves: news, current events, weather, prices, time-sensitive facts. It also explicitly carves out what it is NOT for (recipes, definitions, history), so the agent can route correctly even without siblings.
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 explicit use conditions (recent/latest/today/this week) and explicit exclusions ('Do NOT use for general knowledge like recipes, definitions, or history — those have better tools'). That is a full when/when-not statement with a pointer to alternatives.
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.
1 tool update
v0.1.0- First observed
web_search
TDQS
Scored across 1 tool
With only one tool, there is no possibility of confusing it with another. Its purpose is clearly limited to current/timely web search, with explicit negative guidance for general knowledge.
A single tool named `web_search` is descriptive, readable, and uses consistent snake_case. There is no pattern to violate or mix.
One tool is thin even for a narrow search server, though it may be intentional. The surface feels minimal rather than clearly well-scoped across typical search needs.
The tool covers core web search with useful parameters like region and result count. Minor gaps remain, such as no page-content retrieval or specialized news/image search, but the stated snippet-only behavior is clear.
Maintenance
Related MCP Connectors
Executes live web/news search queries and returns clean, token-pruned results with zero ad bloat.
Search the web, images, videos, news, and local businesses with robust filters, freshness controls…
Web search, agentic search, news, page retrieval, sitemaps, and trending topics through Search1API.
Google, Bing, DuckDuckGo and Google Maps search results, free without an API key.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables free web searching using Google search results without the need for API keys or authentication. It returns structured data including titles, URLs, and descriptions with configurable result limits.21 npm1MIT
- AlicenseAqualityCmaintenanceProvides web and news search via DuckDuckGo with support for region filtering, time ranges, and token optimization for AI assistants.242,091 npm1MIT
- AlicenseAqualityCmaintenanceEnables keyless multi-engine web, news, image, and video metasearch plus full-page markdown extraction for AI agents over MCP, with resilient fallback across DuckDuckGo, Bing, Brave, Google, and other backends.6MIT
- AlicenseNot gradedqualityCmaintenanceEnables free web searches using DuckDuckGo results without requiring API keys or authentication, returning structured titles, URLs, and descriptions with a configurable result limit.21 npmMIT