@prmichaelsen/remember-mcp 2.5.2 → 2.6.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.
@@ -7,6 +7,18 @@
7
7
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
8
8
  /**
9
9
  * Tool definition for remember_confirm
10
+ *
11
+ * CRITICAL SAFETY: This tool must ONLY be called after explicit user confirmation
12
+ * in a separate message. Never chain with other tools or call immediately after
13
+ * receiving a token. The confirmation workflow requires:
14
+ *
15
+ * 1. Agent calls remember_publish (or other confirmable action)
16
+ * 2. Agent receives token in response
17
+ * 3. Agent presents details to user and asks for confirmation
18
+ * 4. User responds in SEPARATE message with explicit yes/no
19
+ * 5. Agent calls remember_confirm or remember_deny in NEW response
20
+ *
21
+ * Chaining confirmations bypasses user consent and violates security model.
10
22
  */
11
23
  export declare const confirmTool: Tool;
12
24
  interface ConfirmArgs {
@@ -6,6 +6,18 @@
6
6
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
7
7
  /**
8
8
  * Tool definition for remember_deny
9
+ *
10
+ * CRITICAL SAFETY: This tool must ONLY be called after explicit user denial
11
+ * in a separate message. Never chain with other tools or call immediately after
12
+ * receiving a token. The denial workflow requires:
13
+ *
14
+ * 1. Agent calls remember_publish (or other confirmable action)
15
+ * 2. Agent receives token in response
16
+ * 3. Agent presents details to user and asks for confirmation
17
+ * 4. User responds in SEPARATE message with explicit denial
18
+ * 5. Agent calls remember_deny in NEW response
19
+ *
20
+ * Proper user consent workflow must be followed.
9
21
  */
10
22
  export declare const denyTool: Tool;
11
23
  interface DenyArgs {
@@ -17,6 +17,7 @@ interface QuerySpaceArgs {
17
17
  min_weight?: number;
18
18
  date_from?: string;
19
19
  date_to?: string;
20
+ include_comments?: boolean;
20
21
  limit?: number;
21
22
  format?: 'detailed' | 'compact';
22
23
  }
@@ -18,6 +18,7 @@ interface SearchSpaceArgs {
18
18
  max_weight?: number;
19
19
  date_from?: string;
20
20
  date_to?: string;
21
+ include_comments?: boolean;
21
22
  limit?: number;
22
23
  offset?: number;
23
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prmichaelsen/remember-mcp",
3
- "version": "2.5.2",
3
+ "version": "2.6.2",
4
4
  "description": "Multi-tenant memory system MCP server with vector search and relationships",
5
5
  "main": "dist/server.js",
6
6
  "type": "module",
package/src/config.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import dotenv from 'dotenv';
2
+ import { logger } from './utils/logger.js';
2
3
 
3
4
  dotenv.config();
4
5
 
@@ -52,5 +53,11 @@ export function validateConfig(): void {
52
53
  );
53
54
  }
54
55
 
55
- console.log('[Config] Configuration validated');
56
+ // Import logger here to avoid circular dependency
57
+ // Use dynamic import synchronously (logger is already loaded by this point)
58
+ import('./utils/logger.js').then(({ logger }) => {
59
+ logger.info('Configuration validated', {
60
+ module: 'config',
61
+ });
62
+ });
56
63
  }
@@ -1,5 +1,6 @@
1
1
  import { initializeApp } from '@prmichaelsen/firebase-admin-sdk-v8';
2
2
  import { config } from '../config.js';
3
+ import { logger } from '../utils/logger.js';
3
4
 
4
5
  let initialized = false;
5
6
 
@@ -23,11 +24,20 @@ export function initFirestore(): void {
23
24
  });
24
25
 
25
26
  initialized = true;
26
- console.log('[Firestore] Initialized successfully');
27
+ logger.info('Firestore initialized successfully', {
28
+ module: 'firestore-init',
29
+ });
27
30
  } catch (error) {
28
- console.error('[Firestore] Initialization failed:', error);
29
- console.error('[Firestore] Make sure FIREBASE_ADMIN_SERVICE_ACCOUNT_KEY is valid JSON');
30
- console.error('[Firestore] Check for proper escaping in .env file');
31
+ logger.error('Firestore initialization failed', {
32
+ module: 'firestore-init',
33
+ error: error instanceof Error ? error.message : String(error),
34
+ });
35
+ logger.error('Make sure FIREBASE_ADMIN_SERVICE_ACCOUNT_KEY is valid JSON', {
36
+ module: 'firestore-init',
37
+ });
38
+ logger.error('Check for proper escaping in .env file', {
39
+ module: 'firestore-init',
40
+ });
31
41
  throw error;
32
42
  }
