@prmichaelsen/remember-mcp 4.0.2 → 4.1.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.
Files changed (74) hide show
  1. package/AGENT.md +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/agent/commands/acp.artifact-glossary.md +22 -0
  4. package/agent/commands/acp.artifact-reference.md +21 -0
  5. package/agent/commands/acp.artifact-research.md +20 -0
  6. package/agent/commands/acp.audit.md +19 -0
  7. package/agent/commands/acp.clarification-address.md +20 -0
  8. package/agent/commands/acp.clarification-capture.md +9 -0
  9. package/agent/commands/acp.clarification-create.md +20 -0
  10. package/agent/commands/acp.command-create.md +20 -0
  11. package/agent/commands/acp.design-create.md +20 -0
  12. package/agent/commands/acp.design-reference.md +9 -0
  13. package/agent/commands/acp.handoff.md +17 -0
  14. package/agent/commands/acp.index.md +23 -0
  15. package/agent/commands/acp.init.md +25 -2
  16. package/agent/commands/acp.package-create.md +14 -0
  17. package/agent/commands/acp.package-info.md +17 -0
  18. package/agent/commands/acp.package-install.md +20 -0
  19. package/agent/commands/acp.package-list.md +20 -0
  20. package/agent/commands/acp.package-publish.md +13 -0
  21. package/agent/commands/acp.package-remove.md +18 -0
  22. package/agent/commands/acp.package-search.md +19 -0
  23. package/agent/commands/acp.package-update.md +21 -0
  24. package/agent/commands/acp.package-validate.md +14 -0
  25. package/agent/commands/acp.pattern-create.md +20 -0
  26. package/agent/commands/acp.plan.md +42 -13
  27. package/agent/commands/acp.proceed.md +55 -21
  28. package/agent/commands/acp.project-create.md +13 -0
  29. package/agent/commands/acp.project-info.md +17 -0
  30. package/agent/commands/acp.project-list.md +19 -0
  31. package/agent/commands/acp.project-remove.md +18 -0
  32. package/agent/commands/acp.project-set.md +16 -0
  33. package/agent/commands/acp.project-update.md +22 -0
  34. package/agent/commands/acp.projects-restore.md +18 -0
  35. package/agent/commands/acp.projects-sync.md +14 -0
  36. package/agent/commands/acp.report.md +15 -0
  37. package/agent/commands/acp.resume.md +15 -0
  38. package/agent/commands/acp.sessions.md +21 -0
  39. package/agent/commands/acp.status.md +15 -0
  40. package/agent/commands/acp.sync.md +15 -0
  41. package/agent/commands/acp.task-create.md +21 -0
  42. package/agent/commands/acp.update.md +15 -0
  43. package/agent/commands/acp.validate.md +25 -2
  44. package/agent/commands/acp.version-check-for-updates.md +13 -0
  45. package/agent/commands/acp.version-check.md +13 -0
  46. package/agent/commands/acp.version-update.md +14 -0
  47. package/agent/commands/command.template.md +33 -0
  48. package/agent/commands/git.commit.md +14 -0
  49. package/agent/commands/git.init.md +13 -0
  50. package/agent/manifest.yaml +3 -3
  51. package/agent/milestones/milestone-24-mcp-elicitation-confirmation.md +99 -0
  52. package/agent/progress.yaml +1406 -1327
  53. package/agent/tasks/milestone-24-mcp-elicitation-confirmation/task-530-create-elicitation-helper.md +78 -0
  54. package/agent/tasks/milestone-24-mcp-elicitation-confirmation/task-531-update-handler-signatures.md +62 -0
  55. package/agent/tasks/milestone-24-mcp-elicitation-confirmation/task-532-implement-elicitation-in-tools.md +113 -0
  56. package/agent/tasks/milestone-24-mcp-elicitation-confirmation/task-533-wire-server-instance.md +62 -0
  57. package/agent/tasks/milestone-24-mcp-elicitation-confirmation/task-534-verification-cleanup.md +60 -0
  58. package/dist/server-factory.js +183 -13
  59. package/dist/server.js +183 -13
  60. package/dist/tools/delete-memory.d.ts +2 -1
  61. package/dist/tools/publish.d.ts +2 -1
  62. package/dist/tools/request-set-trust-level.d.ts +2 -1
  63. package/dist/tools/retract.d.ts +2 -1
  64. package/dist/tools/revise.d.ts +2 -1
  65. package/dist/utils/elicitation.d.ts +31 -0
  66. package/package.json +1 -1
  67. package/src/server-factory.ts +5 -5
  68. package/src/server.ts +5 -5
  69. package/src/tools/delete-memory.ts +51 -3
  70. package/src/tools/publish.ts +37 -1
  71. package/src/tools/request-set-trust-level.ts +35 -4
  72. package/src/tools/retract.ts +37 -1
  73. package/src/tools/revise.ts +39 -1
  74. package/src/utils/elicitation.ts +53 -0
