frinus-mcp 3.2.0 → 3.2.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.
|
@@ -86,10 +86,12 @@ export class MemoryClient {
|
|
|
86
86
|
agent_id: data.agent_id,
|
|
87
87
|
content: data.content,
|
|
88
88
|
memory_type: data.memory_type || "episodic",
|
|
89
|
-
scope: data.scope || "organization",
|
|
90
89
|
importance: data.importance || 0.5,
|
|
91
90
|
metadata: data.metadata,
|
|
92
91
|
};
|
|
92
|
+
// The handler is the source of truth for scope; only send it when defined.
|
|
93
|
+
if (data.scope)
|
|
94
|
+
payload.scope = data.scope;
|
|
93
95
|
if (data.user_id)
|
|
94
96
|
payload.user_id = data.user_id;
|
|
95
97
|
if (data.created_by_user_id)
|
|
@@ -98,6 +100,8 @@ export class MemoryClient {
|
|
|
98
100
|
payload.context_id = data.context_id;
|
|
99
101
|
if (data.credential_ref)
|
|
100
102
|
payload.credential_ref = data.credential_ref;
|
|
103
|
+
if (data.universe_id)
|
|
104
|
+
payload.universe_id = data.universe_id;
|
|
101
105
|
const response = await this.client.post("/memories", payload);
|
|
102
106
|
return response.data;
|
|
103
107
|
}
|
|
@@ -38,7 +38,7 @@ Scopes:
|
|
|
38
38
|
scope: {
|
|
39
39
|
type: "string",
|
|
40
40
|
enum: ["user", "agent", "universe", "organization"],
|
|
41
|
-
description: "Visibility scope:
|
|
41
|
+
description: "Visibility scope. Padrão: a memória é associada ao universo do agente (contexto). 'organization' (org-wide) e 'user' (private) só são usados quando explicitamente definidos; 'agent' (agent-only) é o fallback automático quando não há universo identificável.",
|
|
42
42
|
},
|
|
43
43
|
importance: {
|
|
44
44
|
type: "number",
|
|
@@ -56,6 +56,10 @@ Scopes:
|
|
|
56
56
|
type: "object",
|
|
57
57
|
description: "Metadata adicional (tags, universe, idioma, etc.)",
|
|
58
58
|
},
|
|
59
|
+
universe_id: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "UUID do universo/contexto ao qual associar a memória. Se omitido, a memória é associada automaticamente ao universo do agente.",
|
|
62
|
+
},
|
|
59
63
|
context_id: {
|
|
60
64
|
type: "string",
|
|
61
65
|
description: "Optional UUID of a hierarchy node (universe, concept, theme, topic, or point). When provided, the memory is automatically linked to this node and all its ancestors. Takes precedence over universe_id for hierarchy placement.",
|
package/dist/tools/handlers.js
CHANGED
|
@@ -200,39 +200,33 @@ const handlers = {
|
|
|
200
200
|
// ==========================================================================
|
|
201
201
|
// Core Memory
|
|
202
202
|
// ==========================================================================
|
|
203
|
-
async memory_store(args, { memoryClient, resolvedUserId }) {
|
|
203
|
+
async memory_store(args, { memoryClient, cpClient, resolvedUserId }) {
|
|
204
|
+
const createdByUser = args.created_by_user_id || resolvedUserId || undefined;
|
|
205
|
+
const userId = args.user_id || resolvedUserId || undefined;
|
|
206
|
+
const meta = args.metadata || {};
|
|
207
|
+
const universeId = args.universe_id || meta.universe_id || undefined;
|
|
208
|
+
// Context-first default: when the caller does NOT pass an explicit `scope`,
|
|
209
|
+
// memories are associated with a CONTEXT (universe). The backend resolves
|
|
210
|
+
// the universe_id from the agent when none is supplied. `organization` and
|
|
211
|
+
// `user` are only used when explicitly requested by the caller. When the
|
|
212
|
+
// agent has no resolvable universe, we fall back to `agent` scope and help
|
|
213
|
+
// future categorization by returning the list of available universes.
|
|
214
|
+
const explicitScope = args.scope;
|
|
215
|
+
const resolvedScope = explicitScope || "universe";
|
|
216
|
+
const baseInput = {
|
|
217
|
+
agent_id: args.agent_id,
|
|
218
|
+
content: args.content,
|
|
219
|
+
memory_type: args.memory_type,
|
|
220
|
+
importance: args.importance,
|
|
221
|
+
user_id: userId,
|
|
222
|
+
created_by_user_id: createdByUser,
|
|
223
|
+
metadata: args.metadata,
|
|
224
|
+
context_id: args.context_id,
|
|
225
|
+
credential_ref: args.credential_ref,
|
|
226
|
+
universe_id: universeId,
|
|
227
|
+
};
|
|
204
228
|
try {
|
|
205
|
-
const
|
|
206
|
-
const userId = args.user_id || resolvedUserId || undefined;
|
|
207
|
-
// Auto-scope inference: if scope not provided, pick the narrowest
|
|
208
|
-
// scope justified by the available context. Caller can always pass
|
|
209
|
-
// an explicit `scope` to override this heuristic.
|
|
210
|
-
const meta = args.metadata || {};
|
|
211
|
-
const universeId = args.universe_id || meta.universe_id || undefined;
|
|
212
|
-
let resolvedScope = args.scope;
|
|
213
|
-
if (!resolvedScope) {
|
|
214
|
-
if (userId || createdByUser) {
|
|
215
|
-
resolvedScope = "user";
|
|
216
|
-
}
|
|
217
|
-
else if (universeId) {
|
|
218
|
-
resolvedScope = "universe";
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
resolvedScope = "organization";
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
const result = await memoryClient.storeMemory({
|
|
225
|
-
agent_id: args.agent_id,
|
|
226
|
-
content: args.content,
|
|
227
|
-
memory_type: args.memory_type,
|
|
228
|
-
scope: resolvedScope,
|
|
229
|
-
importance: args.importance,
|
|
230
|
-
user_id: userId,
|
|
231
|
-
created_by_user_id: createdByUser,
|
|
232
|
-
metadata: args.metadata,
|
|
233
|
-
context_id: args.context_id,
|
|
234
|
-
credential_ref: args.credential_ref,
|
|
235
|
-
});
|
|
229
|
+
const result = await memoryClient.storeMemory({ ...baseInput, scope: resolvedScope });
|
|
236
230
|
return {
|
|
237
231
|
content: [{
|
|
238
232
|
type: "text",
|
|
@@ -241,6 +235,45 @@ const handlers = {
|
|
|
241
235
|
};
|
|
242
236
|
}
|
|
243
237
|
catch (error) {
|
|
238
|
+
// Fallback: scope was implicitly "universe" but the agent has no
|
|
239
|
+
// resolvable universe (backend returns 400 "must be linked to a
|
|
240
|
+
// universe"). Retry as `agent` scope and surface available universes.
|
|
241
|
+
const status = error?.response?.status;
|
|
242
|
+
const detail = String(error?.response?.data?.detail ?? "");
|
|
243
|
+
const isMissingUniverse = status === 400 &&
|
|
244
|
+
!explicitScope &&
|
|
245
|
+
!universeId &&
|
|
246
|
+
detail.includes("must be linked to a universe");
|
|
247
|
+
if (isMissingUniverse) {
|
|
248
|
+
try {
|
|
249
|
+
const result = await memoryClient.storeMemory({ ...baseInput, scope: "agent" });
|
|
250
|
+
let text = `Memory stored successfully.\nID: ${result.id}\nType: ${result.memory_type}\nScope: ${result.scope}`;
|
|
251
|
+
// Enrich with available universes to help future categorization.
|
|
252
|
+
try {
|
|
253
|
+
const orgId = getResolvedTenantOrgId();
|
|
254
|
+
if (orgId) {
|
|
255
|
+
const list = await cpClient.listUniverses(orgId);
|
|
256
|
+
const universes = Array.isArray(list) ? list : (list.universes || list.items || []);
|
|
257
|
+
if (universes && universes.length > 0) {
|
|
258
|
+
text += `\n\nDica: esta memória não foi associada a um universo (salva como memória do agente). Para categorizá-la, informe universe_id na próxima vez. Universos disponíveis:`;
|
|
259
|
+
universes.forEach((u) => {
|
|
260
|
+
text += `\n- ${u.name} (id: ${u.id})`;
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
// Listing universes is best-effort; never break a successful store.
|
|
267
|
+
}
|
|
268
|
+
return { content: [{ type: "text", text }] };
|
|
269
|
+
}
|
|
270
|
+
catch (retryError) {
|
|
271
|
+
const retryApiErr = handleApiError(retryError);
|
|
272
|
+
if (retryApiErr)
|
|
273
|
+
return retryApiErr;
|
|
274
|
+
throw retryError;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
244
277
|
const apiErr = handleApiError(error);
|
|
245
278
|
if (apiErr)
|
|
246
279
|
return apiErr;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frinus-mcp",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.1",
|
|
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",
|