内容
# RavenDB MCP 服务器
一款 MCP(模型上下文协议)服务器,允许 Claude Code 与您的 RavenDB 数据库交互 — 探索集合和架构,运行 RQL 查询,检查和创建索引,读取统计数据 — 具有安全优先的设计:
- **读取操作免费。** 查询、采样、检查任何内容。
- **写入操作需要开发人员批准。** 每个数据或索引更改必须先预览,写入工具本身始终会触发 Claude Code 的交互式权限提示。
- **删除操作是不可能的。** 没有删除工具,每个间接删除向量(补丁脚本 `del()`、`deleteCounter()`、时序 `.delete()`、`@expires` 过期元数据)都被 AST-based 脚本净化器阻止。
## 安装
需要 Node.js ≥ 20。
```
npm install
npm run build
```
## 注册到 Claude Code — 定义您的环境
在您要使用的项目中创建一个 `.mcp.json` 文件(参见 `.mcp.json.example`)。您可以定义最多两个环境 — **开发环境(dev)** 和 **生产环境(prod)** — 每个环境都有自己的服务器 URL、默认数据库和(每个环境)客户端证书。每个团队成员都设置自己的地址:
```json
{
"mcpServers": {
"ravendb": {
"command": "node",
"args": ["C:\\path\\to\\ravendb-mcp-server\\dist\\index.js"],
"env": {
"RAVENDB_DEV_URLS": "http://your-dev-server:8080",
"RAVENDB_DEV_DATABASE": "YourDevDatabase",
"RAVENDB_PROD_URLS": "https://your-prod-server.example.com",
"RAVENDB_PROD_DATABASE": "YourProdDatabase",
"RAVENDB_PROD_CERT_PATH": "C:\\path\\to\\prod-client-cert.pfx",
"RAVENDB_PROD_CERT_PASSWORD": "your-cert-password"
}
}
}
}
```
任一环境都可能被省略(例如,仅在 prod 凭证不可用时省略 dev)。安全(https)服务器 **需要** 匹配的 `*_CERT_PATH` — 否则服务器拒绝启动。会话从 `RAVENDB_DEFAULT_ENV` 开始(默认为 `dev`)。
### 在会话中选择服务器和数据库
Claude Code 的 `/mcp` 菜单没有每服务器设置 UI,因此选择通过两个工具进行 — 只需告诉 Claude Code 您想要的:
- **`read_environments`** — 列出 dev/prod,标记哪些是生产环境,以及每个可达服务器的数据库列表(“我有哪些环境?”)。
- **`use_connection`** — 切换活动环境和数据库用于会话(“切换到 prod,数据库 X”)。此工具故意 **不被允许**,因此每次切换都会显示权限提示和参数。
### 生产环境安全
- 切换到 prod 会打印一个醒目的 `⚠️⚠️ 生产环境数据库 ⚠️⚠️` 横幅,并且 **每个** 预览、批准指令、诱导消息和写入结果都会重复此横幅 — 您无法在不看到此横幅的情况下批准 prod 更改。
- **默认情况下,prod 是只读的。** 写入/预览工具在开发人员明确解锁会话之前会在 prod 上被拒绝:`use_connection` 带有 `allowProdWrites: true`(在针对 dev 时被拒绝,因此不能凭空创建)。任何后续切换都会重新锁定。
- 每次连接切换都会使所有待定的写入确认令牌失效,并且令牌绑定到它们预览的环境 — 在 dev 上批准的 diff 不能授权 prod 上的相同写入。
### 推荐的权限允许列表
将以下内容添加到消费项目的 `.claude/settings.json` 中,以便在 **仍需要交互式批准** 的情况下允许读取工具运行:
```json
{
"permissions": {
"allow": [
"mcp__ravendb__read_environments",
"mcp__ravendb__read_server_info",
"mcp__ravendb__read_databases",
"mcp__ravendb__read_database_stats",
"mcp__ravendb__read_collections",
"mcp__ravendb__read_collection_sample",
"mcp__ravendb__read_document",
"mcp__ravendb__read_query",
"mcp__ravendb__read_indexes",
"mcp__ravendb__read_index_definition",
"mcp__ravendb__read_index_stats",
"mcp__ravendb__read_index_errors",
"mcp__ravendb__read_indexing_status",
"mcp__ravendb__read_ai_tasks",
"mcp__ravendb__read_ai_task",
"mcp__ravendb__read_essential_stats",
"mcp__ravendb__read_detailed_stats",
"mcp__ravendb__read_database_health",
"mcp__ravendb__read_ongoing_tasks",
"mcp__ravendb__read_subscriptions",
"mcp__ravendb__read_backup_status",
"mcp__ravendb__read_topology",
"mcp__ravendb__read_database_settings",
"mcp__ravendb__preview_put_document",
"mcp__ravendb__preview_patch_document",
"mcp__ravendb__preview_patch_by_query",
"mcp__ravendb__preview_put_index",
"mcp__ravendb__preview_update_ai_task",
"mcp__ravendb__preview_toggle_ai_task"
]
}
}
```
**永远不要允许列出 `write_*` 工具或 `use_connection`** (并且永远不要整个服务器作为 `mcp__ravendb` 允许)。这些调用上的交互式提示是人类批准的关口。
## 环境变量
每个环境(`DEV` / `PROD` — 至少配置一个):
| 变量名 | 含义 |
|---|---|
| `RAVENDB_DEV_URLS` / `RAVENDB_PROD_URLS` | 以逗号分隔的服务器 URL |
| `RAVENDB_DEV_DATABASE` / `RAVENDB_PROD_DATABASE` | 默认数据库(回退到 `RAVENDB_DATABASE`) |
| `RAVENDB_DEV_CERT_PATH` / `RAVENDB_PROD_CERT_PATH` | `.pfx` 客户端证书 — **需要 https URL** |
| `RAVENDB_DEV_CERT_PASSWORD` / `RAVENDB_PROD_CERT_PASSWORD` | 证书密码 |
| `RAVENDB_DEV_CA_PATH` / `RAVENDB_PROD_CA_PATH` | 可选 CA 包 |
全局:
| 变量名 | 默认值 | 含义 |
|---|---|---|
| `RAVENDB_DEFAULT_ENV` | `dev` | 会话开始的环境 |
| `RAVENDB_URLS` / `RAVENDB_DATABASE` / `RAVENDB_CERT_*` | — | 开发环境的旧别名 |
| `RAVENDB_MCP_READONLY` | `false` | `true` 禁用所有预览/写入工具(覆盖会话级 prod 锁定) |
| `RAVENDB_ALLOW_SCRIPT_PUT` | `false` | 允许补丁脚本中的 `put()` |
| `RAVENDB_MAX_RESULTS` | `50` | 默认查询结果限制(硬上限 200) |
| `RAVENDB_APPROVAL_TTL_SECONDS` | `300` | 预览令牌生命周期 |
## 工具
**读取(15):** `read_environments` (dev/prod + 数据库列表),`read_server_info`,`read_databases`,`read_database_stats`,`read_collections`,`read_collection_sample` (带有架构推断),`read_document`,`read_query` (仅限 RQL 查询,带参数和统计信息),`read_indexes`,`read_index_definition`,`read_index_stats`,`read_index_errors`,`read_indexing_status`,`read_ai_tasks` (AI 中心:嵌入式生成 + GenAI 任务),`read_ai_task`。
**连接(1):** `use_connection` — 切换会话的环境/数据库(始终提示;重新锁定 prod 写入;使待定令牌失效)。
**性能诊断(8):** `read_essential_stats`,`read_detailed_stats` (比较交换/身份计数),`read_database_health` (活动探测),`read_ongoing_tasks` (所有任务类型 — ETL,复制,备份,订阅,AI — 而不仅仅是 AI 中心),`read_subscriptions` (通过 `lastBatchAckTime` / `lastClientConnectionTime` 的工作线程陈旧性),`read_backup_status` (实际持续时间和每个目标的上传大小),`read_topology` (集群节点/角色或每个数据库的节点分配),`read_database_settings` (有效的运行时配置)。
不可用 — `ravendb` Node 客户端(与 .NET 客户端不同)不公开 IO 度量操作,存储报告,每个索引的性能时间线,每个 ETL 的性能统计或许可/内存统计操作。这些操作需要调用未记录的 Studio-only HTTP 端点,而此服务器不执行此操作。
**预览(6,只读):** `preview_put_document`,`preview_patch_document`,`preview_patch_by_query`,`preview_put_index`。每个返回一个人类可读的 diff/摘要以及确切的待定更改和一次性 `confirmationToken`。两个补丁预览在 **RavenDB 服务器端测试模式** (`PATCH ...&test=true` — 不会持久化)下执行脚本并返回实际的前后文档以及行 diff;基于集合的预览对最多 3 个受影响的文档执行此操作,以及总共受影响的计数。运行时出错的脚本会使预览失败,因此损坏的补丁永远不会进入批准阶段。
**写入(6,需要批准):** `write_put_document`,`write_patch_document`,`write_patch_by_query`,`write_put_index`,`write_update_ai_task`,`write_toggle_ai_task`。每个都需要与其匹配的预览的令牌,带有 **字节相同的有效载荷** — 任何更改都会使令牌失效。补丁脚本在执行时重新验证。
**AI 中心:** `read_ai_tasks` / `read_ai_task` 列表和检查嵌入式生成和 GenAI ETL 任务。`preview_update_ai_task` → `write_update_ai_task` 更新任务配置(客户端验证;每个嵌入式脚本 — GenAI 转换,GenAI updateScript,嵌入式转换 — 通过相同的删除阻止净化器)。`preview_toggle_ai_task` → `write_toggle_ai_task` 运行(启用)或停止(禁用)任务;预览提示启用会产生 AI 模型 API 成本,并且 GenAI 任务会更新匹配的文档。**不支持创建或删除 AI 任务** — 永远不会导入 `DeleteOngoingTaskOperation`;禁用是可逆的并且不是删除。
## 安全模型
三个独立层:
1. **没有删除功能。** 代码库中任何地方都不导入删除操作。补丁脚本使用 JavaScript AST (acorn)解析,如果它们包含 `del()`、`deleteCounter()`、任何 `.delete()` 调用、计算成员调用 (`obj[expr]()`)、`eval`/`Function`/`globalThis` 或 `@expires` 过期密钥,则会被拒绝。无法解析的脚本会被拒绝(关闭失败)。`read_query` 拒绝 `update { }` 块。
2. **Claude Code 权限提示。** `write_*` 工具被注释为非只读/破坏性,并且永远不会被允许列出,因此开发人员会用可见的参数物理批准每个写入。
3. **预览令牌。** 写入操作仅在具有新鲜的、单次使用的令牌绑定(SHA-256)到确切的预览有效载荷时执行 — 保证 diff/影响计数预览出现在对话之前写入。已知的限制:模型传递令牌,因此绑定保证 *预览前写入*,而非由其本身的人类批准 — 那就是第 2 层的作用。
覆盖保护:`write_put_document` 拒绝覆盖现有文档,除非提供预览的更改向量,因此无法静默丢失并发更改。
## 开发
```
npm test # 安全模块的单元测试
npm run inspect # MCP 检查器针对已构建的服务器
```