33
43
  }
@@ -52,10 +62,15 @@ export async function testFirestoreConnection(): Promise<boolean> {
52
62
  const { getDocument } = await import('@prmichaelsen/firebase-admin-sdk-v8');
53
63
  await getDocument('_health_check', 'test');
54
64
 
55
- console.log('[Firestore] Connection successful');
65
+ logger.info('Firestore connection test successful', {
66
+ module: 'firestore-init',
67
+ });
56
68
  return true;
57
69
  } catch (error) {
58
- console.error('[Firestore] Connection test failed:', error);
70
+ logger.error('Firestore connection test failed', {
71
+ module: 'firestore-init',
72
+ error: error instanceof Error ? error.message : String(error),
73
+ });
59
74
  return false;
60
75
  }
61
76
  }
@@ -1,18 +1,19 @@
1
1
  /**
2
2
  * Confirmation Token Service
3
- *
3
+ *
4
4
  * Manages confirmation tokens for sensitive operations like publishing memories.
5
5
  * Tokens are one-time use with 5-minute expiry.
6
6
  */
7
7
 
8
8
  import { randomUUID } from 'crypto';
9
- import {
10
- getDocument,
11
- addDocument,
9
+ import {
10
+ getDocument,
11
+ addDocument,
12
12
  updateDocument,
13
13
  queryDocuments,
14
- type QueryOptions
14
+ type QueryOptions
15
15
  } from '../firestore/init.js';
16
+ import { logger } from '../utils/logger.js';
16
17
 
17
18
  /**
18
19
  * Confirmation request stored in Firestore
@@ -69,21 +70,22 @@ export class ConfirmationTokenService {
69
70
 
70
71
  // Add document to Firestore (auto-generates ID)
71
72
  const collectionPath = `users/${userId}/requests`;
72
- console.log('[ConfirmationTokenService] Creating request:', {
73
+ logger.info('Creating confirmation request', {
74
+ service: 'ConfirmationTokenService',
73
75
  userId,
74
76
  action,
75
77
  targetCollection,
76
78
  collectionPath,
77
- requestData: {
78
- token,
79
- action,
80
- payloadKeys: Object.keys(payload),
81
- },
79
+ payloadKeys: Object.keys(payload),
82
80
  });
83
81
 
84
- console.log('[ConfirmationTokenService] Calling addDocument...');
82
+ logger.debug('Calling Firestore addDocument', {
83
+ service: 'ConfirmationTokenService',
84
+ collectionPath,
85
+ });
85
86
  const docRef = await addDocument(collectionPath, request);
86
- console.log('[ConfirmationTokenService] addDocument returned:', {
87
+ logger.debug('Firestore addDocument returned', {
88
+ service: 'ConfirmationTokenService',
87
89
  hasDocRef: !!docRef,
88
90
  hasId: !!docRef?.id,
89
91
  docRefId: docRef?.id,
@@ -92,7 +94,8 @@ export class ConfirmationTokenService {
92
94
  // Validate docRef
93
95
  if (!docRef) {
94
96
  const error = new Error('Firestore addDocument returned null/undefined');
95
- console.error('[ConfirmationTokenService] CRITICAL: addDocument returned null', {
97
+ logger.error('CRITICAL: addDocument returned null', {
98
+ service: 'ConfirmationTokenService',
96
99
  userId,
97
100
  collectionPath,
98
101
  });
@@ -101,7 +104,8 @@ export class ConfirmationTokenService {
101
104
 
102
105
  if (!docRef.id) {
103
106
  const error = new Error('Firestore addDocument returned docRef without ID');
104
- console.error('[ConfirmationTokenService] CRITICAL: docRef has no ID', {
107
+ logger.error('CRITICAL: docRef has no ID', {
108
+ service: 'ConfirmationTokenService',
105
109
  userId,
106
110
  collectionPath,
107
111
  docRef,
@@ -109,7 +113,8 @@ export class ConfirmationTokenService {
109
113
  throw error;
110
114
  }
111
115
 
112
- console.log('[ConfirmationTokenService] Request created successfully:', {
116
+ logger.info('Confirmation request created successfully', {
117
+ service: 'ConfirmationTokenService',
113
118
  requestId: docRef.id,
114
119
  token,
115
120
  expiresAt: request.expires_at,
@@ -117,7 +122,8 @@ export class ConfirmationTokenService {
117
122
 
118
123
  return { requestId: docRef.id, token };
119
124
  } catch (error) {
120
- console.error('[ConfirmationTokenService] FAILED to create request:', {
125
+ logger.error('Failed to create confirmation request', {
126
+ service: 'ConfirmationTokenService',
121
127
  error: error instanceof Error ? error.message : String(error),
122
128
  stack: error instanceof Error ? error.stack : undefined,
123
129
  userId,
@@ -143,7 +149,8 @@ export class ConfirmationTokenService {
143
149
  ): Promise<(ConfirmationRequest & { request_id: string }) | null> {
144
150
  const collectionPath = `users/${userId}/requests`;
145
151
 
146
- console.log('[ConfirmationTokenService] Validating token:', {
152
+ logger.debug('Validating confirmation token', {
153
+ service: 'ConfirmationTokenService',
147
154
  userId,
148
155
  token,
149
156
  collectionPath,
@@ -160,20 +167,25 @@ export class ConfirmationTokenService {
160
167
 
161
168
  const results = await queryDocuments(collectionPath, queryOptions);
162
169
 
163
- console.log('[ConfirmationTokenService] Query results:', {
170
+ logger.debug('Token query results', {
171
+ service: 'ConfirmationTokenService',
164
172
  resultsFound: results.length,
165
173
  hasResults: results.length > 0,
166
174
  });
167
175
 
168
176
  if (results.length === 0) {
169
- console.log('[ConfirmationTokenService] Token not found or not pending');
177
+ logger.info('Token not found or not pending', {
178
+ service: 'ConfirmationTokenService',
179
+ userId,
180
+ });
170
181
  return null;
171
182
  }
172
183
 
173
184
  const doc = results[0];
174
185
  const request = doc.data as ConfirmationRequest;
175
186
 
176
- console.log('[ConfirmationTokenService] Request found:', {
187
+ logger.info('Confirmation request found', {
188
+ service: 'ConfirmationTokenService',
177
189
  requestId: doc.id,
178
190
  action: request.action,
179
191
  status: request.status,
@@ -183,7 +195,11 @@ export class ConfirmationTokenService {
183
195
  // Check expiry
184
196
  const expiresAt = new Date(request.expires_at);
185
197
  if (expiresAt.getTime() < Date.now()) {
186
- console.log('[ConfirmationTokenService] Token expired');
198
+ logger.info('Token expired', {
199
+ service: 'ConfirmationTokenService',
200
+ requestId: doc.id,
201
+ expiresAt: request.expires_at,
202
+ });
187
203
  await this.updateStatus(userId, doc.id, 'expired');
188
204
  return null;
189
205
  }
@@ -298,7 +314,10 @@ export class ConfirmationTokenService {
298
314
  // Note: firebase-admin-sdk-v8 doesn't support collectionGroup queries
299
315
  // This would need to be implemented differently or rely on Firestore TTL
300
316
  // For now, return 0 and rely on Firestore TTL policy
301
- console.warn('[ConfirmationTokenService] cleanupExpired not implemented - rely on Firestore TTL');
317
+ logger.warn('cleanupExpired not implemented - relying on Firestore TTL', {
318
+ service: 'ConfirmationTokenService',
319
+ note: 'Configure Firestore TTL policy on requests collection group',
320
+ });
302
321
  return 0;
303
322
  }
304
323
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * remember_confirm tool
3
- *
3
+ *
4
4
  * Generic confirmation tool that executes any pending action.
5
5
  * This is the second phase of the confirmation workflow.
6
6
  */
@@ -10,13 +10,36 @@ import { confirmationTokenService, type ConfirmationRequest } from '../services/
10
10
  import { getWeaviateClient, getMemoryCollectionName } from '../weaviate/client.js';
11
11
  import { ensurePublicCollection } from '../weaviate/space-schema.js';
12
12
  import { handleToolError } from '../utils/error-handler.js';
13
+ import { logger } from '../utils/logger.js';
13
14
 
14
15
  /**
15
16
  * Tool definition for remember_confirm
17
+ *
18
+ * CRITICAL SAFETY: This tool must ONLY be called after explicit user confirmation
19
+ * in a separate message. Never chain with other tools or call immediately after
20
+ * receiving a token. The confirmation workflow requires:
21
+ *
22
+ * 1. Agent calls remember_publish (or other confirmable action)
23
+ * 2. Agent receives token in response
24
+ * 3. Agent presents details to user and asks for confirmation
25
+ * 4. User responds in SEPARATE message with explicit yes/no
26
+ * 5. Agent calls remember_confirm or remember_deny in NEW response
27
+ *
28
+ * Chaining confirmations bypasses user consent and violates security model.
16
29
  */
17
30
  export const confirmTool: Tool = {
18
31
  name: 'remember_confirm',
19
- description: 'Confirm and execute a pending action using the token. Works for any action that requires confirmation (publish, delete, etc.).',
32
+ description: `Confirm and execute a pending action using the token. Works for any action that requires confirmation (publish, delete, etc.).
33
+
34
+ ⚠️ CRITICAL SAFETY REQUIREMENTS:
35
+ Before executing this tool, you MUST:
36
+ 1. Have received the confirmation token in a PREVIOUS tool response
37
+ 2. Have presented the token details to the user for review
38
+ 3. Have received EXPLICIT user confirmation in a SEPARATE user message
39
+ 4. NEVER chain this tool with other tool calls in the same response
40
+ 5. ALWAYS treat confirmations as standalone, deliberate actions
41
+
42
+ Violating these requirements bypasses user consent and is a security violation.`,
20
43
  inputSchema: {
21
44
  type: 'object',
22
45
  properties: {
@@ -41,7 +64,8 @@ export async function handleConfirm(
41
64
  userId: string
42
65
  ): Promise<string> {
43
66
  try {
44
- console.log('[remember_confirm] Starting confirmation:', {
67
+ logger.info('Starting confirmation', {
68
+ tool: 'remember_confirm',
45
69
  userId,
46
70
  token: args.token,
47
71
  });
@@ -49,13 +73,17 @@ export async function handleConfirm(
49
73
  // Validate and confirm token
50
74
  const request = await confirmationTokenService.confirmRequest(userId, args.token);
51
75
 
52
- console.log('[remember_confirm] Token validation result:', {
76
+ logger.debug('Token validation result', {
77
+ tool: 'remember_confirm',
53
78
  requestFound: !!request,
54
79
  action: request?.action,
55
80
  });
56
81
 
57
82
  if (!request) {
58
- console.log('[remember_confirm] Token invalid or expired');
83
+ logger.info('Token invalid or expired', {
84
+ tool: 'remember_confirm',
85
+ userId,
86
+ });
59
87
  return JSON.stringify(
60
88
  {
61
89
  success: false,
@@ -67,7 +95,11 @@ export async function handleConfirm(
67
95
  );
68
96
  }
69
97
 
70
- console.log('[remember_confirm] Executing action:', request.action);
98
+ logger.info('Executing confirmed action', {
99
+ tool: 'remember_confirm',
100
+ action: request.action,
101
+ userId,
102
+ });
71
103
 
72
104
  // GENERIC: Execute action based on type
73
105
  // This is where the generic pattern delegates to action-specific executors
@@ -99,7 +131,8 @@ async function executePublishMemory(
99
131
  userId: string
100
132
  ): Promise<string> {
101
133
  try {
102
- console.log('[executePublishMemory] Starting execution:', {
134
+ logger.info('Executing publish memory action', {
135
+ function: 'executePublishMemory',
103
136
  userId,
104
137
  memoryId: request.payload.memory_id,
105
138
  spaces: request.payload.spaces,
@@ -112,19 +145,27 @@ async function executePublishMemory(
112
145
  getMemoryCollectionName(userId)
113
146
  );
114
147
 
115
- console.log('[executePublishMemory] Fetching original memory from:', getMemoryCollectionName(userId));
148
+ logger.debug('Fetching original memory', {
149
+ function: 'executePublishMemory',
150
+ collectionName: getMemoryCollectionName(userId),
151
+ memoryId: request.payload.memory_id,
152
+ });
116
153
 
117
154
  const originalMemory = await userCollection.query.fetchObjectById(
118
155
  request.payload.memory_id
119
156
  );
120
157
 
121
- console.log('[executePublishMemory] Original memory fetch result:', {
158
+ logger.debug('Original memory fetch result', {
159
+ function: 'executePublishMemory',
122
160
  found: !!originalMemory,
123
161
  memoryId: request.payload.memory_id,
124
162
  });
125
163
 
126
164
  if (!originalMemory) {
127
- console.log('[executePublishMemory] Memory not found');
165
+ logger.info('Original memory not found', {
166
+ function: 'executePublishMemory',
167
+ memoryId: request.payload.memory_id,
168
+ });
128
169
  return JSON.stringify(
129
170
  {
130
171
  success: false,
@@ -138,7 +179,12 @@ async function executePublishMemory(
138
179
 
139
180
  // Verify ownership again
140
181
  if (originalMemory.properties.user_id !== userId) {
141
- console.log('[executePublishMemory] Permission denied - wrong owner');
182
+ logger.warn('Permission denied - wrong owner', {
183
+ function: 'executePublishMemory',
184
+ memoryId: request.payload.memory_id,
185
+ memoryOwner: originalMemory.properties.user_id,
186
+ requestingUser: userId,
187
+ });
142
188
  return JSON.stringify(
143
189
  {
144
190
  success: false,
@@ -150,12 +196,17 @@ async function executePublishMemory(
150
196
  );
151
197
  }
152
198
 
153
- console.log('[executePublishMemory] Ensuring public collection');
199
+ logger.debug('Ensuring public collection exists', {
200
+ function: 'executePublishMemory',
201
+ });
154
202
 
155
203
  // Get unified public collection
156
204
  const publicCollection = await ensurePublicCollection(weaviateClient);
157
205
 
158
- console.log('[executePublishMemory] Public collection ready');
206
+ logger.debug('Public collection ready', {
207
+ function: 'executePublishMemory',
208
+ collectionName: 'Memory_public',
209
+ });
159
210
 
160
211
  // Create published memory (copy with modifications)
161
212
  const originalTags = Array.isArray(originalMemory.properties.tags)
@@ -183,7 +234,8 @@ async function executePublishMemory(
183
234
  version: 1,
184
235
  };
185
236
 
186
- console.log('[executePublishMemory] Inserting into Memory_public:', {
237
+ logger.info('Inserting memory into Memory_public', {
238
+ function: 'executePublishMemory',
187
239
  spaces: request.payload.spaces,
188
240
  spaceCount: request.payload.spaces?.length || 0,
189
241
  memoryId: request.payload.memory_id,
@@ -194,9 +246,10 @@ async function executePublishMemory(
194
246
  // Insert directly into unified public collection
195
247
  const result = await publicCollection.data.insert(publishedMemory as any);
196
248
 
197
- console.log('[executePublishMemory] Insert result:', {
198
- success: !!result,
249
+ logger.info('Memory published successfully', {
250
+ function: 'executePublishMemory',
199
251
  spaceMemoryId: result,
252
+ spaces: request.payload.spaces,
200
253
  });
201
254
 
202
255
  // Return minimal response with spaces array
package/src/tools/deny.ts CHANGED
@@ -10,10 +10,32 @@ import { handleToolError } from '../utils/error-handler.js';
10
10
 
11
11
  /**
12
12
  * Tool definition for remember_deny
13
+ *
14
+ * CRITICAL SAFETY: This tool must ONLY be called after explicit user denial
15
+ * in a separate message. Never chain with other tools or call immediately after
16
+ * receiving a token. The denial workflow requires:
17
+ *
18
+ * 1. Agent calls remember_publish (or other confirmable action)
19
+ * 2. Agent receives token in response
20
+ * 3. Agent presents details to user and asks for confirmation
21
+ * 4. User responds in SEPARATE message with explicit denial
22
+ * 5. Agent calls remember_deny in NEW response
23
+ *
24
+ * Proper user consent workflow must be followed.
13
25
  */
14
26
  export const denyTool: Tool = {
15
27
  name: 'remember_deny',
16
- description: 'Deny a pending action. The request will be marked as denied and the token invalidated. Works for any action that requires confirmation.',
28
+ description: `Deny a pending action. The request will be marked as denied and the token invalidated. Works for any action that requires confirmation.
29
+
30
+ ⚠️ CRITICAL SAFETY REQUIREMENTS:
31
+ Before executing this tool, you MUST:
32
+ 1. Have received the confirmation token in a PREVIOUS tool response
33
+ 2. Have presented the token details to the user for review
34
+ 3. Have received EXPLICIT user denial in a SEPARATE user message
35
+ 4. NEVER chain this tool with other tool calls in the same response
36
+ 5. ALWAYS treat denials as standalone, deliberate actions
37
+
38
+ This ensures proper user consent workflow is followed.`,
17
39
  inputSchema: {
18
40
  type: 'object',
19
41
  properties: {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * remember_publish tool
3
- *
3
+ *
4
4
  * Generates a confirmation token for publishing a memory to a shared space.
5
5
  * This is the first phase of the two-phase publish workflow.
6
6
  */
@@ -11,6 +11,7 @@ import { getWeaviateClient, getMemoryCollectionName } from '../weaviate/client.j
11
11
  import { isValidSpaceId } from '../weaviate/space-schema.js';
12
12
  import { handleToolError } from '../utils/error-handler.js';
13
13
  import { SUPPORTED_SPACES } from '../types/space-memory.js';
14
+ import { logger } from '../utils/logger.js';
14
15
 
15
16
  /**
16
17
  * Tool definition for remember_publish
@@ -60,7 +61,8 @@ export async function handlePublish(
60
61
  userId: string
61
62
  ): Promise<string> {
62
63
  try {
63
- console.log('[remember_publish] Starting publish request:', {
64
+ logger.info('Starting publish request', {
65
+ tool: 'remember_publish',
64
66
  userId,
65
67
  memoryId: args.memory_id,
66
68
  spaces: args.spaces,
@@ -71,7 +73,11 @@ export async function handlePublish(
71
73
  // Validate all space IDs
72
74
  const invalidSpaces = args.spaces.filter(s => !isValidSpaceId(s));
73
75
  if (invalidSpaces.length > 0) {
74
- console.log('[remember_publish] Invalid space IDs:', invalidSpaces);
76
+ logger.warn('Invalid space IDs provided', {
77
+ tool: 'remember_publish',
78
+ invalidSpaces,
79
+ providedSpaces: args.spaces,
80
+ });
75
81
  return JSON.stringify(
76
82
  {
77
83
  success: false,
@@ -90,7 +96,10 @@ export async function handlePublish(
90
96
 
91
97
  // Validate not empty
92
98
  if (args.spaces.length === 0) {
93
- console.log('[remember_publish] Empty spaces array');
99
+ logger.warn('Empty spaces array provided', {
100
+ tool: 'remember_publish',
101
+ userId,
102
+ });
94
103
  return JSON.stringify(
95
104
  {
96
105
  success: false,
@@ -105,19 +114,28 @@ export async function handlePublish(
105
114
  // Verify memory exists and user owns it
106
115
  const weaviateClient = getWeaviateClient();
107
116
  const collectionName = getMemoryCollectionName(userId);
108
- console.log('[remember_publish] Fetching memory from collection:', collectionName);
117
+ logger.debug('Fetching memory from collection', {
118
+ tool: 'remember_publish',
119
+ collectionName,
120
+ memoryId: args.memory_id,
121
+ });
109
122
 
110
123
  const userCollection = weaviateClient.collections.get(collectionName);
111
124
 
112
125
  const memory = await userCollection.query.fetchObjectById(args.memory_id);
113
126
 
114
- console.log('[remember_publish] Memory fetch result:', {
127
+ logger.debug('Memory fetch result', {
128
+ tool: 'remember_publish',
115
129
  found: !!memory,
116
130
  memoryId: args.memory_id,
117
131
  });
118
132
 
119
133
  if (!memory) {
120
- console.log('[remember_publish] Memory not found');
134
+ logger.info('Memory not found', {
135
+ tool: 'remember_publish',
136
+ memoryId: args.memory_id,
137
+ collectionName,
138
+ });
121
139
  return JSON.stringify(
122
140
  {
123
141
  success: false,
@@ -175,7 +193,12 @@ export async function handlePublish(
175
193
  additional_tags: args.additional_tags || [],
176
194
  };
177
195
 
178
- console.log('[remember_publish] Generating confirmation token');
196
+ logger.info('Generating confirmation token', {
197
+ tool: 'remember_publish',
198
+ userId,
199
+ memoryId: args.memory_id,
200
+ spaces: args.spaces,
201
+ });
179
202
 
180
203
  // Generate confirmation token
181
204
  const { requestId, token} = await confirmationTokenService.createRequest(
@@ -185,10 +208,12 @@ export async function handlePublish(
185
208
  undefined // No single target_collection anymore
186
209
  );
187
210
 
188
- console.log('[remember_publish] Token generated:', {
211
+ logger.info('Confirmation token generated', {
212
+ tool: 'remember_publish',
189
213
  requestId,
190
214
  token,
191
215
  action: 'publish_memory',
216
+ spaces: args.spaces,
192
217
  });
193
218
 
194
219
  // Return minimal response - agent already knows memory details