memnest-mcp 0.3.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ venv/
8
+ .venv/
9
+ *.egg
10
+ .agent-memory/
11
+
12
+ # macOS / IDE detritus
13
+ .DS_Store
14
+ .kiro/
15
+ .pytest_cache/
16
+ .tmp_*
17
+ *.bak
18
+ # Benchmark results (regenerate with: python benchmark/run_benchmark.py)
19
+ benchmark/results/dbs/
20
+ benchmark/results/*.json
21
+ benchmark/results/*.txt
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 arunkse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.4
2
+ Name: memnest-mcp
3
+ Version: 0.3.0
4
+ Summary: Persistent graph memory MCP server for AI agents using LadybugDB
5
+ Author: arunkse
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: agent,graph,ladybugdb,mcp,memory,vector-search
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: fastembed>=0.3.0
16
+ Requires-Dist: mcp>=1.0.0
17
+ Requires-Dist: real-ladybug>=0.15.0
18
+ Requires-Dist: toon-format==0.9.0b1
19
+ Description-Content-Type: text/markdown
20
+
21
+ # Memnest Memory MCP Server
22
+
23
+ [![PyPI version](https://badge.fury.io/py/memnest-mcp.svg)](https://pypi.org/project/memnest-mcp/)
24
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
25
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
26
+
27
+ Persistent graph memory for AI agents using [LadybugDB](https://ladybugdb.com/) — an embedded graph database with native vector search and full-text search.
28
+
29
+ Give your AI agent memory that persists across sessions, deduplicates automatically, and models knowledge as a graph with typed relationships.
30
+
31
+ ## Why Memnest?
32
+
33
+ - **Graph memory** — memories linked via Topic nodes and relationships (RELATED_TO, SUPERSEDES, EXPLAINS) with Cypher queries
34
+ - **Three-layer auto-dedup** — exact hash + semantic similarity + LLM-driven consolidation
35
+ - **Workspace namespacing** — memories scoped per project; `global_search` opt-out
36
+ - **HNSW vector search** — fast cosine similarity over FastEmbed embeddings
37
+ - **Topic auto-linking** — tags become graph nodes, enabling traversal queries
38
+ - **Embedded** — no Docker, no server process, single database directory
39
+ - **Zero config** — sensible defaults, just install and run
40
+ - **Importance & access tracking** — memories ranked by relevance and usage
41
+
42
+ ## Benchmarks
43
+
44
+ Memnest scores **82.9%** on the [LOCOMO benchmark](https://snap-research.github.io/locomo/) — the standard evaluation for long-term conversational memory (ACL 2024).
45
+
46
+ | Category | Score |
47
+ |----------|-------|
48
+ | Single-hop | 84.4% |
49
+ | Multi-hop | 76.9% |
50
+ | Open-domain | 85.7% |
51
+ | Temporal | 86.5% |
52
+ | Adversarial | 76.6% |
53
+ | **Overall** | **82.9%** |
54
+
55
+ Evaluated with Claude Sonnet 4.5 as the answer agent and Haiku 4.5 as the judge, using the industry-standard LLM-as-a-Judge methodology. All 5 LOCOMO categories included.
56
+
57
+ ### Architecture advantages
58
+
59
+ - **Zero LLM calls in the server** — intelligence lives in the agent, not the memory layer
60
+ - **Local embeddings** — no API key needed (`bge-small-en-v1.5`, 384-dim)
61
+ - **Single embedded database** — no Docker, no PostgreSQL, no separate vector DB
62
+ - **Hybrid search** — Vector (HNSW) + Full-text (BM25) + Graph (PageRank + Louvain communities)
63
+ - **3 agent tools** — `memory_search`, `memory_get`, `calculator`. Simple interface, powerful retrieval.
64
+
65
+ ## Quick Start
66
+
67
+ ```bash
68
+ # Run directly with uvx (no install needed)
69
+ uvx memnest-mcp
70
+ ```
71
+
72
+ Or install and run:
73
+
74
+ ```bash
75
+ pip install memnest-mcp
76
+ memnest-mcp
77
+ ```
78
+
79
+ ## MCP Configuration
80
+
81
+ Add to your MCP client config (Kiro, Claude Desktop, Cursor, etc.):
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "memnest": {
87
+ "command": "uvx",
88
+ "args": ["memnest-mcp@latest"],
89
+ "env": {
90
+ "FASTMCP_LOG_LEVEL": "ERROR"
91
+ }
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ That's it — zero config required. All settings have sensible defaults.
98
+
99
+ ## Tools
100
+
101
+ | Tool | What it does |
102
+ |------|-------------|
103
+ | `memory_store` | Store a memory (single or batch) with auto-dedup, auto-link to Topic nodes |
104
+ | `memory_search` | Hybrid semantic + keyword search, ranked by relevance |
105
+ | `memory_update` | Update content, importance, or tags (single or batch) |
106
+ | `memory_delete` | Delete one or more memories and their relationships |
107
+ | `memory_relate` | Create RELATED_TO / SUPERSEDES / EXPLAINS relationships (single or batch) |
108
+ | `memory_query` | Run any Cypher query — traversals, writes, extension calls (INSTALL/LOAD), table scans |
109
+ | `memory_schema` | Inspect live DB schema: tables, columns, indexes, extensions |
110
+ | `memory_topics` | List all topics (tags) with memory counts |
111
+ | `memory_stats` | Database statistics: counts, categories, topics, top memories |
112
+ | `memory_dream` | Periodic consolidation — auto-prune stale, auto-merge trivial duplicates, surface clusters for review |
113
+ | `memory_graph_html` | Generate an interactive HTML visualization of the graph |
114
+ | `memory_get` | (compat) Get full content of a memory by ID |
115
+ | `memory_list` | (compat) List memories filtered by recency, category, topic, or importance |
116
+ | `memory_traverse` | (compat) Read-only Cypher — alias for `memory_query(read_only=True)` |
117
+
118
+ ## Graph Data Model
119
+
120
+ ```
121
+ (:Memory) — content, embedding, category, tags, importance, access_count, timestamps
122
+ (:Topic) — auto-created from tags
123
+
124
+ (:Memory)-[:ABOUT]->(:Topic) # memory is about a topic
125
+ (:Memory)-[:RELATED_TO]->(:Memory) # memories are related
126
+ (:Memory)-[:SUPERSEDES]->(:Memory) # newer memory replaces older
127
+ ```
128
+
129
+ ### Example: Store and Search
130
+
131
+ ```python
132
+ # Store a memory (via MCP tool call)
133
+ memory_store(
134
+ content="User prefers Python over Node.js for backend tools",
135
+ category="preference",
136
+ tags=["python", "nodejs", "backend"],
137
+ importance=4
138
+ )
139
+
140
+ # Search memories
141
+ memory_search(query="what language does the user prefer")
142
+
143
+ # Traverse the graph
144
+ memory_query(
145
+ cypher_query="MATCH (m:Memory)-[:ABOUT]->(t:Topic {name: 'python'}) RETURN m.content"
146
+ )
147
+ ```
148
+
149
+ ### Example: Graph Relationships
150
+
151
+ ```python
152
+ # Link related memories
153
+ memory_relate(from_id=5, to_id=3, relationship="RELATED_TO")
154
+
155
+ # Mark a decision as superseded
156
+ memory_relate(from_id=8, to_id=2, relationship="SUPERSEDES")
157
+
158
+ # Find all memories about a topic
159
+ memory_query(
160
+ cypher_query="MATCH (m:Memory)-[:ABOUT]->(t:Topic) RETURN t.name, COUNT(m) ORDER BY COUNT(m) DESC"
161
+ )
162
+ ```
163
+
164
+ ## Three-Layer Deduplication
165
+
166
+ Every `memory_store` call runs through three dedup layers:
167
+
168
+ 1. **Exact hash** — SHA256 of normalized content. Identical content is rejected, importance bumped.
169
+ 2. **Semantic similarity** — If cosine similarity > 0.92 with an existing memory, merges into it (keeps longer content, merges tags, bumps importance).
170
+ 3. **Consolidation** — Periodic via `memory_dream`. Auto-prunes stale low-importance memories, auto-merges trivial duplicates (similarity ≥ 0.95), surfaces clusters for LLM-driven review.
171
+
172
+ ## Categories
173
+
174
+ | Category | Use for |
175
+ |----------|---------|
176
+ | `learning` | Technical knowledge, facts, how things work |
177
+ | `preference` | User preferences and choices |
178
+ | `decision` | Architecture decisions, tool choices |
179
+ | `pattern` | Recurring workflows, conventions |
180
+ | `general` | Everything else (default) |
181
+
182
+ ## Configuration
183
+
184
+ All settings are optional — defaults work out of the box.
185
+
186
+ | Environment Variable | Default | Description |
187
+ |---------------------|---------|-------------|
188
+ | `MEMORY_DB_PATH` | `~/.memnest/memory.lbug` | LadybugDB database path. Use `:memory:` for ephemeral testing |
189
+ | `MEMORY_DEDUP_THRESHOLD` | `0.92` | Semantic similarity threshold for auto-dedup |
190
+ | `MEMORY_EMBEDDING_MODEL` | `BAAI/bge-small-en-v1.5` | FastEmbed model for embeddings |
191
+ | `MEMORY_EMBEDDING_DIM` | `384` | Embedding dimension (must match model) |
192
+ | `MEMORY_WORKSPACE` | `cwd` | Workspace identifier for memory namespacing |
193
+ | `MEMORY_RESPONSE_FORMAT` | `toon` if installed, else `json` | Response serialization. `toon` is more token-efficient for LLM context |
194
+ | `MEMORY_SEARCH_LIMIT` | `10` | Max results from `memory_search` |
195
+ | `MEMORY_LIST_LIMIT` | `20` | Default page size for `memory_list` |
196
+ | `MEMORY_MAX_CONTENT` | `500` | Content truncation length in search/list results |
197
+ | `MEMORY_LATENCY_WARN_MS` | `200` | Log a warning when an op exceeds this (ms) |
198
+ | `MEMORY_DREAM_MIN_OPS` | `10` | Min ops since last dream before next runs |
199
+ | `MEMORY_DREAM_MIN_HOURS` | `24` | Min hours since last dream before next runs |
200
+ | `MEMORY_DREAM_MIN_MEMORIES` | `20` | Min total memories before dream is allowed (skipped otherwise) |
201
+ | `MEMORY_DREAM_PRUNE_DAYS` | `30` | Auto-prune memories older than N days (with low importance) |
202
+ | `MEMORY_DREAM_PRUNE_MAX_IMP` | `2` | Auto-prune only memories at or below this importance |
203
+ | `MEMORY_DREAM_TRIVIAL_THRESHOLD` | `0.95` | Cosine similarity ≥ this is auto-merged in dream |
204
+ | `MEMORY_DREAM_CLUSTER_LOW` | `0.88` | Cluster-review window: `[low, trivial)` is surfaced for agent review |
205
+ | `MEMORY_CONSOLIDATE_CLUSTERS` | `10` | Max clusters returned per `memory_dream` run |
206
+ | `MEMORY_CONSOLIDATE_SCAN` | `1000` | Max memories scanned per dream phase |
207
+ | `MEMORY_ALLOW_DESTRUCTIVE` | `false` | Allow DELETE/DROP/TRUNCATE through `memory_query`. **Off by default for safety**. Opt in with `true` |
208
+ | `MEMORY_GRAPH_MAX_NODES` | `2000` | Max nodes `memory_graph_html` will render before refusing |
209
+ | `MEMORY_EMBED_TIMEOUT_S` | `30` | Soft timeout for embedding model load (warm-up only) |
210
+
211
+ ### In-Memory Mode (Testing)
212
+
213
+ ```json
214
+ "env": { "MEMORY_DB_PATH": ":memory:" }
215
+ ```
216
+
217
+ All data is ephemeral — lost on restart. Useful for testing.
218
+
219
+ ## Kiro Power
220
+
221
+ This server is also available as a [Kiro Power](https://github.com/arunkumars-mf/memnest-power) with:
222
+ - Pre-configured MCP server
223
+ - Three hooks for automatic memory persistence and recall
224
+ - Steering files with setup guide and Cypher query examples
225
+
226
+ ## Architecture
227
+
228
+ ```
229
+ AI Agent (Kiro, Claude, etc.)
230
+ │
231
+ ├─ memory_store ──→ embed content → dedup check → insert node → link topics
232
+ ├─ memory_search ─→ embed query → HNSW vector search → tag boost → rank
233
+ ├─ memory_query ──→ execute Cypher → return graph results
234
+ │
235
+ └─ LadybugDB (embedded, single directory)
236
+ ├─ Memory nodes (content + FLOAT[384] embeddings)
237
+ ├─ Topic nodes (auto-linked from tags)
238
+ ├─ HNSW vector index (cosine similarity)
239
+ └─ Graph relationships (ABOUT, RELATED_TO, SUPERSEDES, EXPLAINS)
240
+ ```
241
+
242
+ ## Requirements
243
+
244
+ - Python 3.10+
245
+ - Dependencies installed automatically: `real-ladybug`, `fastembed`, `mcp`
246
+ - ~130MB disk for the embedding model (downloaded on first run)
247
+
248
+ ## Contributing
249
+
250
+ Issues and PRs welcome. See [LICENSE](LICENSE) for terms.
251
+
252
+ ## License
253
+
254
+ [MIT](LICENSE)
255
+
256
+ ## Changelog
257
+
258
+ ### 0.3.0
259
+
260
+ - Default database directory is `~/.memnest/`.
261
+ - Set `MEMORY_DB_PATH` to use a custom location.
262
+ - Hybrid search: Vector (HNSW) + Full-text (BM25) + Graph scoring with PageRank, Louvain community detection, and K-Core decomposition.
263
+ - LOCOMO benchmark: 82.9% overall score.
264
+
265
+ ### 0.2.0
266
+
267
+ Compatibility-preserving redesign with improved safety defaults.
268
+
269
+ - New tools: `memory_query` (general Cypher), `memory_schema`, `memory_topics`, `memory_dream`, `memory_graph_html`. Batch mode added to `memory_store`, `memory_update`, `memory_relate`, `memory_delete`.
270
+ - **Breaking**: `MEMORY_ALLOW_DESTRUCTIVE` now defaults to `false`. Set it to `true` if you previously relied on `memory_query` deleting nodes.
271
+ - **Breaking**: tag storage migrated from comma-joined strings to JSON arrays. Old rows are still readable; rewriting (e.g. via `memory_update`) upgrades them to JSON.
272
+ - `memory_get`, `memory_list`, `memory_traverse` from 0.1.x are retained as compatibility aliases. They will be removed in 0.3.0.
273
+ - TOON serialization is now the default response format when `toon-format` is installed; set `MEMORY_RESPONSE_FORMAT=json` to opt out.
274
+ - `memory_relate` validates that both endpoints exist before returning `created` (used to silently no-op on typo'd IDs).
275
+ - `memory_graph_html` is now XSS-safe (HTML-escaped tooltips, DOM `textContent` for the detail panel), refuses to render >`MEMORY_GRAPH_MAX_NODES`, and rotates snapshots.
276
+ - Workspace filter pushed inside the vector index `WITH` clause so search recall isn't starved across workspaces.
277
+ - Dream consolidation: dedupes parallel edges across merges, isolates clusters by workspace, persists state via atomic sidecar JSON.
@@ -0,0 +1,257 @@
1
+ # Memnest Memory MCP Server
2
+
3
+ [![PyPI version](https://badge.fury.io/py/memnest-mcp.svg)](https://pypi.org/project/memnest-mcp/)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
6
+
7
+ Persistent graph memory for AI agents using [LadybugDB](https://ladybugdb.com/) — an embedded graph database with native vector search and full-text search.
8
+
9
+ Give your AI agent memory that persists across sessions, deduplicates automatically, and models knowledge as a graph with typed relationships.
10
+
11
+ ## Why Memnest?
12
+
13
+ - **Graph memory** — memories linked via Topic nodes and relationships (RELATED_TO, SUPERSEDES, EXPLAINS) with Cypher queries
14
+ - **Three-layer auto-dedup** — exact hash + semantic similarity + LLM-driven consolidation
15
+ - **Workspace namespacing** — memories scoped per project; `global_search` opt-out
16
+ - **HNSW vector search** — fast cosine similarity over FastEmbed embeddings
17
+ - **Topic auto-linking** — tags become graph nodes, enabling traversal queries
18
+ - **Embedded** — no Docker, no server process, single database directory
19
+ - **Zero config** — sensible defaults, just install and run
20
+ - **Importance & access tracking** — memories ranked by relevance and usage
21
+
22
+ ## Benchmarks
23
+
24
+ Memnest scores **82.9%** on the [LOCOMO benchmark](https://snap-research.github.io/locomo/) — the standard evaluation for long-term conversational memory (ACL 2024).
25
+
26
+ | Category | Score |
27
+ |----------|-------|
28
+ | Single-hop | 84.4% |
29
+ | Multi-hop | 76.9% |
30
+ | Open-domain | 85.7% |
31
+ | Temporal | 86.5% |
32
+ | Adversarial | 76.6% |
33
+ | **Overall** | **82.9%** |
34
+
35
+ Evaluated with Claude Sonnet 4.5 as the answer agent and Haiku 4.5 as the judge, using the industry-standard LLM-as-a-Judge methodology. All 5 LOCOMO categories included.
36
+
37
+ ### Architecture advantages
38
+
39
+ - **Zero LLM calls in the server** — intelligence lives in the agent, not the memory layer
40
+ - **Local embeddings** — no API key needed (`bge-small-en-v1.5`, 384-dim)
41
+ - **Single embedded database** — no Docker, no PostgreSQL, no separate vector DB
42
+ - **Hybrid search** — Vector (HNSW) + Full-text (BM25) + Graph (PageRank + Louvain communities)
43
+ - **3 agent tools** — `memory_search`, `memory_get`, `calculator`. Simple interface, powerful retrieval.
44
+
45
+ ## Quick Start
46
+
47
+ ```bash
48
+ # Run directly with uvx (no install needed)
49
+ uvx memnest-mcp
50
+ ```
51
+
52
+ Or install and run:
53
+
54
+ ```bash
55
+ pip install memnest-mcp
56
+ memnest-mcp
57
+ ```
58
+
59
+ ## MCP Configuration
60
+
61
+ Add to your MCP client config (Kiro, Claude Desktop, Cursor, etc.):
62
+
63
+ ```json
64
+ {
65
+ "mcpServers": {
66
+ "memnest": {
67
+ "command": "uvx",
68
+ "args": ["memnest-mcp@latest"],
69
+ "env": {
70
+ "FASTMCP_LOG_LEVEL": "ERROR"
71
+ }
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ That's it — zero config required. All settings have sensible defaults.
78
+
79
+ ## Tools
80
+
81
+ | Tool | What it does |
82
+ |------|-------------|
83
+ | `memory_store` | Store a memory (single or batch) with auto-dedup, auto-link to Topic nodes |
84
+ | `memory_search` | Hybrid semantic + keyword search, ranked by relevance |
85
+ | `memory_update` | Update content, importance, or tags (single or batch) |
86
+ | `memory_delete` | Delete one or more memories and their relationships |
87
+ | `memory_relate` | Create RELATED_TO / SUPERSEDES / EXPLAINS relationships (single or batch) |
88
+ | `memory_query` | Run any Cypher query — traversals, writes, extension calls (INSTALL/LOAD), table scans |
89
+ | `memory_schema` | Inspect live DB schema: tables, columns, indexes, extensions |
90
+ | `memory_topics` | List all topics (tags) with memory counts |
91
+ | `memory_stats` | Database statistics: counts, categories, topics, top memories |
92
+ | `memory_dream` | Periodic consolidation — auto-prune stale, auto-merge trivial duplicates, surface clusters for review |
93
+ | `memory_graph_html` | Generate an interactive HTML visualization of the graph |
94
+ | `memory_get` | (compat) Get full content of a memory by ID |
95
+ | `memory_list` | (compat) List memories filtered by recency, category, topic, or importance |
96
+ | `memory_traverse` | (compat) Read-only Cypher — alias for `memory_query(read_only=True)` |
97
+
98
+ ## Graph Data Model
99
+
100
+ ```
101
+ (:Memory) — content, embedding, category, tags, importance, access_count, timestamps
102
+ (:Topic) — auto-created from tags
103
+
104
+ (:Memory)-[:ABOUT]->(:Topic) # memory is about a topic
105
+ (:Memory)-[:RELATED_TO]->(:Memory) # memories are related
106
+ (:Memory)-[:SUPERSEDES]->(:Memory) # newer memory replaces older
107
+ ```
108
+
109
+ ### Example: Store and Search
110
+
111
+ ```python
112
+ # Store a memory (via MCP tool call)
113
+ memory_store(
114
+ content="User prefers Python over Node.js for backend tools",
115
+ category="preference",
116
+ tags=["python", "nodejs", "backend"],
117
+ importance=4
118
+ )
119
+
120
+ # Search memories
121
+ memory_search(query="what language does the user prefer")
122
+
123
+ # Traverse the graph
124
+ memory_query(
125
+ cypher_query="MATCH (m:Memory)-[:ABOUT]->(t:Topic {name: 'python'}) RETURN m.content"
126
+ )
127
+ ```
128
+
129
+ ### Example: Graph Relationships
130
+
131
+ ```python
132
+ # Link related memories
133
+ memory_relate(from_id=5, to_id=3, relationship="RELATED_TO")
134
+
135
+ # Mark a decision as superseded
136
+ memory_relate(from_id=8, to_id=2, relationship="SUPERSEDES")
137
+
138
+ # Find all memories about a topic
139
+ memory_query(
140
+ cypher_query="MATCH (m:Memory)-[:ABOUT]->(t:Topic) RETURN t.name, COUNT(m) ORDER BY COUNT(m) DESC"
141
+ )
142
+ ```
143
+
144
+ ## Three-Layer Deduplication
145
+
146
+ Every `memory_store` call runs through three dedup layers:
147
+
148
+ 1. **Exact hash** — SHA256 of normalized content. Identical content is rejected, importance bumped.
149
+ 2. **Semantic similarity** — If cosine similarity > 0.92 with an existing memory, merges into it (keeps longer content, merges tags, bumps importance).
150
+ 3. **Consolidation** — Periodic via `memory_dream`. Auto-prunes stale low-importance memories, auto-merges trivial duplicates (similarity ≥ 0.95), surfaces clusters for LLM-driven review.
151
+
152
+ ## Categories
153
+
154
+ | Category | Use for |
155
+ |----------|---------|
156
+ | `learning` | Technical knowledge, facts, how things work |
157
+ | `preference` | User preferences and choices |
158
+ | `decision` | Architecture decisions, tool choices |
159
+ | `pattern` | Recurring workflows, conventions |
160
+ | `general` | Everything else (default) |
161
+
162
+ ## Configuration
163
+
164
+ All settings are optional — defaults work out of the box.
165
+
166
+ | Environment Variable | Default | Description |
167
+ |---------------------|---------|-------------|
168
+ | `MEMORY_DB_PATH` | `~/.memnest/memory.lbug` | LadybugDB database path. Use `:memory:` for ephemeral testing |
169
+ | `MEMORY_DEDUP_THRESHOLD` | `0.92` | Semantic similarity threshold for auto-dedup |
170
+ | `MEMORY_EMBEDDING_MODEL` | `BAAI/bge-small-en-v1.5` | FastEmbed model for embeddings |
171
+ | `MEMORY_EMBEDDING_DIM` | `384` | Embedding dimension (must match model) |
172
+ | `MEMORY_WORKSPACE` | `cwd` | Workspace identifier for memory namespacing |
173
+ | `MEMORY_RESPONSE_FORMAT` | `toon` if installed, else `json` | Response serialization. `toon` is more token-efficient for LLM context |
174
+ | `MEMORY_SEARCH_LIMIT` | `10` | Max results from `memory_search` |
175
+ | `MEMORY_LIST_LIMIT` | `20` | Default page size for `memory_list` |
176
+ | `MEMORY_MAX_CONTENT` | `500` | Content truncation length in search/list results |
177
+ | `MEMORY_LATENCY_WARN_MS` | `200` | Log a warning when an op exceeds this (ms) |
178
+ | `MEMORY_DREAM_MIN_OPS` | `10` | Min ops since last dream before next runs |
179
+ | `MEMORY_DREAM_MIN_HOURS` | `24` | Min hours since last dream before next runs |
180
+ | `MEMORY_DREAM_MIN_MEMORIES` | `20` | Min total memories before dream is allowed (skipped otherwise) |
181
+ | `MEMORY_DREAM_PRUNE_DAYS` | `30` | Auto-prune memories older than N days (with low importance) |
182
+ | `MEMORY_DREAM_PRUNE_MAX_IMP` | `2` | Auto-prune only memories at or below this importance |
183
+ | `MEMORY_DREAM_TRIVIAL_THRESHOLD` | `0.95` | Cosine similarity ≥ this is auto-merged in dream |
184
+ | `MEMORY_DREAM_CLUSTER_LOW` | `0.88` | Cluster-review window: `[low, trivial)` is surfaced for agent review |
185
+ | `MEMORY_CONSOLIDATE_CLUSTERS` | `10` | Max clusters returned per `memory_dream` run |
186
+ | `MEMORY_CONSOLIDATE_SCAN` | `1000` | Max memories scanned per dream phase |
187
+ | `MEMORY_ALLOW_DESTRUCTIVE` | `false` | Allow DELETE/DROP/TRUNCATE through `memory_query`. **Off by default for safety**. Opt in with `true` |
188
+ | `MEMORY_GRAPH_MAX_NODES` | `2000` | Max nodes `memory_graph_html` will render before refusing |
189
+ | `MEMORY_EMBED_TIMEOUT_S` | `30` | Soft timeout for embedding model load (warm-up only) |
190
+
191
+ ### In-Memory Mode (Testing)
192
+
193
+ ```json
194
+ "env": { "MEMORY_DB_PATH": ":memory:" }
195
+ ```
196
+
197
+ All data is ephemeral — lost on restart. Useful for testing.
198
+
199
+ ## Kiro Power
200
+
201
+ This server is also available as a [Kiro Power](https://github.com/arunkumars-mf/memnest-power) with:
202
+ - Pre-configured MCP server
203
+ - Three hooks for automatic memory persistence and recall
204
+ - Steering files with setup guide and Cypher query examples
205
+
206
+ ## Architecture
207
+
208
+ ```
209
+ AI Agent (Kiro, Claude, etc.)
210
+ │
211
+ ├─ memory_store ──→ embed content → dedup check → insert node → link topics
212
+ ├─ memory_search ─→ embed query → HNSW vector search → tag boost → rank
213
+ ├─ memory_query ──→ execute Cypher → return graph results
214
+ │
215
+ └─ LadybugDB (embedded, single directory)
216
+ ├─ Memory nodes (content + FLOAT[384] embeddings)
217
+ ├─ Topic nodes (auto-linked from tags)
218
+ ├─ HNSW vector index (cosine similarity)
219
+ └─ Graph relationships (ABOUT, RELATED_TO, SUPERSEDES, EXPLAINS)
220
+ ```
221
+
222
+ ## Requirements
223
+
224
+ - Python 3.10+
225
+ - Dependencies installed automatically: `real-ladybug`, `fastembed`, `mcp`
226
+ - ~130MB disk for the embedding model (downloaded on first run)
227
+
228
+ ## Contributing
229
+
230
+ Issues and PRs welcome. See [LICENSE](LICENSE) for terms.
231
+
232
+ ## License
233
+
234
+ [MIT](LICENSE)
235
+
236
+ ## Changelog
237
+
238
+ ### 0.3.0
239
+
240
+ - Default database directory is `~/.memnest/`.
241
+ - Set `MEMORY_DB_PATH` to use a custom location.
242
+ - Hybrid search: Vector (HNSW) + Full-text (BM25) + Graph scoring with PageRank, Louvain community detection, and K-Core decomposition.
243
+ - LOCOMO benchmark: 82.9% overall score.
244
+
245
+ ### 0.2.0
246
+
247
+ Compatibility-preserving redesign with improved safety defaults.
248
+
249
+ - New tools: `memory_query` (general Cypher), `memory_schema`, `memory_topics`, `memory_dream`, `memory_graph_html`. Batch mode added to `memory_store`, `memory_update`, `memory_relate`, `memory_delete`.
250
+ - **Breaking**: `MEMORY_ALLOW_DESTRUCTIVE` now defaults to `false`. Set it to `true` if you previously relied on `memory_query` deleting nodes.
251
+ - **Breaking**: tag storage migrated from comma-joined strings to JSON arrays. Old rows are still readable; rewriting (e.g. via `memory_update`) upgrades them to JSON.
252
+ - `memory_get`, `memory_list`, `memory_traverse` from 0.1.x are retained as compatibility aliases. They will be removed in 0.3.0.
253
+ - TOON serialization is now the default response format when `toon-format` is installed; set `MEMORY_RESPONSE_FORMAT=json` to opt out.
254
+ - `memory_relate` validates that both endpoints exist before returning `created` (used to silently no-op on typo'd IDs).
255
+ - `memory_graph_html` is now XSS-safe (HTML-escaped tooltips, DOM `textContent` for the detail panel), refuses to render >`MEMORY_GRAPH_MAX_NODES`, and rotates snapshots.
256
+ - Workspace filter pushed inside the vector index `WITH` clause so search recall isn't starved across workspaces.
257
+ - Dream consolidation: dedupes parallel edges across merges, isolates clusters by workspace, persists state via atomic sidecar JSON.
@@ -0,0 +1 @@
1
+ """Memnest LOCOMO benchmark adapter."""