@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,243 @@
|
|
|
1
|
+
# MCP Local Memory Server – Skeleton Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Dokumen ini mendefinisikan skeleton MCP server lokal (Node.js) yang:
|
|
6
|
+
- Kompatibel secara konsep dengan MCP Memory berbasis remote API
|
|
7
|
+
- Minimal tapi lengkap: resources, tools, prompts
|
|
8
|
+
- Siap dikembangkan ke SQLite + vector DB
|
|
9
|
+
- Dirancang untuk coding copilot & antigravity agent
|
|
10
|
+
|
|
11
|
+
Skeleton ini bukan full implementation, tapi contract + struktur agar:
|
|
12
|
+
- Agent tidak perlu diubah
|
|
13
|
+
- Remote MCP bisa diganti local MCP tanpa friction
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Design Principles
|
|
18
|
+
|
|
19
|
+
1. **Contract-first, storage-second**
|
|
20
|
+
2. **Agent-facing API harus stabil**
|
|
21
|
+
3. **Memory high-signal only**
|
|
22
|
+
4. **Strict project / git scoping**
|
|
23
|
+
5. **Local-first, no auth by default**
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Server Capabilities
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"resources": { "list": true, "read": true, "templates": true },
|
|
32
|
+
"tools": { "list": true, "call": true },
|
|
33
|
+
"prompts": { "list": true, "get": true }
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Resources
|
|
40
|
+
|
|
41
|
+
### 1. `memory://index`
|
|
42
|
+
**Purpose:** Lightweight discovery index (metadata only).
|
|
43
|
+
**Contract:**
|
|
44
|
+
- Returns list of recent memory entries
|
|
45
|
+
- **MUST NOT** include full content
|
|
46
|
+
- Used for de-duplication & inspection
|
|
47
|
+
|
|
48
|
+
### 2. `memory://{id}`
|
|
49
|
+
**Purpose:** Read a single memory entry.
|
|
50
|
+
**Returned Fields:**
|
|
51
|
+
```typescript
|
|
52
|
+
{
|
|
53
|
+
id: string
|
|
54
|
+
type: "code_fact" | "decision" | "mistake" | "pattern"
|
|
55
|
+
content: string
|
|
56
|
+
importance: number
|
|
57
|
+
scope: { repo: string }
|
|
58
|
+
created_at: string
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. `memory://summary/{repo}`
|
|
63
|
+
**Purpose:** Antigravity snapshot per project / repo.
|
|
64
|
+
**Notes:**
|
|
65
|
+
- High-level only
|
|
66
|
+
- Used before any search
|
|
67
|
+
|
|
68
|
+
### 4. `schema://mcp`
|
|
69
|
+
**Purpose:** Machine-readable schema for tools, resources, prompts.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Resource Templates
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
[
|
|
77
|
+
{ "uriTemplate": "memory://index", "description": "Recent memory index (metadata only)" },
|
|
78
|
+
{ "uriTemplate": "memory://{id}", "description": "Read individual memory" },
|
|
79
|
+
{ "uriTemplate": "memory://summary/{repo}", "description": "Project summary" },
|
|
80
|
+
{ "uriTemplate": "schema://mcp", "description": "MCP schema" }
|
|
81
|
+
]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Tools (Minimal Set)
|
|
87
|
+
|
|
88
|
+
> Tool names intentionally mirip secara semantik dengan remote MCP, tapi disederhanakan untuk local usage.
|
|
89
|
+
|
|
90
|
+
### 1. `memory.store`
|
|
91
|
+
Create a new memory entry.
|
|
92
|
+
|
|
93
|
+
**Input:**
|
|
94
|
+
```typescript
|
|
95
|
+
{
|
|
96
|
+
type: "code_fact" | "decision" | "mistake" | "pattern"
|
|
97
|
+
content: string
|
|
98
|
+
importance: number
|
|
99
|
+
scope: { repo: string, folder?: string, language?: string }
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
**Rules:**
|
|
103
|
+
- `repo` is **REQUIRED**
|
|
104
|
+
- No speculative or temporary info
|
|
105
|
+
|
|
106
|
+
### 2. `memory.update`
|
|
107
|
+
Update existing memory.
|
|
108
|
+
|
|
109
|
+
**Input:**
|
|
110
|
+
```typescript
|
|
111
|
+
{
|
|
112
|
+
id: string
|
|
113
|
+
content?: string
|
|
114
|
+
importance?: number
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. `memory.search`
|
|
119
|
+
Semantic + filtered search.
|
|
120
|
+
|
|
121
|
+
**Input:**
|
|
122
|
+
```typescript
|
|
123
|
+
{
|
|
124
|
+
query: string
|
|
125
|
+
repo: string
|
|
126
|
+
types?: ("code_fact" | "decision" | "mistake" | "pattern")[]
|
|
127
|
+
minImportance?: number
|
|
128
|
+
limit?: number
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
**Behavior:**
|
|
132
|
+
- Vector similarity search
|
|
133
|
+
- Repo match is **mandatory**
|
|
134
|
+
|
|
135
|
+
### 4. `memory.summarize`
|
|
136
|
+
Update antigravity summary.
|
|
137
|
+
|
|
138
|
+
**Input:**
|
|
139
|
+
```typescript
|
|
140
|
+
{
|
|
141
|
+
repo: string
|
|
142
|
+
signals: string[]
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Prompts
|
|
149
|
+
|
|
150
|
+
### 1. `memory-agent-core`
|
|
151
|
+
**Purpose:** Core behavioral contract.
|
|
152
|
+
|
|
153
|
+
> You are a coding copilot agent.
|
|
154
|
+
>
|
|
155
|
+
> You must:
|
|
156
|
+
> - Respect stored decisions and constraints
|
|
157
|
+
> - Avoid repeating known mistakes
|
|
158
|
+
> - Use memory only when relevant
|
|
159
|
+
>
|
|
160
|
+
> Memory is a source of truth, not a suggestion.
|
|
161
|
+
|
|
162
|
+
### 2. `memory-index-policy`
|
|
163
|
+
**Purpose:** Enforce strict memory discipline.
|
|
164
|
+
|
|
165
|
+
> Do not store:
|
|
166
|
+
> - Temporary discussions
|
|
167
|
+
> - Brainstorming
|
|
168
|
+
> - Subjective opinions
|
|
169
|
+
>
|
|
170
|
+
> Only store durable knowledge.
|
|
171
|
+
|
|
172
|
+
### 3. `tool-usage-guidelines`
|
|
173
|
+
**Purpose:** Prevent tool abuse.
|
|
174
|
+
|
|
175
|
+
> Only call memory.store when:
|
|
176
|
+
> - The information affects future behavior
|
|
177
|
+
> - The scope (repo) is clear
|
|
178
|
+
> - The memory will still matter later
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Git / Project Scoping (Hard Requirement)
|
|
183
|
+
|
|
184
|
+
### Rule
|
|
185
|
+
Every memory entry **MUST** include:
|
|
186
|
+
`scope.repo`
|
|
187
|
+
|
|
188
|
+
### Resolution Order
|
|
189
|
+
1. Git repository root
|
|
190
|
+
2. Project folder name
|
|
191
|
+
|
|
192
|
+
### Enforcement
|
|
193
|
+
- Search without repo → **reject**
|
|
194
|
+
- Store without repo → **reject**
|
|
195
|
+
|
|
196
|
+
*This prevents cross-project contamination.*
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Suggested Internal Folder Structure
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
mcp-memory-local/
|
|
204
|
+
├─ server.ts # MCP JSON-RPC loop
|
|
205
|
+
├─ capabilities.ts # static MCP contract
|
|
206
|
+
├─ tools/
|
|
207
|
+
│ ├─ store.ts
|
|
208
|
+
│ ├─ search.ts
|
|
209
|
+
│ └─ summarize.ts
|
|
210
|
+
├─ resources/
|
|
211
|
+
│ ├─ index.ts
|
|
212
|
+
│ └─ read.ts
|
|
213
|
+
├─ prompts/
|
|
214
|
+
│ └─ registry.ts
|
|
215
|
+
├─ storage/
|
|
216
|
+
│ ├─ sqlite.ts
|
|
217
|
+
│ └─ vectors.ts
|
|
218
|
+
└─ utils/
|
|
219
|
+
└─ git-scope.ts
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Explicit Non-Goals (for Skeleton)
|
|
225
|
+
|
|
226
|
+
- ❌ Auth & tokens
|
|
227
|
+
- ❌ Organization-level scope
|
|
228
|
+
- ❌ Knowledge graph
|
|
229
|
+
- ❌ Audit & versioning
|
|
230
|
+
- ❌ Bulk operations
|
|
231
|
+
|
|
232
|
+
*These can be added later without breaking contract.*
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Final Note
|
|
237
|
+
|
|
238
|
+
Skeleton ini cukup kecil untuk dibangun cepat, tapi cukup kuat untuk:
|
|
239
|
+
- Menggantikan remote MCP
|
|
240
|
+
- Menjadi fondasi agent yang konsisten
|
|
241
|
+
- Menjaga antigravity behavior
|
|
242
|
+
|
|
243
|
+
Kalau kontrak ini dijaga, backend bisa berubah tanpa menyentuh agent.
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Skeleton – MCP Local Memory Server Loop (Node.js)
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Dokumen ini mendefinisikan server loop MCP JSON-RPC minimal untuk MCP Local Memory Server.
|
|
6
|
+
|
|
7
|
+
**Tujuan skeleton ini:**
|
|
8
|
+
- Menjadi *drop-in replacement* untuk MCP memory remote
|
|
9
|
+
- Fokus ke contract & flow, bukan storage
|
|
10
|
+
- Mudah dikembangkan ke SQLite + vector DB
|
|
11
|
+
|
|
12
|
+
> *Catatan: Skeleton ini sengaja boring & eksplisit. MCP server yang bagus itu stabil, bukan pintar.*
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## High-Level Flow
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
graph TD
|
|
20
|
+
A[stdin JSON-RPC] --> B[Parse message]
|
|
21
|
+
B --> C[Handle initialize]
|
|
22
|
+
C --> D[Advertise capabilities]
|
|
23
|
+
B --> E[Route method -> handler]
|
|
24
|
+
E --> F[Return JSON-RPC response]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Required Files
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
mcp-memory-local/
|
|
33
|
+
├─ server.ts # entrypoint (JSON-RPC loop)
|
|
34
|
+
├─ capabilities.ts # static MCP contract
|
|
35
|
+
├─ router.ts # method dispatcher
|
|
36
|
+
├─ tools/
|
|
37
|
+
│ ├─ memory.store.ts
|
|
38
|
+
│ ├─ memory.search.ts
|
|
39
|
+
│ └─ memory.summarize.ts
|
|
40
|
+
├─ resources/
|
|
41
|
+
│ ├─ list.ts
|
|
42
|
+
│ └─ read.ts
|
|
43
|
+
└─ prompts/
|
|
44
|
+
└─ registry.ts
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## `server.ts` (JSON-RPC Loop)
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import readline from "node:readline";
|
|
53
|
+
import { handleMethod } from "./router.js";
|
|
54
|
+
import { CAPABILITIES } from "./capabilities.js";
|
|
55
|
+
|
|
56
|
+
const rl = readline.createInterface({
|
|
57
|
+
input: process.stdin,
|
|
58
|
+
output: process.stdout,
|
|
59
|
+
terminal: false
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function reply(payload: unknown) {
|
|
63
|
+
process.stdout.write(JSON.stringify(payload) + "\n");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
rl.on("line", async (line) => {
|
|
67
|
+
if (!line.trim()) return;
|
|
68
|
+
|
|
69
|
+
let msg;
|
|
70
|
+
try {
|
|
71
|
+
msg = JSON.parse(line);
|
|
72
|
+
} catch {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const { id, method, params } = msg;
|
|
77
|
+
|
|
78
|
+
// --- initialize ---
|
|
79
|
+
if (method === "initialize") {
|
|
80
|
+
reply({
|
|
81
|
+
jsonrpc: "2.0",
|
|
82
|
+
id,
|
|
83
|
+
result: {
|
|
84
|
+
protocolVersion: "2024-11-05",
|
|
85
|
+
serverInfo: CAPABILITIES.serverInfo,
|
|
86
|
+
capabilities: CAPABILITIES.capabilities
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
reply({
|
|
91
|
+
jsonrpc: "2.0",
|
|
92
|
+
method: "notifications/initialized",
|
|
93
|
+
params: {}
|
|
94
|
+
});
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// --- ignore notification ---
|
|
99
|
+
if (method === "notifications/initialized") return;
|
|
100
|
+
|
|
101
|
+
// --- route method ---
|
|
102
|
+
try {
|
|
103
|
+
const result = await handleMethod(method, params);
|
|
104
|
+
|
|
105
|
+
reply({
|
|
106
|
+
jsonrpc: "2.0",
|
|
107
|
+
id,
|
|
108
|
+
result
|
|
109
|
+
});
|
|
110
|
+
} catch (err: any) {
|
|
111
|
+
reply({
|
|
112
|
+
jsonrpc: "2.0",
|
|
113
|
+
id,
|
|
114
|
+
error: {
|
|
115
|
+
code: -32603,
|
|
116
|
+
message: err.message || "Internal error"
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## `capabilities.ts`
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
export const CAPABILITIES = {
|
|
129
|
+
serverInfo: {
|
|
130
|
+
name: "mcp-memory-local",
|
|
131
|
+
version: "0.1.0"
|
|
132
|
+
},
|
|
133
|
+
capabilities: {
|
|
134
|
+
resources: {
|
|
135
|
+
list: true,
|
|
136
|
+
read: true,
|
|
137
|
+
templates: true
|
|
138
|
+
},
|
|
139
|
+
tools: {
|
|
140
|
+
list: true,
|
|
141
|
+
call: true
|
|
142
|
+
},
|
|
143
|
+
prompts: {
|
|
144
|
+
list: true,
|
|
145
|
+
get: true
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## `router.ts` (Method Dispatcher)
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { listResources, readResource } from "./resources/index.js";
|
|
157
|
+
import { PROMPTS } from "./prompts/registry.js";
|
|
158
|
+
|
|
159
|
+
export async function handleMethod(method: string, params: any) {
|
|
160
|
+
switch (method) {
|
|
161
|
+
// ---- tools ----
|
|
162
|
+
case "tools/list":
|
|
163
|
+
return { tools: [] };
|
|
164
|
+
|
|
165
|
+
case "tools/call":
|
|
166
|
+
return { result: "not implemented" };
|
|
167
|
+
|
|
168
|
+
// ---- resources ----
|
|
169
|
+
case "resources/list":
|
|
170
|
+
return listResources();
|
|
171
|
+
|
|
172
|
+
case "resources/read":
|
|
173
|
+
return readResource(params?.uri);
|
|
174
|
+
|
|
175
|
+
// ---- prompts ----
|
|
176
|
+
case "prompts/list":
|
|
177
|
+
return { prompts: Object.values(PROMPTS) };
|
|
178
|
+
|
|
179
|
+
case "prompts/get":
|
|
180
|
+
return { prompt: PROMPTS[params.name] };
|
|
181
|
+
|
|
182
|
+
default:
|
|
183
|
+
throw new Error(`Unsupported method: ${method}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## `prompts/registry.ts`
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
export const PROMPTS = {
|
|
194
|
+
"memory-agent-core": {
|
|
195
|
+
name: "memory-agent-core",
|
|
196
|
+
description: "Core behavioral contract for memory-aware agents",
|
|
197
|
+
content: `You are a coding copilot agent.
|
|
198
|
+
|
|
199
|
+
Respect stored decisions.
|
|
200
|
+
Avoid repeating mistakes.
|
|
201
|
+
Memory is a source of truth.`
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## `resources/index.ts`
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
export function listResources() {
|
|
212
|
+
return {
|
|
213
|
+
resources: [
|
|
214
|
+
{ uri: "memory://index", title: "Memory Index" }
|
|
215
|
+
]
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function readResource(uri: string) {
|
|
220
|
+
return {
|
|
221
|
+
resource: {
|
|
222
|
+
uri,
|
|
223
|
+
title: "Not implemented",
|
|
224
|
+
content: ""
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Why This Skeleton Works
|
|
233
|
+
|
|
234
|
+
- Matches MCP lifecycle exactly
|
|
235
|
+
- Easy to extend per tool
|
|
236
|
+
- No storage coupling
|
|
237
|
+
- Agent-safe (no breaking contract)
|
|
238
|
+
|
|
239
|
+
*Ini adalah fondasi yang tepat sebelum:*
|
|
240
|
+
1. SQLite
|
|
241
|
+
2. Vector search
|
|
242
|
+
3. Auto-memory logic
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Next Recommended Step
|
|
247
|
+
|
|
248
|
+
1. Tambah tool definitions (`memory.store`, `memory.search`)
|
|
249
|
+
2. Tambah git-scope resolver
|
|
250
|
+
3. Baru wiring ke SQLite
|
|
251
|
+
|
|
252
|
+
*Kalau kamu mau, langkah berikutnya aku bisa:*
|
|
253
|
+
- Tambahkan tool schema lengkap
|
|
254
|
+
- Tambahkan git scope resolver code
|
|
255
|
+
- Tambahkan SQLite + vector stub
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Spec – SQLite Schema & Migration
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Dokumen ini mendefinisikan skema SQLite final untuk MCP Local Memory Server.
|
|
6
|
+
|
|
7
|
+
**Fokus utama:**
|
|
8
|
+
- Skema tahan lama & mudah di-migrate
|
|
9
|
+
- Selaras dengan tool schema, git scope, dan heuristics
|
|
10
|
+
- Siap dipakai dengan atau tanpa vector DB
|
|
11
|
+
|
|
12
|
+
> *Prinsip: SQLite adalah source of truth. Vector hanyalah index.*
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Design Principles
|
|
17
|
+
|
|
18
|
+
1. **Append-friendly** (mudah evolve)
|
|
19
|
+
2. **Readable** (debug via sqlite CLI masih masuk akal)
|
|
20
|
+
3. **Strict schema** (hindari JSON berlebihan)
|
|
21
|
+
4. **Repo-scoped by design**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Database File
|
|
26
|
+
|
|
27
|
+
`storage/memory.db`
|
|
28
|
+
|
|
29
|
+
Single file, local-only.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Table: `memories`
|
|
34
|
+
|
|
35
|
+
**Purpose:**
|
|
36
|
+
Menyimpan semua long-term memory berkualitas tinggi.
|
|
37
|
+
|
|
38
|
+
**Schema:**
|
|
39
|
+
```sql
|
|
40
|
+
CREATE TABLE memories (
|
|
41
|
+
id TEXT PRIMARY KEY,
|
|
42
|
+
repo TEXT NOT NULL,
|
|
43
|
+
type TEXT NOT NULL CHECK (type IN (
|
|
44
|
+
'code_fact',
|
|
45
|
+
'decision',
|
|
46
|
+
'mistake',
|
|
47
|
+
'pattern'
|
|
48
|
+
)),
|
|
49
|
+
content TEXT NOT NULL,
|
|
50
|
+
importance INTEGER NOT NULL CHECK (importance BETWEEN 1 AND 5),
|
|
51
|
+
folder TEXT,
|
|
52
|
+
language TEXT,
|
|
53
|
+
created_at TEXT NOT NULL,
|
|
54
|
+
updated_at TEXT NOT NULL
|
|
55
|
+
);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Notes:**
|
|
59
|
+
- `repo` adalah **hard boundary**
|
|
60
|
+
- `content` adalah canonical text (untuk embedding)
|
|
61
|
+
- Jangan simpan JSON besar di sini
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Indexes (WAJIB)
|
|
66
|
+
|
|
67
|
+
```sql
|
|
68
|
+
CREATE INDEX idx_memories_repo ON memories(repo);
|
|
69
|
+
CREATE INDEX idx_memories_type ON memories(type);
|
|
70
|
+
CREATE INDEX idx_memories_importance ON memories(importance);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
*Index ini cukup untuk tahap awal.*
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Table: `memory_summary`
|
|
78
|
+
|
|
79
|
+
**Purpose:**
|
|
80
|
+
Antigravity snapshot per repo.
|
|
81
|
+
|
|
82
|
+
**Schema:**
|
|
83
|
+
```sql
|
|
84
|
+
CREATE TABLE memory_summary (
|
|
85
|
+
repo TEXT PRIMARY KEY,
|
|
86
|
+
summary TEXT NOT NULL,
|
|
87
|
+
updated_at TEXT NOT NULL
|
|
88
|
+
);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Optional Table: `memory_embeddings`
|
|
94
|
+
|
|
95
|
+
> *Opsional – hanya jika embedding tidak disimpan inline.*
|
|
96
|
+
|
|
97
|
+
```sql
|
|
98
|
+
CREATE TABLE memory_embeddings (
|
|
99
|
+
memory_id TEXT PRIMARY KEY,
|
|
100
|
+
embedding BLOB NOT NULL,
|
|
101
|
+
FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE
|
|
102
|
+
);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
*Jika pakai sqlite-vector extension, table ini bisa diganti.*
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Migration Strategy
|
|
110
|
+
|
|
111
|
+
### v1 – Initial
|
|
112
|
+
|
|
113
|
+
```sql
|
|
114
|
+
-- 001_init.sql
|
|
115
|
+
BEGIN;
|
|
116
|
+
|
|
117
|
+
-- memories table
|
|
118
|
+
CREATE TABLE memories (...);
|
|
119
|
+
CREATE INDEX ...;
|
|
120
|
+
|
|
121
|
+
-- summary table
|
|
122
|
+
CREATE TABLE memory_summary (...);
|
|
123
|
+
|
|
124
|
+
COMMIT;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Rules
|
|
128
|
+
- Tidak ada destructive migration di awal
|
|
129
|
+
- Tambah kolom → nullable
|
|
130
|
+
- Jangan rename kolom (add new instead)
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Insert Example
|
|
135
|
+
|
|
136
|
+
```sql
|
|
137
|
+
INSERT INTO memories (
|
|
138
|
+
id, repo, type, content, importance, created_at, updated_at
|
|
139
|
+
) VALUES (
|
|
140
|
+
'uuid',
|
|
141
|
+
'my-repo',
|
|
142
|
+
'decision',
|
|
143
|
+
'Do not use ORM; raw SQL only',
|
|
144
|
+
5,
|
|
145
|
+
datetime('now'),
|
|
146
|
+
datetime('now')
|
|
147
|
+
);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Query Patterns
|
|
153
|
+
|
|
154
|
+
### By Repo (most common)
|
|
155
|
+
|
|
156
|
+
```sql
|
|
157
|
+
SELECT * FROM memories
|
|
158
|
+
WHERE repo = ?
|
|
159
|
+
ORDER BY importance DESC, created_at DESC
|
|
160
|
+
LIMIT 5;
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## What NOT to Store
|
|
166
|
+
|
|
167
|
+
- ❌ Chat logs
|
|
168
|
+
- ❌ Prompt history
|
|
169
|
+
- ❌ Temporary task state
|
|
170
|
+
- ❌ Vector-only data without text
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Final Take
|
|
175
|
+
|
|
176
|
+
Skema ini sengaja tidak kompleks.
|
|
177
|
+
|
|
178
|
+
**Kalau kamu disiplin di schema & heuristics:**
|
|
179
|
+
- SQLite akan cukup lama
|
|
180
|
+
- Vector DB bisa ditambah belakangan
|
|
181
|
+
- Memory tetap bersih & bernilai tinggi
|
|
182
|
+
|
|
183
|
+
Ini fondasi terakhir sebelum masuk ke vector search.
|