@mnemoverse/mcp-memory-server 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -199,7 +199,8 @@ If it doesn't remember: check that the client was fully restarted and the config
199
199
  | Tool | What it does |
200
200
  |------|-------------|
201
201
  | `memory_write` | Store a memory — insight, preference, lesson learned |
202
- | `memory_read` | Search memories by natural language query |
202
+ | `memory_read` | Search memories by natural language query (optional recency ordering, time bounds, author exclusion) |
203
+ | `memory_list_recent` | List newest memories first — no query; `since` watermark + cursor paging |
203
204
  | `memory_feedback` | Rate memories as helpful or not (improves future recall) |
204
205
  | `memory_stats` | Check how many memories stored, which domains exist |
205
206
  | `memory_delete` | Permanently delete a single memory by `atom_id` |
package/dist/index.js CHANGED
@@ -3,6 +3,8 @@ import { createRequire } from "node:module";
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
5
  import { z } from "zod";
6
+ import { formatReadItem, formatRecentPage, safeInline, } from "./render.js";
7
+ import { SERVER_INSTRUCTIONS, buildReadEmptyResponse } from "./teaching.js";
6
8
  // Version is read at runtime from package.json so there is exactly one place
7
9
  // to bump on each release. Works both from `dist/` during local dev and from
8
10
  // `node_modules/@mnemoverse/mcp-memory-server/dist/` after an npm install.
