Skip to main content
Glama
adborroto

semantic-search-mcp

by adborroto

semantic-search-mcp

CI Security npm node License: MIT

コンパクトで自己完結型のRAGライト検索エンジンです。ディスク上のファイルをインデックス化し、「このクエリに意味的に関連するものは何か」という問いに答えるだけのシンプルなツールです。LLMを呼び出したり、回答を生成したりはしません。最も関連性の高いテキストチャンク(ファイル、行、スコア)を返すので、それを利用する側(人間、スクリプト、MCP経由のLLMなど)が自由に判断できます。

初回実行後は、すべてローカルかつオフラインで動作します。

  • 埋め込み: @huggingface/transformers を使用し、Xenova/all-MiniLM-L6-v2 をint8量子化ウェイトでCPU上で実行します。GPU、APIキー、クエリ時のネットワーク呼び出しは不要です。

  • ベクトルストア: @lancedb/lancedb — 組み込み型のファイルベースベクトルデータベースです。サーバープロセスやDockerは不要です。

  • インターフェース: CLIと標準入出力のMCPサーバーを提供するため、MCP対応のエージェント(Claude Code、Cursor、Zedなど)が直接コーパスを検索できます。

クイックスタート

npm install -g @adborroto/semantic-search-mcp

semantic-search add ~/code/my-project      # add a folder to the corpus
semantic-search index                      # embed it (incremental on later runs)
semantic-search search "how does the retry logic work"

これでセットアップは完了です。手動で設定ファイルを書く必要はありません。add コマンドが作成と管理を行います。何もインストールせずに試すには:

npx @adborroto/semantic-search-mcp add ~/code/my-project

インストールサイズに関する注意: 約950MBの依存関係に加え、初回使用時に約25MBの埋め込みモデルがダウンロードされます。そのほとんどがネイティブバイナリであり、このレイヤーでは避けられないものです。@lancedb/lancedb(プラットフォームバイナリを含めて約430MB)とONNXランタイム(全プラットフォームのビルドを1パッケージにまとめて出荷するため約300MB)です。どちらも一度キャッシュされれば、初回実行以降はオフラインで動作します。

必要条件

  • Node.js >= 22(フォールバックバックエンドで使用する node:sqlite は22から安定しています)。

  • 依存関係に約950MB、埋め込みモデルに約25MBのディスク容量。さらに、インデックス化されたチャンク1つあたり約1~3KBが必要です。

  • GPU、外部サービス、データベースサーバーは不要です。

「RAGライト」である理由

完全なRAGパイプラインは、チャンクを取得 → LLMに渡す → LLMが回答を生成する、という流れです。このプロジェクトは最初のステップで止めています。これにより、シンプルで高速、低コストで動作し、動作を理解しやすくなります。また、独自の生成レイヤーをバンドルする代わりに、既存のLLMやエージェントフレームワークとクリーンに連携できます。

コーパスの管理

semantic-search add ~/code/api ~/notes     # add one or more folders
semantic-search list                       # show what's configured
semantic-search remove api                 # by folder name...
semantic-search remove ~/notes             # ...or by path
semantic-search config                     # where config + index actually live

add は各パスが実際のディレクトリであることを検証し、絶対パスに解決して、重複(シンボリックリンク経由で到達した同じディレクトリを含む)をスキップします。remove はそのフォルダのチャンクをインデックスからも削除するため、その内容は結果に表示されなくなります。コーパスからは削除するが検索可能な状態は維持したい場合は、--keep-index を指定してください。

保存場所

設定とインデックスはXDGベースディレクトリ仕様に従うため、アップグレード後も存続し、すべてのインストール方法で共有されます。

項目

場所

設定

~/.config/semantic-search/config.json

インデックス + モデルキャッシュ

~/.local/share/semantic-search/

