@j0hanz/memdb 1.2.9 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +663 -382
  2. package/dist/assets/logo.svg +12 -0
  3. package/dist/async-context.d.ts +6 -0
  4. package/dist/async-context.js +4 -0
  5. package/dist/config.d.ts +0 -1
  6. package/dist/config.js +10 -5
  7. package/dist/core/abort.d.ts +1 -0
  8. package/dist/core/abort.js +3 -0
  9. package/dist/core/db.d.ts +9 -5
  10. package/dist/core/db.js +205 -129
  11. package/dist/core/memory-read.d.ts +1 -2
  12. package/dist/core/memory-read.js +18 -21
  13. package/dist/core/memory-write.d.ts +1 -2
  14. package/dist/core/memory-write.js +69 -85
  15. package/dist/core/relationships.d.ts +0 -1
  16. package/dist/core/relationships.js +56 -59
  17. package/dist/core/search.d.ts +0 -1
  18. package/dist/core/search.js +141 -85
  19. package/dist/error-utils.d.ts +1 -0
  20. package/dist/error-utils.js +28 -0
  21. package/dist/index.d.ts +0 -1
  22. package/dist/index.js +63 -16
  23. package/dist/instructions.md +38 -34
  24. package/dist/logger.d.ts +0 -1
  25. package/dist/logger.js +6 -3
  26. package/dist/protocol-version-guard.d.ts +0 -1
  27. package/dist/protocol-version-guard.js +17 -2
  28. package/dist/schemas.d.ts +0 -1
  29. package/dist/schemas.js +12 -9
  30. package/dist/stdio-transport.d.ts +0 -1
  31. package/dist/stdio-transport.js +6 -16
  32. package/dist/tools.d.ts +1 -2
  33. package/dist/tools.js +222 -222
  34. package/dist/types.d.ts +0 -1
  35. package/dist/types.js +0 -1
  36. package/package.json +20 -18
  37. package/dist/config.d.ts.map +0 -1
  38. package/dist/config.js.map +0 -1
  39. package/dist/core/db.d.ts.map +0 -1
  40. package/dist/core/db.js.map +0 -1
  41. package/dist/core/memory-read.d.ts.map +0 -1
  42. package/dist/core/memory-read.js.map +0 -1
  43. package/dist/core/memory-write.d.ts.map +0 -1
  44. package/dist/core/memory-write.js.map +0 -1
  45. package/dist/core/relationships.d.ts.map +0 -1
  46. package/dist/core/relationships.js.map +0 -1
  47. package/dist/core/search.d.ts.map +0 -1
  48. package/dist/core/search.js.map +0 -1
  49. package/dist/index.d.ts.map +0 -1
  50. package/dist/index.js.map +0 -1
  51. package/dist/logger.d.ts.map +0 -1
  52. package/dist/logger.js.map +0 -1
  53. package/dist/protocol-version-guard.d.ts.map +0 -1
  54. package/dist/protocol-version-guard.js.map +0 -1
  55. package/dist/schemas.d.ts.map +0 -1
  56. package/dist/schemas.js.map +0 -1
  57. package/dist/stdio-transport.d.ts.map +0 -1
  58. package/dist/stdio-transport.js.map +0 -1
  59. package/dist/tools.d.ts.map +0 -1
  60. package/dist/tools.js.map +0 -1
  61. package/dist/types.d.ts.map +0 -1
  62. package/dist/types.js.map +0 -1
