@prmichaelsen/remember-mcp 2.6.12 → 2.7.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/CHANGELOG.md CHANGED
@@ -5,6 +5,45 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.7.0] - 2026-02-17
9
+
10
+ ### Fixed
11
+
12
+ - **CRITICAL: `remember_update_memory` Now Uses `replace()` Instead of `update()`**
13
+ - Switched from `collection.data.update()` to `collection.data.replace()`
14
+ - Fixes Weaviate bug where `update()` only persists if vectorized fields change
15
+ - Now fetches full object and merges updates before replacing
16
+ - Updates to non-vectorized fields (title, type, weight, tags, etc.) now persist correctly
17
+ - Resolves issue where updates returned success but changes weren't saved
18
+ - **Breaking Change**: This is a minor version bump due to behavior change (more reliable updates)
19
+
20
+ ### Changed
21
+
22
+ - Fetch strategy: Now fetches all properties (not just 3) since we need full object for replace
23
+ - Update strategy: Merge updates with existing properties, then replace entire object
24
+ - Logging: Changed "Calling Weaviate update" to "Calling Weaviate replace"
25
+
26
+ ### Root Cause
27
+
28
+ - Weaviate has a known bug where `update()` only persists changes if at least one vectorized field is modified
29
+ - Our schema only vectorizes `content` and `observation`
30
+ - Updates to `title`, `type`, `weight`, `tags`, etc. were silently ignored
31
+ - `replace()` doesn't have this limitation and always persists changes
32
+
33
+ ---
34
+
35
+ ## [2.6.13] - 2026-02-17
36
+
37
+ ### Changed
38
+
39
+ - **Enhanced Logging for `remember_update_memory`**: Added detailed Weaviate update logging
40
+ - Logs update fields and values before calling Weaviate
41
+ - Logs confirmation after Weaviate update completes
42
+ - Helps diagnose if updates are being called but not persisting
43
+ - Shows exact values being sent to Weaviate
44
+
45
+ ---
46
+
8
47
  ## [2.6.12] - 2026-02-17
9
48
 
10
49
  ### Fixed
