philipnee/mvmt
GitHub: philipnee/mvmt
一个基于 MCP 协议的本地文件安全访问层,通过显式挂载和精细化权限控制,让 AI 客户端安全地访问指定本地文件夹。
Stars: 0 | Forks: 1
# mvmt
**多卷挂载传输。**
mvmt 通过一个小巧、具权限控制的工具 API 暴露选定的本地文件夹。
将文件夹挂载到稳定路径下,例如 `/notes`、`/workspace` 或 `/research`,
然后允许客户端在这些挂载内搜索、列出、读取、写入或移除文件。
客户端永远不会获得完整的计算机访问权限。它们只能看到您允许的挂载和
操作。
```
client
|
v
mvmt
|
|-- /notes -> ~/Documents/Obsidian
|-- /workspace -> ~/code/mvmt
|-- /research -> ~/papers
```
mvmt **不是同步工具**。
mvmt **不是云存储**。
mvmt **不是通用文件系统服务器**。
它是一个本地优先的访问层,通过显式挂载、窄范围工具和按客户端分配的权限,
将您机器的特定部分暴露出来。

## 为什么会有 mvmt
许多工具需要受控地访问本地文件。
赋予工具广泛的文件系统访问权限是有风险的。将所有内容上传到云工作区通常是
不必要的。临时的本地服务器通常缺乏清晰的权限模型。
mvmt 采取了更狭窄的方法:
- 仅挂载您希望客户端看到的文件夹。
- 通过稳定的虚拟路径暴露这些文件夹。
- 给每个客户端分配独立的路径/操作权限。
- 将数据保留在您的机器上。
- 审计客户端的搜索、读取、写入和移除操作。
## 核心理念
### 统一的本地命名空间
客户端操作虚拟路径:
```
/notes
/workspace
/research
```
它们不需要知道这些文件夹在磁盘上的具体位置。
### 显式挂载
每次挂载将一个虚拟路径映射到一个真实的本地文件夹。
```
mounts:
- name: notes
path: /notes
root: /Users/you/Documents/Obsidian
writeAccess: false
```
### 按客户端分配权限
不同的客户端可以看到命名空间的不同部分。
```
clients:
- id: codex
permissions:
- path: /workspace/**
actions: [search, read, write]
- id: readonly-client
permissions:
- path: /notes/**
actions: [search, read]
```
### 默认只读
写入操作需要同时满足:
1. 客户端拥有该路径的 `write` 权限;并且
2. 挂载配置了 `writeAccess: true`。
受保护的路径,如 `.env`、`.claude/**` 或其他配置的模式,
不能被写入或移除。mvmt 还具有全局密钥路径拒绝名单,
针对 `.mvmt/**`、`.ssh/**`、`.aws/**`、`.kube/**` 等路径以及常见的
云/开发凭据文件。即使旧版配置中没有列出这些路径,它们也会被阻止。
## 快速开始
从当前检出的源码运行 mvmt:
```
npm install
npm run build
npm link
mvmt serve -i
```
当前名为 `mvmt` 的 npm 包尚未包含此 CLI 发布版。在包含 `mvmt` 可执行文件的
该包发布之前,请使用上述源码安装方式。
首次运行时,mvmt 会创建:
```
~/.mvmt/config.yaml
```
然后它会引导您完成:
- 添加本地文件夹挂载;
- 可选启用模式编辑器;
- 启动 MCP 服务器。
如果要在不更改已保存配置的情况下临时提供只读文件夹:
```
mvmt serve --path ~/Documents -i
```
至少需要启用一个挂载。如果未配置任何挂载,mvmt 将没有
数据可供提供服务。
## 示例设置
添加只读笔记挂载:
```
mvmt mounts add notes ~/Documents/Obsidian \
--mount-path /notes \
--read-only \
--description "Personal notes and project journals" \
--guidance "Search first. Read specific files before answering."
```
添加可写项目挂载:
```
mvmt mounts add workspace ~/code/mvmt \
--mount-path /workspace \
--write \
--protect ".env" \
--protect ".env.*" \
--protect ".claude/**" \
--description "mvmt source code and design docs" \
--guidance "Read README.md and docs before changing code."
```
然后重建索引并提供服务:
```
mvmt reindex
mvmt serve -i
```
## 状态
| 领域 | 状态 |
| --- | --- |
| 本地文件夹挂载 | 已支持 |
| 文本索引 | 作为 JSON 原型索引受到支持 |
| MCP 工具 | `search`、`list`、`read`、`write`、`remove` |
| 挂载管理 CLI | 已支持 |
| API 令牌路径权限 | 通过 `mvmt token add` 支持 |
| 本地可流式 HTTP | 在 `127.0.0.1` 上支持 |
| Stdio 模式 | 已支持 |
| 面向 Web 客户端的 OAuth/PKCE | 已支持,包括动态客户端注册 |
| 隧道模式 | 支持个人远程访问 |
| 模式编辑器插件 | 已支持 |
| 旧版代理连接器配置 | 为兼容性被 schema 接受,被仅挂载的 CLI 运行时忽略 |
| 管理 UI | 未发布 |
| API 令牌颁发 | 支持 Bearer 令牌客户端 |
| 远程 mvmt 挂载 | 未发布 |
| 二进制/PDF/图像索引 | 未发布 |
## 客户端兼容性
mvmt 可供 MCP 客户端、本地 HTTP 客户端和远程 Web 客户端通过
隧道模式使用。
| 客户端 | 传输方式 | 状态 | 认证方式 | 备注 |
| --- | --- | --- | --- | --- |
| Claude Desktop | stdio | 已支持 | 进程启动 | 从客户端配置运行其自己的 mvmt 进程 |
| Claude Code | Streamable HTTP | 已支持 | bearer token | 使用通过 `mvmt token add` 获取的作用域 API 令牌 |
| Codex CLI | Streamable HTTP | 已支持 | bearer token | 使用通过 `mvmt token add` 获取的作用域 API 令牌 |
| Cursor | Streamable HTTP | 预期支持 | bearer token | 行为取决于 Cursor 的 MCP 实现 |
| VS Code / Copilot | Streamable HTTP | 预期支持 | bearer token | 行为取决于 MCP 扩展 |
| claude.ai / ChatGPT web | 公共 HTTPS 隧道 | 支持的远程模式 | OAuth/PKCE | 需要可访问的隧道 URL |
| Raw HTTP / curl | Streamable HTTP | 仅用于调试 | bearer token | 必须遵循 MCP 会话初始化规则 |
大多数本地 HTTP 客户端需要:
```
URL: http://127.0.0.1:4141/mcp
Authorization: Bearer
```
在本地旧版模式下,`` 可以是 `mvmt token session` 中的内部会话令牌。
对于普通的作用域访问,请使用 `mvmt token add` 创建 API 令牌并改为使用该令牌。
远程 Web 客户端使用隧道 URL(通常以 `/mcp` 结尾),并通过 OAuth 2.1 + PKCE 进行授权。
mvmt 支持 RFC 7591 动态客户端注册。颁发的 OAuth 访问令牌在受众上
绑定到当前的 mvmt 资源,因此为一个 mvmt 实例生成的令牌无法用于对
另一个实例进行重放攻击。
Claude Desktop 则不同:它通过 stdio 启动 mvmt,因此没有 HTTP
监听器,也没有 bearer token 头。
## 工具接口
当配置了 `mounts[]` 时,mvmt 会暴露五个 MCP 工具:
| 工具 | 用途 | 所需权限 |
| --- | --- | --- |
| `search` | 搜索允许挂载中的已索引文本块 | `search` |
| `list` | 列出可见的挂载根目录或目录 | `read` |
| `read` | 按虚拟路径读取一个文本文件 | `read` |
| `write` | 创建或覆盖一个文本文件 | `write` |
| `remove` | 删除一个文本文件 | `write` |
重要行为:
- `list("/")` 返回可见的挂载根目录,包含描述、指导和写入访问状态。
- `search` 对已索引的文本块使用简单的关键词评分。
- `read` 和 `write` 仅支持文本。
- `write` 支持 `expected_hash`,以便客户端避免覆盖过时的读取内容。
- `remove` 永久删除文件。它不会删除目录。
- 非文本文件会在 `list` 中隐藏,被索引跳过,并被 `read`/`write` 拒绝。
受支持的类文本文件包括 Markdown、纯文本、JSON、YAML、TOML、CSV、
日志、Shell 脚本、HTML/CSS/XML 和常见的源代码扩展名。
超过 2 MiB 的文件会被索引跳过,并被直接文本读取拒绝。
## 配置
保存的配置位于:
```
~/.mvmt/config.yaml
```
查看配置:
```
mvmt config
```
验证配置:
```
mvmt doctor
```
管理挂载:
```
mvmt mounts list
mvmt mounts add
mvmt mounts edit
mvmt mounts remove
```
最小配置:
```
version: 1
server:
port: 4141
allowedOrigins: []
access: local
mounts:
- name: notes
type: local_folder
path: /notes
root: /Users/you/Documents/Obsidian
description: Personal notes and project journals.
guidance: Search first. Read specific files before answering.
exclude:
- .git/**
- node_modules/**
- .claude/**
- .mvmt/**
- .ssh/**
- .aws/**
protect:
- .env
- .env.*
- .claude/**
- .mvmt/**
- .ssh/**
- .aws/**
writeAccess: false
enabled: true
- name: workspace
type: local_folder
path: /workspace
root: /Users/you/code/mvmt
description: mvmt project source and design docs.
guidance: Read README.md and docs before changing code.
exclude:
- .git/**
- node_modules/**
- dist/**
protect:
- .env
- .env.*
- .claude/**
- .mvmt/**
- .ssh/**
- .aws/**
writeAccess: true
enabled: true
plugins:
- name: pattern-redactor
enabled: true
mode: redact
```
挂载字段:
| 字段 | 含义 |
| --- | --- |
| `name` | 稳定的小写挂载 ID,例如 `notes` |
| `path` | 对客户端可见的虚拟路径,例如 `/notes` |
| `root` | 磁盘上的本地文件夹 |
| `description` | 从 `list("/")` 返回的简短摘要 |
| `guidance` | 从 `list("/")` 返回的可选面向客户端的指导 |
| `exclude` | 在列出、读取、写入、移除和索引中隐藏的路径 |
| `protect` | 不能被写入或移除的路径 |
| `writeAccess` | 挂载级别的写入门控;默认为 `false` |
| `enabled` | 挂载是否处于活动状态 |
Obsidian 仓库只是一个本地文件夹挂载。在当前的仅挂载形态中,没有
特殊的 Obsidian 运行时连接器。
## API 令牌与策略
对于本地测试,当未配置 API 令牌时,mvmt 保持旧版行为:
内部会话 bearer 令牌可以访问所有已配置的挂载。会话
令牌存储在 `~/.mvmt/.session-token` 中,文件模式为 `600`。HTTP
`mvmt serve` 在其缺失时会创建它。
为了实现可重复的客户端访问,请创建作用域 API 令牌:
```
mvmt token add codex --read /notes --ttl 7d
mvmt token add codex --write /workspace --ttl 30d
```
`mvmt token add` 会打印一次明文令牌。mvmt 在配置中仅存储 scrypt
验证器。令牌默认在 30 天后过期;在创建或编辑令牌时,请使用诸如
`--ttl 30m`、`--ttl 7d` 或 `--ttl never` 的值。
如果客户端请求授权令牌,请粘贴打印出的 `mvmt_...`
值。如果 Web 客户端让您通过 OAuth 进行授权,请将相同的令牌粘贴到
mvmt 批准页面中。
一旦存在 API 令牌,`/mcp` 将变得严格:
- bearer 令牌必须与已配置的客户端 `tokenHash` 匹配;
- OAuth 访问令牌继承在批准页面上选择的 API 令牌身份;
- 会话令牌不再授予数据平面访问权限;
- 未知的 OAuth 客户端会被隔离,具有零权限。
隧道模式可以在没有 API 令牌的情况下启动,但 MCP 数据访问会拒绝
旧版会话令牌。添加 API 令牌以授予访问权限。仅用于临时调试,
设置 `MVMT_ALLOW_LEGACY_TUNNEL=1` 以允许通过隧道使用旧版会话令牌。
API 令牌权限是针对虚拟路径而非本地磁盘路径编写的。
底层配置字段当前名为 `clients[]`。
```
clients:
- id: codex
name: Codex CLI
description: Local Codex token
expiresAt: "2026-05-06T12:00:00.000Z"
auth:
type: token
# Verifier for the client API key.
# Do not store the plaintext key.
tokenHash: "scrypt:v1:..."
rawToolsEnabled: false
permissions:
- path: /workspace/**
actions: [search, read, write]
- path: /notes/**
actions: [search, read]
- id: readonly-client
name: Read-only client
auth:
type: token
tokenHash: "scrypt:v1:..."
rawToolsEnabled: false
permissions:
- path: /notes/**
actions: [search, read]
```
策略是累加的。只有当解析后的 API 令牌对目标虚拟路径
具有所需的操作权限时,调用才会成功。
对于写入操作,挂载本身也必须具有 `writeAccess: true`,且目标
不能匹配 `protect`。
## 命令
| 命令 | 描述 |
| --- | --- |
| `mvmt serve` | 如果需要,配置 mvmt,然后启动 MCP 服务器 |
| `mvmt serve -i` | 使用交互式控制提示启动 |
| `mvmt serve --path ` | 临时提供一个只读文件夹 |
| `mvmt reindex` | 重建文本索引 |
| `mvmt mounts` | 列出已配置的挂载 |
| `mvmt mounts --json` | 以 JSON 格式列出已配置的挂载 |
| `mvmt mounts add [name] [root]` | 添加本地文件夹挂载 |
| `mvmt mounts edit [name]` | 编辑挂载 |
| `mvmt mounts remove [name]` | 移除挂载 |
| `mvmt mounts remove [name] --yes` | 无需交互式确认即可移除挂载 |
| `mvmt config` | 显示已保存的配置摘要 |
| `mvmt config setup` | 重新运行引导式设置 |
| `mvmt doctor` | 验证配置和启动先决条件 |
| `mvmt token` | 列出作用域 API 令牌 |
| `mvmt token add [id]` | 创建或更新作用域 API 令牌 |
| `mvmt token edit [id]` | 编辑作用域 API 令牌 |
| `mvmt token rotate [id]` | 替换作用域 API 令牌密钥 |
| `mvmt token remove [id]` | 移除作用域 API 令牌 |
| `mvmt token session` | 用于内部会话令牌的隐藏兼容性命令 |
| `mvmt tunnel` | 显示隧道状态 |
| `mvmt tunnel config` | 选择并保存隧道命令 |
| `mvmt tunnel start` | 启动已配置的隧道 |
| `mvmt tunnel refresh` | 重启隧道并打印新的 URL |
| `mvmt tunnel stop` | 停止公共隧道暴露 |
| `mvmt tunnel disable` | 将配置切换回仅本地访问 |
| `mvmt tunnel logs` | 显示最近的隧道输出 |
| `mvmt tunnel logs stream` | 流式传输实时隧道输出 |
| `mvmt --version` | 打版本并检查更新 |
交互模式接受相同的命令组:
```
> mounts
> mounts add
> mounts edit
> mounts remove
> config
> config setup
> token
> token add
> token edit
> token rotate
> token remove
> tunnel
> tunnel refresh
```
## 索引生命周期
在 `mvmt serve` 时,mvmt 会立即开始提供服务并在后台重建文本索引。
在重建完成之前,搜索可能会返回较少的结果。
请使用:
```
mvmt reindex
```
在通过 mvmt 外部更改文件或编辑挂载配置后使用。
通过 mvmt 执行的写入和移除操作会自动重建索引。
当前索引是配置文件旁边的一个 JSON 文件。SQLite 和增量
文件监控已计划但尚未发布。
## 安全模型
每个数据操作都受路径和操作的门控。
- HTTP 模式绑定到 `127.0.0.1`,而不是 `0.0.0.0`。
- HTTP `/mcp` 和 `/health` 需要身份验证。
- 会话令牌存储在 `~/.mvmt/.session-token` 中,模式为 `600`。
- 挂载根目录在访问前会被解析。
- 超出挂载根目录的路径遍历会被拒绝。
- `exclude` 会在列出、读取、写入、移除和索引中隐藏路径。
- `protect` 会阻止对敏感路径(如 `.env` 和 `.claude/**`)的写入/移除。
- 全局密钥路径,如 `.mvmt/**`、`.ssh/**`、`.aws/**`、`.kube/**`
和常见的凭据文件,无论每个挂载的配置如何,都会被拒绝。
- 写入操作需要同时具备客户端 `write` 权限和挂载的 `writeAccess`。
- 一旦存在 API 令牌/OAuth 策略,未知的 OAuth 客户端将被隔离。
- 浏览器来源检查会阻止来自非本地来源的随发浏览器请求。
- 可选的模式编辑器可以在输出到达客户端之前,对配置的正则表达式匹配发出警告、编辑或阻止。
- 工具调用会附加到 `~/.mvmt/audit.log` 中。
身份验证控制谁可以连接。挂载和客户端策略控制他们可以访问什么。
## 远程访问
mvmt 是本地优先的。
远程客户端无法直接访问 `127.0.0.1`,因此隧道模式可以发布一个
公共 HTTPS URL。
远程访问检查清单:
1. 仅挂载远程客户端需要的文件夹。
2. 优先使用只读挂载。
3. 准备好时启动隧道。如果没有 API 令牌,公共端点
可以访问,但无法读取数据。
4. 使用 `mvmt token add` 创建作用域 API 令牌。
5. 对秘密和私有文件夹使用 `protect`。
6. 在测试新的远程客户端时关注 `~/.mvmt/audit.log`。
7. 使用稳定的隧道 URL 以实现可重复的 OAuth 流程。
快速隧道虽然方便,但是临时的。
## 当前限制
- 本地文件夹是唯一已发布的挂载提供者。
- mvmt 当前作为单实例运行。
- 远程 mvmt 挂载未发布。
- 活跃的 CLI 运行时仅限挂载。
- 旧版代理连接器配置仍会为兼容性进行解析,但代理连接器不会作为运行时工具加载。
- 搜索是原型关键词评分,而不是语义嵌入搜索。
- PDF、图像、归档文件和其他二进制文件会被跳过。
- 尚无文件监控器。
- API 令牌轮换和管理 UI 未发布。
- mvmt 不会跨机器同步、复制或解决冲突。
## 近期计划
近期:
- 基于 SQLite 的文本索引。
- 增量索引更新。
- 更好的挂载和 API 令牌管理命令。
- 用于客户端密钥、路径权限、审计和挂载可见性的管理 UI。
稍后:
- 远程 mvmt 挂载。
- 在相同的 `search`/`list`/`read`/`write`/`remove` 接口背后提供多个挂载提供者。
- `resolve(path) -> AccessPlan`,用于将虚拟路径路由到本地或远程后端。
## 项目文档
- [安装指南](docs/setup.md)
- [客户端配置](docs/client-setup.md)
- [文本索引原型](docs/text-index-prototype.md)
- [远程访问](docs/remote-access.md)
- [审计日志](docs/audit-log.md)
- [故障排除](docs/troubleshooting.md)
- [架构](docs/architecture.md)
- [安全策略](SECURITY.md)
- [贡献](CONTRIBUTING.md)
- [更新日志](CHANGELOG.md)
## 贡献
在项目早期阶段欢迎贡献。
保持更改专注且具有安全意识。请阅读 [CONTRIBUTING.md](CONTRIBUTING.md)
并通过 [SECURITY.md](SECURITY.md) 报告漏洞。
## 许可证
MIT
标签:API网关, HTTP工具, MITM代理, Python开发, 代理服务, 安全沙箱, 客户端权限, 数据隐私, 文件共享, 文件搜索, 文件系统隔离, 文件读写, 文档管理, 文档结构分析, 本地优先, 本地开发环境, 本地文件访问, 本地服务器, 权限控制, 目录映射, 细粒度访问控制, 网络安全审计, 虚拟挂载, 访问控制列表(ACL), 路径映射