@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.
- package/README.md +663 -382
- package/dist/assets/logo.svg +12 -0
- package/dist/async-context.d.ts +6 -0
- package/dist/async-context.js +4 -0
- package/dist/config.d.ts +0 -1
- package/dist/config.js +10 -5
- package/dist/core/abort.d.ts +1 -0
- package/dist/core/abort.js +3 -0
- package/dist/core/db.d.ts +9 -5
- package/dist/core/db.js +205 -129
- package/dist/core/memory-read.d.ts +1 -2
- package/dist/core/memory-read.js +18 -21
- package/dist/core/memory-write.d.ts +1 -2
- package/dist/core/memory-write.js +69 -85
- package/dist/core/relationships.d.ts +0 -1
- package/dist/core/relationships.js +56 -59
- package/dist/core/search.d.ts +0 -1
- package/dist/core/search.js +141 -85
- package/dist/error-utils.d.ts +1 -0
- package/dist/error-utils.js +28 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +63 -16
- package/dist/instructions.md +38 -34
- package/dist/logger.d.ts +0 -1
- package/dist/logger.js +6 -3
- package/dist/protocol-version-guard.d.ts +0 -1
- package/dist/protocol-version-guard.js +17 -2
- package/dist/schemas.d.ts +0 -1
- package/dist/schemas.js +12 -9
- package/dist/stdio-transport.d.ts +0 -1
- package/dist/stdio-transport.js +6 -16
- package/dist/tools.d.ts +1 -2
- package/dist/tools.js +222 -222
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -1
- package/package.json +20 -18
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/core/db.d.ts.map +0 -1
- package/dist/core/db.js.map +0 -1
- package/dist/core/memory-read.d.ts.map +0 -1
- package/dist/core/memory-read.js.map +0 -1
- package/dist/core/memory-write.d.ts.map +0 -1
- package/dist/core/memory-write.js.map +0 -1
- package/dist/core/relationships.d.ts.map +0 -1
- package/dist/core/relationships.js.map +0 -1
- package/dist/core/search.d.ts.map +0 -1
- package/dist/core/search.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/protocol-version-guard.d.ts.map +0 -1
- package/dist/protocol-version-guard.js.map +0 -1
- package/dist/schemas.d.ts.map +0 -1
- package/dist/schemas.js.map +0 -1
- package/dist/stdio-transport.d.ts.map +0 -1
- package/dist/stdio-transport.js.map +0 -1
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,382 +1,663 @@
|
|
|
1
|
-
# memdb
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@j0hanz/memdb) [](https://opensource.org/licenses/MIT) [](https://nodejs.org/) [](https://www.typescriptlang.org/) [](https://modelcontextprotocol.io/)
|
|
4
|
+
|
|
5
|
+
[](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) [](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
|
+
[](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)
|