research-mcp
research-mcp
Una fachada MCP sin estado que oculta una pirámide de proveedores de búsqueda/lectura detrás de un único endpoint MCP streamable-http y expone solo 3 herramientas limpias con buenos textos de ayuda en ruso. Un LLM obtiene un conjunto de herramientas simple de "buscar → leer"; detrás, varios proveedores se prueban, fusionan y cambian automáticamente.
La aplicación no hace autenticación — se publica a través de Traefik + basicAuth en el host. No mantiene estado de aplicación: lo único que se persiste es un archivo de registro en data/ (guardado en un volumen).
Tools
Tool | Qué hace |
| Busca en todos los proveedores habilitados, fusiona + deduplica → lista clasificada (título, URL, fragmento). Solo búsqueda. |
| Una página o PDF → Markdown limpio. Detecta automáticamente el tipo, recorre el pipeline de lectura (ligero → pesado) hasta que uno tenga éxito. |
| Hasta 20 urls concurrentemente → lista de |
Related MCP server: serp-it
Arquitectura: tipos + instancias
Los proveedores son plugins. Separamos:
tipo — una clase de implementación (por ejemplo, el proveedor de búsqueda
searxng), una por módulo ensrc/providers/, registrada con@register("type").instancia — una copia configurada de un tipo con sus secretos/URL resueltos desde variables de entorno con nombre (se permiten múltiples instancias de un tipo, p. ej.
tavily-1/tavily-2con diferentes claves).
Qué instancias existen y el orden en que cada pipeline las prueba se configura en código (src/pipeline_config.py); las claves/URLs provienen de ENV por nombre de variable.
Pipeline de búsqueda (
searxng → brave → jina-search → serper → exa): las instancias habilitadas se ejecutan concurrentemente; los resultados se fusionan y deduplican por URL normalizada (la posición anterior en el pipeline gana). CuandoJINA_API_KEYestá configurada (ySEARCH_RERANK_ENABLEDno está desactivado), la lista fusionada completa se reordena conjina-reranker-v3.5para que el recorte anum_resultsconserve los resultados más relevantes en lugar de un prefijo ciego por orden de pipeline; cualquier fallo de reordenamiento vuelve al orden de fusión.searxngybraveademás se limitan localmente (una consulta cada 45s y cada 1.1s respectivamente, coincidiendo con un límite ascendente medido); cuando el espacio está ocupado, omiten la búsqueda actual en lugar de esperarla.Pipeline de lectura (
trafilatura → jina → crawl4ai → tavily-1 → tavily-2 → firecrawl): un único GET de sondeo clasifica la URL. Los PDF (Content-Type /.pdf/ magia%PDF) se extraen con pypdf; para HTML, ese mismo cuerpo se entrega atrafilaturapara que la ruta caliente nunca haga GET dos veces, luego las instancias restantes se prueban en orden y la primera que devuelva contenido>= FALLBACK_MIN_CHARSgana.
Transversal: un reintento transitorio (errores 5xx / de transporte) con un backoff corto; 402 (sin créditos) / 429 (límite de velocidad) se tratan como fallo del proveedor → siguiente instancia (esto es lo que hace que tavily-1 → tavily-2 falle).
Una instancia está habilitada solo si sus variables de entorno requeridas están configuradas; de lo contrario, se omite con una línea de registro. trafilatura no necesita configuración (siempre activo); jina funciona sin clave (su clave es opcional). Al inicio, el servidor requiere al menos una instancia de búsqueda y una de lectura; de lo contrario, sale con un mensaje claro.
Añadir un proveedor
Escribe
src/providers/<type>.pycon una clase decorada con@register("<type>")que implementeSearchProvider.search(...)oReadProvider.read(...).Importa el módulo en
src/providers/__init__.py(para que el decorador se ejecute).Añade una línea
Instance("name", "<type>", api_key_env="YOUR_ENV_NAME")ensrc/pipeline_config.pyy referencia sunameenSEARCH_PIPELINE/READ_PIPELINE. Usa el NOMBRE de la variable ENV, nunca un valor.Documenta la variable de entorno en
.env.example.
Inicio rápido
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)Configuración
Toda la configuración proviene de ENV / .env (ver .env.example). Los secretos/URLs de los proveedores se leen por nombre en el cargador de instancias, no se declaran como campos de Settings. Los ajustes no secretos (todos con valores predeterminados): 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. El límite de urls por llamada de read_pages es un 20 fijo (constante dura, que coincide con la descripción de la herramienta) — no configurable.
Variables de entorno de proveedores: SEARXNG_URL, BRAVE_API_KEY, SERPER_API_KEY, EXA_API_KEY, JINA_API_KEY (una clave habilita el lector jina en modo con clave, el proveedor jina-search y el reordenador de búsqueda; el lector solo también funciona sin clave), CRAWL4AI_URL + CRAWL4AI_TOKEN, TAVILY_1_API_KEY, TAVILY_2_API_KEY, FIRECRAWL_API_KEY.
Proxy
Cualquier instancia externa puede enrutarse a través de su propio proxy SOCKS5/HTTP configurando <INSTANCE>_PROXY — útil para una salida limpia más allá de bloqueos por IP (por ejemplo, Cloudflare frente a Exa). Soportado por instancia: EXA_PROXY, BRAVE_PROXY, SERPER_PROXY, JINA_PROXY, TAVILY_1_PROXY, TAVILY_2_PROXY, FIRECRAWL_PROXY. Las instancias internas (searxng, crawl4ai, trafilatura) no tienen proxy.
El valor se pasa directamente a httpx; socks5://host:port hace DNS del lado del proxy (el nombre de host de destino lo resuelve el proxy, como curl --socks5-hostname), y también se aceptan socks5h:// / http://host:port. Sin configurar → esa instancia va directa. El pipeline mantiene un cliente httpx agrupado por cada URL de proxy distinta (y un cliente directo), seleccionado por instancia, de modo que los proveedores con proxy y directos se ejecutan lado a lado. Necesita el extra socks (httpx[socks], ya fijado).
Registro
Además de stderr (capturado por el controlador json-file con rotación limitada de Docker), el servidor escribe un archivo de registro persistente en data/research-mcp.log (por defecto; LOG_ROTATION=20 MB, LOG_RETENTION=14 days). Vive en el volumen data/, por lo que sobrevive a reinicios de contenedor y actualizaciones de imagen. El archivo lleva una línea por solicitud por llamada de herramienta — búsqueda (query, qué instancias de proveedor realmente se ejecutaron, recuento de resultados, latencia) y lectura (url, el proveedor/nivel ganador o pdf, ok, latencia), más un resumen read_pages count=N ok=K — lo que lo hace útil para analizar cómo se distribuyen las solicitudes entre los niveles de proveedores. No se registran cuerpos de solicitud ni secretos, solo urls/consultas, nombres de proveedores, recuentos, tiempos.
Despliegue
Gitea Actions construye la imagen y la envía al registro de Gitea gitea.vvzvlad.xyz/projects/research-mcp (test → build, etiquetas latest + sha). En producción extraemos la imagen preconstruida mediante docker-compose.yml (detrás de Traefik + basicAuth, watchtower actualiza automáticamente latest; el volumen data/ mantiene el archivo de registro entre actualizaciones) — nunca construimos en producción.
Estructura
Ruta | Propósito |
| Interfaces de proveedor + |
| Decorador |
| Un módulo por tipo de proveedor. |
| Detección de PDF + extracción de texto con pypdf (usado por el pipeline). |
| Instancias en código + orden del pipeline. |
| Cargador de instancias + lógica de búsqueda/lectura. |
|
|
| Ajustes no secretos (pydantic-settings). |
|
|
| Punto de entrada delgado: construir servidor, ejecutar streamable-http. |
| Suite de pytest (red simulada con respx). |
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