vault-index について
vault-indexは、Markdownのノートやコードをローカルで検索するハイブリッド検索MCPサーバーです。長期資料を手元で探したいユーザー向けに、キーワード検索とベクトル検索を組み合わせ、結果を再ランキングします。
主な機能
- 01FTS5のキーワード検索とベクトル検索
- 02クロスエンコーダーによる再ランキング
- 03見出し単位で分割しパスを返却
- 04Markdownソースの増分インデックス
- 05除外ルールによるフォルダー除外
活用シーン
- 01ノートと異なる表現の質問への回答検索
- 02ローカルのプロジェクト文書や決定記録の検索
- 03Claude Codeへの長期ノート検索機能の提供
- 04コマンドラインでの資料のインデックス作成と検索
MCP 対応
MCPサーバーとして、index_paths、search_notes、get_note、list_sources、remove_sourceをクライアントに公開します。stdioで接続し、ノートソースの登録と内容の検索に対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx vault-indexVAULT_INDEX_DBPath to the SQLite index file (default ~/.mcp-memory/vault-index.db)VAULT_RERANKSet to 0 to turn off the cross-encoder rerank of the top 10 resultsVAULT_MODEL_CACHEEmbedding model cache folder (default ~/.mcp-memory/models)ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
5掲載時のツール一覧 · 1 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| paths | any | いいえ | |
| reindex | boolean | いいえ |
詳細
claude-second-brain
Claude Code 用のローカルでプライベートな長期記憶です。Markdown のノートが記録として残ります。Claude はハイブリッドなキーワード+ベクトルインデックスを使ってノートを検索し、決定事項や学びをプレーンなファイルとして書き戻します。また、フックがインデックス、ナレッジグラフ、長時間のセッションを管理します。
すべてお使いのマシン上で動作します。SQLite ファイル 1 つ、小規模な CPU モデル 2 つを使い、クラウドサービスは不要です。