@@ -67,7 +69,7 @@ async function apiFetch(path, options = {}) {
67
69
  * result stays well-formed. Otherwise an emoji or non-BMP character at the
68
70
  * boundary can produce a lone surrogate and corrupt downstream JSON encoding.
69
71
  */
70
- function capResult(text) {
72
+ function capResult(text, moreHint = "Use a more specific query or smaller top_k to see all results.") {
71
73
  if (text.length <= MAX_RESULT_CHARS)
72
74
  return text;
73
75
  let truncated = text.slice(0, MAX_RESULT_CHARS - 200);
@@ -75,8 +77,10 @@ function capResult(text) {
75
77
  if (lastCode >= 0xd800 && lastCode <= 0xdbff) {
76
78
  truncated = truncated.slice(0, -1);
77
79
  }
78
- return (truncated +
79
- `\n\n[…truncated to fit 25K token limit. Use a more specific query or smaller top_k to see all results.]`);
80
+ // `moreHint` lets no-input tools (the discovery lists) give accurate truncation
81
+ // guidance instead of the read-tool default (which points at query/top_k controls a
82
+ // repeated no-arg call cannot use). Existing callers keep the default message.
83
+ return `${truncated}\n\n[…truncated to fit the 25K token limit. ${moreHint}]`;
80
84
  }
81
85
  /**
82
86
  * Sanitize an untrusted string for safe inline rendering in tool output that a
@@ -85,22 +89,21 @@ function capResult(text) {
85
89
  * core only trims whitespace on it, so quotes/colons/newlines pass. Strip to a
86
90
  * conservative charset and collapse whitespace, then cap length. Same treatment
87
91
  * `formatAuthorTag` already applies to a server-stamped author.
92
+ * Implementation lives in src/render.ts (shared with the item renderers,
93
+ * testable there); re-imported here for the 15 other call sites.
88
94
  */
89
- function safeInline(s, cap = 200) {
90
- return (s ?? "")
91
- .replace(/[^\w .@:+/-]/g, " ")
92
- .replace(/\s+/g, " ")
93
- .trim()
94
- .slice(0, cap);
95
- }
96
95
  // --- Server setup ---
96
+ // The second argument lands verbatim in the connected model's system prompt on
97
+ // clients that surface MCP instructions — it is the single highest-leverage
98
+ // teaching surface this server has. Kept in src/teaching.ts so tests can
99
+ // assert its polarity/length without booting the server.
97
100
  const server = new McpServer({
98
101
  name: "mnemoverse-memory",
99
102
  version: pkg.version,
100
- });
103
+ }, { instructions: SERVER_INSTRUCTIONS });
101
104
  // --- Tool: memory_write ---
102
105
  server.registerTool("memory_write", {
103
- description: "Store a long-term memory that persists across sessions AND across every AI tool the user has connected to Mnemoverse (Claude, ChatGPT, Cursor, VS Code) — write once, recall everywhere. Call this PROACTIVELY the moment the user states a preference, makes a decision, or you learn a durable fact (people, roles, project setup, a lesson). Don't wait to be asked. Do NOT use it for transient chatter, secrets, or anything only relevant to the current turn. Behavior: an importance gate may filter low-value writes, so the result tells you whether the memory was stored or filtered. Write `content` as a self-contained statement that still makes sense when recalled out of context.",
106
+ description: "Store a long-term memory that persists across sessions AND across every AI tool the user has connected to Mnemoverse (Claude, ChatGPT, Cursor, VS Code) — write once, recall everywhere. Call this PROACTIVELY the moment the user states a preference, makes a decision, or you learn a durable fact (people, roles, project setup, a lesson). Don't wait to be asked. Never store passwords, API keys, payment data, MFA codes, government IDs, or health records; skip transient chatter that only matters this turn. Behavior: an importance gate may filter low-value writes, so the result tells you whether the memory was stored or filtered. Write `content` as a self-contained statement that still makes sense when recalled out of context.",
104
107
  inputSchema: {
105
108
  content: z
106
109
  .string()
@@ -154,7 +157,7 @@ server.registerTool("memory_write", {
154
157
  });
155
158
  // --- Tool: memory_read ---
156
159
  server.registerTool("memory_read", {
157
- description: "Search your long-term memory before answering anything that may have come up before — user preferences, past decisions, project setup, people, or earlier context. This memory is shared: it persists across sessions and across every AI tool the user has connected (Claude, ChatGPT, Cursor, VS Code). ALWAYS check here first when you're unsure whether you already know something; no need to call it for general world knowledge you already hold. Returns matches ranked by relevance (semantic similarity plus learned concept associations); each result carries an id you can pass to memory_feedback or memory_delete.",
160
+ description: "Search your long-term memory before answering anything that may have come up before — user preferences, past decisions, project setup, people, or earlier context. This memory is shared: it persists across sessions and across every AI tool the user has connected (Claude, ChatGPT, Cursor, VS Code). ALWAYS check here first when you're unsure whether you already know something; no need to call it for general world knowledge you already hold. Returns matches ranked by relevance (or newest-first with order_by: 'recency'); each result carries an id you can pass to memory_feedback or memory_delete.",
158
161
  inputSchema: {
159
162
  query: z
160
163
  .string()
@@ -172,6 +175,31 @@ server.registerTool("memory_read", {
172
175
  .string()
173
176
  .optional()
174
177
  .describe("Restrict the search to one domain namespace (e.g. 'project:acme'); omit to search across all domains."),
178
+ order_by: z
179
+ .enum(["relevance", "recency"])
180
+ .optional()
181
+ .describe("'relevance' (default) = ranking order. 'recency' = the matched " +
182
+ "set re-sorted newest-first. For a complete newest-first feed " +
183
+ "with no search at all, use memory_list_recent instead."),
184
+ since: z
185
+ .string()
186
+ .max(40)
187
+ .optional()
188
+ .describe("Only memories created at/after this ISO-8601 instant (naive = " +
189
+ "UTC) — e.g. your last-seen watermark in a shared room."),
190
+ until: z
191
+ .string()
192
+ .max(40)
193
+ .optional()
194
+ .describe("Only memories created at/before this ISO-8601 instant."),
195
+ exclude_author: z
196
+ .string()
197
+ .max(200)
198
+ .optional()
199
+ .describe("Drop memories written by this author PRINCIPAL (the server-side " +
200
+ "identity, not shown in these results). Useful when your system " +
201
+ "knows principals (e.g. via the REST API); a self-exclusion " +
202
+ "shortcut is planned server-side."),
175
203
  },
176
204
  annotations: {
177
205
  title: "Search Memories",
@@ -180,7 +208,7 @@ server.registerTool("memory_read", {
180
208
  idempotentHint: true,
181
209
  openWorldHint: true,
182
210
  },
183
- }, async ({ query, top_k, domain }) => {
211
+ }, async ({ query, top_k, domain, order_by, since, until, exclude_author }) => {
184
212
  const r = await apiFetch("/memory/read", {
185
213
  method: "POST",
186
214
  body: JSON.stringify({
@@ -188,42 +216,50 @@ server.registerTool("memory_read", {
188
216
  top_k: top_k || 5,
189
217
  domain: domain || undefined,
190
218
  include_associations: true,
219
+ // #404 temporal dimension — omitted entirely when unused so the
220
+ // request body stays byte-identical for existing callers.
221
+ ...(order_by ? { order_by } : {}),
222
+ ...(since ? { since } : {}),
223
+ ...(until ? { until } : {}),
224
+ ...(exclude_author ? { exclude_author } : {}),
191
225
  }),
192
226
  });
193
227
  const items = Array.isArray(r?.items) ? r.items : [];
194
- if (items.length === 0) {
228
+ if (items.length === 0 && (since || until || exclude_author)) {
229
+ // A bounded/filtered read that finds nothing is NOT a bad query —
230
+ // the truthful answer is "nothing new for these filters" (mirrors
231
+ // memory_list_recent's empty copy; no stats probe, no broaden hint).
195
232
  return {
196
233
  content: [
197
- { type: "text", text: "No memories found for this query." },
234
+ {
235
+ type: "text",
236
+ text: "Nothing matching within the given time/author filters.",
237
+ },
198
238
  ],
199
239
  };
200
240
  }
201
- // Surface server-stamped authorship (CN-001) so the reader knows WHO wrote each
202
- // memory — essential for shared rooms (Mnemoverse A2A Rooms), where atoms come from
203
- // different agents/vendors. The core REST response already carries `provenance`;
204
- // we just render it. Omitted cleanly for legacy atoms that have no author.
205
- const formatAuthorTag = (p) => {
206
- if (!p)
207
- return "";
208
- // Surface only the agent identity / client env — never the human `principal`
209
- // (it may be an email / PII), even though it's present in the response.
210
- const raw = p.agent_name || p.agent || p.client_env || "";
211
- // Sanitize before interpolating into tool output: a hostile connector can
212
- // choose its own agent_name — reuse the shared safeInline helper so the
213
- // CN-032 charset/cap stays consistent across all tool outputs (Copilot).
214
- const who = safeInline(raw, 64);
215
- if (!who)
216
- return "";
217
- return p.is_external ? ` [by ${who} · external]` : ` [by ${who}]`;
218
- };
219
- const lines = items.map((item, i) => {
220
- const relevance = ((item?.relevance ?? 0) * 100).toFixed(0);
221
- const content = item?.content ?? "(empty)";
222
- const concepts = Array.isArray(item?.concepts) && item.concepts.length > 0
223
- ? ` (${item.concepts.join(", ")})`
224
- : "";
225
- return `${i + 1}. [${relevance}%] ${content}${concepts}${formatAuthorTag(item?.provenance)}`;
226
- });
241
+ if (items.length === 0) {
242
+ // Zero results: ONE stats call (made only on this path) distinguishes a
243
+ // truly empty store (first contact — greet with how to save the first
244
+ // memory) from "no match for this query" (hint to broaden). Stats
245
+ // failure falls open to the plain no-match message. Domain-scoped reads
246
+ // never greet and never probe — the stats call measures the PERSONAL
247
+ // store, not the scoped domain. See src/teaching.ts.
248
+ const text = await buildReadEmptyResponse(() => apiFetch("/memory/stats"),
249
+ // trim(): a whitespace-only domain is not a real filter — treating it
250
+ // as scoped would silently suppress the first-contact greeting.
251
+ domain != null && domain.trim() !== "");
252
+ return {
253
+ content: [{ type: "text", text }],
254
+ };
255
+ }
256
+ // Rendering lives in src/render.ts (testable): each line carries the
257
+ // CN-001 author tag, the created_at date (#404 R1 — a reader cannot
258
+ // reason about recency it cannot see) and the full atom id (the tool
259
+ // description always promised ids for memory_feedback/memory_delete;
260
+ // the old render never delivered them, making both uncallable from
261
+ // read results).
262
+ const lines = items.map((item, i) => formatReadItem(item, i));
227
263
  const searchMs = (r?.search_time_ms ?? 0).toFixed(0);
228
264
  const text = lines.join("\n\n") + `\n\n(${searchMs}ms)`;
229
265
  return {
@@ -235,6 +271,93 @@ server.registerTool("memory_read", {
235
271
  ],
236
272
  };
237
273
  });
274
+ // --- Tool: memory_list_recent ---
275
+ server.registerTool("memory_list_recent", {
276
+ description: "List the NEWEST memories first — no search query needed. Semantic search answers 'what do I know about X'; this answers 'what happened lately': resuming work after a break, catching up on a shared room ('any new messages?'), or reviewing what was saved recently. Pass `since` (your last-seen time) to get only what's new, and page through older entries with the returned cursor. Complete by construction — nothing is skipped, unlike a search that only returns semantic matches.",
277
+ inputSchema: {
278
+ domain: z
279
+ .string()
280
+ .optional()
281
+ .describe("Restrict to one domain (e.g. a shared room address 'xroom:...'); omit for all your domains."),
282
+ since: z
283
+ .string()
284
+ .optional()
285
+ .describe("Only entries created at/after this ISO-8601 instant (naive = UTC) — your novelty watermark."),
286
+ limit: z
287
+ .number()
288
+ .int()
289
+ .min(1)
290
+ .max(100)
291
+ .optional()
292
+ .describe("Page size (default: 20). Newest first."),
293
+ cursor: z
294
+ .string()
295
+ .max(512)
296
+ .optional()
297
+ .describe("Opaque cursor from a previous page's 'More older entries exist' line — continues the listing without skips or duplicates."),
298
+ },
299
+ annotations: {
300
+ title: "List Recent Memories",
301
+ readOnlyHint: true,
302
+ destructiveHint: false,
303
+ idempotentHint: true,
304
+ openWorldHint: true,
305
+ },
306
+ }, async ({ domain, since, limit, cursor }) => {
307
+ let r;
308
+ try {
309
+ r = await apiFetch("/memory/recent", {
310
+ method: "POST",
311
+ body: JSON.stringify({
312
+ domain: domain || undefined,
313
+ since: since || undefined,
314
+ limit: limit || 20,
315
+ cursor: cursor || undefined,
316
+ }),
317
+ });
318
+ }
319
+ catch (e) {
320
+ // Graceful degradation while the server side rolls out: a 404 from
321
+ // core means the /memory/recent endpoint is not deployed yet — say
322
+ // so instead of surfacing a raw HTTP error.
323
+ const endpointAbsent = e instanceof Error &&
324
+ e.message.startsWith("Mnemoverse API error 404:") &&
325
+ !e.message.includes('"code"');
326
+ if (endpointAbsent) {
327
+ return {
328
+ content: [
329
+ {
330
+ type: "text",
331
+ text: "The memory service does not support the recent-entries feed yet. " +
332
+ "Use memory_read with order_by: 'recency' as an approximation.",
333
+ },
334
+ ],
335
+ };
336
+ }
337
+ throw e;
338
+ }
339
+ const items = Array.isArray(r?.items) ? r.items : [];
340
+ if (items.length === 0) {
341
+ return {
342
+ content: [
343
+ {
344
+ type: "text",
345
+ text: since
346
+ ? "Nothing new since your watermark."
347
+ : "No memories here yet.",
348
+ },
349
+ ],
350
+ };
351
+ }
352
+ return {
353
+ content: [
354
+ {
355
+ type: "text",
356
+ text: capResult(formatRecentPage(items, r?.next_cursor), "Lower `limit` or add a `domain` for smaller pages."),
357
+ },
358
+ ],
359
+ };
360
+ });
238
361
  // --- Tool: memory_feedback ---
239
362
  server.registerTool("memory_feedback", {
240
363
  description: "Report whether memories returned by memory_read were actually helpful. This is a learning signal, not a log: positive feedback raises a memory's ranking so it surfaces faster next time (across all of the user's tools), negative feedback lets it fade. Call it right after you act on (or reject) recalled memories, passing the ids from the memory_read results.",
@@ -301,7 +424,7 @@ server.registerTool("memory_stats", {
301
424
  });
302
425
  // --- Tool: memory_delete ---
303
426
  server.registerTool("memory_delete", {
304
- description: "Permanently delete ONE memory by its atom_id — irreversible, the memory is gone for good. Use only when the user explicitly asks to forget something specific, or to correct a fact you stored wrongly. Get the atom_id from a memory_read result. To clear an entire topic at once, use memory_delete_domain instead. Never delete on your own initiative — require an explicit user request.",
427
+ description: "Permanently delete ONE memory by its atom_id — irreversible, the memory is gone for good. Use it to keep the memory trustworthy: prune a memory that is obsolete, superseded by a newer decision, or that you stored wrongly — and whenever the user asks to forget something. Get the atom_id from a memory_read result. To clear an entire topic at once, use memory_delete_domain instead.",
305
428
  inputSchema: {
306
429
  atom_id: z
307
430
  .string()
@@ -341,7 +464,7 @@ server.registerTool("memory_delete", {
341
464
  });
342
465
  // --- Tool: memory_delete_domain ---
343
466
  server.registerTool("memory_delete_domain", {
344
- description: "Permanently delete EVERY memory in one domain — irreversible, and far more destructive than memory_delete. Use only on an explicit user request to wipe a whole topic, e.g. 'forget everything about project X' or 'wipe my benchmark experiments'. First run memory_stats to confirm the exact domain name, then pass it together with confirm=true (a deliberate safety interlock). Never call this speculatively or to 'clean up' on your own — only when the user explicitly asks.",
467
+ description: "Permanently delete EVERY memory in one domain — irreversible, and far more sweeping than memory_delete. This is a bulk wipe: run it only when the user asks for it (e.g. 'forget everything about project X') or has explicitly confirmed a wipe you proposed — never on your own judgment alone. First run memory_stats to confirm the exact domain name, then pass it together with confirm=true (a deliberate safety interlock). For a single wrong or stale memory, memory_delete is the right tool.",
345
468
  inputSchema: {
346
469
  domain: z
347
470
  .string()
@@ -510,6 +633,96 @@ server.registerTool("memory_join_room", {
510
633
  ],
511
634
  };
512
635
  });
636
+ // --- Tool: memory_list_rooms ---
637
+ server.registerTool("memory_list_rooms", {
638
+ description: "List the shared memory rooms you can use — the ones you OWN plus the ones you've JOINED — each with the address to pass as `domain` on memory_write / memory_read. Use this to RE-FIND a room in a new session (e.g. 'what rooms do I have?', 'resume the room with Olya') instead of having to create or re-join it.",
639
+ inputSchema: {},
640
+ annotations: {
641
+ title: "List rooms",
642
+ readOnlyHint: true,
643
+ destructiveHint: false,
644
+ idempotentHint: true,
645
+ openWorldHint: true,
646
+ },
647
+ }, async () => {
648
+ const rooms = await apiFetch("/memory/rooms");
649
+ const list = Array.isArray(rooms) ? rooms : [];
650
+ if (list.length === 0) {
651
+ return {
652
+ content: [
653
+ {
654
+ type: "text",
655
+ text: "You have no shared rooms yet. Create one with memory_create_room, " +
656
+ "or join one with memory_join_room using an invite code.",
657
+ },
658
+ ],
659
+ };
660
+ }
661
+ // Room name is OWNER-chosen and surfaced to THIS assistant — sanitize it (CN-032),
662
+ // like memory_join_room already does. address/role/scope are server-shaped but pass
663
+ // through the same guard defensively.
664
+ const lines = list.map((r) => {
665
+ const name = safeInline(r?.name) || "(unnamed room)";
666
+ const roomId = safeInline(r?.room_id);
667
+ // Always surface the canonical address: fall back to xroom:<room_id> when the server
668
+ // omits `address`, so the domain guidance this tool promises is never silently dropped.
669
+ const address = safeInline(r?.address) || (roomId ? `xroom:${roomId}` : "");
670
+ const role = safeInline(r?.role);
671
+ const scope = safeInline(r?.scope);
672
+ const archived = r?.archived ? " [archived]" : "";
673
+ const use = address ? ` — use domain="${address}"` : "";
674
+ return `- "${name}" (${role}${scope ? `, ${scope}` : ""})${archived}${use}`;
675
+ });
676
+ const text = `Your shared rooms (${list.length}):\n${lines.join("\n")}`;
677
+ return {
678
+ content: [
679
+ {
680
+ type: "text",
681
+ text: capResult(text, "The room list was truncated — some rooms are not shown."),
682
+ },
683
+ ],
684
+ };
685
+ });
686
+ // --- Tool: vault_list ---
687
+ server.registerTool("vault_list", {
688
+ description: "List the secrets stored in your Mnemoverse Vault — by ALIAS and purpose only; the secret VALUE is never returned or shown to you. Use this to DISCOVER which secret to use (e.g. the user says 'use my GitHub token' — find its alias here) before a tool that consumes it. Only YOUR account's secrets are listed.",
689
+ inputSchema: {},
690
+ annotations: {
691
+ title: "List vault secrets",
692
+ readOnlyHint: true,
693
+ destructiveHint: false,
694
+ idempotentHint: true,
695
+ openWorldHint: true,
696
+ },
697
+ }, async () => {
698
+ const r = await apiFetch("/vault/secrets");
699
+ const list = Array.isArray(r?.secrets) ? r.secrets : [];
700
+ if (list.length === 0) {
701
+ return {
702
+ content: [
703
+ {
704
+ type: "text",
705
+ text: "No secrets are stored in your Vault yet.",
706
+ },
707
+ ],
708
+ };
709
+ }
710
+ const lines = list.map((s) => {
711
+ const alias = safeInline(s?.alias) || "(no alias)";
712
+ const context = safeInline(s?.context);
713
+ return context ? `- ${alias} — ${context}` : `- ${alias}`;
714
+ });
715
+ const text = `Your Vault secrets (${list.length}) — alias and purpose only, never the value:\n` +
716
+ lines.join("\n");
717
+ return {
718
+ content: [
719
+ {
720
+ type: "text",
721
+ text: capResult(text, "The secret list was truncated — some secrets are not shown."),
722
+ },
723
+ ],
724
+ };
725
+ });
513
726
  // --- Start ---
514
727
  async function main() {
515
728
  const transport = new StdioServerTransport();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Result-rendering helpers for memory_read and memory_list_recent.
3
+ *
4
+ * Kept out of index.ts (same move as teaching.ts) so tests can pin the
5
+ * rendered contract: since the #404 temporal work, every item line
6
+ * carries its id and created_at date WHENEVER the server provides them
7
+ * (memory_feedback / memory_delete are uncallable without ids — the tool
8
+ * description always promised them, the old render never delivered any;
9
+ * a reader cannot reason about recency it cannot see). Legacy response
10
+ * shapes without atom_id/created_at degrade gracefully: those parts of
11
+ * the line are simply omitted.
12
+ */
13
+ /** CN-001 server-stamped authorship, as returned nested on read/feed items. */
14
+ export type Provenance = {
15
+ principal?: string | null;
16
+ agent?: string | null;
17
+ agent_name?: string | null;
18
+ client_env?: string | null;
19
+ is_external?: boolean | null;
20
+ };
21
+ export type ReadItem = {
22
+ atom_id?: string;
23
+ content?: string;
24
+ relevance?: number;
25
+ concepts?: string[];
26
+ domain?: string;
27
+ created_at?: string;
28
+ provenance?: Provenance | null;
29
+ };
30
+ export type RecentItem = {
31
+ atom_id?: string;
32
+ content?: string;
33
+ domain?: string;
34
+ created_at?: string;
35
+ concepts?: string[];
36
+ provenance?: Provenance | null;
37
+ };
38
+ /**
39
+ * Sanitize a string for inline interpolation into tool output (CN-032:
40
+ * hostile connectors choose their own agent_name). Charset/cap identical
41
+ * to index.ts's safeInline — re-exported here so both render paths share
42
+ * one implementation.
43
+ */
44
+ export declare function safeInline(s: string | undefined | null, cap?: number): string;
45
+ /**
46
+ * ` [by X]` / ` [by X · external]` — agent identity only, never the human
47
+ * `principal` (may be an email / PII), even though the response carries it.
48
+ */
49
+ export declare function formatAuthorTag(p?: Provenance | null): string;
50
+ /**
51
+ * ` · 2026-08-01 21:04Z` — minute-precision UTC, compact enough for a line
52
+ * tail, precise enough to order a same-day room conversation by eye.
53
+ * Empty for legacy atoms without a timestamp.
54
+ */
55
+ export declare function formatDateTag(createdAt?: string): string;
56
+ /**
57
+ * One memory_read result line:
58
+ * `N. [82%] content (concepts) [by X] · 2026-08-01 21:04Z\n id: <uuid>`
59
+ *
60
+ * The id sits on its own indented line: full-width (feedback/delete need
61
+ * the EXACT id, truncation would break them) without crowding the content
62
+ * line a model actually reads.
63
+ */
64
+ export declare function formatReadItem(item: ReadItem, index: number): string;
65
+ /**
66
+ * One memory_list_recent line — a feed entry, not a search hit: no
67
+ * relevance, date leads because the feed is ORDERED by it.
68
+ */
69
+ export declare function formatRecentItem(item: RecentItem, index: number): string;
70
+ /** Full feed page: items newest-first + how to continue / that it's over. */
71
+ export declare function formatRecentPage(items: RecentItem[], nextCursor?: string | null): string;
package/dist/render.js ADDED
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Result-rendering helpers for memory_read and memory_list_recent.
3
+ *
4
+ * Kept out of index.ts (same move as teaching.ts) so tests can pin the
5
+ * rendered contract: since the #404 temporal work, every item line
6
+ * carries its id and created_at date WHENEVER the server provides them
7
+ * (memory_feedback / memory_delete are uncallable without ids — the tool
8
+ * description always promised them, the old render never delivered any;
9
+ * a reader cannot reason about recency it cannot see). Legacy response
10
+ * shapes without atom_id/created_at degrade gracefully: those parts of
11
+ * the line are simply omitted.
12
+ */
13
+ /**
14
+ * Sanitize a string for inline interpolation into tool output (CN-032:
15
+ * hostile connectors choose their own agent_name). Charset/cap identical
16
+ * to index.ts's safeInline — re-exported here so both render paths share
17
+ * one implementation.
18
+ */
19
+ export function safeInline(s, cap = 200) {
20
+ return (s ?? "")
21
+ .replace(/[^\w .@:+/-]/g, " ")
22
+ .replace(/\s+/g, " ")
23
+ .trim()
24
+ .slice(0, cap);
25
+ }
26
+ /**
27
+ * ` [by X]` / ` [by X · external]` — agent identity only, never the human
28
+ * `principal` (may be an email / PII), even though the response carries it.
29
+ */
30
+ export function formatAuthorTag(p) {
31
+ if (!p)
32
+ return "";
33
+ const raw = p.agent_name || p.agent || p.client_env || "";
34
+ const who = safeInline(raw, 64);
35
+ if (!who)
36
+ return "";
37
+ return p.is_external ? ` [by ${who} · external]` : ` [by ${who}]`;
38
+ }
39
+ /**
40
+ * ` · 2026-08-01 21:04Z` — minute-precision UTC, compact enough for a line
41
+ * tail, precise enough to order a same-day room conversation by eye.
42
+ * Empty for legacy atoms without a timestamp.
43
+ */
44
+ export function formatDateTag(createdAt) {
45
+ if (!createdAt)
46
+ return "";
47
+ const d = new Date(createdAt);
48
+ if (Number.isNaN(d.getTime()))
49
+ return "";
50
+ const iso = d.toISOString();
51
+ return ` · ${iso.slice(0, 10)} ${iso.slice(11, 16)}Z`;
52
+ }
53
+ /**
54
+ * One memory_read result line:
55
+ * `N. [82%] content (concepts) [by X] · 2026-08-01 21:04Z\n id: <uuid>`
56
+ *
57
+ * The id sits on its own indented line: full-width (feedback/delete need
58
+ * the EXACT id, truncation would break them) without crowding the content
59
+ * line a model actually reads.
60
+ */
61
+ export function formatReadItem(item, index) {
62
+ const relevance = ((item?.relevance ?? 0) * 100).toFixed(0);
63
+ const content = item?.content ?? "(empty)";
64
+ const concepts = Array.isArray(item?.concepts) && item.concepts.length > 0
65
+ ? ` (${item.concepts.join(", ")})`
66
+ : "";
67
+ const head = `${index + 1}. [${relevance}%] ${content}${concepts}${formatAuthorTag(item?.provenance)}${formatDateTag(item?.created_at)}`;
68
+ return item?.atom_id ? `${head}\n id: ${item.atom_id}` : head;
69
+ }
70
+ /**
71
+ * One memory_list_recent line — a feed entry, not a search hit: no
72
+ * relevance, date leads because the feed is ORDERED by it.
73
+ */
74
+ export function formatRecentItem(item, index) {
75
+ const content = item?.content ?? "(empty)";
76
+ const concepts = Array.isArray(item?.concepts) && item.concepts.length > 0
77
+ ? ` (${item.concepts.join(", ")})`
78
+ : "";
79
+ const date = formatDateTag(item?.created_at).replace(/^ · /, "");
80
+ const head = `${index + 1}. ${date ? `[${date}] ` : ""}${content}${concepts}${formatAuthorTag(item?.provenance)}`;
81
+ return item?.atom_id ? `${head}\n id: ${item.atom_id}` : head;
82
+ }
83
+ /** Full feed page: items newest-first + how to continue / that it's over. */
84
+ export function formatRecentPage(items, nextCursor) {
85
+ const lines = items.map((it, i) => formatRecentItem(it, i));
86
+ // Defense-in-depth (CN-032 posture): the cursor is server-supplied and
87
+ // interpolated into instructional text — only echo it when it matches the
88
+ // opaque urlsafe-base64 shape ours always has.
89
+ const cursorOk = nextCursor != null && /^[A-Za-z0-9_=-]{1,512}$/.test(nextCursor);
90
+ const tail = cursorOk
91
+ ? `\n\nMore older entries exist — pass cursor: ${nextCursor}`
92
+ : `\n\n(end of feed — nothing older)`;
93
+ return lines.join("\n\n") + tail;
94
+ }
95
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Teaching surface — the strings and branch logic that teach a connected model
3
+ * how to USE this memory, kept in their own module so tests can import them
4
+ * without booting the stdio server (src/index.ts starts a transport on import).
5
+ *
6
+ * Product frame (Eduard, 2026-08-01): the memory store belongs to THE AGENT,
7
+ * not the user — so the guidance is active ("need it — go get it; learned
8
+ * something — save it"), never gated on the user explicitly asking. Honesty
9
+ * constraints stay: no over-claiming, and the never-store-secrets safety line
10
+ * is kept on write surfaces.
11
+ */
12
+ /**
13
+ * Server-level instructions, passed to the McpServer constructor and landed
14
+ * verbatim in the connected model's system prompt by MCP clients.
15
+ *
16
+ * Constraints (tested in test/teaching-surface.test.ts):
17
+ * - 500–800 chars; some clients (ChatGPT) weight the FIRST ~512 chars, so the
18
+ * core habit (read before answering, write on learning) is front-loaded.
19
+ * - Active polarity: no "only when the user explicitly asks" gating.
20
+ * - Mentions every tool family: read/write/stats/feedback, delete, rooms, vault.
21
+ */
22
+ export declare const SERVER_INSTRUCTIONS = "You own this long-term memory. It persists across sessions and every AI tool this user connects (Claude, ChatGPT, editors). Use it as a habit: call memory_read before answering anything that may have come up before, and memory_write the moment you learn a durable fact, preference, or decision \u2014 don't wait to be asked. Rate recalls with memory_feedback so good ones surface faster; memory_stats shows counts; memory_list_recent: newest first; prune with memory_delete; memory_delete_domain wipes a domain, only with user go-ahead. Rooms (memory_create_room, memory_invite_to_room, memory_join_room, memory_list_rooms) share memory with others; vault_list names stored secrets by alias, never values. Never store passwords, API keys, payment data, MFA codes, government IDs, or health records.";
23
+ /** The pre-existing zero-result message — kept as the fail-open fallback. */
24
+ export declare const NO_MATCH_MESSAGE = "No memories found for this query.";
25
+ /** Hint for an UNSCOPED no-match against a non-empty store: widen the query.
26
+ * (No drop-the-filter clause — none was set; advising to remove a filter that
27
+ * does not exist nudges the model into confabulating state.) */
28
+ export declare const NO_MATCH_HINT = " Try a broader query.";
29
+ /** Hint for a DOMAIN-SCOPED no-match: here a filter genuinely exists, so
30
+ * suggesting to drop it is honest and actionable. */
31
+ export declare const NO_MATCH_SCOPED_HINT = " Try a broader query, or drop the domain filter to search all domains.";
32
+ /**
33
+ * First-contact greeting: shown ONLY when a read comes back empty AND the
34
+ * store holds zero memories — i.e. the very first read of this account's life.
35
+ * Seeds the ANSWER, not the store: one functional paragraph that says what
36
+ * this store is, how to save the first memory, and one next step. It can never
37
+ * appear again once anything is stored (total_atoms > 0 takes the other branch).
38
+ */
39
+ export declare const EMPTY_STORE_WELCOME: string;
40
+ /**
41
+ * Decide what a zero-result memory_read should say.
42
+ *
43
+ * DOMAIN-SCOPED reads (`scopedToDomain` — the caller passed a `domain` arg,
44
+ * e.g. a shared room) never greet and never probe: the stats call measures the
45
+ * PERSONAL store, so on a scoped read it could claim "the store is empty"
46
+ * about a domain that has memories the query merely missed (review finding).
47
+ * The scoped copy suggests dropping the filter — honest, one actually exists.
48
+ *
49
+ * UNSCOPED reads make ONE stats call (only ever on the zero-result path) to
50
+ * distinguish "store is truly empty" from "no match for this query":
51
+ * - total_atoms === 0 → EMPTY_STORE_WELCOME (first-contact greeting)
52
+ * - total_atoms > 0 → no-match + the broaden hint (no filter clause)
53
+ * - stats throws/malformed → the plain old no-match message (fail-open to the
54
+ * pre-greeting behavior; never surfaces an error, never writes anything)
55
+ */
56
+ export declare function buildReadEmptyResponse(fetchStats: () => Promise<{
57
+ total_atoms?: number;
58
+ }>, scopedToDomain?: boolean): Promise<string>;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Teaching surface — the strings and branch logic that teach a connected model
3
+ * how to USE this memory, kept in their own module so tests can import them
4
+ * without booting the stdio server (src/index.ts starts a transport on import).
5
+ *
6
+ * Product frame (Eduard, 2026-08-01): the memory store belongs to THE AGENT,
7
+ * not the user — so the guidance is active ("need it — go get it; learned
8
+ * something — save it"), never gated on the user explicitly asking. Honesty
9
+ * constraints stay: no over-claiming, and the never-store-secrets safety line
10
+ * is kept on write surfaces.
11
+ */
12
+ /**
13
+ * Server-level instructions, passed to the McpServer constructor and landed
14
+ * verbatim in the connected model's system prompt by MCP clients.
15
+ *
16
+ * Constraints (tested in test/teaching-surface.test.ts):
17
+ * - 500–800 chars; some clients (ChatGPT) weight the FIRST ~512 chars, so the
18
+ * core habit (read before answering, write on learning) is front-loaded.
19
+ * - Active polarity: no "only when the user explicitly asks" gating.
20
+ * - Mentions every tool family: read/write/stats/feedback, delete, rooms, vault.
21
+ */
22
+ export const SERVER_INSTRUCTIONS = "You own this long-term memory. It persists across sessions and every AI tool this user connects (Claude, ChatGPT, editors). Use it as a habit: call memory_read before answering anything that may have come up before, and memory_write the moment you learn a durable fact, preference, or decision — don't wait to be asked. Rate recalls with memory_feedback so good ones surface faster; memory_stats shows counts; memory_list_recent: newest first; prune with memory_delete; memory_delete_domain wipes a domain, only with user go-ahead. Rooms (memory_create_room, memory_invite_to_room, memory_join_room, memory_list_rooms) share memory with others; vault_list names stored secrets by alias, never values. Never store passwords, API keys, payment data, MFA codes, government IDs, or health records.";
23
+ /** The pre-existing zero-result message — kept as the fail-open fallback. */
24
+ export const NO_MATCH_MESSAGE = "No memories found for this query.";
25
+ /** Hint for an UNSCOPED no-match against a non-empty store: widen the query.
26
+ * (No drop-the-filter clause — none was set; advising to remove a filter that
27
+ * does not exist nudges the model into confabulating state.) */
28
+ export const NO_MATCH_HINT = " Try a broader query.";
29
+ /** Hint for a DOMAIN-SCOPED no-match: here a filter genuinely exists, so
30
+ * suggesting to drop it is honest and actionable. */
31
+ export const NO_MATCH_SCOPED_HINT = " Try a broader query, or drop the domain filter to search all domains.";
32
+ /**
33
+ * First-contact greeting: shown ONLY when a read comes back empty AND the
34
+ * store holds zero memories — i.e. the very first read of this account's life.
35
+ * Seeds the ANSWER, not the store: one functional paragraph that says what
36
+ * this store is, how to save the first memory, and one next step. It can never
37
+ * appear again once anything is stored (total_atoms > 0 takes the other branch).
38
+ */
39
+ export const EMPTY_STORE_WELCOME = "Your long-term memory is empty — nothing has been saved yet, which is why this search returned nothing. " +
40
+ "This store is your own persistent memory: whatever you save survives across sessions and across every AI tool this user has connected. " +
41
+ 'Save the first memory now with memory_write, e.g. content: "User prefers TypeScript strict mode" — future sessions will recall it with memory_read.';
42
+ /**
43
+ * Decide what a zero-result memory_read should say.
44
+ *
45
+ * DOMAIN-SCOPED reads (`scopedToDomain` — the caller passed a `domain` arg,
46
+ * e.g. a shared room) never greet and never probe: the stats call measures the
47
+ * PERSONAL store, so on a scoped read it could claim "the store is empty"
48
+ * about a domain that has memories the query merely missed (review finding).
49
+ * The scoped copy suggests dropping the filter — honest, one actually exists.
50
+ *
51
+ * UNSCOPED reads make ONE stats call (only ever on the zero-result path) to
52
+ * distinguish "store is truly empty" from "no match for this query":
53
+ * - total_atoms === 0 → EMPTY_STORE_WELCOME (first-contact greeting)
54
+ * - total_atoms > 0 → no-match + the broaden hint (no filter clause)
55
+ * - stats throws/malformed → the plain old no-match message (fail-open to the
56
+ * pre-greeting behavior; never surfaces an error, never writes anything)
57
+ */
58
+ export async function buildReadEmptyResponse(fetchStats, scopedToDomain = false) {
59
+ if (scopedToDomain)
60
+ return NO_MATCH_MESSAGE + NO_MATCH_SCOPED_HINT;
61
+ let totalAtoms;
62
+ try {
63
+ totalAtoms = (await fetchStats())?.total_atoms;
64
+ }
65
+ catch {
66
+ return NO_MATCH_MESSAGE;
67
+ }
68
+ if (totalAtoms === 0)
69
+ return EMPTY_STORE_WELCOME;
70
+ if (typeof totalAtoms === "number" && totalAtoms > 0) {
71
+ return NO_MATCH_MESSAGE + NO_MATCH_HINT;
72
+ }
73
+ return NO_MATCH_MESSAGE;
74
+ }
75
+ //# sourceMappingURL=teaching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teaching.js","sourceRoot":"","sources":["../src/teaching.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,2xBAA2xB,CAAC;AAE9xB,6EAA6E;AAC7E,MAAM,CAAC,MAAM,gBAAgB,GAAG,mCAAmC,CAAC;AAEpE;;iEAEiE;AACjE,MAAM,CAAC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAErD;sDACsD;AACtD,MAAM,CAAC,MAAM,oBAAoB,GAC/B,wEAAwE,CAAC;AAE3E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,0GAA0G;IAC1G,yIAAyI;IACzI,qJAAqJ,CAAC;AAExJ;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAAmD,EACnD,cAAc,GAAG,KAAK;IAEtB,IAAI,cAAc;QAAE,OAAO,gBAAgB,GAAG,oBAAoB,CAAC;IACnE,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,GAAG,CAAC,MAAM,UAAU,EAAE,CAAC,EAAE,WAAW,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,IAAI,UAAU,KAAK,CAAC;QAAE,OAAO,mBAAmB,CAAC;IACjD,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACrD,OAAO,gBAAgB,GAAG,aAAa,CAAC;IAC1C,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnemoverse/mcp-memory-server",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Hosted persistent memory for AI agents that learns which facts help and lets the rest fade — one key across Claude Code, Cursor, VS Code & ChatGPT, no infra to run",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,6 +18,8 @@
18
18
  "build": "tsc",
19
19
  "dev": "tsc --watch",
20
20
  "start": "node dist/index.js",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
21
23
  "generate:configs": "node scripts/generate-configs.mjs",
22
24
  "verify:configs": "node scripts/generate-configs.mjs --check",
23
25
  "check:release-sync": "node scripts/check-release-sync.mjs",
@@ -59,7 +61,8 @@
59
61
  },
60
62
  "devDependencies": {
61
63
  "typescript": "^5.8.3",
62
- "@types/node": "^22.15.3"
64
+ "@types/node": "^22.15.3",
65
+ "vitest": "^4.1.9"
63
66
  },
64
67
  "engines": {
65
68
  "node": ">=18"