🚀 MCP Local RAG
このプロジェクトは、プライバシーを重視したドキュメント検索サーバーで、すべてをローカルマシン上で実行します。APIキー不要、クラウドサービス不要、データを外部に送信する必要もありません。
Model Context Protocol (MCP) 用に構築されており、Cursor、Codex、Claude Code または任意の MCP クライアントを使用して、セマンティック検索でローカルドキュメントを検索できます。外部サービスに何も送信することなく、ドキュメントを検索できます。
🚀 クイックスタート
MCPサーバーをAIコーディングツールに追加します。以下からツールを選択してください。
Cursorの場合 - ~/.cursor/mcp.jsonに追加します。
{
"mcpServers": {
"local-rag": {
"command": "npx",
"args": ["-y", "mcp-local-rag"],
"env": {
"BASE_DIR": "/path/to/your/documents"
}
}
}
}
Codexの場合 - ~/.codex/config.tomlに追加します。
[mcp_servers.local-rag]
command = "npx"
args = ["-y", "mcp-local-rag"]
[mcp_servers.local-rag.env]
BASE_DIR = "/path/to/your/documents"
Claude Codeの場合 - このコマンドを実行します。
claude mcp add local-rag --scope user --env BASE_DIR=/path/to/your/documents -- npx -y mcp-local-rag
ツールを再起動してから、以下のように使用を開始します。
"Ingest api-spec.pdf"
"What does this document say about authentication?"
以上です。インストール不要、Docker不要、複雑なセットアップも不要です。
✨ 主な機能
なぜこのプロジェクトが存在するのか
AIを使ってドキュメントを検索したい場合、技術仕様書、研究論文、社内ドキュメント、会議ノートなど様々なドキュメントが対象になります。しかし、ほとんどのソリューションでは、ファイルを外部APIに送信する必要があり、以下の3つの問題が発生します。
- プライバシーの懸念:ドキュメントにはクライアントデータ、独自の研究成果、個人的なメモなどの機密情報が含まれる可能性があり、これを第三者サービスに送信することは、そのデータを信頼することになります。
- 大規模でのコスト:外部の埋め込みAPIは使用するたびに課金されます。大量のドキュメントセットや頻繁な検索では、コストがすぐに増えていきます。
- ネットワーク依存性:オフラインまたは接続が制限されている場合、自分のドキュメントを検索できません。
このプロジェクトは、すべてをローカルで実行することでこれらの問題を解決します。ドキュメントは決してマシンを離れません。埋め込みモデルは一度ダウンロードすれば、オフラインでも動作します。そして、無料で自由に使用できます。
得られる機能
サーバーはMCPを通じて5つのツールを提供します。
- ドキュメント取り込み:PDF、DOCX、TXT、Markdownファイルを扱います。ファイルを指定すると、テキストを抽出し、検索可能なチャンクに分割し、ローカルモデルを使用して埋め込みを生成し、すべてをローカルのベクターデータベースに保存します。同じファイルを再度取り込むと、古いバージョンが置き換えられ、重複データは発生しません。
- セマンティック検索:自然言語でクエリを行うことができます。キーワードマッチングではなく、意味を理解します。「認証はどのように機能するか」と尋ねると、「ログインフロー」や「資格情報検証」など異なる単語を使用している関連セクションも見つけます。
- ファイル管理:取り込んだファイルとその取り込み日時を表示します。各ファイルが生成したチャンク数を確認でき、すべてが正しくインデックス付けされていることを検証できます。
- ファイル削除:取り込んだドキュメントをベクターデータベースから削除します。ファイルを削除すると、そのすべてのチャンクと埋め込みが永久に削除されます。これは、古いドキュメントやインデックス化したくない機密データを削除するのに便利です。
- システムステータス:データベースの情報(ドキュメント数、総チャンク数、メモリ使用量)を報告します。パフォーマンスの監視や問題のデバッグに役立ちます。
これらすべては以下を使用しています。
- LanceDB:ベクターストレージ用(ファイルベース、サーバー不要)
- Transformers.js:埋め込み生成用(Node.jsで動作、Python不要)
- all-MiniLM-L6-v2 モデル(384次元、速度と精度のバランスが良い)
- RecursiveCharacterTextSplitter:インテリジェントなテキストチャンク分割用
その結果、標準的なラップトップでは、数千のドキュメントチャンクがインデックス付けされている場合でも、クエリ応答は通常3秒以内になります。
📦 インストール
初回実行時の注意事項
サーバーはすぐに起動しますが、埋め込みモデルは初回使用時(初めて取り込みまたは検索するとき)にダウンロードされます。
- ダウンロードサイズ:約90MB(モデルファイル)
- キャッシュ後のディスク使用量:約120MB(ONNXランタイムキャッシュを含む)
- 時間:適度な接続環境で1 - 2分
- 初回操作の遅延:最初の取り込みまたは検索要求は、モデルのダウンロードが完了するまで待機します。
コンソールには「Initializing model (downloading ~90MB, may take 1-2 minutes)...」のようなメッセージが表示されます。モデルはCACHE_DIR(デフォルト: ./models/)にキャッシュされ、オフラインでも使用できます。
遅延初期化の理由:このアプローチにより、サーバーは事前のモデルロードなしですぐに起動できます。実際に必要なときにのみダウンロードするため、サーバーは迅速なステータスチェックやファイル管理操作に対してより応答性が高くなります。
オフラインモード:初回ダウンロード後は、完全にオフラインで動作します。インターネット接続は不要です。
セキュリティ
- パス制限:このサーバーは
BASE_DIR内のファイルのみにアクセスします。このディレクトリ外のファイルへのアクセス試み(例えば、../ パストラバーサル)は拒否されます。
- ローカル限定:すべての処理はマシン上で行われます。初回のモデルダウンロード後は、ネットワーク要求は行われません。
- モデル検証:埋め込みモデルはHuggingFaceの公式リポジトリ (
Xenova/all-MiniLM-L6-v2) からダウンロードされます。公式モデルカードを確認して整合性を検証してください。
設定
サーバーはデフォルト設定ですぐに使用できますが、環境変数を通じてカスタマイズすることもできます。
Codexの場合
~/.codex/config.tomlに追加します。
[mcp_servers.local-rag]
command = "npx"
args = ["-y", "mcp-local-rag"]
[mcp_servers.local-rag.env]
BASE_DIR = "/path/to/your/documents"
DB_PATH = "./lancedb"
CACHE_DIR = "./models"
注意:セクション名はmcp_servers(アンダースコア付き)でなければなりません。mcp-servers や mcpservers を使用すると、Codexは設定を無視します。
Cursorの場合
Cursorの設定に追加します。
- グローバル(すべてのプロジェクト):
~/.cursor/mcp.json
- プロジェクト固有:プロジェクトルートの
.cursor/mcp.json
{
"mcpServers": {
"local-rag": {
"command": "npx",
"args": ["-y", "mcp-local-rag"],
"env": {
"BASE_DIR": "/path/to/your/documents",
"DB_PATH": "./lancedb",
"CACHE_DIR": "./models"
}
}
}
}
Claude Codeの場合
プロジェクトディレクトリで実行して、そのプロジェクトで有効にします。
cd /path/to/your/project
claude mcp add local-rag --env BASE_DIR=/path/to/your/documents -- npx -y mcp-local-rag
または、すべてのプロジェクトにグローバルに追加します。
claude mcp add local-rag --scope user --env BASE_DIR=/path/to/your/documents -- npx -y mcp-local-rag
追加の環境変数を指定する場合
claude mcp add local-rag --scope user \
--env BASE_DIR=/path/to/your/documents \
--env DB_PATH=./lancedb \
--env CACHE_DIR=./models \
-- npx -y mcp-local-rag
環境変数
| 変数 |
デフォルト |
説明 |
有効範囲 |
BASE_DIR |
カレントディレクトリ |
ドキュメントのルートディレクトリ。サーバーはこのパス内のファイルのみにアクセスします(誤ったシステムファイルアクセスを防止)。 |
有効なパス |
DB_PATH |
./lancedb/ |
ベクターデータベースの保存場所。大量のドキュメントでは大きくなる可能性があります。 |
有効なパス |
CACHE_DIR |
./models/ |
モデルのキャッシュディレクトリ。初回ダウンロード後、モデルはここに保存され、オフラインでも使用できます。 |
有効なパス |
MODEL_NAME |
Xenova/all-MiniLM-L6-v2 |
HuggingFaceのモデル識別子。Transformers.js互換でなければなりません。利用可能なモデルを参照してください。注意:モデルを変更すると、異なるモデルの埋め込みは互換性がないため、すべてのドキュメントを再取り込みする必要があります。 |
HFモデルID |
MAX_FILE_SIZE |
104857600 (100MB) |
バイト単位の最大ファイルサイズ。メモリ問題を防止するため、大きいファイルは拒否されます。 |
1MB - 500MB |
CHUNK_SIZE |
512 |
チャンクあたりの文字数。大きいほど文脈が多くなりますが、処理が遅くなります。 |
128 - 2048 |
CHUNK_OVERLAP |
100 |
チャンク間の重複部分。境界を超えた文脈を保持します。 |
0 - (CHUNK_SIZE/2) |
💻 使用例
設定後の手順
設定後、MCPクライアントを再起動します。
- Cursor:完全に終了して再起動します(MacではCmd+Q、ウィンドウを閉じるだけでは不十分です)
- Codex:IDE/拡張機能を再起動します
- Claude Code:再起動不要 - 変更はすぐに適用されます
サーバーは、AIアシスタントが使用できる利用可能なツールとして表示されます。
ドキュメントの取り込み
- Cursorでは、Composer Agentが必要に応じて自動的にMCPツールを使用します。
"Ingest the document at /Users/me/docs/api-spec.pdf"
- Codex CLIでは、アシスタントが必要に応じて自動的に構成されたMCPツールを使用します。
codex "Ingest the document at /Users/me/docs/api-spec.pdf into the RAG system"
- Claude Codeでは、自然に尋ねるだけです。
"Ingest the document at /Users/me/docs/api-spec.pdf"
パスの要件:サーバーはファイルへの絶対パスを必要とします。AIアシスタントは通常、自然言語の要求を自動的に絶対パスに変換します。セキュリティ上の理由で、BASE_DIR設定によりそのディレクトリツリー内のファイルのみにアクセスが制限されますが、依然として完全なパスを提供する必要があります。
サーバーは以下の手順を実行します。
- ファイルが存在し、100MB未満であることを検証します。
- テキストを抽出します(PDF/DOCX/TXT/MD形式を扱います)。
- チャンクに分割します(512文字、100文字の重複)。
- 各チャンクの埋め込みを生成します。
- ベクターデータベースに保存します。
標準的なラップトップでは、1MBあたり約5 - 10秒かかります。完了すると、生成されたチャンク数を含む確認メッセージが表示されます。
ドキュメントの検索
自然言語で質問を行います。
"What does the API documentation say about authentication?"
"Find information about rate limiting"
"Search for error handling best practices"
サーバーは以下の手順を実行します。
- クエリを埋め込みベクターに変換します。
- ベクターデータベースを検索して、類似するチャンクを見つけます。
- 類似度スコア付きの上位5件のマッチを返します。
結果には、テキスト内容、ファイルの出所、関連性スコアが含まれます。AIアシスタントはこれらの結果を使用して質問に回答します。
より多くの結果を要求することもできます。
"Search for database optimization tips, return 10 results"
制限パラメータは1 - 20件の結果を受け付けます。
ファイルの管理
インデックス付けされているファイルを確認します。
"List all ingested files"
これにより、各ファイルのパス、生成されたチャンク数、取り込み日時が表示されます。
データベースからファイルを削除します。
"Delete /Users/me/docs/old-spec.pdf from the RAG system"
これにより、ファイルとそのすべてのチャンクがベクターデータベースから永久に削除されます。この操作は冪等性があり、存在しないファイルを削除してもエラーなく成功します。
システムステータスを確認します。
"Show the RAG server status"
これにより、総ドキュメント数、総チャンク数、現在のメモリ使用量、稼働時間が報告されます。
ファイルの再取り込み
ドキュメントを更新した場合は、再度取り込みます。
"Re-ingest api-spec.pdf with the latest changes"
サーバーは、新しいチャンクを追加する前に、そのファイルの古いチャンクを自動的に削除します。重複や古いデータは発生しません。
📚 ドキュメント
開発
ソースからのビルド
git clone https://github.com/shinpr/mcp-local-rag.git
cd mcp-local-rag
npm install
テストの実行
npm test
npm run test:coverage
npm run test:watch
テストスイートには以下が含まれます。
- 各コンポーネントの単体テスト
- 完全な取り込みと検索フローの統合テスト
- パストラバーサル保護のセキュリティテスト
- クエリ速度目標を検証するパフォーマンステスト
コード品質
npm run type-check
npm run check:fix
npm run check:deps
npm run check:all
プロジェクト構造
src/
index.ts # エントリポイント、MCPサーバーを起動
server/ # RAGServerクラス、MCPツールハンドラー
parser/ # ドキュメント解析(PDF、DOCX、TXT、MD)
chunker/ # テキスト分割ロジック
embedder/ # Transformers.jsを使用した埋め込み生成
vectordb/ # LanceDB操作
__tests__/ # テストスイート
各モジュールには明確な境界があります。
- Parser:ファイルパスを検証し、テキストを抽出します。
- Chunker:テキストを重複するセグメントに分割します。
- Embedder:384次元のベクターを生成します。
- VectorStore:すべてのデータベース操作を処理します。
- RAGServer:すべてを調整し、MCPツールを公開します。
パフォーマンス
- テスト環境:MacBook Pro M1(16GB RAM)、Node.js 22(2025年1月)でv0.1.3を使用してテスト
- クエリパフォーマンス
- 平均:10,000個のインデックス付きチャンクで1.2秒(5件の結果)
- 目標:p90 < 3秒 ✓
- 取り込み速度(10MBのPDF)
- 合計:約45秒
- PDF解析:約8秒(17%)
- テキストチャンク分割:約2秒(4%)
- 埋め込み生成:約30秒(67%)
- データベース挿入:約5秒(11%)
- メモリ使用量
- ベースライン:アイドル時約200MB
- ピーク:50MBのファイルを取り込むとき約800MB
- 目標:< 1GB ✓
- 同時クエリ:5つの並列クエリを性能低下なく処理します。LanceDBの非同期APIにより、非ブロッキング操作が可能です。
注意:結果はハードウェアによって異なります。特にCPU速度(埋め込みはGPUではなくCPUで実行されます)に依存します。
トラブルシューティング
"No results found" エラー
原因:検索する前にドキュメントを取り込む必要があります。
解決策:
- まずドキュメントを取り込みます。
"Ingest /path/to/document.pdf"
- 取り込みを確認します。
"List all ingested files"
- その後、検索します。
"Search for [your query]"
よくある間違い:設定後すぐにドキュメントを取り込まずに検索しようとすること。
"Model download failed" エラー
埋め込みモデルは初回使用時(初めて取り込みまたは検索するとき)にHuggingFaceからダウンロードされます。プロキシまたはファイアウォールの背後にいる場合は、ネットワーク設定を構成する必要があるかもしれません。
発生時:最初の取り込みまたは検索操作でダウンロードがトリガーされます。失敗すると、トラブルシューティングガイダンス付きの詳細なエラーメッセージが表示されます(ネットワーク問題、ディスク容量、キャッシュ破損)。
対処法:エラーメッセージに具体的な推奨事項が記載されています。一般的な解決策は以下の通りです。
- インターネット接続を確認し、操作を再試行します。
- 十分なディスク容量があることを確認します(約120MB必要)。
- 問題が解決しない場合は、キャッシュディレクトリを削除して再度試してみます。
または、手動でモデルをダウンロードすることもできます。
- https://huggingface.co/Xenova/all-MiniLM-L6-v2にアクセスします。
- モデルファイルをダウンロードします。
CACHE_DIRを保存した場所に設定します。
"File too large" エラー
デフォルトの制限は100MBです。より大きいファイルの場合は、以下の対策があります。
- ファイルを小さなドキュメントに分割します。
- または、設定で
MAX_FILE_SIZEを増やします(メモリ使用量に注意してください)。
クエリパフォーマンスが遅い場合
クエリが予想よりも時間がかかる場合は、以下を確認してください。
- インデックス付けされているチャンク数を確認します(
statusコマンド)。
- ハードウェアを考慮します(埋め込みはCPUに負荷がかかります)。
CHUNK_SIZEを減らして、チャンク数を減らすことを試してみます。
"Path outside BASE_DIR" エラー
サーバーはセキュリティ上の理由で、ファイルアクセスをBASE_DIRに制限しています。ファイルパスがそのディレクトリ内にあることを確認してください。以下をチェックします。
- MCP設定で正しい
BASE_DIR設定がされていること。
- 相対パスと絶対パスの違い。
- ファイルパスのタイポ。
MCPクライアントがツールを認識しない場合
Cursorの場合
- 設定 → 機能 → Model Context Protocolを開きます。
- サーバー設定が保存されていることを確認します。
- Cursorを完全に再起動します。
- ステータスバーのMCP接続ステータスを確認します。
Codex CLIの場合
~/.codex/config.tomlを確認して、設定を検証します。
- セクション名が
[mcp_servers.local-rag](アンダースコア付き)であることを確認します。
- サーバーを直接テストします。
npx mcp-local-ragがエラーなく実行されることを確認します。
- Codex CLIまたはIDE拡張機能を再起動します。
- Codex起動時のエラーメッセージを確認します。
Claude Codeの場合
claude mcp listを実行して、構成されたサーバーを確認します。
- サーバーがリストに表示されていることを確認します。
~/.config/claude/mcp_config.jsonの構文エラーを確認します。
- サーバーを直接テストします。
npx mcp-local-ragがエラーなく実行されることを確認します。
よくある問題:
- 設定ファイルの無効なJSON構文。
BASE_DIR設定の誤ったファイルパス。
- サーバーバイナリが見つからない場合(グローバルインストールを試してみてください:
npm install -g mcp-local-rag)。
- ファイアウォールによるローカル通信のブロック。
仕組み
ドキュメントを取り込むと、パーサーがファイルタイプに基づいてテキストを抽出します。PDFはpdf-parseを使用し、DOCXはmammothを使用し、テキストファイルは直接読み取られます。
チャンカーは、LangChainのRecursiveCharacterTextSplitterを使用してテキストを分割します。自然な境界(段落、文)で分割しようとし、チャンクを約512文字に保ちます。隣接するチャンクは100文字重複して、文脈を保持します。
各チャンクはTransformers.js埋め込みモデルを通り、テキストがその意味を表す384次元のベクターに変換されます。効率化のため、一度に8つのチャンクをバッチ処理します。
ベクターはLanceDBに保存されます。これはローカルファイルで動作する列指向のベクターデータベースです。サーバープロセスや複雑なセットアップは不要で、データファイルが入ったディレクトリだけです。
検索するときは、同じモデルを使用してクエリがベクターに変換されます。LanceDBは、クエリベクターに最も類似したベクターを持つチャンクを見つけ(コサイン類似度を使用)、上位のマッチが元のテキストとメタデータとともにMCPクライアントに返されます。
このアプローチの良いところは、意味的に類似したテキストは、単語が異なっていても類似したベクターを持つことです。「認証プロセス」と「ユーザーがログインする方法」は、キーワード検索とは異なり、互いにマッチします。
よくある質問
-
本当にプライベートですか?
はい。初回のモデルダウンロード後は、何もマシンを離れません。ネットワーク監視ツールで確認すると、取り込みまたは検索中に外部への要求は行われていないことがわかります。
-
オフラインで使用できますか?
はい、モデルがキャッシュされた後は使用できます。初回実行時はインターネットでモデルをダウンロードする必要があります(約90MB)が、その後はすべてオフラインで動作します。
-
これはクラウドRAGサービスとどう違いますか?
クラウドサービス(OpenAI、Pineconeなど)は通常、より高い精度と拡張性を提供します。しかし、ドキュメントを外部に送信する必要があり、継続的なコストとインターネット接続が必要です。このプロジェクトは、完全なプライバシーとゼロランタイムコストを得るために、一部の精度を犠牲にしています。
-
どのファイル形式がサポートされていますか?
現在サポートされている形式は以下の通りです。
- PDF:
.pdf(pdf-parseを使用)
- Microsoft Word:
.docx(mammothを使用、.docはサポートされていません)
- プレーンテキスト:
.txt
- Markdown:
.md, .markdown
まだサポートされていない形式:
- Excel/CSV(
.xlsx, .csv)
- PowerPoint(
.pptx)
- OCR付き画像(
.jpg, .png)
- HTML(
.html)
- 古いWordドキュメント(
.doc)
他の形式のサポートが必要な場合は、問題を作成して、ユースケースを記載してください。
-
埋め込みモデルをカスタマイズできますか?
はい、MODEL_NAMEをHuggingFaceのTransformers.js互換モデルに設定することができます。ただし、異なるモデルは異なるベクター次元を持つため、切り替える場合はデータベースを再構築する必要があります。
-
精度はモデルにどれだけ依存しますか?
all-MiniLM-L6-v2は英語用に最適化されており、技術ドキュメントで良好な性能を発揮します。他の言語の場合は、multilingual-e5-smallなどの多言語モデルを検討してください。より高い精度を求める場合は、より大きなモデルを試してみてくださいが、処理速度が遅くなることが予想されます。
-
GPUアクセラレーションはできますか?
Transformers.jsはデフォルトでCPUで実行されます。GPUサポートは実験的で、プラットフォームによって異なります。ほとんどのユースケースでは、CPUのパフォーマンスで十分です(GPUなしでも埋め込みはかなり高速です)。
-
複数の人がデータベースを共有できますか?
現在の設計は単一ユーザーのローカルアクセスを想定しています。多ユーザーシナリオでは、認証とアクセス制御を実装する必要がありますが、これはこのプロジェクトのプライバシー重視の設計の範囲外です。
-
データをバックアップするにはどうすればいいですか?
DB_PATHディレクトリ(デフォルト: ./lancedb/)をコピーします。これがベクターデータベース全体です。元のドキュメントについては、BASE_DIRをコピーします。どちらも単なるファイルなので、特別なエクスポートは必要ありません。
📄 ライセンス
このプロジェクトはMITライセンスの下で公開されています。詳細はLICENSEファイルを参照してください。個人および商用利用に無料です。帰属表示は必要ありませんが、歓迎されます。
謝辞
このプロジェクトは以下の技術を使用して構築されています。
このプロジェクトは、プライバシーを損なうことなくAIによるドキュメント検索を望む開発者のための実用的なツールとして作成されました。