mem-mcp 1.3.5 → 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 (2) hide show
  1. package/index.js +62 -24
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -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.5";
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: "mem-mcp", version: "1.3.4" },
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
  }
@@ -677,7 +715,7 @@ async function checkLatestVersion() {
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
720
  console.error(`NOTE: mem-mcp ${current} is installed; latest is ${latest}. Run 'npm install -g memory-agent-mcp@latest' to update.`);
683
721
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mem-mcp",
3
- "version": "1.3.5",
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",