MCP Research Friend Server
официальныйResearch tools, including a Sqlite-backed document stash
Документация
Research Friend
Дружелюбный помощник для ИИ-ассистентов, которым нужно искать информацию в интернете и управлять локальным хранилищем исследований.
Research Friend — это MCP-сервер, который даёт вашим ИИ-инструментам возможность загружать веб-страницы и выполнять поиск в интернете. Внутри используется настоящий веб-браузер, поэтому он работает даже с современными сайтами, активно использующими JavaScript. Также в нём есть локальное «хранилище» для сохранения документов, извлечения текста и поиска по вашей библиотеке.
Чтобы использовать все его возможности, вам понадобится MCP-клиент, поддерживающий промпты (распространено) и семплинг (встречается реже). Мы разрабатываем Research Friend совместно с Chabeau, который поддерживает и то, и другое.
Что он умеет?
- Загружать веб-страницы с помощью настоящего браузера (включая сайты с большим количеством JS)
- Загружать PDF-файлы и извлекать из них текстовое содержимое
- Искать в интернете через DuckDuckGo или Google
- Вести локальное хранилище документов для поиска, просмотра списка и извлечения данных
Начало работы
На вашем компьютере должен быть установлен Node.js версии 20 или новее.
1. Установка зависимостей
Откройте терминал в этой папке и выполните:
npm install
2. Установка поддержки браузера
Research Friend использует Playwright для управления веб-браузером. После установки зависимостей необходимо установить браузер:
npx playwright install chromium
Это загрузит копию Chromium, которую будет использовать Playwright. Она не зависит от уже установленных у вас браузеров.
3. Запуск сервера
node src/index.js
Сервер обменивается данными через stdio (стандартный ввод/вывод), именно так к нему подключаются MCP-клиенты.
Добавление в ваш MCP-клиент
Способ добавления Research Friend зависит от используемого MCP-клиента. Вот общий пример того, как может выглядеть конфигурация:
[[mcp_servers]]
id = "research-friend"
command = "node"
args = ["/path/to/mcp-research-friend/src"]
transport = "stdio"
Замените /path/to/mcp-research-friend на фактический путь к этой папке на вашем компьютере.
Инструменты
Веб-инструменты
friendly_web_fetch
Загружает веб-страницу и возвращает её содержимое. По умолчанию возвращает markdown с сохранением ссылок — идеально для LLM. Использует Readability для извлечения основного содержимого (убирая навигацию, рекламу и т.д.). Для PDF, постраничной навигации или поиска по содержимому используйте friendly_web_extract.
Параметры:
url(обязательный) — веб-адрес для загрузкиoutputFormat— формат вывода:markdown(по умолчанию),textилиhtmlwaitMs— дополнительное время ожидания после загрузки страницы на случай, если контент появляется медленноtimeoutMs— время ожидания до прекращения попытки (по умолчанию: 15 секунд)maxChars— максимальный объём возвращаемого содержимого (по умолчанию: 40 000 символов)includeHtml— установитеtrue, чтобы также вернуть необработанный HTML вместе с содержимымheadless— установитеfalse, чтобы увидеть окно браузера (полезно для отладки)
Возвращает:
url— запрошенный URLfinalUrl— URL после всех перенаправленийtitle— заголовок страницыcontent— извлечённое содержимое (в запрошенном формате)html— необработанный HTML (только еслиincludeHtmlистинно)meta— метаданные страницы (описание, автор, время публикации и т.д.)fetchedAt— временная метка ISO, когда страница была загруженаtruncated— было ли содержимое обрезано, чтобы уместиться вmaxChars
friendly_search
Выполняет поиск в интернете и возвращает список результатов.
Параметры:
query(обязательный) — что искатьengine— какую поисковую систему использовать (duckduckgoилиgoogle)maxResults— сколько результатов вернуть (по умолчанию: 10, максимум: 50)timeoutMs— время ожидания до прекращения попытки (по умолчанию: 15 секунд)headless— установитеfalse, чтобы увидеть окно браузера
Возвращает:
query— использованный поисковый запросengine— использованная поисковая системаresults— массив результатов, каждый сtitle,urlиsnippetsearchedAt— временная метка ISO, когда был выполнен поискfallback_result_html— необработанный HTML страницы (включается, только если результаты не найдены)debug_info— диагностическая информация о попытке поиска
Обработка CAPTCHA:
Если CAPTCHA обнаружена при работе в фоновом режиме, инструмент автоматически повторяет попытку с видимым окном браузера. Это даёт вам возможность решить CAPTCHA вручную. Поле debug_info.retried указывает, был ли использован этот резервный вариант.
friendly_web_extract
Извлекает содержимое из URL. Автоматически определяет, указывает ли URL на PDF или веб-страницу, и обрабатывает соответствующим образом.
Параметры:
url(обязательный) — URL для загрузки (PDF или веб-страница)maxChars— максимальный объём возвращаемого текста (по умолчанию: 40 000 символов)offset— позиция символа, с которой начинать (по умолчанию: 0). Используйте для постраничной навигации по большому содержимому.search— поиск фразы и возврат совпадений с окружающим контекстом вместо полного содержимогоcontextChars— количество символов контекста вокруг каждого совпадения (по умолчанию: 200)waitMs— дополнительное время ожидания после загрузки страницы для динамического контента (только для веб-страниц)timeoutMs— время ожидания до прекращения попытки (по умолчанию: 15 секунд, только для веб-страниц)headless— установитеfalse, чтобы увидеть окно браузера (только для веб-страниц)
Возвращает (обычный режим):
url— запрошенный URLcontentType— либоpdf, либоhtmltitle— заголовок страницы/документаauthor— автор PDF (только для PDF, если доступно)creationDate— дата создания PDF (только для PDF, если доступно)pageCount— количество страниц (только для PDF)totalChars— общее количество символов (используйте сoffsetдля постраничной навигации)offset— использованное смещениеcontent— извлечённое текстовое содержимоеfetchedAt— временная метка ISOtruncated— осталось ли ещё содержимое после этого фрагмента
Возвращает (режим поиска):
url,contentType,title,totalChars,fetchedAt— то же, что и вышеsearch— использованная поисковая фразаmatchCount— количество найденных совпаденийmatches— массив совпадений, каждый сposition,context,prefixиsuffix
friendly_web_ask
Загружает URL (PDF или веб-страницу) и поручает LLM ответить на вопросы по нему. Автоматически определяет тип содержимого. Документ обрабатывается в отдельном контексте, что позволяет сохранять ваш основной диалог компактным.
Параметры:
url(обязательный) — URL для загрузки (PDF или веб-страница)ask(обязательный) — вопрос или инструкция для LLM (суммировать, извлечь информацию, ответить на вопросы и т.д.)askMaxInputTokens— максимальное количество входных токенов на один вызов LLM (по умолчанию: 150 000)askMaxOutputTokens— максимальное количество выходных токенов на один вызов LLM (по умолчанию: 4 096)askTimeout— тайм-аут в миллисекундах (по умолчанию: 300 000 = 5 минут)askSplitAndSynthesize— для больших документов: разбить на фрагменты, обработать каждый, затем синтезировать результаты (по умолчанию: false). Внимание: потребляет много токенов.waitMs— дополнительное время ожидания после загрузки страницы для динамического контента (только для веб-страниц)timeoutMs— время ожидания до прекращения попытки (по умолчанию: 15 секунд, только для веб-страниц)headless— установитеfalse, чтобы увидеть окно браузера (только для веб-страниц)
Возвращает:
url— запрошенный URLcontentType— либоpdf, либоhtmltitle— заголовок страницы/документаtotalChars— общее количество символов в документеask— данная инструкцияanswer— ответ LLMmodel— модель, сгенерировавшая ответchunksProcessed— количество обработанных фрагментов (1 для небольших документов, больше при использованииaskSplitAndSynthesize)fetchedAt— временная метка ISO
Режим Ask использует MCP-семплинг, чтобы LLM обработал документ с любой инструкцией. Это полезно для:
- Больших документов, которые перегрузили бы контекст
- Снижения затрат токенов в основном диалоге
Когда askSplitAndSynthesize включён, документы, превышающие askMaxInputTokens, автоматически разбиваются на перекрывающиеся фрагменты. Каждый фрагмент обрабатывается отдельно, а результаты синтезируются в единый связный ответ. Итоговый ответ предоставляется на том же языке, что и ваш запрос, независимо от языка документа.
Хранилище документов
Хранилище — это локальная библиотека документов с возможностью поиска. Поддерживаются PDF, HTML-файлы и простой текст (Markdown/TXT). Когда вы добавляете документ, Research Friend сохраняет исходный файл, извлекает текст (для PDF/HTML) и сохраняет метаданные в локальной базе данных. Для поиска используется ripgrep, обеспечивающий быстрый поиск с учётом фраз.
Расположение хранилища
Хранилище находится в ~/.research-friend/:
inbox/— поместите файлы сюда для обработкиstore/— организованное хранение документов и извлечённый текстstash.db— база данных метаданных
Поддерживаемые типы файлов
- PDF:
.pdf(текст извлечён) - HTML:
.html,.htm(текст извлечён) - Markdown:
.md,.markdown(сохраняется как простой текст) - Текст:
.txt(сохраняется как простой текст)
Инструменты хранилища
stash_open_inbox
Открыть папку входящих файлов хранилища в файловом менеджере для удобного перетаскивания.
Возвращает:
opened— был ли отправлен запрос на открытие папкиinboxPath— абсолютный путь к папке входящихcommand— использованная команда ОСargs— использованные аргументы команды
stash_process_inbox
Обработать файлы в inbox/, классифицировать их по темам, извлечь текст и сохранить результаты.
Для длинных документов классификация использует выборочные разделы (начало/середина/конец плюс несколько случайных фрагментов) для повышения точности определения темы.
Возвращает:
processed— массив имён файлов, успешно обработанныхerrors— все возникшие ошибкиdocuments— массив созданных записей документов
reindex_stash
Перегенерировать сводки, перераспределить темы и обновить метаданные хранилища для сохранённых документов. Если ids опущен или пуст, переиндексируются все документы.
Параметры:
ids— идентификаторы документов для переиндексации (необязательно)
Возвращает:
reindexed— переиндексированные идентификаторы документовerrors— все возникшие ошибкиdocuments— массив обновлённых записей документов
stash_list
Вывести список документов в хранилище.
Параметры:
topic— фильтр по теме (необязательно)limit— максимальное количество результатов (по умолчанию: 50)offset— смещение для постраничного вывода (по умолчанию: 0)
Возвращает:
type—allилиtopictotalDocuments— общее количество документов (только когдаtypeравноall)count— результаты, возвращённые после постраничного выводаoffset— использованное смещение постраничного выводаlimit— использованный лимит постраничного выводаtopics— сводка известных тем и количества документовdocuments— список документов с метаданными (включаетisPrimaryпри выводе списка по теме)
stash_search
Поиск по именам файлов и содержимому в хранилище. Все поисковые запросы должны присутствовать (логика И). Совпадения по имени файла выводятся первыми. Используйте кавычки для точных фраз.
Параметры:
query(обязательный) — поисковые запросы. Используйте кавычки для фраз:"sparkling wine"topic— фильтр по теме (необязательно)ids— фильтр по конкретным идентификаторам документов (необязательно)limit— максимальное количество возвращаемых документов (по умолчанию: 20)offset— смещение для постраничного вывода (по умолчанию: 0)maxMatchesPerDoc— максимальное количество совпадений на документ (по умолчанию: 50)context— строк контекста вокруг каждого совпадения (по умолчанию: 1, максимум: 5). Определяет как близость расположения терминов для совпадения, так и объём возвращаемого окружающего текста. Возвращает:totalMatches— Всего документов, совпавших до пагинацииcount— Результаты, возвращённые после пагинацииresults— Массив документов, каждый из которых содержит:id,filename,fileType,summary,charCount,createdAtmatchType—filename,contentилиfilename+contentmatches— Массив{ line, context }для каждого места совпадения
Используйте значения line с stash_extract, чтобы перейти непосредственно к местам совпадений.
stash_extract
Извлекает содержимое из сохранённого документа для чтения. Используйте номера строк из результатов stash_search, чтобы перейти непосредственно к совпадениям.
Параметры:
id(обязательный) — ID документа изstash_list/stash_searchmaxChars— Максимальный объём возвращаемого текста (по умолчанию: 40 000 символов)offset— Позиция символа, с которой начинать (взаимоисключающий сline)line— Номер строки, с которой начинать (взаимоисключающий сoffset)
Возвращает:
id,filename,fileType,summary— Метаданные документаtotalChars— Всего символов в документеoffset— Смещение символов (включается при использованииlineдля справки)line— Номер строки (только если использовался параметрline)content— Извлечённое текстовое содержимоеtruncated— Осталось ли ещё содержимое после этого фрагмента
stash_ask
Позволяет LLM отвечать на вопросы о сохранённом документе. Документ обрабатывается в отдельном контексте, что сохраняет ваш основной разговор компактным.
Параметры:
id(обязательный) — ID документа изstash_list/stash_searchask(обязательный) — Вопрос или инструкция для LLMaskMaxInputTokens— Максимум входных токенов за один вызов LLM (по умолчанию: 150 000)askMaxOutputTokens— Максимум выходных токенов за один вызов LLM (по умолчанию: 4 096)askTimeout— Тайм-аут в миллисекундах (по умолчанию: 300 000 = 5 минут)askSplitAndSynthesize— Для больших документов: разбить на фрагменты, обработать каждый, затем синтезировать результаты (по умолчанию: false)
Возвращает:
id,filename,fileType,summary— Метаданные документаtotalChars— Всего символов в документеask— Данная инструкцияanswer— Ответ LLMmodel— Модель, сгенерировавшая ответchunksProcessed— Количество обработанных фрагментов
Типичный рабочий процесс
- Перетащите файлы в
~/.research-friend/inbox/ - Запустите
stash_process_inbox - Используйте
stash_listдля просмотра тем - Используйте
stash_searchдля поиска релевантных документов - Используйте
stash_extractдля чтения конкретного документа илиstash_ask, чтобы задать вопросы о нём
Устранение неполадок
«Браузер неожиданно закрылся» или подобные ошибки
Попробуйте переустановить браузер:
npx playwright install chromium --force
В Linux вам также могут понадобиться системные зависимости:
npx playwright install-deps chromium
Сервер не запускается
Убедитесь, что вы используете Node.js версии 20 или новее:
node --version
Если ваша версия старее, посетите nodejs.org, чтобы скачать более новую.
Лицензия
MIT