@@ -1948,9 +1948,7 @@ async function handleUpdateMemory(args, userId) {
1948
1948
  const collection = getMemoryCollection(userId);
1949
1949
  let existingMemory;
1950
1950
  try {
1951
- existingMemory = await collection.query.fetchObjectById(args.memory_id, {
1952
- returnProperties: ["user_id", "doc_type", "version"]
1953
- });
1951
+ existingMemory = await collection.query.fetchObjectById(args.memory_id);
1954
1952
  } catch (fetchError) {
1955
1953
  const fetchErrorMsg = fetchError instanceof Error ? fetchError.message : String(fetchError);
1956
1954
  logger.error("Failed to fetch memory for update:", {
@@ -1961,7 +1959,7 @@ async function handleUpdateMemory(args, userId) {
1961
1959
  });
1962
1960
  throw new Error(`Failed to fetch memory ${args.memory_id}: ${fetchErrorMsg}`);
1963
1961
  }
1964
- if (!existingMemory) {
1962
+ if (!existingMemory || !existingMemory.properties) {
1965
1963
  throw new Error(`Memory not found: ${args.memory_id}. It may have been deleted or never existed.`);
1966
1964
  }
1967
1965
  if (existingMemory.properties.user_id !== userId) {
@@ -2034,14 +2032,31 @@ async function handleUpdateMemory(args, userId) {
2034
2032
  const now = (/* @__PURE__ */ new Date()).toISOString();
2035
2033
  updates.updated_at = now;
2036
2034
  updates.version = existingMemory.properties.version + 1;
2035
+ const mergedProperties = {
2036
+ ...existingMemory.properties,
2037
+ ...updates
2038
+ };
2039
+ logger.info("Calling Weaviate replace", {
2040
+ userId,
2041
+ memoryId: args.memory_id,
2042
+ updateFields: Object.keys(updates),
2043
+ updateValues: updates,
2044
+ collectionName: `Memory_${userId}`,
2045
+ totalProperties: Object.keys(mergedProperties).length
2046
+ });
2037
2047
  try {
2038
- await collection.data.update({
2048
+ await collection.data.replace({
2039
2049
  id: args.memory_id,
2040
- properties: updates
2050
+ properties: mergedProperties
2051
+ });
2052
+ logger.info("Weaviate replace completed (no error thrown)", {
2053
+ userId,
2054
+ memoryId: args.memory_id,
2055
+ updatedFields: Object.keys(updates)
2041
2056
  });
2042
2057
  } catch (updateError) {
2043
2058
  const updateErrorMsg = updateError instanceof Error ? updateError.message : String(updateError);
2044
- logger.error("Failed to perform Weaviate update:", {
2059
+ logger.error("Failed to perform Weaviate replace:", {
2045
2060
  error: updateErrorMsg,
2046
2061
  userId,
2047
2062
  memoryId: args.memory_id,
package/dist/server.js CHANGED
@@ -2016,9 +2016,7 @@ async function handleUpdateMemory(args, userId) {
2016
2016
  const collection = getMemoryCollection(userId);
2017
2017
  let existingMemory;
2018
2018
  try {
2019
- existingMemory = await collection.query.fetchObjectById(args.memory_id, {
2020
- returnProperties: ["user_id", "doc_type", "version"]
2021
- });
2019
+ existingMemory = await collection.query.fetchObjectById(args.memory_id);
2022
2020
  } catch (fetchError) {
2023
2021
  const fetchErrorMsg = fetchError instanceof Error ? fetchError.message : String(fetchError);
2024
2022
  logger.error("Failed to fetch memory for update:", {
@@ -2029,7 +2027,7 @@ async function handleUpdateMemory(args, userId) {
2029
2027
  });
2030
2028
  throw new Error(`Failed to fetch memory ${args.memory_id}: ${fetchErrorMsg}`);
2031
2029
  }
2032
- if (!existingMemory) {
2030
+ if (!existingMemory || !existingMemory.properties) {
2033
2031
  throw new Error(`Memory not found: ${args.memory_id}. It may have been deleted or never existed.`);
2034
2032
  }
2035
2033
  if (existingMemory.properties.user_id !== userId) {
@@ -2102,14 +2100,31 @@ async function handleUpdateMemory(args, userId) {
2102
2100
  const now = (/* @__PURE__ */ new Date()).toISOString();
2103
2101
  updates.updated_at = now;
2104
2102
  updates.version = existingMemory.properties.version + 1;
2103
+ const mergedProperties = {
2104
+ ...existingMemory.properties,
2105
+ ...updates
2106
+ };
2107
+ logger.info("Calling Weaviate replace", {
2108
+ userId,
2109
+ memoryId: args.memory_id,
2110
+ updateFields: Object.keys(updates),
2111
+ updateValues: updates,
2112
+ collectionName: `Memory_${userId}`,
2113
+ totalProperties: Object.keys(mergedProperties).length
2114
+ });
2105
2115
  try {
2106
- await collection.data.update({
2116
+ await collection.data.replace({
2107
2117
  id: args.memory_id,
2108
- properties: updates
2118
+ properties: mergedProperties
2119
+ });
2120
+ logger.info("Weaviate replace completed (no error thrown)", {
2121
+ userId,
2122
+ memoryId: args.memory_id,
2123
+ updatedFields: Object.keys(updates)
2109
2124
  });
2110
2125
  } catch (updateError) {
2111
2126
  const updateErrorMsg = updateError instanceof Error ? updateError.message : String(updateError);
2112
- logger.error("Failed to perform Weaviate update:", {
2127
+ logger.error("Failed to perform Weaviate replace:", {
2113
2128
  error: updateErrorMsg,
2114
2129
  userId,
2115
2130
  memoryId: args.memory_id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prmichaelsen/remember-mcp",
3
- "version": "2.6.12",
3
+ "version": "2.7.0",
4
4
  "description": "Multi-tenant memory system MCP server with vector search and relationships",
5
5
  "main": "dist/server.js",
6
6
  "type": "module",
@@ -130,14 +130,12 @@ export async function handleUpdateMemory(
130
130
 
131
131
  const collection = getMemoryCollection(userId);
132
132
 
133
- // Get existing memory to verify ownership and get current version
134
- // Only fetch minimal properties needed for validation - don't query optional properties
135
- // that may not exist on all records (causes Weaviate gRPC errors)
133
+ // Get existing memory - fetch ALL properties for replace operation
134
+ // We need the full object to use replace() instead of update()
135
+ // (Weaviate bug: update() only persists if vectorized fields change)
136
136
  let existingMemory;
137
137
  try {
138
- existingMemory = await collection.query.fetchObjectById(args.memory_id, {
139
- returnProperties: ['user_id', 'doc_type', 'version'],
140
- });
138
+ existingMemory = await collection.query.fetchObjectById(args.memory_id);
141
139
  } catch (fetchError) {
142
140
  const fetchErrorMsg = fetchError instanceof Error ? fetchError.message : String(fetchError);
143
141
  logger.error('Failed to fetch memory for update:', {
@@ -149,7 +147,7 @@ export async function handleUpdateMemory(
149
147
  throw new Error(`Failed to fetch memory ${args.memory_id}: ${fetchErrorMsg}`);
150
148
  }
151
149
 
152
- if (!existingMemory) {
150
+ if (!existingMemory || !existingMemory.properties) {
153
151
  throw new Error(`Memory not found: ${args.memory_id}. It may have been deleted or never existed.`);
154
152
  }
155
153
 
@@ -249,15 +247,37 @@ export async function handleUpdateMemory(
249
247
  updates.updated_at = now;
250
248
  updates.version = (existingMemory.properties.version as number) + 1;
251
249
 
252
- // Perform update in Weaviate
250
+ // Merge updates with existing properties
251
+ // Use replace() instead of update() due to Weaviate bug where update() only
252
+ // persists if vectorized fields (content/observation) are changed
253
+ const mergedProperties = {
254
+ ...existingMemory.properties,
255
+ ...updates,
256
+ };
257
+
258
+ logger.info('Calling Weaviate replace', {
259
+ userId,
260
+ memoryId: args.memory_id,
261
+ updateFields: Object.keys(updates),
262
+ updateValues: updates,
263
+ collectionName: `Memory_${userId}`,
264
+ totalProperties: Object.keys(mergedProperties).length,
265
+ });
266
+
253
267
  try {
254
- await collection.data.update({
268
+ await collection.data.replace({
255
269
  id: args.memory_id,
256
- properties: updates,
270
+ properties: mergedProperties,
271
+ });
272
+
273
+ logger.info('Weaviate replace completed (no error thrown)', {
274
+ userId,
275
+ memoryId: args.memory_id,
276
+ updatedFields: Object.keys(updates),
257
277
  });
258
278
  } catch (updateError) {
259
279
  const updateErrorMsg = updateError instanceof Error ? updateError.message : String(updateError);
260
- logger.error('Failed to perform Weaviate update:', {
280
+ logger.error('Failed to perform Weaviate replace:', {
261
281
  error: updateErrorMsg,
262
282
  userId,
263
283
  memoryId: args.memory_id,