@prmichaelsen/remember-mcp 0.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.
- package/.env.example +65 -0
- package/AGENT.md +840 -0
- package/README.md +72 -0
- package/agent/design/.gitkeep +0 -0
- package/agent/design/access-control-result-pattern.md +458 -0
- package/agent/design/action-audit-memory-types.md +637 -0
- package/agent/design/common-template-fields.md +282 -0
- package/agent/design/complete-tool-set.md +407 -0
- package/agent/design/content-types-expansion.md +521 -0
- package/agent/design/cross-database-id-strategy.md +358 -0
- package/agent/design/default-template-library.md +423 -0
- package/agent/design/firestore-wrapper-analysis.md +606 -0
- package/agent/design/llm-provider-abstraction.md +691 -0
- package/agent/design/location-handling-architecture.md +523 -0
- package/agent/design/memory-templates-design.md +364 -0
- package/agent/design/permissions-storage-architecture.md +680 -0
- package/agent/design/relationship-storage-strategy.md +361 -0
- package/agent/design/remember-mcp-implementation-tasks.md +417 -0
- package/agent/design/remember-mcp-progress.yaml +141 -0
- package/agent/design/requirements-enhancements.md +468 -0
- package/agent/design/requirements.md +56 -0
- package/agent/design/template-storage-strategy.md +412 -0
- package/agent/design/template-suggestion-system.md +853 -0
- package/agent/design/trust-escalation-prevention.md +343 -0
- package/agent/design/trust-system-implementation.md +592 -0
- package/agent/design/user-preferences.md +683 -0
- package/agent/design/weaviate-collection-strategy.md +461 -0
- package/agent/milestones/.gitkeep +0 -0
- package/agent/milestones/milestone-1-project-foundation.md +121 -0
- package/agent/milestones/milestone-2-core-memory-system.md +150 -0
- package/agent/milestones/milestone-3-relationships-graph.md +116 -0
- package/agent/milestones/milestone-4-user-preferences.md +103 -0
- package/agent/milestones/milestone-5-template-system.md +126 -0
- package/agent/milestones/milestone-6-auth-multi-tenancy.md +124 -0
- package/agent/milestones/milestone-7-trust-permissions.md +133 -0
- package/agent/milestones/milestone-8-testing-quality.md +137 -0
- package/agent/milestones/milestone-9-deployment-documentation.md +147 -0
- package/agent/patterns/.gitkeep +0 -0
- package/agent/patterns/bootstrap.md +1271 -0
- package/agent/patterns/firebase-admin-sdk-v8-usage.md +950 -0
- package/agent/patterns/firestore-users-pattern-best-practices.md +347 -0
- package/agent/patterns/library-services.md +454 -0
- package/agent/patterns/testing-colocated.md +316 -0
- package/agent/progress.yaml +395 -0
- package/agent/tasks/.gitkeep +0 -0
- package/agent/tasks/task-1-initialize-project-structure.md +266 -0
- package/agent/tasks/task-2-install-dependencies.md +199 -0
- package/agent/tasks/task-3-setup-weaviate-client.md +330 -0
- package/agent/tasks/task-4-setup-firestore-client.md +362 -0
- package/agent/tasks/task-5-create-basic-mcp-server.md +114 -0
- package/agent/tasks/task-6-create-integration-tests.md +195 -0
- package/agent/tasks/task-7-finalize-milestone-1.md +363 -0
- package/agent/tasks/task-8-setup-utility-scripts.md +382 -0
- package/agent/tasks/task-9-create-server-factory.md +404 -0
- package/dist/config.d.ts +26 -0
- package/dist/constants/content-types.d.ts +60 -0
- package/dist/firestore/init.d.ts +14 -0
- package/dist/firestore/paths.d.ts +53 -0
- package/dist/firestore/paths.spec.d.ts +2 -0
- package/dist/server-factory.d.ts +40 -0
- package/dist/server-factory.js +1741 -0
- package/dist/server-factory.spec.d.ts +2 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +1690 -0
- package/dist/tools/create-memory.d.ts +94 -0
- package/dist/tools/delete-memory.d.ts +47 -0
- package/dist/tools/search-memory.d.ts +88 -0
- package/dist/types/memory.d.ts +183 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/weaviate/client.d.ts +39 -0
- package/dist/weaviate/client.spec.d.ts +2 -0
- package/dist/weaviate/schema.d.ts +29 -0
- package/esbuild.build.js +60 -0
- package/esbuild.watch.js +25 -0
- package/jest.config.js +31 -0
- package/jest.e2e.config.js +17 -0
- package/package.json +68 -0
- package/src/.gitkeep +0 -0
- package/src/config.ts +56 -0
- package/src/constants/content-types.ts +454 -0
- package/src/firestore/init.ts +68 -0
- package/src/firestore/paths.spec.ts +75 -0
- package/src/firestore/paths.ts +124 -0
- package/src/server-factory.spec.ts +60 -0
- package/src/server-factory.ts +215 -0
- package/src/server.ts +243 -0
- package/src/tools/create-memory.ts +198 -0
- package/src/tools/delete-memory.ts +126 -0
- package/src/tools/search-memory.ts +216 -0
- package/src/types/memory.ts +276 -0
- package/src/utils/logger.ts +42 -0
- package/src/weaviate/client.spec.ts +58 -0
- package/src/weaviate/client.ts +114 -0
- package/src/weaviate/schema.ts +288 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
# User Preferences for Remember-MCP
|
|
2
|
+
|
|
3
|
+
**Concept**: User-configurable preferences for system behavior with MCP tool support
|
|
4
|
+
**Created**: 2026-02-11
|
|
5
|
+
**Status**: Design Specification
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Users should be able to configure system behavior to match their preferences. These preferences are stored per-user in Firestore and can be modified through natural conversation using the `remember_update_preferences` tool.
|
|
12
|
+
|
|
13
|
+
**Key Innovation**: Agent can learn and adapt preferences through conversation without requiring UI settings changes.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Preference Schema (Firestore)
|
|
18
|
+
|
|
19
|
+
**Location**: `user_preferences/{user_id}`
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
interface UserPreferences {
|
|
23
|
+
user_id: string;
|
|
24
|
+
|
|
25
|
+
// Template Preferences
|
|
26
|
+
templates: {
|
|
27
|
+
auto_suggest: boolean; // ✅ Default: true, user can disable
|
|
28
|
+
suggestion_threshold: number; // Min confidence to show suggestion (0-1)
|
|
29
|
+
max_suggestions: number; // Max templates to suggest (1-5)
|
|
30
|
+
show_preview: boolean; // Show template preview in suggestion
|
|
31
|
+
remember_choice: boolean; // Remember "don't suggest for this type"
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Search Preferences
|
|
35
|
+
search: {
|
|
36
|
+
default_limit: number; // Default result limit (10-100)
|
|
37
|
+
include_low_trust: boolean; // Include low-trust memories in search
|
|
38
|
+
weight_by_access: boolean; // Use access count in ranking
|
|
39
|
+
weight_by_recency: boolean; // Use recency in ranking
|
|
40
|
+
default_alpha: number; // Default hybrid search alpha (0-1)
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Location Preferences
|
|
44
|
+
location: {
|
|
45
|
+
auto_capture: boolean; // Automatically capture location
|
|
46
|
+
precision: string; // "exact", "approximate", "city", "none"
|
|
47
|
+
share_with_memories: boolean; // Include location in memories
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Privacy Preferences
|
|
51
|
+
privacy: {
|
|
52
|
+
default_trust_level: number; // Default trust for new memories (0-1)
|
|
53
|
+
allow_cross_user_access: boolean; // Allow others to request access
|
|
54
|
+
auto_approve_requests: boolean; // Auto-approve access requests
|
|
55
|
+
audit_logging: boolean; // Enable audit logging
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Notification Preferences
|
|
59
|
+
notifications: {
|
|
60
|
+
trust_violations: boolean; // Notify on trust violations
|
|
61
|
+
access_requests: boolean; // Notify on access requests
|
|
62
|
+
memory_reminders: boolean; // Remind about important memories
|
|
63
|
+
relationship_suggestions: boolean; // Suggest new relationships
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Display Preferences
|
|
67
|
+
display: {
|
|
68
|
+
date_format: string; // From locale cookie
|
|
69
|
+
time_format: string; // From locale cookie
|
|
70
|
+
timezone: string; // From locale cookie
|
|
71
|
+
language: string; // From locale cookie
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Metadata
|
|
75
|
+
created_at: Timestamp;
|
|
76
|
+
updated_at: Timestamp;
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Default Preferences
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const DEFAULT_PREFERENCES: UserPreferences = {
|
|
86
|
+
templates: {
|
|
87
|
+
auto_suggest: true, // ✅ Enabled by default
|
|
88
|
+
suggestion_threshold: 0.6, // Show if >60% confident
|
|
89
|
+
max_suggestions: 3, // Show top 3
|
|
90
|
+
show_preview: true,
|
|
91
|
+
remember_choice: true
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
search: {
|
|
95
|
+
default_limit: 10,
|
|
96
|
+
include_low_trust: false, // Don't show low-trust by default
|
|
97
|
+
weight_by_access: true,
|
|
98
|
+
weight_by_recency: true,
|
|
99
|
+
default_alpha: 0.7 // Balanced hybrid search
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
location: {
|
|
103
|
+
auto_capture: true,
|
|
104
|
+
precision: "approximate", // Privacy-friendly default
|
|
105
|
+
share_with_memories: true
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
privacy: {
|
|
109
|
+
default_trust_level: 0.5, // Medium trust by default
|
|
110
|
+
allow_cross_user_access: false, // Opt-in for cross-user
|
|
111
|
+
auto_approve_requests: false,
|
|
112
|
+
audit_logging: true
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
notifications: {
|
|
116
|
+
trust_violations: true,
|
|
117
|
+
access_requests: true,
|
|
118
|
+
memory_reminders: false,
|
|
119
|
+
relationship_suggestions: true
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
display: {
|
|
123
|
+
date_format: "MM/DD/YYYY", // From locale
|
|
124
|
+
time_format: "12h", // From locale
|
|
125
|
+
timezone: "America/Los_Angeles", // From locale
|
|
126
|
+
language: "en" // From locale
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
created_at: Timestamp.now(),
|
|
130
|
+
updated_at: Timestamp.now()
|
|
131
|
+
};
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Template Auto-Suggestion Behavior
|
|
137
|
+
|
|
138
|
+
### When Enabled (Default)
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// User creates memory
|
|
142
|
+
User: "Met Sarah at the conference"
|
|
143
|
+
|
|
144
|
+
// System automatically suggests
|
|
145
|
+
System: "💡 Would you like to use the 'Person Profile' template?
|
|
146
|
+
Includes fields for: name, company, job_title, how_we_met
|
|
147
|
+
[Use Template] [Skip] [Don't suggest for contacts]"
|
|
148
|
+
|
|
149
|
+
// If user clicks "Don't suggest for contacts"
|
|
150
|
+
await updatePreference(user_id, {
|
|
151
|
+
'templates.suppressed_categories': ['contacts']
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### When Disabled
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// User has disabled auto-suggest
|
|
159
|
+
preferences.templates.auto_suggest = false;
|
|
160
|
+
|
|
161
|
+
// User creates memory
|
|
162
|
+
User: "Met Sarah at the conference"
|
|
163
|
+
|
|
164
|
+
// System creates memory without suggestion
|
|
165
|
+
System: "Memory created."
|
|
166
|
+
|
|
167
|
+
// User can still manually request template
|
|
168
|
+
User: "Use a template for this"
|
|
169
|
+
System: "Which template? [Person Profile] [Professional Contact] [Other]"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Per-Category Control
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
interface TemplateSuggestionPreferences {
|
|
176
|
+
auto_suggest: boolean; // Global toggle
|
|
177
|
+
suppressed_categories: string[]; // Don't suggest for these categories
|
|
178
|
+
suppressed_templates: string[]; // Don't suggest these specific templates
|
|
179
|
+
always_suggest: string[]; // Always suggest these templates
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Example
|
|
183
|
+
preferences.templates = {
|
|
184
|
+
auto_suggest: true,
|
|
185
|
+
suppressed_categories: ['work'], // Don't suggest work templates
|
|
186
|
+
suppressed_templates: ['recipe'], // Don't suggest recipe template
|
|
187
|
+
always_suggest: ['inventory_item'] // Always suggest inventory
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Preference Management API
|
|
194
|
+
|
|
195
|
+
### Get Preferences
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
async function getUserPreferences(user_id: string): Promise<UserPreferences> {
|
|
199
|
+
const doc = await firestore
|
|
200
|
+
.collection('user_preferences')
|
|
201
|
+
.doc(user_id)
|
|
202
|
+
.get();
|
|
203
|
+
|
|
204
|
+
if (!doc.exists) {
|
|
205
|
+
// Create with defaults
|
|
206
|
+
await firestore
|
|
207
|
+
.collection('user_preferences')
|
|
208
|
+
.doc(user_id)
|
|
209
|
+
.set(DEFAULT_PREFERENCES);
|
|
210
|
+
|
|
211
|
+
return DEFAULT_PREFERENCES;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return doc.data() as UserPreferences;
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Update Preferences
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
async function updateUserPreferences(
|
|
222
|
+
user_id: string,
|
|
223
|
+
updates: Partial<UserPreferences>
|
|
224
|
+
): Promise<void> {
|
|
225
|
+
await firestore
|
|
226
|
+
.collection('user_preferences')
|
|
227
|
+
.doc(user_id)
|
|
228
|
+
.update({
|
|
229
|
+
...updates,
|
|
230
|
+
updated_at: Timestamp.now()
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Example: Disable template auto-suggestion
|
|
235
|
+
await updateUserPreferences(user_id, {
|
|
236
|
+
'templates.auto_suggest': false
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Example: Change default trust level
|
|
240
|
+
await updateUserPreferences(user_id, {
|
|
241
|
+
'privacy.default_trust_level': 0.8
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Using Preferences in Tools
|
|
248
|
+
|
|
249
|
+
### In `remember_create_memory`
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
async function createMemory(
|
|
253
|
+
args: CreateMemoryArgs,
|
|
254
|
+
context: RequestContext
|
|
255
|
+
): Promise<CreateMemoryResult> {
|
|
256
|
+
// Get user preferences
|
|
257
|
+
const prefs = await getUserPreferences(context.user_id);
|
|
258
|
+
|
|
259
|
+
// Check if template suggestion enabled
|
|
260
|
+
if (prefs.templates.auto_suggest && !args.skip_template_suggestion) {
|
|
261
|
+
// Suggest templates
|
|
262
|
+
const suggestions = await suggestTemplates(
|
|
263
|
+
args.content,
|
|
264
|
+
context,
|
|
265
|
+
prefs.templates.suggestion_threshold
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
if (suggestions.length > 0) {
|
|
269
|
+
return {
|
|
270
|
+
status: 'template_suggested',
|
|
271
|
+
suggestions: suggestions.slice(0, prefs.templates.max_suggestions),
|
|
272
|
+
message: 'Would you like to use a template?'
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Create memory without template
|
|
278
|
+
return await createMemoryDirect(args, context, prefs);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### In `remember_search_memory`
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
async function searchMemory(
|
|
286
|
+
args: SearchMemoryArgs,
|
|
287
|
+
context: RequestContext
|
|
288
|
+
): Promise<SearchResult> {
|
|
289
|
+
// Get user preferences
|
|
290
|
+
const prefs = await getUserPreferences(context.user_id);
|
|
291
|
+
|
|
292
|
+
// Apply preference-based defaults
|
|
293
|
+
const limit = args.limit || prefs.search.default_limit;
|
|
294
|
+
const alpha = args.alpha || prefs.search.default_alpha;
|
|
295
|
+
|
|
296
|
+
// Apply weighting preferences
|
|
297
|
+
const useAccessWeighting = prefs.search.weight_by_access;
|
|
298
|
+
const useRecencyWeighting = prefs.search.weight_by_recency;
|
|
299
|
+
|
|
300
|
+
// Search with preferences
|
|
301
|
+
return await searchWithPreferences(args, prefs);
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Preference UI
|
|
308
|
+
|
|
309
|
+
### Settings Page
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// User settings interface
|
|
313
|
+
interface SettingsPage {
|
|
314
|
+
sections: [
|
|
315
|
+
{
|
|
316
|
+
title: "Templates",
|
|
317
|
+
settings: [
|
|
318
|
+
{
|
|
319
|
+
key: "auto_suggest",
|
|
320
|
+
label: "Automatically suggest templates",
|
|
321
|
+
type: "toggle",
|
|
322
|
+
default: true,
|
|
323
|
+
description: "System will suggest relevant templates when creating memories"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
key: "suggestion_threshold",
|
|
327
|
+
label: "Suggestion confidence threshold",
|
|
328
|
+
type: "slider",
|
|
329
|
+
min: 0,
|
|
330
|
+
max: 1,
|
|
331
|
+
default: 0.6,
|
|
332
|
+
description: "Only suggest templates with confidence above this level"
|
|
333
|
+
}
|
|
334
|
+
]
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
title: "Privacy",
|
|
338
|
+
settings: [
|
|
339
|
+
{
|
|
340
|
+
key: "default_trust_level",
|
|
341
|
+
label: "Default trust level for new memories",
|
|
342
|
+
type: "slider",
|
|
343
|
+
min: 0,
|
|
344
|
+
max: 1,
|
|
345
|
+
default: 0.5,
|
|
346
|
+
description: "Trust level assigned to new memories by default"
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
}
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## MCP Tool: `remember_update_preferences`
|
|
357
|
+
|
|
358
|
+
### Tool Definition
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
{
|
|
362
|
+
name: 'remember_update_preferences',
|
|
363
|
+
description: `Update user preferences for system behavior through natural conversation.
|
|
364
|
+
|
|
365
|
+
This tool allows the agent to learn and adapt to user preferences without requiring
|
|
366
|
+
the user to navigate settings UI. Preferences are stored in Firestore and affect
|
|
367
|
+
how the system operates.
|
|
368
|
+
|
|
369
|
+
Common use cases:
|
|
370
|
+
- User: "Stop suggesting templates" → disable auto_suggest
|
|
371
|
+
- User: "Don't suggest work templates" → suppress work category
|
|
372
|
+
- User: "Always use high trust for new memories" → set default_trust_level
|
|
373
|
+
- User: "Show me 20 results by default" → set default_limit
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
preference_path: Dot-notation path to preference (e.g., "templates.auto_suggest")
|
|
377
|
+
value: New value for the preference (boolean, number, string, or array)
|
|
378
|
+
reason: Optional reason for the change (for audit trail)
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
UpdatePreferencesResult with:
|
|
382
|
+
- success: boolean
|
|
383
|
+
- preference_path: string
|
|
384
|
+
- old_value: any
|
|
385
|
+
- new_value: any
|
|
386
|
+
- message: string
|
|
387
|
+
`,
|
|
388
|
+
inputSchema: {
|
|
389
|
+
type: 'object',
|
|
390
|
+
properties: {
|
|
391
|
+
preference_path: {
|
|
392
|
+
type: 'string',
|
|
393
|
+
description: 'Dot-notation path (e.g., "templates.auto_suggest")',
|
|
394
|
+
examples: [
|
|
395
|
+
'templates.auto_suggest',
|
|
396
|
+
'templates.suppressed_categories',
|
|
397
|
+
'search.default_limit',
|
|
398
|
+
'privacy.default_trust_level'
|
|
399
|
+
]
|
|
400
|
+
},
|
|
401
|
+
value: {
|
|
402
|
+
description: 'New value (type depends on preference)',
|
|
403
|
+
oneOf: [
|
|
404
|
+
{ type: 'boolean' },
|
|
405
|
+
{ type: 'number' },
|
|
406
|
+
{ type: 'string' },
|
|
407
|
+
{ type: 'array' }
|
|
408
|
+
]
|
|
409
|
+
},
|
|
410
|
+
reason: {
|
|
411
|
+
type: 'string',
|
|
412
|
+
description: 'Optional reason for the change'
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
required: ['preference_path', 'value']
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Implementation
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
async function updatePreferences(
|
|
424
|
+
args: UpdatePreferencesArgs,
|
|
425
|
+
context: RequestContext
|
|
426
|
+
): Promise<UpdatePreferencesResult> {
|
|
427
|
+
const { preference_path, value, reason } = args;
|
|
428
|
+
const user_id = context.user_id;
|
|
429
|
+
|
|
430
|
+
// Get current preferences
|
|
431
|
+
const currentPrefs = await getUserPreferences(user_id);
|
|
432
|
+
|
|
433
|
+
// Get old value
|
|
434
|
+
const oldValue = getNestedValue(currentPrefs, preference_path);
|
|
435
|
+
|
|
436
|
+
// Validate preference path
|
|
437
|
+
if (!isValidPreferencePath(preference_path)) {
|
|
438
|
+
return {
|
|
439
|
+
success: false,
|
|
440
|
+
preference_path,
|
|
441
|
+
old_value: oldValue,
|
|
442
|
+
new_value: value,
|
|
443
|
+
error: `Invalid preference path: ${preference_path}`
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Validate value type
|
|
448
|
+
if (!isValidValueType(preference_path, value)) {
|
|
449
|
+
return {
|
|
450
|
+
success: false,
|
|
451
|
+
preference_path,
|
|
452
|
+
old_value: oldValue,
|
|
453
|
+
new_value: value,
|
|
454
|
+
error: `Invalid value type for ${preference_path}`
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Update in Firestore
|
|
459
|
+
await firestore
|
|
460
|
+
.collection('user_preferences')
|
|
461
|
+
.doc(user_id)
|
|
462
|
+
.update({
|
|
463
|
+
[preference_path]: value,
|
|
464
|
+
updated_at: Timestamp.now()
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
// Log change
|
|
468
|
+
await logPreferenceChange({
|
|
469
|
+
user_id,
|
|
470
|
+
preference_path,
|
|
471
|
+
old_value: oldValue,
|
|
472
|
+
new_value: value,
|
|
473
|
+
reason,
|
|
474
|
+
timestamp: new Date(),
|
|
475
|
+
conversation_id: context.conversation_id
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
return {
|
|
479
|
+
success: true,
|
|
480
|
+
preference_path,
|
|
481
|
+
old_value: oldValue,
|
|
482
|
+
new_value: value,
|
|
483
|
+
message: formatPreferenceChangeMessage(preference_path, oldValue, value)
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### Natural Language Examples
|
|
489
|
+
|
|
490
|
+
#### Example 1: Disable Template Suggestions
|
|
491
|
+
```
|
|
492
|
+
User: "Stop suggesting templates, they're annoying"
|
|
493
|
+
|
|
494
|
+
Agent: remember_update_preferences({
|
|
495
|
+
preference_path: "templates.auto_suggest",
|
|
496
|
+
value: false,
|
|
497
|
+
reason: "User finds template suggestions annoying"
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
Result: {
|
|
501
|
+
success: true,
|
|
502
|
+
message: "Template suggestions disabled. You can re-enable them anytime by saying 'suggest templates again'."
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
#### Example 2: Suppress Category
|
|
507
|
+
```
|
|
508
|
+
User: "Don't suggest work templates anymore"
|
|
509
|
+
|
|
510
|
+
Agent: remember_update_preferences({
|
|
511
|
+
preference_path: "templates.suppressed_categories",
|
|
512
|
+
value: ["work"],
|
|
513
|
+
reason: "User doesn't want work template suggestions"
|
|
514
|
+
})
|
|
515
|
+
|
|
516
|
+
Result: {
|
|
517
|
+
success: true,
|
|
518
|
+
message: "Work templates will no longer be suggested. Other templates will still be suggested."
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
#### Example 3: Change Default Trust
|
|
523
|
+
```
|
|
524
|
+
User: "Make my new memories more private by default"
|
|
525
|
+
|
|
526
|
+
Agent: remember_update_preferences({
|
|
527
|
+
preference_path: "privacy.default_trust_level",
|
|
528
|
+
value: 0.2,
|
|
529
|
+
reason: "User wants more privacy for new memories"
|
|
530
|
+
})
|
|
531
|
+
|
|
532
|
+
Result: {
|
|
533
|
+
success: true,
|
|
534
|
+
old_value: 0.5,
|
|
535
|
+
new_value: 0.2,
|
|
536
|
+
message: "Default trust level changed from 0.5 to 0.2. New memories will be more private."
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
#### Example 4: Change Search Limit
|
|
541
|
+
```
|
|
542
|
+
User: "Show me 20 results when I search"
|
|
543
|
+
|
|
544
|
+
Agent: remember_update_preferences({
|
|
545
|
+
preference_path: "search.default_limit",
|
|
546
|
+
value: 20,
|
|
547
|
+
reason: "User wants more search results"
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
Result: {
|
|
551
|
+
success: true,
|
|
552
|
+
old_value: 10,
|
|
553
|
+
new_value: 20,
|
|
554
|
+
message: "Search results limit changed to 20."
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## Preference Change Logging
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
interface PreferenceChangeLog {
|
|
564
|
+
user_id: string;
|
|
565
|
+
preference_path: string;
|
|
566
|
+
old_value: any;
|
|
567
|
+
new_value: any;
|
|
568
|
+
reason: string | null;
|
|
569
|
+
timestamp: datetime;
|
|
570
|
+
conversation_id: string | null;
|
|
571
|
+
changed_via: 'mcp_tool' | 'ui' | 'api';
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Store in Firestore
|
|
575
|
+
// user_preferences/{user_id}/change_history/{change_id}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## Tool: `remember_get_preferences`
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
{
|
|
584
|
+
name: 'remember_get_preferences',
|
|
585
|
+
description: `Get current user preferences.
|
|
586
|
+
|
|
587
|
+
Use this to understand user's current settings before suggesting changes
|
|
588
|
+
or to explain why system is behaving a certain way.
|
|
589
|
+
|
|
590
|
+
Args:
|
|
591
|
+
category: Optional category to filter (templates, search, privacy, etc.)
|
|
592
|
+
|
|
593
|
+
Returns:
|
|
594
|
+
Current preferences object or filtered by category
|
|
595
|
+
`,
|
|
596
|
+
inputSchema: {
|
|
597
|
+
type: 'object',
|
|
598
|
+
properties: {
|
|
599
|
+
category: {
|
|
600
|
+
type: 'string',
|
|
601
|
+
enum: ['templates', 'search', 'location', 'privacy', 'notifications', 'display'],
|
|
602
|
+
description: 'Optional category to filter preferences'
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// Example
|
|
609
|
+
User: "What are my template settings?"
|
|
610
|
+
|
|
611
|
+
Agent: remember_get_preferences({
|
|
612
|
+
category: "templates"
|
|
613
|
+
})
|
|
614
|
+
|
|
615
|
+
Result: {
|
|
616
|
+
auto_suggest: true,
|
|
617
|
+
suggestion_threshold: 0.6,
|
|
618
|
+
max_suggestions: 3,
|
|
619
|
+
suppressed_categories: [],
|
|
620
|
+
suppressed_templates: []
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
## Benefits
|
|
627
|
+
|
|
628
|
+
### For Users
|
|
629
|
+
- **Control**: Customize system behavior
|
|
630
|
+
- **Privacy**: Control default trust and sharing
|
|
631
|
+
- **Efficiency**: Disable features they don't use
|
|
632
|
+
- **Personalization**: System adapts to preferences
|
|
633
|
+
- **Natural Interface**: Change settings through conversation
|
|
634
|
+
|
|
635
|
+
### For System
|
|
636
|
+
- **Flexibility**: Support different user workflows
|
|
637
|
+
- **Adoption**: Users can ease into features
|
|
638
|
+
- **Feedback**: Learn what features users value
|
|
639
|
+
- **Optimization**: Reduce unnecessary processing
|
|
640
|
+
- **Learning**: Agent learns user preferences over time
|
|
641
|
+
|
|
642
|
+
### For Agent
|
|
643
|
+
- **Adaptive**: Can adjust behavior based on user feedback
|
|
644
|
+
- **Conversational**: No need to direct users to settings UI
|
|
645
|
+
- **Context-Aware**: Can suggest preference changes at appropriate times
|
|
646
|
+
- **Transparent**: Can explain why system behaves certain way
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
## Updated Tool Count
|
|
651
|
+
|
|
652
|
+
**Remember-MCP Tools** (now 13 total):
|
|
653
|
+
|
|
654
|
+
**Memory Operations** (6):
|
|
655
|
+
1. remember_create_memory
|
|
656
|
+
2. remember_update_memory
|
|
657
|
+
3. remember_delete_memory
|
|
658
|
+
4. remember_search_memory
|
|
659
|
+
5. remember_find_similar
|
|
660
|
+
6. remember_query_memory
|
|
661
|
+
|
|
662
|
+
**Relationship Operations** (4):
|
|
663
|
+
7. remember_create_relationship
|
|
664
|
+
8. remember_update_relationship
|
|
665
|
+
9. remember_search_relationship
|
|
666
|
+
10. remember_delete_relationship
|
|
667
|
+
|
|
668
|
+
**Preferences** (2 NEW):
|
|
669
|
+
11. **remember_update_preferences** ← NEW
|
|
670
|
+
12. **remember_get_preferences** ← NEW
|
|
671
|
+
|
|
672
|
+
**Templates** (optional, Phase 3):
|
|
673
|
+
13. remember_create_template
|
|
674
|
+
14. remember_list_templates
|
|
675
|
+
15. remember_update_template
|
|
676
|
+
16. remember_delete_template
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
**Status**: Design Specification
|
|
681
|
+
**Storage**: Firestore (`user_preferences/{user_id}`)
|
|
682
|
+
**Default**: Template auto-suggest enabled, user can disable via tool
|
|
683
|
+
**Key Innovation**: Preferences manageable through natural conversation
|