@echomem/mcp 1.4.6 → 1.4.8

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.
@@ -5,13 +5,18 @@ export const canonicalToolNames = {
5
5
  save: "save_conversation",
6
6
  timeRange: "get_memories_by_time_range",
7
7
  keywords: "search_memories_by_keywords",
8
+ friends: "list_friends",
9
+ searchUsers: "search_users",
10
+ sendFriendRequest: "send_friend_request",
8
11
  others: "search_others_memories",
12
+ publicMemory: "get_public_memory",
9
13
  report: "echomem_usage_report",
10
14
  updateStatus: "echomem_update_status",
11
15
  contextHealth: "echo_context_health",
12
16
  recompose: "echo_recompose",
13
17
  delete: "delete_memory",
14
18
  getByContext: "get_memories_by_context",
19
+ checkpointByContext: "get_checkpoint_by_context",
15
20
  };
16
21
  export const legacyAliasToCanonical = {
17
22
  search_memories_by_description_semantic: canonicalToolNames.search,
@@ -59,9 +64,35 @@ export const keywordsSchema = z.object({
59
64
  keywords: z.array(z.string()),
60
65
  limit: z.number().optional().default(10),
61
66
  });
67
+ export const listFriendsSchema = z.object({
68
+ ...triggerMetadataSchema,
69
+ });
70
+ export const searchUsersSchema = z.object({
71
+ ...triggerMetadataSchema,
72
+ query: z.string().min(1),
73
+ limit: z.number().optional().default(10),
74
+ });
75
+ export const sendFriendRequestSchema = z.object({
76
+ ...triggerMetadataSchema,
77
+ targetUserId: z.string().min(1),
78
+ });
62
79
  export const othersSchema = z.object({
63
80
  ...triggerMetadataSchema,
64
- query: z.string(),
81
+ query: z.string().optional().default(""),
82
+ limit: z.number().optional().default(10),
83
+ target: z.string().optional(),
84
+ ownerUserId: z.string().optional(),
85
+ ownerName: z.string().optional(),
86
+ targetFriendIds: z.array(z.string()).optional(),
87
+ targetFriendNames: z.array(z.string()).optional(),
88
+ recordAccess: z.boolean().optional(),
89
+ kPerUser: z.number().optional(),
90
+ similarityThreshold: z.number().optional(),
91
+ timeFrameDays: z.number().optional(),
92
+ });
93
+ export const publicMemorySchema = z.object({
94
+ ...triggerMetadataSchema,
95
+ memoryId: z.string().min(1),
65
96
  });
66
97
  export const deleteMemorySchema = z.object({
67
98
  memoryId: z.string().min(1),
@@ -84,7 +115,7 @@ export function listToolSpecs(opts = {}) {
84
115
  return [
85
116
  {
86
117
  name: canonicalToolNames.search,
87
- description: withMcpVersion(`Recall the user's prior decisions, preferences, constraints, and project context from EchoMem — their long-term memory across ALL their AI tools (Claude.ai, ChatGPT, other agents), not just this session.${mapSection}\nCall this when the task plausibly relates to that remembered context — a topic above, or when the user refers to past work ("what did we decide", "like before", "the usual") — so you don't re-derive or re-ask what they already settled. Skip it for self-contained tasks with no link to their history (e.g. a generic algorithm question). By default this returns only the ranked memories retrieved for recall and skips EchoMem answer generation; set includeAnswer=true only when you explicitly need EchoMem's legacy synthesized recall. Current time: ${currentTime}.${updateSection}`),
118
+ description: withMcpVersion(`Recall the user's prior decisions, preferences, and project context from EchoMem — their long-term memory across ALL their AI tools, not just this session. Use it instead of re-deriving or re-asking what the user already settled.${mapSection}\nReturns the ranked memories; set includeAnswer=true only if you need the legacy synthesized answer. Current time: ${currentTime}.${updateSection}`),
88
119
  inputSchema: {
89
120
  type: "object",
90
121
  properties: {
@@ -130,7 +161,7 @@ export function listToolSpecs(opts = {}) {
130
161
  },
131
162
  {
132
163
  name: canonicalToolNames.save,
133
- description: "Save conversation into EchoMem for future retrieval. Set passthrough=true to store the text verbatim as a session capsule (no LLM extraction, no embeddings) use this for warm-up capsules that a fresh session will reload via get_memories_by_context.",
164
+ description: "Save this conversation into EchoMem as long-term memory (durable memories are extracted automatically). passthrough=true stores the text verbatim as a session capsule insteadreload it later via get_memories_by_context.",
134
165
  inputSchema: {
135
166
  type: "object",
136
167
  properties: {
@@ -196,20 +227,121 @@ export function listToolSpecs(opts = {}) {
196
227
  required: ["keywords"],
197
228
  },
198
229
  },
230
+ {
231
+ name: canonicalToolNames.friends,
232
+ description: "Friends: list accepted EchoMem friends with each friend's public memory count. Use this before asking a specific friend by name.",
233
+ inputSchema: {
234
+ type: "object",
235
+ properties: {
236
+ triggerMessage: {
237
+ type: "string",
238
+ description: "Optional: the user's message that caused this friend-list lookup. EchoMem stores only a redacted analytics preview and hash.",
239
+ },
240
+ triggerMessageRole: { type: "string", default: "user" },
241
+ },
242
+ },
243
+ },
244
+ {
245
+ name: canonicalToolNames.searchUsers,
246
+ description: "Search EchoMem users by display name/username before sending a friend request. Results include total memories, public memories, and current relationship state.",
247
+ inputSchema: {
248
+ type: "object",
249
+ properties: {
250
+ query: {
251
+ type: "string",
252
+ description: "Name or username fragment to search, e.g. Kobe.",
253
+ },
254
+ limit: { type: "number", default: 10 },
255
+ triggerMessage: {
256
+ type: "string",
257
+ description: "Optional: the user's message that caused this user search. EchoMem stores only a redacted analytics preview and hash.",
258
+ },
259
+ triggerMessageRole: { type: "string", default: "user" },
260
+ },
261
+ required: ["query"],
262
+ },
263
+ },
264
+ {
265
+ name: canonicalToolNames.sendFriendRequest,
266
+ description: "Send a pending EchoMem friend request to an exact user id returned by search_users. The other user must approve before friend-gated memory access is allowed.",
267
+ inputSchema: {
268
+ type: "object",
269
+ properties: {
270
+ targetUserId: {
271
+ type: "string",
272
+ description: "Exact target user id from search_users.",
273
+ },
274
+ triggerMessage: {
275
+ type: "string",
276
+ description: "Optional: the user's message that caused this friend request. EchoMem stores only a redacted analytics preview and hash.",
277
+ },
278
+ triggerMessageRole: { type: "string", default: "user" },
279
+ },
280
+ required: ["targetUserId"],
281
+ },
282
+ },
199
283
  {
200
284
  name: canonicalToolNames.others,
201
- description: "Search other users' public memories.",
285
+ description: "Search accepted friends' public memories. Returned memories are recorded in the existing memory_views pipeline for the memory owners.",
202
286
  inputSchema: {
203
287
  type: "object",
204
288
  properties: {
205
289
  query: { type: "string" },
290
+ limit: { type: "number", default: 10 },
291
+ target: {
292
+ type: "string",
293
+ description: "Accepted-friend user id or exact display name/username. Prefer this for @Name asks.",
294
+ },
295
+ ownerUserId: {
296
+ type: "string",
297
+ description: "Optional accepted-friend user id to scope the search to one friend.",
298
+ },
299
+ ownerName: {
300
+ type: "string",
301
+ description: "Optional accepted-friend display name/username to scope the search to one friend.",
302
+ },
303
+ targetFriendIds: {
304
+ type: "array",
305
+ items: { type: "string" },
306
+ description: "Optional accepted-friend user ids to scope the search.",
307
+ },
308
+ targetFriendNames: {
309
+ type: "array",
310
+ items: { type: "string" },
311
+ description: "Optional accepted-friend display names/usernames to scope the search.",
312
+ },
313
+ recordAccess: {
314
+ type: "boolean",
315
+ description: "Defaults true. When true, returned public memories are recorded in memory_views.",
316
+ },
317
+ kPerUser: { type: "number", default: 5 },
318
+ similarityThreshold: { type: "number", default: 0.1 },
319
+ timeFrameDays: { type: "number" },
206
320
  triggerMessage: {
207
321
  type: "string",
208
322
  description: "Optional: the user's message that caused this public-memory search. EchoMem stores only a redacted analytics preview and hash.",
209
323
  },
210
324
  triggerMessageRole: { type: "string", default: "user" },
211
325
  },
212
- required: ["query"],
326
+ },
327
+ },
328
+ {
329
+ name: canonicalToolNames.publicMemory,
330
+ description: "Fetch one accepted friend's public memory by id. If the caller is not the owner, EchoMem records the access in the existing memory_views pipeline.",
331
+ inputSchema: {
332
+ type: "object",
333
+ properties: {
334
+ memoryId: {
335
+ type: "string",
336
+ description: "The public memory id to fetch.",
337
+ },
338
+ triggerMessage: {
339
+ type: "string",
340
+ description: "Optional: the user's message that caused this public-memory fetch. EchoMem stores only a redacted analytics preview and hash.",
341
+ },
342
+ triggerMessageRole: { type: "string", default: "user" },
343
+ },
344
+ required: ["memoryId"],
213
345
  },
214
346
  },
215
347
  {
@@ -252,6 +384,23 @@ export function listToolSpecs(opts = {}) {
252
384
  required: ["contextId"],
253
385
  },
254
386
  },
387
+ {
388
+ name: canonicalToolNames.checkpointByContext,
389
+ description: withMcpVersion(`Rebuild a clean-context checkpoint / decision log from one EchoMem contextId. Use this when the user or EchoMem HUD gives you a contextId for a renewed coding session and you need the session handoff, not a raw memory dump. It deterministically fetches that context and formats it as orientation state: decisions, carryover, constraints, and checkpoints. Current time: ${currentTime}.`),
390
+ inputSchema: {
391
+ type: "object",
392
+ properties: {
393
+ contextId: { type: "string", description: "The EchoMem contextId shown by the HUD or returned by save_conversation / Renew session." },
394
+ limit: { type: "number", default: 100 },
395
+ triggerMessage: {
396
+ type: "string",
397
+ description: "Optional: the user's message that caused this lookup. EchoMem stores only a redacted analytics preview and hash.",
398
+ },
399
+ triggerMessageRole: { type: "string", default: "user" },
400
+ },
401
+ required: ["contextId"],
402
+ },
403
+ },
255
404
  {
256
405
  name: canonicalToolNames.report,
257
406
  description: "Show the user a one-screen audit of THEIR OWN AI coding usage — computed locally from their Codex/Claude Code logs ($0, nothing uploaded): how many tokens their agents spent, how much was re-reading context, reads vs memory recalls, and what changes with EchoMem. Call this when the user asks about their usage, token spend, cost, how much they're wasting, or wants a summary of their agent activity — and you may offer it once right after EchoMem is first connected. Returns formatted text to show the user verbatim. Needs no login.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@echomem/mcp",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "description": "EchoMem Cloud-First MCP Server",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -20,7 +20,8 @@
20
20
  "start": "node dist/index.js",
21
21
  "dev": "tsx src/index.ts",
22
22
  "smoke": "node smoke.mjs",
23
- "test": "npm run build && node test/crypto.test.mjs && node test/integration.test.mjs && node test/no-restart.test.mjs && node test/report.test.mjs && node test/tools.test.mjs && node test/update-check.test.mjs && node test/delete.test.mjs && node test/migrate.test.mjs && node test/hud.test.mjs",
23
+ "preview:extraction": "npm run build && node scripts/preview-extraction.mjs",
24
+ "test": "npm run build && node test/crypto.test.mjs && node test/integration.test.mjs && node test/no-restart.test.mjs && node test/report.test.mjs && node test/tools.test.mjs && node test/update-check.test.mjs && node test/delete.test.mjs && node test/low-touch-tools.test.mjs && node test/migrate.test.mjs && node test/hud.test.mjs",
24
25
  "prepack": "npm run build && node scripts/bundle-city.mjs"
25
26
  },
26
27
  "dependencies": {