@prmichaelsen/remember-mcp 2.5.2 → 2.6.1

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.
@@ -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.1",
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,6 +10,7 @@ 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
@@ -41,7 +42,8 @@ export async function handleConfirm(
41
42
  userId: string
42
43
  ): Promise<string> {
43
44
  try {
44
- console.log('[remember_confirm] Starting confirmation:', {
45
+ logger.info('Starting confirmation', {
46
+ tool: 'remember_confirm',
45
47
  userId,
46
48
  token: args.token,
47
49
  });
@@ -49,13 +51,17 @@ export async function handleConfirm(
49
51
  // Validate and confirm token
50
52
  const request = await confirmationTokenService.confirmRequest(userId, args.token);
51
53
 
52
- console.log('[remember_confirm] Token validation result:', {
54
+ logger.debug('Token validation result', {
55
+ tool: 'remember_confirm',
53
56
  requestFound: !!request,
54
57
  action: request?.action,
55
58
  });
56
59
 
57
60
  if (!request) {
58
- console.log('[remember_confirm] Token invalid or expired');
61
+ logger.info('Token invalid or expired', {
62
+ tool: 'remember_confirm',
63
+ userId,
64
+ });
59
65
  return JSON.stringify(
60
66
  {
61
67
  success: false,
@@ -67,7 +73,11 @@ export async function handleConfirm(
67
73
  );
68
74
  }
69
75
 
70
- console.log('[remember_confirm] Executing action:', request.action);
76
+ logger.info('Executing confirmed action', {
77
+ tool: 'remember_confirm',
78
+ action: request.action,
79
+ userId,
80
+ });
71
81
 
72
82
  // GENERIC: Execute action based on type
73
83
  // This is where the generic pattern delegates to action-specific executors
@@ -99,7 +109,8 @@ async function executePublishMemory(
99
109
  userId: string
100
110
  ): Promise<string> {
101
111
  try {
102
- console.log('[executePublishMemory] Starting execution:', {
112
+ logger.info('Executing publish memory action', {
113
+ function: 'executePublishMemory',
103
114
  userId,
104
115
  memoryId: request.payload.memory_id,
105
116
  spaces: request.payload.spaces,
@@ -112,19 +123,27 @@ async function executePublishMemory(
112
123
  getMemoryCollectionName(userId)
113
124
  );
114
125
 
115
- console.log('[executePublishMemory] Fetching original memory from:', getMemoryCollectionName(userId));
126
+ logger.debug('Fetching original memory', {
127
+ function: 'executePublishMemory',
128
+ collectionName: getMemoryCollectionName(userId),
129
+ memoryId: request.payload.memory_id,
130
+ });
116
131
 
117
132
  const originalMemory = await userCollection.query.fetchObjectById(
118
133
  request.payload.memory_id
119
134
  );
120
135
 
121
- console.log('[executePublishMemory] Original memory fetch result:', {
136
+ logger.debug('Original memory fetch result', {
137
+ function: 'executePublishMemory',
122
138
  found: !!originalMemory,
123
139
  memoryId: request.payload.memory_id,
124
140
  });
125
141
 
126
142
  if (!originalMemory) {
127
- console.log('[executePublishMemory] Memory not found');
143
+ logger.info('Original memory not found', {
144
+ function: 'executePublishMemory',
145
+ memoryId: request.payload.memory_id,
146
+ });
128
147
  return JSON.stringify(
129
148
  {
130
149
  success: false,
@@ -138,7 +157,12 @@ async function executePublishMemory(
138
157
 
139
158
  // Verify ownership again
140
159
  if (originalMemory.properties.user_id !== userId) {
141
- console.log('[executePublishMemory] Permission denied - wrong owner');
160
+ logger.warn('Permission denied - wrong owner', {
161
+ function: 'executePublishMemory',
162
+ memoryId: request.payload.memory_id,
163
+ memoryOwner: originalMemory.properties.user_id,
164
+ requestingUser: userId,
165
+ });
142
166
  return JSON.stringify(
143
167
  {
144
168
  success: false,
@@ -150,12 +174,17 @@ async function executePublishMemory(
150
174
  );
151
175
  }
152
176
 
153
- console.log('[executePublishMemory] Ensuring public collection');
177
+ logger.debug('Ensuring public collection exists', {
178
+ function: 'executePublishMemory',
179
+ });
154
180
 
155
181
  // Get unified public collection
156
182
  const publicCollection = await ensurePublicCollection(weaviateClient);
157
183
 
158
- console.log('[executePublishMemory] Public collection ready');
184
+ logger.debug('Public collection ready', {
185
+ function: 'executePublishMemory',
186
+ collectionName: 'Memory_public',
187
+ });
159
188
 
160
189
  // Create published memory (copy with modifications)
161
190
  const originalTags = Array.isArray(originalMemory.properties.tags)
@@ -183,7 +212,8 @@ async function executePublishMemory(
183
212
  version: 1,
184
213
  };
185
214
 
186
- console.log('[executePublishMemory] Inserting into Memory_public:', {
215
+ logger.info('Inserting memory into Memory_public', {
216
+ function: 'executePublishMemory',
187
217
  spaces: request.payload.spaces,
188
218
  spaceCount: request.payload.spaces?.length || 0,
189
219
  memoryId: request.payload.memory_id,
@@ -194,9 +224,10 @@ async function executePublishMemory(
194
224
  // Insert directly into unified public collection
195
225
  const result = await publicCollection.data.insert(publishedMemory as any);
196
226
 
197
- console.log('[executePublishMemory] Insert result:', {
198
- success: !!result,
227
+ logger.info('Memory published successfully', {
228
+ function: 'executePublishMemory',
199
229
  spaceMemoryId: result,
230
+ spaces: request.payload.spaces,
200
231
  });
201
232
 
202
233
  // Return minimal response with spaces array
@@ -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
@@ -17,7 +17,7 @@ import { handleToolError } from '../utils/error-handler.js';
17
17
  */
18
18
  export const querySpaceTool: Tool = {
19
19
  name: 'remember_query_space',
20
- description: 'Ask natural language questions about memories in shared spaces. Works like remember_query_memory but queries shared spaces.',
20
+ description: 'Ask natural language questions about memories in shared spaces. By default, excludes comments to focus on original content. Set include_comments: true to include discussions in answers.',
21
21
  inputSchema: {
22
22
  type: 'object',
23
23
  properties: {
@@ -25,11 +25,15 @@ export const querySpaceTool: Tool = {
25
25
  type: 'string',
26
26
  description: 'Natural language question',
27
27
  },
28
- space: {
29
- type: 'string',
30
- description: 'Which space to query',
31
- enum: SUPPORTED_SPACES,
32
- default: 'the_void',
28
+ spaces: {
29
+ type: 'array',
30
+ items: {
31
+ type: 'string',
32
+ enum: SUPPORTED_SPACES,
33
+ },
34
+ description: 'Spaces to query (e.g., ["the_void", "dogs"])',
35
+ minItems: 1,
36
+ default: ['the_void'],
33
37
  },
34
38
  content_type: {
35
39
  type: 'string',
@@ -54,6 +58,11 @@ export const querySpaceTool: Tool = {
54
58
  type: 'string',
55
59
  description: 'Filter memories created before this date (ISO 8601)',
56
60
  },
61
+ include_comments: {
62
+ type: 'boolean',
63
+ description: 'Include comments in query results (default: false)',
64
+ default: false,
65
+ },
57
66
  limit: {
58
67
  type: 'number',
59
68
  default: 10,
@@ -78,6 +87,7 @@ interface QuerySpaceArgs {
78
87
  min_weight?: number;
79
88
  date_from?: string;
80
89
  date_to?: string;
90
+ include_comments?: boolean;
81
91
  limit?: number;
82
92
  format?: 'detailed' | 'compact';
83
93
  }
@@ -134,6 +144,13 @@ export async function handleQuerySpace(
134
144
  filterList.push(publicCollection.filter.byProperty('type').equal(args.content_type));
135
145
  }
136
146
 
147
+ // Exclude comments by default (unless explicitly included)
148
+ if (!args.include_comments && !args.content_type) {
149
+ // Only exclude comments if not filtering by content_type
150
+ // (if content_type is set, user has explicit control)
151
+ filterList.push(publicCollection.filter.byProperty('type').notEqual('comment'));
152
+ }
153
+
137
154
  // Apply tags filter
138
155
  if (args.tags && args.tags.length > 0) {
139
156
  args.tags.forEach(tag => {
@@ -18,7 +18,7 @@ import type { SearchFilters } from '../types/memory.js';
18
18
  */
19
19
  export const searchSpaceTool: Tool = {
20
20
  name: 'remember_search_space',
21
- description: 'Search one or more shared spaces to discover thoughts, ideas, and memories. Works like remember_search_memory but searches shared spaces instead of personal memories. Can search multiple spaces in a single query.',
21
+ description: 'Search one or more shared spaces to discover thoughts, ideas, and memories. By default, excludes comments to keep discovery clean. Set include_comments: true to include threaded discussions. Can search multiple spaces in a single query.',
22
22
  inputSchema: {
23
23
  type: 'object',
24
24
  properties: {
@@ -65,6 +65,11 @@ export const searchSpaceTool: Tool = {
65
65
  type: 'string',
66
66
  description: 'Filter memories created before this date (ISO 8601)',
67
67
  },
68
+ include_comments: {
69
+ type: 'boolean',
70
+ description: 'Include comments in search results (default: false)',
71
+ default: false,
72
+ },
68
73
  limit: {
69
74
  type: 'number',
70
75
  default: 10,
@@ -89,6 +94,7 @@ interface SearchSpaceArgs {
89
94
  max_weight?: number;
90
95
  date_from?: string;
91
96
  date_to?: string;
97
+ include_comments?: boolean;
92
98
  limit?: number;
93
99
  offset?: number;
94
100
  }
@@ -150,6 +156,13 @@ export async function handleSearchSpace(
150
156
  filterList.push(publicCollection.filter.byProperty('type').equal(args.content_type));
151
157
  }
152
158
 
159
+ // Exclude comments by default (unless explicitly included)
160
+ if (!args.include_comments && !args.content_type) {
161
+ // Only exclude comments if not filtering by content_type
162
+ // (if content_type is set, user has explicit control)
163
+ filterList.push(publicCollection.filter.byProperty('type').notEqual('comment'));
164
+ }
165
+
153
166
  // Apply tags filter
154
167
  if (args.tags && args.tags.length > 0) {
155
168
  args.tags.forEach(tag => {