familiarで使う9本のMCPサーバー

familiarのオーケストレーションでは、記録時点で9本のMCPサーバーを使っています。すべてRust製のstdio JSON-RPC 2.0です。1日に1-2本ほど作って試し、残ったものを改良してきました。LLMを開発作業に組み込むための設計と用途をまとめます。

Zed の MCP サーバー一覧 -- 9本全てグリーン
Zed の MCP 設定画面 -- 全サーバーが接続済み。合計ツール数は 41

homelabの構成

MCPサーバーを動かしているhomelabの構成です。

homelab 4ノード構成図 -- edge, storage, desktop, compute
homelab の全体構成。edge (RouterOS), storage (Ubuntu 24/7), desktop (macOS), compute (EPYC + Blackwell x2)。MCP サーバー群は desktop 上で稼働し、compute の LLM バックエンドと storage のデータ基盤に接続する
MCP サーバーツール数一言
voracle4Obsidian vault セマンティック検索 + ウェブリサーチ
argus1クロスリポジトリ コードインテリジェンス
ctree8コードツリー構造解析 + チェックポイント
dgs17ひみつ
memento2ひみつ
okitegami1Discord 置き手紙
smng2homelab シークレット管理
sqlimit-15read-only DB 探索

resolve-inferenceはfamiliar本体へ統合済みです。独立したMCPではありませんが、下に設計経緯を残します。


voracle: vault検索とウェブリサーチ

Obsidian vault向けのセマンティック検索とウェブリサーチです。ONNX embeddingとColBERT rerankingをローカルで動かします。researchはBrave Search APIで得た知見をvaultへ蓄積します。詳細は別記事にあります。

ツール: search, read, research, related


argus: リポジトリを横断するシンボル検索

Giteaの全リポジトリをインデックスします。tree-sitterでシンボルを抽出し、ColBERT MaxSimで検索結果を並べ直します。

  CLI (index + embed)           MCP Server (query)
     |                              |
     v                              v
[Gitea API: repos/search]    [CWD auto-index on startup]
     |                              |
     v                              v
[git clone/fetch]             [argus.see tool]
     |                              |
     v                              v
[tree-sitter: symbols]        [adaptive lexical filter -> ColBERT rerank]
     |                              |
     v                              v
[ColBERT embed (batch)]       [Gemini summarize]
     |                              |
     v                              v
[redb: symbols+embeddings]    [hit tracking + NATS pulse]
  

embeddingは3層で扱います。

  1. Batch: argus embed でインデックス時に全シンボルを事前計算
  2. Hot-hit: アクセス3回以上のシンボルはクエリ時に再 embed して鮮度を保つ
  3. On-demand: 未キャッシュのシンボルはクエリ時に embed して永続化

ツール: see(期待するシンボル・モジュール・仕様を指定してリポジトリ横断検索)


ctree: コード構造・依存関係・リビジョン

.ctree.tomlでスコープを定義し、checkでコードのシンボル構造と依存関係を解析します。checkpointで作業の節目を記録します。

ツール: check, checkpoint, get_affected, get_depends, get_symbol, get_text, get_revs, get_baseline

familiarの開発では、変更後にcheckpointでリビジョンを残し、次の実装前にget_affectedで影響範囲を確認します。Obsidianの作業ログにもctree__checkやctree__get_symbolが繰り返し残っています。

多くの応答は5tok程度のreplyか、シンボル名とハッシュです。コード本体は必要なときだけget_textで取得します。依存関係を確認しながら、コンテキスト消費を抑える構成です。以前はserenaと併用していましたが、この構成が安定してから不要になりました。自前のgiteaとdistribution(registry)を入れた後は、argusを通じてiacやコードベースの設計・ノウハウを参照しながらコーディングできています。

Obsidian の作業ログで ctree__check を検索した結果 -- エージェントが thinking で計画を立てた直後に ctree のツールを連続で呼び出している
エージェントの作業ログ。thinking の直後に ctree__get_symbol, ctree__get_affected, ctree__check, ctree__get_depends, ctree__get_text を連続で呼んでいる

dgs – 17 tools (non-public)

9本の中でツール数が最大です。設計と実装の詳細は非公開です。


memento – 2 tools (non-public)

