@dudamel/mcp-memory 2026.1104.1 → 2026.1106.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 CHANGED
@@ -37,6 +37,10 @@ var DudamelApiError = class extends Error {
37
37
  if (apiError?.context?.["inputsSchema"] !== void 0) {
38
38
  lines.push(`Expected inputs schema: ${JSON.stringify(apiError.context["inputsSchema"])}`);
39
39
  }
40
+ const rest = Object.entries(apiError?.context ?? {}).filter(([key]) => key !== "inputsSchema");
41
+ if (rest.length > 0) {
42
+ lines.push(`Context: ${JSON.stringify(Object.fromEntries(rest))}`);
43
+ }
40
44
  super(lines.join("\n"));
41
45
  this.status = status;
42
46
  this.statusText = statusText;
@@ -145,12 +149,15 @@ function errorResult(error) {
145
149
  };
146
150
  }
147
151
 
152
+ // ../common/dist/owner-tools.js
153
+ import { z } from "zod";
154
+
148
155
  // src/tools/memories.ts
149
- import { z as z2 } from "zod";
156
+ import { z as z3 } from "zod";
150
157
 
151
158
  // src/util.ts
152
- import { z } from "zod";
153
- var AGENT_NAME_FIELD = z.string().optional().describe(
159
+ import { z as z2 } from "zod";
160
+ var AGENT_NAME_FIELD = z2.string().optional().describe(
154
161
  'The Dudamel agent you are acting as (e.g. "dudamel-expert"). Pass it on every call when you are one \u2014 it is what scopes memories, files and conversations to that agent. Omit it only when you are not acting as any Dudamel agent.'
155
162
  );
156
163
  function agentNameInput(ctx) {
@@ -180,14 +187,14 @@ function scopeDescription(unbound) {
180
187
  var AGENT_SCOPES = /* @__PURE__ */ new Set(["relational", "agent"]);
181
188
  function registerMemoryTools(server, client, ctx) {
182
189
  const unbound = ctx.agentName === null;
183
- const scopes = z2.enum(["relational", "profile", "agent", "org"]);
190
+ const scopes = z3.enum(["relational", "profile", "agent", "org"]);
184
191
  const agentInput = agentNameInput(ctx);
185
192
  server.registerTool(
186
193
  "list-memories",
187
194
  {
188
195
  description: "List memories relevant to the current user (summaries only, NOT full content). Returns the union of everything you know that applies here: your notes on this user, their profile, and your/org general knowledge" + (unbound ? " (without agentName: only their profile and org knowledge). " : ". ") + "Call this at the start of an interaction. You MUST call this before creating a memory. Use get-memory to read a full entry.",
189
196
  inputSchema: {
190
- q: z2.string().optional().describe("Keyword filter over summary + content (omit to list all)"),
197
+ q: z3.string().optional().describe("Keyword filter over summary + content (omit to list all)"),
191
198
  scope: scopes.optional().describe("Filter to a single scope"),
192
199
  ...agentInput
193
200
  },
@@ -213,7 +220,7 @@ function registerMemoryTools(server, client, ctx) {
213
220
  "get-memory",
214
221
  {
215
222
  description: "Get the full content of a single memory by id. You MUST call this before updating a memory (so you edit its real content, not blindly). Ids come from list-memories.",
216
- inputSchema: { id: z2.string().describe("Memory id (from list-memories)"), ...agentInput },
223
+ inputSchema: { id: z3.string().describe("Memory id (from list-memories)"), ...agentInput },
217
224
  annotations: { readOnlyHint: true }
218
225
  },
219
226
  async ({ id, agentName }) => {
@@ -238,7 +245,7 @@ function registerMemoryTools(server, client, ctx) {
238
245
  description: "Create a NEW memory. Requires a prior list-memories call this session (to avoid duplicates \u2014 if a similar memory exists, use update-memory instead). Content can be multi-line markdown. A one-line summary is generated automatically; if the summary service is unavailable the memory is NOT saved and you should retry later.",
239
246
  inputSchema: {
240
247
  scope: scopes.describe(scopeDescription(unbound)),
241
- content: z2.string().describe("Full memory text (multi-line markdown allowed)"),
248
+ content: z3.string().describe("Full memory text (multi-line markdown allowed)"),
242
249
  ...agentInput
243
250
  },
244
251
  annotations: { readOnlyHint: false, destructiveHint: false }
@@ -276,8 +283,8 @@ function registerMemoryTools(server, client, ctx) {
276
283
  {
277
284
  description: "Update an existing memory's content (its summary is regenerated). You MUST call get-memory on this id first, so you edit its real content. If the summary service is unavailable the memory is NOT updated and you should retry later.",
278
285
  inputSchema: {
279
- id: z2.string().describe("Memory id to update"),
280
- content: z2.string().describe("New full memory text (replaces the old content)"),
286
+ id: z3.string().describe("Memory id to update"),
287
+ content: z3.string().describe("New full memory text (replaces the old content)"),
281
288
  ...agentInput
282
289
  },
283
290
  annotations: { readOnlyHint: false, destructiveHint: false }
@@ -304,7 +311,7 @@ function registerMemoryTools(server, client, ctx) {
304
311
  "delete-memory",
305
312
  {
306
313
  description: "Delete a memory by id. Requires the id to have been seen via list-memories or get-memory.",
307
- inputSchema: { id: z2.string().describe("Memory id to delete"), ...agentInput },
314
+ inputSchema: { id: z3.string().describe("Memory id to delete"), ...agentInput },
308
315
  annotations: { readOnlyHint: false, destructiveHint: true }
309
316
  },
310
317
  async ({ id, agentName }) => {
@@ -327,7 +334,7 @@ function registerMemoryTools(server, client, ctx) {
327
334
  "mark-memory-useful",
328
335
  {
329
336
  description: "Mark a memory as useful now (bumps its recency ranking). Requires the id to have been seen via list-memories or get-memory.",
330
- inputSchema: { id: z2.string().describe("Memory id to mark as useful"), ...agentInput },
337
+ inputSchema: { id: z3.string().describe("Memory id to mark as useful"), ...agentInput },
331
338
  annotations: { readOnlyHint: false, destructiveHint: false }
332
339
  },
333
340
  async ({ id, agentName }) => {
@@ -351,7 +358,7 @@ function registerMemoryTools(server, client, ctx) {
351
358
  }
352
359
 
353
360
  // src/tools/conversations.ts
354
- import { z as z3 } from "zod";
361
+ import { z as z4 } from "zod";
355
362
  function registerConversationTools(server, client, ctx) {
356
363
  server.registerTool(
357
364
  "list-conversations",
@@ -374,7 +381,7 @@ function registerConversationTools(server, client, ctx) {
374
381
  {
375
382
  description: "Get the full message history for a specific conversation. Returns all messages in chronological order.",
376
383
  inputSchema: {
377
- conversationId: z3.string().describe("The conversation ID to retrieve messages for")
384
+ conversationId: z4.string().describe("The conversation ID to retrieve messages for")
378
385
  },
379
386
  annotations: { readOnlyHint: true }
380
387
  },
@@ -390,7 +397,7 @@ function registerConversationTools(server, client, ctx) {
390
397
  }
391
398
 
392
399
  // src/tools/files.ts
393
- import { z as z4 } from "zod";
400
+ import { z as z5 } from "zod";
394
401
  function registerFileTools(server, client, ctx) {
395
402
  const agentInput = agentNameInput(ctx);
396
403
  server.registerTool(
@@ -398,10 +405,10 @@ function registerFileTools(server, client, ctx) {
398
405
  {
399
406
  description: "Store a file so it survives this turn. The turn workspace is wiped when the turn ends, so anything you want to keep \u2014 a report, a diff, a generated CSV \u2014 has to be saved here. Returns an id you can hand back to the user or use in a later turn. Content goes base64-encoded.",
400
407
  inputSchema: {
401
- fileName: z4.string().describe('Name for the file, e.g. "informe-q3.csv"'),
402
- mimeType: z4.string().describe('MIME type, e.g. "text/csv" or "application/pdf"'),
403
- contentBase64: z4.string().describe("File content, base64-encoded"),
404
- conversationId: z4.string().optional().describe("Conversation this belongs to. Defaults to the current one."),
408
+ fileName: z5.string().describe('Name for the file, e.g. "informe-q3.csv"'),
409
+ mimeType: z5.string().describe('MIME type, e.g. "text/csv" or "application/pdf"'),
410
+ contentBase64: z5.string().describe("File content, base64-encoded"),
411
+ conversationId: z5.string().optional().describe("Conversation this belongs to. Defaults to the current one."),
405
412
  ...agentInput
406
413
  },
407
414
  annotations: { readOnlyHint: false, destructiveHint: false }
@@ -429,9 +436,9 @@ function registerFileTools(server, client, ctx) {
429
436
  {
430
437
  description: "List stored files for this conversation (default) or for this agent across conversations. Returns metadata only \u2014 ids, names, types, sizes \u2014 not content.",
431
438
  inputSchema: {
432
- conversationId: z4.string().optional().describe("Conversation to list. Defaults to the current one."),
433
- allConversations: z4.boolean().optional().describe("List everything this agent saved, not just this conversation's"),
434
- limit: z4.number().optional().describe("Max files to return (default 50)"),
439
+ conversationId: z5.string().optional().describe("Conversation to list. Defaults to the current one."),
440
+ allConversations: z5.boolean().optional().describe("List everything this agent saved, not just this conversation's"),
441
+ limit: z5.number().optional().describe("Max files to return (default 50)"),
435
442
  ...agentInput
436
443
  },
437
444
  annotations: { readOnlyHint: true }
@@ -455,7 +462,7 @@ function registerFileTools(server, client, ctx) {
455
462
  {
456
463
  description: "Read a stored file by id. Small text files come back with their content inline; anything large or binary returns metadata only, and you should pass the id along rather than trying to read the bytes \u2014 they would not fit in your context anyway.",
457
464
  inputSchema: {
458
- id: z4.string().describe("File id from save-file or list-files")
465
+ id: z5.string().describe("File id from save-file or list-files")
459
466
  },
460
467
  annotations: { readOnlyHint: true }
461
468
  },
@@ -472,7 +479,7 @@ function registerFileTools(server, client, ctx) {
472
479
  {
473
480
  description: "Hand a stored file to the user in this conversation. Use it after save-file when the user should actually receive the file \u2014 saving alone only keeps it. It is delivered right after your reply, through whatever channel you are talking on; you do not need to know which.",
474
481
  inputSchema: {
475
- id: z4.string().describe("File id from save-file or list-files")
482
+ id: z5.string().describe("File id from save-file or list-files")
476
483
  },
477
484
  annotations: { readOnlyHint: false, destructiveHint: false }
478
485
  },
@@ -489,7 +496,7 @@ function registerFileTools(server, client, ctx) {
489
496
  {
490
497
  description: "Delete a stored file permanently. Use it for things you produced and no longer need \u2014 not for files a user uploaded, unless they asked.",
491
498
  inputSchema: {
492
- id: z4.string().describe("File id from save-file or list-files")
499
+ id: z5.string().describe("File id from save-file or list-files")
493
500
  },
494
501
  annotations: { readOnlyHint: false, destructiveHint: true }
495
502
  },
@@ -39,6 +39,10 @@ var DudamelApiError = class extends Error {
39
39
  if (apiError?.context?.["inputsSchema"] !== void 0) {
40
40
  lines.push(`Expected inputs schema: ${JSON.stringify(apiError.context["inputsSchema"])}`);
41
41
  }
42
+ const rest = Object.entries(apiError?.context ?? {}).filter(([key]) => key !== "inputsSchema");
43
+ if (rest.length > 0) {
44
+ lines.push(`Context: ${JSON.stringify(Object.fromEntries(rest))}`);
45
+ }
42
46
  super(lines.join("\n"));
43
47
  this.status = status;
44
48
  this.statusText = statusText;
@@ -159,15 +163,18 @@ function errorResult(error) {
159
163
  };
160
164
  }
161
165
 
166
+ // ../common/dist/owner-tools.js
167
+ import { z } from "zod";
168
+
162
169
  // src/server.ts
163
170
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
164
171
 
165
172
  // src/tools/memories.ts
166
- import { z as z2 } from "zod";
173
+ import { z as z3 } from "zod";
167
174
 
168
175
  // src/util.ts
169
- import { z } from "zod";
170
- var AGENT_NAME_FIELD = z.string().optional().describe(
176
+ import { z as z2 } from "zod";
177
+ var AGENT_NAME_FIELD = z2.string().optional().describe(
171
178
  'The Dudamel agent you are acting as (e.g. "dudamel-expert"). Pass it on every call when you are one \u2014 it is what scopes memories, files and conversations to that agent. Omit it only when you are not acting as any Dudamel agent.'
172
179
  );
173
180
  function agentNameInput(ctx) {
@@ -197,14 +204,14 @@ function scopeDescription(unbound) {
197
204
  var AGENT_SCOPES = /* @__PURE__ */ new Set(["relational", "agent"]);
198
205
  function registerMemoryTools(server2, client, ctx) {
199
206
  const unbound = ctx.agentName === null;
200
- const scopes = z2.enum(["relational", "profile", "agent", "org"]);
207
+ const scopes = z3.enum(["relational", "profile", "agent", "org"]);
201
208
  const agentInput = agentNameInput(ctx);
202
209
  server2.registerTool(
203
210
  "list-memories",
204
211
  {
205
212
  description: "List memories relevant to the current user (summaries only, NOT full content). Returns the union of everything you know that applies here: your notes on this user, their profile, and your/org general knowledge" + (unbound ? " (without agentName: only their profile and org knowledge). " : ". ") + "Call this at the start of an interaction. You MUST call this before creating a memory. Use get-memory to read a full entry.",
206
213
  inputSchema: {
207
- q: z2.string().optional().describe("Keyword filter over summary + content (omit to list all)"),
214
+ q: z3.string().optional().describe("Keyword filter over summary + content (omit to list all)"),
208
215
  scope: scopes.optional().describe("Filter to a single scope"),
209
216
  ...agentInput
210
217
  },
@@ -230,7 +237,7 @@ function registerMemoryTools(server2, client, ctx) {
230
237
  "get-memory",
231
238
  {
232
239
  description: "Get the full content of a single memory by id. You MUST call this before updating a memory (so you edit its real content, not blindly). Ids come from list-memories.",
233
- inputSchema: { id: z2.string().describe("Memory id (from list-memories)"), ...agentInput },
240
+ inputSchema: { id: z3.string().describe("Memory id (from list-memories)"), ...agentInput },
234
241
  annotations: { readOnlyHint: true }
235
242
  },
236
243
  async ({ id, agentName: agentName2 }) => {
@@ -255,7 +262,7 @@ function registerMemoryTools(server2, client, ctx) {
255
262
  description: "Create a NEW memory. Requires a prior list-memories call this session (to avoid duplicates \u2014 if a similar memory exists, use update-memory instead). Content can be multi-line markdown. A one-line summary is generated automatically; if the summary service is unavailable the memory is NOT saved and you should retry later.",
256
263
  inputSchema: {
257
264
  scope: scopes.describe(scopeDescription(unbound)),
258
- content: z2.string().describe("Full memory text (multi-line markdown allowed)"),
265
+ content: z3.string().describe("Full memory text (multi-line markdown allowed)"),
259
266
  ...agentInput
260
267
  },
261
268
  annotations: { readOnlyHint: false, destructiveHint: false }
@@ -293,8 +300,8 @@ function registerMemoryTools(server2, client, ctx) {
293
300
  {
294
301
  description: "Update an existing memory's content (its summary is regenerated). You MUST call get-memory on this id first, so you edit its real content. If the summary service is unavailable the memory is NOT updated and you should retry later.",
295
302
  inputSchema: {
296
- id: z2.string().describe("Memory id to update"),
297
- content: z2.string().describe("New full memory text (replaces the old content)"),
303
+ id: z3.string().describe("Memory id to update"),
304
+ content: z3.string().describe("New full memory text (replaces the old content)"),
298
305
  ...agentInput
299
306
  },
300
307
  annotations: { readOnlyHint: false, destructiveHint: false }
@@ -321,7 +328,7 @@ function registerMemoryTools(server2, client, ctx) {
321
328
  "delete-memory",
322
329
  {
323
330
  description: "Delete a memory by id. Requires the id to have been seen via list-memories or get-memory.",
324
- inputSchema: { id: z2.string().describe("Memory id to delete"), ...agentInput },
331
+ inputSchema: { id: z3.string().describe("Memory id to delete"), ...agentInput },
325
332
  annotations: { readOnlyHint: false, destructiveHint: true }
326
333
  },
327
334
  async ({ id, agentName: agentName2 }) => {
@@ -344,7 +351,7 @@ function registerMemoryTools(server2, client, ctx) {
344
351
  "mark-memory-useful",
345
352
  {
346
353
  description: "Mark a memory as useful now (bumps its recency ranking). Requires the id to have been seen via list-memories or get-memory.",
347
- inputSchema: { id: z2.string().describe("Memory id to mark as useful"), ...agentInput },
354
+ inputSchema: { id: z3.string().describe("Memory id to mark as useful"), ...agentInput },
348
355
  annotations: { readOnlyHint: false, destructiveHint: false }
349
356
  },
350
357
  async ({ id, agentName: agentName2 }) => {
@@ -368,7 +375,7 @@ function registerMemoryTools(server2, client, ctx) {
368
375
  }
369
376
 
370
377
  // src/tools/conversations.ts
371
- import { z as z3 } from "zod";
378
+ import { z as z4 } from "zod";
372
379
  function registerConversationTools(server2, client, ctx) {
373
380
  server2.registerTool(
374
381
  "list-conversations",
@@ -391,7 +398,7 @@ function registerConversationTools(server2, client, ctx) {
391
398
  {
392
399
  description: "Get the full message history for a specific conversation. Returns all messages in chronological order.",
393
400
  inputSchema: {
394
- conversationId: z3.string().describe("The conversation ID to retrieve messages for")
401
+ conversationId: z4.string().describe("The conversation ID to retrieve messages for")
395
402
  },
396
403
  annotations: { readOnlyHint: true }
397
404
  },
@@ -407,7 +414,7 @@ function registerConversationTools(server2, client, ctx) {
407
414
  }
408
415
 
409
416
  // src/tools/files.ts
410
- import { z as z4 } from "zod";
417
+ import { z as z5 } from "zod";
411
418
  function registerFileTools(server2, client, ctx) {
412
419
  const agentInput = agentNameInput(ctx);
413
420
  server2.registerTool(
@@ -415,10 +422,10 @@ function registerFileTools(server2, client, ctx) {
415
422
  {
416
423
  description: "Store a file so it survives this turn. The turn workspace is wiped when the turn ends, so anything you want to keep \u2014 a report, a diff, a generated CSV \u2014 has to be saved here. Returns an id you can hand back to the user or use in a later turn. Content goes base64-encoded.",
417
424
  inputSchema: {
418
- fileName: z4.string().describe('Name for the file, e.g. "informe-q3.csv"'),
419
- mimeType: z4.string().describe('MIME type, e.g. "text/csv" or "application/pdf"'),
420
- contentBase64: z4.string().describe("File content, base64-encoded"),
421
- conversationId: z4.string().optional().describe("Conversation this belongs to. Defaults to the current one."),
425
+ fileName: z5.string().describe('Name for the file, e.g. "informe-q3.csv"'),
426
+ mimeType: z5.string().describe('MIME type, e.g. "text/csv" or "application/pdf"'),
427
+ contentBase64: z5.string().describe("File content, base64-encoded"),
428
+ conversationId: z5.string().optional().describe("Conversation this belongs to. Defaults to the current one."),
422
429
  ...agentInput
423
430
  },
424
431
  annotations: { readOnlyHint: false, destructiveHint: false }
@@ -446,9 +453,9 @@ function registerFileTools(server2, client, ctx) {
446
453
  {
447
454
  description: "List stored files for this conversation (default) or for this agent across conversations. Returns metadata only \u2014 ids, names, types, sizes \u2014 not content.",
448
455
  inputSchema: {
449
- conversationId: z4.string().optional().describe("Conversation to list. Defaults to the current one."),
450
- allConversations: z4.boolean().optional().describe("List everything this agent saved, not just this conversation's"),
451
- limit: z4.number().optional().describe("Max files to return (default 50)"),
456
+ conversationId: z5.string().optional().describe("Conversation to list. Defaults to the current one."),
457
+ allConversations: z5.boolean().optional().describe("List everything this agent saved, not just this conversation's"),
458
+ limit: z5.number().optional().describe("Max files to return (default 50)"),
452
459
  ...agentInput
453
460
  },
454
461
  annotations: { readOnlyHint: true }
@@ -472,7 +479,7 @@ function registerFileTools(server2, client, ctx) {
472
479
  {
473
480
  description: "Read a stored file by id. Small text files come back with their content inline; anything large or binary returns metadata only, and you should pass the id along rather than trying to read the bytes \u2014 they would not fit in your context anyway.",
474
481
  inputSchema: {
475
- id: z4.string().describe("File id from save-file or list-files")
482
+ id: z5.string().describe("File id from save-file or list-files")
476
483
  },
477
484
  annotations: { readOnlyHint: true }
478
485
  },
@@ -489,7 +496,7 @@ function registerFileTools(server2, client, ctx) {
489
496
  {
490
497
  description: "Hand a stored file to the user in this conversation. Use it after save-file when the user should actually receive the file \u2014 saving alone only keeps it. It is delivered right after your reply, through whatever channel you are talking on; you do not need to know which.",
491
498
  inputSchema: {
492
- id: z4.string().describe("File id from save-file or list-files")
499
+ id: z5.string().describe("File id from save-file or list-files")
493
500
  },
494
501
  annotations: { readOnlyHint: false, destructiveHint: false }
495
502
  },
@@ -506,7 +513,7 @@ function registerFileTools(server2, client, ctx) {
506
513
  {
507
514
  description: "Delete a stored file permanently. Use it for things you produced and no longer need \u2014 not for files a user uploaded, unless they asked.",
508
515
  inputSchema: {
509
- id: z4.string().describe("File id from save-file or list-files")
516
+ id: z5.string().describe("File id from save-file or list-files")
510
517
  },
511
518
  annotations: { readOnlyHint: false, destructiveHint: true }
512
519
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudamel/mcp-memory",
3
- "version": "2026.1104.1",
3
+ "version": "2026.1106.2",
4
4
  "description": "Dudamel Memory MCP — stdio client for an org's Dudamel memory (agent/user knowledge) over its REST API.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "type": "module",