@exaudeus/memory-mcp 1.9.0 → 1.9.2
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 +58 -28
- package/dist/normalize.js +35 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -215,7 +215,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
215
215
|
// --- Retrieval ---
|
|
216
216
|
{
|
|
217
217
|
name: 'brief',
|
|
218
|
-
description:
|
|
218
|
+
description: `Session-start briefing for a project. Returns everything stored via learn/gotcha/convention/prefer — preferences, gotchas, stale entries, counts. Call once at conversation start. Usage: {"lobe": "${currentLobeNames[0] ?? 'my-project'}"}`,
|
|
219
219
|
inputSchema: {
|
|
220
220
|
type: 'object',
|
|
221
221
|
properties: {
|
|
@@ -226,18 +226,18 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
name: 'recall',
|
|
229
|
-
description:
|
|
229
|
+
description: `Search your stored memory entries (from learn/gotcha/convention/prefer) — architecture notes, conventions, gotchas, decisions — by relevance using semantic + keyword matching. Does NOT search the codebase itself. Use BEFORE starting a task to surface prior knowledge. Usage: {"context": "auth token refresh", "lobe": "${currentLobeNames[0] ?? 'my-project'}"}`,
|
|
230
230
|
inputSchema: {
|
|
231
231
|
type: 'object',
|
|
232
232
|
properties: {
|
|
233
233
|
lobe: lobeProperty,
|
|
234
234
|
context: {
|
|
235
235
|
type: 'string',
|
|
236
|
-
description: '
|
|
236
|
+
description: 'The topic or area you need knowledge about. Describe in natural language — e.g. "auth token refresh", "how modules communicate", "payment webhook handler".',
|
|
237
237
|
},
|
|
238
238
|
maxResults: {
|
|
239
239
|
type: 'number',
|
|
240
|
-
description: 'Max results (default: 10)',
|
|
240
|
+
description: 'Max results (default: 10).',
|
|
241
241
|
default: 10,
|
|
242
242
|
},
|
|
243
243
|
},
|
|
@@ -246,14 +246,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
246
246
|
},
|
|
247
247
|
{
|
|
248
248
|
name: 'gotchas',
|
|
249
|
-
description:
|
|
249
|
+
description: `Retrieve stored gotchas (pitfalls, traps, surprising behaviors) for a project. Check BEFORE making changes. Optionally filter by area. Usage: {"lobe": "${currentLobeNames[0] ?? 'my-project'}", "area": "auth"} or {"lobe": "${currentLobeNames[0] ?? 'my-project'}"} for all.`,
|
|
250
250
|
inputSchema: {
|
|
251
251
|
type: 'object',
|
|
252
252
|
properties: {
|
|
253
253
|
lobe: lobeProperty,
|
|
254
254
|
area: {
|
|
255
255
|
type: 'string',
|
|
256
|
-
description: 'Optional keyword filter
|
|
256
|
+
description: 'Optional keyword filter (e.g. "auth", "build", "navigation").',
|
|
257
257
|
},
|
|
258
258
|
},
|
|
259
259
|
required: [],
|
|
@@ -261,14 +261,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
263
|
name: 'conventions',
|
|
264
|
-
description:
|
|
264
|
+
description: `Retrieve stored conventions (coding patterns, naming rules, architectural standards) for a project. Check BEFORE writing code. Optionally filter by area. Usage: {"lobe": "${currentLobeNames[0] ?? 'my-project'}", "area": "testing"} or {"lobe": "${currentLobeNames[0] ?? 'my-project'}"} for all.`,
|
|
265
265
|
inputSchema: {
|
|
266
266
|
type: 'object',
|
|
267
267
|
properties: {
|
|
268
268
|
lobe: lobeProperty,
|
|
269
269
|
area: {
|
|
270
270
|
type: 'string',
|
|
271
|
-
description: 'Optional keyword filter
|
|
271
|
+
description: 'Optional keyword filter (e.g. "testing", "naming", "architecture").',
|
|
272
272
|
},
|
|
273
273
|
},
|
|
274
274
|
required: [],
|
|
@@ -277,14 +277,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
277
277
|
// --- Storage ---
|
|
278
278
|
{
|
|
279
279
|
name: 'gotcha',
|
|
280
|
-
description:
|
|
280
|
+
description: `Store a pitfall, surprising behavior, or trap you discovered in the codebase. Persists across sessions, surfaces in brief() and recall(). Write naturally; first sentence becomes the title. Usage: {"lobe": "${currentLobeNames[0] ?? 'my-project'}", "observation": "Gradle cache must be cleaned after Tuist changes or builds silently use stale artifacts"}`,
|
|
281
281
|
inputSchema: {
|
|
282
282
|
type: 'object',
|
|
283
283
|
properties: {
|
|
284
284
|
lobe: lobeProperty,
|
|
285
285
|
observation: {
|
|
286
286
|
type: 'string',
|
|
287
|
-
description: 'The gotcha
|
|
287
|
+
description: 'The gotcha. Write naturally — first sentence becomes the title.',
|
|
288
288
|
},
|
|
289
289
|
durabilityDecision: {
|
|
290
290
|
type: 'string',
|
|
@@ -298,14 +298,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
298
298
|
},
|
|
299
299
|
{
|
|
300
300
|
name: 'convention',
|
|
301
|
-
description:
|
|
301
|
+
description: `Store a coding pattern or standard the codebase follows. Persists across sessions, surfaces in brief() and recall(). Write naturally; first sentence becomes the title. Usage: {"lobe": "${currentLobeNames[0] ?? 'my-project'}", "observation": "All ViewModels use StateFlow for UI state. LiveData is banned."}`,
|
|
302
302
|
inputSchema: {
|
|
303
303
|
type: 'object',
|
|
304
304
|
properties: {
|
|
305
305
|
lobe: lobeProperty,
|
|
306
306
|
observation: {
|
|
307
307
|
type: 'string',
|
|
308
|
-
description: 'The convention
|
|
308
|
+
description: 'The convention. Write naturally — first sentence becomes the title.',
|
|
309
309
|
},
|
|
310
310
|
durabilityDecision: {
|
|
311
311
|
type: 'string',
|
|
@@ -319,14 +319,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
319
319
|
},
|
|
320
320
|
{
|
|
321
321
|
name: 'learn',
|
|
322
|
-
description:
|
|
322
|
+
description: `Store codebase knowledge — architecture, module boundaries, dependencies, or any insight not covered by gotcha/convention. Catch-all for durable project knowledge. Persists across sessions, surfaces in brief() and recall(). Write naturally; first sentence becomes the title. Usage: {"lobe": "${currentLobeNames[0] ?? 'my-project'}", "observation": "Payments module depends on auth for tokens only — no other cross-module dependency"}`,
|
|
323
323
|
inputSchema: {
|
|
324
324
|
type: 'object',
|
|
325
325
|
properties: {
|
|
326
326
|
lobe: lobeProperty,
|
|
327
327
|
observation: {
|
|
328
328
|
type: 'string',
|
|
329
|
-
description: 'The observation
|
|
329
|
+
description: 'The observation. Write naturally — first sentence becomes the title.',
|
|
330
330
|
},
|
|
331
331
|
durabilityDecision: {
|
|
332
332
|
type: 'string',
|
|
@@ -340,17 +340,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
340
340
|
},
|
|
341
341
|
{
|
|
342
342
|
name: 'prefer',
|
|
343
|
-
description:
|
|
343
|
+
description: `Store a user preference or working-style rule — when the user corrects you or states how they want things done. Highest trust, surfaced in every brief(). Omit lobe for global. Usage: {"rule": "Never use !! operator"} or {"rule": "Use Anvil for DI", "lobe": "${currentLobeNames[0] ?? 'my-project'}"}`,
|
|
344
344
|
inputSchema: {
|
|
345
345
|
type: 'object',
|
|
346
346
|
properties: {
|
|
347
347
|
rule: {
|
|
348
348
|
type: 'string',
|
|
349
|
-
description: 'The preference or rule
|
|
349
|
+
description: 'The preference or rule. Write naturally.',
|
|
350
350
|
},
|
|
351
351
|
lobe: {
|
|
352
352
|
...lobeProperty,
|
|
353
|
-
description: `Optional.
|
|
353
|
+
description: `Optional. Scope this preference to a specific lobe. Omit for global. Available: ${currentLobeNames.join(', ')}`,
|
|
354
354
|
},
|
|
355
355
|
},
|
|
356
356
|
required: ['rule'],
|
|
@@ -359,17 +359,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
359
359
|
// --- Maintenance ---
|
|
360
360
|
{
|
|
361
361
|
name: 'fix',
|
|
362
|
-
description:
|
|
362
|
+
description: `Correct or delete a stored memory entry. IDs appear in brief/recall/gotchas/conventions results. Pass correction to update; omit correction to delete. Usage: {"id": "gotcha-3f7a", "correction": "Updated: cache must be cleaned after ANY dependency change"} or {"id": "gotcha-3f7a"} to delete.`,
|
|
363
363
|
inputSchema: {
|
|
364
364
|
type: 'object',
|
|
365
365
|
properties: {
|
|
366
366
|
id: {
|
|
367
367
|
type: 'string',
|
|
368
|
-
description: 'Entry ID (e.g. gotcha-3f7a,
|
|
368
|
+
description: 'Entry ID (e.g. gotcha-3f7a, conv-5c9b, gen-a2d1, pref-8e4f).',
|
|
369
369
|
},
|
|
370
370
|
correction: {
|
|
371
371
|
type: 'string',
|
|
372
|
-
description: 'New text. Omit to delete the entry.',
|
|
372
|
+
description: 'New text to replace the entry content. Omit entirely to delete the entry.',
|
|
373
373
|
},
|
|
374
374
|
lobe: {
|
|
375
375
|
...lobeProperty,
|
|
@@ -384,7 +384,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
384
384
|
// but are hidden from tool discovery. Agents use the new v2 tools above.
|
|
385
385
|
{
|
|
386
386
|
name: 'memory_bootstrap',
|
|
387
|
-
description: 'First-time setup:
|
|
387
|
+
description: 'First-time setup: scans repo structure, README, and build system to seed initial memory. Run once per project. Provide "root" to auto-create a new lobe.',
|
|
388
388
|
inputSchema: {
|
|
389
389
|
type: 'object',
|
|
390
390
|
properties: {
|
|
@@ -1547,20 +1547,50 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1547
1547
|
}
|
|
1548
1548
|
catch (error) {
|
|
1549
1549
|
const message = error instanceof Error ? error.message : String(error);
|
|
1550
|
-
// Provide helpful hints for
|
|
1550
|
+
// Provide helpful, human-readable hints for Zod validation errors.
|
|
1551
|
+
// Raw Zod JSON is cryptic for agents — translate to actionable guidance.
|
|
1552
|
+
const lobeNames = configManager.getLobeNames();
|
|
1553
|
+
const lobeList = lobeNames.join(', ');
|
|
1554
|
+
let friendlyMessage = message;
|
|
1555
|
+
// Detect Zod validation errors (they contain path arrays in JSON)
|
|
1556
|
+
if (message.includes('"path"') && message.includes('"message"')) {
|
|
1557
|
+
// Build a friendlyMessage from the Zod issues
|
|
1558
|
+
try {
|
|
1559
|
+
const issues = JSON.parse(message);
|
|
1560
|
+
const fields = issues.map(i => `${i.path.join('.')}: ${i.message}`).join(', ');
|
|
1561
|
+
friendlyMessage = `Invalid arguments — ${fields}`;
|
|
1562
|
+
}
|
|
1563
|
+
catch {
|
|
1564
|
+
// If parsing fails, keep original message
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
// Tool-specific hints based on which field failed
|
|
1551
1568
|
let hint = '';
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1569
|
+
const v2ToolHints = {
|
|
1570
|
+
brief: `brief takes an optional lobe. Example: {"lobe": "${lobeNames[0] ?? 'default'}"}. Available lobes: ${lobeList}`,
|
|
1571
|
+
recall: `recall requires "context" (describe what you are working on). Example: {"context": "implementing auth flow", "lobe": "${lobeNames[0] ?? 'default'}"}. Available lobes: ${lobeList}`,
|
|
1572
|
+
gotcha: `gotcha requires "lobe" and "observation". Example: {"lobe": "${lobeNames[0] ?? 'default'}", "observation": "Gradle cache breaks after Tuist changes"}`,
|
|
1573
|
+
convention: `convention requires "lobe" and "observation". Example: {"lobe": "${lobeNames[0] ?? 'default'}", "observation": "All ViewModels use StateFlow"}`,
|
|
1574
|
+
learn: `learn requires "lobe" and "observation". Example: {"lobe": "${lobeNames[0] ?? 'default'}", "observation": "Messaging uses MVVM with FlowCoordinator"}`,
|
|
1575
|
+
prefer: `prefer requires "rule". Example: {"rule": "Always suggest the simplest solution first"}`,
|
|
1576
|
+
fix: `fix requires "id". Optional: "correction" (new text; omit to delete). Example: {"id": "gotcha-3f7a", "correction": "updated text"}`,
|
|
1577
|
+
gotchas: `gotchas takes optional "lobe" and "area". Example: {"lobe": "${lobeNames[0] ?? 'default'}", "area": "auth"}. Available lobes: ${lobeList}`,
|
|
1578
|
+
conventions: `conventions takes optional "lobe" and "area". Example: {"lobe": "${lobeNames[0] ?? 'default'}", "area": "testing"}. Available lobes: ${lobeList}`,
|
|
1579
|
+
};
|
|
1580
|
+
if (name in v2ToolHints) {
|
|
1581
|
+
hint = `\n\nUsage: ${v2ToolHints[name]}`;
|
|
1582
|
+
}
|
|
1583
|
+
else if (friendlyMessage.includes('"lobe"') || friendlyMessage.includes('lobe:')) {
|
|
1584
|
+
hint = `\n\nHint: lobe is required. Available: ${lobeList}`;
|
|
1555
1585
|
}
|
|
1556
1586
|
else if (message.includes('"topic"') || message.includes('"entries"')) {
|
|
1557
|
-
hint = '\n\nHint: memory_store requires: topic (architecture|conventions|gotchas|recent-work|modules/<name>) and entries (Array<{title, fact}>).
|
|
1587
|
+
hint = '\n\nHint: memory_store requires: topic (architecture|conventions|gotchas|general|recent-work|modules/<name>) and entries (Array<{title, fact}>).';
|
|
1558
1588
|
}
|
|
1559
1589
|
else if (message.includes('"scope"')) {
|
|
1560
|
-
hint = '\n\nHint: memory_query requires:
|
|
1590
|
+
hint = '\n\nHint: memory_query requires: scope (architecture|conventions|gotchas|*). Example: memory_query(scope: "*")';
|
|
1561
1591
|
}
|
|
1562
1592
|
return {
|
|
1563
|
-
content: [{ type: 'text', text:
|
|
1593
|
+
content: [{ type: 'text', text: `${friendlyMessage}${hint}` }],
|
|
1564
1594
|
isError: true,
|
|
1565
1595
|
};
|
|
1566
1596
|
}
|
package/dist/normalize.js
CHANGED
|
@@ -3,17 +3,10 @@
|
|
|
3
3
|
// Agents frequently guess wrong param names. This module resolves common aliases
|
|
4
4
|
// and applies defaults to avoid wasted round-trips from validation errors.
|
|
5
5
|
// Pure functions — no side effects, no state.
|
|
6
|
-
/**
|
|
7
|
-
const
|
|
6
|
+
/** Global param aliases — apply to all tools regardless of name */
|
|
7
|
+
const GLOBAL_ALIASES = {
|
|
8
8
|
// memory_store aliases
|
|
9
9
|
refs: 'references',
|
|
10
|
-
// memory_query aliases
|
|
11
|
-
query: 'filter',
|
|
12
|
-
search: 'filter',
|
|
13
|
-
keyword: 'filter',
|
|
14
|
-
// memory_context aliases
|
|
15
|
-
description: 'context',
|
|
16
|
-
task: 'context',
|
|
17
10
|
// tag aliases
|
|
18
11
|
tag: 'tags',
|
|
19
12
|
labels: 'tags',
|
|
@@ -22,6 +15,28 @@ const PARAM_ALIASES = {
|
|
|
22
15
|
workspace: 'lobe',
|
|
23
16
|
repo: 'lobe',
|
|
24
17
|
};
|
|
18
|
+
/** Tool-specific param aliases — only apply when the tool name matches.
|
|
19
|
+
* Prevents `query` → `filter` rewriting from breaking `recall(query: "...")`. */
|
|
20
|
+
const TOOL_ALIASES = {
|
|
21
|
+
// Legacy tools: "query" means "filter"
|
|
22
|
+
memory_query: { query: 'filter', search: 'filter', keyword: 'filter' },
|
|
23
|
+
memory_store: { scope: 'topic' },
|
|
24
|
+
// Legacy tools: "description"/"task" mean "context"
|
|
25
|
+
memory_context: { description: 'context', task: 'context' },
|
|
26
|
+
// v2 retrieval tools: "query"/"search"/"description"/"task" mean "context"
|
|
27
|
+
recall: { query: 'context', search: 'context', description: 'context', task: 'context' },
|
|
28
|
+
// v2 storage tools: "content"/"note"/"fact" mean "observation"
|
|
29
|
+
gotcha: { content: 'observation', note: 'observation', fact: 'observation', message: 'observation' },
|
|
30
|
+
convention: { content: 'observation', note: 'observation', fact: 'observation', message: 'observation' },
|
|
31
|
+
learn: { content: 'observation', note: 'observation', fact: 'observation', message: 'observation' },
|
|
32
|
+
// v2 prefer: "preference"/"pref" mean "rule"
|
|
33
|
+
prefer: { preference: 'rule', pref: 'rule' },
|
|
34
|
+
// v2 fix: "text"/"content"/"replacement" mean "correction"
|
|
35
|
+
fix: { text: 'correction', content: 'correction', replacement: 'correction' },
|
|
36
|
+
// v2 retrieval: "filter"/"keyword" mean "area"
|
|
37
|
+
gotchas: { filter: 'area', keyword: 'area', query: 'area', search: 'area' },
|
|
38
|
+
conventions: { filter: 'area', keyword: 'area', query: 'area', search: 'area' },
|
|
39
|
+
};
|
|
25
40
|
/** Wildcard scope aliases — agents guess many variations instead of "*" */
|
|
26
41
|
const SCOPE_WILDCARDS = new Set([
|
|
27
42
|
'all', 'everything', 'any', '*', 'global', 'project', 'repo',
|
|
@@ -30,17 +45,22 @@ const SCOPE_WILDCARDS = new Set([
|
|
|
30
45
|
/** Normalize args before Zod validation: resolve aliases, default workspace, fix wildcards */
|
|
31
46
|
export function normalizeArgs(toolName, raw, lobeNames) {
|
|
32
47
|
const args = { ...(raw ?? {}) };
|
|
33
|
-
// 1. Resolve param aliases
|
|
34
|
-
for (const [alias, canonical] of Object.entries(
|
|
48
|
+
// 1. Resolve global param aliases
|
|
49
|
+
for (const [alias, canonical] of Object.entries(GLOBAL_ALIASES)) {
|
|
35
50
|
if (alias in args && !(canonical in args)) {
|
|
36
51
|
args[canonical] = args[alias];
|
|
37
52
|
delete args[alias];
|
|
38
53
|
}
|
|
39
54
|
}
|
|
40
|
-
// 2.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
// 2. Resolve tool-specific param aliases
|
|
56
|
+
const toolSpecific = TOOL_ALIASES[toolName];
|
|
57
|
+
if (toolSpecific) {
|
|
58
|
+
for (const [alias, canonical] of Object.entries(toolSpecific)) {
|
|
59
|
+
if (alias in args && !(canonical in args)) {
|
|
60
|
+
args[canonical] = args[alias];
|
|
61
|
+
delete args[alias];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
44
64
|
}
|
|
45
65
|
// 3. Default lobe to the only available one when omitted
|
|
46
66
|
if (!('lobe' in args) || args['lobe'] === undefined || args['lobe'] === '') {
|