research-mcp
research-mcp
Безсостоятельный MCP-фасад, который скрывает пирамиду поисковых/читающих провайдеров за единой streamable-http MCP-точкой и предоставляет всего 3 чистых инструмента с хорошими русскими текстами помощи. LLM получает простой набор «поиск → чтение»; за ним несколько провайдеров автоматически перебираются, объединяются и выполняют отказоустойчивый переход.
Приложение не выполняет аутентификацию — оно публикуется через Traefik + basicAuth на хосте. Оно не хранит состояние приложения: единственное, что сохраняется, — это файл журнала в data/ (хранится на томе).
Инструменты
Инструмент | Что делает |
| Поиск по всем включённым провайдерам, объединение + дедупликация → ранжированный список (заголовок, URL, сниппет). Только поиск. |
| Одна страница или PDF → чистый Markdown. Автоопределение типа, проход по конвейеру чтения (лёгкий → тяжёлый), пока один не сработает. |
| До 20 URL одновременно → список |
Related MCP server: serp-it
Архитектура: типы и экземпляры
Провайдеры — это плагины. Мы разделяем:
тип — класс реализации (например, поисковый провайдер
searxng), один на модуль вsrc/providers/, регистрируется с помощью@register("type").экземпляр — настроенная копия типа с его секретами/URL, разрешёнными из именованных переменных окружения (допускается несколько экземпляров одного типа, например
tavily-1/tavily-2с разными ключами).
Какие экземпляры существуют и порядок, в котором каждый конвейер их пробует, настраивается в коде (src/pipeline_config.py); ключи/URL берутся из ENV по имени переменной.
Поисковый конвейер (
searxng → brave → jina-search → serper → exa): включённые экземпляры работают параллельно; результаты объединяются и дедуплицируются по нормализованному URL (ранняя позиция в конвейере выигрывает). Когда заданJINA_API_KEY(иSEARCH_RERANK_ENABLEDне отключён), полный объединённый список затем переранжируется с помощьюjina-reranker-v3.5, чтобы усечение доnum_resultsсохраняло наиболее релевантные результаты, а не слепой префикс порядка конвейера; любой сбой переранжирования возвращается к порядку объединения.searxngиbraveдополнительно ограничивают себя локально (один запрос за 45 с и за 1,1 с соответственно, что соответствует измеренному лимиту вышестоящего сервиса); когда слот занят, они пропускают текущий поиск, а не ждут его.Конвейер чтения (
trafilatura → jina → crawl4ai → tavily-1 → tavily-2 → firecrawl): одиночный пробный GET классифицирует URL. PDF (Content-Type /.pdf/ магическое%PDF) извлекаются с помощью pypdf; для HTML то же тело передаётся вtrafilatura, чтобы горячий путь не делал второй GET, затем остальные экземпляры пробуются по порядку, и первый, вернувший содержимое>= FALLBACK_MIN_CHARS, побеждает.
Сквозные аспекты: одна повторная попытка при временных ошибках (5xx / транспортные ошибки) с короткой задержкой; 402 (исчерпаны кредиты) / 429 (ограничение скорости) рассматриваются как сбой провайдера → следующий экземпляр (именно это обеспечивает отказоустойчивый переход tavily-1 → tavily-2).
Экземпляр включён, только если заданы его обязательные переменные окружения; в противном случае он пропускается с записью в журнал. trafilatura не требует настройки (всегда включён); jina работает без ключа (его ключ необязателен). При запуске сервер требует хотя бы один поисковый и один читающий экземпляр, иначе завершается с понятным сообщением.
Добавление провайдера
Напишите
src/providers/<type>.pyс классом, декорированным@register("<type>"), реализующимSearchProvider.search(...)илиReadProvider.read(...).Импортируйте модуль в
src/providers/__init__.py(чтобы декоратор выполнился).Добавьте строку
Instance("name", "<type>", api_key_env="YOUR_ENV_NAME")вsrc/pipeline_config.pyи укажите егоnameвSEARCH_PIPELINE/READ_PIPELINE. Используйте ИМЯ переменной ENV, никогда не значение.Документируйте переменную окружения в
.env.example.
Быстрый старт
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)Конфигурация
Вся конфигурация берётся из ENV / .env (см. .env.example). Секреты/URL провайдеров читаются по имени в загрузчике экземпляров, а не объявляются как поля Settings. Несекретные параметры (все со значениями по умолчанию): 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. Ограничение числа URL на вызов read_pages — фиксированное 20 (жёсткая константа, соответствующая описанию инструмента) — не настраивается.
Переменные окружения провайдеров: SEARXNG_URL, BRAVE_API_KEY, SERPER_API_KEY, EXA_API_KEY, JINA_API_KEY (один ключ включает читатель jina в режиме с ключом, провайдер jina-search и переранжировщик поиска; читатель также работает без ключа), CRAWL4AI_URL + CRAWL4AI_TOKEN, TAVILY_1_API_KEY, TAVILY_2_API_KEY, FIRECRAWL_API_KEY.
Прокси
Любой внешний экземпляр можно направить через собственный SOCKS5/HTTP-прокси, задав <INSTANCE>_PROXY — полезно для чистого исходящего трафика в обход блокировок по IP (например, Cloudflare перед Exa). Поддерживается для каждого экземпляра: EXA_PROXY, BRAVE_PROXY, SERPER_PROXY, JINA_PROXY, TAVILY_1_PROXY, TAVILY_2_PROXY, FIRECRAWL_PROXY. Внутренние экземпляры (searxng, crawl4ai, trafilatura) прокси не имеют.
Значение передаётся напрямую в httpx; socks5://host:port выполняет DNS на стороне прокси (целевое имя хоста разрешается прокси, как curl --socks5-hostname), также принимаются socks5h:// и http://host:port. Не задано → этот экземпляр идёт напрямую. Конвейер держит один пул httpx-клиентов на каждый отдельный URL прокси (и один прямой клиент), выбираемый для каждого экземпляра, так что проксированные и прямые провайдеры работают бок о бок. Требуется дополнительный пакет socks (httpx[socks], уже закреплён).
Журналирование
Помимо stderr (захватываемого драйвером Docker json-file с ротацией по размеру), сервер записывает постоянный файл журнала в data/research-mcp.log (по умолчанию; LOG_ROTATION=20 MB, LOG_RETENTION=14 days). Он находится на томе data/, поэтому переживает перезапуски контейнера и обновления образа. Файл содержит одну строку на запрос для каждого вызова инструмента — поиск (query, какие экземпляры провайдеров реально выполнялись, количество результатов, задержка) и чтение (url, победивший провайдер/уровень или pdf, ok, задержка), а также сводку read_pages count=N ok=K — что полезно для анализа распределения запросов по уровням провайдеров. Тела запросов и секреты не журналируются, только URL/запросы, имена провайдеров, количества, тайминги.
Развёртывание
Gitea Actions собирает образ и отправляет его в реестр Gitea gitea.vvzvlad.xyz/projects/research-mcp (test → build, теги latest + sha). На проде мы тянем предварительно собранный образ через docker-compose.yml (за Traefik + basicAuth, watchtower автоматически обновляет latest; том data/ сохраняет файл журнала между обновлениями) — мы никогда не собираем на проде.
Структура
Путь | Назначение |
| Интерфейсы провайдеров + |
| Декоратор |
| Один модуль на тип провайдера. |
| Определение PDF + извлечение текста через pypdf (используется конвейером). |
| Экземпляры в коде + порядок конвейеров. |
| Загрузчик экземпляров + логика поиска/чтения. |
|
|
| Несекретные параметры (pydantic-settings). |
|
|
| Тонкая точка входа: сборка сервера, запуск streamable-http. |
| Набор pytest (сеть замокана с помощью 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