关于 emperor-folder
emperor-folder 是供 Agent 和客户端操作指定文件夹的 MCP 服务。默认只读,并将文件操作限制在配置的根目录内;启用后可修改文件。
主要功能
- 01列出、读取、搜索和查看文件信息
- 02可选的写入、编辑和移动操作
- 03将访问限制在配置的文件夹根目录
- 04通过 Streamable HTTP 或 stdio 连接
- 05筛选隐藏文件和忽略文件
适用场景
- 01让 Agent 搜索项目文件而不开放其他目录
- 02启用写入后允许受控地编辑文件
- 03向 MCP 客户端提供多个命名文件夹
MCP 相关
向 MCP 客户端提供文件夹列表、读取、搜索和元数据工具;只有启动时启用写入功能,才会提供写入、编辑和移动工具。支持 Streamable HTTP 和 stdio。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
emperor-folder
一个仅限于单个文件夹的 MCP 服务。 指定一个或几个目录后,模型便可以列出、读取、搜索,以及(如果你允许)写入、编辑和移动其中的文件;它无法访问目录之外的任何内容:无论是通过绝对路径、..,还是符号链接。
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/...
原因
把“文件系统”交给 Agent,是让它拿到你的 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 文件和构建来源证明
attestations:使用 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 | 关闭 | 通过 stdin/stdout 而非 HTTP 使用 MCP。日志输出到 stderr。 |
--hidden | 关闭 | 在 list 和 search 中包含隐藏文件和目录。 |
--no-ignore | 关闭 | 不遵循 .gitignore、.ignore 和 git exclude 文件。 |
--max-file-bytes N | 1048576 | read 完整返回、search 打开、stat 统计行数以及 write 接受的文件大小上限。 |
--max-results N | 200 | list 返回的条目数以及 search 返回的匹配数上限。 |
--max-chars N | 50000 | 单次 read 返回的文本字符数上限(最高为 200 000);超出时会在行边界处停止,并说明从何处继续。 |
--allowed-host HOST | 见下文 | 接受的 Host 标头,可重复指定。 |
--allowed-origin ORIGIN | 无 | 接受的 Origin 标头,需包含 scheme(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 客户端也可采用相同方式。
工具
共有七种工具,每种都是一个动词。所有路径均相对于根目录(. 或省略表示根目录)。
只有使用 --writable 时才会提供三个会修改文件的工具;只读服务会列出四个工具。
| 工具 | 参数 | 返回内容 | 注释 |
|---|---|---|---|
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 必须恰好出现一次(否则错误信息会说明出现次数)。仅支持文本文件。 | 具有破坏性,仅限 --writable |
move | from、to、overwrite?(false) | 新路径。在根目录内重命名或移动(也可以在根目录之间移动);除非设置 overwrite,否则不会替换已存在的目标。 | 具有破坏性,仅限 --writable |
每个工具都会设置 openWorldHint: false:它只会操作指定的文件夹,不会涉及其他内容。
list 和 search 使用 ripgrep 的遍历器 ignore:
除非另行指定 --no-ignore / --hidden,否则会跳过 .gitignore(即使不在 git 工作区内)、.ignore 和隐藏文件,并且绝不会跟随符号链接。正则表达式使用 regex crate:匹配时间为线性,不会发生灾难性回溯,编译后的大小上限为 1 MiB。Glob 会匹配工具显示的路径(*.rs 可匹配 src/main.rs)。
输出。 read 返回的文件内容会被框定为作者身份未知的文档(FrameKind::Document);列表、匹配结果和元数据会作为计算结果以 JSON 格式框定(FrameKind::Computed)。每次调用的帧 nonce 都不同,因此,即使文件中包含伪造的数据结束标记,也无法跳出代码块。拒绝操作时会返回工具错误(isError: true),并说明应如何处理。
多个根目录
--root 可以指定多次。只有一个根目录时,行为不变:路径相对于该根目录。
指定多个根目录时,每个路径都以根目录名称开头,而 . 是一个虚拟文件夹,其条目为各个根目录:
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);如果两个根目录名称相同,启动时会拒绝运行。在 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中都会被拒绝;指向根目录内部的符号链接则可正常使用。遍历器绝不会跟随链接,且会通过根句柄重新打开返回的每个路径,因此,遍历过程中被替换为逃逸链接的目录会被跳过,而不会被读取。 - 默认写入。 服务启动时为只读模式:
write、edit和move会从工具列表中移除,文件操作也会拒绝写入,除非操作人员传入--writable(或设置FOLDER_WRITABLE),这是 Emperor Profile P1.1 的要求。工具注释(readOnlyHint、destructiveHint)会告知客户端哪些工具会更改文件,以便客户端在运行前征求确认。 - 耗尽主机资源或上下文。 整个文件的读取会受
--max-file-bytes限制(按行范围读取会以流式方式进行,且返回内容不超过该限制),并受--max-chars字符数限制;search会跳过较大的文件,list和search会在达到--max-results后停止;除较小的图像外,不会返回二进制文件。 - 被网页访问。 绑定到环回地址时,
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
链接
- Crate: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,版本 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 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。