MCP Research Friend Server

oficial

Research tools, including a Sqlite-backed document stash

Documentação

Research Friend

Um assistente amigável para ferramentas de IA que precisam buscar coisas na web e gerenciar um repositório local de pesquisa.

O Research Friend é um servidor MCP que oferece às suas ferramentas de IA a capacidade de buscar páginas da web e pesquisar na internet. Ele usa um navegador web real por trás dos panos, então funciona até mesmo com sites modernos que dependem muito de JavaScript. Ele também inclui um "repositório" local para armazenar documentos, extrair texto e pesquisar em toda a sua biblioteca.

Para aproveitar todos os seus recursos, você precisará de um cliente MCP que suporte prompts (comum) e sampling (menos comum). Estamos desenvolvendo o Research Friend junto com o Chabeau, que suporta ambos.

O que ele pode fazer?

  • Buscar páginas da web com um navegador real (incluindo sites com muito JS)
  • Buscar PDFs e extrair seu conteúdo de texto
  • Pesquisar na web via DuckDuckGo ou Google
  • Manter um repositório local de documentos para pesquisa, listagem e extração

Primeiros passos

Você precisará do Node.js versão 20 ou mais recente instalado no seu computador.

1. Instalar dependências

Abra um terminal nesta pasta e execute:

npm install

2. Instalar suporte ao navegador

O Research Friend usa o Playwright para controlar um navegador web. Após instalar as dependências, você precisará instalar o navegador:

npx playwright install chromium

Isso baixa uma cópia do Chromium que o Playwright usará. É separado de quaisquer navegadores que você já tenha instalado.

3. Iniciar o servidor

node src/index.js

O servidor se comunica via stdio (entrada/saída padrão), que é como os clientes MCP se conectam a ele.

Adicionando ao seu cliente MCP

A forma de adicionar o Research Friend depende de qual cliente MCP você está usando. Aqui está um exemplo geral de como a configuração pode ser:

[[mcp_servers]]
id = "research-friend"
command = "node"
args = ["/path/to/mcp-research-friend/src"]
transport = "stdio"

Substitua /path/to/mcp-research-friend pelo caminho real para esta pasta no seu computador.

Ferramentas

Ferramentas web

friendly_web_fetch

Busca uma página da web e retorna seu conteúdo. Por padrão, retorna markdown com links preservados — ideal para LLMs. Usa o Readability para extrair o conteúdo principal (removendo navegação, anúncios, etc.). Para PDFs, paginação ou pesquisa dentro do conteúdo, use friendly_web_extract em vez disso.

Parâmetros:

  • url (obrigatório) - O endereço web a ser buscado
  • outputFormat - Formato de saída: markdown (padrão), text ou html
  • waitMs - Tempo extra para esperar após o carregamento da página, caso o conteúdo apareça lentamente
  • timeoutMs - Quanto tempo esperar antes de desistir (padrão: 15 segundos)
  • maxChars - Quantidade máxima de conteúdo a retornar (padrão: 40.000 caracteres)
  • includeHtml - Defina como true para também retornar o HTML bruto junto com o conteúdo
  • headless - Defina como false para ver a janela do navegador (útil para depuração)

Retorna:

  • url - A URL que foi solicitada
  • finalUrl - A URL após quaisquer redirecionamentos
  • title - O título da página
  • content - O conteúdo extraído (no formato solicitado)
  • html - HTML bruto (somente se includeHtml for verdadeiro)
  • meta - Metadados da página (descrição, autor, horário de publicação, etc.)
  • fetchedAt - Timestamp ISO de quando a página foi buscada
  • truncated - Se o conteúdo foi truncado para caber em maxChars

friendly_search

Pesquisa na web e retorna uma lista de resultados.

Parâmetros:

  • query (obrigatório) - O que pesquisar
  • engine - Qual mecanismo de busca usar (duckduckgo ou google)
  • maxResults - Quantos resultados retornar (padrão: 10, máximo: 50)
  • timeoutMs - Quanto tempo esperar antes de desistir (padrão: 15 segundos)
  • headless - Defina como false para ver a janela do navegador

