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.
Files changed (4) hide show
  1. package/PLAN.md +2 -2
  2. package/README.md +7 -7
  3. package/index.js +66 -28
  4. 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 `memory-agent-mcp` npm package following `vibe-token-mcp` pattern.
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 `memory-agent-mcp` (v1.0.1)
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 memory-agent-mcp@latest` in your MCP config. npx checks the registry on each launch (cached, fast).
20
- - **Global install**: run `npm install -g memory-agent-mcp@latest` periodically, or `npm update -g memory-agent-mcp`. Use the `memory-mcp` binary in your MCP config for offline startup.
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 `memory-agent-mcp` and call the `init` tool with your agentId. It will set everything up and explain the rest.
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 memory-agent-mcp
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", "memory-agent-mcp@latest"],
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 `memory-agent-mcp`). Use `memory-mcp` if globally
119
- installed, `npx -y memory-agent-mcp@latest` otherwise. MEMORY_PRIVATE_KEY is optional —
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 memory-agent-mcp
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.4";
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
- const opts = { method, headers: { "Accept": "application/json" } };
176
- if (body) {
177
- opts.headers["Content-Type"] = "application/json";
178
- opts.body = JSON.stringify(body);
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: "memory-agent-mcp", version: "1.0.0" },
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
- const { agentId, key, value, writeToken, sessionId, metadata, base } = args;
334
- if (!agentId || !key || !value) {
335
- throw new McpError(ErrorCode.InvalidParams, "agentId, key, and value are required");
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
- const { agentId, query, writeToken, topK = 10, sessionId, cursor, includeBase } = args;
373
- if (!agentId || !writeToken) {
374
- throw new McpError(ErrorCode.InvalidParams, "agentId and writeToken are required");
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
- const { agentId, writeToken, keys } = args;
494
- if (!agentId || !writeToken) {
495
- throw new McpError(ErrorCode.InvalidParams, "agentId and writeToken are required");
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
- const { agentId, writeToken, key } = args;
508
- if (!agentId || !writeToken || !key) {
509
- throw new McpError(ErrorCode.InvalidParams, "agentId, writeToken, and key are required");
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
- const { agentId, writeToken: providedToken, key = "init", value = "Memory01 initialized." } = args;
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
- const { writeToken } = args;
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/memory-agent-mcp/latest", { signal: controller.signal });
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.1";
718
+ const current = "1.3.5";
681
719
  if (latest && latest !== current) {
682
- console.error(`NOTE: memory-agent-mcp ${current} is installed; latest is ${latest}. Run 'npm install -g memory-agent-mcp@latest' to update.`);
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("memory-agent-mcp running on stdio");
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.4",
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",