@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
@@ -3,10 +3,12 @@
3
3
  * Requests a trust level change for a memory via confirmation flow.
4
4
  */
5
5
 
6
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
7
  import { handleToolError } from '../utils/error-handler.js';
7
8
  import { createDebugLogger } from '../utils/debug.js';
8
9
  import type { AuthContext } from '../types/auth.js';
9
10
  import { createCoreServices } from '../core-services.js';
11
+ import { elicitConfirmation } from '../utils/elicitation.js';
10
12
 
11
13
  export const requestSetTrustLevelTool = {
12
14
  name: 'remember_request_set_trust_level',
@@ -49,7 +51,8 @@ interface RequestSetTrustLevelArgs {
49
51
  export async function handleRequestSetTrustLevel(
50
52
  args: RequestSetTrustLevelArgs,
51
53
  userId: string,
52
- authContext?: AuthContext
54
+ authContext?: AuthContext,
55
+ server?: Server
53
56
  ): Promise<string> {
54
57
  const debug = createDebugLogger({
55
58
  tool: 'remember_request_set_trust_level',
@@ -84,6 +87,34 @@ export async function handleRequestSetTrustLevel(
84
87
  5: 'SECRET',
85
88
  };
86
89
 
90
+ const currentName = TRUST_NAMES[result.current_trust_level] || 'UNKNOWN';
91
+ const requestedName = TRUST_NAMES[result.requested_trust_level] || 'UNKNOWN';
92
+
93
+ const confirmation = await elicitConfirmation({
94
+ server,
95
+ message: `Change trust level for memory "${args.memory_id}" from ${currentName} (${result.current_trust_level}) to ${requestedName} (${result.requested_trust_level})?`,
96
+ });
97
+
98
+ if (confirmation.type === 'confirmed') {
99
+ const confirmResult = await memory.confirmSetTrustLevel(result.token);
100
+ return JSON.stringify({
101
+ success: true,
102
+ memory_id: confirmResult.memory_id,
103
+ previous_trust_level: confirmResult.previous_trust_level,
104
+ new_trust_level: confirmResult.new_trust_level,
105
+ updated_at: confirmResult.updated_at,
106
+ 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}`,
107
+ }, null, 2);
108
+ }
109
+
110
+ if (confirmation.type === 'declined') {
111
+ return JSON.stringify({
112
+ success: false,
113
+ message: 'Trust level change cancelled by user.',
114
+ }, null, 2);
115
+ }
116
+
117
+ // Fallback: return token for legacy confirm/deny flow
87
118
  return JSON.stringify({
88
119
  token: result.token,
89
120
  request_id: result.request_id,
@@ -91,10 +122,10 @@ export async function handleRequestSetTrustLevel(
91
122
  memory_id: result.memory_id,
92
123
  current_trust_level: result.current_trust_level,
93
124
  requested_trust_level: result.requested_trust_level,
94
- current_trust_name: TRUST_NAMES[result.current_trust_level] || 'UNKNOWN',
95
- requested_trust_name: TRUST_NAMES[result.requested_trust_level] || 'UNKNOWN',
125
+ current_trust_name: currentName,
126
+ requested_trust_name: requestedName,
96
127
  expires_at: result.expires_at,
97
- message: `Trust level change requested: ${TRUST_NAMES[result.current_trust_level] || result.current_trust_level} (${result.current_trust_level}) → ${TRUST_NAMES[result.requested_trust_level] || result.requested_trust_level} (${result.requested_trust_level}). Confirm with token to apply.`,
128
+ message: `Trust level change requested: ${currentName} (${result.current_trust_level}) → ${requestedName} (${result.requested_trust_level}). Confirm with token to apply.`,
98
129
  }, null, 2);
99
130
  } catch (error) {
100
131
  debug.error('Tool failed', { error: error instanceof Error ? error.message : String(error) });
@@ -12,10 +12,12 @@
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 { createDebugLogger } from '../utils/debug.js';
17
18
  import type { AuthContext } from '../types/auth.js';
18
19
  import { createCoreServices } from '../core-services.js';
20
+ import { elicitConfirmation } from '../utils/elicitation.js';
19
21
 
20
22
  /**
21
23
  * Tool definition for remember_retract
@@ -69,7 +71,8 @@ interface RetractArgs {
69
71
  export async function handleRetract(
70
72
  args: RetractArgs,
71
73
  userId: string,
72
- authContext?: AuthContext
74
+ authContext?: AuthContext,
75
+ server?: Server
73
76
  ): Promise<string> {
74
77
  const debug = createDebugLogger({
75
78
  tool: 'remember_retract',
@@ -88,6 +91,39 @@ export async function handleRetract(
88
91
  groups: args.groups,
89
92
  });
90
93
 
94
+ const destinations = [...(args.spaces || []), ...(args.groups || [])].join(', ');
95
+ const confirmation = await elicitConfirmation({
96
+ server,
97
+ message: `Retract memory "${args.memory_id}" from ${destinations || 'all destinations'}?`,
98
+ });
99
+
100
+ if (confirmation.type === 'confirmed') {
101
+ const confirmResult = await space.confirm({ token: result.token });
102
+ return JSON.stringify(
103
+ {
104
+ success: confirmResult.success,
105
+ composite_id: confirmResult.composite_id,
106
+ retracted_from: confirmResult.retracted_from,
107
+ failed: confirmResult.failed?.length ? confirmResult.failed : undefined,
108
+ space_ids: confirmResult.space_ids,
109
+ group_ids: confirmResult.group_ids,
110
+ is_orphaned: (confirmResult.space_ids?.length === 0) && (confirmResult.group_ids?.length === 0),
111
+ },
112
+ null,
113
+ 2
114
+ );
115
+ }
116
+
117
+ if (confirmation.type === 'declined') {
118
+ await space.deny({ token: result.token });
119
+ return JSON.stringify(
120
+ { success: false, message: 'Retraction cancelled by user.' },
121
+ null,
122
+ 2
123
+ );
124
+ }
125
+
126
+ // Fallback: return token for legacy confirm/deny flow
91
127
  return JSON.stringify(
92
128
  {
93
129
  success: true,
@@ -9,10 +9,12 @@
9
9
  */
10
10
 
11
11
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
12
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
13
  import { handleToolError } from '../utils/error-handler.js';
13
14
  import { createDebugLogger } from '../utils/debug.js';
14
15
  import type { AuthContext } from '../types/auth.js';
15
16
  import { createCoreServices } from '../core-services.js';
17
+ import { elicitConfirmation } from '../utils/elicitation.js';
16
18
 
17
19
  /** Maximum number of revision history entries to retain */
18
20
  const MAX_REVISION_HISTORY = 10;
@@ -108,7 +110,8 @@ export function buildRevisionHistory(
108
110
  export async function handleRevise(
109
111
  args: ReviseArgs,
110
112
  userId: string,
111
- authContext?: AuthContext
113
+ authContext?: AuthContext,
114
+ server?: Server
112
115
  ): Promise<string> {
113
116
  const debug = createDebugLogger({
114
117
  tool: 'remember_revise',
@@ -125,6 +128,41 @@ export async function handleRevise(
125
128
  memory_id: args.memory_id,
126
129
  });
127
130
 
131
+ const confirmation = await elicitConfirmation({
132
+ server,
133
+ message: `Revise all published copies of memory "${args.memory_id}"?`,
134
+ });
135
+
136
+ if (confirmation.type === 'confirmed') {
137
+ const confirmResult = await space.confirm({ token: result.token });
138
+ const results = confirmResult.results || [];
139
+ const successCount = results.filter((r: any) => r.status === 'success').length;
140
+ const failedCount = results.filter((r: any) => r.status === 'failed').length;
141
+ const skippedCount = results.filter((r: any) => r.status === 'skipped').length;
142
+ return JSON.stringify(
143
+ {
144
+ success: confirmResult.success,
145
+ composite_id: confirmResult.composite_id,
146
+ revised_at: confirmResult.revised_at,
147
+ summary: { total: results.length, success: successCount, failed: failedCount, skipped: skippedCount },
148
+ results,
149
+ ...(failedCount > 0 ? { warnings: [`Failed to revise ${failedCount} of ${results.length} location(s)`] } : {}),
150
+ },
151
+ null,
152
+ 2
153
+ );
154
+ }
155
+
156
+ if (confirmation.type === 'declined') {
157
+ await space.deny({ token: result.token });
158
+ return JSON.stringify(
159
+ { success: false, message: 'Revision cancelled by user.' },
160
+ null,
161
+ 2
162
+ );
163
+ }
164
+
165
+ // Fallback: return token for legacy confirm/deny flow
128
166
  return JSON.stringify(
129
167
  {
130
168
  success: true,
@@ -0,0 +1,53 @@
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
+
10
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
+
12
+ export interface ElicitConfirmParams {
13
+ server?: Server;
14
+ message: string;
15
+ }
16
+
17
+ export type ElicitConfirmResult =
18
+ | { type: 'confirmed' }
19
+ | { type: 'declined'; reason: string }
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 async function elicitConfirmation(
31
+ params: ElicitConfirmParams
32
+ ): Promise<ElicitConfirmResult> {
33
+ const { server, message } = params;
34
+
35
+ if (!server) return { type: 'unsupported' };
36
+
37
+ const caps = server.getClientCapabilities();
38
+ if (!caps?.elicitation) return { type: 'unsupported' };
39
+
40
+ try {
41
+ const result = await server.elicitInput({
42
+ message,
43
+ requestedSchema: { type: 'object', properties: {} },
44
+ });
45
+
46
+ if (result.action === 'accept') return { type: 'confirmed' };
47
+ return { type: 'declined', reason: result.action };
48
+ } catch {
49
+ // If elicitation throws (e.g. transport doesn't support it),
50
+ // fall back to token flow rather than failing the tool call.
51
+ return { type: 'unsupported' };
52
+ }
53
+ }