frinus-mcp 3.6.3 → 3.6.4
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.js +1 -1
- package/dist/tools/definitions.js +18 -8
- package/dist/tools/handlers.js +55 -18
- package/manifest.json +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -9,16 +9,19 @@ export const TOOLS = [
|
|
|
9
9
|
Use this to record important information, learnings, decisions, or procedures
|
|
10
10
|
that should be remembered for future reference.
|
|
11
11
|
|
|
12
|
-
The backend classifies the memory by content at write time and
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
The backend classifies the memory by content at write time and proposes which
|
|
13
|
+
universe/context node it belongs to. When the tenant has auto-classification
|
|
14
|
+
enabled and the proposal's confidence meets the tenant threshold (the platform
|
|
15
|
+
target is 0.60), the backend ANCHORS the memory on that node automatically — it
|
|
16
|
+
is moved without review. Below the threshold (or with auto-classification off)
|
|
17
|
+
the proposal stays a PENDING suggestion: review it with
|
|
18
|
+
memory_classification_pending and apply with memory_classification_approve.
|
|
16
19
|
|
|
17
20
|
Passing universe_id or context_id anchors the memory THERE directly (status
|
|
18
21
|
"manual"): auto-classification is skipped entirely, so no suggestion is returned
|
|
19
22
|
and nothing may later move it. The response always reports the destination the
|
|
20
|
-
memory actually landed in — a suggestion
|
|
21
|
-
and
|
|
23
|
+
memory actually landed in — a suggestion that is still pending is labelled as
|
|
24
|
+
such and has NOT been applied.
|
|
22
25
|
|
|
23
26
|
Memory types:
|
|
24
27
|
- episodic: Specific experiences and events (what happened)
|
|
@@ -678,8 +681,15 @@ Useful for maintaining consistency in the knowledge base.`,
|
|
|
678
681
|
inputSchema: {
|
|
679
682
|
type: "object",
|
|
680
683
|
properties: {
|
|
681
|
-
|
|
682
|
-
|
|
684
|
+
// NOTE: the backend (POST /consolidation/detect-conflicts →
|
|
685
|
+
// ConflictDetectionRequest) does NOT accept similarity_threshold for
|
|
686
|
+
// conflict detection — conflict pairs are found by the forgetting
|
|
687
|
+
// manager's own analysis, and the field is silently ignored (the
|
|
688
|
+
// request model inherits _IgnoreExtra). It is kept here only for
|
|
689
|
+
// forward compatibility; it currently has no effect. Redundant
|
|
690
|
+
// detection (consolidation_detect_redundant) DOES honour it.
|
|
691
|
+
similarity_threshold: { type: "number", description: "Currently IGNORED by the backend for conflict detection (kept for forward compatibility). Use consolidation_detect_redundant to tune a similarity threshold." },
|
|
692
|
+
limit: { type: "integer", description: "Maximum memories to analyze (default: 50)" },
|
|
683
693
|
},
|
|
684
694
|
required: [],
|
|
685
695
|
},
|
package/dist/tools/handlers.js
CHANGED
|
@@ -365,14 +365,17 @@ const handlers = {
|
|
|
365
365
|
const userId = args.user_id || resolvedUserId || undefined;
|
|
366
366
|
const meta = args.metadata || {};
|
|
367
367
|
const universeId = args.universe_id || meta.universe_id || undefined;
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
//
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
//
|
|
368
|
+
// Write-time classification: the backend classifies the memory by content
|
|
369
|
+
// and, when the tenant's `auto_classify` setting is enabled and the
|
|
370
|
+
// proposal confidence meets the tenant threshold, anchors it automatically
|
|
371
|
+
// (classification_status "proposed"/"universe_only" become real FK columns);
|
|
372
|
+
// below the threshold it stays a pending SUGGESTION the user reviews via
|
|
373
|
+
// memory_classification_pending / memory_classification_approve. See
|
|
374
|
+
// memory/src/api/routers/memories.py (classification/settings). The MCP
|
|
375
|
+
// layer no longer injects an implicit "universe" scope nor surfaces
|
|
376
|
+
// "available universes"; scope, universe_id and context_id are forwarded
|
|
377
|
+
// ONLY when the caller sets them (explicit overrides → status "manual",
|
|
378
|
+
// which anchors there directly and skips classification).
|
|
376
379
|
try {
|
|
377
380
|
const result = await memoryClient.storeMemory({
|
|
378
381
|
agent_id: args.agent_id,
|
|
@@ -890,7 +893,18 @@ const handlers = {
|
|
|
890
893
|
}
|
|
891
894
|
formatted += `\n`;
|
|
892
895
|
results.memories.forEach((mem, i) => {
|
|
893
|
-
|
|
896
|
+
// Q-MEM-02: /memories/search-with-attention returns `attention_score`
|
|
897
|
+
// (re-ranked) + `base_similarity` (see memory/src/api/schemas.py
|
|
898
|
+
// MemoryWithAttentionScore). The legacy field `weighted_score` and the
|
|
899
|
+
// plain /memories/search field `similarity` are kept as fallbacks so the
|
|
900
|
+
// same renderer works across endpoints. `?? ` (not `||`) so a real 0 score
|
|
901
|
+
// is not swallowed.
|
|
902
|
+
const score = mem.attention_score ??
|
|
903
|
+
mem.weighted_score ??
|
|
904
|
+
mem.base_similarity ??
|
|
905
|
+
mem.similarity;
|
|
906
|
+
const scoreTxt = typeof score === "number" ? score.toFixed(2) : "n/a";
|
|
907
|
+
formatted += `${i + 1}. [${mem.memory_type}] (id: ${mem.id}) (score: ${scoreTxt})\n`;
|
|
894
908
|
formatted += ` ${mem.content?.slice(0, 200)}...\n\n`;
|
|
895
909
|
});
|
|
896
910
|
return { content: [{ type: "text", text: formatted }] };
|
|
@@ -1035,11 +1049,27 @@ const handlers = {
|
|
|
1035
1049
|
if (!conflicts || conflicts.length === 0) {
|
|
1036
1050
|
return { content: [{ type: "text", text: "No conflicts detected." }] };
|
|
1037
1051
|
}
|
|
1038
|
-
let formatted = `Detected ${result.conflicts_found
|
|
1052
|
+
let formatted = `Detected ${result.conflicts_found ?? conflicts.length} potential conflicts:\n\n`;
|
|
1039
1053
|
conflicts.forEach((conflict, i) => {
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1054
|
+
// Q-MEM-03: the backend emits `memory_1` / `memory_2` (ConflictPair in
|
|
1055
|
+
// memory/src/api/schemas.py), each with id/content, plus `conflict_type`
|
|
1056
|
+
// and `suggested_action`. The old code read `memory1`/`memory2` (no
|
|
1057
|
+
// underscore) so content printed as "undefined" and the type/action were
|
|
1058
|
+
// dropped. Keep the snake-less variants as a defensive fallback.
|
|
1059
|
+
const m1 = conflict.memory_1 ?? conflict.memory1;
|
|
1060
|
+
const m2 = conflict.memory_2 ?? conflict.memory2;
|
|
1061
|
+
const simTxt = typeof conflict.similarity === "number"
|
|
1062
|
+
? conflict.similarity.toFixed(2)
|
|
1063
|
+
: "n/a";
|
|
1064
|
+
formatted += `${i + 1}. Similarity: ${simTxt}`;
|
|
1065
|
+
if (conflict.conflict_type)
|
|
1066
|
+
formatted += ` · type: ${conflict.conflict_type}`;
|
|
1067
|
+
formatted += `\n`;
|
|
1068
|
+
formatted += ` Memory 1 (${m1?.id ?? "?"}): ${m1?.content?.slice(0, 100) ?? "(no content)"}...\n`;
|
|
1069
|
+
formatted += ` Memory 2 (${m2?.id ?? "?"}): ${m2?.content?.slice(0, 100) ?? "(no content)"}...\n`;
|
|
1070
|
+
if (conflict.suggested_action)
|
|
1071
|
+
formatted += ` Suggested action: ${conflict.suggested_action}\n`;
|
|
1072
|
+
formatted += `\n`;
|
|
1043
1073
|
});
|
|
1044
1074
|
return { content: [{ type: "text", text: formatted }] };
|
|
1045
1075
|
},
|
|
@@ -1062,12 +1092,19 @@ const handlers = {
|
|
|
1062
1092
|
if (!groups || groups.length === 0) {
|
|
1063
1093
|
return { content: [{ type: "text", text: "No redundant memories detected." }] };
|
|
1064
1094
|
}
|
|
1065
|
-
let formatted = `Detected ${result.groups_found
|
|
1095
|
+
let formatted = `Detected ${result.groups_found ?? groups.length} redundant memory groups (${result.total_redundant ?? 0} redundant memories):\n\n`;
|
|
1066
1096
|
groups.forEach((group, i) => {
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1097
|
+
// Q-MEM-04: the backend emits `keep` (the memory to retain), `redundant`
|
|
1098
|
+
// (the duplicates) and `total_in_group` (RedundantGroup in
|
|
1099
|
+
// memory/src/api/schemas.py). The old code read `avg_similarity`,
|
|
1100
|
+
// `memory_ids` and `memories`, none of which exist, so every group showed
|
|
1101
|
+
// "N/A" and 0 memories.
|
|
1102
|
+
const redundantCount = Array.isArray(group.redundant) ? group.redundant.length : 0;
|
|
1103
|
+
const total = group.total_in_group ?? (redundantCount + (group.keep ? 1 : 0));
|
|
1104
|
+
formatted += `${i + 1}. Memories in group: ${total} (keep 1, redundant ${redundantCount})\n`;
|
|
1105
|
+
const keepPreview = group.keep?.content?.slice(0, 100);
|
|
1106
|
+
if (keepPreview) {
|
|
1107
|
+
formatted += ` Keep (${group.keep?.id ?? "?"}): ${keepPreview}...\n`;
|
|
1071
1108
|
}
|
|
1072
1109
|
formatted += `\n`;
|
|
1073
1110
|
});
|
package/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": "0.3",
|
|
3
3
|
"name": "frinus",
|
|
4
4
|
"display_name": "Frinus — Memória Cognitiva",
|
|
5
|
-
"version": "3.6.
|
|
5
|
+
"version": "3.6.4",
|
|
6
6
|
"description": "Memória cognitiva de longo prazo para o Claude (φρήν + νοῦς). 83 ferramentas de memória, sessões, agentes e conhecimento.",
|
|
7
7
|
"long_description": "O Frinus dá ao Claude memória de longo prazo, identidade e inteligência persistente entre conversas. Conecta o Claude Desktop à plataforma Frinus (Memory Engine, Control Plane e Agent Service) via MCP. Basta colar sua chave de API pessoal — nada para instalar ou compilar.",
|
|
8
8
|
"author": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frinus-mcp",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.4",
|
|
4
4
|
"description": "Frinus - MCP Server for Cognitive Memory (φρήν + νοῦς). Long-term memory, sessions, agents and knowledge for Claude and any MCP client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsc",
|
|
20
|
+
"test": "node --import tsx --test tests/*.test.ts",
|
|
20
21
|
"start": "node dist/index.js",
|
|
21
22
|
"dev": "tsx src/index.ts",
|
|
22
23
|
"pack:mcpb": "./scripts/pack-mcpb.sh",
|