MCP Research Friend Server

公式

研究ツール(Sqliteバックアップのドキュメントストレージを含む)

ドキュメント

Research Friend

AIアシスタントがWeb上の情報を検索し、ローカルのリサーチストックを管理するためのフレンドリーなヘルパーです。

Research Friendは、AIツールにWebページの取得やインターネット検索の機能を提供するMCPサーバーです。内部では実際のWebブラウザを使用するため、JavaScriptに大きく依存する最新のWebサイトでも動作します。また、ドキュメントの保存、テキスト抽出、ライブラリ全体の検索を行うためのローカル「ストック」機能も備えています。

すべての機能を活用するには、プロンプト(一般的)とサンプリング(やや稀)をサポートするMCPクライアントが必要です。Research Friendは、両方をサポートするChabeauと並行して開発を進めています。

機能

  • 実際のブラウザによるWebページの取得(JavaScriptを多用するサイトを含む)
  • PDFの取得とテキストコンテンツの抽出
  • DuckDuckGoまたはGoogleによるWeb検索
  • ドキュメントのローカルストック管理(検索、一覧表示、抽出)

はじめに

コンピュータにNode.jsバージョン20以降がインストールされている必要があります。

1. 依存関係のインストール

このフォルダでターミナルを開き、以下を実行します。

npm install

2. ブラウザサポートのインストール

Research FriendはPlaywrightを使用してWebブラウザを制御します。依存関係のインストール後、ブラウザをインストールする必要があります。

npx playwright install chromium

これにより、Playwrightが使用するChromiumのコピーがダウンロードされます。既存のブラウザとは別にインストールされます。

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 は、コンピュータ上のこのフォルダへの実際のパスに置き換えてください。

ツール

Webツール

friendly_web_fetch

Webページを取得し、そのコンテンツを返します。デフォルトでは、リンクを保持したMarkdown形式で返します(LLMに最適)。 Readabilityを使用してメインコンテンツを抽出します(ナビゲーションや広告などを除去)。PDF、ページネーション、コンテンツ内検索には、代わりに friendly_web_extract を使用してください。

パラメータ:

  • url (必須) - 取得するWebアドレス
  • outputFormat - 出力形式: markdown (デフォルト)、text、または html
  • waitMs - コンテンツの表示が遅い場合に、ページ読み込み後に追加で待機する時間
  • timeoutMs - タイムアウトまでの待機時間(デフォルト: 15秒)
  • maxChars - 返すコンテンツの最大量(デフォルト: 40,000文字)
  • includeHtml - true に設定すると、コンテンツと共に生のHTMLも返します
  • headless - false に設定すると、ブラウザウィンドウを表示します(デバッグに便利)

戻り値:

  • url - リクエストされたURL
  • finalUrl - リダイレクト後のURL
  • title - ページタイトル
  • content - 抽出されたコンテンツ(リクエストされた形式)
  • html - 生のHTML(includeHtml がtrueの場合のみ)
  • meta - ページのメタデータ(説明、作成者、公開日時など)
  • fetchedAt - ページが取得された日時のISOタイムスタンプ
  • truncated - コンテンツが maxChars に収まるように切り詰められたかどうか

friendly_search

Webを検索し、結果のリストを返します。

