Content
# RavenDB MCP Server
An MCP (Model Context Protocol) server that lets Claude Code work against your RavenDB databases — explore collections and schema, run RQL queries, inspect and create indexes, read stats — with a safety-first design:
- **Reads are free.** Query, sample, inspect anything.
- **Writes require developer approval.** Every data or index change must be previewed first, and the write tool itself always triggers Claude Code's interactive permission prompt.
- **Deletion is impossible.** No delete tool exists, and every indirect deletion vector (patch-script `del()`, `deleteCounter()`, timeseries `.delete()`, `@expires` expiration metadata) is blocked by an AST-based script sanitizer.
## Setup
Requires Node.js ≥ 20.
```
npm install
npm run build
```
## Registering with Claude Code — defining your environments
Create a `.mcp.json` in the project where you want to use it (see `.mcp.json.example`). You define up to two environments — **dev** and **prod** — each with its own server URLs, default database, and (per environment) client certificate. Every team member sets their own addresses:
```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"
}
}
}
}
```
Either environment may be omitted (e.g. only dev while prod credentials aren't available yet). Secured (https) servers **require** the matching `*_CERT_PATH` — the server refuses to start otherwise. The session starts on `RAVENDB_DEFAULT_ENV` (default: `dev`).
### Choosing the server & database in a session
Claude Code's `/mcp` menu has no per-server settings UI, so selection happens through two tools — just tell Claude what you want:
- **`read_environments`** — lists dev/prod, flags which is PRODUCTION, and live-lists the databases on each reachable server ("what environments do I have?").
- **`use_connection`** — switches the active environment + database for the session ("switch to prod, database X"). This tool is intentionally NOT allowlisted, so every switch shows you a permission prompt with the arguments.
### Production safety
- Switching to prod prints a loud `⚠️⚠️ PRODUCTION DATABASE ⚠️⚠️` banner, and **every** write preview, approval instruction, elicitation message, and write result repeats it — you cannot approve a prod change without seeing it.
- **Prod is read-only by default.** Write/preview tools refuse on prod until the developer explicitly unlocks the session: `use_connection` with `allowProdWrites: true` (rejected when targeting dev, so the flag can't be cargo-culted). Any subsequent switch re-locks.
- Every connection switch invalidates all pending write confirmation tokens, and tokens are bound to the environment they were previewed on — a diff approved against dev can never authorize the same write on prod.
### Recommended permission allowlist
Add this to the consuming project's `.claude/settings.json` so read tools run without prompts while **every write still requires your interactive approval**:
```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"
]
}
}
```
**Never allowlist the `write_*` tools or `use_connection`** (and never allowlist the server wholesale as `mcp__ravendb`). The interactive prompt on those calls is the human-approval gate.
## Environment variables
Per environment (`DEV` / `PROD` — configure at least one):
| Variable | Meaning |
|---|---|
| `RAVENDB_DEV_URLS` / `RAVENDB_PROD_URLS` | Comma-separated server URLs |
| `RAVENDB_DEV_DATABASE` / `RAVENDB_PROD_DATABASE` | Default database (falls back to `RAVENDB_DATABASE`) |
| `RAVENDB_DEV_CERT_PATH` / `RAVENDB_PROD_CERT_PATH` | `.pfx` client certificate — **required for https URLs** |
| `RAVENDB_DEV_CERT_PASSWORD` / `RAVENDB_PROD_CERT_PASSWORD` | Certificate password |
| `RAVENDB_DEV_CA_PATH` / `RAVENDB_PROD_CA_PATH` | Optional CA bundle |
Global:
| Variable | Default | Meaning |
|---|---|---|
| `RAVENDB_DEFAULT_ENV` | `dev` | Environment the session starts on |
| `RAVENDB_URLS` / `RAVENDB_DATABASE` / `RAVENDB_CERT_*` | — | Legacy aliases for the dev environment |
| `RAVENDB_MCP_READONLY` | `false` | `true` disables all preview/write tools (supersedes the session-level prod lock) |
| `RAVENDB_ALLOW_SCRIPT_PUT` | `false` | Allow `put()` inside patch scripts |
| `RAVENDB_MAX_RESULTS` | `50` | Default query result limit (hard cap 200) |
| `RAVENDB_APPROVAL_TTL_SECONDS` | `300` | Preview-token lifetime |
## Tools
**Read (15):** `read_environments` (dev/prod + live database lists), `read_server_info`, `read_databases`, `read_database_stats`, `read_collections`, `read_collection_sample` (with schema inference), `read_document`, `read_query` (read-only RQL with parameters and statistics), `read_indexes`, `read_index_definition`, `read_index_stats`, `read_index_errors`, `read_indexing_status`, `read_ai_tasks` (AI Hub: Embeddings Generation + GenAI tasks), `read_ai_task`.
**Connection (1):** `use_connection` — switches the session's environment/database (always prompts; re-locks prod writes; invalidates pending tokens).
**Performance diagnostics (8):** `read_essential_stats`, `read_detailed_stats` (compare-exchange/identity counts), `read_database_health` (liveness probe), `read_ongoing_tasks` (ALL task types — ETL, replication, backup, subscriptions, AI — not just AI Hub), `read_subscriptions` (worker staleness via `lastBatchAckTime`/`lastClientConnectionTime`), `read_backup_status` (real durations + per-destination upload sizes), `read_topology` (cluster nodes/roles or per-database node assignment), `read_database_settings` (effective runtime config).
Not available — the `ravendb` Node client (unlike the .NET client) exposes no IO-metrics operation, storage report, per-index performance timeline, per-ETL performance stats, or license/memory-stats operation. These would require calling undocumented Studio-only HTTP endpoints, which this server does not do.
**Preview (6, read-only):** `preview_put_document`, `preview_patch_document`, `preview_patch_by_query`, `preview_put_index`. Each returns a human-readable diff/summary of the exact pending change plus a single-use `confirmationToken`. The two patch previews execute the script in **RavenDB's server-side test mode** (`PATCH ...&test=true` — nothing is persisted) and return the real before/after documents with a line diff; set-based previews do this for up to 3 sample affected documents alongside the total affected count. A script that errors at runtime fails the preview, so broken patches never reach the approval stage.
**Write (6, approval required):** `write_put_document`, `write_patch_document`, `write_patch_by_query`, `write_put_index`, `write_update_ai_task`, `write_toggle_ai_task`. Each requires the token from its matching preview with a **byte-identical payload** — any change invalidates the token. Patch scripts are re-validated at execution time.
**AI Hub:** `read_ai_tasks` / `read_ai_task` list and inspect Embeddings Generation and GenAI ETL tasks. `preview_update_ai_task` → `write_update_ai_task` updates a task's configuration (validated client-side; every embedded script — GenAI transformation, GenAI updateScript, embeddings transformation — passes the same deletion-blocking sanitizer). `preview_toggle_ai_task` → `write_toggle_ai_task` runs (enables) or stops (disables) a task; previews call out that enabling incurs AI-model API cost and that GenAI tasks update matching documents. Creating or **deleting AI tasks is not supported** — `DeleteOngoingTaskOperation` is never imported; disabling is reversible and is not deletion.
## Safety model
Three independent layers:
1. **No deletion capability.** No delete operation is imported anywhere in the codebase. Patch scripts are parsed with a JavaScript AST (acorn) and rejected if they contain `del()`, `deleteCounter()`, any `.delete()` call, computed member calls (`obj[expr]()`), `eval`/`Function`/`globalThis`, or the `@expires` expiration key (delayed deletion). Unparseable scripts are rejected (fail closed). `read_query` rejects `update { }` blocks.
2. **Claude Code permission prompts.** `write_*` tools are annotated non-read-only/destructive and are never allowlisted, so the developer physically approves each write with the arguments visible.
3. **Preview tokens.** A write executes only with a fresh, single-use token bound (SHA-256) to the exact previewed payload — guaranteeing the diff/affected-count preview appeared in the conversation before the write. Known limitation: the model passes the token, so the binding guarantees *preview-before-write*, not human approval by itself — that's what layer 2 is for.
Overwrite protection: `write_put_document` refuses to overwrite an existing document unless the change vector from the preview is supplied, so concurrent changes can't be silently lost.
## Development
```
npm test # unit tests for the safety modules
npm run inspect # MCP Inspector against the built server
```
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available