サンプルの保管庫を含む v0.1.0 の新規クローンから実際の出力を再生したものです(当時の評価には 32 個の質問がありました)。追加したのは入力アニメーションのみです。
概要
Claude Code はセッションをまたぐとすべてを忘れてしまいます。一般的な対処法は、毎回のターンでコストがかかる巨大な CLAUDE.md を使うか、誰も読んだり修正したりできないベクトルストアを使うことです。このプロジェクトは別の方法を採用しています。
- ファイルが正本です。 ノート、決定記録、学びは、読んだり編集したりバージョン管理したりできる Markdown です。インデックスとグラフはいつでもファイルから再構築できます。
- 推測する前に検索します。 Claude は過去の作業について回答する前に保管庫を検索するよう指示されており、言い換えられた回答も実際に見つけられるツールを利用できます。
- 感覚ではなく測定します。 検索を変更するたびに正解データセットで評価し、ベースラインを上回った場合のみ採用します。失敗した実験も記録しています。
- 自己チェック機能があります。 セッション開始時に不変条件を検証し、各パイプラインが引き続き利用側に到達できることを確認するため、問題が発生してもその日のうちに検出できます。
動作の仕組み
flowchart LR
subgraph files["Markdown files: the record"]
notes["notes/"]
adr["docs/adr/"]
lessons["docs/lessons.md"]
handoffs["docs/handoffs/"]
end
cc["Claude Code"]
vi["vault-index MCP server<br/>mcp/server.py"]
db[("vault-index.db<br/>FTS5 + sqlite-vec")]
mem["memory MCP server"]
kg[("memory.jsonl<br/>entities and relations")]
cc -- "Write / Edit" --> files
cc -- "PostToolUse hook<br/>reindex_hook.py" --> db
cc -- "search_notes, get_note" --> vi
vi --> db
files -- "index_paths" --> db
cc -- "search_nodes" --> mem
mem --> kg
kg -. "each fact names its source file" .-> files
| フック | スクリプト | 動作 |
|---|---|---|
| SessionStart | scripts/invariants.py --hook | 10 項目をチェックします:MCP サーバーが起動可能、グラフのソースが存在、インデックスが最新、フックが接続済み、正解ラベルが有効、学びが適切な形式、コンテキスト予算。 |
| PostToolUse (Write, Edit) | mcp/reindex_hook.py | 編集されたファイルが登録済みソースの配下にある場合、再インデックスします。処理をブロックすることはありません。 |
| UserPromptSubmit | scripts/context_guard.py | トランスクリプトから実際のコンテキストサイズを読み取ります。45 万トークンまでは何もせず、それを超えると /handoff を要求します。新しいセッションを始めるためのメモとカードを作成します(.claude/handoff.json)。 |
| PreCompact | scripts/precompact_snapshot.py | 圧縮前のフォールバックとして、直近のリクエストと変更されたファイルを docs/handoffs/auto/ に保存します。 |
検索
flowchart LR
q["query"] --> sw["drop stopwords"] --> fts["FTS5 bm25<br/>top 4 x limit"]
q --> emb["embed with<br/>bge-small-en-v1.5"] --> vec["sqlite-vec kNN<br/>top 4 x limit"]
fts --> rrf["reciprocal rank fusion<br/>k = 60, keyword weight 0.1"]
vec --> rrf
rrf --> rr["cross-encoder rerank<br/>top 10, MiniLM-L6"]
rr --> out["top chunks with<br/>file path and heading path"]
- Markdown は見出しごと(約 1,200 文字まで)に分割されるため、各ヒットには
Recipe box data model > Unitsのようなパスが含まれます。 - インデックス作成は差分更新です。変更のないファイルは更新時刻とコンテンツハッシュを使ってスキップされ、削除されたファイルは次回の同期時に除外されます。
- キーワードの順位の重みはベクトルの順位の 10 分の 1 です。同順位を解消し、意味の順位を覆すことなく、正確な用語(ID、ツール名)の順位を上げます。
- 小規模なクロスエンコーダー(
ms-marco-MiniLM-L-6-v2、80 MB)が、クエリとチャンクをまとめて読み取り、上位 10 件を並べ替えます。CPU では検索 1 回あたり約 200 ms かかります。VAULT_RERANK=0で無効にできます。 - フォルダーごとの
.indexignoreを使って、ツールのコードが検索結果に含まれないようにできます。
MCP ツール:index_paths、search_notes、get_note、list_sources、remove_source。
コマンド
| コマンド | 内容 |
|---|---|
/recall <topic> | ノート、教訓、グラフをまとめて検索し、クリック可能なソースを添えて回答します。読み取り専用です。 |
/adr <title> | 判断記録を docs/adr/ に書き込み、グラフにリンクします。 |
/learn <what happened> | 教訓をテスト可能な指示として記録します(scripts/learn.py)。内容は、教訓、原因、検出方法です。削除せず、置き換えるか廃止してください。 |
/ingest <path> | ファイルまたはフォルダーをインデックス化し、長期的に保持するエンティティをグラフに追加します。 |
/handoff [topic] | 引き継ぎメモを書き込み、そのメモから新しいセッションを開始します。 |
クイックスタート
uv(Python 3.10〜3.13 を取得します)、メモリーサーバー用の Node.js、Claude Code が必要です。
git clone https://github.com/GitGudatCodeing/claude-second-brain.git
cd claude-second-brain
uv run --project mcp python scripts/setup.py
setup.py は .mcp.json を書き込み(--memory-file を指定しない場合、メモリーグラフは ~/.mcp-memory/memory.jsonl に保存されます)、フォルダーをインデックス化して、不変条件を実行します。その後、フォルダー内で claude を起動し、プロジェクトの MCP サーバーとフックを承認して、/recall garden sensor battery life を試してください。python scripts/invariants.py を実行すれば、いつでも設定を確認できます。
独自のノートは notes/ に保存します。評価が不要になったら example-vault/ を削除し、独自のノートに関する質問で eval/golden.jsonl を更新してください。
Windows では、Claude Code は Git Bash 経由でフックを実行します。フックのコマンドではすでにスラッシュを使用しています。
検索サーバーのみ
vault-index は PyPI と MCP registry で公開されています。このリポジトリの他の部分を使わずに、任意のノートフォルダーでハイブリッド検索を使うには、次のようにします。
claude mcp add vault-index -- uvx --python 3.12 vault-index
続いて、Claude にフォルダーのインデックス化(例:「index_paths ~/notes」)を依頼し、search_notes で検索します。
ターミナルからも利用できます。大きなボルトを先にインデックス化すると、進行状況が表示され、Claude の最初のツール呼び出しが短くなります。
uvx --python 3.12 vault-index index ~/notes # no paths re-syncs every source
uvx --python 3.12 vault-index search "your question" -n 5
uvx --python 3.12 vault-index sources
uvx --python 3.12 vault-index --help
コマンドを指定しない場合、stdio 経由で MCP を提供します。インデックスは ~/.mcp-memory/vault-index.db に保存されます。保存先を変更するには、MCP 設定だけでなく、シェル環境で VAULT_INDEX_DB を設定してください。そうすれば、サーバー、再インデックス化フック、不変条件のすべてが同じファイルを使用します。埋め込みランタイムがまだサポートしていない新しい Python が uvx で使われないようにするには、--python 3.12 を指定します。
検索評価
example-vault/ は、ある人物のノート、判断、教訓を創作したものです。eval/golden.jsonl には、この人物とこのリポジトリのドキュメントに関する44件の質問が含まれています。ノートの表現とは意図的に異なる言い回しにしているため、キーワードの一致だけではほとんどの回答を見つけられません。最後の12件は、回答と共通する単語がほとんどない難しい言い換えです。(README のようにインデックス化されたファイルに正解付きの質問を入れないでください。実際の回答と競合するためです。)
VAULT_INDEX_DB=/tmp/csb-eval.db uv run --project mcp python eval/run_eval.py --modes all -v
| モード | NDCG@5 | MRR | Recall@5 |
|---|---|---|---|
ハイブリッド+再ランキング(search_notes が提供する方式) | 0.747 | 0.797 | 0.780 |
| ハイブリッド、融合のみ(再ランキングなし) | 0.686 | 0.724 | 0.758 |
| キーワードのみ(FTS5) | 0.491 | 0.544 | 0.576 |
| ベクトルのみ | 0.697 | 0.729 | 0.758 |
| 素朴な grep、インデックスなし(ベースライン) | 0.305 | 0.341 | 0.375 |
grep の行では、クエリ内の単語をいくつ含むかに基づいてチャンクを順位付けしています。これは、おおむね単語ごとに rg で検索した場合に相当します。
再ランキングなしでは、サンプルのボルトでベクトルのみの方式が融合方式をわずかに上回りました(難しい言い換えでは、キーワードが一致対象を持たないためです)。再ランキングを加えると、ハイブリッド方式が再び首位になります。作者のプライベートなボルト(41件の質問)でも順位は同じです。ハイブリッド+再ランキングは0.550、融合のみは0.487、ベクトルは0.473、キーワードは0.433、grep は0.327です。
basic-memory との比較
basic-memory は、独自のハイブリッド検索を備えた人気の Markdown メモリ MCP サーバーです。eval/compare_basic_memory.py では、同じ Markdown ファイルのコピーを使って(v0.24.1、同じ bge-small モデル)、同じ44問で両方を実行し、スコアを比較します。basic-memory はノート全体を返すため、ここでは両方ともファイル単位でスコアを計算しています(vault-index のチャンクは元のファイル単位に統合しています)。
| システム(ファイル単位) | NDCG@5 | MRR | Recall@5 |
|---|---|---|---|
| vault-index ハイブリッド検索+再ランキング | 0.829 | 0.858 | 0.886 |
| basic-memory、デフォルト検索 | 0.619 | 0.611 | 0.750 |
| basic-memory、ベクトルのみ | 0.708 | 0.736 | 0.814 |
basic-memory は検索以外にも、ノートの作成、ノートからのグラフ構築、クラウド同期など、多くの機能を提供します。この比較では検索のみを評価しています。デフォルト検索の結果は、実行ごとに約0.005変動しました。CIでは実行されません。
ハイブリッド検索のいずれかの指標が eval/baseline.json を0.03より大きく下回ると、CIは失敗します。UbuntuとWindowsではスコアは同一です。
効果があった変更と効果がなかった変更
各変更を個別に保存済みのベースラインと比較してテストしました。大半は作者のプライベートな保管庫でのテストです。
| 変更 | NDCG@5への影響 | 採用 |
|---|---|---|
| 上位10件のクロスエンコーダーによる再ランキング(MiniLM-L6、80 MB) | サンプル +0.061、プライベート +0.063 | はい:検索あたり約200 ms |
| より大きな再ランキングモデル(MiniLM-L12、Jina v1 tiny/turbo、bge-reranker-base) | まちまち:サンプルセットでスコアが下がるものもありました | いいえ |
| 融合時のキーワード重みを0.1に設定(以前は1.0) | プライベート +0.037、サンプル +0.066 | はい |
ツールコードを除外(.indexignore) | +0.063 | はい |
| FTSクエリからストップワードを削除 | +0.018 | はい |
| bge-smallの代わりにall-MiniLM-L6-v2を使用 | -0.024 | いいえ |
| bm25で見出しの重みを上げる(x2~x10) | -0.015~-0.036 | いいえ |
| bge-base+クエリプレフィックス(768 dims) | +0.030、約1問分 | いいえ:ノイズ程度の改善にモデルが3倍 |
重みを同じにすると、サンプルの保管庫ではベクトルのみの検索がハイブリッド検索を上回り、プライベートな保管庫ではハイブリッド検索が上回りました(専門用語にはキーワードが必要です)。両方のセットで勝る設定を見つけるため、RRF kごとにキーワードの重みを変えて検証しました。プライベートな保管庫ではベクトルのみの検索のほうが依然として劣るため、キーワード検索は低い重みで引き続き使用します。詳細は docs/adr/ を参照してください。
リポジトリの構成
mcp/ vault-index MCP server and re-index hook
scripts/ invariants, learn.py, context guard, pre-compact snapshot
eval/ golden set, baseline, run_eval.py, compare_basic_memory.py
tests/ pytest suite (fake embedder, no model download)
example-vault/ fictional sample notes for the eval
docs/adr/ decision records for this system
docs/lessons.md lessons learned while building it
.claude/ slash commands, hook settings, handoff thresholds
開発
uv run --project mcp --with pytest pytest tests -q
uvx ruff check .
テストでは偽のbag-of-wordsエンベッダーを使うため、約1秒で実行できます。CIでは、プッシュごとにUbuntuとWindowsでリンター、テスト、検索評価、不変条件のチェックを実行します。CONTRIBUTING.md を参照してください。
ステータス
まだ初期段階で、独自の方針を持つプロジェクトです。1人の日常的な使用向けに作成した後、汎用化しました。Windows 11でClaudeデスクトップアプリを使い、日々の使用でテストしています。CIではUbuntuとWindowsを対象としています。ポータブルなフックコマンド($CLAUDE_PROJECT_DIR)はCIで不変条件を満たしていますが、macOSやLinuxの実セッションではまだ実行していません。
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。