@j0hanz/memory-mcp 0.1.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 +363 -0
- package/dist/assets/logo.svg +36 -0
- package/dist/completions/index.d.ts +3 -0
- package/dist/completions/index.d.ts.map +1 -0
- package/dist/completions/index.js +17 -0
- package/dist/completions/index.js.map +1 -0
- package/dist/db/index.d.ts +6 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +102 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/typed.d.ts +15 -0
- package/dist/db/typed.d.ts.map +1 -0
- package/dist/db/typed.js +24 -0
- package/dist/db/typed.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.md +144 -0
- package/dist/lib/errors.d.ts +5 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +12 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/hash.d.ts +2 -0
- package/dist/lib/hash.d.ts.map +1 -0
- package/dist/lib/hash.js +11 -0
- package/dist/lib/hash.js.map +1 -0
- package/dist/lib/pagination.d.ts +8 -0
- package/dist/lib/pagination.d.ts.map +1 -0
- package/dist/lib/pagination.js +40 -0
- package/dist/lib/pagination.js.map +1 -0
- package/dist/lib/search.d.ts +14 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +36 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/tool-response.d.ts +8 -0
- package/dist/lib/tool-response.d.ts.map +1 -0
- package/dist/lib/tool-response.js +21 -0
- package/dist/lib/tool-response.js.map +1 -0
- package/dist/lib/types.d.ts +75 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +25 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +46 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/resources/index.d.ts +4 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +89 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/schemas/index.d.ts +3 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +4 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/inputs.d.ts +128 -0
- package/dist/schemas/inputs.d.ts.map +1 -0
- package/dist/schemas/inputs.js +176 -0
- package/dist/schemas/inputs.js.map +1 -0
- package/dist/schemas/outputs.d.ts +202 -0
- package/dist/schemas/outputs.d.ts.map +1 -0
- package/dist/schemas/outputs.js +104 -0
- package/dist/schemas/outputs.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +73 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/create-relationship.d.ts +4 -0
- package/dist/tools/create-relationship.d.ts.map +1 -0
- package/dist/tools/create-relationship.js +49 -0
- package/dist/tools/create-relationship.js.map +1 -0
- package/dist/tools/delete-memories.d.ts +4 -0
- package/dist/tools/delete-memories.d.ts.map +1 -0
- package/dist/tools/delete-memories.js +55 -0
- package/dist/tools/delete-memories.js.map +1 -0
- package/dist/tools/delete-memory.d.ts +4 -0
- package/dist/tools/delete-memory.d.ts.map +1 -0
- package/dist/tools/delete-memory.js +35 -0
- package/dist/tools/delete-memory.js.map +1 -0
- package/dist/tools/delete-relationship.d.ts +4 -0
- package/dist/tools/delete-relationship.d.ts.map +1 -0
- package/dist/tools/delete-relationship.js +35 -0
- package/dist/tools/delete-relationship.js.map +1 -0
- package/dist/tools/get-memory.d.ts +4 -0
- package/dist/tools/get-memory.d.ts.map +1 -0
- package/dist/tools/get-memory.js +30 -0
- package/dist/tools/get-memory.js.map +1 -0
- package/dist/tools/get-relationships.d.ts +4 -0
- package/dist/tools/get-relationships.d.ts.map +1 -0
- package/dist/tools/get-relationships.js +57 -0
- package/dist/tools/get-relationships.js.map +1 -0
- package/dist/tools/helpers.d.ts +13 -0
- package/dist/tools/helpers.d.ts.map +1 -0
- package/dist/tools/helpers.js +49 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +29 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/memory-stats.d.ts +4 -0
- package/dist/tools/memory-stats.d.ts.map +1 -0
- package/dist/tools/memory-stats.js +60 -0
- package/dist/tools/memory-stats.js.map +1 -0
- package/dist/tools/recall.d.ts +4 -0
- package/dist/tools/recall.d.ts.map +1 -0
- package/dist/tools/recall.js +192 -0
- package/dist/tools/recall.js.map +1 -0
- package/dist/tools/retrieve-context.d.ts +4 -0
- package/dist/tools/retrieve-context.d.ts.map +1 -0
- package/dist/tools/retrieve-context.js +75 -0
- package/dist/tools/retrieve-context.js.map +1 -0
- package/dist/tools/search-memories.d.ts +4 -0
- package/dist/tools/search-memories.d.ts.map +1 -0
- package/dist/tools/search-memories.js +62 -0
- package/dist/tools/search-memories.js.map +1 -0
- package/dist/tools/store-memories.d.ts +4 -0
- package/dist/tools/store-memories.d.ts.map +1 -0
- package/dist/tools/store-memories.js +52 -0
- package/dist/tools/store-memories.js.map +1 -0
- package/dist/tools/store-memory.d.ts +4 -0
- package/dist/tools/store-memory.d.ts.map +1 -0
- package/dist/tools/store-memory.js +35 -0
- package/dist/tools/store-memory.js.map +1 -0
- package/dist/tools/update-memory.d.ts +4 -0
- package/dist/tools/update-memory.d.ts.map +1 -0
- package/dist/tools/update-memory.js +49 -0
- package/dist/tools/update-memory.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Memory INSTRUCTIONS
|
|
2
|
+
|
|
3
|
+
> Available as resource `internal://instructions`. Load when unsure about tool usage.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## CORE CAPABILITY
|
|
8
|
+
|
|
9
|
+
- Domain: SQLite-backed memory store with FTS5 search and knowledge graph for AI assistants.
|
|
10
|
+
- Primary Resources: Memory (content+tags+hash), Relationship (directed edges).
|
|
11
|
+
- Tools: `search_memories` `get_memory` `recall` `get_relationships` `memory_stats` (READ); `store_memory` `store_memories` `update_memory` `delete_memory` `delete_memories` `create_relationship` `delete_relationship` (WRITE).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## PROMPTS
|
|
16
|
+
|
|
17
|
+
- `get-help`: Returns these instructions for quick recall.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## RESOURCES & RESOURCE LINKS
|
|
22
|
+
|
|
23
|
+
- `internal://instructions`: This document.
|
|
24
|
+
- `memory://memories/{hash}`: Retrieve a single memory by SHA-256 hash (JSON). Supports hash autocompletion.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## THE "GOLDEN PATH" WORKFLOWS (CRITICAL)
|
|
29
|
+
|
|
30
|
+
### WORKFLOW A: Recall & Exploration
|
|
31
|
+
|
|
32
|
+
1. Call `search_memories` with `{ query }` to find memories by content/tags.
|
|
33
|
+
2. Call `recall` with `{ query, depth }` to traverse graph connections from search hits.
|
|
34
|
+
3. Call `get_memory` with `{ hash }` for exact retrieval using a hash from previous results.
|
|
35
|
+
NOTE: Never guess hashes. Always search first.
|
|
36
|
+
|
|
37
|
+
### WORKFLOW B: Knowledge Storage
|
|
38
|
+
|
|
39
|
+
1. Call `store_memory` to persist a single memory with content, tags, and optional type/importance.
|
|
40
|
+
2. Call `store_memories` for batch storage (up to 50 items, atomic transaction).
|
|
41
|
+
3. Call `create_relationship` to link memories via `{ from_hash, to_hash, relation_type }`.
|
|
42
|
+
NOTE: Both hashes must exist before creating a relationship.
|
|
43
|
+
|
|
44
|
+
### WORKFLOW C: Knowledge Management
|
|
45
|
+
|
|
46
|
+
1. Call `update_memory` with `{ hash, content }` to revise — returns a **new hash** (hash changes on content/tag update).
|
|
47
|
+
2. Call `delete_memory` or `delete_memories` to remove items. Deleting a memory cascades to its relationships.
|
|
48
|
+
3. Call `delete_relationship` to remove a specific edge.
|
|
49
|
+
NOTE: Confirm destructive actions with the user first.
|
|
50
|
+
|
|
51
|
+
### WORKFLOW D: Diagnostics & Graph Inspection
|
|
52
|
+
|
|
53
|
+
1. Call `memory_stats` (no input) to get counts, timestamps, and type breakdown.
|
|
54
|
+
2. Call `get_relationships` with `{ hash, direction }` to inspect a memory's connections.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## TOOL NUANCES & GOTCHAS
|
|
59
|
+
|
|
60
|
+
`store_memory` / `store_memories`
|
|
61
|
+
|
|
62
|
+
- Idempotent: storing the same content+tags returns the existing hash with `created: false`.
|
|
63
|
+
- Hash is computed from `SHA-256(content + sorted_tags)` — changing tags produces a different hash.
|
|
64
|
+
- `importance`: integer 0–10 (default 0). `memory_type`: one of `general`, `fact`, `plan`, `decision`, `reflection`, `lesson`, `error`, `gradient` (default `general`).
|
|
65
|
+
- Batch: `store_memories` accepts 1–50 items. All succeed or the transaction rolls back.
|
|
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.
|
|
80
|
+
|
|
81
|
+
`update_memory`
|
|
82
|
+
|
|
83
|
+
- `hash` must exist (`E_NOT_FOUND` otherwise). New `content` required; `tags` optional (kept if omitted).
|
|
84
|
+
- Returns `{ old_hash, new_hash }`. **The hash changes** — update references accordingly.
|
|
85
|
+
- Emits a `resources/updated` notification for the old hash URI.
|
|
86
|
+
|
|
87
|
+
`get_relationships`
|
|
88
|
+
|
|
89
|
+
- `direction`: `outgoing` | `incoming` | `both` (default `both`).
|
|
90
|
+
- Each relationship includes the linked memory's content and tags inline.
|
|
91
|
+
- Returns `E_NOT_FOUND` if the source hash does not exist.
|
|
92
|
+
|
|
93
|
+
`delete_memory` / `delete_memories`
|
|
94
|
+
|
|
95
|
+
- Deleting a memory cascades to all its relationships (foreign key ON DELETE CASCADE).
|
|
96
|
+
- Batch: `delete_memories` accepts 1–50 hashes. Atomic transaction.
|
|
97
|
+
- Items not found are returned with `deleted: false` (not an error in batch mode).
|
|
98
|
+
|
|
99
|
+
`create_relationship` / `delete_relationship`
|
|
100
|
+
|
|
101
|
+
- `create_relationship`: Idempotent — re-creating returns `created: false`.
|
|
102
|
+
- `relation_type`: no whitespace, max 50 chars (e.g., `related_to`, `causes`, `depends_on`).
|
|
103
|
+
- `delete_relationship`: Returns `E_NOT_FOUND` if the exact edge does not exist.
|
|
104
|
+
|
|
105
|
+
`memory_stats`
|
|
106
|
+
|
|
107
|
+
- No input. Returns total memories, total relationships, oldest/newest timestamps, average importance, and per-type breakdown.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## CROSS-FEATURE RELATIONSHIPS
|
|
112
|
+
|
|
113
|
+
- Use `search_memories` results to obtain hashes for `get_memory`, `update_memory`, `delete_memory`, and `create_relationship`.
|
|
114
|
+
- Use `recall` to discover connected memories and graph edges in a single call — combines FTS5 search with BFS traversal.
|
|
115
|
+
- `update_memory` changes the hash — any relationships referencing the old hash are updated via CASCADE.
|
|
116
|
+
- `memory://memories/{hash}` resource provides the same data as `get_memory` but through the MCP resource protocol.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## CONSTRAINTS & LIMITATIONS
|
|
121
|
+
|
|
122
|
+
- Transport: stdio only.
|
|
123
|
+
- Requires Node.js ≥ 24 with built-in `node:sqlite` and FTS5 support.
|
|
124
|
+
- Database path: set via `MEMORY_DB_PATH` env var (default: `memory.db`).
|
|
125
|
+
- SQLite busy timeout: 5,000 ms.
|
|
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.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## ERROR HANDLING STRATEGY
|
|
136
|
+
|
|
137
|
+
- `E_NOT_FOUND`: Hash or relationship missing. → Call `search_memories` or `recall` to find valid hashes.
|
|
138
|
+
- `E_DUPLICATE`: Entry already exists. → Safe to ignore for idempotent operations.
|
|
139
|
+
- `E_CONSTRAINT`: Foreign key or uniqueness violation. → Verify both hashes exist before creating relationships.
|
|
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
|
+
---
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,eAAO,MAAM,SAAS,cAAc,CAAC;AAErC,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAKpD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const E_NOT_FOUND = 'E_NOT_FOUND';
|
|
2
|
+
export const E_INVALID_CURSOR = 'E_INVALID_CURSOR';
|
|
3
|
+
export const E_UNKNOWN = 'E_UNKNOWN';
|
|
4
|
+
export function getErrorMessage(err) {
|
|
5
|
+
if (err instanceof Error)
|
|
6
|
+
return err.message;
|
|
7
|
+
const errorAsString = typeof err === 'string' ? err : undefined;
|
|
8
|
+
if (errorAsString != null)
|
|
9
|
+
return errorAsString;
|
|
10
|
+
return 'Unknown error occurred';
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AACzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AACnD,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AAErC,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,MAAM,aAAa,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,IAAI,aAAa,IAAI,IAAI;QAAE,OAAO,aAAa,CAAC;IAChD,OAAO,wBAAwB,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/lib/hash.ts"],"names":[],"mappings":"AAMA,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,MAAM,CAKR"}
|
package/dist/lib/hash.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
function normalizeTags(tags) {
|
|
3
|
+
return [...tags].sort();
|
|
4
|
+
}
|
|
5
|
+
export function computeMemoryHash(content, tags) {
|
|
6
|
+
return createHash('sha256')
|
|
7
|
+
.update(content)
|
|
8
|
+
.update(JSON.stringify(normalizeTags(tags)))
|
|
9
|
+
.digest('hex');
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/lib/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,SAAS,aAAa,CAAC,IAAuB;IAC5C,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,IAAuB;IAEvB,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,OAAO,CAAC;SACf,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;SAC3C,MAAM,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface PageSlice<T> {
|
|
2
|
+
page: T[];
|
|
3
|
+
hasMore: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function encodeCursor(offset: number): string;
|
|
6
|
+
export declare function decodeCursor(cursor: string): number;
|
|
7
|
+
export declare function splitPage<T>(rows: readonly T[], limit: number): PageSlice<T>;
|
|
8
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/lib/pagination.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;CAClB;AAwBD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CASnD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAM5E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { E_INVALID_CURSOR } from './errors.js';
|
|
3
|
+
const CURSOR_ENCODING = 'base64url';
|
|
4
|
+
function isCursorPayload(value) {
|
|
5
|
+
if (typeof value !== 'object' || value === null) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const { offset } = value;
|
|
9
|
+
return (typeof offset === 'number' &&
|
|
10
|
+
Number.isInteger(offset) &&
|
|
11
|
+
Number.isFinite(offset) &&
|
|
12
|
+
offset >= 0);
|
|
13
|
+
}
|
|
14
|
+
function parseCursorPayload(cursor) {
|
|
15
|
+
const json = Buffer.from(cursor, CURSOR_ENCODING).toString();
|
|
16
|
+
const parsed = JSON.parse(json);
|
|
17
|
+
if (!isCursorPayload(parsed)) {
|
|
18
|
+
throw new Error('Invalid cursor structure');
|
|
19
|
+
}
|
|
20
|
+
return parsed;
|
|
21
|
+
}
|
|
22
|
+
export function encodeCursor(offset) {
|
|
23
|
+
const payload = { offset };
|
|
24
|
+
return Buffer.from(JSON.stringify(payload)).toString(CURSOR_ENCODING);
|
|
25
|
+
}
|
|
26
|
+
export function decodeCursor(cursor) {
|
|
27
|
+
try {
|
|
28
|
+
return parseCursorPayload(cursor).offset;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new McpError(ErrorCode.InvalidParams, `${E_INVALID_CURSOR}: malformed cursor`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function splitPage(rows, limit) {
|
|
35
|
+
if (rows.length > limit) {
|
|
36
|
+
return { page: rows.slice(0, limit), hasMore: true };
|
|
37
|
+
}
|
|
38
|
+
return { page: [...rows], hasMore: false };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/lib/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,eAAe,GAAG,WAAW,CAAC;AAWpC,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,GAAG,KAAgC,CAAC;IACpD,OAAO,CACL,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QACxB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvB,MAAM,IAAI,CAAC,CACZ,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7D,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,OAAO,GAAkB,EAAE,MAAM,EAAE,CAAC;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,aAAa,EACvB,GAAG,gBAAgB,oBAAoB,CACxC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,IAAkB,EAAE,KAAa;IAC5D,IAAI,IAAI,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACvD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SQLInputValue } from 'node:sqlite';
|
|
2
|
+
export declare function sanitizeFtsQuery(query: string): string;
|
|
3
|
+
export interface MemoryFilters {
|
|
4
|
+
min_importance?: number;
|
|
5
|
+
max_importance?: number;
|
|
6
|
+
memory_type?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface FilterClauses {
|
|
9
|
+
clauses: string[];
|
|
10
|
+
params: SQLInputValue[];
|
|
11
|
+
}
|
|
12
|
+
export declare function buildFilterClauses(filters: MemoryFilters): FilterClauses;
|
|
13
|
+
export declare function buildAndWhereClause(clauses: readonly string[]): string;
|
|
14
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAgBxE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAMtE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const FTS_SAFE_TOKEN_REGEX = /[A-Za-z0-9_]+/g;
|
|
2
|
+
const FTS_EMPTY_QUERY_FALLBACK = '"__mcp_no_results__"';
|
|
3
|
+
function tokenizeQuery(query) {
|
|
4
|
+
return query.match(FTS_SAFE_TOKEN_REGEX) ?? [];
|
|
5
|
+
}
|
|
6
|
+
export function sanitizeFtsQuery(query) {
|
|
7
|
+
const tokens = tokenizeQuery(query);
|
|
8
|
+
if (tokens.length === 0) {
|
|
9
|
+
return FTS_EMPTY_QUERY_FALLBACK;
|
|
10
|
+
}
|
|
11
|
+
return tokens.map((token) => `"${token}"`).join(' ');
|
|
12
|
+
}
|
|
13
|
+
export function buildFilterClauses(filters) {
|
|
14
|
+
const clauses = [];
|
|
15
|
+
const params = [];
|
|
16
|
+
if (filters.min_importance != null) {
|
|
17
|
+
clauses.push('m.importance >= ?');
|
|
18
|
+
params.push(filters.min_importance);
|
|
19
|
+
}
|
|
20
|
+
if (filters.max_importance != null) {
|
|
21
|
+
clauses.push('m.importance <= ?');
|
|
22
|
+
params.push(filters.max_importance);
|
|
23
|
+
}
|
|
24
|
+
if (filters.memory_type != null) {
|
|
25
|
+
clauses.push('m.memory_type = ?');
|
|
26
|
+
params.push(filters.memory_type);
|
|
27
|
+
}
|
|
28
|
+
return { clauses, params };
|
|
29
|
+
}
|
|
30
|
+
export function buildAndWhereClause(clauses) {
|
|
31
|
+
if (clauses.length === 0) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
return ` ${clauses.map((clause) => `AND ${clause}`).join(' ')}`;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AAEA,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAC9C,MAAM,wBAAwB,GAAG,sBAAsB,CAAC;AAExD,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,wBAAwB,CAAC;IAClC,CAAC;IAED,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvD,CAAC;AAaD,MAAM,UAAU,kBAAkB,CAAC,OAAsB;IACvD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAA0B;IAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
interface StructuredToolResponse extends Record<string, unknown> {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function createToolResponse(structured: StructuredToolResponse): CallToolResult;
|
|
6
|
+
export declare function createErrorResponse(code: string, message: string): CallToolResult;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=tool-response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-response.d.ts","sourceRoot":"","sources":["../../src/lib/tool-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAOzE,UAAU,sBAAuB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC9D,EAAE,EAAE,OAAO,CAAC;CACb;AAiBD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,sBAAsB,GACjC,cAAc,CAEhB;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,cAAc,CAMhB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function toTextContent(value) {
|
|
2
|
+
return { type: 'text', text: JSON.stringify(value) };
|
|
3
|
+
}
|
|
4
|
+
function buildResponse(structured, isError = false) {
|
|
5
|
+
return {
|
|
6
|
+
content: [toTextContent(structured)],
|
|
7
|
+
structuredContent: structured,
|
|
8
|
+
...(isError ? { isError: true } : {}),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function createToolResponse(structured) {
|
|
12
|
+
return buildResponse(structured);
|
|
13
|
+
}
|
|
14
|
+
export function createErrorResponse(code, message) {
|
|
15
|
+
const structured = {
|
|
16
|
+
ok: false,
|
|
17
|
+
error: { code, message },
|
|
18
|
+
};
|
|
19
|
+
return buildResponse(structured, true);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=tool-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-response.js","sourceRoot":"","sources":["../../src/lib/tool-response.ts"],"names":[],"mappings":"AAWA,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AACvD,CAAC;AAED,SAAS,aAAa,CACpB,UAAkC,EAClC,OAAO,GAAG,KAAK;IAEf,OAAO;QACL,OAAO,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACpC,iBAAiB,EAAE,UAAU;QAC7B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,UAAkC;IAElC,OAAO,aAAa,CAAC,UAAU,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,OAAe;IAEf,MAAM,UAAU,GAA2B;QACzC,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;KACzB,CAAC;IACF,OAAO,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export interface Memory {
|
|
2
|
+
hash: string;
|
|
3
|
+
content: string;
|
|
4
|
+
tags: string[];
|
|
5
|
+
memory_type: string;
|
|
6
|
+
importance: number;
|
|
7
|
+
created_at: string;
|
|
8
|
+
updated_at: string;
|
|
9
|
+
relevance?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Relationship {
|
|
12
|
+
from_hash: string;
|
|
13
|
+
to_hash: string;
|
|
14
|
+
relation_type: string;
|
|
15
|
+
created_at: string;
|
|
16
|
+
}
|
|
17
|
+
export interface RelationshipWithMemory extends Relationship {
|
|
18
|
+
linked_hash: string;
|
|
19
|
+
linked_content: string;
|
|
20
|
+
linked_tags: string[];
|
|
21
|
+
}
|
|
22
|
+
export type RelationshipEdge = Pick<Relationship, 'from_hash' | 'to_hash' | 'relation_type'>;
|
|
23
|
+
export interface BatchItemResult {
|
|
24
|
+
hash: string;
|
|
25
|
+
ok: boolean;
|
|
26
|
+
created?: boolean;
|
|
27
|
+
deleted?: boolean;
|
|
28
|
+
error?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface MemoryRow {
|
|
31
|
+
hash: string;
|
|
32
|
+
content: string;
|
|
33
|
+
tags: string;
|
|
34
|
+
memory_type: string;
|
|
35
|
+
importance: number;
|
|
36
|
+
created_at: string;
|
|
37
|
+
updated_at: string;
|
|
38
|
+
rank?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface RelationshipRow {
|
|
41
|
+
from_hash: string;
|
|
42
|
+
to_hash: string;
|
|
43
|
+
relation_type: string;
|
|
44
|
+
created_at: string;
|
|
45
|
+
linked_hash?: string;
|
|
46
|
+
linked_content?: string;
|
|
47
|
+
linked_tags?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface CountRow {
|
|
50
|
+
count: number;
|
|
51
|
+
}
|
|
52
|
+
export interface TotalRow {
|
|
53
|
+
total: number;
|
|
54
|
+
}
|
|
55
|
+
export interface EdgeRow {
|
|
56
|
+
from_hash: string;
|
|
57
|
+
to_hash: string;
|
|
58
|
+
relation_type: string;
|
|
59
|
+
}
|
|
60
|
+
export interface OldestRow {
|
|
61
|
+
oldest: string | null;
|
|
62
|
+
}
|
|
63
|
+
export interface NewestRow {
|
|
64
|
+
newest: string | null;
|
|
65
|
+
}
|
|
66
|
+
export interface TypeRow {
|
|
67
|
+
memory_type: string;
|
|
68
|
+
count: number;
|
|
69
|
+
}
|
|
70
|
+
export interface HashRow {
|
|
71
|
+
hash: string;
|
|
72
|
+
}
|
|
73
|
+
export declare function parseTags(tagsJson: string): string[];
|
|
74
|
+
export declare function parseMemoryRow(row: MemoryRow): Memory;
|
|
75
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,YAAY,EACZ,WAAW,GAAG,SAAS,GAAG,eAAe,CAC1C,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAUD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAOpD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CASrD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function asStringArray(value) {
|
|
2
|
+
if (!Array.isArray(value)) {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
return value.every((entry) => typeof entry === 'string') ? value : undefined;
|
|
6
|
+
}
|
|
7
|
+
export function parseTags(tagsJson) {
|
|
8
|
+
try {
|
|
9
|
+
const parsed = JSON.parse(tagsJson);
|
|
10
|
+
return asStringArray(parsed) ?? [];
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function parseMemoryRow(row) {
|
|
17
|
+
const { rank, ...rest } = row;
|
|
18
|
+
const relevance = rank != null ? -rank : undefined;
|
|
19
|
+
return {
|
|
20
|
+
...rest,
|
|
21
|
+
tags: parseTags(row.tags),
|
|
22
|
+
...(relevance != null ? { relevance } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAyFA,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7C,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAc;IAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnD,OAAO;QACL,GAAG,IAAI;QACP,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QACzB,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA+CzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAI1D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const INSTRUCTIONS_CONTENT = `# Memory Instructions
|
|
2
|
+
|
|
3
|
+
> Available as resource \`internal://instructions\`. Load when unsure about tool usage.
|
|
4
|
+
|
|
5
|
+
## CORE CAPABILITY
|
|
6
|
+
|
|
7
|
+
- Domain: SQLite-backed memory store with FTS5 search and knowledge graph for AI assistants.
|
|
8
|
+
- Tools: \`search_memories\` \`get_memory\` \`recall\` \`get_relationships\` \`memory_stats\` (READ); \`store_memory\` \`store_memories\` \`update_memory\` \`delete_memory\` \`delete_memories\` \`create_relationship\` \`delete_relationship\` (WRITE).
|
|
9
|
+
|
|
10
|
+
## WORKFLOWS
|
|
11
|
+
|
|
12
|
+
1. **Recall**: \`search_memories\` → \`recall\` → \`get_memory\`
|
|
13
|
+
2. **Store**: \`store_memory\` or \`store_memories\` (batch ≤50)
|
|
14
|
+
3. **Graph**: \`create_relationship\` → \`get_relationships\`
|
|
15
|
+
|
|
16
|
+
## RESOURCES
|
|
17
|
+
|
|
18
|
+
- \`internal://instructions\`: This document.
|
|
19
|
+
- \`memory://memories/{hash}\`: Single memory by SHA-256 hash.
|
|
20
|
+
`;
|
|
21
|
+
const HELP_MESSAGES = [
|
|
22
|
+
{
|
|
23
|
+
role: 'user',
|
|
24
|
+
content: {
|
|
25
|
+
type: 'text',
|
|
26
|
+
text: 'Show me the memory usage instructions.',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
role: 'assistant',
|
|
31
|
+
content: {
|
|
32
|
+
type: 'text',
|
|
33
|
+
text: INSTRUCTIONS_CONTENT,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
const GET_HELP_PROMPT_CONFIG = {
|
|
38
|
+
title: 'Get Help',
|
|
39
|
+
description: 'Return the full usage instructions for all memory tools and workflows.',
|
|
40
|
+
};
|
|
41
|
+
export function registerAllPrompts(server) {
|
|
42
|
+
server.registerPrompt('get-help', GET_HELP_PROMPT_CONFIG, () => ({
|
|
43
|
+
messages: HELP_MESSAGES,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAGA,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;CAmB5B,CAAC;AAEF,MAAM,aAAa,GAAoB;IACrC;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,wCAAwC;SAC/C;KACF;IACD;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,oBAAoB;SAC3B;KACF;CACF,CAAC;AAEF,MAAM,sBAAsB,GAAG;IAC7B,KAAK,EAAE,UAAU;IACjB,WAAW,EACT,wEAAwE;CAClE,CAAC;AAEX,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/D,QAAQ,EAAE,aAAa;KACxB,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAuD9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CA0DzE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { createHashCompletionCallback } from '../completions/index.js';
|
|
6
|
+
import { parseMemoryRow } from '../lib/types.js';
|
|
7
|
+
const BASE_DIR = fileURLToPath(new URL('.', import.meta.url));
|
|
8
|
+
const FALLBACK_INSTRUCTIONS = '# Memory instructions\n\nSee the README for usage details.';
|
|
9
|
+
const HASH_REGEX = /^[a-f0-9]{64}$/;
|
|
10
|
+
const INSTRUCTIONS_URI = 'internal://instructions';
|
|
11
|
+
function getInstructionPaths() {
|
|
12
|
+
return [
|
|
13
|
+
join(BASE_DIR, 'instructions.md'),
|
|
14
|
+
join(BASE_DIR, '..', 'instructions.md'),
|
|
15
|
+
join(BASE_DIR, '..', '..', 'src', 'instructions.md'),
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
function loadInstructions() {
|
|
19
|
+
const paths = getInstructionPaths();
|
|
20
|
+
for (const p of paths) {
|
|
21
|
+
try {
|
|
22
|
+
return readFileSync(p, 'utf8');
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// try next path
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return FALLBACK_INSTRUCTIONS;
|
|
29
|
+
}
|
|
30
|
+
function createJsonContent(uri, payload) {
|
|
31
|
+
return {
|
|
32
|
+
uri,
|
|
33
|
+
mimeType: 'application/json',
|
|
34
|
+
text: JSON.stringify(payload),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function getSingleVariable(value) {
|
|
38
|
+
return Array.isArray(value) ? value[0] : value;
|
|
39
|
+
}
|
|
40
|
+
function readMemoryByHash(db, hash) {
|
|
41
|
+
return db
|
|
42
|
+
.prepare('SELECT * FROM memories WHERE hash = ?')
|
|
43
|
+
.get(hash);
|
|
44
|
+
}
|
|
45
|
+
const INSTRUCTIONS_CONTENT = loadInstructions();
|
|
46
|
+
export function registerAllResources(server, db) {
|
|
47
|
+
server.registerResource('instructions', INSTRUCTIONS_URI, {
|
|
48
|
+
title: 'Memory Instructions',
|
|
49
|
+
description: 'Usage guide for all memory tools and workflows.',
|
|
50
|
+
mimeType: 'text/markdown',
|
|
51
|
+
annotations: { audience: ['assistant'], priority: 0.9 },
|
|
52
|
+
}, () => ({
|
|
53
|
+
contents: [
|
|
54
|
+
{
|
|
55
|
+
uri: INSTRUCTIONS_URI,
|
|
56
|
+
mimeType: 'text/markdown',
|
|
57
|
+
text: INSTRUCTIONS_CONTENT,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
}));
|
|
61
|
+
const hashCompletion = createHashCompletionCallback(db);
|
|
62
|
+
server.registerResource('memory', new ResourceTemplate('memory://memories/{hash}', {
|
|
63
|
+
list: undefined,
|
|
64
|
+
complete: { hash: hashCompletion },
|
|
65
|
+
}), {
|
|
66
|
+
title: 'Memory',
|
|
67
|
+
description: 'Retrieve a memory by its SHA-256 hash.',
|
|
68
|
+
mimeType: 'application/json',
|
|
69
|
+
annotations: { audience: ['assistant'], priority: 0.7 },
|
|
70
|
+
}, (uri, variables) => {
|
|
71
|
+
const rawHash = variables['hash'];
|
|
72
|
+
const hash = getSingleVariable(rawHash);
|
|
73
|
+
if (!hash || !HASH_REGEX.test(hash)) {
|
|
74
|
+
return {
|
|
75
|
+
contents: [createJsonContent(uri.href, { error: 'Invalid hash' })],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const row = readMemoryByHash(db, hash);
|
|
79
|
+
if (!row) {
|
|
80
|
+
return {
|
|
81
|
+
contents: [createJsonContent(uri.href, { error: 'Not found', hash })],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
contents: [createJsonContent(uri.href, parseMemoryRow(row))],
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAE5B,cAAc,cAAc,CAAC"}
|