Retorna:

  • query - A consulta de pesquisa que foi usada
  • engine - Qual mecanismo de busca foi usado
  • results - Array de resultados, cada um com title, url e snippet
  • searchedAt - Timestamp ISO de quando a pesquisa foi realizada
  • fallback_result_html - HTML bruto da página (incluído apenas se nenhum resultado foi encontrado)
  • debug_info - Informações de diagnóstico sobre a tentativa de pesquisa

Tratamento de CAPTCHA: Se um CAPTCHA for detectado durante a execução em modo headless, a ferramenta automaticamente tenta novamente com uma janela do navegador visível. Isso lhe dá a chance de resolver o CAPTCHA manualmente. O campo debug_info.retried indica se esse fallback foi usado.

friendly_web_extract

Extrai conteúdo de uma URL. Detecta automaticamente se a URL aponta para um PDF ou uma página da web e trata cada um adequadamente.

Parâmetros:

  • url (obrigatório) - A URL a ser buscada (PDF ou página da web)
  • maxChars - Quantidade máxima de texto a retornar (padrão: 40.000 caracteres)
  • offset - Posição do caractere para começar (padrão: 0). Use isso para paginar através de conteúdo grande.
  • search - Pesquisar por uma frase e retornar correspondências com contexto ao redor em vez do conteúdo completo
  • contextChars - Caracteres de contexto ao redor de cada correspondência de pesquisa (padrão: 200)
  • waitMs - Tempo extra para esperar após o carregamento da página para conteúdo dinâmico (apenas páginas da web)
  • timeoutMs - Quanto tempo esperar antes de desistir (padrão: 15 segundos, apenas páginas da web)
  • headless - Defina como false para ver a janela do navegador (apenas páginas da web)

Retorna (modo normal):

  • url - A URL que foi solicitada
  • contentType - pdf ou html
  • title - O título da página/documento
  • author - O autor do PDF (apenas PDFs, se disponível)
  • creationDate - Quando o PDF foi criado (apenas PDFs, se disponível)
  • pageCount - Número de páginas (apenas PDFs)
  • totalChars - Total de caracteres (use com offset para paginar)
  • offset - O deslocamento que foi usado
  • content - O conteúdo de texto extraído
  • fetchedAt - Timestamp ISO
  • truncated - Se mais conteúdo permanece após este trecho

Retorna (modo de pesquisa):

  • url, contentType, title, totalChars, fetchedAt - Igual ao acima
  • search - A frase de pesquisa que foi usada
  • matchCount - Número de correspondências encontradas
  • matches - Array de correspondências, cada uma com position, context, prefix e suffix

friendly_web_ask

Busca uma URL (PDF ou página da web) e faz com que um LLM responda a perguntas sobre ela. Detecta automaticamente o tipo de conteúdo. O documento é processado em um contexto separado, mantendo sua conversa principal compacta.

Parâmetros:

  • url (obrigatório) - A URL a ser buscada (PDF ou página da web)
  • ask (obrigatório) - Pergunta ou instrução para o LLM (resumir, extrair informações, responder perguntas, etc.)
  • askMaxInputTokens - Tokens de entrada máximos por chamada do LLM (padrão: 150.000)
  • askMaxOutputTokens - Tokens de saída máximos por chamada do LLM (padrão: 4.096)
  • askTimeout - Tempo limite em milissegundos (padrão: 300.000 = 5 minutos)
  • askSplitAndSynthesize - Para documentos grandes: dividir em partes, processar cada uma e depois sintetizar os resultados (padrão: falso). Aviso: consome muitos tokens.
  • waitMs - Tempo extra para esperar após o carregamento da página para conteúdo dinâmico (apenas páginas da web)
  • timeoutMs - Quanto tempo esperar antes de desistir (padrão: 15 segundos, apenas páginas da web)
  • headless - Defina como false para ver a janela do navegador (apenas páginas da web)

