shelpaからfilesystemへ — Rust MCPファイルシステムサーバーの全面再設計
ローカルLLMエージェント向けMCPサーバーshelpaをfilesystemにリネームし、パイプライン実行エンジンを撤去してundo/redo・ゴミ箱・ファイル追跡付きのMCPファイルシステムサーバーに全面再設計した記録
概要
ローカルLLMエージェント向けに構築したMCPサーバー「shelpa」を「filesystem」に再利用して作り直した。名前の変更にとどまらず、パイプライン実行エンジンの完全撤去、undo/redo・ゴミ箱・ファイル追跡機能を備えたMCPファイルシステムサーバーへの全面改修となった。
shelpaの旧設計については仮想パイプラインの設計記録とサンドボックス設計と教訓を参照。本稿はその後継として生まれ変わったfilesystemの設計と実装の記録である。
shelpaが抱えていた問題
shelpaはshelpa_pipe(パイプライン実行)とshelpa_write(ダイレクト書き込み)の2つのMCPツールを提供し、許可コマンドのみを実行できるミニマルな文法を強制するサンドボックスだった。書き込み操作はすべて.shelpa/ディレクトリにミラーコピーを保存し、トレーサビリティを確保していた。
しかし、パイプライン実行というコンセプト自体がLLMとの相性に限界があった。このライブラリを「filesystem」として作り直すにあたり、名前だけでなくアーキテクチャの根本を見直すことにした。
shelpaから使える実装だけを残してプロトタイプへ
最初の作業は「shelpa」から使える実装だけを残し、構想に不足していた機能をまず動く形へ全体を構成し、仮組みを行ってプロトタイプを作ることだった。
パイプライン実行関連のモジュール(parser.rs、executor.rs、types.rsとそのテスト群)を削除し、パス安全性検証やワークスペーススコープの制限機構など再利用できるコアだけを残した。依存クレートもregex、os_pipe、shell-words、thiserrorを削除してスリム化した。
パイプラインエンジンの撤去とMCPファイルシステムAPIへの移行
最も大きな設計変更として、shelpa由来のパイプライン実行エンジンを完全に撤去し、MCP公式のfilesystemサーバー(modelcontextprotocol/serversのsrc/filesystem)を参考にした標準的なファイルシステム操作ツールに置き換えた。
公式リファレンス実装はTypeScriptで書かれている。これをRustベースのMCPサーバーとして再実装しつつ、shelpaの特徴だった.filesystem/ディレクトリによるトレーサビリティを発展させ、ゴミ箱・バージョン履歴・ファイル追跡を備えた設計に拡張した。
14ツール構成
最終的なツール構成は14個になった。
基本ファイル操作
| ツール | 機能 |
|---|---|
read_text_file | ファイル読み取り。head/tailで部分読み取り対応 |
create_file | 新規作成。既存ファイルがある場合はエラー |
write_file | 作成・上書きの両方に対応 |
edit_file | oldText/newTextによる検索置換。diff出力、dryRun対応 |
create_directory | 再帰的ディレクトリ作成 |
list_directory | [FILE]/[DIR]プレフィックス付き一覧 |
directory_tree | JSON形式の再帰ツリー(除外パターン対応) |
move_file | 移動・リネーム。移動先既存の場合はエラー |
安全な削除と復元
| ツール | 機能 |
|---|---|
delete_file | ファイルを.filesystem/.trash/に移動(永久削除しない) |
list_trash | ゴミ箱の内容一覧 |
restore_file | ゴミ箱から元のパスに復元 |
search_file | ファイルの状態検索。移動・削除の追跡結果を返す |
バージョン履歴(--backupモード限定)
| ツール | 機能 |
|---|---|
undo_file | nバージョン前の状態に復元 |
redo_file | undo後にnバージョン先に進める |
書き込みを伴う操作(create_file、write_file、edit_file、move_file)は自動的に.filesystem/への記録を実行する。move_fileは.filesystem/.movesにログを追記し、delete_fileは.filesystem/.deletesにログを残す。
デュアルモードMCPサーバー
filesystemは--mcpと--serverの2つの起動モードを持つ。同じMCPツールキット内のctreeやpathfinderとCLIインターフェースを統一するための設計である。
filesystem --mcp [--root <ROOT>] # シングルプロジェクト
filesystem --server # グローバルデーモン
| 観点 | --mcp | --server |
|---|---|---|
--root(起動時) | 任意(デフォルト: cwd) | 受け付けない |
ツール呼び出しのroot | 無視 | 必須 |
| マルチプロジェクト | 不可 | 可 |
| 用途 | CLI / スタンドアロン | agent-gatewayデーモン |
--serverモードはagent-gatewayから常駐プロセスとして起動される前提で、ゲートウェイがすべてのツール呼び出しにrootを注入する。
ServerConfig{
Name: "filesystem",
Command: "filesystem",
Args: []string{"--server"},
Scope: "global",
}
ワイヤプロトコルは最初のメッセージから自動検出される。先頭バイトが{ならLine JSON、Content-Length:ヘッダならHTTPスタイルフレーミング(LSP互換)として処理する。
.filesystem/のヒストリモデル
.filesystem/ディレクトリはshelpa時代の単純なミラーから、構造化された履歴システムに進化した。
--backupモード時の構造
.filesystem/
src/
main.rs/ # src/main.rsの履歴
00001 # バージョン1(全文スナップショット)
00002 # バージョン2
.head # 現在のバージョンポインタ
.moves # append-onlyのリネームログ(タブ区切り)
.trash/
00001 # 削除されたファイル内容
00001.history/ # 削除されたファイルのバージョン履歴
.deletes # append-onlyの削除・復元ログ
各書き込みはdiffではなく全文スナップショットを追記する。シンプルで高速、リスクが低い。.headが現在のバージョンを追跡し、undoでデクリメント、redoでインクリメントする。undo後に新しい書き込みが発生するとredoスタックはクリアされる(一般的なエディタと同じ挙動)。
move_fileは履歴ディレクトリごと移動し.movesに追記する。delete_fileはファイルと履歴を.trash/に移動して.deletesにログを残す。ゴミ箱IDは単調増加で再利用されない。
--backupなしの場合
.moves、.trash/、.deletesのみを使用する。バージョンスナップショット、.head、undo/redoは無効。最小限のフットプリントで動作する。
パス安全性とサンドボックス
shelpaから引き継いだワークスペーススコープの制限は維持・強化した。
- パスはファイルシステムアクセスなしで正規化(
..と.を折りたたむ) - 絶対パスもワークスペースルート内でなければ
PathEscapeエラー - シンボリンクは起動時に解決(macOSの
/tmp→/private/tmpに対応) - シェル実行なし。コマンドインジェクションの攻撃面がない
list_directoryとdirectory_treeは.filesystem、.git、node_modules、target、__pycache__など一般的なビルド・キャッシュディレクトリをデフォルトで除外し、ワークスペースルートの.gitignoreパターンも適用する。
エラーモデル
すべてのエラーはisError: trueのMCPツール結果として返る。
| エラー種別 | 発生条件 |
|---|---|
PathEscape | パスがワークスペースルートを逸脱 |
NotFound | ファイル/ディレクトリが見つからない、edit_fileのoldText不一致 |
AlreadyExists | create_fileの対象が既存、move_file/restore_fileの移動先が既存 |
IoError | ファイルシステムI/Oエラー |
InvalidArgument | 不正なパラメータ(headとtailの同時指定、undoの超過など) |
まとめ
この改修で達成した主要な成果を整理する。
- shelpaからfilesystemへの再設計 — パイプライン実行エンジンを完全撤去し、標準的なファイルシステムAPIに移行
- 14ツールのMCPサーバー — 基本ファイル操作8種、安全な削除/復元4種、バージョン履歴2種の構成
- デュアルモード —
--mcp(シングルプロジェクト)と--server(マルチプロジェクトデーモン)でctree・pathfinderとCLIパターンを統一 .filesystem/ヒストリモデル — 全文スナップショットによるundo/redo、ゴミ箱による安全な削除、リネーム/削除の追跡ログ--backupフラグによる段階的な機能選択 — バージョン履歴が不要な場合は最小フットプリントで動作
このfilesystemを作り直した直接の動機は、agent-gatewayを自作エージェントに改良したことにある。ワーカーとして動くローカルLLMがファイルを誤って削除・破壊しても、ゴミ箱とバージョン履歴から容易に復旧・検証できる仕組みが必要だった。shelpaのワークスペーススコープとミラーリングの設計思想は、この要件にそのまま再利用できた。
