th-memory-mcp 2.2.9 → 2.3.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.
@@ -1,7 +1,7 @@
1
1
  # th-memory-mcp v2 — Architecture & Implementation Specification
2
2
 
3
3
  **Status:** ✅ Released — `th-memory-mcp v2.0.0` is published (npm + Official MCP Registry + Glama).
4
- **Baseline:** v1.2.2 → **Current:** v2.2.9
4
+ **Baseline:** v1.2.2 → **Current:** v2.3.0
5
5
  **Primary goal:** evolve th-memory-mcp from a structured local memory MCP into a durable, temporal, conflict-aware, hybrid-retrieval memory engine for AI agents.
6
6
 
7
7
  > **Audience guide:** End users should read [README.md](README.md) (install, tools, usage). This document is the **canonical architecture & agent-rules spec** for developers and AI coding agents — the single source of truth for structure and behavior. The former `design.md` build log has been folded into §40 Implementation Status.
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  [![th-memory-mcp MCP server](https://glama.ai/mcp/servers/worakorn-prince/th-memory-mcp/badges/card.svg)](https://glama.ai/mcp/servers/worakorn-prince/th-memory-mcp)
12
12
 
13
13
 
14
- **Status:** v2.2.9 — a temporal, conflict-aware, hybrid-retrieval memory engine. 16 MCP tools, 25 passing test suites. Non-destructive schema migration from v1 (all v1 data preserved). New in v2.2: lifecycle states, temporal validity, conflict/dedup resolution with USER/SESSION/PROJECT/GLOBAL scope, hybrid FTS+vector retrieval (RRF), memory graph, `get_context` assembly, periodic consolidation, and `link_memory` / `merge_memory` / `update_memory` / `import_memory` / `extract_memories`. New in v2.2.3: scope-enforced retrieval, graph scope isolation, export/import round-trip, hardened import path (realpath), strict import validation, N+1 query elimination, cold/ablation benchmark, and `MEMORY_RETRIEVAL_MODE` switch. New in v2.2.7: synced secret filter between Claude hook and capture-core (6-pattern redact instead of line-drop), fixed `err()` to return `isError:true` per MCP spec, fixed backup rotation (backup only when migrations pending + prune to 5 files), and added hook error logging for SessionEnd distill. New in v2.2.8: fixed scope contamination 0.75→0 (critical) and conflict false 0→1 (GLOBAL leak), fixed graph hop1 0.52→1.0 via includeGraph, and rescaled benchmark profiles to 5K/20K/100K/500K/1M (pre-commit now quick 5K + normal 20K only). New in v2.2.9: extended export to entities/users/relations, forget now removes associated links, fail-closed migration with shared ISO helper, eliminated FTS N+1, included smoke in test script, and synced viewer to rescaled profiles 5K/20K/100K/500K/1M.
14
+ **Status:** v2.3.0 — a temporal, conflict-aware, hybrid-retrieval memory engine. 16 MCP tools, 25 passing test suites. Non-destructive schema migration from v1 (all v1 data preserved). New in v2.2: lifecycle states, temporal validity, conflict/dedup resolution with USER/SESSION/PROJECT/GLOBAL scope, hybrid FTS+vector retrieval (RRF), memory graph, `get_context` assembly, periodic consolidation, and `link_memory` / `merge_memory` / `update_memory` / `import_memory` / `extract_memories`. New in v2.2.3: scope-enforced retrieval, graph scope isolation, export/import round-trip, hardened import path (realpath), strict import validation, N+1 query elimination, cold/ablation benchmark, and `MEMORY_RETRIEVAL_MODE` switch. New in v2.2.7: synced secret filter between Claude hook and capture-core (6-pattern redact instead of line-drop), fixed `err()` to return `isError:true` per MCP spec, fixed backup rotation (backup only when migrations pending + prune to 5 files), and added hook error logging for SessionEnd distill. New in v2.2.8: fixed scope contamination 0.75→0 (critical) and conflict false 0→1 (GLOBAL leak), fixed graph hop1 0.52→1.0 via includeGraph, and rescaled benchmark profiles to 5K/20K/100K/500K/1M (pre-commit now quick 5K + normal 20K only). New in v2.2.9: extended export to entities/users/relations, forget now removes associated links, fail-closed migration with shared ISO helper, eliminated FTS N+1, included smoke in test script, and synced viewer to rescaled profiles 5K/20K/100K/500K/1M. New in v2.3.0: CLI th-memory + highlight underline.
15
15
 
16
16
  ## Requirements
17
17
 
@@ -27,6 +27,7 @@ No external services, accounts, or API keys are required — everything lives in
27
27
  **Fastest path:** after cloning, run `npm run quickstart` — it builds, wires `opencode.json`, deploys the plugin, and sets `MEMORY_DB_PATH` for you in one command. The steps below show exactly what it does (use them if you prefer manual control).
28
28
 
29
29
  **Install via npm (alternative):** install the server globally with `npm install -g th-memory-mcp` (or run it on demand with `npx th-memory-mcp`), then point the `mcp` `command` in `opencode.json` to `th-memory-mcp` instead of the built `dist/index.js`. The auto-capture plugin still comes from this repo (copy `src/plugin/learning-capture.ts` as described in step 4 below).
30
+ > Note: no longer published to GitHub Packages — install from npmjs with `npm i -g th-memory-mcp`.
30
31
 
31
32
  ```bash
32
33
  # 1. Clone and build
@@ -175,6 +176,55 @@ anywhere is readable everywhere.
175
176
  | `import_memory` | import memories from JSON (validates type, dedupes against existing, never overwrites blindly); dry-run by default, `apply=true` to insert |
176
177
  | `extract_memories` | scan recent captured interactions for memory-intent phrases and propose memory candidates (deterministic, no LLM); dry-run by default, `apply=true` to create (source=captured) |
177
178
 
179
+ ## CLI (`th-memory`)
180
+
181
+ Two binaries ship in `package.json` (`bin`):
182
+
183
+ | Binary | Entry | Purpose |
184
+ |--------|-------|---------|
185
+ | `th-memory-mcp` | `dist/index.js` | MCP server (stdio) — the 16 tools above |
186
+ | `th-memory` | `dist/cli.js` | local memory CLI (zero-dep, shares the same DB via `MEMORY_DB_PATH`) |
187
+
188
+ Usage: `th-memory [--db <path>] [--json] [--plain] <command> [options]` — per-command help via `th-memory <command> --help`.
189
+
190
+ Global flags (every command):
191
+
192
+ | Flag | Effect |
193
+ |------|--------|
194
+ | `--db <path>` | use this SQLite file (sets `MEMORY_DB_PATH`) |
195
+ | `--json` | print JSON `{ok,data}` instead of plain text |
196
+ | `--plain` / `--no-color` | disable colors |
197
+ | `-h, --help` | show help (global or per-command) |
198
+ | `-V, --version` | print version |
199
+
200
+ Commands:
201
+
202
+ | Command | Usage |
203
+ |---------|-------|
204
+ | `remember` | `remember --category <c> --key <k> --value <v\|->` — save a preference (`--value -` reads from stdin) |
205
+ | `recall` | `recall <topic> [--limit <n>] [--highlight]` — search memory |
206
+ | `forget` | `forget <id> [--type <t>]` — delete by id (`t`: `memory\|preference\|lesson\|interaction`) |
207
+ | `export` | `export [--include-interactions] [--filename <n>]` — export to `data/exports/*.json` |
208
+ | `import` | `import (--file <p>\|--json <s>) [--apply] [--user-id <id>]` — import backup (dry-run by default) |
209
+ | `stats` | `stats` — memory statistics |
210
+ | `profile` | `profile` — distilled user profile |
211
+ | `history` | `history [--query <q>] [--limit <n>]` — search past prompts (no query = recent prompts) |
212
+ | `recent` | `recent [--limit <n>] [--kind <k>]` — recent interactions (`k`: `prompt\|tool_call\|error`) |
213
+ | `highlight` | `highlight [text...] -q <topic> [--limit <n>]` — highlight topic matches (empty text = stdin pipe) |
214
+
215
+ Highlight behavior (`highlight` command and `recall --highlight`): matches are wrapped with an **underline** (`ESC[4m`…`ESC[24m`) when stdout is a TTY with colors enabled; when piped, with `--json`, or with `--plain`/`--no-color`, matches are wrapped with `[mem]`…`[/mem]` markers instead.
216
+
217
+ Examples:
218
+
219
+ ```bash
220
+ th-memory remember --category coding_pref --key package_manager --value pnpm
221
+ th-memory recall pnpm --limit 5
222
+ th-memory recall pnpm --highlight
223
+ echo "I prefer pnpm for installs" | th-memory highlight -q pnpm
224
+ ```
225
+
226
+ Note: `--value -` reads the value from stdin (e.g. `echo -n "pnpm" | th-memory remember --category coding_pref --key package_manager --value -`).
227
+
178
228
  ## Install with OpenCode
179
229
 
180
230
  1. Merge the `mcp` section from [`opencode.example.json`](opencode.example.json) into your `opencode.json` (global or project-level)
@@ -262,6 +312,7 @@ Last internal run (v2.2.8, warm, normal profile, a2dcbce — not third-party): R
262
312
  ## Known Limitations
263
313
 
264
314
  - **No encryption at rest (plaintext-at-rest)** — `data/memory.db` (WAL mode, `better-sqlite3`) is a plain, unencrypted SQLite file. `100% local & private` means no cloud or network exfiltration — it does **not** mean encrypted at rest. Anyone with filesystem access (shared machine, backup, malware, stolen device) can read preferences/lessons/interactions in plaintext. For sensitive data, use OS-level full-disk encryption (BitLocker / FileVault / LUKS) or an opt-in SQLCipher build (requires native rebuild and key management). No SQLCipher/in-code encryption is applied by default and `src/db/index.ts` documents this explicitly.
315
+ - **Single-user local process — no auth layer (Batch B-3)** — `userId` / `sessionId` / `projectId` are caller-supplied strings with **no authentication or authorization check inside the server**. Scope isolation (retrieval, `get_context`, graph traversal/expansion, `consolidate`, `link_memory`, `merge_memory`) is enforced only against the values the caller sends, so a caller can read or write any scope by passing a different id. This is suitable for a **single-user local process** (one operator, local `data/memory.db`). Do **not** share one server/DB across mutually-untrusted users without an auth layer in front that authenticates each caller and forces the correct `userId` (and allowed `projectId` / `sessionId`). No new auth system is built into the server by design — that layer belongs in front of it.
265
316
 
266
317
  ## License
267
318
 
package/README.th.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  MCP server ความจำระยะยาวสำหรับ OpenCode — เก็บ preferences, lessons, ประวัติการใช้งาน ลง SQLite ไฟล์เดียว (local 100%, ไม่มี external API) เพื่อให้ AI "จำและปรับตัว" กับผู้ใช้ผ่าน context-based learning
9
9
 
10
- **สถานะ:** v2.2.9 — engine ความจำแบบ temporal, conflict-aware, hybrid-retrieval 16 MCP tools, 25 ชุดเทสผ่าน อัปเกรด schema แบบ non-destructive จาก v1 (ข้อมูล v1 ทั้งหมดถูกเก็บรักษา) ฟีเจอร์ใหม่ใน v2.2: lifecycle states, temporal validity, การแก้ conflict/dedup พร้อม scope USER/SESSION/PROJECT/GLOBAL, hybrid FTS+vector retrieval (RRF), memory graph, ประกอบ `get_context`, consolidation, และ `link_memory` / `merge_memory` / `update_memory` / `import_memory` / `extract_memories` ใหม่ใน v2.2.3: บังคับ scope ใน retrieval, แยก scope ใน graph, export/import แบบ round-trip, ป้องกัน symlink ด้วย realpath, ตรวจ import เข้มงวด, เลิก N+1 query, benchmark cold/ablation และสวิตช์ `MEMORY_RETRIEVAL_MODE` ใหม่ใน v2.2.7: ซิงค์ secret filter ระหว่าง Claude hook กับ capture-core (redact 6 patterns แทนทิ้งบรรทัด), แก้ `err()` ให้ส่ง `isError:true` ตาม MCP spec, แก้ backup rotation (backup เฉพาะเมื่อมี migration pending + prune เก็บ 5 ไฟล์ล่าสุด) และเพิ่ม hook error logging สำหรับ SessionEnd distill ใหม่ใน v2.2.8: แก้บัค scope contamination 0.75→0 (ร้ายแรง), แก้ conflict false 0→1, ปรับ benchmark rescale 5K/20K/100K/500K/1M และ viewer เทียบ profiles ภายใน version, workflow ก่อน commit เหลือ 2 profiles (quick 5K + normal 20K) ใหม่ใน v2.2.9: ขยาย export ให้ครอบคลุม entities/users/relations, forget ลบลิงก์ที่เกี่ยวข้อง, migration แบบ fail-closed พร้อม ISO helper กลาง, เลิก N+1 ใน FTS, รวม smoke ในสคริปต์เทส และซิงค์ viewer กับโปรไฟล์ rescale 5K/20K/100K/500K/1M
10
+ **สถานะ:** v2.3.0 — engine ความจำแบบ temporal, conflict-aware, hybrid-retrieval 16 MCP tools, 25 ชุดเทสผ่าน อัปเกรด schema แบบ non-destructive จาก v1 (ข้อมูล v1 ทั้งหมดถูกเก็บรักษา) ฟีเจอร์ใหม่ใน v2.2: lifecycle states, temporal validity, การแก้ conflict/dedup พร้อม scope USER/SESSION/PROJECT/GLOBAL, hybrid FTS+vector retrieval (RRF), memory graph, ประกอบ `get_context`, consolidation, และ `link_memory` / `merge_memory` / `update_memory` / `import_memory` / `extract_memories` ใหม่ใน v2.2.3: บังคับ scope ใน retrieval, แยก scope ใน graph, export/import แบบ round-trip, ป้องกัน symlink ด้วย realpath, ตรวจ import เข้มงวด, เลิก N+1 query, benchmark cold/ablation และสวิตช์ `MEMORY_RETRIEVAL_MODE` ใหม่ใน v2.2.7: ซิงค์ secret filter ระหว่าง Claude hook กับ capture-core (redact 6 patterns แทนทิ้งบรรทัด), แก้ `err()` ให้ส่ง `isError:true` ตาม MCP spec, แก้ backup rotation (backup เฉพาะเมื่อมี migration pending + prune เก็บ 5 ไฟล์ล่าสุด) และเพิ่ม hook error logging สำหรับ SessionEnd distill ใหม่ใน v2.2.8: แก้บัค scope contamination 0.75→0 (ร้ายแรง), แก้ conflict false 0→1, ปรับ benchmark rescale 5K/20K/100K/500K/1M และ viewer เทียบ profiles ภายใน version, workflow ก่อน commit เหลือ 2 profiles (quick 5K + normal 20K) ใหม่ใน v2.2.9: ขยาย export ให้ครอบคลุม entities/users/relations, forget ลบลิงก์ที่เกี่ยวข้อง, migration แบบ fail-closed พร้อม ISO helper กลาง, เลิก N+1 ใน FTS, รวม smoke ในสคริปต์เทส และซิงค์ viewer กับโปรไฟล์ rescale 5K/20K/100K/500K/1M ใหม่ใน v2.3.0: CLI th-memory + highlight underline
11
11
 
12
12
  > English: [README.md](README.md)
13
13
 
@@ -25,6 +25,7 @@ MCP server ความจำระยะยาวสำหรับ OpenCode
25
25
  **ทางที่เร็วที่สุด:** หลัง clone ให้รัน `npm run quickstart` — มันจะ build, ต่อไฟล์ `opencode.json`, วาง plugin และตั้ง `MEMORY_DB_PATH` ให้ในคำสั่งเดียว ขั้นตอนด้านล่างคือสิ่งที่สคริปต์ทำ (ใช้ได้หากอยากควบคุมเองทีละขั้น)
26
26
 
27
27
  **ติดตั้งผ่าน npm (อีกทางเลือก):** ติดตั้ง server แบบ global ด้วย `npm install -g th-memory-mcp` (หรือรันทันทีด้วย `npx th-memory-mcp`) แล้วชี้ `command` ของ `mcp` ใน `opencode.json` ไปที่ `th-memory-mcp` แทน `dist/index.js` ที่ build แล้ว plugin auto-capture ยังคงมาจาก repo นี้ (คัดลอก `src/plugin/learning-capture.ts` ตามขั้นตอน 4 ด้านล่าง)
28
+ > หมายเหตุ: ไม่พับลิชขึ้น GitHub Packages แล้ว — ติดตั้งจาก npmjs ด้วย `npm i -g th-memory-mcp` แทน
28
29
 
29
30
  ```bash
30
31
  # 1. Clone และ build
@@ -128,6 +129,55 @@ LLM ไม่ได้จำคุณข้าม session — แชทใหม
128
129
  | `import_memory` | นำเข้าความจำจาก JSON (ตรวจสอบ type, dedup กับของเดิม, ไม่เขียนทับแบบมืดบอด); ค่าเริ่มต้น dry-run, ตั้ง `apply=true` เพื่อเพิ่ม |
129
130
  | `extract_memories` | สแกน interactions ล่าสุดหาเจตนาบันทึกความจำ และเสนอ/สร้างความจำ (ไม่ใช้ LLM); ค่าเริ่มต้น dry-run, ตั้ง `apply=true` เพื่อสร้าง (source=captured) |
130
131
 
132
+ ## CLI (`th-memory`)
133
+
134
+ ไบนารี 2 ตัวใน `package.json` (`bin`):
135
+
136
+ | ไบนารี | Entry | ใช้ทำอะไร |
137
+ |--------|-------|-----------|
138
+ | `th-memory-mcp` | `dist/index.js` | MCP server (stdio) — tools 16 ตัวข้างบน |
139
+ | `th-memory` | `dist/cli.js` | CLI ความจำภายในเครื่อง (zero-dep, ใช้ DB เดียวกันผ่าน `MEMORY_DB_PATH`) |
140
+
141
+ วิธีใช้: `th-memory [--db <path>] [--json] [--plain] <command> [options]` — ดูวิธีใช้รายคำสั่งด้วย `th-memory <command> --help`
142
+
143
+ แฟล็กกลาง (ใช้ได้ทุกคำสั่ง):
144
+
145
+ | แฟล็ก | ผล |
146
+ |------|-----|
147
+ | `--db <path>` | ใช้ไฟล์ SQLite นี้ (ตั้งค่า `MEMORY_DB_PATH`) |
148
+ | `--json` | พิมพ์ JSON `{ok,data}` แทนข้อความธรรมดา |
149
+ | `--plain` / `--no-color` | ปิดสี |
150
+ | `-h, --help` | แสดงวิธีใช้ (รวม หรือรายคำสั่ง) |
151
+ | `-V, --version` | แสดงเวอร์ชัน |
152
+
153
+ ตารางคำสั่ง:
154
+
155
+ | คำสั่ง | วิธีใช้ |
156
+ |--------|---------|
157
+ | `remember` | `remember --category <c> --key <k> --value <v\|->` — บันทึก preference (`--value -` อ่านจาก stdin) |
158
+ | `recall` | `recall <topic> [--limit <n>] [--highlight]` — ค้นความจำ |
159
+ | `forget` | `forget <id> [--type <t>]` — ลบตาม id (`t`: `memory\|preference\|lesson\|interaction`) |
160
+ | `export` | `export [--include-interactions] [--filename <n>]` — export ไป `data/exports/*.json` |
161
+ | `import` | `import (--file <p>\|--json <s>) [--apply] [--user-id <id>]` — นำเข้า backup (ค่าเริ่มต้น dry-run) |
162
+ | `stats` | `stats` — สถิติความจำ |
163
+ | `profile` | `profile` — ภาพรวมโปรไฟล์ผู้ใช้ |
164
+ | `history` | `history [--query <q>] [--limit <n>]` — ค้น prompt เก่า (ไม่ใส่ query = prompt ล่าสุด) |
165
+ | `recent` | `recent [--limit <n>] [--kind <k>]` — interactions ล่าสุด (`k`: `prompt\|tool_call\|error`) |
166
+ | `highlight` | `highlight [text...] -q <topic> [--limit <n>]` — ไฮไลต์ส่วนที่ตรง topic (ไม่ใส่ text = อ่านจาก stdin pipe) |
167
+
168
+ พฤติกรรม highlight (คำสั่ง `highlight` และ `recall --highlight`): ส่วนที่ตรงจะถูกหุ้มด้วย**ขีดเส้นใต้** (`ESC[4m`…`ESC[24m`) เมื่อ stdout เป็น TTY และเปิดสีอยู่; เมื่อ pipe output, ใช้ `--json`, หรือใช้ `--plain`/`--no-color` จะหุ้มด้วยเครื่องหมาย `[mem]`…`[/mem]` แทน
169
+
170
+ ตัวอย่าง:
171
+
172
+ ```bash
173
+ th-memory remember --category coding_pref --key package_manager --value pnpm
174
+ th-memory recall pnpm --limit 5
175
+ th-memory recall pnpm --highlight
176
+ echo "I prefer pnpm for installs" | th-memory highlight -q pnpm
177
+ ```
178
+
179
+ หมายเหตุ: `--value -` อ่านค่าจาก stdin (เช่น `echo -n "pnpm" | th-memory remember --category coding_pref --key package_manager --value -`)
180
+
131
181
  ## ติดตั้งกับ OpenCode
132
182
 
133
183
  1. Merge `mcp` section จาก [`opencode.example.json`](opencode.example.json) เข้า `opencode.json` (global หรือ project-level)
package/SECURITY.md CHANGED
@@ -35,6 +35,15 @@ Use one of these private channels:
35
35
 
36
36
  This policy covers the MCP server (`src/`), SQLite store (`data/memory.db`), and the auto-capture plugin (`src/plugin/learning-capture.ts`). The benchmark harness (`benchmark/`, `repro/`) and result files (`result/`) are out of scope.
37
37
 
38
+ ## Authentication scope — single-user local process (Batch B-3)
39
+
40
+ There is **no authentication or authorization layer** in this server by design (no new auth system is introduced):
41
+
42
+ - `userId` / `sessionId` / `projectId` are **caller-supplied** values. Scope checks in `merge_memory` / `get_context` (via `context-engine` + `retrieval-engine`) and the USER/SESSION/PROJECT isolation they enforce are only as trustworthy as the caller — a caller that passes another user's id is treated as that user.
43
+ - The supported deployment is a **single-user local process**: one operator running the MCP server against a local `data/memory.db`. In that model the caller is trusted and scope parameters are a correctness/isolation mechanism, not a security boundary.
44
+ - **Multi-user deployments MUST add an auth layer in front** (outside this repo): authenticate each caller, then map/force the correct `userId` (and allowed `projectId` / `sessionId`) before the call reaches the MCP tools. Sharing one server/DB across mutually-untrusted users without that layer will leak USER/SESSION-scoped memories across users.
45
+ - Memory content rendered back to the model is wrapped in `<memory-reference>` delimiters with an explicit "reference data, not instructions" guidance line, and entries imported with `metadata.trusted=false` are labelled `[untrusted-import]` — defense-in-depth against prompt injection, not a substitute for caller auth.
46
+
38
47
  ## Disclosure
39
48
 
40
49
  We follow coordinated disclosure. Please give us reasonable time to release a fix before public disclosure. We will publish a GitHub Release and update `SECURITY.md` with the fix version.
package/design.md CHANGED
@@ -3,7 +3,7 @@
3
3
  This document is up-to-date with the actual codebase state (after completing all future feature plans except AI-assisted extraction, which was removed). The full specification is at `ARCHITECTURE_v2.md` (canonical spec); this file summarizes the overview and current status for convenience.
4
4
 
5
5
  ## Current Status
6
- - **Version:** `package.json` = `2.2.9`
6
+ - **Version:** `package.json` = `2.3.0`
7
7
  - **MCP tools:** 16 tools (`remember`, `recall`, `get_context`, `link_memory`, `merge_memory`, `update_memory`, `import_memory`, `extract_memories`, `consolidate`, `forget`, `history`, `recent_interactions`, `profile`, `lesson`, `memory_stats`, `export_memory`)
8
8
  - **Test suites:** 25 suites passing (0 fail) — run via `npm test` (CI on GitHub Actions)
9
9