mem-mcp 1.3.4 → 1.3.6
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/PLAN.md +2 -2
- package/README.md +7 -7
- package/index.js +66 -28
- package/package.json +1 -1
package/PLAN.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Memory MCP Wrapper — Plan & Status
|
|
2
2
|
|
|
3
3
|
## Goal
|
|
4
|
-
Build and publish `
|
|
4
|
+
Build and publish `mem-mcp` npm package following `vibe-token-mcp` pattern.
|
|
5
5
|
|
|
6
6
|
## Status: ✅ BUILT & TESTED
|
|
7
7
|
|
|
@@ -20,7 +20,7 @@ Build and publish `memory-agent-mcp` npm package following `vibe-token-mcp` patt
|
|
|
20
20
|
- [ ] Test search tool (free tier + paid)
|
|
21
21
|
- [ ] Test subscribe tool (x402 payment)
|
|
22
22
|
- [ ] Fix sample tool to handle existing write_token
|
|
23
|
-
- [x] Publish to npm as `
|
|
23
|
+
- [x] Publish to npm as `mem-mcp` (v1.0.1)
|
|
24
24
|
- [ ] Add to x402-list MCP registry
|
|
25
25
|
- [ ] Create README for npm page
|
|
26
26
|
- [x] Test end-to-end (health + sample passed)
|
package/README.md
CHANGED
|
@@ -16,22 +16,22 @@ MCP wrapper for [Memory01](https://memory.node01.org) — agentic memory for AI
|
|
|
16
16
|
|
|
17
17
|
MCP clients do not auto-update servers. To always use the latest version:
|
|
18
18
|
|
|
19
|
-
- **Recommended config**: use `npx -y
|
|
20
|
-
- **Global install**: run `npm install -g
|
|
19
|
+
- **Recommended config**: use `npx -y mem-mcp@latest` in your MCP config. npx checks the registry on each launch (cached, fast).
|
|
20
|
+
- **Global install**: run `npm install -g mem-mcp@latest` periodically, or `npm update -g mem-mcp`. Use the `memory-mcp` binary in your MCP config for offline startup.
|
|
21
21
|
- The server prints a note on startup if a newer version is available.
|
|
22
22
|
|
|
23
23
|
## One-command setup
|
|
24
24
|
|
|
25
25
|
After installing, tell your agent:
|
|
26
26
|
|
|
27
|
-
> Install `
|
|
27
|
+
> Install `mem-mcp` and call the `init` tool with your agentId. It will set everything up and explain the rest.
|
|
28
28
|
|
|
29
29
|
The `init` tool creates the token, saves credentials to `~/.memory01_token` / `~/.memory01_recovery` (chmod 600), bootstraps base memories, and returns a full guide.
|
|
30
30
|
|
|
31
31
|
## Installation
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
npm install -g
|
|
34
|
+
npm install -g mem-mcp
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
## Configuration
|
|
@@ -106,7 +106,7 @@ Add to your `opencode.json`:
|
|
|
106
106
|
"mcp": {
|
|
107
107
|
"memory": {
|
|
108
108
|
"type": "local",
|
|
109
|
-
"command": ["npx", "-y", "
|
|
109
|
+
"command": ["npx", "-y", "mem-mcp@latest"],
|
|
110
110
|
"environment": {
|
|
111
111
|
"MEMORY_PRIVATE_KEY": "0x..."
|
|
112
112
|
}
|
|
@@ -115,8 +115,8 @@ Add to your `opencode.json`:
|
|
|
115
115
|
}
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
Note: the binary is `memory-mcp` (not `
|
|
119
|
-
installed, `npx -y
|
|
118
|
+
Note: the binary is `memory-mcp` (not `mem-mcp`). Use `memory-mcp` if globally
|
|
119
|
+
installed, `npx -y mem-mcp@latest` otherwise. MEMORY_PRIVATE_KEY is optional —
|
|
120
120
|
the free tier (store + 30 searches/day + bootstrap + get) works without it.
|
|
121
121
|
```
|
|
122
122
|
|
package/index.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* - sample() -> Free sample (store + search demo)
|
|
16
16
|
*
|
|
17
17
|
* Usage:
|
|
18
|
-
* npx
|
|
18
|
+
* npx mem-mcp
|
|
19
19
|
* or: node index.js
|
|
20
20
|
*
|
|
21
21
|
* Configure with environment variables (all optional):
|
|
@@ -45,7 +45,7 @@ import fs from "node:fs";
|
|
|
45
45
|
|
|
46
46
|
// ============================= Config =============================
|
|
47
47
|
const MEMORY_BASE_URL = process.env.MEMORY_BASE_URL || "https://memory.node01.org";
|
|
48
|
-
const CLIENT_VERSION = "1.3.
|
|
48
|
+
const CLIENT_VERSION = "1.3.6";
|
|
49
49
|
const MEMORY_PRIVATE_KEY = process.env.MEMORY_PRIVATE_KEY;
|
|
50
50
|
|
|
51
51
|
|
|
@@ -54,6 +54,18 @@ if (!HAS_WALLET) {
|
|
|
54
54
|
console.error("NOTE: No MEMORY_PRIVATE_KEY set. Free operations (store, health, stats, sample, 30 free searches/day) will work. Paid operations (search after free tier, subscribe) will require a wallet.");
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// ============================= Credential File Helper =============================
|
|
58
|
+
function readTokenFile() {
|
|
59
|
+
try {
|
|
60
|
+
const home = os.homedir();
|
|
61
|
+
const p = path.join(home, ".memory01_token");
|
|
62
|
+
if (fs.existsSync(p)) {
|
|
63
|
+
return fs.readFileSync(p, "utf8").trim();
|
|
64
|
+
}
|
|
65
|
+
} catch (e) {}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
57
69
|
let account = null;
|
|
58
70
|
if (HAS_WALLET) {
|
|
59
71
|
const privateKey = MEMORY_PRIVATE_KEY.startsWith("0x") ? MEMORY_PRIVATE_KEY : `0x${MEMORY_PRIVATE_KEY}`;
|
|
@@ -171,19 +183,32 @@ async function payAndRetry(endpoint, body, priceUsd = "0.01") {
|
|
|
171
183
|
}
|
|
172
184
|
|
|
173
185
|
// ============================= Free API Calls =============================
|
|
174
|
-
async function callFree(endpoint, method = "GET", body = null) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
186
|
+
async function callFree(endpoint, method = "GET", body = null, retries = 1) {
|
|
187
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
188
|
+
const opts = { method, headers: { "Accept": "application/json" } };
|
|
189
|
+
if (body) {
|
|
190
|
+
opts.headers["Content-Type"] = "application/json";
|
|
191
|
+
opts.body = JSON.stringify(body);
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const response = await fetch(`${MEMORY_BASE_URL}${endpoint}`, opts);
|
|
195
|
+
const text = await response.text();
|
|
196
|
+
let data;
|
|
197
|
+
try { data = JSON.parse(text); } catch (e) {
|
|
198
|
+
if (attempt < retries) { await new Promise(r => setTimeout(r, 500)); continue; }
|
|
199
|
+
throw new Error(`Non-JSON response from ${endpoint}: ${text.substring(0, 200)}`);
|
|
200
|
+
}
|
|
201
|
+
return { data, status: response.status };
|
|
202
|
+
} catch (e) {
|
|
203
|
+
if (attempt < retries) { await new Promise(r => setTimeout(r, 500)); continue; }
|
|
204
|
+
throw e;
|
|
205
|
+
}
|
|
179
206
|
}
|
|
180
|
-
const response = await fetch(`${MEMORY_BASE_URL}${endpoint}`, opts);
|
|
181
|
-
return { data: await response.json(), status: response.status };
|
|
182
207
|
}
|
|
183
208
|
|
|
184
209
|
// ============================= MCP Server =============================
|
|
185
210
|
const server = new Server(
|
|
186
|
-
{ name: "
|
|
211
|
+
{ name: "mem-mcp", version: "1.3.5" },
|
|
187
212
|
{ capabilities: { tools: {} } }
|
|
188
213
|
);
|
|
189
214
|
|
|
@@ -330,10 +355,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
330
355
|
try {
|
|
331
356
|
switch (name) {
|
|
332
357
|
case "store": {
|
|
333
|
-
|
|
334
|
-
if (!
|
|
335
|
-
|
|
358
|
+
let { agentId, key, value, writeToken, sessionId, metadata, base } = args;
|
|
359
|
+
if (!writeToken) writeToken = readTokenFile();
|
|
360
|
+
if (!agentId && !writeToken) {
|
|
361
|
+
throw new McpError(ErrorCode.InvalidParams, "agentId is required on first store (no writeToken found). Pass agentId or set ~/.memory01_token.");
|
|
362
|
+
}
|
|
363
|
+
if (!key || !value) {
|
|
364
|
+
throw new McpError(ErrorCode.InvalidParams, "key and value are required");
|
|
336
365
|
}
|
|
366
|
+
if (!agentId) agentId = "agent";
|
|
337
367
|
if (key.length > 256) throw new McpError(ErrorCode.InvalidParams, "key max 256 chars");
|
|
338
368
|
const valueLimit = (args.base ? 2048 : 51200);
|
|
339
369
|
if (value.length > valueLimit) throw new McpError(ErrorCode.InvalidParams, `value max ${args.base ? '2KB (base)' : '50KB'}`);
|
|
@@ -369,10 +399,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
369
399
|
}
|
|
370
400
|
|
|
371
401
|
case "search": {
|
|
372
|
-
|
|
373
|
-
if (!
|
|
374
|
-
|
|
402
|
+
let { agentId, query, writeToken, topK = 10, sessionId, cursor, includeBase } = args;
|
|
403
|
+
if (!writeToken) writeToken = readTokenFile();
|
|
404
|
+
if (!writeToken) {
|
|
405
|
+
throw new McpError(ErrorCode.InvalidParams, "writeToken is required (or set ~/.memory01_token).");
|
|
375
406
|
}
|
|
407
|
+
if (!agentId) agentId = "agent";
|
|
376
408
|
if (query && query.length > 500) throw new McpError(ErrorCode.InvalidParams, "query max 500 chars");
|
|
377
409
|
|
|
378
410
|
const body = { agent_id: agentId, write_token: writeToken, top_k: topK, client_version: CLIENT_VERSION };
|
|
@@ -490,10 +522,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
490
522
|
}
|
|
491
523
|
|
|
492
524
|
case "bootstrap": {
|
|
493
|
-
|
|
494
|
-
if (!
|
|
495
|
-
|
|
525
|
+
let { agentId, writeToken, keys } = args;
|
|
526
|
+
if (!writeToken) writeToken = readTokenFile();
|
|
527
|
+
if (!writeToken) {
|
|
528
|
+
throw new McpError(ErrorCode.InvalidParams, "writeToken is required (or set ~/.memory01_token).");
|
|
496
529
|
}
|
|
530
|
+
if (!agentId) agentId = "agent";
|
|
497
531
|
const body = { agent_id: agentId, write_token: writeToken, client_version: CLIENT_VERSION };
|
|
498
532
|
if (keys) body.keys = keys;
|
|
499
533
|
const result = await callFree("/api/memory/bootstrap", "POST", body);
|
|
@@ -504,10 +538,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
504
538
|
}
|
|
505
539
|
|
|
506
540
|
case "get": {
|
|
507
|
-
|
|
508
|
-
if (!
|
|
509
|
-
|
|
541
|
+
let { agentId, writeToken, key } = args;
|
|
542
|
+
if (!writeToken) writeToken = readTokenFile();
|
|
543
|
+
if (!writeToken || !key) {
|
|
544
|
+
throw new McpError(ErrorCode.InvalidParams, "writeToken and key are required");
|
|
510
545
|
}
|
|
546
|
+
if (!agentId) agentId = "agent";
|
|
511
547
|
const result = await callFree("/api/memory/get", "POST", { agent_id: agentId, write_token: writeToken, key, client_version: CLIENT_VERSION });
|
|
512
548
|
if (result.status >= 400) {
|
|
513
549
|
throw new McpError(ErrorCode.InternalError, `API error: ${JSON.stringify(result.data)}`);
|
|
@@ -516,7 +552,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
516
552
|
}
|
|
517
553
|
|
|
518
554
|
case "init": {
|
|
519
|
-
|
|
555
|
+
let { agentId, writeToken: providedToken, key = "init", value = "Memory01 initialized." } = args;
|
|
556
|
+
if (!providedToken) providedToken = readTokenFile();
|
|
520
557
|
if (!agentId) {
|
|
521
558
|
throw new McpError(ErrorCode.InvalidParams, "agentId is required");
|
|
522
559
|
}
|
|
@@ -646,7 +683,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
646
683
|
}
|
|
647
684
|
|
|
648
685
|
case "regenerate_recovery": {
|
|
649
|
-
|
|
686
|
+
let { writeToken } = args;
|
|
687
|
+
if (!writeToken) writeToken = readTokenFile();
|
|
650
688
|
if (!writeToken) {
|
|
651
689
|
throw new McpError(ErrorCode.InvalidParams, "writeToken is required");
|
|
652
690
|
}
|
|
@@ -672,14 +710,14 @@ async function checkLatestVersion() {
|
|
|
672
710
|
try {
|
|
673
711
|
const controller = new AbortController();
|
|
674
712
|
const timer = setTimeout(() => controller.abort(), 3000);
|
|
675
|
-
const res = await fetch("https://registry.npmjs.org/
|
|
713
|
+
const res = await fetch("https://registry.npmjs.org/mem-mcp/latest", { signal: controller.signal });
|
|
676
714
|
clearTimeout(timer);
|
|
677
715
|
if (!res.ok) return;
|
|
678
716
|
const data = await res.json();
|
|
679
717
|
const latest = data.version;
|
|
680
|
-
const current = "1.3.
|
|
718
|
+
const current = "1.3.5";
|
|
681
719
|
if (latest && latest !== current) {
|
|
682
|
-
console.error(`NOTE:
|
|
720
|
+
console.error(`NOTE: mem-mcp ${current} is installed; latest is ${latest}. Run 'npm install -g memory-agent-mcp@latest' to update.`);
|
|
683
721
|
}
|
|
684
722
|
} catch (e) {
|
|
685
723
|
// best-effort, ignore
|
|
@@ -690,7 +728,7 @@ async function main() {
|
|
|
690
728
|
checkLatestVersion(); // best-effort, non-blocking
|
|
691
729
|
const transport = new StdioServerTransport();
|
|
692
730
|
await server.connect(transport);
|
|
693
|
-
console.error("
|
|
731
|
+
console.error("mem-mcp running on stdio");
|
|
694
732
|
}
|
|
695
733
|
|
|
696
734
|
main().catch((err) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mem-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"description": "MCP wrapper for Memory01 agentic memory service - persistent memory for AI agents, free to store and search. Base memories, recovery codes, upsert, 50+ languages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|