package/dist/server.js CHANGED
@@ -1329,6 +1329,27 @@ async function handleSearchMemory(args, userId, authContext) {
1329
1329
  }
1330
1330
  }
1331
1331
 
1332
+ // src/utils/elicitation.ts
1333
+ async function elicitConfirmation(params) {
1334
+ const { server, message } = params;
1335
+ if (!server)
1336
+ return { type: "unsupported" };
1337
+ const caps = server.getClientCapabilities();
1338
+ if (!caps?.elicitation)
1339
+ return { type: "unsupported" };
1340
+ try {
1341
+ const result = await server.elicitInput({
1342
+ message,
1343
+ requestedSchema: { type: "object", properties: {} }
1344
+ });
1345
+ if (result.action === "accept")
1346
+ return { type: "confirmed" };
1347
+ return { type: "declined", reason: result.action };
1348
+ } catch {
1349
+ return { type: "unsupported" };
1350
+ }
1351
+ }
1352
+
1332
1353
  // src/tools/delete-memory.ts
1333
1354
  var deleteMemoryTool = {
1334
1355
  name: "remember_delete_memory",
@@ -1359,7 +1380,7 @@ Examples:
1359
1380
  required: ["memory_id"]
1360
1381
  }
1361
1382
  };
1362
- async function handleDeleteMemory(args, userId, authContext) {
1383
+ async function handleDeleteMemory(args, userId, authContext, server) {
1363
1384
  const debug = createDebugLogger({ tool: "remember_delete_memory", userId, operation: "delete memory" });
1364
1385
  try {
1365
1386
  debug.info("Tool invoked");
@@ -1373,6 +1394,44 @@ async function handleDeleteMemory(args, userId, authContext) {
1373
1394
  reason: args.reason || null
1374
1395
  }
1375
1396
  );
1397
+ const confirmation = await elicitConfirmation({
1398
+ server,
1399
+ message: `Delete memory "${args.memory_id}"${args.reason ? ` (reason: ${args.reason})` : ""}?`
1400
+ });
1401
+ if (confirmation.type === "confirmed") {
1402
+ const confirmed = await tokenService2.confirmRequest(userId, token);
1403
+ if (!confirmed) {
1404
+ return JSON.stringify(
1405
+ { success: false, error: "Token already consumed", message: "The confirmation token has already been used." },
1406
+ null,
1407
+ 2
1408
+ );
1409
+ }
1410
+ const { memory_id, reason } = confirmed.payload;
1411
+ const client2 = getWeaviateClient();
1412
+ const collectionName = getMemoryCollectionName(userId);
1413
+ const collection = client2.collections.get(collectionName);
1414
+ await collection.data.update({
1415
+ id: memory_id,
1416
+ properties: {
1417
+ deleted_at: (/* @__PURE__ */ new Date()).toISOString(),
1418
+ deleted_by: userId,
1419
+ deletion_reason: reason || null
1420
+ }
1421
+ });
1422
+ return JSON.stringify(
1423
+ { success: true, memory_id, message: "Memory deleted successfully" },
1424
+ null,
1425
+ 2
1426
+ );
1427
+ }
1428
+ if (confirmation.type === "declined") {
1429
+ return JSON.stringify(
1430
+ { success: false, message: "Deletion cancelled by user." },
1431
+ null,
1432
+ 2
1433
+ );
1434
+ }
1376
1435
  const expiresAt = new Date(Date.now() + 5 * 60 * 1e3);
1377
1436
  return JSON.stringify(
1378
1437
  {
@@ -2521,7 +2580,7 @@ Publication Destinations:
2521
2580
  required: ["memory_id"]
2522
2581
  }
2523
2582
  };
2524
- async function handlePublish(args, userId, authContext) {
2583
+ async function handlePublish(args, userId, authContext, server) {
2525
2584
  const debug = createDebugLogger({
2526
2585
  tool: "remember_publish",
2527
2586
  userId,
@@ -2537,6 +2596,34 @@ async function handlePublish(args, userId, authContext) {
2537
2596
  groups: args.groups,
2538
2597
  additional_tags: args.additional_tags
2539
2598
  });
2599
+ const destinations = [...args.spaces || [], ...args.groups || []].join(", ");
2600
+ const confirmation = await elicitConfirmation({
2601
+ server,
2602
+ message: `Publish memory "${args.memory_id}" to ${destinations || "default space"}?`
2603
+ });
2604
+ if (confirmation.type === "confirmed") {
2605
+ const confirmResult = await space.confirm({ token: result.token });
2606
+ return JSON.stringify(
2607
+ {
2608
+ success: confirmResult.success,
2609
+ composite_id: confirmResult.composite_id,
2610
+ published_to: confirmResult.published_to,
2611
+ failed: confirmResult.failed?.length ? confirmResult.failed : void 0,
2612
+ space_ids: confirmResult.space_ids,
2613
+ group_ids: confirmResult.group_ids
2614
+ },
2615
+ null,
2616
+ 2
2617
+ );
2618
+ }
2619
+ if (confirmation.type === "declined") {
2620
+ await space.deny({ token: result.token });
2621
+ return JSON.stringify(
2622
+ { success: false, message: "Publication cancelled by user." },
2623
+ null,
2624
+ 2
2625
+ );
2626
+ }
2540
2627
  return JSON.stringify(
2541
2628
  {
2542
2629
  success: true,
@@ -2599,7 +2686,7 @@ Orphaned memories are preserved for historical reference but become unsearchable
2599
2686
  required: ["memory_id"]
2600
2687
  }
2601
2688
  };
2602
- async function handleRetract(args, userId, authContext) {
2689
+ async function handleRetract(args, userId, authContext, server) {
2603
2690
  const debug = createDebugLogger({
2604
2691
  tool: "remember_retract",
2605
2692
  userId,
@@ -2614,6 +2701,35 @@ async function handleRetract(args, userId, authContext) {
2614
2701
  spaces: args.spaces,
2615
2702
  groups: args.groups
2616
2703
  });
2704
+ const destinations = [...args.spaces || [], ...args.groups || []].join(", ");
2705
+ const confirmation = await elicitConfirmation({
2706
+ server,
2707
+ message: `Retract memory "${args.memory_id}" from ${destinations || "all destinations"}?`
2708
+ });
2709
+ if (confirmation.type === "confirmed") {
2710
+ const confirmResult = await space.confirm({ token: result.token });
2711
+ return JSON.stringify(
2712
+ {
2713
+ success: confirmResult.success,
2714
+ composite_id: confirmResult.composite_id,
2715
+ retracted_from: confirmResult.retracted_from,
2716
+ failed: confirmResult.failed?.length ? confirmResult.failed : void 0,
2717
+ space_ids: confirmResult.space_ids,
2718
+ group_ids: confirmResult.group_ids,
2719
+ is_orphaned: confirmResult.space_ids?.length === 0 && confirmResult.group_ids?.length === 0
2720
+ },
2721
+ null,
2722
+ 2
2723
+ );
2724
+ }
2725
+ if (confirmation.type === "declined") {
2726
+ await space.deny({ token: result.token });
2727
+ return JSON.stringify(
2728
+ { success: false, message: "Retraction cancelled by user." },
2729
+ null,
2730
+ 2
2731
+ );
2732
+ }
2617
2733
  return JSON.stringify(
2618
2734
  {
2619
2735
  success: true,
@@ -2672,7 +2788,7 @@ Requirements:
2672
2788
  required: ["memory_id"]
2673
2789
  }
2674
2790
  };
2675
- async function handleRevise(args, userId, authContext) {
2791
+ async function handleRevise(args, userId, authContext, server) {
2676
2792
  const debug = createDebugLogger({
2677
2793
  tool: "remember_revise",
2678
2794
  userId,
@@ -2685,6 +2801,37 @@ async function handleRevise(args, userId, authContext) {
2685
2801
  const result = await space.revise({
2686
2802
  memory_id: args.memory_id
2687
2803
  });
2804
+ const confirmation = await elicitConfirmation({
2805
+ server,
2806
+ message: `Revise all published copies of memory "${args.memory_id}"?`
2807
+ });
2808
+ if (confirmation.type === "confirmed") {
2809
+ const confirmResult = await space.confirm({ token: result.token });
2810
+ const results = confirmResult.results || [];
2811
+ const successCount = results.filter((r) => r.status === "success").length;
2812
+ const failedCount = results.filter((r) => r.status === "failed").length;
2813
+ const skippedCount = results.filter((r) => r.status === "skipped").length;
2814
+ return JSON.stringify(
2815
+ {
2816
+ success: confirmResult.success,
2817
+ composite_id: confirmResult.composite_id,
2818
+ revised_at: confirmResult.revised_at,
2819
+ summary: { total: results.length, success: successCount, failed: failedCount, skipped: skippedCount },
2820
+ results,
2821
+ ...failedCount > 0 ? { warnings: [`Failed to revise ${failedCount} of ${results.length} location(s)`] } : {}
2822
+ },
2823
+ null,
2824
+ 2
2825
+ );
2826
+ }
2827
+ if (confirmation.type === "declined") {
2828
+ await space.deny({ token: result.token });
2829
+ return JSON.stringify(
2830
+ { success: false, message: "Revision cancelled by user." },
2831
+ null,
2832
+ 2
2833
+ );
2834
+ }
2688
2835
  return JSON.stringify(
2689
2836
  {
2690
2837
  success: true,
@@ -3691,7 +3838,7 @@ This is the ONLY way to change a memory's trust level. Trust cannot be set durin
3691
3838
  required: ["memory_id", "trust_level"]
3692
3839
  }
3693
3840
  };
3694
- async function handleRequestSetTrustLevel(args, userId, authContext) {
3841
+ async function handleRequestSetTrustLevel(args, userId, authContext, server) {
3695
3842
  const debug = createDebugLogger({
3696
3843
  tool: "remember_request_set_trust_level",
3697
3844
  userId,
@@ -3718,6 +3865,29 @@ async function handleRequestSetTrustLevel(args, userId, authContext) {
3718
3865
  4: "RESTRICTED",
3719
3866
  5: "SECRET"
3720
3867
  };
3868
+ const currentName = TRUST_NAMES[result.current_trust_level] || "UNKNOWN";
3869
+ const requestedName = TRUST_NAMES[result.requested_trust_level] || "UNKNOWN";
3870
+ const confirmation = await elicitConfirmation({
3871
+ server,
3872
+ message: `Change trust level for memory "${args.memory_id}" from ${currentName} (${result.current_trust_level}) to ${requestedName} (${result.requested_trust_level})?`
3873
+ });
3874
+ if (confirmation.type === "confirmed") {
3875
+ const confirmResult = await memory.confirmSetTrustLevel(result.token);
3876
+ return JSON.stringify({
3877
+ success: true,
3878
+ memory_id: confirmResult.memory_id,
3879
+ previous_trust_level: confirmResult.previous_trust_level,
3880
+ new_trust_level: confirmResult.new_trust_level,
3881
+ updated_at: confirmResult.updated_at,
3882
+ message: `Trust level changed from ${TRUST_NAMES[confirmResult.previous_trust_level] || confirmResult.previous_trust_level} to ${TRUST_NAMES[confirmResult.new_trust_level] || confirmResult.new_trust_level}`
3883
+ }, null, 2);
3884
+ }
3885
+ if (confirmation.type === "declined") {
3886
+ return JSON.stringify({
3887
+ success: false,
3888
+ message: "Trust level change cancelled by user."
3889
+ }, null, 2);
3890
+ }
3721
3891
  return JSON.stringify({
3722
3892
  token: result.token,
3723
3893
  request_id: result.request_id,
@@ -3725,10 +3895,10 @@ async function handleRequestSetTrustLevel(args, userId, authContext) {
3725
3895
  memory_id: result.memory_id,
3726
3896
  current_trust_level: result.current_trust_level,
3727
3897
  requested_trust_level: result.requested_trust_level,
3728
- current_trust_name: TRUST_NAMES[result.current_trust_level] || "UNKNOWN",
3729
- requested_trust_name: TRUST_NAMES[result.requested_trust_level] || "UNKNOWN",
3898
+ current_trust_name: currentName,
3899
+ requested_trust_name: requestedName,
3730
3900
  expires_at: result.expires_at,
3731
- message: `Trust level change requested: ${TRUST_NAMES[result.current_trust_level] || result.current_trust_level} (${result.current_trust_level}) \u2192 ${TRUST_NAMES[result.requested_trust_level] || result.requested_trust_level} (${result.requested_trust_level}). Confirm with token to apply.`
3901
+ message: `Trust level change requested: ${currentName} (${result.current_trust_level}) \u2192 ${requestedName} (${result.requested_trust_level}). Confirm with token to apply.`
3732
3902
  }, null, 2);
3733
3903
  } catch (error) {
3734
3904
  debug.error("Tool failed", { error: error instanceof Error ? error.message : String(error) });
@@ -3819,7 +3989,7 @@ function registerHandlers(server) {
3819
3989
  result = await handleSearchMemory(args, userId, authContext);
3820
3990
  break;
3821
3991
  case "remember_delete_memory":
3822
- result = await handleDeleteMemory(args, userId, authContext);
3992
+ result = await handleDeleteMemory(args, userId, authContext, server);
3823
3993
  break;
3824
3994
  case "remember_update_memory":
3825
3995
  result = await handleUpdateMemory(args, userId, authContext);
@@ -3849,13 +4019,13 @@ function registerHandlers(server) {
3849
4019
  result = await handleGetPreferences(args, userId, authContext);
3850
4020
  break;
3851
4021
  case "remember_publish":
3852
- result = await handlePublish(args, userId, authContext);
4022
+ result = await handlePublish(args, userId, authContext, server);
3853
4023
  break;
3854
4024
  case "remember_retract":
3855
- result = await handleRetract(args, userId, authContext);
4025
+ result = await handleRetract(args, userId, authContext, server);
3856
4026
  break;
3857
4027
  case "remember_revise":
3858
- result = await handleRevise(args, userId, authContext);
4028
+ result = await handleRevise(args, userId, authContext, server);
3859
4029
  break;
3860
4030
  case "remember_confirm":
3861
4031
  result = await handleConfirm(args, userId, authContext);
@@ -3876,7 +4046,7 @@ function registerHandlers(server) {
3876
4046
  result = await handleGhostConfig(args, userId, authContext);
3877
4047
  break;
3878
4048
  case "remember_request_set_trust_level":
3879
- result = await handleRequestSetTrustLevel(args, userId, authContext);
4049
+ result = await handleRequestSetTrustLevel(args, userId, authContext, server);
3880
4050
  break;
3881
4051
  default:
3882
4052
  throw new McpError(
@@ -3,6 +3,7 @@
3
3
  * Request to delete a memory (requires confirmation)
4
4
  */
5
5
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
6
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
7
  import type { AuthContext } from '../types/auth.js';
7
8
  /**
8
9
  * Tool definition for remember_delete_memory
@@ -19,5 +20,5 @@ export interface DeleteMemoryArgs {
19
20
  * Handle remember_delete_memory tool
20
21
  * Creates confirmation token and returns preview
21
22
  */
22
- export declare function handleDeleteMemory(args: DeleteMemoryArgs, userId: string, authContext?: AuthContext): Promise<string>;
23
+ export declare function handleDeleteMemory(args: DeleteMemoryArgs, userId: string, authContext?: AuthContext, server?: Server): Promise<string>;
23
24
  //# sourceMappingURL=delete-memory.d.ts.map
@@ -11,6 +11,7 @@
11
11
  * - Maintains tracking arrays (space_ids, group_ids) on source memory
12
12
  */
13
13
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
14
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
14
15
  import type { AuthContext } from '../types/auth.js';
15
16
  /**
16
17
  * Tool definition for remember_publish
@@ -25,6 +26,6 @@ interface PublishArgs {
25
26
  /**
26
27
  * Handle remember_publish tool execution
27
28
  */
28
- export declare function handlePublish(args: PublishArgs, userId: string, authContext?: AuthContext): Promise<string>;
29
+ export declare function handlePublish(args: PublishArgs, userId: string, authContext?: AuthContext, server?: Server): Promise<string>;
29
30
  export {};
30
31
  //# sourceMappingURL=publish.d.ts.map
@@ -2,6 +2,7 @@
2
2
  * remember_request_set_trust_level tool
3
3
  * Requests a trust level change for a memory via confirmation flow.
4
4
  */
5
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
6
  import type { AuthContext } from '../types/auth.js';
6
7
  export declare const requestSetTrustLevelTool: {
7
8
  name: string;
@@ -27,6 +28,6 @@ interface RequestSetTrustLevelArgs {
27
28
  memory_id: string;
28
29
  trust_level: number;
29
30
  }
30
- export declare function handleRequestSetTrustLevel(args: RequestSetTrustLevelArgs, userId: string, authContext?: AuthContext): Promise<string>;
31
+ export declare function handleRequestSetTrustLevel(args: RequestSetTrustLevelArgs, userId: string, authContext?: AuthContext, server?: Server): Promise<string>;
31
32
  export {};
32
33
  //# sourceMappingURL=request-set-trust-level.d.ts.map
@@ -11,6 +11,7 @@
11
11
  * - Tracking arrays updated on source memory
12
12
  */
13
13
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
14
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
14
15
  import type { AuthContext } from '../types/auth.js';
15
16
  /**
16
17
  * Tool definition for remember_retract
@@ -24,6 +25,6 @@ interface RetractArgs {
24
25
  /**
25
26
  * Handle remember_retract tool execution
26
27
  */
27
- export declare function handleRetract(args: RetractArgs, userId: string, authContext?: AuthContext): Promise<string>;
28
+ export declare function handleRetract(args: RetractArgs, userId: string, authContext?: AuthContext, server?: Server): Promise<string>;
28
29
  export {};
29
30
  //# sourceMappingURL=retract.d.ts.map
@@ -8,6 +8,7 @@
8
8
  * before revision is executed. The old content is preserved in revision_history.
9
9
  */
10
10
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
11
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
12
  import type { AuthContext } from '../types/auth.js';
12
13
  /**
13
14
  * Tool definition for remember_revise
@@ -40,6 +41,6 @@ export declare function buildRevisionHistory(existing: RevisionEntry[], oldConte
40
41
  * Phase 1: Validates the request and generates a confirmation token.
41
42
  * The actual revision is executed in confirm.ts when the token is confirmed.
42
43
  */
43
- export declare function handleRevise(args: ReviseArgs, userId: string, authContext?: AuthContext): Promise<string>;
44
+ export declare function handleRevise(args: ReviseArgs, userId: string, authContext?: AuthContext, server?: Server): Promise<string>;
44
45
  export {};
45
46
  //# sourceMappingURL=revise.d.ts.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * MCP Elicitation helper for confirmation flows.
3
+ *
4
+ * Checks if the connected client supports elicitation, issues a
5
+ * confirmation-only prompt via server.elicitInput(), and returns a
6
+ * discriminated result. Falls back gracefully when the client (or
7
+ * server reference) doesn't support elicitation.
8
+ */
9
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
+ export interface ElicitConfirmParams {
11
+ server?: Server;
12
+ message: string;
13
+ }
14
+ export type ElicitConfirmResult = {
15
+ type: 'confirmed';
16
+ } | {
17
+ type: 'declined';
18
+ reason: string;
19
+ } | {
20
+ type: 'unsupported';
21
+ };
22
+ /**
23
+ * Ask the user for confirmation via MCP elicitation.
24
+ *
25
+ * - Returns `{ type: 'confirmed' }` when the user accepts.
26
+ * - Returns `{ type: 'declined', reason }` when the user declines or cancels.
27
+ * - Returns `{ type: 'unsupported' }` when elicitation is unavailable
28
+ * (no server, client lacks capability, or elicitation throws).
29
+ */
30
+ export declare function elicitConfirmation(params: ElicitConfirmParams): Promise<ElicitConfirmResult>;
31
+ //# sourceMappingURL=elicitation.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prmichaelsen/remember-mcp",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "description": "Multi-tenant memory system MCP server with vector search and relationships",
5
5
  "main": "dist/server.js",
6
6
  "type": "module",
@@ -388,7 +388,7 @@ function registerHandlers(
388
388
  break;
389
389
 
390
390
  case 'remember_delete_memory':
391
- result = await handleDeleteMemory(args as any, userId, authContext);
391
+ result = await handleDeleteMemory(args as any, userId, authContext, server);
392
392
  break;
393
393
 
394
394
  case 'remember_update_memory':
@@ -428,15 +428,15 @@ function registerHandlers(
428
428
  break;
429
429
 
430
430
  case 'remember_publish':
431
- result = await handlePublish(args as any, userId, authContext);
431
+ result = await handlePublish(args as any, userId, authContext, server);
432
432
  break;
433
433
 
434
434
  case 'remember_retract':
435
- result = await handleRetract(args as any, userId, authContext);
435
+ result = await handleRetract(args as any, userId, authContext, server);
436
436
  break;
437
437
 
438
438
  case 'remember_revise':
439
- result = await handleRevise(args as any, userId, authContext);
439
+ result = await handleRevise(args as any, userId, authContext, server);
440
440
  break;
441
441
 
442
442
  case 'remember_confirm':
@@ -464,7 +464,7 @@ function registerHandlers(
464
464
  break;
465
465
 
466
466
  case 'remember_request_set_trust_level':
467
- result = await handleRequestSetTrustLevel(args as any, userId, authContext);
467
+ result = await handleRequestSetTrustLevel(args as any, userId, authContext, server);
468
468
  break;
469
469
 
470
470
  case 'remember_search_by':
package/src/server.ts CHANGED
@@ -152,7 +152,7 @@ function registerHandlers(server: Server): void {
152
152
  break;
153
153
 
154
154
  case 'remember_delete_memory':
155
- result = await handleDeleteMemory(args as any, userId, authContext);
155
+ result = await handleDeleteMemory(args as any, userId, authContext, server);
156
156
  break;
157
157
 
158
158
  case 'remember_update_memory':
@@ -192,15 +192,15 @@ function registerHandlers(server: Server): void {
192
192
  break;
193
193
 
194
194
  case 'remember_publish':
195
- result = await handlePublish(args as any, userId, authContext);
195
+ result = await handlePublish(args as any, userId, authContext, server);
196
196
  break;
197
197
 
198
198
  case 'remember_retract':
199
- result = await handleRetract(args as any, userId, authContext);
199
+ result = await handleRetract(args as any, userId, authContext, server);
200
200
  break;
201
201
 
202
202
  case 'remember_revise':
203
- result = await handleRevise(args as any, userId, authContext);
203
+ result = await handleRevise(args as any, userId, authContext, server);
204
204
  break;
205
205
 
206
206
  case 'remember_confirm':
@@ -228,7 +228,7 @@ function registerHandlers(server: Server): void {
228
228
  break;
229
229
 
230
230
  case 'remember_request_set_trust_level':
231
- result = await handleRequestSetTrustLevel(args as any, userId, authContext);
231
+ result = await handleRequestSetTrustLevel(args as any, userId, authContext, server);
232
232
  break;
233
233
 
234
234
  default:
@@ -4,10 +4,13 @@
4
4
  */
5
5
 
6
6
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
7
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
7
8
  import { handleToolError } from '../utils/error-handler.js';
8
9
  import { createDebugLogger } from '../utils/debug.js';
9
10
  import type { AuthContext } from '../types/auth.js';
10
11
  import { createCoreServices } from '../core-services.js';
12
+ import { getWeaviateClient, getMemoryCollectionName } from '../weaviate/client.js';
13
+ import { elicitConfirmation } from '../utils/elicitation.js';
11
14
 
12
15
  /**
13
16
  * Tool definition for remember_delete_memory
@@ -57,7 +60,8 @@ export interface DeleteMemoryArgs {
57
60
  export async function handleDeleteMemory(
58
61
  args: DeleteMemoryArgs,
59
62
  userId: string,
60
- authContext?: AuthContext
63
+ authContext?: AuthContext,
64
+ server?: Server
61
65
  ): Promise<string> {
62
66
  const debug = createDebugLogger({ tool: 'remember_delete_memory', userId, operation: 'delete memory' });
63
67
  try {
@@ -76,9 +80,53 @@ export async function handleDeleteMemory(
76
80
  }
77
81
  );
78
82
 
79
- // Calculate expiry time (5 minutes from now)
80
- const expiresAt = new Date(Date.now() + 5 * 60 * 1000);
83
+ const confirmation = await elicitConfirmation({
84
+ server,
85
+ message: `Delete memory "${args.memory_id}"${args.reason ? ` (reason: ${args.reason})` : ''}?`,
86
+ });
87
+
88
+ if (confirmation.type === 'confirmed') {
89
+ // Consume the token and execute deletion
90
+ const confirmed = await tokenService.confirmRequest(userId, token);
91
+ if (!confirmed) {
92
+ return JSON.stringify(
93
+ { success: false, error: 'Token already consumed', message: 'The confirmation token has already been used.' },
94
+ null,
95
+ 2
96
+ );
97
+ }
98
+
99
+ const { memory_id, reason } = confirmed.payload;
100
+ const client = getWeaviateClient();
101
+ const collectionName = getMemoryCollectionName(userId);
102
+ const collection = client.collections.get(collectionName);
81
103
 
104
+ await collection.data.update({
105
+ id: memory_id,
106
+ properties: {
107
+ deleted_at: new Date().toISOString(),
108
+ deleted_by: userId,
109
+ deletion_reason: reason || null,
110
+ },
111
+ });
112
+
113
+ return JSON.stringify(
114
+ { success: true, memory_id, message: 'Memory deleted successfully' },
115
+ null,
116
+ 2
117
+ );
118
+ }
119
+
120
+ if (confirmation.type === 'declined') {
121
+ return JSON.stringify(
122
+ { success: false, message: 'Deletion cancelled by user.' },
123
+ null,
124
+ 2
125
+ );
126
+ }
127
+
128
+ // Fallback: return token for legacy confirm/deny flow
129
+ const expiresAt = new Date(Date.now() + 5 * 60 * 1000);
82
130
  return JSON.stringify(
83
131
  {
84
132
  success: true,
@@ -12,11 +12,13 @@
12
12
  */
13
13
 
14
14
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
15
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
15
16
  import { handleToolError } from '../utils/error-handler.js';
16
17
  import { SUPPORTED_SPACES } from '../types/space-memory.js';
17
18
  import { createDebugLogger } from '../utils/debug.js';
18
19
  import type { AuthContext } from '../types/auth.js';
19
20
  import { createCoreServices } from '../core-services.js';
21
+ import { elicitConfirmation } from '../utils/elicitation.js';
20
22
 
21
23
  /**
22
24
  * Tool definition for remember_publish
@@ -78,7 +80,8 @@ interface PublishArgs {
78
80
  export async function handlePublish(
79
81
  args: PublishArgs,
80
82
  userId: string,
81
- authContext?: AuthContext
83
+ authContext?: AuthContext,
84
+ server?: Server
82
85
  ): Promise<string> {
83
86
  const debug = createDebugLogger({
84
87
  tool: 'remember_publish',
@@ -98,6 +101,39 @@ export async function handlePublish(
98
101
  additional_tags: args.additional_tags,
99
102
  });
100
103
 
104
+ // Try elicitation for direct user confirmation
105
+ const destinations = [...(args.spaces || []), ...(args.groups || [])].join(', ');
106
+ const confirmation = await elicitConfirmation({
107
+ server,
108
+ message: `Publish memory "${args.memory_id}" to ${destinations || 'default space'}?`,
109
+ });
110
+
111
+ if (confirmation.type === 'confirmed') {
112
+ const confirmResult = await space.confirm({ token: result.token });
113
+ return JSON.stringify(
114
+ {
115
+ success: confirmResult.success,
116
+ composite_id: confirmResult.composite_id,
117
+ published_to: confirmResult.published_to,
118
+ failed: confirmResult.failed?.length ? confirmResult.failed : undefined,
119
+ space_ids: confirmResult.space_ids,
120
+ group_ids: confirmResult.group_ids,
121
+ },
122
+ null,
123
+ 2
124
+ );
125
+ }
126
+
127
+ if (confirmation.type === 'declined') {
128
+ await space.deny({ token: result.token });
129
+ return JSON.stringify(
130
+ { success: false, message: 'Publication cancelled by user.' },
131
+ null,
132
+ 2
133
+ );
134
+ }
135
+
136
+ // Fallback: return token for legacy confirm/deny flow
101
137
  return JSON.stringify(
102
138
  {
103
139
  success: true,