memoryai-mcp 2.2.0 → 2.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.
Files changed (2) hide show
  1. package/dist/index.js +240 -71
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -8,13 +8,13 @@
8
8
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
10
  import { z } from "zod";
11
- const API_URL = process.env.HM_ENDPOINT || "http://localhost:8420";
12
- const API_KEY = process.env.HM_API_KEY || "";
11
+ const API_URL = process.env.MEMORYAI_ENDPOINT || process.env.HM_ENDPOINT || "http://localhost:8420";
12
+ const API_KEY = process.env.MEMORYAI_API_KEY || process.env.HM_API_KEY || "";
13
13
  const REQUEST_TIMEOUT_MS = 30_000; // P2 #6: 30s default timeout for API requests
14
- // Context Guard — per-IDE settings via env vars
15
- const CG_CONTEXT_CAP = parseInt(process.env.HM_CONTEXT_CAP || "0", 10); // IDE's context window (0 = let server detect)
16
- const CG_COMPACT_PCT = parseInt(process.env.HM_COMPACT_AT || "0", 10); // % to warn (e.g. 30 = 30%)
17
- const CG_CRITICAL_PCT = parseInt(process.env.HM_CRITICAL_AT || "0", 10); // % to force compact (e.g. 50 = 50%)
14
+ // Context Guard — per-IDE settings via env vars (MEMORYAI_ preferred, HM_ backward compat)
15
+ const CG_CONTEXT_CAP = parseInt(process.env.MEMORYAI_CONTEXT_CAP || process.env.HM_CONTEXT_CAP || "0", 10);
16
+ const CG_COMPACT_PCT = parseInt(process.env.MEMORYAI_COMPACT_AT || process.env.HM_COMPACT_AT || "0", 10);
17
+ const CG_CRITICAL_PCT = parseInt(process.env.MEMORYAI_CRITICAL_AT || process.env.HM_CRITICAL_AT || "0", 10);
18
18
  // --- HTTP helper ---
