cd /news/agent-protocols/duckduckgo-mcp-bench-8-servers-12-se… · home topics agent-protocols article
[ARTICLE · art-137920] src=gist.github.com ↗ pub= topic=agent-protocols verified=true sentiment=· neutral

DuckDuckGo MCP bench: 8 servers, 12 searches, 3 passes, Sept 2026

HasData benchmarked eight DuckDuckGo MCP servers across twelve searches and three passes on 2026-09-15, publishing the harness and fixtures on GitHub. free-search-mcp and HasData's own hosted server each returned 12/12 results, open-webSearch managed 10/12, while zhsama failed every call and web-scout returned just one result. The company disclosed that it maintains one of the servers tested.

by read8 min views1 publishedSep 23, 2026

Raw results from running the same twelve searches against every DuckDuckGo MCP server we could find in the MCP registry, npm, PyPI, Smithery, the Docker MCP catalog and search, on 2026-09-15. Three full passes plus one from a fresh clone of the public harness. Twelve distinct queries per pass, one per call, no delay between calls, the official MCP TypeScript SDK as the client. No ranking here, only what came back. The harness and the fixture are public at https://github.com/HasData/mcp-bench.

Disclosure. HasData, which maintains the harness, also runs one of the servers below.

Server Where it runs Auth Source
HasData DuckDuckGo MCP hosted, streamable HTTP x-api-key header, free key https://hasdata.com/mcp/duckduckgo
nickclyde/duckduckgo-mcp-server local, uvx duckduckgo-mcp-server none https://github.com/nickclyde/duckduckgo-mcp-server
Aas-ee/open-webSearch local, npx open-websearch none https://github.com/Aas-ee/open-webSearch
sweetcornna/free-search-mcp local, uvx free-search-mcp none https://github.com/sweetcornna/free-search-mcp
yokingma/one-search-mcp local, npx one-search-mcp none https://github.com/yokingma/one-search-mcp
pinkpixel-dev/web-scout-mcp local, npx @pinkpixel/web-scout-mcp none https://github.com/pinkpixel-dev/web-scout-mcp
OEvortex/ddg_search local, npx @oevortex/ddg_search none https://github.com/OEvortex/ddg_search
zhsama/duckduckgo-mcp-server local, npx duckduckgo-mcp-server none https://github.com/zhsama/duckduckgo-mcp-server

Not run, with the reason. DDDMUC/dsh-free-search (140 stars, ranks for the head term) is a DeepSeek Harness search plugin rather than a standalone MCP server, and its npm package ships no binary. Bright Data and Apify have no DuckDuckGo product.

Three of the eight are multi-engine. free-search-mcp and open-webSearch take an engine argument and were pinned to DuckDuckGo. one-search-mcp has no engine field in its tool schema and is covered separately below.

A call counted as failed when the server returned isError, when the body was an error envelope such as {"error": ...} regardless of transport status, when the body carried no results, or when the call timed out. Two rules were added during this run because servers kept failing inside a success: a result set whose every item has an empty or missing link, and a payload with no item array at all whose text opens with a failure word. Both are in the public harness.

Latency is the median of successful calls only, computed as a true median. The harness report command prints sorted[floor(n/2)], the upper median, so its figures sit slightly above these.

Server Result Median Fastest to slowest Median bytes Connect
open-webSearch 10/12 1.12 s 0.98 to 2.45 s 5.4 KB 37.1 s
free-search-mcp 12/12 1.39 s 1.06 to 1.59 s 4.2 KB 8.3 s
HasData 12/12 1.96 s 1.49 to 2.77 s 10.0 KB 2.3 s
nickclyde 12/12 2.37 s 2.21 to 4.91 s 3.6 KB 8.8 s
one-search-mcp, default provider 12/12 7.27 s 6.66 to 10.74 s 4.9 KB 8.7 s
OEvortex 3/12 1.53 s 1.41 to 1.84 s 1.2 KB 48.5 s
web-scout 1/12 1.51 s single call 4.0 KB 6.6 s
zhsama 0/12 n/a n/a n/a 5.8 s

Connect times in this pass include npx -y and uvx fetching packages on first use. Warm connects in the two later passes ran 1.8 to 10.9 s for the local servers against 1.6 to 3.6 s hosted.

Server Pass 1 Pass 2 Pass 3
free-search-mcp 12/12 12/12 12/12
HasData 12/12 12/12 12/12
nickclyde 12/12 12/12 12/12
open-webSearch 10/12 12/12 12/12
OEvortex 3/12 6/12 2/12
web-scout 1/12 0/12 1/12
zhsama 0/12 0/12 0/12

Local servers ran together at 09:42, 10:43 and 11:25 UTC. The hosted server was measured at 09:42, 10:48, 11:25 and 11:54, so its passes sit on a different clock and the columns are per server rather than a synchronised schedule.