Retorna:

  • url - A URL que foi solicitada
  • contentType - pdf ou html
  • title - O título da página/documento
  • totalChars - Total de caracteres no documento
  • ask - A instrução que foi dada
  • answer - A resposta do LLM
  • model - O modelo que gerou a resposta
  • chunksProcessed - Número de partes processadas (1 para documentos pequenos, mais ao usar askSplitAndSynthesize)
  • fetchedAt - Timestamp ISO

O modo de pergunta usa MCP sampling para que um LLM processe o documento com qualquer instrução. Isso é útil para:

  • Documentos grandes que sobrecarregariam o contexto
  • Manter os custos de token baixos na conversa principal

Quando askSplitAndSynthesize está habilitado, documentos que excedem askMaxInputTokens são automaticamente divididos em partes sobrepostas. Cada parte é processada separadamente e os resultados são sintetizados em uma única resposta coerente. A resposta final é fornecida no mesmo idioma da sua solicitação, independentemente do idioma do documento.

Repositório de documentos

O repositório é uma biblioteca local e pesquisável de documentos. Ele suporta PDFs, arquivos HTML e texto simples (Markdown/TXT). Quando você adiciona um documento, o Research Friend armazena o arquivo original, extrai texto (para PDFs/HTML) e salva metadados em um banco de dados local. As pesquisas usam o ripgrep internamente para correspondência rápida e com reconhecimento de frases.

Localização do repositório

O repositório reside em ~/.research-friend/:

  • inbox/ - Solte arquivos aqui para serem processados
  • store/ - Armazenamento organizado de documentos e texto extraído
  • stash.db - Banco de dados de metadados

Tipos de arquivo suportados

  • PDF: .pdf (texto extraído)
  • HTML: .html, .htm (texto extraído)
  • Markdown: .md, .markdown (armazenado como texto simples)
  • Texto: .txt (armazenado como texto simples)

Ferramentas do repositório

stash_open_inbox

Abre a pasta da caixa de entrada do repositório no seu gerenciador de arquivos para facilitar o arrastar e soltar.

Retorna:

  • opened - Se a solicitação de abertura da pasta foi enviada
  • inboxPath - Caminho absoluto para a caixa de entrada
  • command - Comando do SO usado
  • args - Argumentos do comando usados

stash_process_inbox

Processa arquivos em inbox/, classifica-os em tópicos, extrai texto e armazena os resultados. Para documentos longos, a classificação usa seções amostradas (início/meio/fim mais alguns trechos aleatórios) para melhorar a precisão do tópico.

Retorna:

  • processed - Array de nomes de arquivo processados com sucesso
  • errors - Quaisquer erros encontrados
  • documents - Array de registros de documentos criados

reindex_stash

Regenera resumos, realoca tópicos e atualiza metadados armazenados para documentos no repositório. Se ids for omitido ou vazio, todos os documentos são reindexados.

Parâmetros:

  • ids - IDs de documentos para reindexar (opcional)

Retorna:

  • reindexed - IDs de documentos reindexados
  • errors - Quaisquer erros encontrados
  • documents - Array de registros de documentos atualizados

stash_list

Lista documentos no repositório.

Parâmetros:

  • topic - Filtrar por um tópico (opcional)
  • limit - Máximo de resultados (padrão: 50)
  • offset - Deslocamento de paginação (padrão: 0)

Retorna:

  • type - all ou topic
  • totalDocuments - Total de documentos (somente quando type é all)
  • count - Resultados retornados após a paginação
  • offset - Deslocamento de paginação usado
  • limit - Limite de paginação usado
  • topics - Resumo de tópicos conhecidos e contagens de documentos
  • documents - Lista de documentos com metadados (inclui isPrimary ao listar um tópico)

stash_search

