memory-agent-mcp 1.2.1 → 1.3.0
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/README.md +11 -0
- package/index.js +121 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,6 +12,14 @@ MCP wrapper for [Memory01](https://memory.node01.org) — agentic memory for AI
|
|
|
12
12
|
- **Subscribe**: Subscription plans (Starter $2/500, Pro $9/mo, Enterprise $20/mo)
|
|
13
13
|
- **Health / Stats / Sample**: Free utilities
|
|
14
14
|
|
|
15
|
+
## One-command setup
|
|
16
|
+
|
|
17
|
+
After installing, tell your agent:
|
|
18
|
+
|
|
19
|
+
> Install `memory-agent-mcp` and call the `init` tool with your agentId. It will set everything up and explain the rest.
|
|
20
|
+
|
|
21
|
+
The `init` tool creates the token, saves credentials to `~/.memory01_token` / `~/.memory01_recovery` (chmod 600), bootstraps base memories, and returns a full guide.
|
|
22
|
+
|
|
15
23
|
## Installation
|
|
16
24
|
|
|
17
25
|
```bash
|
|
@@ -87,6 +95,9 @@ Add to your `opencode.json`:
|
|
|
87
95
|
|
|
88
96
|
## Tools
|
|
89
97
|
|
|
98
|
+
### init
|
|
99
|
+
Initialize Memory01 in one call: creates token, saves credentials to standard files (chmod 600), bootstraps base memories, stores credentials-location pointer. Returns full guide. Call once per agent.
|
|
100
|
+
|
|
90
101
|
### store
|
|
91
102
|
Store a memory (free). First call returns a write_token and recovery_code — save both! All future operations require the write_token. Re-storing with the same key updates in place (upsert). Supports `base: true` for small (2KB) contextual memories.
|
|
92
103
|
|
package/index.js
CHANGED
|
@@ -39,6 +39,9 @@ import {
|
|
|
39
39
|
import { createWalletClient, http, parseEther } from "viem";
|
|
40
40
|
import { privateKeyToAccount } from "viem/accounts";
|
|
41
41
|
import { base } from "viem/chains";
|
|
42
|
+
import os from "node:os";
|
|
43
|
+
import path from "node:path";
|
|
44
|
+
import fs from "node:fs";
|
|
42
45
|
|
|
43
46
|
// ============================= Config =============================
|
|
44
47
|
const MEMORY_BASE_URL = process.env.MEMORY_BASE_URL || "https://memory.node01.org";
|
|
@@ -274,6 +277,25 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
274
277
|
required: ["agentId", "writeToken", "key"],
|
|
275
278
|
},
|
|
276
279
|
},
|
|
280
|
+
{
|
|
281
|
+
name: "init",
|
|
282
|
+
description: "Initialize Memory01 for this agent in one call: creates a write_token (first store), saves token+recovery_code to standard files (~/.memory01_token, ~/.memory01_recovery, chmod 600), bootstraps conventional base memories, and stores a credentials-location pointer. Returns full guide. Call once per agent; idempotent-ish (if token exists, pass writeToken).",
|
|
283
|
+
inputSchema: {
|
|
284
|
+
type: "object",
|
|
285
|
+
properties: {
|
|
286
|
+
agentId: { type: "string", description: "Your agent identifier (required)" },
|
|
287
|
+
writeToken: { type: "string", description: "Existing write token (omit on first run)" },
|
|
288
|
+
key: { type: "string", description: "Optional first memory key (default: 'init')" },
|
|
289
|
+
value: { type: "string", description: "Optional first memory value" },
|
|
290
|
+
},
|
|
291
|
+
required: ["agentId"],
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "guide",
|
|
296
|
+
description: "Get a concise guide on how to use Memory01: init flow, base memories, recovery, upsert, limits. Call this first if unsure. Full guide: https://memory.node01.org/agents.md",
|
|
297
|
+
inputSchema: { type: "object", properties: {} },
|
|
298
|
+
},
|
|
277
299
|
{
|
|
278
300
|
name: "recover",
|
|
279
301
|
description: "Recover a write_token on a new IP using a recovery code (free). Use when your host's IP changed.",
|
|
@@ -489,6 +511,105 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
489
511
|
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
490
512
|
}
|
|
491
513
|
|
|
514
|
+
case "init": {
|
|
515
|
+
const { agentId, writeToken: providedToken, key = "init", value = "Memory01 initialized." } = args;
|
|
516
|
+
if (!agentId) {
|
|
517
|
+
throw new McpError(ErrorCode.InvalidParams, "agentId is required");
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const home = os.homedir();
|
|
521
|
+
const tokenFile = path.join(home, ".memory01_token");
|
|
522
|
+
const recoveryFile = path.join(home, ".memory01_recovery");
|
|
523
|
+
|
|
524
|
+
// Step 1: get or create token
|
|
525
|
+
let token = providedToken;
|
|
526
|
+
let recoveryCode = null;
|
|
527
|
+
let isNew = false;
|
|
528
|
+
let storeResult = null;
|
|
529
|
+
|
|
530
|
+
if (!token) {
|
|
531
|
+
const r = await callFree("/api/memory/store", "POST", { agent_id: agentId, key, value });
|
|
532
|
+
if (r.status === 403 && r.data && r.data.error === "token_required") {
|
|
533
|
+
throw new McpError(ErrorCode.InvalidParams, "A token already exists for this (IP, agent_id). Pass writeToken to init, or use recover if your IP changed.");
|
|
534
|
+
}
|
|
535
|
+
if (r.status >= 400) {
|
|
536
|
+
throw new McpError(ErrorCode.InternalError, `API error: ${JSON.stringify(r.data)}`);
|
|
537
|
+
}
|
|
538
|
+
token = r.data.write_token;
|
|
539
|
+
recoveryCode = r.data.recovery_code;
|
|
540
|
+
isNew = true;
|
|
541
|
+
storeResult = r.data;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// Step 2: write credential files (chmod 600)
|
|
545
|
+
const savedFiles = [];
|
|
546
|
+
if (isNew && token) {
|
|
547
|
+
try {
|
|
548
|
+
fs.writeFileSync(tokenFile, token + "\n", { mode: 0o600 });
|
|
549
|
+
savedFiles.push(tokenFile);
|
|
550
|
+
} catch (e) {
|
|
551
|
+
console.error("Could not write token file:", e);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (isNew && recoveryCode) {
|
|
555
|
+
try {
|
|
556
|
+
fs.writeFileSync(recoveryFile, recoveryCode + "\n", { mode: 0o600 });
|
|
557
|
+
savedFiles.push(recoveryFile);
|
|
558
|
+
} catch (e) {
|
|
559
|
+
console.error("Could not write recovery file:", e);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Step 3: bootstrap base memories (idempotent)
|
|
564
|
+
const bootstrapResult = await callFree("/api/memory/bootstrap", "POST", { agent_id: agentId, write_token: token });
|
|
565
|
+
|
|
566
|
+
// Step 4: upsert credentials-location base memory pointing to the files
|
|
567
|
+
const credValue = `Token at ${tokenFile}, recovery at ${recoveryFile} (chmod 600). Do not store secrets in memory.`;
|
|
568
|
+
await callFree("/api/memory/store", "POST", { agent_id: agentId, write_token: token, key: "credentials-location", value: credValue, base: true });
|
|
569
|
+
|
|
570
|
+
return {
|
|
571
|
+
content: [{
|
|
572
|
+
type: "text",
|
|
573
|
+
text: JSON.stringify({
|
|
574
|
+
ok: true,
|
|
575
|
+
new_token: isNew,
|
|
576
|
+
write_token: token,
|
|
577
|
+
recovery_code: recoveryCode,
|
|
578
|
+
credential_files: savedFiles,
|
|
579
|
+
bootstrap: bootstrapResult.data,
|
|
580
|
+
guide: {
|
|
581
|
+
init_done: "Memory01 initialized. Token and recovery code saved to standard files (chmod 600). Base memories bootstrapped. credentials-location base memory stored.",
|
|
582
|
+
next_steps: [
|
|
583
|
+
"Use store(key, value) to save memories. Re-store with same key to update (upsert).",
|
|
584
|
+
"Use search(query) for semantic search (free: 30/day). Use includeBase:true to load context at session start.",
|
|
585
|
+
"Recovery: if your IP changes, call recover(agentId, recoveryCode) from the new host.",
|
|
586
|
+
"Regenerate recovery code from original IP with regenerate_recovery(writeToken) if lost.",
|
|
587
|
+
"Full guide: https://memory.node01.org/agents.md",
|
|
588
|
+
],
|
|
589
|
+
standard_paths: { token: tokenFile, recovery: recoveryFile },
|
|
590
|
+
},
|
|
591
|
+
}, null, 2),
|
|
592
|
+
}],
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
case "guide": {
|
|
597
|
+
return {
|
|
598
|
+
content: [{
|
|
599
|
+
type: "text",
|
|
600
|
+
text: JSON.stringify({
|
|
601
|
+
init: "1) store a memory with agentId+key+value (omit writeToken on first call). 2) Save write_token AND recovery_code to ~/.memory01_token and ~/.memory01_recovery (chmod 600). 3) Store a base memory key='credentials-location' pointing to those files. 4) Use bootstrap to create conventional base memories.",
|
|
602
|
+
tools: ["store", "search", "bootstrap", "get", "recover", "regenerate_recovery", "subscribe", "health", "stats", "sample", "guide"],
|
|
603
|
+
base_memories: "Small (max 2KB) contextual memories. Excluded from normal search by default. Use includeBase:true to load them (e.g. at session start). Conventional keys: credentials-location (sensitive), user-preferences, user-details, code-style.",
|
|
604
|
+
recovery: "Token bound to (IP, agent_id). If IP changes, use recover(agentId, recoveryCode) to get a new token. Regenerate recovery code from original IP if lost. Save recovery_code offline.",
|
|
605
|
+
upsert: "Re-store with the same key updates in place (no duplicates). updated_at refreshed, stored_at preserved.",
|
|
606
|
+
limits: "key max 256, value max 50KB (2KB for base), metadata max 2KB, session_id max 128, top_k 1-20. Free: 30 searches/day, then $0.01 USDC.",
|
|
607
|
+
full_guide: "https://memory.node01.org/agents.md",
|
|
608
|
+
}, null, 2),
|
|
609
|
+
}],
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
|
|
492
613
|
case "recover": {
|
|
493
614
|
const { agentId, recoveryCode } = args;
|
|
494
615
|
if (!agentId || !recoveryCode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memory-agent-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
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",
|