mnemo-agent 0.2.2__tar.gz → 0.3.1__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.
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/PKG-INFO +60 -19
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/README.md +59 -18
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/pyproject.toml +1 -1
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/cli.py +101 -6
- mnemo_agent-0.3.1/src/mnemo/server.py +383 -0
- mnemo_agent-0.3.1/src/mnemo/stdio_server.py +64 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo_agent.egg-info/PKG-INFO +60 -19
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo_agent.egg-info/SOURCES.txt +3 -1
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/tests/test_cli.py +82 -0
- mnemo_agent-0.3.1/tests/test_server.py +380 -0
- mnemo_agent-0.2.2/src/mnemo/server.py +0 -237
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/LICENSE +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/setup.cfg +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/__init__.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/adapters/__init__.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/adapters/letta_adapter.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/adapters/mem0_adapter.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/models.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/remotes.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/search.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo/storage.py +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo_agent.egg-info/dependency_links.txt +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo_agent.egg-info/entry_points.txt +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo_agent.egg-info/requires.txt +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/src/mnemo_agent.egg-info/top_level.txt +0 -0
- {mnemo_agent-0.2.2 → mnemo_agent-0.3.1}/tests/test_remote.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mnemo-agent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Local-first agent memory CLI — dump, diff, migrate & query across Mem0, Letta, and more
|
|
5
5
|
Author: Joshua Ndala
|
|
6
6
|
License-Expression: MIT
|
|
@@ -62,7 +62,7 @@ Inspired by Mnemosyne (Greek goddess of memory), **mnemo** is a portable CLI for
|
|
|
62
62
|
- **TF-IDF search** — `mnemo recall "query"` with zero external ML deps, filterable by `--tag`
|
|
63
63
|
- **Rich tables** — confidence color-coded (🟢 ≥0.8, 🟡 ≥0.5, 🔴 <0.5)
|
|
64
64
|
- **HTML + graph diffs** — visual diff between dump snapshots
|
|
65
|
-
- **MCP server** —
|
|
65
|
+
- **MCP server** — JSON-RPC 2.0 + stdio transport; plug directly into Claude Desktop, Cursor, or any MCP client
|
|
66
66
|
- **Push/pull sync** — S3, Cloudflare R2, or local filesystem remote; timestamp-based merge
|
|
67
67
|
- **Safe writes** — `--dry-run` on load, pull, and migrate
|
|
68
68
|
|
|
@@ -110,8 +110,10 @@ mnemo load --file tests/fixtures/job_prep_sample.json --agent job-prep
|
|
|
110
110
|
mnemo diff --agent-a job-prep --agent-b job-prep-v2
|
|
111
111
|
mnemo diff dump1.json dump2.json --html diff_report.html
|
|
112
112
|
|
|
113
|
-
# Start the MCP server
|
|
113
|
+
# Start the MCP server — HTTP mode
|
|
114
114
|
mnemo serve --agent job-prep --port 8080
|
|
115
|
+
# Or stdio mode (Claude Desktop / Cursor — no port needed)
|
|
116
|
+
mnemo serve --agent job-prep --stdio
|
|
115
117
|
|
|
116
118
|
# Sync to S3 (prompts for credentials on first add)
|
|
117
119
|
mnemo remote add origin s3://my-bucket/mnemo --agent job-prep
|
|
@@ -137,7 +139,7 @@ mnemo pull --agent job-prep # merges remote facts into local
|
|
|
137
139
|
| `mnemo retract <fact-id> --agent <name>` | Remove a fact by ID or 8-char prefix |
|
|
138
140
|
| `mnemo edit <fact-id> --agent <name>` | Edit value/attribute/confidence of an existing fact |
|
|
139
141
|
| `mnemo migrate --dump f.json --target mem0 --agent name` | Migrate between providers |
|
|
140
|
-
| `mnemo serve --agent <name> [--port 8080] [--read-only]` | MCP
|
|
142
|
+
| `mnemo serve --agent <name> [--port 8080] [--stdio] [--read-only]` | MCP server — HTTP (JSON-RPC 2.0) or stdio for Claude Desktop / Cursor |
|
|
141
143
|
| `mnemo remote add <name> <url> --agent <name>` | Add a named remote (s3://, r2://, file://) |
|
|
142
144
|
| `mnemo remote list --agent <name>` | List configured remotes |
|
|
143
145
|
| `mnemo remote remove <name> --agent <name>` | Remove a remote |
|
|
@@ -157,13 +159,15 @@ mnemo-agent/
|
|
|
157
159
|
│ ├── storage.py # Local file I/O (JSON, YAML, credentials)
|
|
158
160
|
│ ├── search.py # TF-IDF search + diff engine
|
|
159
161
|
│ ├── remotes.py # Push/pull backends: FileBackend, S3Backend
|
|
160
|
-
│ ├── server.py # FastAPI MCP server
|
|
162
|
+
│ ├── server.py # FastAPI MCP server (HTTP + JSON-RPC 2.0)
|
|
163
|
+
│ ├── stdio_server.py # stdio MCP transport (Claude Desktop / Cursor)
|
|
161
164
|
│ └── adapters/
|
|
162
165
|
│ ├── mem0_adapter.py # Mem0 API → normalized facts
|
|
163
166
|
│ └── letta_adapter.py # Letta API → normalized facts
|
|
164
167
|
├── tests/
|
|
165
168
|
│ ├── test_cli.py # CLI command tests
|
|
166
169
|
│ ├── test_remote.py # Remote backends, merge, push/pull tests
|
|
170
|
+
│ ├── test_server.py # MCP server: JSON-RPC 2.0, tools, stdio transport
|
|
167
171
|
│ └── fixtures/
|
|
168
172
|
│ └── job_prep_sample.json
|
|
169
173
|
├── config.yaml # Sample agent config
|
|
@@ -238,7 +242,28 @@ mnemo-agent/
|
|
|
238
242
|
|
|
239
243
|
---
|
|
240
244
|
|
|
241
|
-
## 🔌 MCP Server
|
|
245
|
+
## 🔌 MCP Server
|
|
246
|
+
|
|
247
|
+
mnemo implements the [MCP 2024-11-05 spec](https://spec.modelcontextprotocol.io) and supports two transports.
|
|
248
|
+
|
|
249
|
+
### stdio — Claude Desktop / Cursor
|
|
250
|
+
|
|
251
|
+
Add to `~/.claude/claude_desktop_config.json`:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"mcpServers": {
|
|
256
|
+
"mnemo-job-prep": {
|
|
257
|
+
"command": "mnemo",
|
|
258
|
+
"args": ["serve", "--agent", "job-prep", "--stdio"]
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
That's it — Claude Desktop will spawn mnemo as a subprocess and communicate over stdin/stdout.
|
|
265
|
+
|
|
266
|
+
### HTTP — REST + JSON-RPC 2.0
|
|
242
267
|
|
|
243
268
|
```bash
|
|
244
269
|
mnemo serve --agent job-prep --port 8080
|
|
@@ -246,20 +271,26 @@ mnemo serve --agent job-prep --port 8080
|
|
|
246
271
|
|
|
247
272
|
| Endpoint | Description |
|
|
248
273
|
|---|---|
|
|
249
|
-
| `
|
|
250
|
-
| `
|
|
251
|
-
| `
|
|
252
|
-
| `GET /
|
|
274
|
+
| `POST /` | JSON-RPC 2.0 — `initialize`, `tools/list`, `tools/call`, `ping` |
|
|
275
|
+
| `GET /mcp/list_tools` | List available tools (legacy, kept for compatibility) |
|
|
276
|
+
| `POST /mcp/call_tool` | Call a tool by name (legacy, kept for compatibility) |
|
|
277
|
+
| `GET /facts` | REST: list all facts (`?entity=`, `?attribute=`, `?tag=`) |
|
|
278
|
+
| `GET /search?q=query` | REST: search memories (`?tag=` filter supported) |
|
|
279
|
+
| `GET /health` | Health check with version info |
|
|
253
280
|
| `GET /docs` | Swagger UI |
|
|
254
281
|
|
|
255
282
|
### Available MCP tools
|
|
256
283
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
284
|
+
| Tool | Description |
|
|
285
|
+
|---|---|
|
|
286
|
+
| `search_memory` | TF-IDF keyword search; supports `tag` filter |
|
|
287
|
+
| `list_facts` | List all facts; filterable by `entity`, `attribute`, `tag`; shows IDs |
|
|
288
|
+
| `upsert_fact` | Add a fact; supports `tags` array |
|
|
289
|
+
| `retract_fact` | Remove a fact by ID or 8-char prefix |
|
|
290
|
+
| `edit_fact` | Update a fact's `value`, `attribute`, or `confidence` |
|
|
291
|
+
| `get_agent_info` | Agent name, fact count, last updated timestamp |
|
|
292
|
+
|
|
293
|
+
`retract_fact` and `edit_fact` are disabled when `--read-only` is set.
|
|
263
294
|
|
|
264
295
|
---
|
|
265
296
|
|
|
@@ -299,20 +330,23 @@ Remote credentials (S3/R2 access keys) are stored separately in `~/.mnemo/creden
|
|
|
299
330
|
## Tests
|
|
300
331
|
|
|
301
332
|
```bash
|
|
302
|
-
pip install "mnemo-agent[dev]"
|
|
333
|
+
pip install "mnemo-agent[dev,s3]"
|
|
303
334
|
pytest tests/ -v
|
|
304
335
|
```
|
|
305
336
|
|
|
337
|
+
114 tests across `test_cli.py`, `test_remote.py`, and `test_server.py`.
|
|
338
|
+
|
|
306
339
|
---
|
|
307
340
|
|
|
308
341
|
## Roadmap
|
|
309
342
|
|
|
310
343
|
- [x] Push/pull sync to S3, R2, and local filesystem remotes
|
|
344
|
+
- [x] Write-time conflict detection with overwrite / keep-both / abort prompt
|
|
345
|
+
- [x] Full MCP 2024-11-05 protocol — JSON-RPC 2.0 + stdio transport (Claude Desktop / Cursor)
|
|
311
346
|
- [ ] Vector embeddings for semantic search (v2)
|
|
312
347
|
- [ ] Parquet export for analytics
|
|
313
348
|
- [ ] `mnemo audit` — fact provenance trace
|
|
314
349
|
- [ ] Web UI dashboard
|
|
315
|
-
- [ ] Native Ollama MCP client registration
|
|
316
350
|
|
|
317
351
|
---
|
|
318
352
|
|
|
@@ -323,13 +357,20 @@ pytest tests/ -v
|
|
|
323
357
|
mnemo init --agent job-prep
|
|
324
358
|
mnemo load --file tests/fixtures/job_prep_sample.json --agent job-prep
|
|
325
359
|
|
|
326
|
-
#
|
|
360
|
+
# Connect to Claude Desktop (add to claude_desktop_config.json, then restart)
|
|
361
|
+
mnemo serve --agent job-prep --stdio
|
|
362
|
+
|
|
363
|
+
# Or run as an HTTP server for other MCP clients
|
|
327
364
|
mnemo serve --agent job-prep --port 8080
|
|
328
365
|
|
|
329
366
|
# After a practice interview, add what you learned
|
|
330
367
|
mnemo add --fact "Lead with Supabase migration story at FAANG interviews" \
|
|
331
368
|
--agent job-prep --attribute interview_tip --confidence 0.9 --tag tip
|
|
332
369
|
|
|
370
|
+
# If you added a conflicting fact by mistake, retract it by ID prefix
|
|
371
|
+
mnemo show --agent job-prep --format plain # see IDs
|
|
372
|
+
mnemo retract a1b2c3d4 --agent job-prep
|
|
373
|
+
|
|
333
374
|
# Before next session, recall relevant context
|
|
334
375
|
mnemo recall "React Supabase full-stack" --agent job-prep
|
|
335
376
|
```
|
|
@@ -16,7 +16,7 @@ Inspired by Mnemosyne (Greek goddess of memory), **mnemo** is a portable CLI for
|
|
|
16
16
|
- **TF-IDF search** — `mnemo recall "query"` with zero external ML deps, filterable by `--tag`
|
|
17
17
|
- **Rich tables** — confidence color-coded (🟢 ≥0.8, 🟡 ≥0.5, 🔴 <0.5)
|
|
18
18
|
- **HTML + graph diffs** — visual diff between dump snapshots
|
|
19
|
-
- **MCP server** —
|
|
19
|
+
- **MCP server** — JSON-RPC 2.0 + stdio transport; plug directly into Claude Desktop, Cursor, or any MCP client
|
|
20
20
|
- **Push/pull sync** — S3, Cloudflare R2, or local filesystem remote; timestamp-based merge
|
|
21
21
|
- **Safe writes** — `--dry-run` on load, pull, and migrate
|
|
22
22
|
|
|
@@ -64,8 +64,10 @@ mnemo load --file tests/fixtures/job_prep_sample.json --agent job-prep
|
|
|
64
64
|
mnemo diff --agent-a job-prep --agent-b job-prep-v2
|
|
65
65
|
mnemo diff dump1.json dump2.json --html diff_report.html
|
|
66
66
|
|
|
67
|
-
# Start the MCP server
|
|
67
|
+
# Start the MCP server — HTTP mode
|
|
68
68
|
mnemo serve --agent job-prep --port 8080
|
|
69
|
+
# Or stdio mode (Claude Desktop / Cursor — no port needed)
|
|
70
|
+
mnemo serve --agent job-prep --stdio
|
|
69
71
|
|
|
70
72
|
# Sync to S3 (prompts for credentials on first add)
|
|
71
73
|
mnemo remote add origin s3://my-bucket/mnemo --agent job-prep
|
|
@@ -91,7 +93,7 @@ mnemo pull --agent job-prep # merges remote facts into local
|
|
|
91
93
|
| `mnemo retract <fact-id> --agent <name>` | Remove a fact by ID or 8-char prefix |
|
|
92
94
|
| `mnemo edit <fact-id> --agent <name>` | Edit value/attribute/confidence of an existing fact |
|
|
93
95
|
| `mnemo migrate --dump f.json --target mem0 --agent name` | Migrate between providers |
|
|
94
|
-
| `mnemo serve --agent <name> [--port 8080] [--read-only]` | MCP
|
|
96
|
+
| `mnemo serve --agent <name> [--port 8080] [--stdio] [--read-only]` | MCP server — HTTP (JSON-RPC 2.0) or stdio for Claude Desktop / Cursor |
|
|
95
97
|
| `mnemo remote add <name> <url> --agent <name>` | Add a named remote (s3://, r2://, file://) |
|
|
96
98
|
| `mnemo remote list --agent <name>` | List configured remotes |
|
|
97
99
|
| `mnemo remote remove <name> --agent <name>` | Remove a remote |
|
|
@@ -111,13 +113,15 @@ mnemo-agent/
|
|
|
111
113
|
│ ├── storage.py # Local file I/O (JSON, YAML, credentials)
|
|
112
114
|
│ ├── search.py # TF-IDF search + diff engine
|
|
113
115
|
│ ├── remotes.py # Push/pull backends: FileBackend, S3Backend
|
|
114
|
-
│ ├── server.py # FastAPI MCP server
|
|
116
|
+
│ ├── server.py # FastAPI MCP server (HTTP + JSON-RPC 2.0)
|
|
117
|
+
│ ├── stdio_server.py # stdio MCP transport (Claude Desktop / Cursor)
|
|
115
118
|
│ └── adapters/
|
|
116
119
|
│ ├── mem0_adapter.py # Mem0 API → normalized facts
|
|
117
120
|
│ └── letta_adapter.py # Letta API → normalized facts
|
|
118
121
|
├── tests/
|
|
119
122
|
│ ├── test_cli.py # CLI command tests
|
|
120
123
|
│ ├── test_remote.py # Remote backends, merge, push/pull tests
|
|
124
|
+
│ ├── test_server.py # MCP server: JSON-RPC 2.0, tools, stdio transport
|
|
121
125
|
│ └── fixtures/
|
|
122
126
|
│ └── job_prep_sample.json
|
|
123
127
|
├── config.yaml # Sample agent config
|
|
@@ -192,7 +196,28 @@ mnemo-agent/
|
|
|
192
196
|
|
|
193
197
|
---
|
|
194
198
|
|
|
195
|
-
## 🔌 MCP Server
|
|
199
|
+
## 🔌 MCP Server
|
|
200
|
+
|
|
201
|
+
mnemo implements the [MCP 2024-11-05 spec](https://spec.modelcontextprotocol.io) and supports two transports.
|
|
202
|
+
|
|
203
|
+
### stdio — Claude Desktop / Cursor
|
|
204
|
+
|
|
205
|
+
Add to `~/.claude/claude_desktop_config.json`:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"mcpServers": {
|
|
210
|
+
"mnemo-job-prep": {
|
|
211
|
+
"command": "mnemo",
|
|
212
|
+
"args": ["serve", "--agent", "job-prep", "--stdio"]
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
That's it — Claude Desktop will spawn mnemo as a subprocess and communicate over stdin/stdout.
|
|
219
|
+
|
|
220
|
+
### HTTP — REST + JSON-RPC 2.0
|
|
196
221
|
|
|
197
222
|
```bash
|
|
198
223
|
mnemo serve --agent job-prep --port 8080
|
|
@@ -200,20 +225,26 @@ mnemo serve --agent job-prep --port 8080
|
|
|
200
225
|
|
|
201
226
|
| Endpoint | Description |
|
|
202
227
|
|---|---|
|
|
203
|
-
| `
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
206
|
-
| `GET /
|
|
228
|
+
| `POST /` | JSON-RPC 2.0 — `initialize`, `tools/list`, `tools/call`, `ping` |
|
|
229
|
+
| `GET /mcp/list_tools` | List available tools (legacy, kept for compatibility) |
|
|
230
|
+
| `POST /mcp/call_tool` | Call a tool by name (legacy, kept for compatibility) |
|
|
231
|
+
| `GET /facts` | REST: list all facts (`?entity=`, `?attribute=`, `?tag=`) |
|
|
232
|
+
| `GET /search?q=query` | REST: search memories (`?tag=` filter supported) |
|
|
233
|
+
| `GET /health` | Health check with version info |
|
|
207
234
|
| `GET /docs` | Swagger UI |
|
|
208
235
|
|
|
209
236
|
### Available MCP tools
|
|
210
237
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
238
|
+
| Tool | Description |
|
|
239
|
+
|---|---|
|
|
240
|
+
| `search_memory` | TF-IDF keyword search; supports `tag` filter |
|
|
241
|
+
| `list_facts` | List all facts; filterable by `entity`, `attribute`, `tag`; shows IDs |
|
|
242
|
+
| `upsert_fact` | Add a fact; supports `tags` array |
|
|
243
|
+
| `retract_fact` | Remove a fact by ID or 8-char prefix |
|
|
244
|
+
| `edit_fact` | Update a fact's `value`, `attribute`, or `confidence` |
|
|
245
|
+
| `get_agent_info` | Agent name, fact count, last updated timestamp |
|
|
246
|
+
|
|
247
|
+
`retract_fact` and `edit_fact` are disabled when `--read-only` is set.
|
|
217
248
|
|
|
218
249
|
---
|
|
219
250
|
|
|
@@ -253,20 +284,23 @@ Remote credentials (S3/R2 access keys) are stored separately in `~/.mnemo/creden
|
|
|
253
284
|
## Tests
|
|
254
285
|
|
|
255
286
|
```bash
|
|
256
|
-
pip install "mnemo-agent[dev]"
|
|
287
|
+
pip install "mnemo-agent[dev,s3]"
|
|
257
288
|
pytest tests/ -v
|
|
258
289
|
```
|
|
259
290
|
|
|
291
|
+
114 tests across `test_cli.py`, `test_remote.py`, and `test_server.py`.
|
|
292
|
+
|
|
260
293
|
---
|
|
261
294
|
|
|
262
295
|
## Roadmap
|
|
263
296
|
|
|
264
297
|
- [x] Push/pull sync to S3, R2, and local filesystem remotes
|
|
298
|
+
- [x] Write-time conflict detection with overwrite / keep-both / abort prompt
|
|
299
|
+
- [x] Full MCP 2024-11-05 protocol — JSON-RPC 2.0 + stdio transport (Claude Desktop / Cursor)
|
|
265
300
|
- [ ] Vector embeddings for semantic search (v2)
|
|
266
301
|
- [ ] Parquet export for analytics
|
|
267
302
|
- [ ] `mnemo audit` — fact provenance trace
|
|
268
303
|
- [ ] Web UI dashboard
|
|
269
|
-
- [ ] Native Ollama MCP client registration
|
|
270
304
|
|
|
271
305
|
---
|
|
272
306
|
|
|
@@ -277,13 +311,20 @@ pytest tests/ -v
|
|
|
277
311
|
mnemo init --agent job-prep
|
|
278
312
|
mnemo load --file tests/fixtures/job_prep_sample.json --agent job-prep
|
|
279
313
|
|
|
280
|
-
#
|
|
314
|
+
# Connect to Claude Desktop (add to claude_desktop_config.json, then restart)
|
|
315
|
+
mnemo serve --agent job-prep --stdio
|
|
316
|
+
|
|
317
|
+
# Or run as an HTTP server for other MCP clients
|
|
281
318
|
mnemo serve --agent job-prep --port 8080
|
|
282
319
|
|
|
283
320
|
# After a practice interview, add what you learned
|
|
284
321
|
mnemo add --fact "Lead with Supabase migration story at FAANG interviews" \
|
|
285
322
|
--agent job-prep --attribute interview_tip --confidence 0.9 --tag tip
|
|
286
323
|
|
|
324
|
+
# If you added a conflicting fact by mistake, retract it by ID prefix
|
|
325
|
+
mnemo show --agent job-prep --format plain # see IDs
|
|
326
|
+
mnemo retract a1b2c3d4 --agent job-prep
|
|
327
|
+
|
|
287
328
|
# Before next session, recall relevant context
|
|
288
329
|
mnemo recall "React Supabase full-stack" --agent job-prep
|
|
289
330
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mnemo-agent"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Local-first agent memory CLI — dump, diff, migrate & query across Mem0, Letta, and more"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -827,6 +827,7 @@ def cmd_edit(
|
|
|
827
827
|
|
|
828
828
|
|
|
829
829
|
@cli.command("add")
|
|
830
|
+
@click.option("--force", "force", is_flag=True, default=False, help="Skip conflict check and keep both facts (useful for scripts)")
|
|
830
831
|
@click.option("--fact", "-f", "fact_text", required=True, help="Free-text fact to store")
|
|
831
832
|
@AGENT_OPTION
|
|
832
833
|
@DIR_OPTION
|
|
@@ -844,8 +845,13 @@ def cmd_add(
|
|
|
844
845
|
confidence: float,
|
|
845
846
|
source: str,
|
|
846
847
|
tags: tuple[str, ...],
|
|
848
|
+
force: bool,
|
|
847
849
|
) -> None:
|
|
848
|
-
"""Add a fact to an agent's memory store.
|
|
850
|
+
"""Add a fact to an agent's memory store.
|
|
851
|
+
|
|
852
|
+
If an existing fact shares the same entity+attribute, you will be prompted
|
|
853
|
+
to overwrite it, keep both, or abort. Use --force to always keep both (for scripts).
|
|
854
|
+
"""
|
|
849
855
|
base = _resolve_base(mnemo_dir)
|
|
850
856
|
ag = _resolve_agent(agent)
|
|
851
857
|
require_agent(ag, base)
|
|
@@ -856,8 +862,42 @@ def cmd_add(
|
|
|
856
862
|
except FileNotFoundError:
|
|
857
863
|
dump = AgentDump(agent=ag)
|
|
858
864
|
|
|
865
|
+
resolved_entity = entity or ag
|
|
866
|
+
|
|
867
|
+
# ── Conflict detection ────────────────────────────────────────────────────
|
|
868
|
+
if not force:
|
|
869
|
+
conflicts = [
|
|
870
|
+
f for f in dump.facts
|
|
871
|
+
if f.entity.lower() == resolved_entity.lower()
|
|
872
|
+
and f.attribute.lower() == attribute.lower()
|
|
873
|
+
]
|
|
874
|
+
if conflicts:
|
|
875
|
+
console.print(
|
|
876
|
+
f"\n[yellow]⚠ Conflict[/] — {len(conflicts)} existing fact(s) for "
|
|
877
|
+
f"[bold]{resolved_entity}[/].[cyan]{attribute}[/]:\n"
|
|
878
|
+
)
|
|
879
|
+
for c in conflicts:
|
|
880
|
+
color = _conf_color(c.confidence)
|
|
881
|
+
console.print(
|
|
882
|
+
f" [dim]{c.id[:8]}[/] {c.value} "
|
|
883
|
+
f"[{color}](conf={c.confidence:.2f}, {c.timestamp.strftime('%Y-%m-%d')})[/]"
|
|
884
|
+
)
|
|
885
|
+
console.print()
|
|
886
|
+
choice = click.prompt(
|
|
887
|
+
" Choice",
|
|
888
|
+
type=click.Choice(["o", "k", "a"], case_sensitive=False),
|
|
889
|
+
default="k",
|
|
890
|
+
prompt_suffix=" — [o] overwrite [k] keep both [a] abort: ",
|
|
891
|
+
)
|
|
892
|
+
if choice == "a":
|
|
893
|
+
console.print("[dim]Aborted.[/]")
|
|
894
|
+
return
|
|
895
|
+
if choice == "o":
|
|
896
|
+
conflict_ids = {c.id for c in conflicts}
|
|
897
|
+
dump.facts = [f for f in dump.facts if f.id not in conflict_ids]
|
|
898
|
+
|
|
859
899
|
fact = Fact(
|
|
860
|
-
entity=
|
|
900
|
+
entity=resolved_entity,
|
|
861
901
|
attribute=attribute,
|
|
862
902
|
value=fact_text,
|
|
863
903
|
source=source, # type: ignore[arg-type]
|
|
@@ -881,12 +921,51 @@ def cmd_add(
|
|
|
881
921
|
@click.option("--agent", "-a", required=True)
|
|
882
922
|
@click.option("--port", "-p", default=8080, show_default=True)
|
|
883
923
|
@click.option("--read-only", is_flag=True, help="Disable write endpoints")
|
|
924
|
+
@click.option(
|
|
925
|
+
"--stdio",
|
|
926
|
+
"use_stdio",
|
|
927
|
+
is_flag=True,
|
|
928
|
+
help="Run in stdio mode (for Claude Desktop / Cursor MCP integration)",
|
|
929
|
+
)
|
|
884
930
|
@DIR_OPTION
|
|
885
|
-
def cmd_serve(agent: str, port: int, read_only: bool, mnemo_dir: Path | None) -> None:
|
|
886
|
-
"""Start the MCP
|
|
931
|
+
def cmd_serve(agent: str, port: int, read_only: bool, use_stdio: bool, mnemo_dir: Path | None) -> None:
|
|
932
|
+
"""Start the MCP server for an agent.
|
|
933
|
+
|
|
934
|
+
\b
|
|
935
|
+
HTTP mode (default) — REST + JSON-RPC 2.0 at POST /:
|
|
936
|
+
mnemo serve --agent job-prep --port 8080
|
|
937
|
+
|
|
938
|
+
\b
|
|
939
|
+
stdio mode — for Claude Desktop / Cursor integration:
|
|
940
|
+
mnemo serve --agent job-prep --stdio
|
|
941
|
+
|
|
942
|
+
\b
|
|
943
|
+
Claude Desktop config (~/.claude/claude_desktop_config.json):
|
|
944
|
+
{
|
|
945
|
+
"mcpServers": {
|
|
946
|
+
"mnemo-job-prep": {
|
|
947
|
+
"command": "mnemo",
|
|
948
|
+
"args": ["serve", "--agent", "job-prep", "--stdio"]
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
"""
|
|
887
953
|
base = _resolve_base(mnemo_dir)
|
|
888
954
|
require_agent(agent, base)
|
|
889
955
|
|
|
956
|
+
if use_stdio:
|
|
957
|
+
# stdio transport — used by Claude Desktop, Cursor, etc.
|
|
958
|
+
# Print nothing to stdout (it's the JSON-RPC channel); use stderr for status.
|
|
959
|
+
import sys
|
|
960
|
+
print(
|
|
961
|
+
f"mnemo MCP stdio — agent={agent} read_only={read_only}",
|
|
962
|
+
file=sys.stderr,
|
|
963
|
+
)
|
|
964
|
+
from mnemo.stdio_server import run_stdio
|
|
965
|
+
run_stdio(agent=agent, base=base, read_only=read_only)
|
|
966
|
+
return
|
|
967
|
+
|
|
968
|
+
# HTTP transport
|
|
890
969
|
try:
|
|
891
970
|
import uvicorn # type: ignore
|
|
892
971
|
except ImportError:
|
|
@@ -896,13 +975,29 @@ def cmd_serve(agent: str, port: int, read_only: bool, mnemo_dir: Path | None) ->
|
|
|
896
975
|
|
|
897
976
|
app = create_app(agent=agent, base=base, read_only=read_only)
|
|
898
977
|
|
|
978
|
+
import json as _json
|
|
979
|
+
desktop_cfg = _json.dumps(
|
|
980
|
+
{
|
|
981
|
+
"mcpServers": {
|
|
982
|
+
f"mnemo-{agent}": {
|
|
983
|
+
"command": "mnemo",
|
|
984
|
+
"args": ["serve", "--agent", agent, "--stdio"],
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
},
|
|
988
|
+
indent=2,
|
|
989
|
+
)
|
|
990
|
+
|
|
899
991
|
console.print(
|
|
900
992
|
Panel.fit(
|
|
901
993
|
f"[bold cyan]Agent:[/] {agent}\n"
|
|
902
994
|
f"[bold cyan]Port:[/] {port}\n"
|
|
903
995
|
f"[bold cyan]Read-only:[/] {read_only}\n\n"
|
|
904
|
-
f"[dim]
|
|
905
|
-
f"[dim]
|
|
996
|
+
f"[dim]JSON-RPC 2.0: POST http://localhost:{port}/[/]\n"
|
|
997
|
+
f"[dim]Tools list: GET http://localhost:{port}/mcp/list_tools[/]\n"
|
|
998
|
+
f"[dim]Docs: http://localhost:{port}/docs[/]\n\n"
|
|
999
|
+
f"[bold]Claude Desktop config[/] [dim](~/.claude/claude_desktop_config.json)[/]:\n"
|
|
1000
|
+
f"[dim]{desktop_cfg}[/]",
|
|
906
1001
|
title="🌐 mnemo serve",
|
|
907
1002
|
border_style="green",
|
|
908
1003
|
)
|