これらは SS_CONFIG_PATHSS_INDEX_DIRSS_MODEL_CACHE_DIR、または標準の XDG_CONFIG_HOME / XDG_DATA_HOME で上書きできます。SS_STORE_BACKEND=sqlite でフォールバックバックエンドを強制します。

インデックスには、インデックス化したすべての内容がそのままのテキストで含まれます。 プライベートコードを指定した場合、~/.local/share/semantic-search/ にはその内容が平文で保持されます。これをコミットしたり、バグレポートに添付したりしないでください。

すべてのオプションは src/config.js に文書化されています(チャンクサイズ、無視パターン、モデル名、top-k、同時実行数など)。config.json を直接編集してもこれらのオプションは機能します。add/remove は自身が管理しないキーを保持します。

使用方法

インデックス

semantic-search index                      # all configured folders
semantic-search index ~/code/one-project   # just this folder, ignoring config
semantic-search index --force              # reprocess everything

インデックス作成はインクリメンタルです。変更されていないファイルは更新時刻でスキップされ、内容が実際に変更されていないファイル(touchされただけ)は再埋め込みをスキップし、ディスクから削除されたファイルはインデックスから削除されます。実際に変更されたものだけが再処理されます。

複数のフォルダが設定されている場合、index はフォルダごとのヘッダーと合計とともに順次処理します:

[1/3] my-api  /home/me/code/my-api  ─────────────────────────────
  ↺ indexed   src/auth/middleware.js  (8 chunks)
  2 indexed  1,203 skipped  16 chunks  4.1s

[2/3] my-app  /home/me/code/my-app  ─────────────────────────────
  ...

──────────────────────────────────────────────────────────────
total  5 indexed  3,891 skipped  0 deleted  41 chunks  12.3s

index <path> 呼び出しは、そのパス以下のファイルの古いエントリのみを削除するため、フォルダBのインデックス作成がフォルダAのエントリに影響を与えることはありません。

便利なフラグ:--max-files <n> はN個の新しいファイルで停止し(巨大なコーパスでのメモリ使用を制限)、--concurrency <n> は並列処理数を設定し、--verbose は各ファイルをstderrにログ出力します。

検索

semantic-search search "how does the retry logic work" -k 5

ファイルパス、行番号、スコア、テキストプレビューの表を出力します。内部処理:クエリを埋め込み、最近傍ベクトルマッチのプールを取得し、リテラルクエリ用語も含むチャンクに小さな語彙ブーストを適用し、上位 k 件を返します。

ファイルの除外

インデックス作成はデフォルトで node_modules/.git/、ビルド出力、ロックファイル、および500,000バイトを超えるファイルをスキップします。さらに除外するには、gitignore形式の .indexignore を以下のいずれかの場所に配置します:

  • インデックス化するフォルダ内 — パターンはそのフォルダからの相対パスとなるため、リポジトリが自身の生成出力を除外できます。

  • 設定ファイルの隣~/.config/semantic-search/.indexignore) — すべての場所に適用されます。

iOS、Android、Flutter、Ruby、JVMのビルドアーティファクトをカバーする出発点として、.indexignore.example を参照してください。

MCPサーバー

semantic-search mcp

6つのツールを公開する標準入出力MCPサーバーを起動します。

search(query, k?) — セマンティック検索。生のJSONを返します:

[{ filePath, text, score, offset, startLine }, ...]

gather(query, k?, contextLines?) — 同じ検索ですが、コンテキストウィンドウにそのままドロップできる、フォーマット済みの単一マークダウンブロックとして返します:

### [1/5]  my-api  ·  src/auth/session.js  ·  line 42  ·  score 0.923
```
...chunk text...
```

contextLines(デフォルト0)は、各チャンクの周囲からN行の追加行をソースファイルから読み取ります。チャンク境界で必要なコンテキストが切れてしまう場合に便利です。

list_folders() — 設定されているすべてのフォルダを、その名前と絶対パスとともに返します。エージェントがどのようなコーパスが存在するかを把握するための、最初の呼び出しとして適しています。