Pesquisa nomes de arquivo e conteúdo em todo o repositório. Todos os termos de pesquisa devem estar presentes (lógica E). Correspondências de nome de arquivo são listadas primeiro. Use aspas para frases exatas.

Parâmetros:

  • query (obrigatório) - Termos de pesquisa. Use aspas para frases: "sparkling wine"
  • topic - Filtrar por um tópico (opcional)
  • ids - Filtrar por IDs de documentos específicos (opcional)
  • limit - Máximo de documentos a retornar (padrão: 20)
  • offset - Deslocamento de paginação (padrão: 0)
  • maxMatchesPerDoc - Máximo de correspondências por documento (padrão: 50)
  • context - Linhas de contexto ao redor de cada correspondência (padrão: 1, máx: 5). Controla tanto quão próximos os termos devem aparecer para corresponder QUANTO quanto texto ao redor é retornado. Retorna:
  • totalMatches - Total de documentos correspondentes antes da paginação
  • count - Resultados retornados após a paginação
  • results - Array de documentos, cada um com:
    • id, filename, fileType, summary, charCount, createdAt
    • matchType - filename, content ou filename+content
    • matches - Array de { line, context } para cada local de correspondência

Use os valores line com stash_extract para pular diretamente para os locais de correspondência.

stash_extract

Extrai conteúdo de um documento armazenado para leitura. Use números de linha dos resultados de stash_search para pular diretamente para as correspondências.

Parâmetros:

  • id (obrigatório) - ID do documento de stash_list/stash_search
  • maxChars - Quantidade máxima de texto a retornar (padrão: 40.000 caracteres)
  • offset - Posição do caractere para iniciar (mutuamente exclusivo com line)
  • line - Número da linha para iniciar (mutuamente exclusivo com offset)

Retorna:

  • id, filename, fileType, summary - Metadados do documento
  • totalChars - Total de caracteres no documento
  • offset - Deslocamento de caractere (incluído ao usar line para referência)
  • line - Número da linha (somente quando o parâmetro line foi usado)
  • content - O conteúdo de texto extraído
  • truncated - Se mais conteúdo permanece após este trecho

stash_ask

Faz com que um LLM responda perguntas sobre um documento armazenado. O documento é processado em um contexto separado, mantendo sua conversa principal compacta.

Parâmetros:

  • id (obrigatório) - ID do documento de stash_list/stash_search
  • ask (obrigatório) - Pergunta ou instrução para o LLM
  • askMaxInputTokens - Tokens de entrada máximos por chamada do LLM (padrão: 150.000)
  • askMaxOutputTokens - Tokens de saída máximos por chamada do LLM (padrão: 4.096)
  • askTimeout - Tempo limite em milissegundos (padrão: 300.000 = 5 minutos)
  • askSplitAndSynthesize - Para documentos grandes: divide em partes, processa cada uma e depois sintetiza os resultados (padrão: false)

Retorna:

  • id, filename, fileType, summary - Metadados do documento
  • totalChars - Total de caracteres no documento
  • ask - A instrução que foi dada
  • answer - A resposta do LLM
  • model - O modelo que gerou a resposta
  • chunksProcessed - Número de partes processadas

Fluxo típico

  1. Solte arquivos em ~/.research-friend/inbox/
  2. Execute stash_process_inbox
  3. Use stash_list para navegar pelos tópicos
  4. Use stash_search para encontrar documentos relevantes
  5. Use stash_extract para ler um documento específico ou stash_ask para fazer perguntas sobre ele

Solução de problemas

"Navegador fechado inesperadamente" ou erros semelhantes

Tente reinstalar o navegador:

npx playwright install chromium --force

No Linux, você também pode precisar de dependências do sistema:

npx playwright install-deps chromium

O servidor não inicia

Certifique-se de estar usando Node.js 20 ou mais recente:

node --version

Se sua versão for mais antiga, visite nodejs.org para baixar uma mais nova.

Licença

MIT