keyless-web-search-mcp
keyless-web-search-mcp
Eigenständiger MCP-stdio-Server: zwei schlüssellose Tools – web_search über einen selbst betriebenen Engine-Pool (Bing, 360, Baidu, Google, Naver, Yandex, DuckDuckGo) und web_fetch (anonymer HTTP(S)-Seitenleser). Jede Suche behält höchstens zwei nutzbare Engines bei, priorisiert Standardrouten nach Abfragesprache, füllt fehlgeschlagene oder irrelevante Engines innerhalb eines begrenzten Versuchsbudgets auf, bewertet Ergebnisse nach Relevanz, führt sie zusammen und entfernt Duplikate anhand der kanonischen URL. In sich geschlossenes Verzeichnis, kein Build-Schritt, nicht Teil des Harness-Paketsystems – überallhin verschiebbar.
Warum es das gibt
Die eingebaute web_search-Funktion des Harness (DeepSeek-Anbieter) benötigt DEEPSEEK_API_KEY und sendet jede Abfrage an die DeepSeek-Cloud. Dieser Server ist die lokale, modellfreundliche Alternative: keine Schlüssel, keine Such-API eines Anbieters, funktioniert in Festlandchina- und Hongkong-Netzen (Bing/360/Baidu aus Festlandleitungen, Bing/360/Naver/Yandex aus der getesteten Hongkong-Leitung; DuckDuckGo ist von keiner davon aus erreichbar).
web_fetch existiert aus demselben Grund auf der Leseseite: Das Webprofil bindet zwar einen Suchanbieter ein, aber keinen Fetch-Anbieter, sodass das eingebaute web_fetch-Tool (selbst wenn es durch ein Preset aktiviert wird) jeden Aufruf mit WEB_PROVIDER_UNAVAILABLE abbricht. Dieses Tool liest stattdessen den vollständigen Seiteninhalt über denselben schlüssellosen Server.
Related MCP server: web-search-mcp
Ausführen
npm install --cache ./.npm-cache # deps: @modelcontextprotocol/sdk, zod
node index.js # speaks MCP over stdio
npm test # run deterministic ranking/fallback testsSchneller Test ohne Client:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"0.0.1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| node index.jsIn Claude Code installieren
Für den aktuellen Benutzer installieren, damit jedes Claude-Code-Projekt es verwenden kann. Beide Pfade beim Registrieren des Servers auflösen; so vermeidet man die Abhängigkeit vom Arbeitsverzeichnis der Shell oder vom PATH:
claude mcp add --transport stdio --scope user web-search-self -- "$(command -v node)" "/absolute/path/to/keyless-web-search-mcp/index.js"
claude mcp get web-search-selfVerwenden Sie stattdessen --scope local, um es auf das aktuelle Projekt zu beschränken, oder --scope project, um eine gemeinsam nutzbare .mcp.json zu schreiben. Claude Code speichert Benutzer-/Lokalregistrierungen in ~/.claude.json; MCP-Serverdefinitionen gehören nicht in settings.json.
Nach der Registrierung sollte claude mcp list web-search-self als verbunden melden. Die Tools erscheinen als mcp__web-search-self__web_search und mcp__web-search-self__web_fetch.
Werkzeuge
web_search
web_search({ query, count?, maxSources?, engines? })
Parameter | Standard | Bedeutung |
| — | Suchanfrage, beliebige Sprache |
|
| Maximale Anzahl zusammengeführter Ergebnisse (1–20) |
|
| Maximale Anzahl nutzbarer Engines pro Suche (hartes Limit 2; Nachschlagversuche sind begrenzt) |
| abhängig von der Abfragesprache | Optionale explizite Liste in Prioritätsreihenfolge; wenn weggelassen, verwenden chinesische/koreanische/japanische/russische Abfragen regionsgerechte Prioritäten |
Zwei-Quellen-Richtlinie. Der Pool wird bei Weglassen von engines nach Abfragesprache geroutet: Chinesisch beginnt mit 360/Baidu/Bing; Englisch beginnt mit Bing/Google/Naver/360, sodass das Budget von vier Versuchen funktionierende Fallbacks in den getesteten Festland-/Hongkong-Netzen behält. Eine explizite engines-Liste hat weiterhin Vorrang. Kandidaten laufen in begrenzten parallelen Runden; eine Engine belegt nur dann einen Quellenplatz, wenn sie parsebare Ergebnisse liefert, die die konservative lexikalische Relevanzfilterung bestehen. Fehlgeschlagene, herausgeforderte, leere oder irrelevante Engines werden bis zum Versuchs- und Sammlungsbudget nachgefüllt, und Diagnosen werden in einer Zeile „Engine-Hinweis" angezeigt. Die Ergebnisse werden nach Abfrageüberlappung mit einer kleinen Quellenqualitätsanpassung sortiert: Offensichtliche Repost-/Content-Farm-Signale werden abgewertet, während offizielle/Dokumentations-/Bildungs-/GitHub-Signale bevorzugt werden, ohne normale Websites hart zu blockieren. Die Zusammenführung bleibt round-robin verschachtelt (1. von Engine A, 1. von Engine B, 2. von A, …), und die Deduplizierung anhand der kanonischen URL entfernt Fragmente, häufige Tracking-Parameter und sichere www.-Unterschiede.
Ergebnis: nummerierte Liste aus Titel [Engine] / echter Ziel-URL / Ausschnitt. Linkbereinigung pro Engine: Bing-Klick-Tracker-Links werden lokal dekodiert (base64-u-Parameter); 360 liest das data-mdurl-Attribut; Baidu liest das mu-Attribut des Blocks (direkte URL, mit einem einzigen Redirect-GET im Best-Effort-Verfahren nur für veraltete link?url=-Wrapper); Naver- und Yandex-Titel tragen die direkte URL im Anker; Google-/url?q=-Wrapper werden entfernt; DuckDuckGo-/l/?uddg=-Tracker werden entfernt. Pro-Engine-Probe-Budgets: 10 s (Bing, Baidu), 8 s (360, Naver, Yandex), 5 s (Google, DuckDuckGo) – alle laufen parallel, sodass die Runde nur so langsam ist wie ihr langsamstes Mitglied.
web_fetch
web_fetch({ url, maxChars? })
Parameter | Standard | Bedeutung |
| — | Absolute |
|
| Maximale Anzahl zurückgegebener Zeichen (1000–100000) |
Anonymes Lesen aus dem öffentlichen Web, keine Anmeldedaten: Browser-User-Agent, höchstens fünf Weiterleitungen, 20 s Wanduhrzeit für Header und Body, Antworttext bei exakt 5 MB abgeschnitten. Jedes Anfangs- und Weiterleitungsziel wird nach der DNS-Auflösung geprüft; Loopback-, private, Link-Local-, Carrier-Grade-NAT-, reservierte, Multicast- und lokale Hostnamen werden abgelehnt, um SSRF in den Rechner oder in Cloud-Metadatendienste zu verhindern. HTML wird zu sichtbarem Text reduziert (script/style/noscript/svg/head/iframe/canvas/form werden verworfen, Blockgrenzen werden zu Zeilenumbrüchen, der <title> wird im Kopfbereich übernommen); Text-, JSON- und XML-Medientypen werden mit deklariertem Zeichensatz entity-dekodiert durchgereicht, während binäre Medientypen abgelehnt werden. Die Ausgabe ist ein Statuskopf – status, endgültige url (nach Weiterleitungen), content-type, Kürzung – gefolgt vom Inhalt. Antworten ungleich 2xx geben den Body-Anfang plus einen Hinweis zurück (403/429 als Bot-Check oder Paywall gelesen), niemals eine erfundene Seite.
Engines und ihr Status
Verifiziert 2026-07 von drei Leitungen (einer früheren Festlandleitung, einer Shanghai-Telecom-Leitung und einer Hongkonger Zenlayer-Rechenzentrumsleitung):
Suchmaschine | Endpunkt | Status aus diesen Netzwerken |
|
| ✅ ~10 organische Blöcke auf beiden Leitungen. Je nach Leitung liefert |
|
| ✅ sauberer 200er; organische Blöcke tragen die echte URL im Attribut |
|
| Erreichbar (200), aber dieser Client/diese IP sind für plain-HTML-SERPs nicht vertrauenswürdig: Der Body ist eine No-JS-Meta-Refresh-Sperre ( |
|
| ✅ bei den Leitungen Shanghai und HK: Das Risikokontroll-Gate blockiert skriptförmige Requests, die per UA überprüft werden (UA-only-302-Weiterleitungen zum Bild-Captcha |
|
| ✅ auf der HK-Leitung (200, ~10 organische Blöcke |
|
| ✅ auf der HK-Leitung: die gleiche Lektion zur Navigationssignatur wie bei Baidu – Script-artige Anfragen erhalten das SmartCaptcha-„Not a robot“-Kontrollkästchen, aber die vollständige „document-navigation“-Headersignatur plus die Cookie-Sitzung der Startseite (yandexuid usw.) bedient die TZero-HTML-SERPS ( |
|
| ❌ TCP-unerreichbar auf allen drei getesteten Leitungen (inkl. HK); als Fallback-Engine für Netzwerke, in denen sie geht recht. |
Bewusst nicht im Pool: Sogou – 302t auf sogou.com/antispider/, also in dieselbe IP+Mauer-Klasse wie Baidu. Ebenso von der HK-Leitung aus gescannt und abgrund: Mojeek (Captcha-Seite), Ecosia (403 „Ecosia Firewall“), MetaGer (redirects to empty page), sowie Yahoo/Brave/Qwant/Startpage/goo.ne.jp (TCP-unerreichbar von Mainland-Leitungen und HK-Leitung).
Google-Sperre: was warfen wurden
Die 200er-Antwort dieser Route ist keine UID-Sperre, sondern eine JS Challenge-Interstitialseite (~90 KB obfuskierter / verschlüsselter JavaScript-Code; der No-JS-Pfad ist ein meta-Refresh in eine Sackgasse. Die Sperre erweist sich als zwei Schichten:
JS-Challenge (Rechenaufgabe): Der dekodierte Code errechnet einen Nachweiswert, setzt ein
id_ss-Cookie (5 Minuten Gültigkeit) und lädt neu. Diese Schicht ist auch außerhalb des Browsers lösbar: Die Skripte der Seite in reinem Node.js mit einem minimalen DOM-Shim (CookieJar,navigator,image,document) laufen nach und die Berechnung; das dabei meldende, errechnete Prüfwert-Cookie wurden einmal an-«enommen – Google antwortete mit 200 and liessNID/AEC-Vertrauenscookies aus, die es dieser IP sonst nie gibt.Session-Pattern-Schicht (Verhalten): Nachfolgende Re-HTTPS-Follow-ups – inklusive exakter Nachbildung des echten Seiten-Skript-Reload („
emsg=SG_REL+ passendescommand; Cookie-Jar‑Sykary; Cookie‑, Browser-Header) – landen in dergoogle.com/sorry-Anomale (HTTP 429). Diese Schicht bewertet die gesamte Sitzung (TLS/HTTP2-Fingerprint, Request-Abstand, Methodenmix), was der Node-Stack (OpenSSL/undici) nie realistisch nachbedienen kann.
Getestete, den Los des 1. Level nicht verändernde Client-Seitige: die gbv=1-Parameter, Cookie-Warm-up, vollständige Browser-Fingerprint-Header, der retry/enablejs-Flow, der /m-Serverpfad, Browser-/Feature-PM/IE6/alt-Android-UAs, ein gespoofter Googlebot-UA (Google-Verifizierung), CONSENT-Cookies, POST-Abs, Alt-TLDs sowie der "tokens klick"-Link emsg=SG_REL (ohne EÇSS). Google-Proxy-Alternativen waren vom Netzwerk aus ebenfalls nicht erreichbar / blockiert: Startpage und Qwant Time-outs, Mojeek liefert Capcha, Ecosia antwortet mit 403.
Fazit: Layer 1 ist in Node zu lösen (demonstration), Layer 2 in einer Nicht-Browser-Netzwerk-Stack nicht. The only reliable paths from this device: saubere-IP-Proxy or = Tatbestand browser "headless Chromium"; The IP-Muster-Schicht bleibt. Repeated – non-pong risk the "anomaly" window of the IP.
In den DeepSeek-Harness (Mount)
Ergänze deine cordis.yml (die MCP-Bridge lädt diesen Eintrag per Hot-Reload):
- id: mcp-search
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: search
transport: stdio
command: node
args: ['/absolute/path/to/keyless-web-search-mcp/index.js']Das Modell zeigt die Tools schließlich als mcp__search__web_search und mcp__search__web_fetch.
Einschränkungen
Suchqualität ist heuristisch: Lexikalische Resultate räumen mit offensichtlich unpassenden Ergebnis-E-und – und chinesischen n‑Telegrammen; interne Suchmaschinen-Suchseiten werden ausgeschlossen; Content-Farm-/Re-Repost-Signale bereinigen die Reihenfolgen – aber kein universelles Vertrauensurteil. Ein Treffer ist kein Beweis für die Korrekthee darin–. Fund- und Quelldaten (fetch) Quoten als bei Fake.
Scraping, keine API: Layout-Änderungen können einen Parser grenzen; Der Fehlschlag ist laut (z. B. „
no parse organic results) und nie fabriziert. Die Google- und DuckDuckGo-Parser sind aus dokumentierter SERP-Struktur entstanden und in diesem Netzwerk nicht live prüfbar – stimme sie bei der ersten Gelegenheit, wenn die jeweilige Engine selbst antwortet.Rate-Control: Beide öffentlichen Engines tolerieren gelegentliche Nutzung; Dauer durch Hammern lockt Bot-Challenges.
Die Such-Anfrage verlässt die Maschine in Richtung der konsultierten Engines (das ist der Preis der keyless Suche); Mit dem Zwei-Quellen-Limit sehen pro Suche höchstens zwei davon die Abfrage.
Fetch ist ein ohne Schlüssel anfähiger Leser für öffentliche Seiten, kein Browser/Intranet-Client: JS-gerendered content bleibt unsichtbar (gleiche Limit-Klasse wie die Such-Parser intern; drei 403/429 gegenüberwie anonymen Clients werden gemeldet, nicht umgangen). Lokale/private/reservierte Netwerkzeileliste werden vollständig blockiert, inklusive Redirect-Ziel.
Available Tools
2 toolsweb_fetchWeb Fetch (keyless anonymous HTTP(S) reader)A
Fetch one HTTP(S) URL anonymously and return the page as readable text: HTML is stripped to visible text with block structure preserved; text/markdown/JSON/XML pass through decoded. No credentials: browser User-Agent, up to five validated redirects, bounded output. Local, private, link-local, and reserved network targets are blocked, including after DNS resolution and redirects. The result is a status header (status code, final URL, content-type, truncation) followed by the content. Use it to read full page content for a URL, e.g. one found by web_search.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Absolute http(s) URL to fetch. | |
| maxChars | No | Maximum content characters to return (default 20000, hard cap 100000). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full responsibility. It discloses anonymous access, no credentials, browser User-Agent, redirect limits, target blocking, and truncation behavior, which is strong transparency for a network tool.
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?
Three purposeful sentences: main behavior, safety boundaries, and output/usage context. No filler, no redundant schema echoing, and key constraints are front-loaded.
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?
With no output schema or annotations, the description still explains output format, status header components, redirects, target restrictions, and content conversion. This is an unusually complete one-paragraph contract for a fetch tool.
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?
The schema already clearly documents both parameters at 100% coverage, with maxChars including a default and limits. The description affirms bounded output but does not add substantial meaning about parameter formats beyond the schema.
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, resource, and output: fetches one HTTP(S) URL and returns readable text. It also references web_search, making the distinction between search and fetch explicit without ambiguity.
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?
Description explicitly says to use it to read page content for a URL and gives a web_search output as an example, naming the sibling tool. It does not explicitly state when not to use it, so it stops short of a full when/when-not map.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
web_searchWeb Search (self pool: Bing / 360 / Baidu / Google / Naver / Yandex / DuckDuckGo)A
Search the web without any API key from a self-operated pool: Bing, 360, Baidu, Google, Naver, Yandex, and DuckDuckGo. Each search keeps at most two usable engines — the pool is routed by query language when no explicit pool is given, failed or irrelevant engines are back-filled within a bounded attempt budget, and results are relevance-ranked, quality-adjusted, and deduplicated by canonical URL. Each result includes a title, the real destination URL, a snippet, and its engine. Engines unreachable from the local network, or walled by captcha/JS/bot checks, are skipped and reported in an engine note; the remaining engines still answer.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Maximum merged results to return (default 8). | |
| query | Yes | Search query in any language. | |
| engines | No | Optional explicit engine pool in priority order; omitted uses query-language routing. | |
| maxSources | No | Maximum usable engines per search (default 2, hard cap 2; fallback attempts are bounded). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly discloses behavioral details: no API key needed, engine pool self-operated, at most two usable engines, back-fill on failures, relevance/quality ranking, deduplication, skipping unreachable or walled engines, and reporting an engine note. This exceeds the baseline and compensates for the absence of annotations. No contradiction with annotations since none are provided.
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?
The description is concise and front-loaded with the primary purpose (search the web without API key) and then provides relevant behavioral details in a structured manner. Each sentence adds value; it is not overly verbose. Slight redundancy with the engines list in the title but overall well-structured.
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?
The description covers key aspects: purpose, engine selection, failure handling, result format, and edge cases (captcha/JS/bot walls). No output schema exists, but the description mentions what each result includes (title, URL, snippet, engine), which partially compensates. The absence of annotations is mitigated by the detailed description. Minor gaps remain about the return structure of the full response, but the information is sufficient for an agent to invoke the tool correctly.
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?
The input schema already has complete (100% coverage) descriptions for all four parameters: count, query, engines, and maxSources. The description adds contextual insight on routing by query language and back-fill behavior but does not add substantial new parameter semantics beyond what the schema provides. Per the guideline, high schema coverage means baseline 3 is appropriate.
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?
The description clearly states the tool performs a web search using a self-operated engine pool, listing the supported engines and the result characteristics (title, URL, snippet, engine). It does not explicitly contrast with the sibling tool web_fetch, but the purpose is distinct and clear.
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?
The description explains how the engine pool is selected (query-language routing when no explicit pool), how failures are handled (back-filling, bounded attempts), and how results are ranked and deduplicated. It does not explicitly state 'when to use' versus 'when not to use' but provides contextual routing guidance. The sibling tool web_fetch is not referenced, so no alternative routing is mentioned.
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.
2 tool updates
v1.1.0- First observed
web_fetch - First observed
web_search
TDQS
Scored across 2 tools
The two tools are completely distinct: web_search performs web searches across multiple engines, while web_fetch retrieves the content of a specific URL. There is no overlap or ambiguity between them.
Both tool names follow the same verb_noun pattern: web_search and web_fetch. The naming is clear, consistent, and predictable.
The server has only two tools, which is slightly below the typical well-scoped range of 3-15. However, each tool is essential and covers the core functionality of keyless web search and fetching, so the count is reasonable for the narrow scope.
The tool surface fully covers the stated purpose of keyless web search: web_search finds relevant results and web_fetch retrieves full page content. There are no obvious missing operations for this domain.
Maintenance
Related MCP Connectors
Google, Bing, DuckDuckGo and Google Maps search results, free without an API key.
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Keyless web, GitHub, YouTube and Reddit search and read. Delegated shop, booking and signup.
Web search for AI agents — one tool across 6 engines, routed to the cheapest + cached.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables web search without API keys using DuckDuckGo and Bing search engines, and retrieves webpage content. Supports multiple search engines simultaneously with privacy protection and asynchronous processing.263 PyPI10MIT
- FlicenseNot gradedqualityDmaintenanceProvides free web search, content fetching, image search, and deep research via SearXNG, no API keys required.-
- 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 MCP clients to perform free web search and read web pages as markdown without paid APIs, Docker, or a background service, by querying multiple free search engines in parallel with optional fallbacks and extracting clean page content. Also supports fetching a site's llms.txt documentation files.MIT