@j0hanz/memory-mcp 0.1.0 → 0.1.1
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 +308 -117
- package/dist/assets/logo.svg +35 -35
- package/dist/index.js +0 -0
- package/dist/instructions.md +59 -80
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,34 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- markdownlint-disable MD033 -->
|
|
4
4
|
|
|
5
|
-
[](https://github.com/j0hanz/memory-mcp/blob/master/package.json) [](https://github.com/j0hanz/memory-mcp/blob/master/package.json) [](https://github.com/j0hanz/memory-mcp/blob/master/package.json)
|
|
5
|
+
[](https://www.npmjs.com/package/@j0hanz/memory-mcp) [](https://github.com/j0hanz/memory-mcp/blob/master/package.json) [](https://github.com/j0hanz/memory-mcp/blob/master/package.json) [](https://github.com/j0hanz/memory-mcp/blob/master/package.json)
|
|
6
6
|
|
|
7
7
|
[](https://insiders.vscode.dev/redirect/mcp/install?name=memory-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemory-mcp%40latest%22%5D%7D) [](https://insiders.vscode.dev/redirect/mcp/install?name=memory-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemory-mcp%40latest%22%5D%7D&quality=insiders)
|
|
8
8
|
|
|
9
|
+
[](https://cursor.com/en/install-mcp?name=memory-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovbWVtb3J5LW1jcEBsYXRlc3QiXX0=)
|
|
10
|
+
|
|
9
11
|
A SQLite-backed MCP server for persistent memory storage, full-text retrieval, and relationship graph traversal.
|
|
10
12
|
|
|
11
13
|
## Overview
|
|
12
14
|
|
|
13
|
-
Memory MCP provides a local, persistent memory layer for MCP-enabled assistants. It
|
|
15
|
+
Memory MCP provides a local, persistent memory layer for MCP-enabled assistants. It stores SHA-256-addressed memory items in SQLite with FTS5-powered full-text search, a directed relationship graph, BFS recall traversal, and token-budget-aware context retrieval — all accessible over stdio transport with no external dependencies.
|
|
14
16
|
|
|
15
17
|
## Key Features
|
|
16
18
|
|
|
17
|
-
-
|
|
18
|
-
- Full-text search over content and tags via SQLite FTS5.
|
|
19
|
-
- Graph recall with BFS traversal
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
19
|
+
- **13 MCP tools** for CRUD, batch operations, FTS5 search, BFS graph recall, token-budget context retrieval, relationships, and stats.
|
|
20
|
+
- **Full-text search** over content and tags via SQLite FTS5 with importance and type filters.
|
|
21
|
+
- **Graph recall** with BFS traversal, bounded frontier, and MCP progress notifications per hop.
|
|
22
|
+
- **Token-budget retrieval** (`retrieve_context`) selects memories that fit a caller-specified token budget — no manual pagination needed.
|
|
23
|
+
- **Strict Zod input validation** with typed output envelopes and SHA-256 hash addressing.
|
|
24
|
+
- **Resource support** with `internal://instructions` (Markdown guide) and `memory://memories/{hash}` URI template with hash auto-completion.
|
|
25
|
+
- **stdio transport** with clean shutdown handling (`SIGINT`, `SIGTERM`) and no HTTP endpoints.
|
|
23
26
|
|
|
24
27
|
## Requirements
|
|
25
28
|
|
|
26
29
|
- Node.js `>=24`.
|
|
27
|
-
- SQLite with FTS5 support (
|
|
30
|
+
- SQLite with FTS5 support (verified at startup).
|
|
28
31
|
- Any MCP client that supports stdio command servers.
|
|
29
32
|
|
|
30
33
|
## Quick Start
|
|
31
34
|
|
|
32
|
-
Use the npm package directly with `npx
|
|
35
|
+
Use the npm package directly with `npx` — no installation required:
|
|
33
36
|
|
|
34
37
|
```json
|
|
35
38
|
{
|
|
@@ -43,7 +46,13 @@ Use the npm package directly with `npx`:
|
|
|
43
46
|
```
|
|
44
47
|
|
|
45
48
|
> [!TIP]
|
|
46
|
-
> The server uses stdio transport only; no HTTP endpoint is exposed.
|
|
49
|
+
> The server uses stdio transport only; no HTTP endpoint is exposed. Stdout must not be polluted by custom logging.
|
|
50
|
+
|
|
51
|
+
Or run with Docker:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
docker run --rm -i ghcr.io/j0hanz/memory-mcp:latest
|
|
55
|
+
```
|
|
47
56
|
|
|
48
57
|
## Client Configuration
|
|
49
58
|
|
|
@@ -65,6 +74,45 @@ Workspace file `.vscode/mcp.json`:
|
|
|
65
74
|
}
|
|
66
75
|
```
|
|
67
76
|
|
|
77
|
+
CLI:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
code --add-mcp '{"name":"memory-mcp","command":"npx","args":["-y","@j0hanz/memory-mcp@latest"]}'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
</details>
|
|
84
|
+
|
|
85
|
+
<details>
|
|
86
|
+
<summary><b>Install in VS Code Insiders</b></summary>
|
|
87
|
+
|
|
88
|
+
[](https://insiders.vscode.dev/redirect/mcp/install?name=memory-mcp&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fmemory-mcp%40latest%22%5D%7D&quality=insiders)
|
|
89
|
+
|
|
90
|
+
CLI:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
code-insiders --add-mcp '{"name":"memory-mcp","command":"npx","args":["-y","@j0hanz/memory-mcp@latest"]}'
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
</details>
|
|
97
|
+
|
|
98
|
+
<details>
|
|
99
|
+
<summary><b>Install in Cursor</b></summary>
|
|
100
|
+
|
|
101
|
+
[](https://cursor.com/en/install-mcp?name=memory-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovbWVtb3J5LW1jcEBsYXRlc3QiXX0=)
|
|
102
|
+
|
|
103
|
+
`~/.cursor/mcp.json`:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"memory-mcp": {
|
|
109
|
+
"command": "npx",
|
|
110
|
+
"args": ["-y", "@j0hanz/memory-mcp@latest"]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
68
116
|
</details>
|
|
69
117
|
|
|
70
118
|
<details>
|
|
@@ -92,9 +140,9 @@ claude mcp add memory-mcp -- npx -y @j0hanz/memory-mcp@latest
|
|
|
92
140
|
</details>
|
|
93
141
|
|
|
94
142
|
<details>
|
|
95
|
-
<summary><b>Install in
|
|
143
|
+
<summary><b>Install in Windsurf</b></summary>
|
|
96
144
|
|
|
97
|
-
|
|
145
|
+
MCP config:
|
|
98
146
|
|
|
99
147
|
```json
|
|
100
148
|
{
|
|
@@ -109,6 +157,41 @@ claude mcp add memory-mcp -- npx -y @j0hanz/memory-mcp@latest
|
|
|
109
157
|
|
|
110
158
|
</details>
|
|
111
159
|
|
|
160
|
+
<details>
|
|
161
|
+
<summary><b>Run with Docker</b></summary>
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Pull and run (stdio mode)
|
|
165
|
+
docker run --rm -i \
|
|
166
|
+
-e MEMORY_DB_PATH=/data/memory.db \
|
|
167
|
+
-v memory-data:/data \
|
|
168
|
+
ghcr.io/j0hanz/memory-mcp:latest
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
MCP client config:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"mcpServers": {
|
|
176
|
+
"memory-mcp": {
|
|
177
|
+
"command": "docker",
|
|
178
|
+
"args": [
|
|
179
|
+
"run",
|
|
180
|
+
"--rm",
|
|
181
|
+
"-i",
|
|
182
|
+
"-e",
|
|
183
|
+
"MEMORY_DB_PATH=/data/memory.db",
|
|
184
|
+
"-v",
|
|
185
|
+
"memory-data:/data",
|
|
186
|
+
"ghcr.io/j0hanz/memory-mcp:latest"
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
</details>
|
|
194
|
+
|
|
112
195
|
## MCP Surface
|
|
113
196
|
|
|
114
197
|
### Tools Summary
|
|
@@ -116,210 +199,286 @@ claude mcp add memory-mcp -- npx -y @j0hanz/memory-mcp@latest
|
|
|
116
199
|
| Tool | Category | Notes |
|
|
117
200
|
| --------------------- | -------- | --------------------------------------- |
|
|
118
201
|
| `store_memory` | Write | Idempotent by content+sorted tags hash |
|
|
119
|
-
| `store_memories` | Write | Batch (1
|
|
202
|
+
| `store_memories` | Write | Batch (1–50), transaction-wrapped |
|
|
120
203
|
| `get_memory` | Read | Hash lookup |
|
|
121
204
|
| `update_memory` | Write | Returns `old_hash` + `new_hash` |
|
|
122
205
|
| `delete_memory` | Write | Cascades relationship deletion |
|
|
123
|
-
| `delete_memories` | Write | Batch (1
|
|
124
|
-
| `search_memories` | Read | FTS5
|
|
125
|
-
| `create_relationship` | Write | Idempotent edge creation
|
|
206
|
+
| `delete_memories` | Write | Batch (1–50), transaction-wrapped |
|
|
207
|
+
| `search_memories` | Read | FTS5 + importance/type filters + cursor |
|
|
208
|
+
| `create_relationship` | Write | Idempotent directed edge creation |
|
|
126
209
|
| `delete_relationship` | Write | Deletes exact directed edge |
|
|
127
210
|
| `get_relationships` | Read | Direction filter + linked memory fields |
|
|
128
|
-
| `recall` | Read |
|
|
211
|
+
| `recall` | Read | FTS5 seed + BFS traversal (depth 0–3) |
|
|
212
|
+
| `retrieve_context` | Read | Token-budget-aware context retrieval |
|
|
129
213
|
| `memory_stats` | Read | Store aggregates and type breakdown |
|
|
130
214
|
|
|
215
|
+
---
|
|
216
|
+
|
|
131
217
|
### `store_memory`
|
|
132
218
|
|
|
133
|
-
|
|
219
|
+
Store a new memory with content, tags, and optional type/importance. Idempotent — storing the same content+tags returns the existing hash with `created: false`.
|
|
134
220
|
|
|
135
221
|
| Name | Type | Required | Default | Description |
|
|
136
222
|
| ------------- | ---------- | -------- | --------- | ---------------------------------------------------------------------------------- |
|
|
137
|
-
| `content` | `string` | Yes | — | Memory content (1
|
|
138
|
-
| `tags` | `string[]` | Yes | — | 1
|
|
223
|
+
| `content` | `string` | Yes | — | Memory content (1–100000 chars) |
|
|
224
|
+
| `tags` | `string[]` | Yes | — | 1–100 tags, each max 50 chars, no whitespace |
|
|
139
225
|
| `memory_type` | enum | No | `general` | `general`, `fact`, `plan`, `decision`, `reflection`, `lesson`, `error`, `gradient` |
|
|
140
|
-
| `importance` | `integer` | No | `0` | Priority 0
|
|
226
|
+
| `importance` | `integer` | No | `0` | Priority 0–10 |
|
|
227
|
+
|
|
228
|
+
Returns: `{ ok, result: { hash, created } }`
|
|
141
229
|
|
|
142
|
-
|
|
230
|
+
---
|
|
143
231
|
|
|
144
232
|
### `store_memories`
|
|
145
233
|
|
|
146
|
-
|
|
234
|
+
Store multiple memories in one transaction (max 50 items).
|
|
235
|
+
|
|
236
|
+
| Name | Type | Required | Description |
|
|
237
|
+
| ------- | ------------------------ | -------- | -------------------------------------------------------------------------------------- |
|
|
238
|
+
| `items` | `Array<StoreMemoryItem>` | Yes | 1–50 items, each with `content`, `tags`, optional `memory_type`, optional `importance` |
|
|
147
239
|
|
|
148
|
-
|
|
149
|
-
| ------- | ------------------------ | -------- | ------- | --------------------------------------------------------------------------------------------- |
|
|
150
|
-
| `items` | `Array<StoreMemoryItem>` | Yes | — | 1-50 memory items, each with `content`, `tags`, optional `memory_type`, optional `importance` |
|
|
240
|
+
Returns: `{ ok, result: { items, succeeded, failed } }`
|
|
151
241
|
|
|
152
|
-
|
|
242
|
+
---
|
|
153
243
|
|
|
154
244
|
### `get_memory`
|
|
155
245
|
|
|
156
|
-
|
|
246
|
+
Retrieve one memory by its SHA-256 hash.
|
|
157
247
|
|
|
158
|
-
| Name | Type | Required |
|
|
159
|
-
| ------ | -------- | -------- |
|
|
160
|
-
| `hash` | `string` | Yes |
|
|
248
|
+
| Name | Type | Required | Description |
|
|
249
|
+
| ------ | -------- | -------- | ----------------------------- |
|
|
250
|
+
| `hash` | `string` | Yes | 64-char lowercase SHA-256 hex |
|
|
161
251
|
|
|
162
|
-
Returns: `{ ok, result: Memory }` or `{ ok: false, error }`
|
|
252
|
+
Returns: `{ ok, result: Memory }` or `{ ok: false, error }` on `E_NOT_FOUND`.
|
|
253
|
+
|
|
254
|
+
---
|
|
163
255
|
|
|
164
256
|
### `update_memory`
|
|
165
257
|
|
|
166
|
-
|
|
258
|
+
Update content and optionally tags for an existing memory. Returns both hashes.
|
|
167
259
|
|
|
168
260
|
| Name | Type | Required | Default | Description |
|
|
169
261
|
| --------- | ---------- | -------- | ------------- | -------------------- |
|
|
170
262
|
| `hash` | `string` | Yes | — | Existing memory hash |
|
|
171
263
|
| `content` | `string` | Yes | — | Replacement content |
|
|
172
|
-
| `tags` | `string[]` | No |
|
|
264
|
+
| `tags` | `string[]` | No | Existing tags | Replacement tags |
|
|
265
|
+
|
|
266
|
+
Returns: `{ ok, result: { old_hash, new_hash } }`
|
|
173
267
|
|
|
174
|
-
|
|
268
|
+
---
|
|
175
269
|
|
|
176
270
|
### `delete_memory`
|
|
177
271
|
|
|
178
|
-
|
|
272
|
+
Delete one memory by hash. Cascades to related relationship rows.
|
|
273
|
+
|
|
274
|
+
| Name | Type | Required | Description |
|
|
275
|
+
| ------ | -------- | -------- | ----------- |
|
|
276
|
+
| `hash` | `string` | Yes | Memory hash |
|
|
179
277
|
|
|
180
|
-
|
|
181
|
-
| ------ | -------- | -------- | ------- | ----------- |
|
|
182
|
-
| `hash` | `string` | Yes | — | Memory hash |
|
|
278
|
+
Returns: `{ ok, result: { hash, deleted } }`
|
|
183
279
|
|
|
184
|
-
|
|
280
|
+
---
|
|
185
281
|
|
|
186
282
|
### `delete_memories`
|
|
187
283
|
|
|
188
|
-
|
|
284
|
+
Delete multiple memories by hash in one transaction.
|
|
189
285
|
|
|
190
|
-
| Name | Type | Required |
|
|
191
|
-
| -------- | ---------- | -------- |
|
|
192
|
-
| `hashes` | `string[]` | Yes |
|
|
286
|
+
| Name | Type | Required | Description |
|
|
287
|
+
| -------- | ---------- | -------- | ------------------ |
|
|
288
|
+
| `hashes` | `string[]` | Yes | 1–50 memory hashes |
|
|
193
289
|
|
|
194
|
-
Returns: `{ ok, result: { items, succeeded, failed } }
|
|
290
|
+
Returns: `{ ok, result: { items, succeeded, failed } }`
|
|
291
|
+
|
|
292
|
+
---
|
|
195
293
|
|
|
196
294
|
### `search_memories`
|
|
197
295
|
|
|
198
|
-
|
|
296
|
+
Full-text search over memory content and tags using FTS5. Supports importance and type filters with cursor pagination.
|
|
297
|
+
|
|
298
|
+
| Name | Type | Required | Default | Description |
|
|
299
|
+
| ---------------- | --------- | -------- | ------- | --------------------------------------------------------- |
|
|
300
|
+
| `query` | `string` | Yes | — | Search text (1–1000 chars) |
|
|
301
|
+
| `limit` | `integer` | No | `20` | Results per page (1–100) |
|
|
302
|
+
| `cursor` | `string` | No | — | Pagination cursor from previous response |
|
|
303
|
+
| `min_importance` | `integer` | No | — | Only return memories with importance >= this value (0–10) |
|
|
304
|
+
| `max_importance` | `integer` | No | — | Only return memories with importance <= this value (0–10) |
|
|
305
|
+
| `memory_type` | enum | No | — | Filter by memory type |
|
|
199
306
|
|
|
200
|
-
|
|
201
|
-
| -------- | --------- | -------- | ------- | --------------------------- |
|
|
202
|
-
| `query` | `string` | Yes | — | Search text (1-1000 chars) |
|
|
203
|
-
| `limit` | `integer` | No | `20` | Result cap per page (1-100) |
|
|
204
|
-
| `cursor` | `string` | No | — | Pagination cursor |
|
|
307
|
+
Returns: `{ ok, result: { memories, total_returned, nextCursor? } }`
|
|
205
308
|
|
|
206
|
-
|
|
309
|
+
---
|
|
207
310
|
|
|
208
311
|
### `create_relationship`
|
|
209
312
|
|
|
210
|
-
|
|
313
|
+
Create a directed relationship edge between two memories. Idempotent.
|
|
314
|
+
|
|
315
|
+
Suggested `relation_type` values: `related_to`, `causes`, `depends_on`, `parent_of`, `child_of`, `supersedes`, `contradicts`, `supports`, `references`.
|
|
211
316
|
|
|
212
|
-
| Name | Type | Required |
|
|
213
|
-
| --------------- | -------- | -------- |
|
|
214
|
-
| `from_hash` | `string` | Yes |
|
|
215
|
-
| `to_hash` | `string` | Yes |
|
|
216
|
-
| `relation_type` | `string` | Yes |
|
|
317
|
+
| Name | Type | Required | Description |
|
|
318
|
+
| --------------- | -------- | -------- | ------------------------------------------------- |
|
|
319
|
+
| `from_hash` | `string` | Yes | Source memory hash |
|
|
320
|
+
| `to_hash` | `string` | Yes | Target memory hash |
|
|
321
|
+
| `relation_type` | `string` | Yes | Edge label (1–50 chars, no whitespace, free-form) |
|
|
217
322
|
|
|
218
|
-
Returns: `{ ok, result: { created } }
|
|
323
|
+
Returns: `{ ok, result: { created } }`
|
|
324
|
+
|
|
325
|
+
---
|
|
219
326
|
|
|
220
327
|
### `delete_relationship`
|
|
221
328
|
|
|
222
|
-
|
|
329
|
+
Delete one directed relationship edge.
|
|
330
|
+
|
|
331
|
+
| Name | Type | Required | Description |
|
|
332
|
+
| --------------- | -------- | -------- | ----------------- |
|
|
333
|
+
| `from_hash` | `string` | Yes | Source hash |
|
|
334
|
+
| `to_hash` | `string` | Yes | Target hash |
|
|
335
|
+
| `relation_type` | `string` | Yes | Relationship type |
|
|
223
336
|
|
|
224
|
-
|
|
225
|
-
| --------------- | -------- | -------- | ------- | ----------------- |
|
|
226
|
-
| `from_hash` | `string` | Yes | — | Source hash |
|
|
227
|
-
| `to_hash` | `string` | Yes | — | Target hash |
|
|
228
|
-
| `relation_type` | `string` | Yes | — | Relationship type |
|
|
337
|
+
Returns: `{ ok, result: { deleted } }` or `{ ok: false, error }` on `E_NOT_FOUND`.
|
|
229
338
|
|
|
230
|
-
|
|
339
|
+
---
|
|
231
340
|
|
|
232
341
|
### `get_relationships`
|
|
233
342
|
|
|
234
|
-
|
|
343
|
+
Retrieve relationships for a memory, with optional direction filter.
|
|
235
344
|
|
|
236
345
|
| Name | Type | Required | Default | Description |
|
|
237
346
|
| ----------- | -------- | -------- | ------- | --------------------------------- |
|
|
238
347
|
| `hash` | `string` | Yes | — | Memory hash |
|
|
239
348
|
| `direction` | enum | No | `both` | `outgoing`, `incoming`, or `both` |
|
|
240
349
|
|
|
241
|
-
Returns: `{ ok, result: { relationships, count } }
|
|
350
|
+
Returns: `{ ok, result: { relationships, count } }`
|
|
351
|
+
|
|
352
|
+
Each relationship includes `from_hash`, `to_hash`, `relation_type`, `created_at`, `linked_hash`, `linked_content`, and `linked_tags`.
|
|
353
|
+
|
|
354
|
+
---
|
|
242
355
|
|
|
243
356
|
### `recall`
|
|
244
357
|
|
|
245
|
-
|
|
358
|
+
Search memories by full-text query, then traverse the relationship graph up to `depth` hops via BFS. Emits MCP progress notifications per hop.
|
|
246
359
|
|
|
247
|
-
| Name
|
|
248
|
-
|
|
|
249
|
-
| `query`
|
|
250
|
-
| `depth`
|
|
251
|
-
| `limit`
|
|
252
|
-
| `cursor`
|
|
360
|
+
| Name | Type | Required | Default | Description |
|
|
361
|
+
| ---------------- | --------- | -------- | ------- | ---------------------------------------------------------- |
|
|
362
|
+
| `query` | `string` | Yes | — | Seed search query (1–1000 chars) |
|
|
363
|
+
| `depth` | `integer` | No | `1` | BFS hops (0–3) |
|
|
364
|
+
| `limit` | `integer` | No | `10` | Seed memory count (1–50) |
|
|
365
|
+
| `cursor` | `string` | No | — | Pagination cursor from previous response |
|
|
366
|
+
| `min_importance` | `integer` | No | — | Seed filter: only memories with importance >= value (0–10) |
|
|
367
|
+
| `max_importance` | `integer` | No | — | Seed filter: only memories with importance <= value (0–10) |
|
|
368
|
+
| `memory_type` | enum | No | — | Seed filter: only memories of this type |
|
|
253
369
|
|
|
254
|
-
Returns: `{ ok, result: { memories, graph, depth_reached, nextCursor? } }
|
|
370
|
+
Returns: `{ ok, result: { memories, graph, depth_reached, aborted?, nextCursor? } }`
|
|
255
371
|
|
|
256
|
-
Each item in
|
|
372
|
+
Each item in `graph` uses the shape:
|
|
257
373
|
|
|
258
374
|
```json
|
|
259
375
|
{ "from_hash": "...", "to_hash": "...", "relation_type": "..." }
|
|
260
376
|
```
|
|
261
377
|
|
|
378
|
+
> [!NOTE]
|
|
379
|
+
> `aborted: true` indicates the traversal hit a safety limit (`RECALL_MAX_FRONTIER_SIZE`, `RECALL_MAX_EDGE_ROWS`, or `RECALL_MAX_VISITED_NODES`). Partial results are still returned.
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
### `retrieve_context`
|
|
384
|
+
|
|
385
|
+
Search memories and return relevance-ranked results that fit within a caller-specified token budget. Eliminates manual pagination and token counting for context window management.
|
|
386
|
+
|
|
387
|
+
| Name | Type | Required | Default | Description |
|
|
388
|
+
| -------------- | --------- | -------- | ----------- | ------------------------------------------------------------------------------------------ |
|
|
389
|
+
| `query` | `string` | Yes | — | Search query (1–1000 chars) |
|
|
390
|
+
| `token_budget` | `integer` | No | `4000` | Maximum estimated tokens to return (100–200000) |
|
|
391
|
+
| `strategy` | enum | No | `relevance` | Sort order: `relevance` (FTS rank), `importance` (highest first), `recency` (newest first) |
|
|
392
|
+
|
|
393
|
+
Returns: `{ ok, result: { memories, estimated_tokens, truncated } }`
|
|
394
|
+
|
|
395
|
+
> [!TIP]
|
|
396
|
+
> Token estimation is approximate (content length ÷ 4). `truncated: true` means the budget was reached before all candidates were included.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
262
400
|
### `memory_stats`
|
|
263
401
|
|
|
264
|
-
|
|
402
|
+
Return aggregate memory and relationship stats. Takes no input.
|
|
265
403
|
|
|
266
|
-
|
|
267
|
-
| -------- | ---- | -------- | ------- | ------------------ |
|
|
268
|
-
| _(none)_ | — | — | — | Empty input object |
|
|
404
|
+
Returns:
|
|
269
405
|
|
|
270
|
-
|
|
406
|
+
```json
|
|
407
|
+
{
|
|
408
|
+
"ok": true,
|
|
409
|
+
"result": {
|
|
410
|
+
"memories": {
|
|
411
|
+
"total": 0,
|
|
412
|
+
"oldest": null,
|
|
413
|
+
"newest": null,
|
|
414
|
+
"avg_importance": null
|
|
415
|
+
},
|
|
416
|
+
"relationships": { "total": 0 },
|
|
417
|
+
"by_type": {}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
271
423
|
|
|
272
424
|
### Resources
|
|
273
425
|
|
|
274
|
-
| URI |
|
|
275
|
-
| -------------------------- |
|
|
276
|
-
| `internal://instructions` |
|
|
277
|
-
| `memory://memories/{hash}` |
|
|
426
|
+
| URI | MIME | Description |
|
|
427
|
+
| -------------------------- | ------------------ | ----------------------------------------------------- |
|
|
428
|
+
| `internal://instructions` | `text/markdown` | Markdown usage guide for all tools and workflows |
|
|
429
|
+
| `memory://memories/{hash}` | `application/json` | Returns one memory as JSON; hash completion supported |
|
|
278
430
|
|
|
279
431
|
### Prompts
|
|
280
432
|
|
|
281
|
-
| Name | Arguments | Purpose
|
|
282
|
-
| ---------- | --------- |
|
|
283
|
-
| `get-help` | none | Returns
|
|
433
|
+
| Name | Arguments | Purpose |
|
|
434
|
+
| ---------- | --------- | --------------------------------------------- |
|
|
435
|
+
| `get-help` | none | Returns full usage instructions for all tools |
|
|
284
436
|
|
|
285
437
|
## Configuration
|
|
286
438
|
|
|
287
439
|
### Environment Variables
|
|
288
440
|
|
|
289
|
-
| Variable
|
|
290
|
-
|
|
|
291
|
-
| `MEMORY_DB_PATH`
|
|
441
|
+
| Variable | Description | Default | Required |
|
|
442
|
+
| -------------------------- | ------------------------------------------------------- | ----------- | -------- |
|
|
443
|
+
| `MEMORY_DB_PATH` | SQLite database file path | `memory.db` | No |
|
|
444
|
+
| `RECALL_MAX_FRONTIER_SIZE` | Max BFS frontier nodes per hop (100–50000) | `1000` | No |
|
|
445
|
+
| `RECALL_MAX_EDGE_ROWS` | Max relationship rows fetched per traversal (100–50000) | `5000` | No |
|
|
446
|
+
| `RECALL_MAX_VISITED_NODES` | Max visited nodes across entire traversal (100–50000) | `5000` | No |
|
|
292
447
|
|
|
293
448
|
> [!IMPORTANT]
|
|
294
449
|
> If `MEMORY_DB_PATH` is relative (including the default `memory.db`), it resolves from the process working directory.
|
|
295
450
|
|
|
451
|
+
> [!TIP]
|
|
452
|
+
> Add `memory.db` to your `.gitignore` to keep the database out of version control — it contains local session data and should not be shared or committed.
|
|
453
|
+
|
|
296
454
|
### Limits and Constraints
|
|
297
455
|
|
|
298
|
-
| Item
|
|
299
|
-
|
|
|
300
|
-
| Content length
|
|
301
|
-
| Tag count
|
|
302
|
-
| Tag length
|
|
303
|
-
| Hash format
|
|
304
|
-
| Search query length
|
|
305
|
-
| `search_memories.limit`
|
|
306
|
-
| `recall.depth`
|
|
307
|
-
| `recall.limit`
|
|
308
|
-
|
|
|
309
|
-
|
|
|
310
|
-
|
|
|
456
|
+
| Item | Value |
|
|
457
|
+
| ------------------------------- | ------------------------------------------------- |
|
|
458
|
+
| Content length | 1–100000 chars |
|
|
459
|
+
| Tag count | 1–100 per memory |
|
|
460
|
+
| Tag length | 1–50 chars, no whitespace |
|
|
461
|
+
| Hash format | 64-char lowercase hex SHA-256 |
|
|
462
|
+
| Search query length | 1–1000 chars |
|
|
463
|
+
| `search_memories.limit` | 1–100 (default 20) |
|
|
464
|
+
| `recall.depth` | 0–3 (default 1) |
|
|
465
|
+
| `recall.limit` | 1–50 (default 10) |
|
|
466
|
+
| `retrieve_context.token_budget` | 100–200000 (default 4000) |
|
|
467
|
+
| Batch size | 1–50 items (`store_memories`, `delete_memories`) |
|
|
468
|
+
| Recall frontier guard | `RECALL_MAX_FRONTIER_SIZE` (default 1000 per hop) |
|
|
469
|
+
| SQLite busy timeout | 5000 ms |
|
|
311
470
|
|
|
312
471
|
> [!NOTE]
|
|
313
472
|
> Cursor values are base64url-encoded offsets. Treat them as opaque tokens.
|
|
314
473
|
|
|
315
474
|
## Security
|
|
316
475
|
|
|
317
|
-
- Transport is stdio-only (`StdioServerTransport`)
|
|
318
|
-
- Fatal process errors are written to `stderr
|
|
319
|
-
-
|
|
320
|
-
- Hashes are validated against lowercase SHA-256 hex
|
|
321
|
-
- Search input is tokenized to alphanumeric terms before FTS `MATCH` execution (non-alphanumeric characters act as delimiters).
|
|
322
|
-
- SQLite foreign keys are enabled; relationship rows cascade
|
|
476
|
+
- Transport is stdio-only (`StdioServerTransport`) — no HTTP endpoints.
|
|
477
|
+
- Fatal process errors are written to `stderr`; stdout must remain clean for the MCP protocol.
|
|
478
|
+
- All inputs are validated with strict Zod schemas and bounded field constraints before any database access.
|
|
479
|
+
- Hashes are validated against a lowercase 64-char SHA-256 hex regex.
|
|
480
|
+
- Search input is tokenized to alphanumeric terms before FTS `MATCH` execution (non-alphanumeric characters act as delimiters, preventing FTS injection).
|
|
481
|
+
- SQLite foreign keys are enabled; relationship rows cascade-delete when a memory is removed.
|
|
323
482
|
|
|
324
483
|
## Development
|
|
325
484
|
|
|
@@ -340,7 +499,9 @@ Core scripts:
|
|
|
340
499
|
| `test` | `npm run test` | Full build + tests via task runner |
|
|
341
500
|
| `test:fast` | `npm run test:fast` | Run TS tests directly with Node test runner |
|
|
342
501
|
| `lint` | `npm run lint` | ESLint checks |
|
|
502
|
+
| `lint:fix` | `npm run lint:fix` | ESLint auto-fix |
|
|
343
503
|
| `type-check` | `npm run type-check` | Strict TypeScript checks |
|
|
504
|
+
| `format` | `npm run format` | Prettier format |
|
|
344
505
|
| `inspector` | `npm run inspector` | Build and open MCP Inspector against stdio server |
|
|
345
506
|
|
|
346
507
|
Inspect with MCP Inspector:
|
|
@@ -349,15 +510,45 @@ Inspect with MCP Inspector:
|
|
|
349
510
|
npx @modelcontextprotocol/inspector node dist/index.js
|
|
350
511
|
```
|
|
351
512
|
|
|
513
|
+
## Build & Release
|
|
514
|
+
|
|
515
|
+
GitHub Actions release workflow (`.github/workflows/release.yml`) handles versioning, validation, and publishing via a single `workflow_dispatch` trigger:
|
|
516
|
+
|
|
517
|
+
```
|
|
518
|
+
workflow_dispatch (patch / minor / major / custom)
|
|
519
|
+
│
|
|
520
|
+
▼
|
|
521
|
+
release — bump package.json + server.json → lint → type-check → test → build → tag → GitHub Release
|
|
522
|
+
│
|
|
523
|
+
├──► publish-npm ──► publish-mcp (npm Trusted Publishing OIDC → MCP Registry)
|
|
524
|
+
│
|
|
525
|
+
└──► publish-docker (GHCR, linux/amd64 + linux/arm64)
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
Trigger a release:
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
gh workflow run release.yml -f bump=patch
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Or use the GitHub UI: **Actions → Release → Run workflow**.
|
|
535
|
+
|
|
536
|
+
> [!NOTE]
|
|
537
|
+
> npm publishing uses OIDC Trusted Publishing — no `NPM_TOKEN` secret required. MCP Registry uses GitHub OIDC. Docker uses the built-in `GITHUB_TOKEN`.
|
|
538
|
+
|
|
352
539
|
## Troubleshooting
|
|
353
540
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
541
|
+
| Symptom | Cause | Fix |
|
|
542
|
+
| ----------------------------- | ---------------------------- | -------------------------------------------------------- |
|
|
543
|
+
| Startup fails with FTS5 error | Node.js build without FTS5 | Use Node.js 24+ with SQLite FTS5 support |
|
|
544
|
+
| `E_NOT_FOUND` on `get_memory` | Hash doesn't exist | Verify via `search_memories` first |
|
|
545
|
+
| `E_INVALID_CURSOR` | Stale or malformed cursor | Retry the request without the `cursor` parameter |
|
|
546
|
+
| MCP client can't connect | Custom stdout logging added | Ensure nothing writes to stdout in the server process |
|
|
547
|
+
| `aborted: true` in recall | Traversal hit a safety limit | Reduce `depth`, or tune `RECALL_MAX_*` env vars |
|
|
548
|
+
| Database locked errors | High concurrent write load | SQLite busy timeout is 5000 ms; reduce concurrent writes |
|
|
358
549
|
|
|
359
550
|
## License
|
|
360
551
|
|
|
361
|
-
|
|
552
|
+
MIT
|
|
362
553
|
|
|
363
554
|
<!-- markdownlint-enable MD033 -->
|
package/dist/assets/logo.svg
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke-width="0.8" stroke-linecap="round"
|
|
2
|
-
stroke-linejoin="round" role="img" aria-label="icon">
|
|
3
|
-
<style>
|
|
4
|
-
path,
|
|
5
|
-
circle,
|
|
6
|
-
rect,
|
|
7
|
-
line,
|
|
8
|
-
polyline,
|
|
9
|
-
polygon {
|
|
10
|
-
stroke: #111111;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
@media (prefers-color-scheme: dark) {
|
|
14
|
-
|
|
15
|
-
path,
|
|
16
|
-
circle,
|
|
17
|
-
rect,
|
|
18
|
-
line,
|
|
19
|
-
polyline,
|
|
20
|
-
polygon {
|
|
21
|
-
stroke: #eeeeee;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
</style>
|
|
25
|
-
|
|
26
|
-
<rect x="5" y="2" width="14" height="20" rx="2" />
|
|
27
|
-
|
|
28
|
-
<path d="M9 7H15" />
|
|
29
|
-
<path d="M9 12H15" />
|
|
30
|
-
<path d="M9 17H15" />
|
|
31
|
-
|
|
32
|
-
<path d="M3 6H5" />
|
|
33
|
-
<path d="M3 18H5" />
|
|
34
|
-
<path d="M19 6H21" />
|
|
35
|
-
<path d="M19 18H21" />
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke-width="0.8" stroke-linecap="round"
|
|
2
|
+
stroke-linejoin="round" role="img" aria-label="icon">
|
|
3
|
+
<style>
|
|
4
|
+
path,
|
|
5
|
+
circle,
|
|
6
|
+
rect,
|
|
7
|
+
line,
|
|
8
|
+
polyline,
|
|
9
|
+
polygon {
|
|
10
|
+
stroke: #111111;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@media (prefers-color-scheme: dark) {
|
|
14
|
+
|
|
15
|
+
path,
|
|
16
|
+
circle,
|
|
17
|
+
rect,
|
|
18
|
+
line,
|
|
19
|
+
polyline,
|
|
20
|
+
polygon {
|
|
21
|
+
stroke: #eeeeee;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
25
|
+
|
|
26
|
+
<rect x="5" y="2" width="14" height="20" rx="2" />
|
|
27
|
+
|
|
28
|
+
<path d="M9 7H15" />
|
|
29
|
+
<path d="M9 12H15" />
|
|
30
|
+
<path d="M9 17H15" />
|
|
31
|
+
|
|
32
|
+
<path d="M3 6H5" />
|
|
33
|
+
<path d="M3 18H5" />
|
|
34
|
+
<path d="M19 6H21" />
|
|
35
|
+
<path d="M19 18H21" />
|
|
36
36
|
</svg>
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/instructions.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MEMORY-MCP INSTRUCTIONS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
These instructions are available as a resource `internal://instructions` or prompt `get-help`. Load them when unsure about tool usage.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## CORE CAPABILITY
|
|
8
8
|
|
|
9
9
|
- Domain: SQLite-backed memory store with FTS5 search and knowledge graph for AI assistants.
|
|
10
|
-
- Primary Resources:
|
|
11
|
-
- Tools: `search_memories
|
|
10
|
+
- Primary Resources: Memories (content+tags+hash), Relationships (directed edges).
|
|
11
|
+
- Tools: `search_memories`, `get_memory`, `recall`, `get_relationships`, `memory_stats`, `retrieve_context` (READ); `store_memory`, `store_memories`, `update_memory`, `delete_memory`, `delete_memories`, `create_relationship`, `delete_relationship` (WRITE).
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -21,37 +21,39 @@
|
|
|
21
21
|
## RESOURCES & RESOURCE LINKS
|
|
22
22
|
|
|
23
23
|
- `internal://instructions`: This document.
|
|
24
|
-
- `memory://memories/{hash}`: Retrieve a single memory by SHA-256 hash
|
|
24
|
+
- `memory://memories/{hash}`: Retrieve a single memory by its SHA-256 hash.
|
|
25
|
+
- If a tool response includes a `resourceUri` or `resource_link`, call `resources/read` with the URI to fetch the full payload.
|
|
25
26
|
|
|
26
27
|
---
|
|
27
28
|
|
|
28
29
|
## THE "GOLDEN PATH" WORKFLOWS (CRITICAL)
|
|
29
30
|
|
|
30
|
-
### WORKFLOW A:
|
|
31
|
+
### WORKFLOW A: RECALL & EXPLORATION
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
- Call `search_memories` with `{ query }` to find memories by content/tags.
|
|
34
|
+
- Call `recall` with `{ query, depth }` to traverse graph connections from hits.
|
|
35
|
+
- Call `get_memory` with `{ hash }` for exact retrieval using hash from results.
|
|
36
|
+
NOTE: Never guess hashes. Always search first.
|
|
36
37
|
|
|
37
|
-
### WORKFLOW B:
|
|
38
|
+
### WORKFLOW B: KNOWLEDGE MANAGEMENT (STORAGE)
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
- Call `store_memory` or `store_memories` (batch ≤50) to persist content with tags.
|
|
41
|
+
- Call `create_relationship` to link memories via `{ from_hash, to_hash, relation_type }`.
|
|
42
|
+
- Call `update_memory` with `{ hash, content }` to revise — returns new hash.
|
|
43
|
+
NOTE: `update_memory` changes the hash because hash depends on content.
|
|
43
44
|
|
|
44
|
-
### WORKFLOW C:
|
|
45
|
+
### WORKFLOW C: CONTEXT RETRIEVAL (RAG)
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
NOTE: Confirm destructive actions with the user first.
|
|
47
|
+
- Call `retrieve_context` with `{ query, token_budget }` to get relevant memories fitting a token limit.
|
|
48
|
+
- Use `strategy='importance'` for high-priority items or `strategy='recency'` for latest updates.
|
|
49
|
+
NOTE: Output is truncated to fit `token_budget`.
|
|
50
50
|
|
|
51
|
-
### WORKFLOW D:
|
|
51
|
+
### WORKFLOW D: CLEANUP & MAINTENANCE
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
- Call `delete_memory` or `delete_memories` to remove obsolete items.
|
|
54
|
+
- Call `delete_relationship` to remove specific edges.
|
|
55
|
+
- Call `memory_stats` to monitor database size and health.
|
|
56
|
+
NOTE: Always confirm destructive actions (delete) with the user first.
|
|
55
57
|
|
|
56
58
|
---
|
|
57
59
|
|
|
@@ -59,86 +61,63 @@
|
|
|
59
61
|
|
|
60
62
|
`store_memory` / `store_memories`
|
|
61
63
|
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
`search_memories`
|
|
68
|
-
|
|
69
|
-
- Uses FTS5 full-text search over content and tags. Results ranked by relevance.
|
|
70
|
-
- `limit`: 1–100 (default 20). Returns `nextCursor` for pagination.
|
|
71
|
-
- Query is sanitized to alphanumeric tokens — special characters are stripped.
|
|
72
|
-
|
|
73
|
-
`recall`
|
|
74
|
-
|
|
75
|
-
- Seeds from FTS5 search, then performs BFS traversal up to `depth` hops (0–3, default 1).
|
|
76
|
-
- `depth: 0` returns only search results with no graph traversal.
|
|
77
|
-
- `limit`: 1–50 (default 10) controls the seed count, not the total.
|
|
78
|
-
- Returns all discovered `memories` and the `graph` edges connecting them.
|
|
79
|
-
- BFS frontier capped at 1,000 nodes per hop to prevent unbounded memory usage.
|
|
64
|
+
- Purpose: Persist memory content.
|
|
65
|
+
- Input: `tags` (array, no whitespace, max 50 chars each), `importance` (0-10).
|
|
66
|
+
- Output: Returns `hash` and `created` boolean.
|
|
67
|
+
- Gotcha: Idempotent. Storing identical content+tags returns existing hash with `created: false`.
|
|
80
68
|
|
|
81
69
|
`update_memory`
|
|
82
70
|
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
71
|
+
- Purpose: Modify memory content.
|
|
72
|
+
- Input: Requires `hash` and new `content`. `tags` optional.
|
|
73
|
+
- Output: Returns `old_hash` and `new_hash`.
|
|
74
|
+
- Nuance: Changing content changes the hash. The old memory is effectively replaced.
|
|
86
75
|
|
|
87
|
-
`
|
|
76
|
+
`search_memories`
|
|
88
77
|
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
78
|
+
- Purpose: FTS5 full-text search over content and tags.
|
|
79
|
+
- Input: `query`, `limit` (default 20), `cursor` for pagination.
|
|
80
|
+
- Limits: Max 100 results per call.
|
|
92
81
|
|
|
93
|
-
`
|
|
82
|
+
`recall`
|
|
94
83
|
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
84
|
+
- Purpose: Graph traversal starting from search hits.
|
|
85
|
+
- Input: `depth` (0-3, default 1). 0 = search only. Higher depth = more hops.
|
|
86
|
+
- Gotcha: High depth may return large graphs. Use cautiously.
|
|
98
87
|
|
|
99
|
-
`
|
|
88
|
+
`retrieve_context`
|
|
100
89
|
|
|
101
|
-
-
|
|
102
|
-
- `
|
|
103
|
-
-
|
|
90
|
+
- Purpose: Get memories optimized for LLM context window.
|
|
91
|
+
- Input: `token_budget` (default 4000).
|
|
92
|
+
- Output: `memories` array and `truncated` boolean.
|
|
104
93
|
|
|
105
|
-
`
|
|
94
|
+
`create_relationship`
|
|
106
95
|
|
|
107
|
-
-
|
|
96
|
+
- Purpose: Link two memories.
|
|
97
|
+
- Input: `from_hash`, `to_hash`, `relation_type` (e.g., related_to, causes).
|
|
98
|
+
- Gotcha: Both hashes must exist.
|
|
108
99
|
|
|
109
100
|
---
|
|
110
101
|
|
|
111
102
|
## CROSS-FEATURE RELATIONSHIPS
|
|
112
103
|
|
|
113
|
-
- Use `
|
|
114
|
-
- Use `
|
|
115
|
-
- `
|
|
116
|
-
- `memory://memories/{hash}` resource provides the same data as `get_memory` but through the MCP resource protocol.
|
|
104
|
+
- Use `store_memory` to get hashes, then `create_relationship` to link them.
|
|
105
|
+
- Use `search_memories` to find entry points for `recall` traversals.
|
|
106
|
+
- `retrieve_context` uses the same ranking as `search_memories` but limits by token count.
|
|
117
107
|
|
|
118
108
|
---
|
|
119
109
|
|
|
120
110
|
## CONSTRAINTS & LIMITATIONS
|
|
121
111
|
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
- Content: max 100,000 characters per memory.
|
|
127
|
-
- Tags: 1–100 per memory, each max 50 chars, no whitespace.
|
|
128
|
-
- Hash: 64 lowercase hex characters (SHA-256).
|
|
129
|
-
- Search query: 1–1,000 characters.
|
|
130
|
-
- Batch operations: max 50 items per call.
|
|
131
|
-
- Pagination cursors are base64url-encoded offsets — do not construct manually.
|
|
112
|
+
- Content size: Max 100,000 characters per memory.
|
|
113
|
+
- Batch size: Max 50 items for `store_memories` and `delete_memories`.
|
|
114
|
+
- Tags: Max 100 tags per memory, no whitespace.
|
|
115
|
+
- Relationships: Directed edges only.
|
|
132
116
|
|
|
133
117
|
---
|
|
134
118
|
|
|
135
119
|
## ERROR HANDLING STRATEGY
|
|
136
120
|
|
|
137
|
-
- `E_NOT_FOUND`:
|
|
138
|
-
- `
|
|
139
|
-
- `
|
|
140
|
-
- `E_INVALID_CURSOR`: Malformed pagination cursor. → Drop the cursor and restart from the first page.
|
|
141
|
-
- `E_TIMEOUT`: SQLite busy timeout exceeded (5s). → Retry after a brief delay; reduce batch size if persistent.
|
|
142
|
-
- `E_UNKNOWN`: Unexpected error. → Check the error message for details; retry once.
|
|
143
|
-
|
|
144
|
-
---
|
|
121
|
+
- `E_NOT_FOUND`: Memory hash or relationship not found. → Search/recall to find valid hashes.
|
|
122
|
+
- `E_INVALID_CURSOR`: Pagination cursor invalid or expired. → Restart search without cursor.
|
|
123
|
+
- `E_UNKNOWN`: Unexpected internal error. → Check input format and retry.
|