cat_file(filePath, startLine?, endLine?)search/gather が返した絶対パスでファイルを読み取ります。設定されたフォルダ内に制限されます(セキュリティを参照)。

grep(pattern, folder?, fileGlob?, caseSensitive?, maxResults?) — コーパス全体に対するリテラルまたは正規表現検索。類似性ではなく完全一致が必要な場合に使用します。インデックス作成と同じ .indexignore ルールが適用されます。

my-api  ·  src/auth/session.js:42  export function createSession(user) {

index(root?, force?, maxFiles?, concurrency?) — インクリメンタルな再インデックスをトリガーします。エージェントがシェルアウトせずにコーパスを更新できます。

すべての検索ツールはCLIと同じランキングとファイル解決コードを共有しており、再実装はありません。

MCPクライアントへの登録

Claude Code:

claude mcp add --scope user semantic-search -- semantic-search mcp
claude mcp list   # should show "✔ Connected"

JSONサーバー定義を受け付ける任意のクライアント:

{
  "mcpServers": {
    "semantic-search": {
      "command": "semantic-search",
      "args": ["mcp"]
    }
  }
}

ここでは npx よりもグローバルインストールを推奨します。ベアの npx はサーバー起動のたびにパッケージを再解決するため、起動レイテンシが増加し、予告なしにアップグレードが適用されます。npx を使用する場合はバージョンを固定してください — npx -y @adborroto/semantic-search-mcp@0.1.0 mcp

新しいMCPサーバーは通常、セッション開始時にのみ認識されるため、登録後は新しいセッションを開始してください。

セキュリティ

これはローカルなシングルユーザーツールであり、シンプルな信頼モデルを持ちます。設定されたフォルダ内のものはすべて、サーバーに到達できる任意のMCPクライアントから読み取り可能です。

  • cat_file は設定されたフォルダ外のパスを拒否します。まずシンボリックリンクを解決するため、フォルダ内に仕掛けられたリンクを使って脱出することはできません。

  • grep.indexignore ルールを適用するため、インデックス作成から意図的に除外されたファイルが完全一致検索で漏洩することはありません。

  • サブプロセスはargv配列で生成されるため(シェルは使用されません)、パターンによるコマンドインジェクションはできません。

以上の理由から、LLMプロバイダーに渡したくないコーパスを指定しないでください。チャンクはそれを要求したクライアントに返されます。SECURITY.md を参照してください。

仕組み

チャンキング

テキストは段落に分割され、その後、約200トークンのチャンクに約35トークンのオーバーラップで貪欲にパッキングされます。トークン数は文字数近似ではなく、埋め込みモデルの実際のトークナイザーでカウントされます。これは恣意的なものではありません。all-MiniLM-L6-v2 のウィンドウは256トークンであり、それより長いものは暗黙的に切り捨てられるため、チャンクは [CLS]/[SEP] トークンのマージンを持ってその中に収まるようにサイズ設定されています。オーバーラップはさらに、オーバーラップと次の段落を合わせてもその制限を超えないように制限されています。そうしないと、チャンクの末尾が埋め込み時にドロップされながら、search では返されてしまうことになります。

ハードリミットより大きい単一の段落(ミニファイされたバンドル、巨大なログ行など)は、同じオーバーラップロジックで単語レベルのパッキングにフォールバックし、500文字を超える単一の「単語」は最初にスライスされるため、巨大なものがトークナイザーに一度に渡されることはありません。

トークン数は段落/単語ごとに1回計算され、キャッシュされてオーバーラップ計算で再利用されます。初期のバージョンではオーバーラップ参照のたびに再トークナイズしていましたが、小さな入力では問題なくても、大規模なリポジトリではCPU使用率の急上昇と数GBのメモリ増大を引き起こしました。チャンカーを拡張する場合は、この特性を維持してください。

インクリメンタルな再インデックス

個別のマニフェストはありません。ベクトルストア自体がマニフェストです。保存されたすべてのチャンクは、そのソースファイルの mtimeMssha256 コンテンツハッシュを保持します。実行ごとに:

  1. ディスク上のファイルの mtime が保存されているものと一致する場合、ファイルを読み取らずにスキップします。

  2. mtime は変更されたがコンテンツハッシュが同一の場合(touch)、再埋め込みをスキップします。

  3. それ以外の場合は、そのファイルの古いチャンクを削除し、新しく埋め込まれたものを挿入します。

  4. ウォーク後、ディスク上になくなった(かつインデックス化されているルート下にある)インデックス化済みパスは削除されます。

ストレージバックエンド

デフォルトはLanceDBです。組み込み型、ファイルベース、本格的なベクトル検索を提供します。node:sqlite + 力任せのコサイン類似度フォールバック(src/store/sqliteFallbackStore.js)は、LanceDBのネイティブバインディングが読み込めない環境(サンドボックス化されたコンテナ、特殊なアーキテクチャなど)向けに、同じインターフェース(src/store/vectorStore.js)を実装しています。SS_STORE_BACKEND=sqlite で切り替えます。

フォールバックは検索ごとに全テーブルスキャンを行います。数万チャンクまでは問題ありませんが、それを超えると厳しくなります。LanceDBのデフォルトの距離メトリックはL2でありコサインではないため、このプロジェクトではすべてのクエリで明示的に .distanceType('cosine') を設定しています。埋め込みは正規化されたベクトルとして比較されるためです。

プロジェクト構造

src/
  config.js            Defaults + config file resolution (XDG) — the only source of tunables
  configFile.js        Read/modify/write the config file (backs add/remove/list)
  embeddings.js        transformers.js pipeline + tokenizer (lazy singletons)
  chunker.js           Token-aware paragraph packing with overlap
  ignoreRules.js       .indexignore layering, shared by the indexer and grep
  safePath.js          Path confinement for the MCP file-reading tools
  version.js           Version read from package.json
  extractors/          text (.txt .md .js .ts .py .rb .json), pdf (pdf-parse), docx (mammoth)
  store/
    vectorStore.js        Storage interface + backend selector
    lancedbStore.js       LanceDB implementation (default)
    sqliteFallbackStore.js node:sqlite + manual cosine fallback
  indexer.js           Walk + extract + chunk + embed + incremental upsert/prune
  search.js            Embed query + vector search + lexical boost — shared by CLI and MCP
  mcp-server.js        MCP stdio server: the six tools above
  index.js             CLI entrypoint (commander)
scripts/index-all.sh   Batched indexing for very large corpora on constrained hosts (Linux)

開発

git clone https://github.com/adborroto/semantic-search-mcp.git
cd semantic-search-mcp
npm install
npm test              # unit + end-to-end (node:test, no framework)
npm run test:unit     # skip the slow end-to-end test
npm run lint

チェックアウトルートにある config.json はXDGの場所よりも優先されるため、実際の設定に影響を与えずにスクラッチコーパスに対して開発できます。テストは常に一時ディレクトリに書き込みます。CONTRIBUTING.md を参照してください。

対象外(設計上の意図)

  • 回答生成。 これはチャンクを返すものであり、回答ではありません。ご自身でLLMに渡してください。

  • 第2モデルによる再ランキング。 語彙ブーストは安価で依存関係のない近似であり、本格的なクロスエンコーダー再ランカーの代用にはなりません。

  • Web UI。 CLIとMCPのみです。

  • 大規模コーパス。 個人またはチーム規模のドキュメントとコードのコーパス(数万チャンク、数百万ではありません)向けに構築されています。両方のバックエンドがその規模を想定しています。

ライセンス

MIT

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

  • Agentic search over your Dewey document collections from any MCP-compatible client.

  • Hosted MCP memory: save sessions/decisions once, search from Claude, Cursor, ChatGPT. EU-hosted FTS.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adborroto/semantic-search-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server