AIエージェント管理に関わるMCPです。設計と実装の詳細は非公開です。


okitegami: Discordへの非同期通知

LLMエージェントが作業の節目にDiscordへ通知します。ツールは1つです。

進捗を置き、人間は都合のよいときに返事を残します。次にエージェントが通知するとき、残っている返事を読みます。

  1. いまの作業結果を Discord に置き手紙する
2. そのついでに、過去の手紙に返信がついていれば読む
3. 返信がなければ何もしない
  

新しい通知を置くことが読み取りの契機です。返事を探すポーリングループは作りません。

okitegami の Discord スレッド -- tegami APP による置き手紙とksh3のリプライ
tegami が置いた手紙のスレッド。summary, worked, result, concerns, tests が構造化されている。ksh3 が数時間後にリプライしている

エージェントは開発中に#tegamiへスレッドを作り、進捗を残します。私は後から読み、気づいたことをリプライします。1ヶ月後の返事でも、次にtegamiを呼んだときに拾い、確認を求めたり修正したりします。

急ぎの返事は求めません。返事がなくても作業を続けられるので、長時間の自律作業と人間の確認を非同期でつなげられます。

ツール: tegami


smng: 認証情報と接続情報

homelabのクレデンシャル、エンドポイント、接続情報を管理します。*.home.arpa内のサービス認証情報を取得します。

ツール: list_services, get_secret


sqlimit-1: 1行に制限したDB参照

familiarのメインDBだけを対象に、クエリ結果を最大1行へ制限します。LLMにLIMIT 1を書かせるのではなく、ツールが必ずサブクエリで包みます。

  SELECT * FROM (<user_sql>) AS _q LIMIT 1
  

PostgreSQLのdefault_transaction_read_only = onを設定した専用ユーザで接続します。非SELECT文も拒否し、読み取り専用で使います。

接続情報はsmngから取得できます。sqlimit-1はスキーマのバージョン管理も担当します。dump_schemaで取得したスキーマに変更があれば、新しいバージョンを残します。少ないコンテキストでデータ構造を確認する用途です。

smngは認証情報、sqlimit-1はDB参照とスキーマ記録を担当します。責務を分けて組み合わせています。

ツール: tables, describe, sample, query1, dump_schema


resolve-inference: ENOENTを避けるパス解決

LLMがパスを推測してENOENTを起こす問題に対応するために作りました。ファイルシステムインデックス、字句スコアリング、ColBERT MaxSimで候補を選びます。現在はfamiliarに統合しています。

精度改善にはクエリ履歴が効きました。直近5件の解決パスをリングバッファで保持し、ディレクトリとパッケージのアフィニティで候補を補正します。

  Go モノレポ(106ファイル、client.go が4-11箇所に存在):
  履歴あり: 85.0% (17/20)
  履歴なし: 35.0% (7/20)
  差分:     +50.0pp
  

3つのColBERTモデルをアンサンブルで評価しましたが、精度はすべて87.3%で、レイテンシだけ3.7倍になりました。この比較ではモデル変更で改善せず、字句アルゴリズム側を見直しました。アンサンブルを廃止し、クエリ履歴の相関へ注力しています。


廃止・統合したツール

廃止したツールの多くは、別のツールへ統合しました。resolve-inferenceはfamiliar本体に入り、初期shelpaのファイルシステム機能はctreeとdgsへ分かれて引き継がれました。

Rustとstdio JSON-RPC 2.0なら、1日ほどでMCPサーバーの形を作れます。試して不要なら廃止し、使えるものを改良する進め方です。


共通の設計

各サーバーで揃えている方針です。

  • Rust + stdio JSON-RPC 2.0: プロセス起動が速く、メモリフットプリントが小さい
  • 単機能: 1つのツールが1つの問題を解決する。多機能にしない
  • LLM エージェントの実務から生まれた: 「こういうときに困る」から逆算して作っている
  • グレースフルデグラデーション: ツールが落ちても他のツールは動く。familiar 本体のフローが止まらない

41ツールを9プロセスで動かし、合計メモリ使用量は数十MBです。Rustの小さいバイナリと実行時オーバーヘッドが、多数の小さなプロセスを並走させる構成に合っています。