パラメータ:

  • query (必須) - 検索キーワード
  • engine - 使用する検索エンジン(duckduckgo または google
  • maxResults - 返す結果の数(デフォルト: 10、最大: 50)
  • timeoutMs - タイムアウトまでの待機時間(デフォルト: 15秒)
  • headless - false に設定すると、ブラウザウィンドウを表示します

戻り値:

  • query - 使用された検索クエリ
  • engine - 使用された検索エンジン
  • results - 結果の配列。各結果には titleurlsnippet が含まれます
  • searchedAt - 検索が実行された日時のISOタイムスタンプ
  • fallback_result_html - ページの生のHTML(結果が見つからなかった場合のみ)
  • debug_info - 検索試行に関する診断情報

CAPTCHA処理: ヘッドレスモードで実行中にCAPTCHAが検出されると、ツールは自動的に可視ブラウザウィンドウで再試行します。これにより、手動でCAPTCHAを解決する機会が得られます。debug_info.retried フィールドは、このフォールバックが使用されたかどうかを示します。

friendly_web_extract

URLからコンテンツを抽出します。URLがPDFかWebページかを自動検出し、それぞれ適切に処理します。

パラメータ:

  • url (必須) - 取得するURL(PDFまたはWebページ)
  • maxChars - 返すテキストの最大量(デフォルト: 40,000文字)
  • offset - 開始文字位置(デフォルト: 0)。大きなコンテンツをページ分割するために使用します。
  • search - フレーズを検索し、完全なコンテンツの代わりに周辺コンテキスト付きの一致を返します
  • contextChars - 各検索一致の前後のコンテキスト文字数(デフォルト: 200)
  • waitMs - 動的コンテンツのためのページ読み込み後の追加待機時間(Webページのみ)
  • timeoutMs - タイムアウトまでの待機時間(デフォルト: 15秒、Webページのみ)
  • headless - false に設定すると、ブラウザウィンドウを表示します(Webページのみ)

戻り値(通常モード):

  • url - リクエストされたURL
  • contentType - pdf または html
  • title - ページ/ドキュメントのタイトル
  • author - PDFの作成者(PDFのみ、利用可能な場合)
  • creationDate - PDFの作成日時(PDFのみ、利用可能な場合)
  • pageCount - ページ数(PDFのみ)
  • totalChars - 総文字数(offset と共にページ分割に使用)
  • offset - 使用されたオフセット
  • content - 抽出されたテキストコンテンツ
  • fetchedAt - ISOタイムスタンプ
  • truncated - このチャンクの後にさらにコンテンツが残っているかどうか

戻り値(検索モード):

  • urlcontentTypetitletotalCharsfetchedAt - 上記と同じ
  • search - 使用された検索フレーズ
  • matchCount - 見つかった一致の数
  • matches - 一致の配列。各一致には positioncontextprefixsuffix が含まれます

friendly_web_ask

URL(PDFまたはWebページ)を取得し、LLMにそれに関する質問に回答させます。コンテンツタイプを自動検出します。ドキュメントは別のコンテキストで処理されるため、メインの会話をコンパクトに保てます。

パラメータ:

  • url (必須) - 取得するURL(PDFまたはWebページ)
  • ask (必須) - LLMへの質問または指示(要約、情報抽出、質問への回答など)
  • askMaxInputTokens - LLM呼び出しあたりの最大入力トークン数(デフォルト: 150,000)
  • askMaxOutputTokens - LLM呼び出しあたりの最大出力トークン数(デフォルト: 4,096)
  • askTimeout - タイムアウト(ミリ秒)(デフォルト: 300,000 = 5分)
  • askSplitAndSynthesize - 大きなドキュメントの場合: チャンクに分割し、それぞれを処理して結果を統合します(デフォルト: false)。警告: 多くのトークンを消費します。
  • waitMs - 動的コンテンツのためのページ読み込み後の追加待機時間(Webページのみ)
  • timeoutMs - タイムアウトまでの待機時間(デフォルト: 15秒、Webページのみ)
  • headless - false に設定すると、ブラウザウィンドウを表示します(Webページのみ)

戻り値:

  • 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 - 使用されたOSコマンド
  • args - 使用されたコマンド引数

stash_process_inbox

inbox/ 内のファイルを処理し、トピックに分類し、テキストを抽出し、結果を保存します。 長いドキュメントの場合、分類はサンプリングされたセクション(開始/中間/終了といくつかのランダムなチャンク)を使用して、トピックの精度を向上させます。

戻り値:

  • processed - 正常に処理されたファイル名の配列
  • errors - 発生したエラー
  • documents - 作成されたドキュメントレコードの配列

reindex_stash

ストックされたドキュメントのサマリーを再生成し、トピックを再割り当てし、ストアのメタデータを更新します。ids が省略されるか空の場合、すべてのドキュメントが再インデックスされます。

パラメータ:

  • ids - 再インデックスするドキュメントID(オプション)

戻り値:

  • reindexed - 再インデックスされたドキュメントID
  • errors - 発生したエラー
  • documents - 更新されたドキュメントレコードの配列

stash_list

ストック内のドキュメントを一覧表示します。

パラメータ:

  • topic - トピックでフィルタリング(オプション)
  • limit - 最大結果数(デフォルト: 50)
  • offset - ページネーションオフセット(デフォルト: 0)

戻り値:

  • type - all または topic
  • totalDocuments - 総ドキュメント数(typeall の場合のみ)
  • count - ページネーション後に返された結果
  • offset - 使用されたページネーションオフセット
  • limit - 使用されたページネーション制限
  • topics - 既知のトピックとドキュメント数のサマリー
  • documents - メタデータ付きのドキュメントリスト(トピックを一覧表示する場合、isPrimary を含む)

stash_search

ストック全体でファイル名とコンテンツを検索します。すべての検索語が存在する必要があります(AND論理)。ファイル名の一致が最初にリストされます。正確なフレーズには引用符を使用します。

パラメータ:

  • query (必須) - 検索語。フレーズには引用符を使用します: "sparkling wine"
  • topic - トピックでフィルタリング(オプション)
  • ids - 特定のドキュメントIDでフィルタリング(オプション)
  • limit - 返す最大ドキュメント数(デフォルト: 20)
  • offset - ページネーションオフセット(デフォルト: 0)
  • maxMatchesPerDoc - ドキュメントあたりの最大一致数(デフォルト: 50)
  • context - 各一致の前後のコンテキスト行数(デフォルト: 1、最大: 5)。一致と見なされるために語がどれだけ近くに出現する必要があるか、および返される周辺テキストの量の両方を制御します。 戻り値:
  • totalMatches - ページネーション前の一致ドキュメント総数
  • count - ページネーション後に返された結果
  • results - ドキュメントの配列。各要素は以下を含む:
    • id, filename, fileType, summary, charCount, createdAt
    • matchType - filename, content, または filename+content
    • matches - 各一致箇所の { line, context } の配列

line の値を stash_extract と共に使用して、一致箇所に直接ジャンプします。

stash_extract

スタッシュされたドキュメントからコンテンツを抽出して読み取ります。stash_search の結果の行番号を使用して、一致箇所に直接ジャンプします。

パラメータ:

  • id (必須) - stash_list/stash_search からのドキュメントID
  • maxChars - 返すテキストの最大量 (デフォルト: 40,000文字)
  • offset - 開始文字位置 (line とは排他的)
  • line - 開始行番号 (offset とは排他的)

戻り値:

  • id, filename, fileType, summary - ドキュメントのメタデータ
  • totalChars - ドキュメントの総文字数
  • offset - 文字オフセット (参照に line を使用した場合に含まれる)
  • line - 行番号 (line パラメータが使用された場合のみ)
  • content - 抽出されたテキストコンテンツ
  • truncated - このチャンクの後にさらにコンテンツが残っているかどうか

stash_ask

スタッシュされたドキュメントについてLLMに質問させます。ドキュメントは別のコンテキストで処理されるため、メインの会話をコンパクトに保てます。

パラメータ:

  • id (必須) - stash_list/stash_search からのドキュメントID
  • 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