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 или html
  • waitMs — дополнительное время ожидания после загрузки страницы на случай, если контент появляется медленно
  • timeoutMs — время ожидания до прекращения попытки (по умолчанию: 15 секунд)
  • maxChars — максимальный объём возвращаемого содержимого (по умолчанию: 40 000 символов)
  • includeHtml — установите true, чтобы также вернуть необработанный HTML вместе с содержимым
  • headless — установите false, чтобы увидеть окно браузера (полезно для отладки)

Возвращает:

  • url — запрошенный URL
  • finalUrl — 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 и snippet
  • searchedAt — временная метка 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 — запрошенный URL
  • contentType — либо pdf, либо html
  • title — заголовок страницы/документа
  • author — автор PDF (только для PDF, если доступно)
  • creationDate — дата создания PDF (только для PDF, если доступно)
  • pageCount — количество страниц (только для PDF)
  • totalChars — общее количество символов (используйте с offset для постраничной навигации)
  • offset — использованное смещение
  • content — извлечённое текстовое содержимое
  • fetchedAt — временная метка ISO
  • truncated — осталось ли ещё содержимое после этого фрагмента

Возвращает (режим поиска):

  • 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 — запрошенный URL
  • contentType — либо pdf, либо html
  • title — заголовок страницы/документа
  • totalChars — общее количество символов в документе
  • ask — данная инструкция
  • answer — ответ LLM
  • model — модель, сгенерировавшая ответ
  • 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)

Возвращает:

  • typeall или topic
  • totalDocuments — общее количество документов (только когда 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, createdAt
    • matchTypefilename, content или filename+content
    • matches — Массив { line, context } для каждого места совпадения

Используйте значения line с stash_extract, чтобы перейти непосредственно к местам совпадений.

stash_extract

Извлекает содержимое из сохранённого документа для чтения. Используйте номера строк из результатов stash_search, чтобы перейти непосредственно к совпадениям.

Параметры:

  • id (обязательный) — ID документа из stash_list/stash_search
  • maxChars — Максимальный объём возвращаемого текста (по умолчанию: 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_search
  • ask (обязательный) — Вопрос или инструкция для LLM
  • askMaxInputTokens — Максимум входных токенов за один вызов LLM (по умолчанию: 150 000)
  • askMaxOutputTokens — Максимум выходных токенов за один вызов LLM (по умолчанию: 4 096)
  • askTimeout — Тайм-аут в миллисекундах (по умолчанию: 300 000 = 5 минут)
  • askSplitAndSynthesize — Для больших документов: разбить на фрагменты, обработать каждый, затем синтезировать результаты (по умолчанию: false)

Возвращает:

  • id, filename, fileType, summary — Метаданные документа
  • totalChars — Всего символов в документе
  • ask — Данная инструкция
  • answer — Ответ LLM
  • model — Модель, сгенерировавшая ответ
  • chunksProcessed — Количество обработанных фрагментов

Типичный рабочий процесс

  1. Перетащите файлы в ~/.research-friend/inbox/
  2. Запустите stash_process_inbox
  3. Используйте stash_list для просмотра тем
  4. Используйте stash_search для поиска релевантных документов
  5. Используйте stash_extract для чтения конкретного документа или stash_ask, чтобы задать вопросы о нём

Устранение неполадок

«Браузер неожиданно закрылся» или подобные ошибки

Попробуйте переустановить браузер:

npx playwright install chromium --force

В Linux вам также могут понадобиться системные зависимости:

npx playwright install-deps chromium

Сервер не запускается

Убедитесь, что вы используете Node.js версии 20 или новее:

node --version

Если ваша версия старее, посетите nodejs.org, чтобы скачать более новую.

Лицензия

MIT