memoryai-mcp 2.1.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.
- package/dist/index.js +414 -65
- 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);
|
|
16
|
-
const CG_COMPACT_PCT = parseInt(process.env.HM_COMPACT_AT || "0", 10);
|
|
17
|
-
const CG_CRITICAL_PCT = parseInt(process.env.HM_CRITICAL_AT || "0", 10);
|
|
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: "
|
|
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,
|
|
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
|
|
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", "
|
|
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
|
|
819
|
+
server.tool("context_guard_check", "[CORE] Check context pressure — returns 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", "
|
|
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)"),
|
|
@@ -874,12 +874,30 @@ server.tool("context_guard_compact", "Compact session context with DNA protectio
|
|
|
874
874
|
return err(e);
|
|
875
875
|
}
|
|
876
876
|
});
|
|
877
|
-
// context_guard_bootstrap — DNA-first session bootstrap
|
|
878
|
-
server.tool("context_guard_bootstrap", "
|
|
877
|
+
// context_guard_bootstrap — DNA-first session bootstrap (IDE)
|
|
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
|
+
task: z.string().describe("Task description for context relevance"),
|
|
880
|
+
limit: z.number().optional().describe("Max memories to include (default: 10)"),
|
|
881
|
+
}, async (args) => {
|
|
882
|
+
try {
|
|
883
|
+
const r = (await api("POST", "/v1/context/guard/bootstrap", {
|
|
884
|
+
task: args.task,
|
|
885
|
+
limit: args.limit || 10,
|
|
886
|
+
}));
|
|
887
|
+
return ok(`Context restored: ${r.memories_restored || r.memories_included || 0} memories (${r.dna_memories || 0} DNA)\n` +
|
|
888
|
+
`Tokens used: ${r.tokens_used}\n\n` +
|
|
889
|
+
r.context_block);
|
|
890
|
+
}
|
|
891
|
+
catch (e) {
|
|
892
|
+
return err(e);
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
// bot_guard_bootstrap — 3-tier wake-up for bots (800 tokens)
|
|
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.", {
|
|
879
897
|
task: z.string().describe("Task description for the new session"),
|
|
880
898
|
limit: z.number().optional().describe("Max memories to include (default: 10)"),
|
|
881
|
-
mode: z.enum(["default", "deep"]).optional().describe("'default' = 800 token 3-tier
|
|
882
|
-
token_budget: z.number().optional().describe("Token budget
|
|
899
|
+
mode: z.enum(["default", "deep"]).optional().describe("'default' = 800 token 3-tier, 'deep' = full context with L2 chunks"),
|
|
900
|
+
token_budget: z.number().optional().describe("Token budget (default: 800)"),
|
|
883
901
|
}, async (args) => {
|
|
884
902
|
try {
|
|
885
903
|
const r = (await api("POST", "/v1/bot/guard/bootstrap", {
|
|
@@ -898,7 +916,7 @@ server.tool("context_guard_bootstrap", "Bootstrap a new session with DNA-first c
|
|
|
898
916
|
}
|
|
899
917
|
});
|
|
900
918
|
// bot_session_message — Rolling 3-session tracking (60 msg raw context)
|
|
901
|
-
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.", {
|
|
902
920
|
message: z.object({
|
|
903
921
|
role: z.enum(["user", "assistant"]).describe("Message role"),
|
|
904
922
|
content: z.string().describe("Message content"),
|
|
@@ -927,7 +945,7 @@ server.tool("bot_session_message", "Track a message in the rolling session (roll
|
|
|
927
945
|
}
|
|
928
946
|
});
|
|
929
947
|
// bot_guard_check — Bot-specific guard with spawn signal
|
|
930
|
-
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.", {
|
|
931
949
|
estimated_tokens: z.number().describe("Current token count in context window"),
|
|
932
950
|
max_tokens: z.number().optional().describe("Max context window size (default: 200000)"),
|
|
933
951
|
model: z.string().optional().describe("Model name for auto-detecting context window size"),
|
|
@@ -964,7 +982,7 @@ server.tool("bot_guard_check", "Bot context guard — checks context pressure AN
|
|
|
964
982
|
});
|
|
965
983
|
// ── Self-Thinking Tools ──────────────────────────────────────────────
|
|
966
984
|
// brain_thoughts — Get current active thoughts
|
|
967
|
-
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.", {
|
|
968
986
|
limit: z.number().optional().describe("Max thoughts to return (default: 10)"),
|
|
969
987
|
}, async (args) => {
|
|
970
988
|
try {
|
|
@@ -979,7 +997,7 @@ server.tool("brain_thoughts", "Get the brain's current active thoughts — what
|
|
|
979
997
|
}
|
|
980
998
|
});
|
|
981
999
|
// brain_think_about — Request brain to think about a topic
|
|
982
|
-
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.", {
|
|
983
1001
|
topic: z.string().describe("What should the brain think about?"),
|
|
984
1002
|
}, async (args) => {
|
|
985
1003
|
try {
|
|
@@ -991,7 +1009,7 @@ server.tool("brain_think_about", "Request the brain to think about a specific to
|
|
|
991
1009
|
}
|
|
992
1010
|
});
|
|
993
1011
|
// brain_hypotheses — Get active hypotheses
|
|
994
|
-
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.", {
|
|
995
1013
|
limit: z.number().optional().describe("Max hypotheses to return (default: 10)"),
|
|
996
1014
|
}, async (args) => {
|
|
997
1015
|
try {
|
|
@@ -1006,7 +1024,7 @@ server.tool("brain_hypotheses", "Get hypotheses the brain is currently testing
|
|
|
1006
1024
|
}
|
|
1007
1025
|
});
|
|
1008
1026
|
// brain_feedback — Rate a thought
|
|
1009
|
-
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.", {
|
|
1010
1028
|
thought_id: z.number().describe("ID of the thought to rate"),
|
|
1011
1029
|
useful: z.boolean().describe("Was this thought useful?"),
|
|
1012
1030
|
}, async (args) => {
|
|
@@ -1022,7 +1040,7 @@ server.tool("brain_feedback", "Rate a thought as useful or not — helps the bra
|
|
|
1022
1040
|
}
|
|
1023
1041
|
});
|
|
1024
1042
|
// brain_thinking_stats — Budget and efficiency
|
|
1025
|
-
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 () => {
|
|
1026
1044
|
try {
|
|
1027
1045
|
const r = (await api("GET", "/v1/brain/thinking-stats"));
|
|
1028
1046
|
return ok(`Budget: ${r.budget.remaining_tokens} tokens remaining (limit: ${r.budget.limit_per_hour}/hr)\n` +
|
|
@@ -1039,7 +1057,7 @@ server.tool("brain_thinking_stats", "Get thinking system statistics — token bu
|
|
|
1039
1057
|
});
|
|
1040
1058
|
// ── Session Settings Tools ──────────────────────────────────────────
|
|
1041
1059
|
// memory_auto_extract — LLM-based fact extraction from conversation
|
|
1042
|
-
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.", {
|
|
1043
1061
|
conversation: z.string().describe("The conversation text to extract facts from (include both user and assistant messages)"),
|
|
1044
1062
|
source: z.string().optional().describe("Source context (e.g. 'discord chat', 'slack thread')"),
|
|
1045
1063
|
store: z.boolean().optional().describe("Whether to store extracted facts (default: true). Set false to preview what would be extracted."),
|
|
@@ -1063,7 +1081,7 @@ server.tool("memory_auto_extract", "CRITICAL: Call this at the END of every conv
|
|
|
1063
1081
|
});
|
|
1064
1082
|
// ── IDE Upgrade Tools ──────────────────────────────────────────────
|
|
1065
1083
|
// memory_pitfall_check — Check pitfalls before risky actions
|
|
1066
|
-
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.", {
|
|
1067
1085
|
intent: z.string().describe("What you're about to do (e.g. 'deploy to production', 'delete user table')"),
|
|
1068
1086
|
tags: z.array(z.string()).optional().describe("Filter by tags"),
|
|
1069
1087
|
limit: z.number().optional().describe("Max results (default 5)"),
|
|
@@ -1086,7 +1104,7 @@ server.tool("memory_pitfall_check", "IMPORTANT: Call this BEFORE executing risky
|
|
|
1086
1104
|
}
|
|
1087
1105
|
});
|
|
1088
1106
|
// memory_plan_save — Save current plan/state for session resumption
|
|
1089
|
-
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.", {
|
|
1090
1108
|
session_id: z.string().optional().describe("Session identifier (default: 'default')"),
|
|
1091
1109
|
state: z.record(z.string(), z.unknown()).describe("State to save: {plan: [...], cursor: 3, active_goal: '...', last_action: '...', files_read: [...]}"),
|
|
1092
1110
|
}, async (args) => {
|
|
@@ -1102,7 +1120,7 @@ server.tool("memory_plan_save", "Save your current work state (plan steps, curso
|
|
|
1102
1120
|
}
|
|
1103
1121
|
});
|
|
1104
1122
|
// memory_plan_resume — Restore saved state from previous session
|
|
1105
|
-
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.", {
|
|
1106
1124
|
session_id: z.string().optional().describe("Session identifier (default: 'default')"),
|
|
1107
1125
|
}, async (args) => {
|
|
1108
1126
|
try {
|
|
@@ -1116,7 +1134,7 @@ server.tool("memory_plan_resume", "Restore your work state from a previous sessi
|
|
|
1116
1134
|
}
|
|
1117
1135
|
});
|
|
1118
1136
|
// memory_goal_track — Create/update/query goals
|
|
1119
|
-
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).", {
|
|
1120
1138
|
action: z.enum(["create", "update", "list"]).describe("Action to perform"),
|
|
1121
1139
|
title: z.string().optional().describe("Goal title (for create)"),
|
|
1122
1140
|
progress: z.number().optional().describe("Progress 0.0-1.0 (for update)"),
|
|
@@ -1154,7 +1172,7 @@ server.tool("memory_goal_track", "Track goals across sessions. Create new goals,
|
|
|
1154
1172
|
}
|
|
1155
1173
|
});
|
|
1156
1174
|
// memory_thought_log — Query what the brain has been thinking about
|
|
1157
|
-
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.", {
|
|
1158
1176
|
limit: z.number().optional().describe("Max thoughts to return (default 5)"),
|
|
1159
1177
|
}, async (args) => {
|
|
1160
1178
|
try {
|
|
@@ -1171,7 +1189,7 @@ server.tool("memory_thought_log", "See what the brain has been thinking about au
|
|
|
1171
1189
|
}
|
|
1172
1190
|
});
|
|
1173
1191
|
// memory_feedback — Report recall quality for self-improvement
|
|
1174
|
-
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.", {
|
|
1175
1193
|
query: z.string().describe("The recall query that was made"),
|
|
1176
1194
|
chunk_ids: z.array(z.number()).describe("IDs of chunks that were returned"),
|
|
1177
1195
|
helpful: z.boolean().describe("Were the results helpful for your task?"),
|
|
@@ -1191,7 +1209,7 @@ server.tool("memory_feedback", "Report whether recall results were helpful. This
|
|
|
1191
1209
|
}
|
|
1192
1210
|
});
|
|
1193
1211
|
// memory_predict — Predictive recall (push intent, get predicted memories)
|
|
1194
|
-
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.", {
|
|
1195
1213
|
intent: z.string().describe("What you/user are about to do"),
|
|
1196
1214
|
context: z.string().optional().describe("Current conversation context (helps prediction accuracy)"),
|
|
1197
1215
|
limit: z.number().optional().describe("Max predictions (default 5)"),
|
|
@@ -1214,7 +1232,7 @@ server.tool("memory_predict", "Predictive recall — tell the brain what you're
|
|
|
1214
1232
|
}
|
|
1215
1233
|
});
|
|
1216
1234
|
// memory_changelog — What changed since last session
|
|
1217
|
-
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.", {
|
|
1218
1236
|
since: z.string().describe("ISO datetime — show changes after this time (e.g. '2026-05-20T10:00:00Z')"),
|
|
1219
1237
|
project_id: z.string().optional().describe("Filter to specific project"),
|
|
1220
1238
|
limit: z.number().optional().describe("Max changes to return (default 50)"),
|
|
@@ -1237,7 +1255,7 @@ server.tool("memory_changelog", "See what changed in your memory since your last
|
|
|
1237
1255
|
}
|
|
1238
1256
|
});
|
|
1239
1257
|
// memory_cognitive_profile — Complete self-model (metacognition)
|
|
1240
|
-
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 () => {
|
|
1241
1259
|
try {
|
|
1242
1260
|
const r = (await api("GET", "/v1/personality/cognitive-profile"));
|
|
1243
1261
|
let out = `## Cognitive Profile\n\n`;
|
|
@@ -1260,7 +1278,7 @@ server.tool("memory_cognitive_profile", "Get the brain's complete self-model: wh
|
|
|
1260
1278
|
}
|
|
1261
1279
|
});
|
|
1262
1280
|
// memory_entity_profile — Get everything known about an entity
|
|
1263
|
-
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.", {
|
|
1264
1282
|
name: z.string().describe("Entity name to look up (e.g. 'Sarah', 'React', 'AuthService')"),
|
|
1265
1283
|
}, async (args) => {
|
|
1266
1284
|
try {
|
|
@@ -1289,6 +1307,337 @@ server.tool("memory_entity_profile", "Get complete profile for a specific entity
|
|
|
1289
1307
|
return err(e);
|
|
1290
1308
|
}
|
|
1291
1309
|
});
|
|
1310
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1311
|
+
// PHASE 5 (2026-05-28) — DNA-aligned tools:
|
|
1312
|
+
// • brain_export / brain_import — DNA #3 vendor neutrality
|
|
1313
|
+
// • benchmark_recall_vs_full — DNA #2 retina (measurable moat)
|
|
1314
|
+
// • benchmark_pricing — public model pricing reference
|
|
1315
|
+
// • trust_agents / trust_chunk — DNA #1.5 trust graph
|
|
1316
|
+
// • twin_respond / twin_status — Cognitive Twin (promax+ tier)
|
|
1317
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1318
|
+
// brain_export
|
|
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
|
+
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
|
+
since: z.string().optional().describe("ISO8601 datetime, only used when scope='since'"),
|
|
1322
|
+
}, async (args) => {
|
|
1323
|
+
try {
|
|
1324
|
+
const r = (await api("POST", "/v1/brain/export", {
|
|
1325
|
+
scope: args.scope || "full",
|
|
1326
|
+
since: args.since,
|
|
1327
|
+
}));
|
|
1328
|
+
const counts = r?.manifest?.counts || {};
|
|
1329
|
+
const summary = `Exported brain bundle (format=${r.format} v${r.version}):\n` +
|
|
1330
|
+
`- chunks: ${counts.chunks ?? 0}\n` +
|
|
1331
|
+
`- memory_edges: ${counts.memory_edges ?? 0}\n` +
|
|
1332
|
+
`- entities: ${counts.entities ?? 0}\n` +
|
|
1333
|
+
`- l2_sessions: ${counts.l2_sessions ?? 0}\n` +
|
|
1334
|
+
`- agents: ${counts.agents ?? 0}\n` +
|
|
1335
|
+
`- checksum: ${r?.manifest?.checksum?.slice(0, 16)}...\n\n` +
|
|
1336
|
+
`Bundle JSON ready (truncated preview):\n\`\`\`json\n${JSON.stringify(r, null, 2).slice(0, 1200)}...\n\`\`\``;
|
|
1337
|
+
return ok(summary);
|
|
1338
|
+
}
|
|
1339
|
+
catch (e) {
|
|
1340
|
+
return err(e);
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1343
|
+
// brain_import
|
|
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
|
+
bundle: z.record(z.string(), z.unknown()).describe("The bundle JSON produced by brain_export (must contain format='memoryai-bundle', version, manifest, etc.)"),
|
|
1346
|
+
keep_embeddings: z.boolean().optional().describe("Reuse bundle embeddings if model matches (default: true)"),
|
|
1347
|
+
}, async (args) => {
|
|
1348
|
+
try {
|
|
1349
|
+
const r = (await api("POST", `/v1/brain/import?keep_embeddings=${args.keep_embeddings === false ? "false" : "true"}`, args.bundle));
|
|
1350
|
+
const rep = r?.report || {};
|
|
1351
|
+
const out = `Brain import complete (format=${rep.bundle_format} v${rep.bundle_version}):\n` +
|
|
1352
|
+
`- chunks: ${rep.chunks?.inserted ?? 0} inserted, ${rep.chunks?.skipped_duplicate ?? 0} skipped (dup), ${rep.chunks?.skipped_invalid ?? 0} invalid\n` +
|
|
1353
|
+
`- memory_edges: ${rep.memory_edges?.upserted ?? 0} upserted (${rep.memory_edges?.skipped ?? 0} skipped)\n` +
|
|
1354
|
+
`- entities: ${rep.entities?.upserted ?? 0} upserted\n` +
|
|
1355
|
+
`- l2_sessions: ${rep.l2_sessions?.inserted ?? 0} inserted\n` +
|
|
1356
|
+
`- agents: ${rep.agents?.upserted ?? 0} upserted\n` +
|
|
1357
|
+
`- embedding_model_match: ${rep.embedding_model_match}\n` +
|
|
1358
|
+
(rep.warnings?.length ? `\nWarnings:\n ${rep.warnings.join("\n ")}` : "");
|
|
1359
|
+
return ok(out);
|
|
1360
|
+
}
|
|
1361
|
+
catch (e) {
|
|
1362
|
+
return err(e);
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
// benchmark_recall_vs_full
|
|
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
|
+
query: z.string().describe("The query to benchmark (e.g. 'what does the user prefer?')"),
|
|
1368
|
+
model: z.string().optional().describe("Model whose pricing to apply (default: claude-opus-4-6). Affects $cost only."),
|
|
1369
|
+
naive_budget_tokens: z.number().optional().describe("Cap on full-context dump (default: 200K = Claude window)"),
|
|
1370
|
+
smart_top_k: z.number().optional().describe("Top-K chunks for smart mode (default: 8)"),
|
|
1371
|
+
smart_depth: z.enum(["instant", "fast", "deep"]).optional().describe("Smart recall depth (default: deep)"),
|
|
1372
|
+
}, async (args) => {
|
|
1373
|
+
try {
|
|
1374
|
+
const r = (await api("POST", "/v1/benchmark/recall-vs-fullcontext", {
|
|
1375
|
+
query: args.query,
|
|
1376
|
+
model: args.model || "claude-opus-4-6",
|
|
1377
|
+
naive_budget_tokens: args.naive_budget_tokens,
|
|
1378
|
+
smart_top_k: args.smart_top_k,
|
|
1379
|
+
smart_depth: args.smart_depth,
|
|
1380
|
+
}));
|
|
1381
|
+
const out = `Benchmark — query: ${JSON.stringify(r.query)}\n` +
|
|
1382
|
+
`Model: ${r.model} ($${r.price_per_m_tokens_usd}/M tokens)\n\n` +
|
|
1383
|
+
`NAIVE: ${r.naive.chunks_used} chunks · ${r.naive.input_tokens} tok · $${r.naive.estimated_cost_usd} · ${r.naive.latency_ms}ms\n` +
|
|
1384
|
+
`SMART: ${r.smart.chunks_used} chunks · ${r.smart.input_tokens} tok · $${r.smart.estimated_cost_usd} · ${r.smart.latency_ms}ms\n\n` +
|
|
1385
|
+
`→ ${r.headline}`;
|
|
1386
|
+
return ok(out);
|
|
1387
|
+
}
|
|
1388
|
+
catch (e) {
|
|
1389
|
+
return err(e);
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1392
|
+
// benchmark_pricing
|
|
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
|
+
try {
|
|
1395
|
+
const r = (await api("GET", "/v1/benchmark/pricing"));
|
|
1396
|
+
const lines = Object.entries(r.prices || {}).map(([k, v]) => `- ${k}: $${v}`);
|
|
1397
|
+
return ok(`Model pricing (${r.currency} ${r.unit}, as of ${r.as_of}):\n${lines.join("\n")}\n\nNote: ${r.note}`);
|
|
1398
|
+
}
|
|
1399
|
+
catch (e) {
|
|
1400
|
+
return err(e);
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
// trust_agents
|
|
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
|
+
limit: z.number().optional().describe("Max agents to return (default: 50, max: 500)"),
|
|
1406
|
+
}, async (args) => {
|
|
1407
|
+
try {
|
|
1408
|
+
const r = (await api("GET", `/v1/trust/agents?limit=${args.limit ?? 50}`));
|
|
1409
|
+
if (!r.agents?.length)
|
|
1410
|
+
return ok("No agent reputation snapshots yet. Run /v1/trust/recompute-all to populate.");
|
|
1411
|
+
const lines = r.agents.map((a) => `- ${a.agent_id}: ${a.reputation_score.toFixed(3)} [${a.label}] — V=${a.verified_count}/C=${a.contradicted_count}/N=${a.feedback_n}`);
|
|
1412
|
+
return ok(`Agent reputation (${r.agents.length} agents):\n${lines.join("\n")}`);
|
|
1413
|
+
}
|
|
1414
|
+
catch (e) {
|
|
1415
|
+
return err(e);
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
// trust_chunk
|
|
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
|
+
chunk_id: z.number().describe("The chunk ID returned by recall"),
|
|
1421
|
+
}, async (args) => {
|
|
1422
|
+
try {
|
|
1423
|
+
const r = (await api("GET", `/v1/trust/chunks/${args.chunk_id}`));
|
|
1424
|
+
const stats = r.agent_stats || {};
|
|
1425
|
+
const fb = r.feedback || {};
|
|
1426
|
+
return ok(`Chunk #${r.chunk_id} (${r.memory_type})\n` +
|
|
1427
|
+
`Source agent: ${r.source_agent_id ?? "(none)"}\n` +
|
|
1428
|
+
`Agent trust: ${r.agent_trust?.toFixed(3) ?? "(none)"} — V=${stats.verified_count ?? 0}/C=${stats.contradicted_count ?? 0}/total=${stats.claim_count ?? 0}\n` +
|
|
1429
|
+
`Per-chunk trust: ${r.chunk_trust_score?.toFixed(3) ?? "(none)"} (helpful=${fb.helpful ?? 0}, unhelpful=${fb.unhelpful ?? 0})`);
|
|
1430
|
+
}
|
|
1431
|
+
catch (e) {
|
|
1432
|
+
return err(e);
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1435
|
+
// twin_respond
|
|
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
|
+
query: z.string().describe("The free-form question to ask the twin (e.g. 'what database for a chat app?')"),
|
|
1438
|
+
operation: z.enum(["respond", "decide"]).optional().describe("'respond'=free-form answer (default), 'decide'=pick one option from the query"),
|
|
1439
|
+
}, async (args) => {
|
|
1440
|
+
try {
|
|
1441
|
+
const path = args.operation === "decide" ? "/v1/twin/decide" : "/v1/twin/respond";
|
|
1442
|
+
const r = (await api("POST", path, { query: args.query }));
|
|
1443
|
+
const out = `Cognitive Twin (${r.operation}, confidence ${r.confidence}):\n` +
|
|
1444
|
+
`Persona: ${r.persona_summary || "(not synthesized)"}\n` +
|
|
1445
|
+
`Mood: ${r.mood || "unknown"}\n` +
|
|
1446
|
+
`Provenance chunks: ${r.provenance_chunks?.length ?? 0}\n\n` +
|
|
1447
|
+
`Response:\n${r.response}\n\n` +
|
|
1448
|
+
`(reason: ${r.confidence_reason})`;
|
|
1449
|
+
return ok(out);
|
|
1450
|
+
}
|
|
1451
|
+
catch (e) {
|
|
1452
|
+
return err(e);
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
// twin_status
|
|
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
|
+
try {
|
|
1458
|
+
const r = (await api("GET", "/v1/twin/status"));
|
|
1459
|
+
return ok(`Twin ready: ${r.ready ? "YES" : "NO"} (need ≥${r.min_dna_required} DNA, have ${r.dna_count})\n` +
|
|
1460
|
+
`- has_personality: ${r.has_personality}\n` +
|
|
1461
|
+
`- has_mood: ${r.has_mood}\n` +
|
|
1462
|
+
`- procedures: ${r.procedures_count}\n` +
|
|
1463
|
+
`- active_goals: ${r.active_goals_count}\n` +
|
|
1464
|
+
`- top_entities: ${r.top_entities_count}\n` +
|
|
1465
|
+
(r.persona_summary ? `\nPersona: ${r.persona_summary}\n` : "") +
|
|
1466
|
+
(r.mood ? `Mood: ${r.mood}\n` : ""));
|
|
1467
|
+
}
|
|
1468
|
+
catch (e) {
|
|
1469
|
+
return err(e);
|
|
1470
|
+
}
|
|
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
|
+
});
|
|
1292
1641
|
async function main() {
|
|
1293
1642
|
const transport = new StdioServerTransport();
|
|
1294
1643
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memoryai-mcp",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "MCP server for MemoryAI —
|
|
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",
|