@tpsdev-ai/flair-mcp 0.16.1 → 0.18.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/dist/index.d.ts +1 -0
- package/dist/index.js +42 -25
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Tools:
|
|
6
6
|
* - memory_search — semantic search across memories
|
|
7
7
|
* - memory_store — save a memory with type + durability
|
|
8
|
+
* - memory_update — update an existing memory by ID (dedup-bypassed)
|
|
8
9
|
* - memory_get — retrieve a specific memory by ID
|
|
9
10
|
* - memory_delete — delete a memory
|
|
10
11
|
* - bootstrap — cold-start context (soul + recent memories)
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Tools:
|
|
6
6
|
* - memory_search — semantic search across memories
|
|
7
7
|
* - memory_store — save a memory with type + durability
|
|
8
|
+
* - memory_update — update an existing memory by ID (dedup-bypassed)
|
|
8
9
|
* - memory_get — retrieve a specific memory by ID
|
|
9
10
|
* - memory_delete — delete a memory
|
|
10
11
|
* - bootstrap — cold-start context (soul + recent memories)
|
|
@@ -184,40 +185,56 @@ export async function runMcp() {
|
|
|
184
185
|
dedup: true,
|
|
185
186
|
dedupThreshold: 0.95,
|
|
186
187
|
});
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
content: [{
|
|
200
|
-
type: "text",
|
|
201
|
-
text: `⚠️ DEDUPLICATED — new content was NOT written. ` +
|
|
202
|
-
`Matched existing memory id=${result.id}: ${result.content?.slice(0, 200)}\n\n` +
|
|
203
|
-
`If the new content is genuinely distinct, retry with different phrasing ` +
|
|
204
|
-
`or call memory_store with the same id to update.`,
|
|
205
|
-
}],
|
|
206
|
-
structuredContent: sc,
|
|
207
|
-
};
|
|
208
|
-
}
|
|
188
|
+
// The server's conservative dedup gate NEVER suppresses a write
|
|
189
|
+
// (memory-integrity fix, flair#526) — `result.deduplicated` is a
|
|
190
|
+
// collision SIGNAL, not a "was this dropped" flag. The new content at
|
|
191
|
+
// `result.id` is ALWAYS written; when flagged, `result.matchedId` names
|
|
192
|
+
// the similar existing memory (see result.matchConfidence for the
|
|
193
|
+
// cosine/lexical scores). Emit both prose AND structuredContent so
|
|
194
|
+
// callers can react programmatically even when LLMs compress prose
|
|
195
|
+
// imprecisely. (Historical note: this tool used to treat a dedup hit as
|
|
196
|
+
// "new content was NOT written" — that WAS the flair#449/#526 silent
|
|
197
|
+
// data-loss bug. The gate is server-side now and never suppresses.)
|
|
198
|
+
const deduplicated = result.deduplicated === true;
|
|
199
|
+
const matchedId = result.matchedId;
|
|
209
200
|
const preview = content.length > 120 ? content.slice(0, 120) + "..." : content;
|
|
210
201
|
const tagStr = tags && tags.length > 0 ? tags.join(", ") : "none";
|
|
211
|
-
const
|
|
202
|
+
const lines = [
|
|
212
203
|
`Memory stored (id: ${result.id})`,
|
|
213
204
|
`Preview: ${preview}`,
|
|
214
205
|
`Size: ${content.length} chars`,
|
|
215
206
|
`Tags: ${tagStr}`,
|
|
216
207
|
`Type: ${type}, Durability: ${durability}`,
|
|
217
|
-
]
|
|
208
|
+
];
|
|
209
|
+
if (deduplicated && matchedId) {
|
|
210
|
+
lines.push("", `Note: similar to existing memory id=${matchedId} — both are kept. ` +
|
|
211
|
+
`If this was meant to UPDATE that memory rather than add a new one, use memory_update instead.`);
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
215
|
+
structuredContent: { deduplicated, id: result.id, written: true, ...(deduplicated ? { matchedId } : {}) },
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
return errorResult(err, flair.url);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
server.tool("memory_update", "Update an existing memory by ID. Dedup-bypassed — this is an intentional overwrite/version, not an ambiguous new write. " +
|
|
223
|
+
"Default: overwrites the same id in place. Pass preserveHistory=true to instead write a new version linked via " +
|
|
224
|
+
"`supersedes`, closing the old one's validity window (requires owning the memory, or a write grant if it's another agent's).", {
|
|
225
|
+
id: z.string().describe("ID of the memory to update"),
|
|
226
|
+
content: z.string().describe("New content"),
|
|
227
|
+
preserveHistory: z.coerce.boolean().optional().default(false)
|
|
228
|
+
.describe("Write a new supersedes-linked version instead of overwriting in place (default false)"),
|
|
229
|
+
}, async ({ id, content, preserveHistory }) => {
|
|
230
|
+
try {
|
|
231
|
+
const result = await flair.memory.update(id, content, { preserveHistory });
|
|
232
|
+
const text = preserveHistory
|
|
233
|
+
? `Memory updated: new version stored (id: ${result.id}), supersedes ${id}.`
|
|
234
|
+
: `Memory updated (id: ${id}).`;
|
|
218
235
|
return {
|
|
219
236
|
content: [{ type: "text", text }],
|
|
220
|
-
structuredContent: {
|
|
237
|
+
structuredContent: { id: result.id, supersedes: preserveHistory ? id : undefined, written: true },
|
|
221
238
|
};
|
|
222
239
|
}
|
|
223
240
|
catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tpsdev-ai/flair-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "MCP server for Flair — persistent memory for Claude Code, Cursor, and any MCP client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@modelcontextprotocol/sdk": "1.27.1",
|
|
30
|
-
"@tpsdev-ai/flair-client": "0.
|
|
30
|
+
"@tpsdev-ai/flair-client": "0.18.0",
|
|
31
31
|
"zod": "4.3.6"
|
|
32
32
|
},
|
|
33
33
|
"license": "Apache-2.0",
|