Medians by pass, finishers only: pass 1 open-webSearch 1.12, free-search 1.39, HasData 1.96, nickclyde 2.37, one-search 7.27. Pass 2 open-webSearch 1.08, free-search 1.48, nickclyde 1.52, HasData 2.15, one-search 6.25. Pass 3 open-webSearch 1.04, free-search 1.42, nickclyde 1.44, HasData 2.14. The order of the middle three changes between passes.

Its tool schema exposes query, limit, language, categories and timeRange, with no engine field, so the first pass ran it as shipped. It returned twelve well-formed responses at a 7.27 s median, and every URL in them was a bing.com/ck/a redirect with no duckduckgo.com string anywhere in the captured payloads.

The server reads SEARCH_PROVIDER from the environment. The default is local, which drives a real Chrome profile ( userDataDir pointing at the user's own Chrome) against Bing. Pinned to SEARCH_PROVIDER=duckduckgo it returned 0 of 12, each call failing after 10.8 to 16.4 s with DDG detected an anomaly in the request, you are likely making requests too quickly and Failed to get the VQD in its log.

Both measurements are in the results files. The fixture now carries the env var.

Server Format Links Extras
HasData JSON, 10 results with position, title, link, displayedLink, source, snippet, snippetHighlightedWords direct DuckDuckGo's assist answer with sources, pagination token
open-webSearch JSON, 10 results with title, url, description, source, engine direct reports which engines ran and any partial failures
free-search-mcp markdown by default, JSON with format: "json" direct names the engines used
nickclyde text, Found N search results: then numbered title, URL, summary direct none
one-search-mcp text, title, URL, description Bing redirects on the default provider none
  • zhsama , 2 of 12 reached DuckDuckGo and came back withDDG detected an anomaly in the request, you are likely making requests too quickly after 2.4 s and 0.6 s. The other 10 returned in 2 to 5 ms with a 26-byteRate limit exceeded from its owncheckRateLimit . Its published build setsrateLimit: { perSecond: 1, perMonth: 15000 } , so the stderr line{ second: 1, month: 2 } is a running count and the one-per-second ceiling is what a zero-delay burst trips. It throws rather than queueing.

  • web-scout , one real answer then 11 repetitions ofNo results were found for your search query. Please try rephrasing your search or try again in a few minutes , each under 310 ms against 1.5 s for the one that worked.isError false throughout.

  • OEvortex , 9 of 12Error: Search failed for "<query>": HTTP 202: Failed to fetch search results . Successes landed on calls 8, 9 and 12 in pass 1.

  • open-webSearch , clean for ten queries then{"query": "...", "engines": ["duckduckgo"], "totalResults": 0, "results": [], "partialFailures": []} on calls 11 and 12. No error flag. Its stderr for those two calls says it could not find the preloadedd.js URL it scrapes out of DuckDuckGo's HTML, so the diagnostic exists but never reaches the caller.

  • nickclyde , clean in all three passes, then in the fresh-clone pass it answered seven queries and returnedNo results were found for your search query. This could be due to DuckDuckGo's bot detection or the query returned no matches ... installing the optional browser backend (pip install 'duckduckgo-mcp-server[browser]') enables Chrome TLS impersonation for the remaining five.

  • duckduckgo-mcp-server is two unrelated projects. On PyPI it is nickclyde's, which finished every pass. On npm it is zhsama's, which finished none. One command apart.

  • Three of the eight fail inside a 200 rather than erroring. Two return an empty list, one returns a prose sentence. A client that branches on errors treats all three as an empty search.

  • The test IP was not the limiting factor. free-search-mcp started a tenth of a second after web-scout's last empty answer, from the same address, and completed twelve of twelve. open-webSearch started a tenth of a second after zhsama finished failing and completed ten.

  • Zero delay between calls is not a realistic agent workload, and it is exactly what tripped zhsama. Read these as burst results.

  • open-webSearch binds an HTTP server on port 3000 even over stdio. A stale instance surfaces to the client as MCP error -32000: Connection closed .MODE=stdio avoids it.

  • Cold start is dominated by package fetch on first use, 5.8 to 48.5 s here, and drops to 1.8 to 10.9 s warm.

git clone https://github.com/HasData/mcp-bench.git && cd mcp-bench && npm install
cp .env.example .env            # only the hosted server needs a key
node mcp-bench.mjs probe duckduckgo
node mcp-bench.mjs run duckduckgo --runs 12 --timeout 180000
node mcp-bench.mjs report duckduckgo

Node 20 or newer, and uv on PATH for the two servers that start through uvx. The twelve queries live in fixtures/duckduckgo.json under queryVariants, one per run. Note that one-search-mcp on its default provider launches your real Chrome profile, and that open-webSearch wants port 3000 free.

All measurements are from tool calls made on 2026-09-15 between 09:42 and 11:56 UTC from one machine in Europe on one IP. Star counts, push dates and the Docker pull count were read the same week.

── more in #agent-protocols 4 stories · sorted by recency
── more on @hasdata 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/duckduckgo-mcp-bench…] indexed:0 read:8min 2026-09-23 ·