@vheins/local-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/DASHBOARD.md +129 -0
- package/HYBRID_SEARCH.md +204 -0
- package/IMPLEMENTATION.md +159 -0
- package/README.md +175 -0
- package/dist/capabilities.d.ts +22 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +23 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/dashboard/dashboard.test.d.ts +2 -0
- package/dist/dashboard/dashboard.test.d.ts.map +1 -0
- package/dist/dashboard/dashboard.test.js +362 -0
- package/dist/dashboard/dashboard.test.js.map +1 -0
- package/dist/dashboard/public/app.js +1187 -0
- package/dist/dashboard/public/chart.js +0 -0
- package/dist/dashboard/public/index.html +967 -0
- package/dist/dashboard/server.d.ts +3 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +297 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/mcp/client.d.ts +34 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +181 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/client.test.d.ts +2 -0
- package/dist/mcp/client.test.d.ts.map +1 -0
- package/dist/mcp/client.test.js +130 -0
- package/dist/mcp/client.test.js.map +1 -0
- package/dist/prompts/registry.d.ts +39 -0
- package/dist/prompts/registry.d.ts.map +1 -0
- package/dist/prompts/registry.js +90 -0
- package/dist/prompts/registry.js.map +1 -0
- package/dist/resources/index.d.ts +17 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +100 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/index.test.d.ts +2 -0
- package/dist/resources/index.test.d.ts.map +1 -0
- package/dist/resources/index.test.js +96 -0
- package/dist/resources/index.test.js.map +1 -0
- package/dist/router.d.ts +4 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +60 -0
- package/dist/router.js.map +1 -0
- package/dist/router.test.d.ts +2 -0
- package/dist/router.test.d.ts.map +1 -0
- package/dist/router.test.js +113 -0
- package/dist/router.test.js.map +1 -0
- package/dist/search_memory_example.d.ts +3 -0
- package/dist/search_memory_example.d.ts.map +1 -0
- package/dist/search_memory_example.js +56 -0
- package/dist/search_memory_example.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +91 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/sqlite.d.ts +95 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +537 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/storage/sqlite.test.d.ts +2 -0
- package/dist/storage/sqlite.test.d.ts.map +1 -0
- package/dist/storage/sqlite.test.js +358 -0
- package/dist/storage/sqlite.test.js.map +1 -0
- package/dist/storage/vectors.stub.d.ts +12 -0
- package/dist/storage/vectors.stub.d.ts.map +1 -0
- package/dist/storage/vectors.stub.js +88 -0
- package/dist/storage/vectors.stub.js.map +1 -0
- package/dist/store_memory_example.d.ts +3 -0
- package/dist/store_memory_example.d.ts.map +1 -0
- package/dist/store_memory_example.js +69 -0
- package/dist/store_memory_example.js.map +1 -0
- package/dist/test_quotes_client.d.ts +3 -0
- package/dist/test_quotes_client.d.ts.map +1 -0
- package/dist/test_quotes_client.js +72 -0
- package/dist/test_quotes_client.js.map +1 -0
- package/dist/tools/memory.delete.d.ts +9 -0
- package/dist/tools/memory.delete.d.ts.map +1 -0
- package/dist/tools/memory.delete.js +22 -0
- package/dist/tools/memory.delete.js.map +1 -0
- package/dist/tools/memory.recap.d.ts +4 -0
- package/dist/tools/memory.recap.d.ts.map +1 -0
- package/dist/tools/memory.recap.js +42 -0
- package/dist/tools/memory.recap.js.map +1 -0
- package/dist/tools/memory.search.d.ts +5 -0
- package/dist/tools/memory.search.d.ts.map +1 -0
- package/dist/tools/memory.search.js +192 -0
- package/dist/tools/memory.search.js.map +1 -0
- package/dist/tools/memory.search.test.d.ts +2 -0
- package/dist/tools/memory.search.test.d.ts.map +1 -0
- package/dist/tools/memory.search.test.js +181 -0
- package/dist/tools/memory.search.test.js.map +1 -0
- package/dist/tools/memory.store.d.ts +5 -0
- package/dist/tools/memory.store.d.ts.map +1 -0
- package/dist/tools/memory.store.js +41 -0
- package/dist/tools/memory.store.js.map +1 -0
- package/dist/tools/memory.summarize.d.ts +4 -0
- package/dist/tools/memory.summarize.d.ts.map +1 -0
- package/dist/tools/memory.summarize.js +13 -0
- package/dist/tools/memory.summarize.js.map +1 -0
- package/dist/tools/memory.update.d.ts +5 -0
- package/dist/tools/memory.update.d.ts.map +1 -0
- package/dist/tools/memory.update.js +31 -0
- package/dist/tools/memory.update.js.map +1 -0
- package/dist/tools/schemas.d.ts +334 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +251 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/git-scope.d.ts +8 -0
- package/dist/utils/git-scope.d.ts.map +1 -0
- package/dist/utils/git-scope.js +38 -0
- package/dist/utils/git-scope.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +40 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/logger.test.d.ts +2 -0
- package/dist/utils/logger.test.d.ts.map +1 -0
- package/dist/utils/logger.test.js +84 -0
- package/dist/utils/logger.test.js.map +1 -0
- package/dist/utils/mcp-response.d.ts +44 -0
- package/dist/utils/mcp-response.d.ts.map +1 -0
- package/dist/utils/mcp-response.js +81 -0
- package/dist/utils/mcp-response.js.map +1 -0
- package/dist/utils/normalize.d.ts +4 -0
- package/dist/utils/normalize.d.ts.map +1 -0
- package/dist/utils/normalize.js +51 -0
- package/dist/utils/normalize.js.map +1 -0
- package/dist/utils/normalize.test.d.ts +2 -0
- package/dist/utils/normalize.test.d.ts.map +1 -0
- package/dist/utils/normalize.test.js +159 -0
- package/dist/utils/normalize.test.js.map +1 -0
- package/dist/utils/query-expander.d.ts +2 -0
- package/dist/utils/query-expander.d.ts.map +1 -0
- package/dist/utils/query-expander.js +50 -0
- package/dist/utils/query-expander.js.map +1 -0
- package/dist/utils/query-expander.test.d.ts +2 -0
- package/dist/utils/query-expander.test.d.ts.map +1 -0
- package/dist/utils/query-expander.test.js +35 -0
- package/dist/utils/query-expander.test.js.map +1 -0
- package/docs/PRD.md +199 -0
- package/docs/PROMPT-agent.md +139 -0
- package/docs/SPEC-git-scope.md +172 -0
- package/docs/SPEC-heuristics.md +199 -0
- package/docs/SPEC-server.md +243 -0
- package/docs/SPEC-skeleton.md +255 -0
- package/docs/SPEC-sqlite-schema.md +183 -0
- package/docs/SPEC-tool-schema.md +201 -0
- package/docs/SPEC-vector-search.md +198 -0
- package/docs/TEST-scenarios.md +179 -0
- package/package.json +43 -0
- package/scripts/update-null-titles-ai.mjs +272 -0
- package/scripts/update-titles-batch.mjs +71 -0
- package/scripts/update-titles.mjs +66 -0
- package/seed-data.mjs +151 -0
- package/src/capabilities.ts +22 -0
- package/src/dashboard/dashboard.test.ts +546 -0
- package/src/dashboard/public/app.js +1187 -0
- package/src/dashboard/public/chart.js +0 -0
- package/src/dashboard/public/index.html +967 -0
- package/src/dashboard/server.ts +347 -0
- package/src/mcp/client.test.ts +164 -0
- package/src/mcp/client.ts +212 -0
- package/src/prompts/registry.ts +89 -0
- package/src/resources/index.test.ts +132 -0
- package/src/resources/index.ts +113 -0
- package/src/router.test.ts +145 -0
- package/src/router.ts +80 -0
- package/src/server.ts +99 -0
- package/src/storage/sqlite.test.ts +504 -0
- package/src/storage/sqlite.ts +688 -0
- package/src/storage/vectors.stub.ts +101 -0
- package/src/tools/memory.delete.ts +37 -0
- package/src/tools/memory.recap.ts +61 -0
- package/src/tools/memory.search.test.ts +276 -0
- package/src/tools/memory.search.ts +244 -0
- package/src/tools/memory.store.ts +56 -0
- package/src/tools/memory.summarize.ts +23 -0
- package/src/tools/memory.update.ts +46 -0
- package/src/tools/schemas.ts +261 -0
- package/src/types.ts +36 -0
- package/src/utils/git-scope.ts +42 -0
- package/src/utils/logger.test.ts +125 -0
- package/src/utils/logger.ts +53 -0
- package/src/utils/mcp-response.ts +116 -0
- package/src/utils/normalize.test.ts +203 -0
- package/src/utils/normalize.ts +53 -0
- package/src/utils/query-expander.test.ts +40 -0
- package/src/utils/query-expander.ts +60 -0
- package/storage/.gitkeep +5 -0
- package/test.sh +48 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Spec – MCP Tool Schema & Validation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Dokumen ini mendefinisikan tool schema final + aturan validasi untuk MCP Local Memory Server.
|
|
6
|
+
|
|
7
|
+
**Fokus dokumen ini:**
|
|
8
|
+
- Kontrak tool yang stabil & agent-safe
|
|
9
|
+
- Validasi ketat untuk mencegah memory pollution
|
|
10
|
+
- Konsisten dengan skeleton server & git scope resolver
|
|
11
|
+
|
|
12
|
+
> *Prinsip: tolak request buruk lebih awal. Memory jelek lebih berbahaya daripada tidak ada memory.*
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Design Principles
|
|
17
|
+
|
|
18
|
+
1. **Schema-first** – logic mengikuti schema, bukan sebaliknya
|
|
19
|
+
2. **Fail fast** – invalid input langsung reject
|
|
20
|
+
3. **Repo-scoped by default**
|
|
21
|
+
4. **Minimal surface area**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Shared Types
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
type MemoryType = "code_fact" | "decision" | "mistake" | "pattern";
|
|
29
|
+
|
|
30
|
+
type MemoryScope = {
|
|
31
|
+
repo: string;
|
|
32
|
+
branch?: string;
|
|
33
|
+
folder?: string;
|
|
34
|
+
language?: string;
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Tool: `memory.store`
|
|
41
|
+
|
|
42
|
+
**Purpose:**
|
|
43
|
+
Menyimpan memory baru yang berdampak jangka panjang.
|
|
44
|
+
|
|
45
|
+
**Input Schema:**
|
|
46
|
+
```typescript
|
|
47
|
+
{
|
|
48
|
+
type: MemoryType;
|
|
49
|
+
content: string;
|
|
50
|
+
importance: number; // 1–5
|
|
51
|
+
scope: MemoryScope;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Validation Rules (WAJIB):**
|
|
56
|
+
- `content.length >= 10`
|
|
57
|
+
- `importance` antara 1–5
|
|
58
|
+
- `scope.repo` **REQUIRED** & non-empty
|
|
59
|
+
- `content` **tidak boleh**:
|
|
60
|
+
- pertanyaan
|
|
61
|
+
- speculative language ("mungkin", "kayaknya")
|
|
62
|
+
|
|
63
|
+
**Semantic Guardrails:**
|
|
64
|
+
- Tolak jika `content` mengandung:
|
|
65
|
+
- brainstorming
|
|
66
|
+
- diskusi sementara
|
|
67
|
+
- opini subjektif
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Tool: `memory.update`
|
|
72
|
+
|
|
73
|
+
**Purpose:**
|
|
74
|
+
Update memory yang sudah ada.
|
|
75
|
+
|
|
76
|
+
**Input Schema:**
|
|
77
|
+
```typescript
|
|
78
|
+
{
|
|
79
|
+
id: string; // uuid
|
|
80
|
+
content?: string;
|
|
81
|
+
importance?: number;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Validation Rules:**
|
|
86
|
+
- `id` **REQUIRED**
|
|
87
|
+
- Minimal 1 field selain id
|
|
88
|
+
- Update tidak boleh mengubah `scope.repo`
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Tool: `memory.search`
|
|
93
|
+
|
|
94
|
+
**Purpose:**
|
|
95
|
+
Mencari memory relevan untuk augment prompt.
|
|
96
|
+
|
|
97
|
+
**Input Schema:**
|
|
98
|
+
```typescript
|
|
99
|
+
{
|
|
100
|
+
query: string;
|
|
101
|
+
repo: string;
|
|
102
|
+
types?: MemoryType[];
|
|
103
|
+
minImportance?: number;
|
|
104
|
+
limit?: number; // default 5
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Validation Rules:**
|
|
109
|
+
- `query.length >= 3`
|
|
110
|
+
- `repo` **REQUIRED**
|
|
111
|
+
- `limit` max 10
|
|
112
|
+
|
|
113
|
+
**Behavioral Rules:**
|
|
114
|
+
- Repo mismatch → **reject**
|
|
115
|
+
- No global search
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Tool: `memory.summarize`
|
|
120
|
+
|
|
121
|
+
**Purpose:**
|
|
122
|
+
Update antigravity summary per repo.
|
|
123
|
+
|
|
124
|
+
**Input Schema:**
|
|
125
|
+
```typescript
|
|
126
|
+
{
|
|
127
|
+
repo: string;
|
|
128
|
+
signals: string[];
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Validation Rules:**
|
|
133
|
+
- `repo` **REQUIRED**
|
|
134
|
+
- `signals.length >= 1`
|
|
135
|
+
- Setiap signal max 200 chars
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Zod Validation Example
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { z } from "zod";
|
|
143
|
+
|
|
144
|
+
export const MemoryStoreSchema = z.object({
|
|
145
|
+
type: z.enum(["code_fact", "decision", "mistake", "pattern"]),
|
|
146
|
+
content: z.string().min(10),
|
|
147
|
+
importance: z.number().min(1).max(5),
|
|
148
|
+
scope: z.object({
|
|
149
|
+
repo: z.string().min(1),
|
|
150
|
+
branch: z.string().optional(),
|
|
151
|
+
folder: z.string().optional(),
|
|
152
|
+
language: z.string().optional()
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Tool Registration (`router.ts`)
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
case "tools/list":
|
|
163
|
+
return {
|
|
164
|
+
tools: [
|
|
165
|
+
{ name: "memory.store", inputSchema: MemoryStoreSchema },
|
|
166
|
+
{ name: "memory.search", inputSchema: MemorySearchSchema },
|
|
167
|
+
{ name: "memory.update", inputSchema: MemoryUpdateSchema },
|
|
168
|
+
{ name: "memory.summarize", inputSchema: MemorySummarizeSchema }
|
|
169
|
+
]
|
|
170
|
+
};
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Error Strategy (Opinionated)
|
|
176
|
+
|
|
177
|
+
- Validation error → `-32602 Invalid params`
|
|
178
|
+
- Scope missing → **hard error**
|
|
179
|
+
- Silent fallback → **DILARANG**
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Anti-Patterns (DILARANG)
|
|
184
|
+
|
|
185
|
+
- ❌ Auto-coerce input
|
|
186
|
+
- ❌ Infer repo implicitly in search
|
|
187
|
+
- ❌ Store memory without scope
|
|
188
|
+
- ❌ Accept vague content
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Final Take
|
|
193
|
+
|
|
194
|
+
Tool schema adalah kontrak moral antara agent dan memory.
|
|
195
|
+
|
|
196
|
+
**Kalau schema ini dijaga ketat:**
|
|
197
|
+
- Memory tetap bersih
|
|
198
|
+
- Agent makin konsisten
|
|
199
|
+
- Antigravity benar-benar terasa
|
|
200
|
+
|
|
201
|
+
Ini fondasi sebelum masuk ke SQLite & vector DB.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Spec – Vector Search Stub & Similarity Layer
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Dokumen ini mendefinisikan vector search layer (stub) untuk MCP Local Memory Server.
|
|
6
|
+
|
|
7
|
+
**Fokus dokumen ini:**
|
|
8
|
+
- Menyediakan abstraction yang benar sebelum embedding/model dipilih
|
|
9
|
+
- Mendukung typo, paraphrase, dan semantic similarity
|
|
10
|
+
- Aman untuk diintegrasikan dengan SQLite schema yang sudah ada
|
|
11
|
+
|
|
12
|
+
> *Prinsip: jangan nikahi embedding atau library terlalu cepat.*
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Design Goals
|
|
17
|
+
|
|
18
|
+
1. **Replaceable** – embedding & index bisa diganti
|
|
19
|
+
2. **Predictable** – ranking stabil
|
|
20
|
+
3. **Repo-scoped** – tidak ada cross-project similarity
|
|
21
|
+
4. **Fail-safe** – jika vector gagal, agent tetap jalan
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Conceptual Model
|
|
26
|
+
|
|
27
|
+
```mermaid
|
|
28
|
+
graph TD
|
|
29
|
+
A[query text] --> B[normalize]
|
|
30
|
+
B --> C[embed - stub dulu]
|
|
31
|
+
C --> D[vector search]
|
|
32
|
+
D --> E[rank + filter]
|
|
33
|
+
E --> F[return memory IDs]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
*Vector layer tidak pernah return full memory.*
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Vector Responsibility Boundary
|
|
41
|
+
|
|
42
|
+
**Vector Layer BOLEH:**
|
|
43
|
+
- Hitung similarity
|
|
44
|
+
- Return memory_id + score
|
|
45
|
+
|
|
46
|
+
**Vector Layer TIDAK BOLEH:**
|
|
47
|
+
- Filter by repo (harus sudah dilakukan)
|
|
48
|
+
- Filter by type / importance
|
|
49
|
+
- Mengubah atau menulis data
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Vector Interface (Canonical)
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
export type VectorResult = {
|
|
57
|
+
id: string;
|
|
58
|
+
score: number; // 0.0 – 1.0
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export interface VectorStore {
|
|
62
|
+
upsert(id: string, text: string): Promise<void>;
|
|
63
|
+
remove(id: string): Promise<void>;
|
|
64
|
+
search(query: string, limit: number): Promise<VectorResult[]>;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
*Ini kontrak WAJIB dijaga.*
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Stub Implementation (No Embedding Yet)
|
|
73
|
+
|
|
74
|
+
`storage/vectors.stub.ts`
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { VectorStore, VectorResult } from "./types.js";
|
|
78
|
+
|
|
79
|
+
export class StubVectorStore implements VectorStore {
|
|
80
|
+
async upsert(id: string, text: string) {
|
|
81
|
+
// no-op
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async remove(id: string) {
|
|
85
|
+
// no-op
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async search(query: string, limit: number): Promise<VectorResult[]> {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Dengan stub ini:**
|
|
95
|
+
- MCP server jalan
|
|
96
|
+
- Tool contract stabil
|
|
97
|
+
- Vector bisa ditambahkan belakangan
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Normalization Layer (WAJIB)
|
|
102
|
+
|
|
103
|
+
Normalization dilakukan sebelum embedding.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
export function normalize(text: string): string {
|
|
107
|
+
return text
|
|
108
|
+
.toLowerCase()
|
|
109
|
+
.replace(/[^a-z0-9\s]/g, " ")
|
|
110
|
+
.replace(/\s+/g, " ")
|
|
111
|
+
.trim();
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
*Normalization ini sudah membantu typo ringan, bahkan tanpa vector.*
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Ranking Strategy (Server-side)
|
|
120
|
+
|
|
121
|
+
Vector similarity **BUKAN** satu-satunya sinyal.
|
|
122
|
+
|
|
123
|
+
**Final score =**
|
|
124
|
+
```
|
|
125
|
+
(similarity * 0.7)
|
|
126
|
+
+ (importanceBoost * 0.2)
|
|
127
|
+
+ (recencyBoost * 0.1)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Dimana:**
|
|
131
|
+
- `importanceBoost` = `importance / 5`
|
|
132
|
+
- `recencyBoost` = decay berdasarkan `created_at`
|
|
133
|
+
|
|
134
|
+
> *Ini bikin agent terasa stabil & dewasa.*
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## `memory.search` Integration Flow
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// 1. fetch candidates by repo + importance
|
|
142
|
+
// 2. vector.search(query)
|
|
143
|
+
// 3. merge scores
|
|
144
|
+
// 4. threshold + limit
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
*Jika vector kosong → fallback ke keyword match.*
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Fallback Strategy (WAJIB)
|
|
152
|
+
|
|
153
|
+
**Jika:**
|
|
154
|
+
- embedding service down
|
|
155
|
+
- vector index corrupt
|
|
156
|
+
|
|
157
|
+
**Maka:**
|
|
158
|
+
- Gunakan `LIKE %query%` di SQLite
|
|
159
|
+
- Tetap hormati repo boundary
|
|
160
|
+
|
|
161
|
+
*Agent tidak boleh error karena vector.*
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Future Implementations (Drop-in)
|
|
166
|
+
|
|
167
|
+
VectorStore bisa diganti dengan:
|
|
168
|
+
- sqlite-vec
|
|
169
|
+
- sqlite-vss
|
|
170
|
+
- hnswlib-node
|
|
171
|
+
- faiss (via binding)
|
|
172
|
+
|
|
173
|
+
**Tanpa mengubah:**
|
|
174
|
+
- tool schema
|
|
175
|
+
- MCP contract
|
|
176
|
+
- agent prompt
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Anti-Patterns (DILARANG)
|
|
181
|
+
|
|
182
|
+
- ❌ Store vector tanpa text canonical
|
|
183
|
+
- ❌ Vector sebagai source of truth
|
|
184
|
+
- ❌ Global vector index lintas repo
|
|
185
|
+
- ❌ Tuning threshold tanpa test
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Final Take
|
|
190
|
+
|
|
191
|
+
Vector layer adalah **amplifier**, bukan otak.
|
|
192
|
+
|
|
193
|
+
**Kalau stub + boundary ini dijaga:**
|
|
194
|
+
- Kamu bisa eksperimen bebas
|
|
195
|
+
- Agent tetap stabil
|
|
196
|
+
- Produk tidak terkunci vendor
|
|
197
|
+
|
|
198
|
+
Ini langkah terakhir sebelum implementasi embedding nyata.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Test Scenarios – MCP Local Memory
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Dokumen ini berisi test scenarios konseptual & praktis untuk memverifikasi bahwa MCP Local Memory:
|
|
6
|
+
- Menyimpan memory yang benar
|
|
7
|
+
- Menolak memory yang buruk
|
|
8
|
+
- Tidak bocor lintas repo
|
|
9
|
+
- Mendukung antigravity behavior
|
|
10
|
+
|
|
11
|
+
*Test ini bukan unit test code, tapi behavioral contract test untuk agent + MCP server.*
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Test Category Overview
|
|
16
|
+
|
|
17
|
+
1. **Memory Quality** (Good vs Bad)
|
|
18
|
+
2. **Repo / Git Scoping**
|
|
19
|
+
3. **Auto-Memory Heuristics**
|
|
20
|
+
4. **Vector & Fallback Behavior**
|
|
21
|
+
5. **Antigravity Consistency**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 1. Memory Quality Tests
|
|
26
|
+
|
|
27
|
+
### 1.1 GOOD – Architectural Decision
|
|
28
|
+
**Context:** Repo `backend-api`
|
|
29
|
+
|
|
30
|
+
**User:**
|
|
31
|
+
> "Kita tidak akan pakai ORM di project ini, semua query pakai raw SQL."
|
|
32
|
+
|
|
33
|
+
**Expected Agent Behavior:**
|
|
34
|
+
- Detect as `decision`
|
|
35
|
+
- `importance = 5`
|
|
36
|
+
- `scope.repo = backend-api`
|
|
37
|
+
- Call `memory.store`
|
|
38
|
+
|
|
39
|
+
**Expected Stored Memory:**
|
|
40
|
+
```
|
|
41
|
+
Type: decision
|
|
42
|
+
Content: Do not use ORM; use raw SQL for all database access
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 1.2 BAD – Temporary Discussion
|
|
46
|
+
**User:**
|
|
47
|
+
> "Coba dulu pakai cara ini, nanti lihat hasilnya."
|
|
48
|
+
|
|
49
|
+
**Expected Behavior:**
|
|
50
|
+
- ❌ **DO NOT** store memory
|
|
51
|
+
- Continue task without memory
|
|
52
|
+
|
|
53
|
+
### 1.3 BAD – Opinion Only
|
|
54
|
+
**User:**
|
|
55
|
+
> "Menurutku style ini lebih enak dibaca."
|
|
56
|
+
|
|
57
|
+
**Expected Behavior:**
|
|
58
|
+
- ❌ **DO NOT** store memory
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 2. Repo / Git Scope Tests
|
|
63
|
+
|
|
64
|
+
### 2.1 GOOD – Same Repo Retrieval
|
|
65
|
+
**Repo:** `frontend-app`
|
|
66
|
+
|
|
67
|
+
**Existing Memory:**
|
|
68
|
+
`decision: Use React Query for data fetching`
|
|
69
|
+
|
|
70
|
+
**User Prompt:**
|
|
71
|
+
> "Buatkan hook untuk fetch user profile"
|
|
72
|
+
|
|
73
|
+
**Expected Behavior:**
|
|
74
|
+
- `memory.search` with `repo = frontend-app`
|
|
75
|
+
- Inject React Query constraint
|
|
76
|
+
|
|
77
|
+
### 2.2 BAD – Cross Repo Leakage
|
|
78
|
+
**Repo A:** `backend-api`
|
|
79
|
+
**Repo B:** `frontend-app`
|
|
80
|
+
|
|
81
|
+
**Existing Memory (Repo A):**
|
|
82
|
+
`decision: Do not use ORM`
|
|
83
|
+
|
|
84
|
+
**User Prompt (Repo B):**
|
|
85
|
+
> "Setup database access"
|
|
86
|
+
|
|
87
|
+
**Expected Behavior:**
|
|
88
|
+
- ❌ Memory from Repo A **NOT** retrieved
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 3. Auto-Memory Heuristics Tests
|
|
93
|
+
|
|
94
|
+
### 3.1 GOOD – Repeated Correction
|
|
95
|
+
**Agent Output:**
|
|
96
|
+
Uses default export
|
|
97
|
+
|
|
98
|
+
**User Correction:**
|
|
99
|
+
> "Jangan pakai default export di domain layer."
|
|
100
|
+
|
|
101
|
+
**Expected Behavior:**
|
|
102
|
+
- Detect as `mistake`
|
|
103
|
+
- Store memory after confirmation
|
|
104
|
+
|
|
105
|
+
### 3.2 BAD – Single Minor Correction
|
|
106
|
+
**User:**
|
|
107
|
+
> "Yang ini ganti nama variabel aja."
|
|
108
|
+
|
|
109
|
+
**Expected Behavior:**
|
|
110
|
+
- ❌ **DO NOT** store memory
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 4. Vector & Fallback Tests
|
|
115
|
+
|
|
116
|
+
### 4.1 Typo Tolerance
|
|
117
|
+
**Stored Memory:**
|
|
118
|
+
`decision: Do not use ORM`
|
|
119
|
+
|
|
120
|
+
**User Query:**
|
|
121
|
+
> "Jangan pake ormm ya"
|
|
122
|
+
|
|
123
|
+
**Expected Behavior:**
|
|
124
|
+
- `normalize(query)`
|
|
125
|
+
- `memory.search` returns `decision`
|
|
126
|
+
|
|
127
|
+
### 4.2 Vector Failure Fallback
|
|
128
|
+
**Condition:**
|
|
129
|
+
Vector index unavailable
|
|
130
|
+
|
|
131
|
+
**Expected Behavior:**
|
|
132
|
+
- Fallback to SQLite keyword search
|
|
133
|
+
- Agent still works
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 5. Antigravity Consistency Tests
|
|
138
|
+
|
|
139
|
+
### 5.1 Long Session Drift Prevention
|
|
140
|
+
**Day 1:**
|
|
141
|
+
Decision stored: `Use clean architecture`
|
|
142
|
+
|
|
143
|
+
**Day 5 User Prompt:**
|
|
144
|
+
> "Buat handler cepat aja tanpa layer ribet"
|
|
145
|
+
|
|
146
|
+
**Expected Behavior:**
|
|
147
|
+
- Agent retrieves decision
|
|
148
|
+
- Push back politely
|
|
149
|
+
- Follow clean architecture
|
|
150
|
+
|
|
151
|
+
### 5.2 Summary Usage
|
|
152
|
+
**Condition:**
|
|
153
|
+
`memory_summary` exists for repo
|
|
154
|
+
|
|
155
|
+
**Expected Behavior:**
|
|
156
|
+
- Agent reads summary **BEFORE** `memory.search`
|
|
157
|
+
- Uses summary to guide reasoning
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Failure Signals (Red Flags)
|
|
162
|
+
|
|
163
|
+
- 🚨 Memory count grows rapidly
|
|
164
|
+
- 🚨 Agent output inconsistent day-to-day
|
|
165
|
+
- 🚨 Same correction repeated often
|
|
166
|
+
- 🚨 Cross-project rules applied
|
|
167
|
+
|
|
168
|
+
*Jika muncul → heuristics atau scope resolver salah.*
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Final Take
|
|
173
|
+
|
|
174
|
+
Kalau semua test ini lulus:
|
|
175
|
+
- Memory kamu bersih
|
|
176
|
+
- Agent kamu stabil
|
|
177
|
+
- Antigravity behavior nyata
|
|
178
|
+
|
|
179
|
+
Test ini sebaiknya dijalankan manual di awal, lalu dijadikan automated regression tests.
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vheins/local-memory-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP Local Memory Service for coding copilot agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/server.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-memory-local": "./dist/server.js",
|
|
9
|
+
"mcp-memory-dashboard": "./dist/dashboard/server.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc && mkdir -p dist/dashboard/public && rsync -a --delete src/dashboard/public/ dist/dashboard/public/",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"start": "node dist/server.js",
|
|
15
|
+
"dashboard": "node dist/dashboard/server.js",
|
|
16
|
+
"both": "npm run start & npm run dashboard",
|
|
17
|
+
"test": "vitest --run",
|
|
18
|
+
"test:watch": "vitest"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"mcp",
|
|
22
|
+
"memory",
|
|
23
|
+
"ai",
|
|
24
|
+
"coding-copilot"
|
|
25
|
+
],
|
|
26
|
+
"author": "",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"better-sqlite3": "^12.6.2",
|
|
30
|
+
"express": "^5.2.1",
|
|
31
|
+
"qs": "^6.15.0",
|
|
32
|
+
"zod": "^4.3.5"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@fast-check/vitest": "^0.3.0",
|
|
36
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
37
|
+
"@types/express": "^5.0.6",
|
|
38
|
+
"@types/node": "^22.19.7",
|
|
39
|
+
"fast-check": "^4.6.0",
|
|
40
|
+
"typescript": "^5.7.3",
|
|
41
|
+
"vitest": "^4.1.1"
|
|
42
|
+
}
|
|
43
|
+
}
|