package/README.md CHANGED
@@ -1,382 +1,663 @@
1
- # memdb
2
-
3
- A SQLite-backed MCP memory server with local workspace storage.
4
-
5
- [![npm version](https://img.shields.io/npm/v/@j0hanz/memdb.svg)](https://www.npmjs.com/package/@j0hanz/memdb)
6
-
7
- ## One-Click Install
8
-
9
- [![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=memdb&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemdb%40latest%22%5D%7D)[![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=memdb&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemdb%40latest%22%5D%7D&quality=insiders)
10
-
11
- [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=memdb&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovbWVtZGJAbGF0ZXN0Il19)
12
-
13
- ## Features
14
-
15
- | Feature | Description |
16
- | :--------------- | :---------------------------------------------------------------- |
17
- | Memory Storage | Store text memories with tags |
18
- | Full-Text Search | FTS5-backed tokenized search with relevance ranking |
19
- | Stats | Memory and tag counts + activity range |
20
- | Local Privacy | All data stored locally in SQLite (`.memdb/memory.db` by default) |
21
-
22
- ## Quick Start
23
-
24
- ### VS Code / Cursor
25
-
26
- Add this to your `mcpServers` configuration:
27
-
28
- ```json
29
- {
30
- "memdb": {
31
- "command": "npx",
32
- "args": ["-y", "@j0hanz/memdb@latest"]
33
- }
34
- }
35
- ```
36
-
37
- ## Installation
38
-
39
- ### NPX (Recommended)
40
-
41
- ```bash
42
- npx -y @j0hanz/memdb@latest
43
- ```
44
-
45
- ### Global Installation
46
-
47
- ```bash
48
- npm install -g @j0hanz/memdb
49
- ```
50
-
51
- ### From Source
52
-
53
- ```bash
54
- git clone https://github.com/j0hanz/memdb-mcp-server.git
55
- cd memdb-mcp-server
56
- npm install
57
- npm run build
58
- ```
59
-
60
- ## Storage
61
-
62
- The server uses a local SQLite database at `<cwd>/.memdb/memory.db`. The
63
- directory is created automatically when needed. All data remains local to your
64
- workspace.
65
-
66
- > **Tip:** Add `.memdb/` to your `.gitignore` to keep your memory database out of
67
- > version control:
68
- >
69
- > ```bash
70
- > echo ".memdb/" >> .gitignore
71
- > ```
72
-
73
- To completely reset or remove all stored memories, simply delete the `.memdb/`
74
- folder. The server will create a fresh database on the next run.
75
-
76
- ## Tool Response Format
77
-
78
- All tools return structured JSON in `structuredContent`. For backwards
79
- compatibility, the first `content` item is a JSON string that matches
80
- `structuredContent`.
81
-
82
- Success (`structuredContent`):
83
-
84
- ```json
85
- {
86
- "ok": true,
87
- "result": { "...": "..." }
88
- }
89
- ```
90
-
91
- Error (`structuredContent`):
92
-
93
- ```json
94
- {
95
- "ok": false,
96
- "error": {
97
- "code": "E_CODE",
98
- "message": "Human-readable message"
99
- }
100
- }
101
- ```
102
-
103
- Error responses also set `isError: true` on the top-level tool result.
104
-
105
- Example `content[0].text`:
106
-
107
- ```text
108
- {"ok":true,"result":{...}}
109
- ```
110
-
111
- ## Tools
112
-
113
- ### `store_memory`
114
-
115
- Store a new memory with tags.
116
-
117
- | Parameter | Type | Required | Default | Description |
118
- | :-------- | :------- | :------- | :------ | :-------------------------------------------------- |
119
- | `content` | string | Yes | - | The content of the memory (1-100000 chars) |
120
- | `tags` | string[] | Yes | - | Tags (1-100 tags, no whitespace, max 50 chars each) |
121
-
122
- **Returns:** `{ id, hash, isNew }`
123
-
124
- Notes:
125
-
126
- - Content is deduplicated by MD5 hash. Storing the same content again returns the same hash with `isNew: false`.
127
- - Tags must not contain whitespace. Use hyphens for compound words (e.g., `api-design`, `error-handling`).
128
-
129
- ### `store_memories`
130
-
131
- Store multiple memories in a single batch operation.
132
-
133
- | Parameter | Type | Required | Default | Description |
134
- | :-------- | :------- | :------- | :------ | :------------------------------------- |
135
- | `items` | object[] | Yes | - | Array of memory items (1-50 items max) |
136
-
137
- Each item in `items` has:
138
-
139
- | Field | Type | Required | Default | Description |
140
- | :-------- | :------- | :------- | :------ | :-------------------------------------------------- |
141
- | `content` | string | Yes | - | The content of the memory (1-100000 chars) |
142
- | `tags` | string[] | Yes | - | Tags (1-100 tags, no whitespace, max 50 chars each) |
143
-
144
- **Returns:** `{ results, succeeded, failed }`
145
-
146
- - `results`: Array of `{ index, hash?, isNew?, error? }` for each item
147
- - `succeeded`: Count of successfully stored memories
148
- - `failed`: Count of failed items
149
-
150
- Notes:
151
-
152
- - Supports partial success: if one item fails, others still process.
153
- - Each item is validated independently.
154
- - Useful for bulk memory imports.
155
-
156
- ### `search_memories`
157
-
158
- Search memories by content and tags.
159
-
160
- | Parameter | Type | Required | Default | Description |
161
- | :-------- | :----- | :------- | :------ | :---------------------------------------- |
162
- | `query` | string | Yes | - | Search query (1-1000 chars, max 50 terms) |
163
-
164
- **Returns:** Array of search results (`Memory` + `relevance`, includes `tags`).
165
-
166
- Notes:
167
-
168
- - Searches both memory content (full-text) and tags.
169
- - Returns up to 100 results, ranked by relevance.
170
- - Content matches rank higher than tag matches.
171
-
172
- ### `get_memory`
173
-
174
- Retrieve a specific memory by its hash.
175
-
176
- | Parameter | Type | Required | Default | Description |
177
- | :-------- | :----- | :------- | :------ | :------------------ |
178
- | `hash` | string | Yes | - | MD5 hash (32 chars) |
179
-
180
- **Returns:** `Memory` (includes `tags`).
181
-
182
- Notes:
183
-
184
- - Updates `accessed_at` on read.
185
-
186
- ### `delete_memory`
187
-
188
- Delete a memory by its hash.
189
-
190
- | Parameter | Type | Required | Default | Description |
191
- | :-------- | :----- | :------- | :------ | :------------------ |
192
- | `hash` | string | Yes | - | MD5 hash (32 chars) |
193
-
194
- **Returns:** `{ deleted: true }`.
195
-
196
- ### `delete_memories`
197
-
198
- Delete multiple memories by hash in a single batch operation.
199
-
200
- | Parameter | Type | Required | Default | Description |
201
- | :-------- | :------- | :------- | :------ | :------------------------------------ |
202
- | `hashes` | string[] | Yes | - | Array of MD5 hashes (1-50 hashes max) |
203
-
204
- **Returns:** `{ results, succeeded, failed }`
205
-
206
- - `results`: Array of `{ hash, deleted, error? }` for each hash
207
- - `succeeded`: Count of successfully deleted memories
208
- - `failed`: Count of hashes not found or failed
209
-
210
- Notes:
211
-
212
- - Supports partial success: if one hash doesn't exist, others still delete.
213
- - Returns `deleted: false` for non-existent hashes (not an error).
214
- - Useful for bulk cleanup operations.
215
-
216
- ### `memory_stats`
217
-
218
- Get database statistics.
219
-
220
- _No parameters required._
221
-
222
- **Returns:** `{ memoryCount, tagCount, oldestMemory, newestMemory }`.
223
-
224
- ### `update_memory`
225
-
226
- Update the content of a memory. Returns the new hash since changing content changes the hash.
227
-
228
- | Parameter | Type | Required | Default | Description |
229
- | :-------- | :------- | :------- | :------ | :-------------------------------------- |
230
- | `hash` | string | Yes | - | MD5 hash of memory to update (32 chars) |
231
- | `content` | string | Yes | - | New content (1-100000 chars) |
232
- | `tags` | string[] | No | - | Replace tags (max 100, each 1-50 chars) |
233
-
234
- **Returns:** `{ updated: true, oldHash, newHash }`.
235
-
236
- Notes:
237
-
238
- - If `tags` is omitted, existing tags are preserved.
239
- - If `tags` is provided, it replaces all existing tags for the memory.
240
- - Updating to content that already exists in another memory returns an error.
241
-
242
- ### Memory Fields
243
-
244
- All memory-shaped responses include:
245
-
246
- - `id`: integer ID
247
- - `content`: original content string
248
- - `summary`: optional summary (currently unset by tools)
249
- - `tags`: string array
250
- - `created_at`: timestamp string
251
- - `accessed_at`: timestamp string
252
- - `hash`: MD5 hash
253
-
254
- ## Client Configuration
255
-
256
- <details>
257
- <summary><b>VS Code</b></summary>
258
-
259
- Add to your `settings.json` or `mcpServers` config:
260
-
261
- ```json
262
- {
263
- "mcpServers": {
264
- "memdb": {
265
- "command": "npx",
266
- "args": ["-y", "@j0hanz/memdb@latest"]
267
- }
268
- }
269
- }
270
- ```
271
-
272
- </details>
273
-
274
- <details>
275
- <summary><b>Claude Desktop</b></summary>
276
-
277
- Add to your `claude_desktop_config.json`:
278
-
279
- ```json
280
- {
281
- "mcpServers": {
282
- "memdb": {
283
- "command": "npx",
284
- "args": ["-y", "@j0hanz/memdb@latest"]
285
- }
286
- }
287
- }
288
- ```
289
-
290
- </details>
291
-
292
- <details>
293
- <summary><b>Cursor</b></summary>
294
-
295
- 1. Go to **Cursor Settings** > **Features** > **MCP**
296
- 2. Click **+ Add New MCP Server**
297
- 3. Name: `memdb`
298
- 4. Type: `command`
299
- 5. Command: `npx -y @j0hanz/memdb@latest`
300
-
301
- </details>
302
-
303
- ## Limits & Constraints
304
-
305
- | Constraint | Value | Description |
306
- | :---------------------- | :------------ | :---------------------------------------------------------------------------- |
307
- | **Max content length** | 100,000 chars | Maximum characters in memory content |
308
- | **Max query length** | 1,000 chars | Maximum characters in search query |
309
- | **Max search terms** | 50 | Maximum whitespace-separated terms per query |
310
- | **Max search results** | 100 | Maximum results returned from `search_memories` |
311
- | **Min tags per memory** | 1 | At least one tag is required |
312
- | **Max tags per memory** | 100 | Maximum number of tags when storing a memory |
313
- | **Max tag length** | 50 chars | Maximum characters per tag |
314
- | **Tag format** | No whitespace | Tags cannot contain spaces or tabs; use hyphens for compound words |
315
- | **Hash length** | 32 chars | MD5 hash length |
316
- | **Batch store limit** | 50 items | Maximum items per `store_memories` call |
317
- | **Batch delete limit** | 50 hashes | Maximum hashes per `delete_memories` call |
318
- | **Search mode** | Tokenized OR | Whitespace-split terms are quoted and OR'ed; FTS5 operators are not supported |
319
-
320
- ### Notes
321
-
322
- - **Content deduplication**: Memories are deduplicated using MD5 hashes.
323
- - **Search errors**: If FTS5 is unavailable, `search_memories` returns an error indicating the index is missing. Invalid query syntax returns an error with details.
324
- - **Search tokenization**: Queries are split on whitespace (max 50 terms); whitespace-only queries are rejected.
325
- - **Batch operations**: `store_memories` and `delete_memories` support partial success—individual item failures don't affect other items in the batch.
326
- - **Tag requirements**: At least one tag is required. Tags cannot contain whitespace; use hyphens for compound words (e.g., `api-design`).
327
- - **Local storage**: All data is stored locally in `.memdb/memory.db`.
328
-
329
- ## Development
330
-
331
- ### Prerequisites
332
-
333
- - Node.js >= 22.0.0 (required for `node:sqlite`)
334
-
335
- ### Scripts
336
-
337
- | Command | Description |
338
- | :------------------------ | :----------------------------------------- |
339
- | `npm run clean` | Remove `dist/` |
340
- | `npm run build` | Compile TypeScript to `dist/` |
341
- | `npm run dev` | Run in development mode with watch |
342
- | `npm run start` | Run compiled server (`node dist/index.js`) |
343
- | `npm run test` | Run tests |
344
- | `npm run test:coverage` | Run tests with coverage |
345
- | `npm run lint` | Run ESLint |
346
- | `npm run format` | Format code with Prettier |
347
- | `npm run format:check` | Check code formatting |
348
- | `npm run type-check` | TypeScript type checking |
349
- | `npm run type-check:test` | Type-check tests only |
350
- | `npm run duplication` | Run duplication report (jscpd) |
351
- | `npm run inspector` | Run MCP inspector |
352
-
353
- ### Project Structure
354
-
355
- ```text
356
- src/
357
- |-- index.ts # Server entry point (stdio transport)
358
- |-- config.ts # CLI/env configuration
359
- |-- logger.ts # stderr logger with level filtering
360
- |-- protocol-version-guard.ts # Reject unsupported MCP protocol versions
361
- |-- tools.ts # Tool registration + handlers
362
- |-- schemas.ts # Zod input/output schemas
363
- |-- types.ts # Shared TypeScript types
364
- `-- core/ # SQLite setup + memory CRUD/search
365
- |-- db.ts # DB init + schema + helpers
366
- |-- memory-read.ts # Read + delete + stats
367
- |-- memory-write.ts # Create + update + tag handling
368
- `-- search.ts # FTS + tag search
369
-
370
- tests/
371
- `-- *.test.ts # Node.js test runner tests
372
- ```
373
-
374
- ## Troubleshooting
375
-
376
- - **`node:sqlite` / `DatabaseSync` not found**: Ensure Node.js >= 22.0.0.
377
- - **Search errors about FTS5**: FTS5 must be available; the server creates the
378
- virtual table automatically, but your SQLite build must include FTS5 support.
379
-
380
- ## Contributing
381
-
382
- Contributions are welcome! Please feel free to submit a Pull Request.
1
+ # memdb
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40j0hanz%2Fmemdb)](https://www.npmjs.com/package/@j0hanz/memdb) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D24-339933?logo=node.js)](https://nodejs.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript)](https://www.typescriptlang.org/) [![MCP SDK](https://img.shields.io/badge/MCP_SDK-1.26-blueviolet)](https://modelcontextprotocol.io/)
4
+
5
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0078d7?logo=visual-studio-code&logoColor=white)](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%7B%22name%22%3A%22memdb%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemdb%40latest%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?logo=visual-studio-code&logoColor=white)](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%7B%22name%22%3A%22memdb%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemdb%40latest%22%5D%7D)
6
+
7
+ > A SQLite-backed MCP memory server with local workspace storage, full-text search (FTS5), and knowledge graph capabilities for AI assistants.
8
+
9
+ ---
10
+
11
+ ## Overview
12
+
13
+ **memdb** is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that provides persistent memory storage for AI assistants. It uses Node.js's native `node:sqlite` module to store memories locally with SHA-256 content deduplication, FTS5 full-text search, and a knowledge graph of typed relationships between memories. Communication happens over **stdio** transport.
14
+
15
+ ## Key Features
16
+
17
+ - **Persistent local storage** SQLite database stored in the workspace (`.memdb/memory.db` by default) with WAL mode for performance
18
+ - **Full-text search** FTS5-powered content and tag search with BM25 relevance scoring and recency boosting
19
+ - **Knowledge graph** Directed, typed relationships between memories with recursive graph traversal (`recall`)
20
+ - **SHA-256 deduplication** Content-addressed storage prevents duplicate memories automatically
21
+ - **Batch operations** — Store or delete up to 50 memories in a single call with partial success support
22
+ - **Memory classification** — Categorize memories by type (general, fact, plan, decision, reflection, lesson, error, gradient) and importance (0–10)
23
+ - **Protocol safety** — Custom stdio transport that rejects JSON-RPC batch requests, protocol version guard, and tool execution timeouts
24
+
25
+ ## Tech Stack
26
+
27
+ | Component | Technology |
28
+ | --------------- | ----------------------------------------- |
29
+ | Runtime | Node.js ≥ 24 |
30
+ | Language | TypeScript 5.9 (strict mode) |
31
+ | MCP SDK | `@modelcontextprotocol/sdk` v1.26.0 |
32
+ | Database | SQLite via native `node:sqlite` with FTS5 |
33
+ | Validation | Zod v4 |
34
+ | Transport | stdio |
35
+ | Package Manager | npm |
36
+
37
+ ## Architecture
38
+
39
+ ```text
40
+ ┌─────────────────────────────────────────────┐
41
+ │ Client │
42
+ └──────────────────┬──────────────────────────┘
43
+ │ stdio (JSON-RPC)
44
+ ┌──────────────────▼──────────────────────────┐
45
+ 1. BatchRejectingStdioServerTransport │ ← Rejects JSON-RPC batch arrays
46
+ │ 2. ProtocolVersionGuardTransport │ ← Validates protocol version
47
+ │ 3. McpServer (MCP SDK) │ ← Tool/resource registration
48
+ 4. Tool handlers with timeout + error wrap │ ← Zod validation, abort signals
49
+ │ 5. Core layer (db, search, relationships) │ ← SQLite + FTS5 + knowledge graph
50
+ └─────────────────────────────────────────────┘
51
+ ```
52
+
53
+ ## Repository Structure
54
+
55
+ ```text
56
+ memdb/
57
+ ├── src/
58
+ │ ├── core/ # Database and business logic
59
+ │ │ ├── db.ts # SQLite connection, schema, WAL, statement cache
60
+ │ │ ├── memory-read.ts # Get, delete, stats operations
61
+ │ │ ├── memory-write.ts # Store, update with SHA-256 deduplication
62
+ │ │ ├── relationships.ts # Knowledge graph edge operations
63
+ │ │ ├── search.ts # FTS5 search and graph traversal (recall)
64
+ │ │ └── abort.ts # Abort signal utilities
65
+ │ ├── index.ts # Server entrypoint, stdio transport, shutdown
66
+ │ ├── tools.ts # MCP tool registration with timeout handling
67
+ │ ├── schemas.ts # Zod schemas for all 12 tools
68
+ │ ├── types.ts # TypeScript interfaces
69
+ │ ├── config.ts # Environment variable configuration
70
+ │ ├── logger.ts # Logging (console.error, never stdout)
71
+ │ ├── stdio-transport.ts # Custom stdio transport with batch rejection
72
+ │ ├── protocol-version-guard.ts # Protocol version validation
73
+ │ ├── instructions.md # User-facing instructions (MCP resource)
74
+ │ ├── async-context.ts # AsyncLocalStorage for tool context
75
+ │ └── error-utils.ts # Error message extraction
76
+ ├── tests/ # node:test runner tests
77
+ ├── scripts/ # Build & task automation
78
+ ├── assets/ # Logo/icon assets
79
+ ├── .github/workflows/ # CI/CD (npm publish on release)
80
+ ├── package.json
81
+ ├── tsconfig.json
82
+ └── eslint.config.mjs
83
+ ```
84
+
85
+ ## Requirements
86
+
87
+ - **Node.js ≥ 24** — required for the native `node:sqlite` module
88
+
89
+ ## Quickstart
90
+
91
+ The fastest way to start using memdb is via `npx`:
92
+
93
+ ```bash
94
+ npx -y @j0hanz/memdb@latest
95
+ ```
96
+
97
+ Add to your MCP client configuration:
98
+
99
+ ```json
100
+ {
101
+ "mcpServers": {
102
+ "memdb": {
103
+ "command": "npx",
104
+ "args": ["-y", "@j0hanz/memdb@latest"]
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ ## Installation
111
+
112
+ ### NPX (recommended)
113
+
114
+ No installation needed — runs the latest version directly:
115
+
116
+ ```bash
117
+ npx -y @j0hanz/memdb@latest
118
+ ```
119
+
120
+ ### Global Install
121
+
122
+ ```bash
123
+ npm install -g @j0hanz/memdb
124
+ memdb
125
+ ```
126
+
127
+ ### From Source
128
+
129
+ ```bash
130
+ git clone https://github.com/j0hanz/memdb-mcp-server.git
131
+ cd memdb-mcp-server
132
+ npm install
133
+ npm run build
134
+ npm start
135
+ ```
136
+
137
+ ## Configuration
138
+
139
+ ### Environment Variables
140
+
141
+ | Variable | Type | Default | Description |
142
+ | ----------------------- | --------------------------- | ------------------ | ------------------------------------------------------------------------------ |
143
+ | `MEMDB_PATH` | `string` | `.memdb/memory.db` | Path to the SQLite database file. Set to `:memory:` for an in-memory database. |
144
+ | `MEMDB_LOG_LEVEL` | `error` \| `warn` \| `info` | `info` | Logging verbosity level |
145
+ | `MEMDB_TOOL_TIMEOUT_MS` | `integer` | `15000` | Tool execution timeout in milliseconds (non-negative integer) |
146
+
147
+ Environment variables can be set via a `.env` file when using `npm run dev:run`, or passed directly to the process.
148
+
149
+ ### Database Location
150
+
151
+ By default, memdb creates the database at `.memdb/memory.db` relative to the working directory. The directory is created automatically if it doesn't exist.
152
+
153
+ ## Usage
154
+
155
+ memdb communicates exclusively over **stdio** transport. Start the server and connect via any MCP-compatible client:
156
+
157
+ ```bash
158
+ # Direct
159
+ node dist/index.js
160
+
161
+ # Via npx
162
+ npx -y @j0hanz/memdb@latest
163
+
164
+ # With custom database path
165
+ MEMDB_PATH=/path/to/my.db npx -y @j0hanz/memdb@latest
166
+ ```
167
+
168
+ ## MCP Surface
169
+
170
+ ### Tools
171
+
172
+ memdb exposes **12 tools** organized into memory management, search, knowledge graph, and diagnostics.
173
+
174
+ ---
175
+
176
+ #### `store_memory`
177
+
178
+ Store a new memory with tags. Idempotent storing the same content returns the existing hash.
179
+
180
+ | Parameter | Type | Required | Default | Description |
181
+ | ------------- | ---------- | -------- | ----------- | ------------------------------------------------------------------------------------------------ |
182
+ | `content` | `string` | Yes | — | The content of the memory (1–100,000 chars) |
183
+ | `tags` | `string[]` | Yes | — | Tags to categorize the memory (1–100 tags, no whitespace, max 50 chars each) |
184
+ | `importance` | `integer` | No | `0` | Priority level 0–10 (0=lowest, 10=critical). Higher importance memories surface first in search. |
185
+ | `memory_type` | `string` | No | `"general"` | Category: `general`, `fact`, `plan`, `decision`, `reflection`, `lesson`, `error`, `gradient` |
186
+
187
+ **Returns:**
188
+
189
+ ```json
190
+ {
191
+ "ok": true,
192
+ "result": {
193
+ "id": 1,
194
+ "hash": "a1b2c3d4e5f6...",
195
+ "isNew": true
196
+ }
197
+ }
198
+ ```
199
+
200
+ ---
201
+
202
+ #### `store_memories`
203
+
204
+ Store multiple memories in a single batch operation (1–50 items). Supports partial success.
205
+
206
+ | Parameter | Type | Required | Default | Description |
207
+ | --------- | ---------- | -------- | ------- | ------------------------------------------------------------------------------------------------------ |
208
+ | `items` | `object[]` | Yes | — | Array of 1–50 memory objects, each with `content`, `tags`, and optional `importance` and `memory_type` |
209
+
210
+ **Returns:**
211
+
212
+ ```json
213
+ {
214
+ "ok": true,
215
+ "result": {
216
+ "results": [
217
+ { "ok": true, "index": 0, "hash": "a1b2...", "isNew": true },
218
+ { "ok": false, "index": 1, "error": "Tag must not contain whitespace" }
219
+ ],
220
+ "succeeded": 1,
221
+ "failed": 1
222
+ }
223
+ }
224
+ ```
225
+
226
+ ---
227
+
228
+ #### `get_memory`
229
+
230
+ Retrieve a single memory by its SHA-256 hash.
231
+
232
+ | Parameter | Type | Required | Default | Description |
233
+ | --------- | -------- | -------- | ------- | ----------------------------------------- |
234
+ | `hash` | `string` | Yes | — | SHA-256 hash of the memory (64 hex chars) |
235
+
236
+ **Returns:**
237
+
238
+ ```json
239
+ {
240
+ "ok": true,
241
+ "result": {
242
+ "id": 1,
243
+ "content": "TypeScript uses structural typing",
244
+ "summary": null,
245
+ "tags": ["typescript", "types"],
246
+ "importance": 5,
247
+ "memory_type": "fact",
248
+ "created_at": "2025-01-15 10:30:00",
249
+ "accessed_at": "2025-01-15 10:30:00",
250
+ "hash": "a1b2c3d4..."
251
+ }
252
+ }
253
+ ```
254
+
255
+ ---
256
+
257
+ #### `update_memory`
258
+
259
+ Update memory content. Returns the new hash since content changes affect the hash. Idempotent.
260
+
261
+ | Parameter | Type | Required | Default | Description |
262
+ | --------- | ---------- | -------- | ------- | ---------------------------------------------- |
263
+ | `hash` | `string` | Yes | — | Hash of the memory to update |
264
+ | `content` | `string` | Yes | — | New content for the memory (1–100,000 chars) |
265
+ | `tags` | `string[]` | No | — | Replace tags (max 100 tags, each max 50 chars) |
266
+
267
+ **Returns:**
268
+
269
+ ```json
270
+ {
271
+ "ok": true,
272
+ "result": {
273
+ "updated": true,
274
+ "oldHash": "a1b2c3d4...",
275
+ "newHash": "e5f6g7h8..."
276
+ }
277
+ }
278
+ ```
279
+
280
+ ---
281
+
282
+ #### `delete_memory`
283
+
284
+ Delete a single memory by hash. Destructive operation.
285
+
286
+ | Parameter | Type | Required | Default | Description |
287
+ | --------- | -------- | -------- | ------- | ----------------------------------------- |
288
+ | `hash` | `string` | Yes | — | SHA-256 hash of the memory (64 hex chars) |
289
+
290
+ **Returns:**
291
+
292
+ ```json
293
+ { "ok": true, "result": { "deleted": true } }
294
+ ```
295
+
296
+ ---
297
+
298
+ #### `delete_memories`
299
+
300
+ Delete multiple memories by hash in a single batch operation (1–50 hashes). Supports partial success. Destructive.
301
+
302
+ | Parameter | Type | Required | Default | Description |
303
+ | --------- | ---------- | -------- | ------- | -------------------------------------- |
304
+ | `hashes` | `string[]` | Yes | — | Array of 1–50 SHA-256 hashes to delete |
305
+
306
+ **Returns:**
307
+
308
+ ```json
309
+ {
310
+ "ok": true,
311
+ "result": {
312
+ "results": [
313
+ { "hash": "a1b2...", "deleted": true },
314
+ { "hash": "c3d4...", "deleted": false, "error": "Memory not found" }
315
+ ],
316
+ "succeeded": 1,
317
+ "failed": 1
318
+ }
319
+ }
320
+ ```
321
+
322
+ ---
323
+
324
+ #### `search_memories`
325
+
326
+ Search memories by content and tags using FTS5 full-text search with BM25 relevance scoring and recency boosting. Read-only.
327
+
328
+ | Parameter | Type | Required | Default | Description |
329
+ | --------- | -------- | -------- | ------- | ------------------------------------------------------- |
330
+ | `query` | `string` | Yes | — | Search query (1–1,000 chars, searches content and tags) |
331
+
332
+ **Returns:**
333
+
334
+ ```json
335
+ {
336
+ "ok": true,
337
+ "result": [
338
+ {
339
+ "id": 1,
340
+ "content": "TypeScript uses structural typing",
341
+ "tags": ["typescript", "types"],
342
+ "importance": 5,
343
+ "memory_type": "fact",
344
+ "relevance": 0.85,
345
+ "hash": "a1b2c3d4...",
346
+ "created_at": "2025-01-15 10:30:00",
347
+ "accessed_at": "2025-01-15 10:30:00"
348
+ }
349
+ ]
350
+ }
351
+ ```
352
+
353
+ ---
354
+
355
+ #### `recall`
356
+
357
+ Search for memories and traverse relationships to return a connected graph cluster. Use for deeper context retrieval that follows knowledge graph connections. Read-only.
358
+
359
+ | Parameter | Type | Required | Default | Description |
360
+ | --------- | --------- | -------- | ------- | -------------------------------------------------------------------------------- |
361
+ | `query` | `string` | Yes | — | Search query to find initial memories (1–1,000 chars) |
362
+ | `depth` | `integer` | No | `1` | How many relationship hops to follow (0–3). 0 = search only, no graph traversal. |
363
+
364
+ **Returns:**
365
+
366
+ ```json
367
+ {
368
+ "ok": true,
369
+ "result": {
370
+ "memories": [{ "id": 1, "content": "...", "relevance": 0.9, "...": "..." }],
371
+ "relationships": [
372
+ {
373
+ "id": 1,
374
+ "from_hash": "a1b2...",
375
+ "to_hash": "c3d4...",
376
+ "relation_type": "related_to",
377
+ "created_at": "2025-01-15 10:30:00"
378
+ }
379
+ ],
380
+ "depth": 1
381
+ }
382
+ }
383
+ ```
384
+
385
+ ---
386
+
387
+ #### `create_relationship`
388
+
389
+ Link two memories with a typed, directed relationship. Idempotent — creating the same relationship returns the existing ID.
390
+
391
+ | Parameter | Type | Required | Default | Description |
392
+ | --------------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
393
+ | `from_hash` | `string` | Yes | — | SHA-256 hash of the source memory |
394
+ | `to_hash` | `string` | Yes | — | SHA-256 hash of the target memory |
395
+ | `relation_type` | `string` | Yes | — | Type of relationship (e.g., `related_to`, `causes`, `depends_on`, `part_of`, `follows`; 1–50 chars, no whitespace) |
396
+
397
+ **Returns:**
398
+
399
+ ```json
400
+ { "ok": true, "result": { "id": 1, "isNew": true } }
401
+ ```
402
+
403
+ ---
404
+
405
+ #### `get_relationships`
406
+
407
+ Get all relationships for a memory. Read-only.
408
+
409
+ | Parameter | Type | Required | Default | Description |
410
+ | ----------- | -------- | -------- | -------- | --------------------------------------------------- |
411
+ | `hash` | `string` | Yes | — | SHA-256 hash of the memory |
412
+ | `direction` | `string` | No | `"both"` | Direction filter: `outgoing`, `incoming`, or `both` |
413
+
414
+ **Returns:**
415
+
416
+ ```json
417
+ {
418
+ "ok": true,
419
+ "result": [
420
+ {
421
+ "id": 1,
422
+ "from_hash": "a1b2...",
423
+ "to_hash": "c3d4...",
424
+ "relation_type": "depends_on",
425
+ "created_at": "2025-01-15 10:30:00"
426
+ }
427
+ ]
428
+ }
429
+ ```
430
+
431
+ ---
432
+
433
+ #### `delete_relationship`
434
+
435
+ Remove a relationship between two memories. Destructive.
436
+
437
+ | Parameter | Type | Required | Default | Description |
438
+ | --------------- | -------- | -------- | ------- | --------------------------------- |
439
+ | `from_hash` | `string` | Yes | — | SHA-256 hash of the source memory |
440
+ | `to_hash` | `string` | Yes | — | SHA-256 hash of the target memory |
441
+ | `relation_type` | `string` | Yes | — | Type of relationship to delete |
442
+
443
+ **Returns:**
444
+
445
+ ```json
446
+ { "ok": true, "result": { "deleted": true } }
447
+ ```
448
+
449
+ ---
450
+
451
+ #### `memory_stats`
452
+
453
+ Database statistics and health. No parameters required. Read-only.
454
+
455
+ **Returns:**
456
+
457
+ ```json
458
+ {
459
+ "ok": true,
460
+ "result": {
461
+ "memoryCount": 42,
462
+ "tagCount": 15,
463
+ "oldestMemory": "2025-01-01 00:00:00",
464
+ "newestMemory": "2025-02-09 12:00:00"
465
+ }
466
+ }
467
+ ```
468
+
469
+ ---
470
+
471
+ ### Resources
472
+
473
+ | URI | MIME Type | Description |
474
+ | ------------------------- | --------------- | -------------------------------------------------- |
475
+ | `internal://instructions` | `text/markdown` | Server usage instructions and tool reference guide |
476
+
477
+ ### Prompts
478
+
479
+ None.
480
+
481
+ ## Client Configuration Examples
482
+
483
+ <details>
484
+ <summary><b>VS Code / VS Code Insiders</b></summary>
485
+
486
+ Add to your VS Code `settings.json` or use the one-click install buttons above:
487
+
488
+ ```json
489
+ {
490
+ "mcp": {
491
+ "servers": {
492
+ "memdb": {
493
+ "command": "npx",
494
+ "args": ["-y", "@j0hanz/memdb@latest"]
495
+ }
496
+ }
497
+ }
498
+ }
499
+ ```
500
+
501
+ With environment variables:
502
+
503
+ ```json
504
+ {
505
+ "mcp": {
506
+ "servers": {
507
+ "memdb": {
508
+ "command": "npx",
509
+ "args": ["-y", "@j0hanz/memdb@latest"],
510
+ "env": {
511
+ "MEMDB_PATH": "${workspaceFolder}/.memdb/memory.db",
512
+ "MEMDB_LOG_LEVEL": "warn"
513
+ }
514
+ }
515
+ }
516
+ }
517
+ }
518
+ ```
519
+
520
+ </details>
521
+
522
+ <details>
523
+ <summary><b>Claude Desktop</b></summary>
524
+
525
+ Add to your Claude Desktop configuration file (`claude_desktop_config.json`):
526
+
527
+ ```json
528
+ {
529
+ "mcpServers": {
530
+ "memdb": {
531
+ "command": "npx",
532
+ "args": ["-y", "@j0hanz/memdb@latest"]
533
+ }
534
+ }
535
+ }
536
+ ```
537
+
538
+ </details>
539
+
540
+ <details>
541
+ <summary><b>Cursor</b></summary>
542
+
543
+ [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=memdb&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovbWVtZGJAbGF0ZXN0Il19)
544
+
545
+ Or manually add to Cursor MCP settings:
546
+
547
+ ```json
548
+ {
549
+ "mcpServers": {
550
+ "memdb": {
551
+ "command": "npx",
552
+ "args": ["-y", "@j0hanz/memdb@latest"]
553
+ }
554
+ }
555
+ }
556
+ ```
557
+
558
+ </details>
559
+
560
+ <details>
561
+ <summary><b>Windsurf</b></summary>
562
+
563
+ Add to your Windsurf MCP configuration:
564
+
565
+ ```json
566
+ {
567
+ "mcpServers": {
568
+ "memdb": {
569
+ "command": "npx",
570
+ "args": ["-y", "@j0hanz/memdb@latest"]
571
+ }
572
+ }
573
+ }
574
+ ```
575
+
576
+ </details>
577
+
578
+ ## Security
579
+
580
+ - **stdio hygiene** — All logging is sent to `stderr` via `console.error()`. No non-MCP output is written to `stdout`, preventing JSON-RPC corruption.
581
+ - **Batch request rejection** — JSON-RPC batch arrays are explicitly rejected by the custom `BatchRejectingStdioServerTransport` with proper error responses per MCP spec (≥ 2025-06-18).
582
+ - **Protocol version guard** — Unsupported protocol versions are rejected at the transport layer before reaching tool handlers. The connection is closed after sending the error.
583
+ - **Input validation** — All tool inputs are validated via Zod strict schemas at the MCP boundary. Null bytes in environment variables are detected and rejected.
584
+ - **Database safety** — SQLite defensive mode is enabled, foreign key constraints are enforced, and the `allowExtension` option is set to `false`.
585
+
586
+ ## Development Workflow
587
+
588
+ ### Prerequisites
589
+
590
+ - Node.js ≥ 24
591
+
592
+ ### Install dependencies
593
+
594
+ ```bash
595
+ npm install
596
+ ```
597
+
598
+ ### Scripts
599
+
600
+ | Script | Command | Purpose |
601
+ | --------------- | ---------------------------------------- | -------------------------------------------- |
602
+ | `dev` | `tsc --watch` | TypeScript watch mode (compile on change) |
603
+ | `dev:run` | `node --watch dist/index.js` | Run server with auto-restart and `.env` file |
604
+ | `build` | `node scripts/tasks.mjs build` | Compile TypeScript to `dist/` |
605
+ | `start` | `node dist/index.js` | Run the compiled server |
606
+ | `test` | `node scripts/tasks.mjs test` | Run tests with `node:test` runner |
607
+ | `test:coverage` | `node scripts/tasks.mjs test --coverage` | Run tests with coverage |
608
+ | `type-check` | `node scripts/tasks.mjs type-check` | TypeScript type checking (`tsc --noEmit`) |
609
+ | `lint` | `eslint .` | Run ESLint |
610
+ | `lint:fix` | `eslint . --fix` | Auto-fix linting issues |
611
+ | `format` | `prettier --write .` | Format code with Prettier |
612
+ | `clean` | `node scripts/tasks.mjs clean` | Remove build artifacts |
613
+ | `inspector` | `npx @modelcontextprotocol/inspector` | Launch MCP Inspector for debugging |
614
+
615
+ ## Build and Release
616
+
617
+ The project publishes to npm via a GitHub Actions workflow triggered on GitHub Releases:
618
+
619
+ 1. Checkout → Setup Node.js 20 → Install dependencies
620
+ 2. Lint → Type-check → Test → Coverage
621
+ 3. Build → Extract version from release tag → Publish to npm with trusted publishing (OIDC)
622
+
623
+ See [`.github/workflows/publish.yml`](.github/workflows/publish.yml) for the full pipeline.
624
+
625
+ ## Troubleshooting
626
+
627
+ ### `node:sqlite` not found
628
+
629
+ You are running Node.js < 24. The native `node:sqlite` module requires Node.js ≥ 24.
630
+
631
+ ```bash
632
+ node --version # Must be >= 24.0.0
633
+ ```
634
+
635
+ ### Database locked errors
636
+
637
+ The server uses SQLite WAL mode. If you see locked errors, ensure no external tools are accessing `.memdb/memory.db` while the server is running.
638
+
639
+ ### FTS5 errors
640
+
641
+ If you get errors mentioning `fts5` or `no such module`, ensure your Node.js binary includes the standard SQLite FTS5 extension (it should by default in Node.js ≥ 24).
642
+
643
+ ### Debugging with MCP Inspector
644
+
645
+ ```bash
646
+ npx @modelcontextprotocol/inspector node dist/index.js
647
+ ```
648
+
649
+ ### stdout corruption (stdio mode)
650
+
651
+ If your MCP client receives malformed responses, ensure no middleware or debugging tools are writing to `stdout`. memdb routes all logging to `stderr`.
652
+
653
+ ## Contributing
654
+
655
+ Contributions are welcome! Please ensure your changes pass all checks before submitting:
656
+
657
+ ```bash
658
+ npm run lint && npm run type-check && npm run build && npm test
659
+ ```
660
+
661
+ ## License
662
+
663
+ [MIT](https://opensource.org/licenses/MIT)