research-mcp
research-mcp
Eine zustandslose MCP-Fassade, die eine Pyramide von Such-/Lese-Anbietern hinter einem einzigen streamable-http-MCP-Endpunkt verbirgt und nur 3 saubere Tools mit guten russischen Hilfetexten bereitstellt. Eine LLM erhält ein einfaches „Suche → Lesen“-Werkzeugset; dahinter werden mehrere Anbieter automatisch ausprobiert, zusammengeführt und über Failover umgeschaltet.
Die App führt keine Authentifizierung durch – sie wird über Traefik + basicAuth auf dem Host veröffentlicht. Sie hält keinen Anwendungszustand: Das Einzige, was persistiert wird, ist eine Logdatei unter data/ (auf einem Volume gehalten).
Tools
Tool | Was es tut |
| Durchsucht alle aktivierten Anbieter, führt zusammen + dedupliziert → sortierte Liste (Titel, URL, Ausschnitt). Nur Suche. |
| Eine Seite oder PDF → sauberes Markdown. Erkennt den Typ automatisch, durchläuft die Lese-Pipeline (leicht → schwer), bis eine erfolgreich ist. |
| Bis zu 20 URLs gleichzeitig → Liste von |
Related MCP server: serp-it
Architektur: Typen + Instanzen
Anbieter sind Plugins. Wir unterscheiden:
Typ – eine Implementierungsklasse (z. B. der
searxng-Suchanbieter), eine pro Modul insrc/providers/, registriert mit@register("type").Instanz – eine konfigurierte Kopie eines Typs mit Geheimnissen/URL, aufgelöst aus benannten Umgebungsvariablen (mehrere Instanzen eines Typs sind erlaubt, z. B.
tavily-1/tavily-2mit verschiedenen Schlüsseln).
Welche Instanzen existieren und die Reihenfolge, in der jede Pipeline sie ausprobiert, wird im Code konfiguriert (src/pipeline_config.py); Schlüssel/URLs kommen aus der ENV per Variablennamen.
Such-Pipeline (
searxng → brave → jina-search → serper → exa): aktivierte Instanzen laufen gleichzeitig; Ergebnisse werden zusammengeführt und nach normalisierter URL dedupliziert (frühere Pipeline-Position gewinnt). WennJINA_API_KEYgesetzt ist (undSEARCH_RERANK_ENABLEDnicht deaktiviert ist), wird die gesamte zusammengeführte Liste dann vonjina-reranker-v3.5neu bewertet, sodass der Zuschnitt aufnum_resultsdie relevantesten Treffer behält statt eines blinden Präfixes in Pipeline-Reihenfolge; ein Fehler beim Re-Ranking fällt auf die Zusammenführungsreihenfolge zurück.searxngundbravedrosseln sich zusätzlich lokal (eine Abfrage pro 45s bzw. pro 1,1s, entsprechend einem gemessenen Upstream-Limit); wenn der Slot belegt ist, überspringen sie die aktuelle Suche, statt darauf zu warten.Lese-Pipeline (
trafilatura → jina → crawl4ai → tavily-1 → tavily-2 → firecrawl): ein einzelner Probe-GET klassifiziert die URL. PDFs (Content-Type /.pdf/%PDF-Magic) werden mit pypdf extrahiert; für HTML wird derselbe Body antrafilaturaübergeben, sodass der heiße Pfad nie zweimal GET ausführt, dann werden die restlichen Instanzen der Reihe nach ausprobiert und die erste, die Inhalt>= FALLBACK_MIN_CHARSzurückgibt, gewinnt.
Querschnittlich: ein einmaliger transienter Retry (5xx / Transportfehler) mit kurzem Backoff; 402 (kein Guthaben) / 429 (Rate-Limit) werden als Anbieterfehler behandelt → nächste Instanz (das ermöglicht das Failover von tavily-1 → tavily-2).
Eine Instanz ist nur dann aktiviert, wenn ihre erforderlichen Umgebungsvariablen gesetzt sind; andernfalls wird sie mit einer Logzeile übersprungen. trafilatura benötigt keine Konfiguration (immer an); jina funktioniert ohne Schlüssel (sein Schlüssel ist optional). Beim Start verlangt der Server mindestens eine Such- und eine Lese-Instanz, sonst beendet er sich mit einer klaren Meldung.
Einen Anbieter hinzufügen
Schreibe
src/providers/<type>.pymit einer Klasse, die mit@register("<type>")dekoriert ist undSearchProvider.search(...)oderReadProvider.read(...)implementiert.Importiere das Modul in
src/providers/__init__.py(damit der Dekorator ausgeführt wird).Füge eine Zeile
Instance("name", "<type>", api_key_env="YOUR_ENV_NAME")insrc/pipeline_config.pyhinzu und referenziere ihrennameinSEARCH_PIPELINE/READ_PIPELINE. Verwende den ENV-Variablennamen, niemals einen Wert.Dokumentiere die Umgebungsvariable in
.env.example.
Schnellstart
make install # create .venv + install dev/test deps
cp .env.example .env # fill in the keys you have (shortcut: make env)
make test # run tests
make run # run the server (streamable-http on MCP_HOST:MCP_PORT, endpoint /mcp)Konfiguration
Die gesamte Konfiguration stammt aus ENV / .env (siehe .env.example). Anbieter-Geheimnisse/URLs werden im Instanz-Loader per Name gelesen, nicht als Settings-Felder deklariert. Die nicht geheimen Stellschrauben (alle mit Standardwerten): MCP_HOST, MCP_PORT, LOG_LEVEL, LOG_FILE, LOG_ROTATION, LOG_RETENTION, REQUEST_TIMEOUT, FALLBACK_MIN_CHARS, READ_PAGES_CONCURRENCY, RETRIES, SEARCH_RERANK_ENABLED, JINA_TOKEN_BUDGET. Das URL-Limit pro Aufruf von read_pages ist fest 20 (harte Konstante, passend zur Tool-Beschreibung) – nicht konfigurierbar.
Umgebungsvariablen der Anbieter: SEARXNG_URL, BRAVE_API_KEY, SERPER_API_KEY, EXA_API_KEY, JINA_API_KEY (ein Schlüssel aktiviert den jina-Reader im Schlüsselmodus, den jina-search-Anbieter und den Such-Reranker; der Reader allein funktioniert auch ohne Schlüssel), CRAWL4AI_URL + CRAWL4AI_TOKEN, TAVILY_1_API_KEY, TAVILY_2_API_KEY, FIRECRAWL_API_KEY.
Proxy
Jede externe Instanz kann über einen eigenen SOCKS5/HTTP-Proxy geroutet werden, indem <INSTANCE>_PROXY gesetzt wird – nützlich für sauberen Egress an IP-basierten Sperren vorbei (z. B. Cloudflare vor Exa). Unterstützt pro Instanz: EXA_PROXY, BRAVE_PROXY, SERPER_PROXY, JINA_PROXY, TAVILY_1_PROXY, TAVILY_2_PROXY, FIRECRAWL_PROXY. Interne Instanzen (searxng, crawl4ai, trafilatura) haben keinen Proxy.
Der Wert wird direkt an httpx übergeben; socks5://host:port macht Proxy-seitiges DNS (der Zielhostname wird vom Proxy aufgelöst, wie bei curl --socks5-hostname), und socks5h:// / http://host:port werden ebenfalls akzeptiert. Nicht gesetzt → diese Instanz geht direkt. Die Pipeline hält einen gepoolten httpx-Client pro eindeutiger Proxy-URL (und einen direkten Client), ausgewählt pro Instanz, sodass proxierte und direkte Anbieter nebeneinander laufen. Benötigt das socks-Extra (httpx[socks], bereits gepinnt).
Protokollierung
Neben stderr (vom Docker-json-file-Treiber mit Rotationslimit erfasst) schreibt der Server eine persistente Logdatei nach data/research-mcp.log (Standard; LOG_ROTATION=20 MB, LOG_RETENTION=14 Tage). Sie liegt auf dem data/-Volume und überlebt daher Container-Neustarts und Image-Updates. Die Datei enthält eine Zeile pro Anfrage pro Tool-Aufruf – Suche (query, welche Anbieter-Instanzen tatsächlich liefen, Ergebnisanzahl, Latenz) und Lesen (url, der gewinnende Anbieter/Stufe oder pdf, ok, Latenz), plus eine read_pages count=N ok=K-Zusammenfassung – nützlich, um zu analysieren, wie sich Anfragen auf Anbieter-Stufen verteilen. Es werden keine Anfrageinhalte oder Geheimnisse protokolliert, nur URLs/Queries, Anbieternamen, Zählungen, Zeitmessungen.
Bereitstellung
Gitea Actions baut das Image und pusht es in die Gitea-Registry gitea.vvzvlad.xyz/projects/research-mcp (test → build, Tags latest + sha). In Produktion ziehen wir das vorgebaute Image über docker-compose.yml (hinter Traefik + basicAuth, watchtower aktualisiert latest automatisch; das data/-Volume behält die Logdatei über Updates hinweg) – wir bauen nie in Produktion.
Aufbau
Pfad | Zweck |
| Anbieter-Schnittstellen + |
|
|
| Ein Modul pro Anbieter-Typ. |
| PDF-Erkennung + pypdf-Text-Extraktion (von der Pipeline verwendet). |
| Instanzen im Code + Pipeline-Reihenfolge. |
| Instanz-Loader + Such-/Lese-Logik. |
|
|
| Nicht geheime Stellschrauben (pydantic-settings). |
|
|
| Dünner Einstiegspunkt: Server bauen, streamable-http ausführen. |
| pytest-Suite (Netzwerk mit respx gemockt). |
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityAmaintenanceMCP server for web crawling, searching, and AI-powered content extraction, supporting single-page, batch, and full-site crawling along with text, news, image, book, and video search.81MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server that aggregates web search results from multiple engines and optionally renders pages to Markdown, providing a unified search interface.103ISC
- AlicenseAqualityBmaintenanceMulti-source web search MCP server with RRF fusion, 4-layer URL extraction, and provider health tracking.68MIT
- AlicenseAqualityBmaintenanceAn MCP server that fetches web pages and extracts clean, AI-usable context from them, enabling tools for link discovery, content search, and integrated fetch-and-search operations.571MIT
Related MCP Connectors
Free remote MCP server for fetching public web pages through a rotating proxy pool.
Hosted MCP: 1404 structured web-data tools for search, maps, commerce, social, gaming & finance.
Federated commerce search across independent WooCommerce merchants. Keyless, read-only MCP server.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/vvzvlad/research-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server