🚀 Files MCP Server
Stdio MCP服务器,用于沙盒化文件访问 — 可浏览目录、读取文件、搜索内容,并通过校验和验证安全地编辑文件。
作者:overment
⚠️ 重要提示
此服务器为AI代理提供文件系统访问权限。尽管它被沙盒化到特定目录,但请始终:
- 在确认更改之前,仔细审查工具输出
- 使用
dryRun=true 预览破坏性操作
- 对重要文件进行备份
- 将
FS_ROOTS 设置为仅允许代理访问的目录
🚀 快速开始
1. 安装
cd files-mcp
bun install
2. 配置
创建 .env 文件:
# 代理可以访问的目录,用逗号分隔
FS_ROOTS=/path/to/vault,/path/to/docs
# 或者只指定单个目录
# FS_ROOT=/path/to/vault
# 可选配置
LOG_LEVEL=info
MAX_FILE_SIZE=1048576
3. 运行
bun dev
4. 连接到客户端
Claude Desktop / Cursor:
{
"mcpServers": {
"filesystem": {
"command": "bun",
"args": ["run", "/absolute/path/to/files-mcp/src/index.ts"],
"env": {
"FS_ROOTS": "/Users/you/vault,/Users/you/docs"
}
}
}
}
✨ 主要特性
- ✅ 目录浏览 — 以树状视图显示文件数量、大小和时间戳
- ✅ 文件读取 — 带行号的文件内容,并提供校验和以确保安全编辑
- ✅ 文件查找 — 按文件名模式(
*.md、config.json)进行递归搜索
- ✅ 内容搜索 — 支持字面量、正则表达式、模糊模式匹配,可选择忽略大小写
- ✅ 预设模式 — 内置Obsidian模式(维基链接、标签、任务、标题)
- ✅ 安全编辑 — 校验和验证、预运行预览、统一差异显示
- ✅ 批量操作 — 支持
replaceAll 对文件进行批量重命名
- ✅ 多挂载支持 — 可将多个目录作为虚拟挂载点进行访问
- ✅ 沙盒化 — 无法访问配置挂载点之外的路径
设计原则
- 先浏览再编辑:代理在修改文件之前必须先读取文件(获取校验和和行号)
- 先预览再应用:
dryRun=true 可精确显示即将发生的更改
- 清晰反馈:每个响应都包含下一步操作提示和错误恢复建议
- 默认精简显示:仅当
details=true 时才显示文件详细信息(大小、修改时间)
- 单挂载优化:当只配置一个挂载点时,
fs_read(".") 直接显示内容
📚 详细文档
动机
传统的文件操作需要精确的路径和确切的内容,而大语言模型(LLMs)在这方面存在困难。此服务器旨在让AI代理能够:
- 先探索 — 在执行操作之前了解目录结构
- 按名称或内容查找 — 无需知道确切路径即可定位文件
- 安全编辑 — 校验和验证可防止过时的覆盖操作
- 预览更改 — 预运行模式可在应用更改之前显示差异
- 从错误中恢复 — 提示信息可引导代理纠正错误
结果是,代理可以可靠地管理你的Obsidian库、文档、笔记或任何基于文本的文件集合。
MCP Bundle (MCPB)
此服务器也可以作为 MCP Bundle (.mcpb) 使用,可在Claude Desktop、Alice和其他支持MCPB的应用程序中一键安装。
什么是MCPB?
MCP Bundles 是一种zip存档,包含本地MCP服务器和描述服务器及其功能的 manifest.json 文件。这种格式使最终用户可以一键安装本地MCP服务器,无需手动配置。
从MCPB安装
- 下载
files-mcp.mcpb 文件
- 使用兼容的应用程序(Claude Desktop、Alice等)打开它
- 在提示时配置 根目录 — 这是代理可以访问的目录
- 完成!服务器已安装并可以使用
manifest.json
该清单定义了:
- 服务器配置 — 命令、参数、环境变量
- 工具 —
fs_read 和 fs_write 及其描述
- 用户配置 — 在安装过程中提示用户配置
FS_ROOT 目录
{
"manifest_version": "0.2",
"name": "files-mcp",
"version": "1.0.0",
"server": {
"type": "node",
"entry_point": "dist/index.js",
"mcp_config": {
"command": "node",
"args": ["${__dirname}/dist/index.js"],
"env": {
"FS_ROOT": "${user_config.FS_ROOT}"
}
}
},
"user_config": {
"FS_ROOT": {
"type": "directory",
"title": "Root Directory",
"description": "The directory the agent will have access to.",
"required": true
}
}
}
${user_config.FS_ROOT} 语法会在运行时将用户选择的目录注入到服务器的环境中。
服务器说明(模型可见内容)
🔒 沙盒化文件系统 — 此工具只能访问特定的挂载目录。
您不能访问任意系统路径,如 /Users 或 C:\。
始终先使用 fs_read(".") 查看可用的挂载点。
⚠️ 在回答有关文件内容的问题之前,务必先读取文件。
⚠️ 在修改文件之前,务必先读取文件(您需要校验和)。
强制工作流程:
1. fs_read(".") → 查看可用的挂载点
2. fs_read("path/file.md") → 获取内容和校验和
3. 使用 dryRun=true 调用 fs_write → 预览差异
4. 使用 dryRun=false 和校验和调用 fs_write → 应用更改
5. 验证响应中的差异是否符合您的预期
工具
fs_read
浏览目录、读取文件、按名称查找文件或搜索内容。
输入:
{
path: string;
find?: string;
pattern?: string;
patternMode?: "literal" | "regex" | "fuzzy";
caseInsensitive?: boolean;
preset?: "wikilinks" | "tags" | "tasks" | "tasks_open" | "tasks_done"
| "headings" | "codeblocks" | "frontmatter";
depth?: number;
details?: boolean;
lines?: string;
context?: number;
maxFiles?: number;
maxMatches?: number;
}
输出:
{
success: boolean;
path: string;
type: "directory" | "file" | "search";
tree?: {
entries: Array<{ path, kind, children?, size?, modified? }>;
summary: string;
};
content?: {
text: string;
checksum: string;
totalLines: number;
};
matches?: Array<{ file, line, column, text, context }>;
matchCount?: number;
hint: string;
}
fs_write
创建、修改或删除文件,并具备安全特性。
输入:
{
path: string;
operation: "create" | "update" | "delete";
content?: string;
lines?: string;
pattern?: string;
patternMode?: "literal" | "regex" | "fuzzy";
caseInsensitive?: boolean;
action?: "replace" | "insert_before" | "insert_after" | "delete_lines";
content?: string;
replaceAll?: boolean;
checksum?: string;
dryRun?: boolean;
}
输出:
{
success: boolean;
path: string;
operation: "create" | "update" | "delete";
applied: boolean;
result?: {
action: string;
linesAffected?: number;
newChecksum?: string;
diff?: string;
};
error?: {
code: string;
message: string;
recoveryHint?: string;
};
hint: string;
}
预设模式(Obsidian/Markdown)
内置用于常见搜索的模式:
| 预设模式 |
查找内容 |
wikilinks |
[[Note]] 和 [[Note|Display]] |
tags |
#tag 和 #nested/tag |
tasks |
- [ ] 和 - [x](所有任务) |
tasks_open |
- [ ](未完成任务) |
tasks_done |
- [x](已完成任务) |
headings |
# 到 ###### 标题 |
codeblocks |
``` 代码块 |
frontmatter |
YAML --- 块 |
示例:
{ "path": ".", "preset": "tasks_open" }
示例
1. 浏览库
{ "path": "." }
响应:
18 项(15 个文件,3 个目录)
- Core/
- Projects/
- Books/
- map.md
- inbox.md
...
提示:"显示 'vault' 的内容。对任何路径使用 fs_read 以深入探索。"
2. 查找文件
{ "path": ".", "find": "*.md" }
响应:
找到 42 个匹配 "*.md" 的项
- Core/Values.md
- Core/Process.md
- Projects/Alice.md
...
提示:"找到 42 个匹配的文件。对特定路径使用 fs_read 以查看其内容。"
3. 读取文件
{ "path": "Core/Values.md" }
响应:
文件读取完成。校验和:a1b2c3d4e5f6。
1| # Values
2|
3| ## Integrity
4| Be honest, even when it's hard.
5|
6| ## Growth
7| Learn something new every day.
...
提示:"要编辑此文件,请使用带校验和 a1b2c3d4e5f6 的 fs_write。"
4. 查找所有未完成任务
{ "path": ".", "preset": "tasks_open" }
响应:
在所有挂载点的 42 个文件中找到 7 个匹配项。
- Projects/Alice.md:12 — "- [ ] Implement search"
- Projects/Alice.md:15 — "- [ ] Add tests"
- inbox.md:3 — "- [ ] Review PR"
...
5. 替换文本(先预览)
{
"path": "Core/Values.md",
"operation": "update",
"pattern": "Be honest",
"action": "replace",
"content": "Act with integrity",
"checksum": "a1b2c3d4e5f6",
"dryRun": true
}
响应:
预运行 — 未应用任何更改。
--- a/Core/Values.md
+++ b/Core/Values.md
@@ -3,1 +3,1 @@
-Be honest, even when it's hard.
+Act with integrity, even when it's hard.
提示:"查看上述差异。使用 dryRun=false 运行以应用更改。"
6. 批量重命名维基链接
{
"path": "Projects/Alice.md",
"operation": "update",
"pattern": "[[Old Name]]",
"action": "replace",
"content": "[[New Name]]",
"replaceAll": true,
"dryRun": true
}
响应:
预运行 — 将在第 5、12、28 行替换 3 处。
7. 将任务标记为已完成
{
"path": "inbox.md",
"operation": "update",
"pattern": "- [ ] Review PR",
"action": "replace",
"content": "- [x] Review PR",
"checksum": "xyz789"
}
响应:
替换了 1 行。新校验和:abc123。
提示:"上述差异显示了更改内容。"
配置
| 变量 |
默认值 |
描述 |
FS_ROOTS |
. |
代理可以访问的目录,用逗号分隔 |
FS_ROOT |
. |
单个路径(向后兼容) |
MCP_NAME |
files-mcp |
服务器名称 |
MCP_VERSION |
1.0.0 |
服务器版本 |
LOG_LEVEL |
info |
日志级别:debug、info、warning、error |
MAX_FILE_SIZE |
1048576 |
最大文件大小(字节)(1MB) |
多挂载设置
访问多个目录:
FS_ROOTS=/Users/me/vault,/Users/me/projects,/Users/me/notes
每个路径将成为一个以文件夹名称命名的挂载点:
vault/ → /Users/me/vault
projects/ → /Users/me/projects
notes/ → /Users/me/notes
客户端配置
Claude Desktop
{
"mcpServers": {
"filesystem": {
"command": "bun",
"args": ["run", "/path/to/files-mcp/src/index.ts"],
"env": {
"FS_ROOTS": "/Users/me/vault"
}
}
}
}
Cursor
{
"filesystem": {
"command": "bun",
"args": ["run", "/path/to/files-mcp/src/index.ts"],
"env": {
"FS_ROOTS": "/Users/me/vault"
}
}
}
开发
bun dev
bun test
bun run typecheck
bun run lint
bun run build
bun run inspector
架构
src/
├── index.ts # 入口点:标准输入输出传输
├── config/
│ ├── env.ts # 环境配置和挂载解析
│ └── metadata.ts # 工具描述
├── core/
│ ├── capabilities.ts # 服务器功能
│ └── mcp.ts # McpServer构建器
├── tools/
│ ├── index.ts # 工具注册
│ ├── fs-read.tool.ts # 读取、浏览、搜索
│ └── fs-write.tool.ts # 创建、更新、删除
├── lib/
│ ├── checksum.ts # SHA256校验和
│ ├── diff.ts # 统一差异生成
│ ├── filetypes.ts # 文本/二进制文件检测
│ ├── ignore.ts # .gitignore支持
│ ├── lines.ts # 行操作
│ ├── paths.ts # 多挂载路径解析
│ └── patterns.ts # 模式匹配和预设
└── utils/
├── errors.ts # 错误处理工具
└── logger.ts # 日志记录
故障排除
| 问题 |
解决方案 |
| "SANDBOXED FILESYSTEM: Absolute paths not allowed" |
使用挂载点内的相对路径。先使用 fs_read(".") 查看可用的挂载点。 |
| "Path does not match any mount" |
检查 FS_ROOTS 是否设置正确。路径必须以挂载点名称开头(例如,vault/notes.md)。 |
| "CHECKSUM_MISMATCH" |
自读取文件后,文件已更改。使用 fs_read 重新读取以获取最新内容。 |
| "PATTERN_NOT_FOUND" |
模式在文件中不存在。尝试 patternMode="fuzzy" 或先读取文件。 |
| "MULTIPLE_MATCHES" |
模式匹配到多个位置。使用 replaceAll=true 或更具体的模式。 |
| 二进制文件错误 |
只能读取和写入文本文件。检查文件扩展名。 |
| 单挂载仍显示 "docs" |
更改 FS_ROOTS 后,重启MCP服务器。 |
📄 许可证
MIT