emperor-folder について
emperor-folderは、指定フォルダー内のファイルを扱うエージェントやクライアント向けのMCPサーバーです。既定では読み取り専用で、操作範囲を設定したルート内に限定し、起動時に許可すれば変更もできます。
主な機能
- 01ファイルの一覧表示、読み取り、検索、情報取得
- 02書き込み、編集、移動の任意有効化
- 03設定したフォルダーのルート内にアクセスを限定
- 04Streamable HTTPまたはstdioで接続
- 05隠しファイルと除外ファイルのフィルタリング
活用シーン
- 01他のフォルダーを公開せずにプロジェクトファイルを検索
- 02書き込みを有効にしてファイルを制御下で編集
- 03複数の名前付きフォルダーをMCPクライアントに提供
MCP 対応
フォルダーの一覧表示、読み取り、検索、メタデータ取得ツールをMCPクライアントに提供します。書き込み、編集、移動ツールは起動時に有効化した場合のみ提供され、Streamable HTTPとstdioに対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
emperor-folder
1つのフォルダー内に制限されたMCP サーバーです。 ディレクトリを1つ(またはいくつか)指定すると、モデルはその中のファイルを一覧表示、読み取り、検索でき、許可した場合は書き込み、編集、移動もできます。絶対パス、..、シンボリックリンクのいずれを使っても、フォルダーの外にはアクセスできません。
emperor-folder serve --root ~/notes # read-only, Streamable HTTP on 127.0.0.1:8031/mcp
emperor-folder serve --root ~/notes --writable # also write, edit and move
emperor-folder serve --root ~/notes --stdio # for desktop clients
emperor-folder serve --root notes=~/notes --root code=~/src/app # two roots: notes/..., code/...
理由
エージェントに「ファイルシステム」を与えることは、SSHキーを渡す最も手っ取り早い方法です。多くのファイルツールはパスを文字列の接頭辞で確認したあと、プロセスの全権限でファイルを開きます。シンボリックリンク、確認をすり抜けた..、あるいは確認からオープンまでの競合状態があれば、モデルは範囲外へ出てしまいます。
emperor-folderは、確認してから開く方式を採用していません。ルートをcap-stdのディレクトリハンドルとして一度だけ開き、すべてのファイル操作を相対パスでそのハンドルを通じて行います。これにより、パス解決はオペレーティングシステム(またはcap-std)のルート配下に限定する規則に従います。絶対パスでファイルを開くコードパスはありません。
emperor-mcpを基盤としており、ステートレスなStreamable HTTP(セッションIDなし、ロードバランサーに適しています)、ファイルの内容が指示ではなくデータとしてモデルに届くようにする出力フレーミング、doctorサブコマンドを備えています。Emperor Profile P1.1に準拠しており、起動時にオペレーターが書き込みを有効にしない限り、書き込みツールは提供されません。また、ツール定義は簡潔(短い説明、コンパクトな入力スキーマ)であるため、リクエストごとに送信する量を抑えられます。
インストール
Linux(x86_64)、macOS(Apple SiliconおよびIntel)、Windows向けのリリースバイナリは、各GitHubリリースに添付されています。SHA256SUMSファイルとビルド来歴の証明も含まれます。ダウンロードしたファイルはsha256sum -c SHA256SUMS --ignore-missingとgh attestation verify <file> --repo yarenty/emperor-folderで検証してください。ソースからビルドする場合(Rust 1.88以降):
cargo install emperor-folder
または、コンテナーとして実行できます(stdioを使用し、フォルダーは/dataにマウントされます。--writableを追加しない限り読み取り専用です):
docker build -t emperor-folder https://github.com/yarenty/emperor-folder.git
docker run -i --rm -v ~/notes:/data emperor-folder # read-only
docker run -i --rm -v ~/notes:/data emperor-folder --root /data --writable # also write, edit, move
docker run -i --rm -v ~/notes:/data -e FOLDER_WRITABLE=true emperor-folder # the same, from the environment
実行
emperor-folder doctor --root ~/notes # check first: exits 1 if something is wrong
emperor-folder serve --root ~/notes
| フラグ | デフォルト | 意味 |
|---|---|---|
--root [NAME=]DIR | (必須) | サーバーが参照できるフォルダーです。複数のルートを指定するには繰り返します。NAME= を付けると名前を指定できます(デフォルト:フォルダー自体の名前)。複数のルートを参照してください。 |
--bind ADDR | 127.0.0.1:8031 | Streamable HTTP のアドレスです。MCP エンドポイントは /mcp、稼働確認用エンドポイントは /health です。 |
--writable | オフ | write、edit、move を提供します。指定しない場合、これらは一覧に表示されません。環境変数 FOLDER_WRITABLE でも設定できます。true、1、yes(および on)で有効になり、未設定、空、false、0、no(および off)では無効になります。それ以外の値は拒否されます。 |
--stdio | オフ | HTTP の代わりに stdin/stdout で MCP を通信します。ログは stderr に出力されます。 |
--hidden | オフ | list と search に隠しファイルと隠しディレクトリーを含めます。 |
--no-ignore | オフ | .gitignore、.ignore、Git の除外ファイルを無視しません。 |
--max-file-bytes N | 1048576 | read が全体を返すファイル、search が開くファイル、stat が行数を数えるファイル、および write が受け付けるファイルの最大サイズです。 |
--max-results N | 200 | list が返すエントリー数と search が返す一致数の上限です。 |
--max-chars N | 50000 | 1 回の read が返すテキストの最大文字数(上限は 200 000)です。これを超える読み取りは行の境界で停止し、続きの位置を示します。 |
--allowed-host HOST | 下記参照 | 許可する Host ヘッダーです。複数指定できます。 |
--allowed-origin ORIGIN | なし | 許可するスキーム付きの Origin ヘッダー(https://app.example.com)です。複数指定できます。Origin のないリクエスト(ブラウザー以外のクライアント)は引き続き許可されます。 |
RUST_LOG でログレベルを設定します(デフォルトは info)。
接続
Claude Code
claude mcp add --transport http folder http://127.0.0.1:8031/mcp # server already running
claude mcp add folder -- emperor-folder serve --stdio --root ~/notes # or let Claude Code start it
--writable(および複数のルート)を指定した stdio 形式の場合:
claude mcp add folder -- emperor-folder serve --stdio --writable --root notes=$HOME/notes --root code=$HOME/src/app
Claude Desktop(claude_desktop_config.json、stdio):
{
"mcpServers": {
"folder": {
"command": "/usr/local/bin/emperor-folder",
"args": ["serve", "--stdio", "--root", "/Users/me/notes"]
}
}
}
kowalski(config.toml):
[[mcp.servers]]
name = "folder"
transport = "http"
url = "http://127.0.0.1:8031/mcp"
または stdio 経由:
[[mcp.servers]]
name = "folder"
transport = "stdio"
command = ["emperor-folder", "serve", "--stdio", "--root", "/home/me/notes"]
Streamable HTTP または stdio に対応する他の MCP クライアントも、同じように利用できます。
ツール
7つのツールがあり、それぞれ動詞です。すべてのパスはルートからの相対パスです(. または省略した場合はルートを指します)。
ファイルを変更する3つのツールは --writable を指定した場合のみ利用でき、読み取り専用サーバーでは4つのツールが表示されます。
| ツール | 引数 | 戻り値 | アノテーション |
|---|---|---|---|
list | path?、glob?、recursive?(false)、max_entries? | パス、種類(file/dir/symlink)、サイズを含むエントリー。上限に達して打ち切られた場合は truncated も含まれます。 | 読み取り専用、冪等 |
read | path、start_line?、end_line?(1始まり、終端を含む) | path lines A-B of N ヘッダー付きのテキスト。最大5 MiB(および --max-file-bytes の範囲内)のPNG、JPEG、GIF、WebP画像はMCP画像コンテンツとして返されます。それ以外のバイナリファイルは出力されず、binary: true とサイズが報告されます。 | 読み取り専用、冪等 |
search | pattern(正規表現)、path?、glob?、ignore_case?(false) | パス、行番号、行(240文字で打ち切り)を含む一致結果。検索したファイル数、バイナリとしてスキップしたファイル数、大きすぎるためスキップしたファイル数も含まれます。 | 読み取り専用、冪等 |
stat | path | 種類、サイズ、更新時刻(RFC 3339、UTC)、読み取り専用フラグ。サイズ制限内のテキストファイルでは行数、画像では画像の種類も含まれます。 | 読み取り専用、冪等 |
write | path、content、mode?(create | overwrite | append、デフォルトは create) | パスと書き込んだバイト数。親ディレクトリを作成します。create は既存のファイルがある場合、処理を拒否します。 | 破壊的、--writable のみ |
edit | path、old_text、new_text、replace_all?(false) | パス、置換回数、書き込んだバイト数。replace_all を指定しない限り、old_text は正確に1回出現する必要があります(一致回数はエラーメッセージに示されます)。テキストファイルのみ対応します。 | 破壊的、--writable のみ |
move | from、to、overwrite?(false) | 新しいパス。ルート内(またはルート間)で名前変更または移動します。overwrite を指定しない限り、既存の移動先への置き換えは拒否されます。 | 破壊的、--writable のみ |
すべてのツールは openWorldHint: false を設定します。指定されたフォルダー以外にはアクセスしません。
list と search は ignore(ripgrepのウォーカー)を使用します。
.gitignore(Gitチェックアウトの外にある場合も)、.ignore、隠しファイルは、--no-ignore/--hidden を指定しない限りスキップされます。また、シンボリックリンクはたどりません。正規表現には
regex クレートを使用します。マッチングは線形時間で行われ、壊滅的なバックトラッキングは発生せず、コンパイル後のサイズは1 MiBに制限されます。グロブは、ツールが表示するパスに対してマッチします
(*.rs は src/main.rs にマッチします)。
出力。 read のファイルコンテンツは、作成者不明のドキュメント(FrameKind::Document)としてフレーム化されます。一覧、検索結果、メタデータは、計算済みの結果としてJSON形式でフレーム化されます(FrameKind::Computed)。フレームごとに異なるノンスを使用するため、偽のデータ終了マーカーを含むファイルによってブロックを抜け出すことはできません。拒否された操作はツールエラー(isError: true)として返され、代わりに何をすべきかを示すメッセージが含まれます。
複数のルート
--root は複数回指定できます。ルートが1つの場合、動作に変更はなく、パスはそのルートからの相対パスです。
複数ある場合、すべてのパスはルート名から始まり、. はルートをエントリーとして持つ仮想フォルダーになります。
emperor-folder serve --root notes=~/notes --root code=~/src/app
list . -> notes, code
read notes/todo.md
search pattern=TODO -> matches in notes/... and code/...
move notes/a.md -> code/docs/a.md (with --writable)
名前のないルートは、そのフォルダー名が使われます(--root ~/notes は notes です)。同じ名前のルートが2つある場合、起動時に拒否されます。NAME=DIR では、名前に / または \ を含めることはできません。そのため、./a=b は a=b という名前のフォルダーです。各ルートは個別のcap-stdハンドルを持ちます。move で両端を指定する場合を除き、パス、..、シンボリックリンクを使って別のルートに移動することはできません。
セキュリティモデル
モデルができること:無視ルールで隠されていないルート配下のファイルを表示・読み取りできます。--writable を指定すると、ルート配下でファイルの作成、編集、名前変更もできます。
モデルができないこと:
- **ルートの外に出ること。**絶対パス(
/etc/passwd、Windows のC:\)は拒否されます。また、..要素を含むパスは、ルート内にとどまるもの(a/../b)であっても拒否されます。このチェックにより明確なエラーが返されます。さらに、基盤となる強制機構は cap-std で、すべてのパスをルートハンドルの配下で解決します(Linux ではopenat2(RESOLVE_BENEATH)、その他の環境では要素ごとに解決)。ルートの外に出る解決は拒否されます。 - **シンボリックリンク経由で抜け出すこと。**ルート内にある、ルートの外(別のルートも含む)を指すシンボリックリンクは、
read、write、edit、move、list、searchのいずれでも拒否されます。ルート内にとどまるリンクは使用できます。走査処理はリンクをたどらず、取得したすべてのパスをルートハンドル経由で再度開くため、走査中にディレクトリがルート外へ抜け出すリンクに置き換えられても、読み取らずにスキップされます。 - **デフォルトで書き込むこと。**サーバーは読み取り専用で起動します。オペレーターが
--writableを渡す(またはFOLDER_WRITABLEを設定する)まで、ツール一覧からwrite、edit、moveが除かれ、ファイル操作でも書き込みが拒否されます。これは Emperor Profile P1.1 の要件です。ツールのアノテーション(readOnlyHint、destructiveHint)によって、ファイルを変更するツールがクライアントに通知されるため、実行前に確認できます。 - **ホストやコンテキストを使い果たすこと。**ファイル全体の読み取りは
--max-file-bytesで制限されます(行範囲の読み取りはストリーミングされ、同じ上限まで返されます)。また、文字数は--max-charsで制限されます。searchは上限を超えるファイルをスキップし、listとsearchは--max-resultsで停止します。小さな画像を除き、バイナリファイルが返されることはありません。 - **Web ページからアクセスされること。**ループバックにバインドする場合、
Hostヘッダーはlocalhost、127.0.0.1、::1のいずれかでなければなりません(DNS リバインディング対策)。ループバック以外にバインドする場合、Emperor Profile の想定どおり、手前に検証を行うイングレスがあるため、このチェックは無効になります。--allowed-hostを指定すると、名前付きホストに対してチェックが再び有効になり、--allowed-originを指定すると、それ以外のオリジンからのブラウザーリクエストが拒否されます。
対象外:認証(HTTP エンドポイントはゲートウェイの背後に置くか、ループバックでのみ使用してください)とハードリンク(ルート内にある、ルート外のファイルへのハードリンクは同じファイルです。信頼できないユーザーがハードリンクを作成できるフォルダーをサーバーに指定しないでください)。サーバーの実行中も、他のローカルプロセスはフォルダーを変更できます。ただし、すべての操作でルート配下にあることを再解決するため、隔離は維持されます。
doctor
$ emperor-folder doctor --root ~/notes --writable
emperor-folder 0.1.3 doctor
[ok ] dir /Users/me/notes readable (42 entries)
[ok ] dir /Users/me/notes writable
[ok ] write access on: write, edit and move are offered
[ok ] roots notes = /Users/me/notes
[ok ] listen address 127.0.0.1:8031 is free
[ok ] tool budget 7 of at most 8 tools
[ok ] files 1234 visible files under the roots
all good (0 warning(s))
各ルートが存在し、一覧表示できること、--writable が設定されている場合は書き込み可能であること(プローブファイルを作成して削除します)、書き込みが有効かどうか、ルートを開けることと名前が重複していないこと、リッスンアドレスが空いていること(--stdio の場合はスキップ)、ツール数が emperor-mcp の上限内であることをチェックします。また、走査処理が検出するファイル数もカウントします(100 000 を超えると警告が表示されます。一覧表示や検索が遅くなります)。失敗がなければ終了コード 0、それ以外は 1 を返すため、スクリプトやコンテナーのヘルスチェックに使用できます。
ビルド
cargo fmt --all --check
cargo clippy --all-targets -- -D warnings
cargo test # unit tests + every tool over real HTTP and stdio, escape attempts included
cargo deny check
リンク
- クレート:crates.io/crates/emperor-folder、API ドキュメントは docs.rs
- フレームワーク:emperor-mcp
- 他のフォルダーアクセス用 MCP サーバーとの比較:docs/COMPARISON.md
- 公式 MCP Registry のエントリー、mcp-name:io.github.yarenty/emperor-folder
貢献
CONTRIBUTING.md を参照してください。チェックを実行し、ドキュメントを最新の状態に保ち、コミットにサインオフしてください(DCO、git commit -s)。
ライセンス
以下のいずれかのライセンスが適用されます。
- Apache License, Version 2.0 (LICENSE-APACHE または https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT または https://opensource.org/licenses/MIT)
どちらを選択するかは任意です。
別途明示しない限り、emperor-folder に含めるために意図的に提出された貢献は、追加の条件なしに、上記の両方のライセンスの下でデュアルライセンスされます。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。