19
19
  async function api(method, path, body) {
20
20
  const resp = await fetch(`${API_URL}${path}`, {
@@ -40,9 +40,9 @@ function err(e) {
40
40
  return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
41
41
  }
42
42
  // --- MCP Server ---
43
- const server = new McpServer({ name: "memoryai", version: "1.0.0" }, { capabilities: { tools: {} } });
43
+ const server = new McpServer({ name: "memoryai", version: "2.3.0" }, { capabilities: { tools: {} } });
44
44
  // 1. memory_store
45
- server.tool("memory_store", "Store information in persistent memory. Use when you learn something important — project context, user preferences, architectural decisions, patterns, bugs, pricing/cost discussions, business plans, financial calculations, credit/billing info, revenue models, partnership details, or ANY information the user might ask about later. When in doubt, STORE — MemoryAI handles dedup automatically, so storing too much is always better than forgetting.", {
45
+ server.tool("memory_store", "[CORE] Store information in persistent memory. Use when you learn something important — project context, user preferences, architectural decisions, patterns, bugs, pricing/cost discussions, business plans, or ANY information the user might ask about later. When in doubt, STORE — dedup is automatic.", {
46
46
  content: z.string().describe("What to remember"),
47
47
  source: z.string().optional().describe("Source context (e.g. file path, conversation)"),
48
48
  tags: z.array(z.string()).optional().describe("Categories: preferences, architecture, bugs, patterns, decisions"),
@@ -87,7 +87,7 @@ server.tool("memory_store", "Store information in persistent memory. Use when yo
87
87
  }
88
88
  });
89
89
  // 2. memory_recall
90
- server.tool("memory_recall", "Search persistent memory for relevant context. Use before starting work to check what you already know about the project or task.", {
90
+ server.tool("memory_recall", "[CORE] Search persistent memory for relevant context. Use BEFORE starting work to check what you already know about the project, user preferences, or past decisions.", {
91
91
  query: z.string().describe("What to search for"),
92
92
  depth: z.enum(["fast", "instant", "deep", "exhaustive"]).optional().describe("Search depth. 'instant'=vector only (~50ms), 'fast'=FTS only, 'deep'=full fusion (default), 'exhaustive'=deep+more results"),
93
93
  limit: z.number().optional().describe("Max results (default: 5)"),
@@ -129,7 +129,7 @@ server.tool("memory_recall", "Search persistent memory for relevant context. Use
129
129
  }
130
130
  });
131
131
  // 3. memory_stats
132
- server.tool("memory_stats", "Get memory usage statistics — chunk count, storage size, monthly usage.", {}, async () => {
132
+ server.tool("memory_stats", "Advanced: Get memory usage statistics — chunk count, storage size, monthly usage.", {}, async () => {
133
133
  try {
134
134
  const r = (await api("GET", "/v1/stats"));
135
135
  return ok(`Memory Stats:\n` +
@@ -143,7 +143,7 @@ server.tool("memory_stats", "Get memory usage statistics — chunk count, storag
143
143
  }
144
144
  });
145
145
  // 4. memory_compact
146
- server.tool("memory_compact", "Compact long text into memory chunks for long-term storage. Use at end of session or when context is getting large.", {
146
+ server.tool("memory_compact", "Advanced: Compact long text into memory chunks for long-term storage. Use at end of session or when context is getting large.", {
147
147
  content: z.string().describe("Text content to compact"),
148
148
  task_context: z.string().optional().describe("Brief description of the task/session"),
149
149
  content_type: z.enum(["conversation", "code"]).optional().describe("Content type"),
@@ -186,7 +186,7 @@ server.tool("memory_compact", "Compact long text into memory chunks for long-ter
186
186
  }
187
187
  });
188
188
  // 5. context_check
189
- server.tool("context_check", "Check current context token usage and urgency level.", {
189
+ server.tool("context_check", "Advanced: Check current context token usage and urgency level.", {
190
190
  content_type: z.enum(["conversation", "code"]).optional().describe("Check conversation or code context"),
191
191
  }, async (args) => {
192
192
  try {
@@ -203,7 +203,7 @@ server.tool("context_check", "Check current context token usage and urgency leve
203
203
  }
204
204
  });
205
205
  // 6. context_restore
206
- server.tool("context_restore", "Restore context for a task by recalling the most relevant memory chunks.", {
206
+ server.tool("context_restore", "Advanced: Restore context for a task by recalling the most relevant memory chunks.", {
207
207
  task_description: z.string().describe("Description of the task to restore context for"),
208
208
  limit: z.number().optional().describe("Max chunks to restore (default: 5)"),
209
209
  }, async (args) => {
@@ -224,7 +224,7 @@ server.tool("context_restore", "Restore context for a task by recalling the most
224
224
  }
225
225
  });
226
226
  // 7. project_index
227
- server.tool("project_index", "Index a code project's file tree and key files into memory. IDE use only.", {
227
+ server.tool("project_index", "Advanced: Index a code project's file tree and key files into memory. IDE use only.", {
228
228
  file_tree: z.array(z.string()).describe("List of file paths in the project"),
229
229
  key_files: z.record(z.string(), z.string()).optional().describe("Map of file_path → file_content for important files"),
230
230
  git_info: z.record(z.string(), z.unknown()).optional().describe("Git metadata (branch, remote, last commit)"),
@@ -251,7 +251,7 @@ server.tool("project_index", "Index a code project's file tree and key files int
251
251
  // 8. collective_contribute
252
252
  server.tool(
253
253
  "collective_contribute",
254
- "Contribute knowledge to the collective memory pool. Requires opt-in. Content is anonymized before storage. Use for sharing bug fixes, patterns, decisions that could help other developers.",
254
+ "Advanced: Contribute knowledge to the collective memory pool. Requires opt-in. Content is anonymized before storage. Use for sharing bug fixes, patterns, decisions that could help other developers.",
255
255
  {
256
256
  content: z.string().describe("Knowledge to contribute (will be anonymized)"),
257
257
  content_type: z.enum(["bug_fix", "pattern", "decision", "migration", "tip", "performance", "security"]).optional().describe("Type of knowledge (default: bug_fix)"),
@@ -281,7 +281,7 @@ server.tool(
281
281
  // 9. collective_recall
282
282
  server.tool(
283
283
  "collective_recall",
284
- "Search the collective knowledge pool for solutions, patterns, and tips from the developer community. Free for all users.",
284
+ "Advanced: Search the collective knowledge pool for solutions, patterns, and tips from the developer community. Free for all users.",
285
285
  {
286
286
  query: z.string().describe("What to search for"),
287
287
  depth: z.enum(["fast", "deep"]).optional().describe("Search depth (default: deep)"),
@@ -314,7 +314,7 @@ server.tool(
314
314
  // 10. collective_confirm
315
315
  server.tool(
316
316
  "collective_confirm",
317
- "Confirm whether a collective solution worked or not. Helps improve confidence scores.",
317
+ "Advanced: Confirm whether a collective solution worked or not. Helps improve confidence scores.",
318
318
  {
319
319
  collective_chunk_id: z.number().describe("ID of the collective chunk to confirm"),
320
320
  worked: z.boolean().describe("Did the solution work? true/false"),
@@ -337,7 +337,7 @@ server.tool(
337
337
  // 11. collective_stats
338
338
  server.tool(
339
339
  "collective_stats",
340
- "Get statistics about the collective knowledge pool.",
340
+ "Advanced: Get statistics about the collective knowledge pool.",
341
341
  {},
342
342
  async () => {
343
343
  try {
@@ -357,7 +357,7 @@ server.tool(
357
357
  );
358
358
  */
359
359
  // 12. l2_store
360
- server.tool("reasoning_store", "Store content in a reasoning bank. Reasoning banks hold context for deep analysis. Requires Pro plan or higher.", {
360
+ server.tool("reasoning_store", "Advanced: Store content in a reasoning bank. Reasoning banks hold context for deep analysis. Requires Pro plan or higher.", {
361
361
  bank_name: z.string().describe("Name of the L2 bank"),
362
362
  content: z.string().describe("Content to store in the bank"),
363
363
  token_count: z.number().optional().describe("Approximate token count of the content"),
@@ -375,7 +375,7 @@ server.tool("reasoning_store", "Store content in a reasoning bank. Reasoning ban
375
375
  }
376
376
  });
377
377
  // 13. l2_recall
378
- server.tool("reasoning_recall", "Recall from reasoning banks via deep analysis. Requires Pro plan or higher.", {
378
+ server.tool("reasoning_recall", "Advanced: Recall from reasoning banks via deep analysis. Requires Pro plan or higher.", {
379
379
  query: z.string().describe("Question to answer using L2 bank context"),
380
380
  bank_names: z.array(z.string()).optional().describe("Specific banks to search (default: all)"),
381
381
  }, async (args) => {
@@ -393,7 +393,7 @@ server.tool("reasoning_recall", "Recall from reasoning banks via deep analysis.
393
393
  }
394
394
  });
395
395
  // 14. l2_compress
396
- server.tool("reasoning_compress", "Compress old reasoning bank entries into a digest. Reduces storage while preserving key information.", {
396
+ server.tool("reasoning_compress", "Advanced: Compress old reasoning bank entries into a digest. Reduces storage while preserving key information.", {
397
397
  bank_name: z.string().describe("Name of the L2 bank to compress"),
398
398
  }, async (args) => {
399
399
  try {
@@ -409,7 +409,7 @@ server.tool("reasoning_compress", "Compress old reasoning bank entries into a di
409
409
  }
410
410
  });
411
411
  // 15. l2_stats
412
- server.tool("reasoning_stats", "Get reasoning layer statistics — bank sizes, usage, and plan limits.", {}, async () => {
412
+ server.tool("reasoning_stats", "Advanced: Get reasoning layer statistics — bank sizes, usage, and plan limits.", {}, async () => {
413
413
  try {
414
414
  const r = (await api("GET", "/v1/l2/stats"));
415
415
  const bankList = (r.banks || [])
@@ -425,7 +425,7 @@ server.tool("reasoning_stats", "Get reasoning layer statistics — bank sizes, u
425
425
  }
426
426
  });
427
427
  // 16. entity_list
428
- server.tool("entity_list", "List tracked entities (files, URLs, people, packages, code symbols) extracted from stored memories.", {
428
+ server.tool("entity_list", "Advanced: List tracked entities (files, URLs, people, packages, code symbols) extracted from stored memories.", {
429
429
  entity_type: z.string().optional().describe("Filter by type: file, url, person, package, code_symbol"),
430
430
  limit: z.number().optional().describe("Max results (default: 50)"),
431
431
  }, async (args) => {
@@ -449,7 +449,7 @@ server.tool("entity_list", "List tracked entities (files, URLs, people, packages
449
449
  }
450
450
  });
451
451
  // 17. entity_search
452
- server.tool("entity_search", "Find memory chunks linked to a specific entity by name.", {
452
+ server.tool("entity_search", "Advanced: Find memory chunks linked to a specific entity by name.", {
453
453
  name: z.string().describe("Entity name to search for"),
454
454
  limit: z.number().optional().describe("Max chunk IDs to return (default: 20)"),
455
455
  }, async (args) => {
@@ -465,7 +465,7 @@ server.tool("entity_search", "Find memory chunks linked to a specific entity by
465
465
  }
466
466
  });
467
467
  // 18. learn
468
- server.tool("learn", "Store an action, its result, and lesson learned. Use after completing tasks, fixing bugs, or making decisions to build action memory.", {
468
+ server.tool("learn", "Advanced: Store an action, its result, and lesson learned. Use after completing tasks, fixing bugs, or making decisions to build action memory.", {
469
469
  action: z.string().describe("What was done"),
470
470
  result: z.string().describe("What happened"),
471
471
  outcome: z.enum(["success", "failure", "partial"]).optional().describe("Outcome (default: success)"),
@@ -491,7 +491,7 @@ server.tool("learn", "Store an action, its result, and lesson learned. Use after
491
491
  // 12. collective_shards
492
492
  server.tool(
493
493
  "collective_shards",
494
- "List all domain shards in the collective knowledge pool with chunk counts.",
494
+ "Advanced: List all domain shards in the collective knowledge pool with chunk counts.",
495
495
  {},
496
496
  async () => {
497
497
  try {
@@ -508,7 +508,7 @@ server.tool(
508
508
  // 13. collective_synthesize
509
509
  server.tool(
510
510
  "collective_synthesize",
511
- "Trigger knowledge card synthesis from collective chunks. Groups similar chunks and creates merged knowledge cards. Admin operation.",
511
+ "Advanced: Trigger knowledge card synthesis from collective chunks. Groups similar chunks and creates merged knowledge cards. Admin operation.",
512
512
  {},
513
513
  async () => {
514
514
  try {
@@ -530,7 +530,7 @@ server.tool(
530
530
  // 14. pool_stats
531
531
  server.tool(
532
532
  "pool_stats",
533
- "Get content pool dedup statistics — pool size, ref count, dedup ratio, and estimated savings.",
533
+ "Advanced: Get content pool dedup statistics — pool size, ref count, dedup ratio, and estimated savings.",
534
534
  {},
535
535
  async () => {
536
536
  try {
@@ -549,7 +549,7 @@ server.tool(
549
549
  */
550
550
  // --- Start ---
551
551
  // 16. memory_recover
552
- server.tool("memory_recover", "Recover session context from recent memory. Use when resuming work after a break to quickly understand what was happening — active files, pending tasks, timeline, and key references.", {
552
+ server.tool("memory_recover", "Advanced: Recover session context from recent memory. Use when resuming work after a break to quickly understand what was happening — active files, pending tasks, timeline, and key references.", {
553
553
  task_context: z.string().optional().describe("Hint about what you were working on"),
554
554
  time_range_hours: z.number().optional().describe("Look back N hours (default: 24)"),
555
555
  max_tokens: z.number().optional().describe("Token budget for response (default: 8000)"),
@@ -579,7 +579,7 @@ server.tool("memory_recover", "Recover session context from recent memory. Use w
579
579
  }
580
580
  });
581
581
  // 17. memory_health
582
- server.tool("memory_health", "Check context window health — usage percentage, compaction recommendation, and memory freshness stats.", {
582
+ server.tool("memory_health", "Advanced: Check context window health — usage percentage, compaction recommendation, and memory freshness stats.", {
583
583
  current_tokens: z.number().describe("Current token count in context window"),
584
584
  max_tokens: z.number().optional().describe("Max context window size (default: 200000)"),
585
585
  }, async (args) => {
@@ -604,7 +604,7 @@ server.tool("memory_health", "Check context window health — usage percentage,
604
604
  }
605
605
  });
606
606
  // 18. memory_health_detailed
607
- server.tool("memory_health_detailed", "Get detailed memory health — chunk distribution, stale chunk count, entity stats, and actionable recommendations.", {}, async () => {
607
+ server.tool("memory_health_detailed", "Advanced: Get detailed memory health — chunk distribution, stale chunk count, entity stats, and actionable recommendations.", {}, async () => {
608
608
  try {
609
609
  const r = (await api("GET", "/v1/health/detailed"));
610
610
  const recs = (r.recommendations || []).map((rec) => ` ⚠ ${rec}`).join("\n");
@@ -622,7 +622,7 @@ server.tool("memory_health_detailed", "Get detailed memory health — chunk dist
622
622
  }
623
623
  });
624
624
  // 19. snapshot_create
625
- server.tool("snapshot_create", "Create a snapshot backup of all current memory chunks. Use before risky operations.", {}, async () => {
625
+ server.tool("snapshot_create", "Advanced: Create a snapshot backup of all current memory chunks. Use before risky operations.", {}, async () => {
626
626
  try {
627
627
  const r = (await api("POST", "/v1/snapshots/create"));
628
628
  return ok(`Snapshot created (id=${r.snapshot_id}): ${r.chunks_count} chunks, ${r.size_bytes} bytes`);
@@ -632,7 +632,7 @@ server.tool("snapshot_create", "Create a snapshot backup of all current memory c
632
632
  }
633
633
  });
634
634
  // 19. snapshot_list
635
- server.tool("snapshot_list", "List all available memory snapshots.", {}, async () => {
635
+ server.tool("snapshot_list", "Advanced: List all available memory snapshots.", {}, async () => {
636
636
  try {
637
637
  const r = (await api("GET", "/v1/snapshots"));
638
638
  if (!r.snapshots?.length)
@@ -647,7 +647,7 @@ server.tool("snapshot_list", "List all available memory snapshots.", {}, async (
647
647
  }
648
648
  });
649
649
  // 20. snapshot_restore
650
- server.tool("snapshot_restore", "Restore memory from a snapshot. Current chunks will be soft-deleted and replaced.", {
650
+ server.tool("snapshot_restore", "Advanced: Restore memory from a snapshot. Current chunks will be soft-deleted and replaced.", {
651
651
  snapshot_id: z.string().describe("Snapshot ID to restore from"),
652
652
  }, async (args) => {
653
653
  try {
@@ -659,7 +659,7 @@ server.tool("snapshot_restore", "Restore memory from a snapshot. Current chunks
659
659
  }
660
660
  });
661
661
  // 21. memory_bootstrap
662
- server.tool("memory_bootstrap", "Get a ready-to-use context block at session start. Automatically assembles preferences, recent activity, project context, and key entities. Call this at the beginning of every session instead of manual recalls.", {
662
+ server.tool("memory_bootstrap", "[CORE] Load context at session start — call this FIRST in every new session. Returns preferences, recent activity, project context, and key entities as a ready-to-use block.", {
663
663
  task_description: z.string().optional().describe("What you're about to work on"),
664
664
  project_name: z.string().optional().describe("Project name to focus on"),
665
665
  max_tokens: z.number().optional().describe("Token budget for context block (default: 4000)"),
@@ -685,7 +685,7 @@ server.tool("memory_bootstrap", "Get a ready-to-use context block at session sta
685
685
  }
686
686
  });
687
687
  // 22. memory_explore
688
- server.tool("memory_explore", "Explore memory connections — find chunks related to a specific memory. Reveals hidden connections and associations.", {
688
+ server.tool("memory_explore", "Advanced: Explore memory connections — find chunks related to a specific memory. Reveals hidden connections and associations.", {
689
689
  chunk_id: z.number().describe("ID of the memory chunk to explore from"),
690
690
  limit: z.number().optional().describe("Max neighbors to return (default: 10)"),
691
691
  }, async (args) => {
@@ -707,7 +707,7 @@ server.tool("memory_explore", "Explore memory connections — find chunks relate
707
707
  }
708
708
  });
709
709
  // 23. memory_clusters
710
- server.tool("memory_clusters", "View memory topic clusters — groups of related memories organized by topic. Useful for understanding what topics are stored.", {
710
+ server.tool("memory_clusters", "Advanced: View memory topic clusters — groups of related memories organized by topic. Useful for understanding what topics are stored.", {
711
711
  limit: z.number().optional().describe("Max clusters to return (default: 20)"),
712
712
  }, async (args) => {
713
713
  try {
@@ -724,7 +724,7 @@ server.tool("memory_clusters", "View memory topic clusters — groups of related
724
724
  }
725
725
  });
726
726
  // 24. session_handoff_start
727
- server.tool("session_handoff_start", "Start a session handoff — save old session conversation to MemoryAI server for new session to read. Use when context window is filling up and you need to switch sessions without losing context.", {
727
+ server.tool("session_handoff_start", "Advanced: Start a session handoff — save old session conversation to MemoryAI server for new session to read. Use when context window is filling up and you need to switch sessions without losing context.", {
728
728
  conversation: z.array(z.object({
729
729
  role: z.string().describe("Message role: user, assistant, system"),
730
730
  content: z.string().describe("Message content"),
@@ -744,7 +744,7 @@ server.tool("session_handoff_start", "Start a session handoff — save old sessi
744
744
  }
745
745
  });
746
746
  // 25. session_handoff_restore
747
- server.tool("session_handoff_restore", "Restore old session conversation + related MemoryAI memories for a new session. Call this at the start of a new session to pick up where the old session left off — zero context loss.", {
747
+ server.tool("session_handoff_restore", "Advanced: Restore old session conversation + related MemoryAI memories for a new session. Call this at the start of a new session to pick up where the old session left off — zero context loss.", {
748
748
  handoff_id: z.string().optional().describe("Specific handoff ID, or omit for latest"),
749
749
  include_memories: z.boolean().optional().describe("Also include related MemoryAI memories (default: true)"),
750
750
  memory_limit: z.number().optional().describe("Max related memories to include (default: 5)"),
@@ -775,7 +775,7 @@ server.tool("session_handoff_restore", "Restore old session conversation + relat
775
775
  }
776
776
  });
777
777
  // 26. session_handoff_complete
778
- server.tool("session_handoff_complete", "Complete a session handoff — archive old session conversation into long-term MemoryAI storage. Call this when the new session has enough context (e.g., after working for a while).", {
778
+ server.tool("session_handoff_complete", "Advanced: Complete a session handoff — archive old session conversation into long-term MemoryAI storage. Call this when the new session has enough context (e.g., after working for a while).", {
779
779
  handoff_id: z.string().optional().describe("Specific handoff ID, or omit for latest"),
780
780
  archive_to_memory: z.boolean().optional().describe("Store old conversation as MemoryAI chunks (default: true)"),
781
781
  }, async (args) => {
@@ -795,7 +795,7 @@ server.tool("session_handoff_complete", "Complete a session handoff — archive
795
795
  }
796
796
  });
797
797
  // 27. session_handoff_status
798
- server.tool("session_handoff_status", "Check current session handoff status — whether there's a pending handoff and its state.", {}, async () => {
798
+ server.tool("session_handoff_status", "Advanced: Check current session handoff status — whether there's a pending handoff and its state.", {}, async () => {
799
799
  try {
800
800
  const r = (await api("GET", "/v1/session/handoff/status"));
801
801
  if (!r.handoff_id)
@@ -816,7 +816,7 @@ server.tool("session_handoff_status", "Check current session handoff status —
816
816
  });
817
817
  // ─── Context Guard v6 Tools ─────────────────────────────────────────
818
818
  // context_guard_check — universal guard check with DNA count
819
- server.tool("context_guard_check", "Check context window health using Context Guard v6 dynamic thresholds, DNA memory count, bootstrap readiness. Replaces memory_health with richer data.", {
819
+ server.tool("context_guard_check", "[CORE] Check context pressurereturns recommendation (safe/compact_soon/compact_now). Call every ~15 messages to monitor context window health.", {
820
820
  estimated_tokens: z.number().describe("Current token count in context window"),
821
821
  max_tokens: z.number().optional().describe("Max context window size (uses HM_CONTEXT_CAP env if omitted)"),
822
822
  model: z.string().optional().describe("Model name for auto-detecting context window size (e.g. claude-sonnet-4-6)"),
@@ -853,7 +853,7 @@ server.tool("context_guard_check", "Check context window health using Context Gu
853
853
  }
854
854
  });
855
855
  // context_guard_compact — compact with DNA protection
856
- server.tool("context_guard_compact", "Compact session context with DNA protection DNA memories are never overwritten. IMPORTANT: Send a REAL summary of the conversation (>500 chars) including topics discussed, decisions made, key numbers/facts, and current status. Do NOT send just a status string like 'context guard - 132%'. If you send useless content, the server will use its internal buffer as fallback, but a good summary from you produces better memories.", {
856
+ server.tool("context_guard_compact", "[CORE] Save context to long-term memory when context_guard_check says 'compact_now'. Send a REAL summary (>500 chars) of topics discussed, decisions made, key facts, and current status. DNA memories are never overwritten.", {
857
857
  content: z.string().describe("Conversation summary — include topics, decisions, key facts, numbers. Must be >500 chars of real content."),
858
858
  task_context: z.string().optional().describe("Task description for tagging"),
859
859
  blocking: z.boolean().optional().describe("Wait for result (true) or return task_id (false, default)"),
@@ -875,7 +875,7 @@ server.tool("context_guard_compact", "Compact session context with DNA protectio
875
875
  }
876
876
  });
877
877
  // context_guard_bootstrap — DNA-first session bootstrap (IDE)
878
- server.tool("context_guard_bootstrap", "Load context from previous sessions at session start. Returns preferences, recent activity, and task-relevant memories. Call once at the beginning of a session to restore context.", {
878
+ server.tool("context_guard_bootstrap", "Advanced: Load context from previous sessions at session start. Returns preferences, recent activity, and task-relevant memories. Call once at the beginning of a session to restore context.", {
879
879
  task: z.string().describe("Task description for context relevance"),
880
880
  limit: z.number().optional().describe("Max memories to include (default: 10)"),
881
881
  }, async (args) => {
@@ -893,7 +893,7 @@ server.tool("context_guard_bootstrap", "Load context from previous sessions at s
893
893
  }
894
894
  });
895
895
  // bot_guard_bootstrap — 3-tier wake-up for bots (800 tokens)
896
- server.tool("bot_guard_bootstrap", "Bot-specific bootstrap — 3-tier wake-up (Identity→Context→Details) with 800 token budget. Use for chatbots, not IDEs.", {
896
+ server.tool("bot_guard_bootstrap", "Advanced: Bot-specific bootstrap — 3-tier wake-up (Identity→Context→Details) with 800 token budget. Use for chatbots, not IDEs.", {
897
897
  task: z.string().describe("Task description for the new session"),
898
898
  limit: z.number().optional().describe("Max memories to include (default: 10)"),
899
899
  mode: z.enum(["default", "deep"]).optional().describe("'default' = 800 token 3-tier, 'deep' = full context with L2 chunks"),
@@ -916,7 +916,7 @@ server.tool("bot_guard_bootstrap", "Bot-specific bootstrap — 3-tier wake-up (I
916
916
  }
917
917
  });
918
918
  // bot_session_message — Rolling 3-session tracking (60 msg raw context)
919
- server.tool("bot_session_message", "Track a message in the rolling session (rolling 3: keeps 60 messages raw in LLM context). Call on EVERY message (user + assistant). Returns rotate=true when session hits 20 messages. When should_compress=true, compress the oldest session via bot_session_compress.", {
919
+ server.tool("bot_session_message", "Advanced: Track a message in the rolling session (rolling 3: keeps 60 messages raw in LLM context). Call on EVERY message (user + assistant). Returns rotate=true when session hits 20 messages. When should_compress=true, compress the oldest session via bot_session_compress.", {
920
920
  message: z.object({
921
921
  role: z.enum(["user", "assistant"]).describe("Message role"),
922
922
  content: z.string().describe("Message content"),
@@ -945,7 +945,7 @@ server.tool("bot_session_message", "Track a message in the rolling session (roll
945
945
  }
946
946
  });
947
947
  // bot_guard_check — Bot-specific guard with spawn signal
948
- server.tool("bot_guard_check", "Bot context guard — checks context pressure AND returns spawn signal. When should_spawn_new_session=true, bot should spawn a new session and compress the old one later. Use this instead of context_guard_check for bot/chatbot clients.", {
948
+ server.tool("bot_guard_check", "Advanced: Bot context guard — checks context pressure AND returns spawn signal. When should_spawn_new_session=true, bot should spawn a new session and compress the old one later. Use this instead of context_guard_check for bot/chatbot clients.", {
949
949
  estimated_tokens: z.number().describe("Current token count in context window"),
950
950
  max_tokens: z.number().optional().describe("Max context window size (default: 200000)"),
951
951
  model: z.string().optional().describe("Model name for auto-detecting context window size"),
@@ -982,7 +982,7 @@ server.tool("bot_guard_check", "Bot context guard — checks context pressure AN
982
982
  });
983
983
  // ── Self-Thinking Tools ──────────────────────────────────────────────
984
984
  // brain_thoughts — Get current active thoughts
985
- server.tool("brain_thoughts", "Get the brain's current active thoughts — what it's thinking about autonomously.", {
985
+ server.tool("brain_thoughts", "Advanced: Get the brain's current active thoughts — what it's thinking about autonomously.", {
986
986
  limit: z.number().optional().describe("Max thoughts to return (default: 10)"),
987
987
  }, async (args) => {
988
988
  try {
@@ -997,7 +997,7 @@ server.tool("brain_thoughts", "Get the brain's current active thoughts — what
997
997
  }
998
998
  });
999
999
  // brain_think_about — Request brain to think about a topic
1000
- server.tool("brain_think_about", "Request the brain to think about a specific topic. The brain will deliberate on it in its next thinking cycle.", {
1000
+ server.tool("brain_think_about", "Advanced: Request the brain to think about a specific topic. The brain will deliberate on it in its next thinking cycle.", {
1001
1001
  topic: z.string().describe("What should the brain think about?"),
1002
1002
  }, async (args) => {
1003
1003
  try {
@@ -1009,7 +1009,7 @@ server.tool("brain_think_about", "Request the brain to think about a specific to
1009
1009
  }
1010
1010
  });
1011
1011
  // brain_hypotheses — Get active hypotheses
1012
- server.tool("brain_hypotheses", "Get hypotheses the brain is currently testing — predictions about user behavior patterns.", {
1012
+ server.tool("brain_hypotheses", "Advanced: Get hypotheses the brain is currently testing — predictions about user behavior patterns.", {
1013
1013
  limit: z.number().optional().describe("Max hypotheses to return (default: 10)"),
1014
1014
  }, async (args) => {
1015
1015
  try {
@@ -1024,7 +1024,7 @@ server.tool("brain_hypotheses", "Get hypotheses the brain is currently testing
1024
1024
  }
1025
1025
  });
1026
1026
  // brain_feedback — Rate a thought
1027
- server.tool("brain_feedback", "Rate a thought as useful or not — helps the brain learn what's worth thinking about.", {
1027
+ server.tool("brain_feedback", "Advanced: Rate a thought as useful or not — helps the brain learn what's worth thinking about.", {
1028
1028
  thought_id: z.number().describe("ID of the thought to rate"),
1029
1029
  useful: z.boolean().describe("Was this thought useful?"),
1030
1030
  }, async (args) => {
@@ -1040,7 +1040,7 @@ server.tool("brain_feedback", "Rate a thought as useful or not — helps the bra
1040
1040
  }
1041
1041
  });
1042
1042
  // brain_thinking_stats — Budget and efficiency
1043
- server.tool("brain_thinking_stats", "Get thinking system statistics — token budget, efficiency, queue size, and meta-cognition report.", {}, async () => {
1043
+ server.tool("brain_thinking_stats", "Advanced: Get thinking system statistics — token budget, efficiency, queue size, and meta-cognition report.", {}, async () => {
1044
1044
  try {
1045
1045
  const r = (await api("GET", "/v1/brain/thinking-stats"));
1046
1046
  return ok(`Budget: ${r.budget.remaining_tokens} tokens remaining (limit: ${r.budget.limit_per_hour}/hr)\n` +
@@ -1057,7 +1057,7 @@ server.tool("brain_thinking_stats", "Get thinking system statistics — token bu
1057
1057
  });
1058
1058
  // ── Session Settings Tools ──────────────────────────────────────────
1059
1059
  // memory_auto_extract — LLM-based fact extraction from conversation
1060
- server.tool("memory_auto_extract", "CRITICAL: Call this at the END of every conversation session to extract and store important facts automatically. Uses LLM analysis to identify pricing, decisions, plans, technical details, and anything worth remembering. This is MORE reliable than manual memory_store because it catches things you might forget to store. ALWAYS call this before the conversation ends — especially after discussions about money, pricing, plans, decisions, or business.", {
1060
+ server.tool("memory_auto_extract", "Advanced: CRITICAL: Call this at the END of every conversation session to extract and store important facts automatically. Uses LLM analysis to identify pricing, decisions, plans, technical details, and anything worth remembering. This is MORE reliable than manual memory_store because it catches things you might forget to store. ALWAYS call this before the conversation ends — especially after discussions about money, pricing, plans, decisions, or business.", {
1061
1061
  conversation: z.string().describe("The conversation text to extract facts from (include both user and assistant messages)"),
1062
1062
  source: z.string().optional().describe("Source context (e.g. 'discord chat', 'slack thread')"),
1063
1063
  store: z.boolean().optional().describe("Whether to store extracted facts (default: true). Set false to preview what would be extracted."),
@@ -1081,7 +1081,7 @@ server.tool("memory_auto_extract", "CRITICAL: Call this at the END of every conv
1081
1081
  });
1082
1082
  // ── IDE Upgrade Tools ──────────────────────────────────────────────
1083
1083
  // memory_pitfall_check — Check pitfalls before risky actions
1084
- server.tool("memory_pitfall_check", "IMPORTANT: Call this BEFORE executing risky actions (deploy, rm, git push, database changes). Returns known pitfalls (past failures + lessons) so you can avoid repeating mistakes. Pitfalls are DNA-protected and never expire.", {
1084
+ server.tool("memory_pitfall_check", "Advanced: IMPORTANT: Call this BEFORE executing risky actions (deploy, rm, git push, database changes). Returns known pitfalls (past failures + lessons) so you can avoid repeating mistakes. Pitfalls are DNA-protected and never expire.", {
1085
1085
  intent: z.string().describe("What you're about to do (e.g. 'deploy to production', 'delete user table')"),
1086
1086
  tags: z.array(z.string()).optional().describe("Filter by tags"),
1087
1087
  limit: z.number().optional().describe("Max results (default 5)"),
@@ -1104,7 +1104,7 @@ server.tool("memory_pitfall_check", "IMPORTANT: Call this BEFORE executing risky
1104
1104
  }
1105
1105
  });
1106
1106
  // memory_plan_save — Save current plan/state for session resumption
1107
- server.tool("memory_plan_save", "Save your current work state (plan steps, cursor position, active goals) so you can resume exactly where you left off in the next session. Call before session ends or when switching tasks.", {
1107
+ server.tool("memory_plan_save", "Advanced: Save your current work state (plan steps, cursor position, active goals) so you can resume exactly where you left off in the next session. Call before session ends or when switching tasks.", {
1108
1108
  session_id: z.string().optional().describe("Session identifier (default: 'default')"),
1109
1109
  state: z.record(z.string(), z.unknown()).describe("State to save: {plan: [...], cursor: 3, active_goal: '...', last_action: '...', files_read: [...]}"),
1110
1110
  }, async (args) => {
@@ -1120,7 +1120,7 @@ server.tool("memory_plan_save", "Save your current work state (plan steps, curso
1120
1120
  }
1121
1121
  });
1122
1122
  // memory_plan_resume — Restore saved state from previous session
1123
- server.tool("memory_plan_resume", "Restore your work state from a previous session. Returns plan steps, cursor position, active goals — everything needed to continue where you left off.", {
1123
+ server.tool("memory_plan_resume", "Advanced: Restore your work state from a previous session. Returns plan steps, cursor position, active goals — everything needed to continue where you left off.", {
1124
1124
  session_id: z.string().optional().describe("Session identifier (default: 'default')"),
1125
1125
  }, async (args) => {
1126
1126
  try {
@@ -1134,7 +1134,7 @@ server.tool("memory_plan_resume", "Restore your work state from a previous sessi
1134
1134
  }
1135
1135
  });
1136
1136
  // memory_goal_track — Create/update/query goals
1137
- server.tool("memory_goal_track", "Track goals across sessions. Create new goals, update progress, or query active goals. Goals with status='active' are DNA-protected (never decay).", {
1137
+ server.tool("memory_goal_track", "Advanced: Track goals across sessions. Create new goals, update progress, or query active goals. Goals with status='active' are DNA-protected (never decay).", {
1138
1138
  action: z.enum(["create", "update", "list"]).describe("Action to perform"),
1139
1139
  title: z.string().optional().describe("Goal title (for create)"),
1140
1140
  progress: z.number().optional().describe("Progress 0.0-1.0 (for update)"),
@@ -1172,7 +1172,7 @@ server.tool("memory_goal_track", "Track goals across sessions. Create new goals,
1172
1172
  }
1173
1173
  });
1174
1174
  // memory_thought_log — Query what the brain has been thinking about
1175
- server.tool("memory_thought_log", "See what the brain has been thinking about autonomously. Returns recent thoughts, hypotheses, and insights generated during idle time.", {
1175
+ server.tool("memory_thought_log", "Advanced: See what the brain has been thinking about autonomously. Returns recent thoughts, hypotheses, and insights generated during idle time.", {
1176
1176
  limit: z.number().optional().describe("Max thoughts to return (default 5)"),
1177
1177
  }, async (args) => {
1178
1178
  try {
@@ -1189,7 +1189,7 @@ server.tool("memory_thought_log", "See what the brain has been thinking about au
1189
1189
  }
1190
1190
  });
1191
1191
  // memory_feedback — Report recall quality for self-improvement
1192
- server.tool("memory_feedback", "Report whether recall results were helpful. This feeds the neuroplasticity system — over time, the brain learns what works for YOUR specific patterns and improves recall quality.", {
1192
+ server.tool("memory_feedback", "Advanced: Report whether recall results were helpful. This feeds the neuroplasticity system — over time, the brain learns what works for YOUR specific patterns and improves recall quality.", {
1193
1193
  query: z.string().describe("The recall query that was made"),
1194
1194
  chunk_ids: z.array(z.number()).describe("IDs of chunks that were returned"),
1195
1195
  helpful: z.boolean().describe("Were the results helpful for your task?"),
@@ -1209,7 +1209,7 @@ server.tool("memory_feedback", "Report whether recall results were helpful. This
1209
1209
  }
1210
1210
  });
1211
1211
  // memory_predict — Predictive recall (push intent, get predicted memories)
1212
- server.tool("memory_predict", "Predictive recall — tell the brain what you're about to do and get relevant memories pre-loaded. Call this when you can anticipate what context will be needed next.", {
1212
+ server.tool("memory_predict", "Advanced: Predictive recall — tell the brain what you're about to do and get relevant memories pre-loaded. Call this when you can anticipate what context will be needed next.", {
1213
1213
  intent: z.string().describe("What you/user are about to do"),
1214
1214
  context: z.string().optional().describe("Current conversation context (helps prediction accuracy)"),
1215
1215
  limit: z.number().optional().describe("Max predictions (default 5)"),
@@ -1232,7 +1232,7 @@ server.tool("memory_predict", "Predictive recall — tell the brain what you're
1232
1232
  }
1233
1233
  });
1234
1234
  // memory_changelog — What changed since last session
1235
- server.tool("memory_changelog", "See what changed in your memory since your last session. Shows new memories, updates, invalidations, and insights from overnight consolidation. Call at session start after bootstrap to understand what the brain learned while you were away.", {
1235
+ server.tool("memory_changelog", "Advanced: See what changed in your memory since your last session. Shows new memories, updates, invalidations, and insights from overnight consolidation. Call at session start after bootstrap to understand what the brain learned while you were away.", {
1236
1236
  since: z.string().describe("ISO datetime — show changes after this time (e.g. '2026-05-20T10:00:00Z')"),
1237
1237
  project_id: z.string().optional().describe("Filter to specific project"),
1238
1238
  limit: z.number().optional().describe("Max changes to return (default 50)"),
@@ -1255,7 +1255,7 @@ server.tool("memory_changelog", "See what changed in your memory since your last
1255
1255
  }
1256
1256
  });
1257
1257
  // memory_cognitive_profile — Complete self-model (metacognition)
1258
- server.tool("memory_cognitive_profile", "Get the brain's complete self-model: who the user is, their mood, active goals, top entities (people/places), learned procedures, and recent topics. Use for complete context awareness. No LLM cost — pure aggregation (~50ms).", {}, async () => {
1258
+ server.tool("memory_cognitive_profile", "Advanced: Get the brain's complete self-model: who the user is, their mood, active goals, top entities (people/places), learned procedures, and recent topics. Use for complete context awareness. No LLM cost — pure aggregation (~50ms).", {}, async () => {
1259
1259
  try {
1260
1260
  const r = (await api("GET", "/v1/personality/cognitive-profile"));
1261
1261
  let out = `## Cognitive Profile\n\n`;
@@ -1278,7 +1278,7 @@ server.tool("memory_cognitive_profile", "Get the brain's complete self-model: wh
1278
1278
  }
1279
1279
  });
1280
1280
  // memory_entity_profile — Get everything known about an entity
1281
- server.tool("memory_entity_profile", "Get complete profile for a specific entity (person, place, concept). Returns: frequency stats, linked memories, and relationships. Use when you need context about a specific person or topic the user has discussed.", {
1281
+ server.tool("memory_entity_profile", "Advanced: Get complete profile for a specific entity (person, place, concept). Returns: frequency stats, linked memories, and relationships. Use when you need context about a specific person or topic the user has discussed.", {
1282
1282
  name: z.string().describe("Entity name to look up (e.g. 'Sarah', 'React', 'AuthService')"),
1283
1283
  }, async (args) => {
1284
1284
  try {
@@ -1316,7 +1316,7 @@ server.tool("memory_entity_profile", "Get complete profile for a specific entity
1316
1316
  // • twin_respond / twin_status — Cognitive Twin (promax+ tier)
1317
1317
  // ═══════════════════════════════════════════════════════════════════════════
1318
1318
  // brain_export
1319
- server.tool("brain_export", "Export the entire brain to a portable JSON bundle (vendor-neutral). Use when the user wants to back up their brain, migrate to another instance (e.g. lite-build on-prem), or comply with data-portability rights. The bundle is self-contained — chunks, edges, entities, L2 sessions, mood, agents — and includes a sha256 checksum. Returns the bundle JSON.", {
1319
+ server.tool("brain_export", "Advanced: Export the entire brain to a portable JSON bundle (vendor-neutral). Use when the user wants to back up their brain, migrate to another instance (e.g. lite-build on-prem), or comply with data-portability rights. The bundle is self-contained — chunks, edges, entities, L2 sessions, mood, agents — and includes a sha256 checksum. Returns the bundle JSON.", {
1320
1320
  scope: z.enum(["full", "dna_only", "since"]).optional().describe("'full'=everything (default), 'dna_only'=just preferences/decisions/identity (lightweight portable identity), 'since'=incremental (requires `since` ISO datetime)"),
1321
1321
  since: z.string().optional().describe("ISO8601 datetime, only used when scope='since'"),
1322
1322
  }, async (args) => {
@@ -1341,7 +1341,7 @@ server.tool("brain_export", "Export the entire brain to a portable JSON bundle (
1341
1341
  }
1342
1342
  });
1343
1343
  // brain_import
1344
- server.tool("brain_import", "Import a MemoryAI bundle (from brain_export) into the current tenant. Idempotent — chunks deduped by content_hash; edges/entities upserted. Embeddings are reused if the bundle's embedding_model matches the local one; otherwise dropped (chunks re-embed lazily).", {
1344
+ server.tool("brain_import", "Advanced: Import a MemoryAI bundle (from brain_export) into the current tenant. Idempotent — chunks deduped by content_hash; edges/entities upserted. Embeddings are reused if the bundle's embedding_model matches the local one; otherwise dropped (chunks re-embed lazily).", {
1345
1345
  bundle: z.record(z.string(), z.unknown()).describe("The bundle JSON produced by brain_export (must contain format='memoryai-bundle', version, manifest, etc.)"),
1346
1346
  keep_embeddings: z.boolean().optional().describe("Reuse bundle embeddings if model matches (default: true)"),
1347
1347
  }, async (args) => {
@@ -1363,7 +1363,7 @@ server.tool("brain_import", "Import a MemoryAI bundle (from brain_export) into t
1363
1363
  }
1364
1364
  });
1365
1365
  // benchmark_recall_vs_full
1366
- server.tool("benchmark_recall_vs_full", "Run a public benchmark: smart recall vs full-context dump on the calling brain. DNA #2 — proves the 'retina for AI' moat with measurable numbers (cost, latency, signal density). Available on every tier; safe to share results publicly.", {
1366
+ server.tool("benchmark_recall_vs_full", "Advanced: Run a public benchmark: smart recall vs full-context dump on the calling brain. DNA #2 — proves the 'retina for AI' moat with measurable numbers (cost, latency, signal density). Available on every tier; safe to share results publicly.", {
1367
1367
  query: z.string().describe("The query to benchmark (e.g. 'what does the user prefer?')"),
1368
1368
  model: z.string().optional().describe("Model whose pricing to apply (default: claude-opus-4-6). Affects $cost only."),
1369
1369
  naive_budget_tokens: z.number().optional().describe("Cap on full-context dump (default: 200K = Claude window)"),
@@ -1390,7 +1390,7 @@ server.tool("benchmark_recall_vs_full", "Run a public benchmark: smart recall vs
1390
1390
  }
1391
1391
  });
1392
1392
  // benchmark_pricing
1393
- server.tool("benchmark_pricing", "Get the assumed $/1M-input-tokens pricing for each LLM (used by benchmark_recall_vs_full). No auth required; list prices only.", {}, async () => {
1393
+ server.tool("benchmark_pricing", "Advanced: Get the assumed $/1M-input-tokens pricing for each LLM (used by benchmark_recall_vs_full). No auth required; list prices only.", {}, async () => {
1394
1394
  try {
1395
1395
  const r = (await api("GET", "/v1/benchmark/pricing"));
1396
1396
  const lines = Object.entries(r.prices || {}).map(([k, v]) => `- ${k}: $${v}`);
@@ -1401,7 +1401,7 @@ server.tool("benchmark_pricing", "Get the assumed $/1M-input-tokens pricing for
1401
1401
  }
1402
1402
  });
1403
1403
  // trust_agents
1404
- server.tool("trust_agents", "Get the agent reputation leaderboard (sorted by reputation_score desc). DNA #1.5 — when 20 agents share memory and disagree, this tells you whose claims to trust. Requires team+ plan.", {
1404
+ server.tool("trust_agents", "Advanced: Get the agent reputation leaderboard (sorted by reputation_score desc). DNA #1.5 — when 20 agents share memory and disagree, this tells you whose claims to trust. Requires team+ plan.", {
1405
1405
  limit: z.number().optional().describe("Max agents to return (default: 50, max: 500)"),
1406
1406
  }, async (args) => {
1407
1407
  try {
@@ -1416,7 +1416,7 @@ server.tool("trust_agents", "Get the agent reputation leaderboard (sorted by rep
1416
1416
  }
1417
1417
  });
1418
1418
  // trust_chunk
1419
- server.tool("trust_chunk", "Get per-chunk trust info: which agent claimed it, that agent's reputation, helpful/unhelpful counts. Use after a recall to decide whether to trust a specific result. Available on every paid tier.", {
1419
+ server.tool("trust_chunk", "Advanced: Get per-chunk trust info: which agent claimed it, that agent's reputation, helpful/unhelpful counts. Use after a recall to decide whether to trust a specific result. Available on every paid tier.", {
1420
1420
  chunk_id: z.number().describe("The chunk ID returned by recall"),
1421
1421
  }, async (args) => {
1422
1422
  try {
@@ -1433,7 +1433,7 @@ server.tool("trust_chunk", "Get per-chunk trust info: which agent claimed it, th
1433
1433
  }
1434
1434
  });
1435
1435
  // twin_respond
1436
- server.tool("twin_respond", "Ask the Cognitive Twin to predict how the user would respond to a given query. The twin uses the user's personality + mood + DNA + procedures to simulate their voice. Returns the predicted response, a confidence score 0-1, and the chunk IDs that informed it (provenance trail). Auto-refuses with confidence=0 if the brain has fewer than 5 DNA memories. Requires promax+ plan.", {
1436
+ server.tool("twin_respond", "Advanced: Ask the Cognitive Twin to predict how the user would respond to a given query. The twin uses the user's personality + mood + DNA + procedures to simulate their voice. Returns the predicted response, a confidence score 0-1, and the chunk IDs that informed it (provenance trail). Auto-refuses with confidence=0 if the brain has fewer than 5 DNA memories. Requires promax+ plan.", {
1437
1437
  query: z.string().describe("The free-form question to ask the twin (e.g. 'what database for a chat app?')"),
1438
1438
  operation: z.enum(["respond", "decide"]).optional().describe("'respond'=free-form answer (default), 'decide'=pick one option from the query"),
1439
1439
  }, async (args) => {
@@ -1453,7 +1453,7 @@ server.tool("twin_respond", "Ask the Cognitive Twin to predict how the user woul
1453
1453
  }
1454
1454
  });
1455
1455
  // twin_status
1456
- server.tool("twin_status", "Check whether the Cognitive Twin is ready for the calling tenant. Cheap — no LLM call. Returns DNA count, personality/mood presence, and a `ready` boolean. Useful before invoking twin_respond.", {}, async () => {
1456
+ server.tool("twin_status", "Advanced: Check whether the Cognitive Twin is ready for the calling tenant. Cheap — no LLM call. Returns DNA count, personality/mood presence, and a `ready` boolean. Useful before invoking twin_respond.", {}, async () => {
1457
1457
  try {
1458
1458
  const r = (await api("GET", "/v1/twin/status"));
1459
1459
  return ok(`Twin ready: ${r.ready ? "YES" : "NO"} (need ≥${r.min_dna_required} DNA, have ${r.dna_count})\n` +
@@ -1469,6 +1469,175 @@ server.tool("twin_status", "Check whether the Cognitive Twin is ready for the ca
1469
1469
  return err(e);
1470
1470
  }
1471
1471
  });
1472
+ // ═══════════════════════════════════════════════════════════════════════════
1473
+ // v2.3 (billion-dollar foundation, 2026-05-29) — DNA-aligned tools:
1474
+ // • inherit_* — DNA #3 brain belongs to user, transferable when they die
1475
+ // • fed_* — DNA #1 ∞ agents share brain across organizations
1476
+ // • l2_inject — DNA #2 retina endpoint (compose context within budget)
1477
+ // • l2_status — cache + availability summary
1478
+ // • spec_info — public protocol contract (CC BY 4.0)
1479
+ // ═══════════════════════════════════════════════════════════════════════════
1480
+ // inherit_assign
1481
+ server.tool("inherit_assign", "Advanced: Assign an heir who inherits your brain when you trigger inheritance. DNA #3 — brain belongs to the user and is transferable. Idempotent on (owner, heir).", {
1482
+ heir_tenant_id: z.string().describe("Heir's tenant UUID"),
1483
+ share: z.number().optional().describe("Share percentage 0-100 (default: 100 if single heir)"),
1484
+ scope: z.enum(["all", "dna_only", "tagged"]).optional().describe("What to transfer (default: all)"),
1485
+ tag_filter: z.array(z.string()).optional().describe("Only transfer chunks with these tags (when scope=tagged)"),
1486
+ message: z.string().optional().describe("Optional letter to the heir, surfaced in their inbox"),
1487
+ }, async (args) => {
1488
+ try {
1489
+ const r = (await api("POST", "/v1/inheritance/heirs", args));
1490
+ return ok(`Heir assigned: ${r.heir_tenant_id} (share ${r.share}%, scope ${r.scope}). ${r.message_set ? "Message stored." : ""}`);
1491
+ }
1492
+ catch (e) {
1493
+ return err(e);
1494
+ }
1495
+ });
1496
+ // inherit_list
1497
+ server.tool("inherit_list", "Advanced: List your assigned heirs and their share/scope. DNA #3 — your brain inheritance plan, viewable any time.", {}, async () => {
1498
+ try {
1499
+ const r = (await api("GET", "/v1/inheritance/heirs"));
1500
+ const heirs = r.heirs || [];
1501
+ if (heirs.length === 0)
1502
+ return ok("No heirs assigned yet.");
1503
+ const lines = heirs.map((h) => `- ${h.heir_tenant_id} · share=${h.share}% · scope=${h.scope} · status=${h.status} · added=${h.created_at?.slice(0, 10)}`);
1504
+ return ok(`Heirs (${heirs.length}):\n${lines.join("\n")}`);
1505
+ }
1506
+ catch (e) {
1507
+ return err(e);
1508
+ }
1509
+ });
1510
+ // inherit_revoke
1511
+ server.tool("inherit_revoke", "Advanced: Revoke a previously assigned heir. Their access to your brain is removed; nothing is exported.", {
1512
+ heir_tenant_id: z.string().describe("Heir's tenant UUID to revoke"),
1513
+ }, async (args) => {
1514
+ try {
1515
+ await api("DELETE", `/v1/inheritance/heirs/${encodeURIComponent(args.heir_tenant_id)}`);
1516
+ return ok(`Heir revoked: ${args.heir_tenant_id}`);
1517
+ }
1518
+ catch (e) {
1519
+ return err(e);
1520
+ }
1521
+ });
1522
+ // inherit_trigger
1523
+ server.tool("inherit_trigger", "Advanced: Trigger inheritance — exports your brain bundle and imports it into every accepted heir. Owner-only (heir-triggered inheritance is deferred to P2.3.full). DNA #3 — your brain becomes their brain.", {}, async () => {
1524
+ try {
1525
+ const r = (await api("POST", "/v1/inheritance/trigger", {}));
1526
+ const transfers = r.transfers || [];
1527
+ const summary = transfers.map((t) => `- ${t.heir_tenant_id}: ${t.status} (${t.chunks_inserted ?? 0} chunks transferred)`);
1528
+ return ok(`Inheritance triggered (${transfers.length} heirs):\n${summary.join("\n")}`);
1529
+ }
1530
+ catch (e) {
1531
+ return err(e);
1532
+ }
1533
+ });
1534
+ // fed_grant
1535
+ server.tool("fed_grant", "Advanced: Grant a federated reader access to your brain. DNA #1 — multi-agent / cross-organization recall without copying. Optional tag filter, expiry, and DNA exclusion (DNA excluded by default for safety). Requires team+ plan.", {
1536
+ grantee_tenant_id: z.string().describe("Grantee's tenant UUID"),
1537
+ permission: z.enum(["read", "read_write"]).optional().describe("Permission (default: read)"),
1538
+ tag_filter: z.array(z.string()).optional().describe("Only expose chunks matching these tags"),
1539
+ include_dna: z.boolean().optional().describe("Allow grantee to recall DNA chunks (default: false)"),
1540
+ expires_at: z.string().optional().describe("ISO datetime expiry (default: no expiry)"),
1541
+ }, async (args) => {
1542
+ try {
1543
+ const r = (await api("POST", "/v1/federation/grants", args));
1544
+ return ok(`Federation grant created: ${r.grant_id} (grantee=${r.grantee_tenant_id}, permission=${r.permission}, expires=${r.expires_at || "never"})`);
1545
+ }
1546
+ catch (e) {
1547
+ return err(e);
1548
+ }
1549
+ });
1550
+ // fed_revoke
1551
+ server.tool("fed_revoke", "Advanced: Revoke a federation grant. Only the grantor may revoke. Existing in-flight recalls remain audited.", {
1552
+ grant_id: z.string().describe("Grant UUID to revoke"),
1553
+ }, async (args) => {
1554
+ try {
1555
+ await api("DELETE", `/v1/federation/grants/${encodeURIComponent(args.grant_id)}`);
1556
+ return ok(`Federation grant revoked: ${args.grant_id}`);
1557
+ }
1558
+ catch (e) {
1559
+ return err(e);
1560
+ }
1561
+ });
1562
+ // fed_inbox
1563
+ server.tool("fed_inbox", "Advanced: List federation grants others gave you (your federated inbox). Each grant lets you recall against another tenant's brain via fed_recall.", {}, async () => {
1564
+ try {
1565
+ const r = (await api("GET", "/v1/federation/inbox"));
1566
+ const grants = r.grants || [];
1567
+ if (grants.length === 0)
1568
+ return ok("Federation inbox empty.");
1569
+ const lines = grants.map((g) => `- grant=${g.grant_id} · grantor=${g.grantor_tenant_id} · perm=${g.permission} · tags=${(g.tag_filter || []).join(",") || "(any)"} · expires=${g.expires_at || "never"}`);
1570
+ return ok(`Federated grants you can use (${grants.length}):\n${lines.join("\n")}`);
1571
+ }
1572
+ catch (e) {
1573
+ return err(e);
1574
+ }
1575
+ });
1576
+ // fed_recall
1577
+ server.tool("fed_recall", "Advanced: Recall against a federated brain you have access to. Server enforces tag_filter, DNA exclusion, expiry, and audits every call back to the grantor.", {
1578
+ grant_id: z.string().describe("Grant UUID from fed_inbox"),
1579
+ query: z.string().describe("Recall query"),
1580
+ }, async (args) => {
1581
+ try {
1582
+ const r = (await api("POST", "/v1/federation/recall", args));
1583
+ const results = r.results || [];
1584
+ if (results.length === 0)
1585
+ return ok("No federated results.");
1586
+ const lines = results.slice(0, 10).map((m) => `[${m.score?.toFixed(2)}] ${m.content?.slice(0, 200)}`);
1587
+ return ok(`Federated recall (${results.length} results, audited to grantor):\n${lines.join("\n\n")}`);
1588
+ }
1589
+ catch (e) {
1590
+ return err(e);
1591
+ }
1592
+ });
1593
+ // l2_inject — DNA #2 retina endpoint
1594
+ server.tool("l2_inject", "Compose a context block for your prompt within a token budget. DNA #2 — top model thinks with 100K context, L2 holds 100M memory; this tool is the bridge. Pipeline: L4 cache → DNA → pre-reasoned L2 → L3 4-way recall → compress within budget. Latency p95 < 200ms (cache hit), < 800ms (miss). Returns a markdown block ready to paste into your system prompt.", {
1595
+ query: z.string().describe("What you're about to ask the top model"),
1596
+ context_budget_tokens: z.number().optional().describe("Max tokens in returned context (default: 2000)"),
1597
+ model_hint: z.string().optional().describe("Model name (e.g. 'claude-opus-4-7') for token-counting accuracy"),
1598
+ freshness_priority: z.enum(["balanced", "recent", "deep"]).optional().describe("Bias toward freshness vs depth (default: balanced)"),
1599
+ bypass_cache: z.boolean().optional().describe("Skip L4 cache lookup (default: false)"),
1600
+ }, async (args) => {
1601
+ try {
1602
+ const r = (await api("POST", "/v1/l2/inject", args));
1603
+ const out = `L2 inject — ${r.tokens_used}/${r.tokens_budget} tokens, ${r.sources?.length ?? 0} sources, cache_hit=${r.cache_hit}, ${r.latency_ms}ms\n\n${r.context_block}`;
1604
+ return ok(out);
1605
+ }
1606
+ catch (e) {
1607
+ return err(e);
1608
+ }
1609
+ });
1610
+ // l2_status — DNA #2
1611
+ server.tool("l2_status", "Check L2 readiness: cached entries, pre-reasoned chunks, DNA chunks. Cheap — no LLM call. Useful before deciding whether to call l2_inject vs raw recall.", {}, async () => {
1612
+ try {
1613
+ const r = (await api("GET", "/v1/l2/status"));
1614
+ return ok(`L2 status:\n` +
1615
+ `- cached_entries: ${r.cached_entries}\n` +
1616
+ `- pre_reasoned_chunks: ${r.pre_reasoned_chunks}\n` +
1617
+ `- dna_chunks: ${r.dna_chunks}`);
1618
+ }
1619
+ catch (e) {
1620
+ return err(e);
1621
+ }
1622
+ });
1623
+ // spec_info — DNA #3 protocol
1624
+ server.tool("spec_info", "Advanced: Get the MemoryAI Protocol v1 contract (machine-readable summary). DNA #3 — vendor-neutral standard. Use this when interoperating with other MemoryAI-compatible implementations.", {}, async () => {
1625
+ try {
1626
+ const r = (await api("GET", "/v1/spec/info"));
1627
+ const lines = [
1628
+ `Protocol: ${r.format} v${r.version}`,
1629
+ `License: ${r.license}`,
1630
+ `Conformance levels: ${(r.conformance_levels || []).join(", ")}`,
1631
+ `DNA types: ${(r.dna_memory_types || []).join(", ")}`,
1632
+ `Embedding model: ${r.embedding_model} (${r.embedding_dim} dims)`,
1633
+ `Bundle endpoints: ${(r.endpoints || []).join(", ")}`,
1634
+ ];
1635
+ return ok(lines.join("\n"));
1636
+ }
1637
+ catch (e) {
1638
+ return err(e);
1639
+ }
1640
+ });
1472
1641
  async function main() {
1473
1642
  const transport = new StdioServerTransport();
1474
1643
  await server.connect(transport);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memoryai-mcp",
3
- "version": "2.2.0",
4
- "description": "MCP server for MemoryAI v2.0 — One brain. ∞ agents. Forever. Adds Brain Export/Import (vendor-neutral bundles), Public Benchmark (smart recall vs full context), Trust Graph (per-agent reputation), Cognitive Twin (simulate user voice). Plus the v1.5 base: 11 biological behaviors, DNA-protected memories, Multi-Agent Mesh.",
3
+ "version": "2.3.0",
4
+ "description": "MCP server for MemoryAI v2.3 — One brain. ∞ agents. Forever. Adds Brain Inheritance/Federation (P2.3), L2 Inject endpoint (DNA #2 retina), Protocol v1 spec lookup. Plus the v2.0 base: Brain Export/Import, Public Benchmark, Trust Graph, Cognitive Twin. Plus the v1.5 base: 11 biological behaviors, DNA-protected memories, Multi-Agent Mesh.",
5
5
  "homepage": "https://memoryai.dev",
6
6
  "repository": {
7
7
  "type": "git",