@frontmcp/plugin-remember 1.8.6 → 1.9.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/esm/index.mjs +321 -243
- package/esm/package.json +4 -4
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +327 -251
- package/package.json +4 -4
- package/providers/remember-accessor.provider.d.ts +8 -3
- package/providers/remember-accessor.provider.d.ts.map +1 -1
- package/remember.errors.d.ts +9 -0
- package/remember.errors.d.ts.map +1 -1
- package/remember.plugin.d.ts +6 -1
- package/remember.plugin.d.ts.map +1 -1
- package/tools/forget.tool.d.ts +24 -0
- package/tools/forget.tool.d.ts.map +1 -1
- package/tools/index.d.ts +2 -0
- package/tools/index.d.ts.map +1 -1
- package/tools/list-memories.tool.d.ts +25 -0
- package/tools/list-memories.tool.d.ts.map +1 -1
- package/tools/recall.tool.d.ts +26 -0
- package/tools/recall.tool.d.ts.map +1 -1
- package/tools/remember-this.tool.d.ts +33 -0
- package/tools/remember-this.tool.d.ts.map +1 -1
- package/tools/remember-tool-names.d.ts +9 -0
- package/tools/remember-tool-names.d.ts.map +1 -0
- package/tools/remember-tools.factory.d.ts +8 -0
- package/tools/remember-tools.factory.d.ts.map +1 -0
package/index.js
CHANGED
|
@@ -50,6 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
RememberMemoryProvider: () => RememberMemoryProvider,
|
|
51
51
|
RememberPlugin: () => RememberPlugin,
|
|
52
52
|
RememberRedisProvider: () => RememberRedisProvider,
|
|
53
|
+
RememberScopeNotAllowedError: () => RememberScopeNotAllowedError,
|
|
53
54
|
RememberStoreToken: () => RememberStoreToken,
|
|
54
55
|
RememberThisTool: () => RememberThisTool,
|
|
55
56
|
RememberVercelKvProvider: () => RememberVercelKvProvider,
|
|
@@ -61,7 +62,7 @@ __export(index_exports, {
|
|
|
61
62
|
module.exports = __toCommonJS(index_exports);
|
|
62
63
|
|
|
63
64
|
// plugins/plugin-remember/src/remember.plugin.ts
|
|
64
|
-
var
|
|
65
|
+
var import_sdk11 = require("@frontmcp/sdk");
|
|
65
66
|
|
|
66
67
|
// plugins/plugin-remember/src/providers/remember-accessor.provider.ts
|
|
67
68
|
var import_sdk2 = require("@frontmcp/sdk");
|
|
@@ -310,6 +311,16 @@ var RememberIdentityError = class extends import_sdk.PublicMcpError {
|
|
|
310
311
|
super(message, "REMEMBER_IDENTITY_REQUIRED", 403);
|
|
311
312
|
}
|
|
312
313
|
};
|
|
314
|
+
var RememberScopeNotAllowedError = class extends import_sdk.PublicMcpError {
|
|
315
|
+
name = "RememberScopeNotAllowedError";
|
|
316
|
+
constructor(scope, allowedScopes) {
|
|
317
|
+
super(
|
|
318
|
+
`Scope '${scope}' is not allowed. Allowed scopes: ${allowedScopes.join(", ")}`,
|
|
319
|
+
"REMEMBER_SCOPE_NOT_ALLOWED",
|
|
320
|
+
400
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
313
324
|
|
|
314
325
|
// plugins/plugin-remember/src/remember.legacy-purge.ts
|
|
315
326
|
var LEGACY_SCOPES = ["session", "tool", "user"];
|
|
@@ -416,6 +427,9 @@ var STORAGE_LAYOUT_VERSION = "v2";
|
|
|
416
427
|
function encodeKeyPart(value) {
|
|
417
428
|
return encodeURIComponent(value);
|
|
418
429
|
}
|
|
430
|
+
function remainingSeconds(expiresAt, now) {
|
|
431
|
+
return Math.max(1, Math.ceil((expiresAt - now) / 1e3));
|
|
432
|
+
}
|
|
419
433
|
var RememberAccessor = class {
|
|
420
434
|
store;
|
|
421
435
|
ctx;
|
|
@@ -465,16 +479,8 @@ var RememberAccessor = class {
|
|
|
465
479
|
*/
|
|
466
480
|
async get(key, options = {}) {
|
|
467
481
|
const scope = options.scope ?? "session";
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
if (!raw) return options.defaultValue;
|
|
471
|
-
const entry = this.encryptionEnabled ? await deserializeAndDecrypt(raw, this.getKeySource(scope)) : this.parseEntry(raw);
|
|
472
|
-
if (!entry) return options.defaultValue;
|
|
473
|
-
if (entry.expiresAt && Date.now() > entry.expiresAt) {
|
|
474
|
-
await this.forget(key, { scope });
|
|
475
|
-
return options.defaultValue;
|
|
476
|
-
}
|
|
477
|
-
return entry.value;
|
|
482
|
+
const entry = await this.readEntry(this.buildStorageKey(key, scope), scope);
|
|
483
|
+
return entry ? entry.value : options.defaultValue;
|
|
478
484
|
}
|
|
479
485
|
/**
|
|
480
486
|
* Get the full entry including metadata.
|
|
@@ -485,16 +491,7 @@ var RememberAccessor = class {
|
|
|
485
491
|
*/
|
|
486
492
|
async getEntry(key, options = {}) {
|
|
487
493
|
const scope = options.scope ?? "session";
|
|
488
|
-
|
|
489
|
-
const raw = await this.store.getValue(storageKey);
|
|
490
|
-
if (!raw) return void 0;
|
|
491
|
-
const entry = this.encryptionEnabled ? await deserializeAndDecrypt(raw, this.getKeySource(scope)) : this.parseEntry(raw);
|
|
492
|
-
if (!entry) return void 0;
|
|
493
|
-
if (entry.expiresAt && Date.now() > entry.expiresAt) {
|
|
494
|
-
await this.forget(key, { scope });
|
|
495
|
-
return void 0;
|
|
496
|
-
}
|
|
497
|
-
return entry;
|
|
494
|
+
return this.readEntry(this.buildStorageKey(key, scope), scope);
|
|
498
495
|
}
|
|
499
496
|
/**
|
|
500
497
|
* Forget (delete) a value from memory.
|
|
@@ -508,19 +505,18 @@ var RememberAccessor = class {
|
|
|
508
505
|
await this.store.delete(storageKey);
|
|
509
506
|
}
|
|
510
507
|
/**
|
|
511
|
-
* Check if a key is remembered (
|
|
508
|
+
* Check if a key is remembered: true exactly when `get()` would return its value.
|
|
512
509
|
*
|
|
513
510
|
* @param key - The key to check
|
|
514
511
|
* @param options - Options (scope)
|
|
515
|
-
* @returns true if the key exists
|
|
512
|
+
* @returns true if the key exists and has not expired
|
|
516
513
|
*/
|
|
517
514
|
async knows(key, options = {}) {
|
|
518
515
|
const scope = options.scope ?? "session";
|
|
519
|
-
|
|
520
|
-
return this.store.exists(storageKey);
|
|
516
|
+
return await this.readEntry(this.buildStorageKey(key, scope), scope) !== void 0;
|
|
521
517
|
}
|
|
522
518
|
/**
|
|
523
|
-
* List all remembered keys for a scope.
|
|
519
|
+
* List all remembered keys for a scope: the keys `get()` would return a value for.
|
|
524
520
|
*
|
|
525
521
|
* @param options - Options (scope, pattern)
|
|
526
522
|
* @returns Array of keys (without the scope prefix)
|
|
@@ -528,13 +524,16 @@ var RememberAccessor = class {
|
|
|
528
524
|
async list(options = {}) {
|
|
529
525
|
const scope = options.scope ?? "session";
|
|
530
526
|
const scopePrefix = this.buildScopePrefix(scope);
|
|
531
|
-
const
|
|
532
|
-
const
|
|
533
|
-
return
|
|
527
|
+
const storageKeys = await this.store.keys(scopePrefix + (options.pattern ?? "*"));
|
|
528
|
+
const entries = await Promise.all(storageKeys.map((storageKey) => this.readEntry(storageKey, scope)));
|
|
529
|
+
return storageKeys.filter((_storageKey, index) => entries[index] !== void 0).map((storageKey) => storageKey.slice(scopePrefix.length));
|
|
534
530
|
}
|
|
535
531
|
/**
|
|
536
532
|
* Update an existing entry's value while preserving metadata.
|
|
537
533
|
*
|
|
534
|
+
* With a `ttl` the entry expires that many seconds from now; without one it keeps its current
|
|
535
|
+
* expiry, in the store as well, so the store does not keep it past that (rounded up to a second).
|
|
536
|
+
*
|
|
538
537
|
* @param key - The key to update
|
|
539
538
|
* @param value - The new value
|
|
540
539
|
* @param options - Options (scope, ttl)
|
|
@@ -543,15 +542,18 @@ var RememberAccessor = class {
|
|
|
543
542
|
const scope = options.scope ?? "session";
|
|
544
543
|
const existing = await this.getEntry(key, { scope });
|
|
545
544
|
if (!existing) return false;
|
|
545
|
+
const now = Date.now();
|
|
546
|
+
const expiresAt = options.ttl ? now + options.ttl * 1e3 : existing.expiresAt;
|
|
546
547
|
const entry = {
|
|
547
548
|
...existing,
|
|
548
549
|
value,
|
|
549
|
-
updatedAt:
|
|
550
|
-
expiresAt
|
|
550
|
+
updatedAt: now,
|
|
551
|
+
expiresAt
|
|
551
552
|
};
|
|
552
553
|
const storageKey = this.buildStorageKey(key, scope);
|
|
553
554
|
const serialized = this.encryptionEnabled ? await encryptAndSerialize(entry, this.getKeySource(scope)) : JSON.stringify(entry);
|
|
554
|
-
|
|
555
|
+
const storageTtl = options.ttl ?? (expiresAt !== void 0 ? remainingSeconds(expiresAt, now) : void 0);
|
|
556
|
+
await this.store.setValue(storageKey, serialized, storageTtl);
|
|
555
557
|
return true;
|
|
556
558
|
}
|
|
557
559
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -669,6 +671,18 @@ var RememberAccessor = class {
|
|
|
669
671
|
toolName: scope === "tool" ? this.toolName : void 0
|
|
670
672
|
});
|
|
671
673
|
}
|
|
674
|
+
/** The entry stored under `storageKey`, if readable and unexpired; an expired one is deleted. */
|
|
675
|
+
async readEntry(storageKey, scope) {
|
|
676
|
+
const raw = await this.store.getValue(storageKey);
|
|
677
|
+
if (!raw) return void 0;
|
|
678
|
+
const entry = this.encryptionEnabled ? await deserializeAndDecrypt(raw, this.getKeySource(scope)) : this.parseEntry(raw);
|
|
679
|
+
if (!entry) return void 0;
|
|
680
|
+
if (entry.expiresAt && Date.now() > entry.expiresAt) {
|
|
681
|
+
await this.store.delete(storageKey);
|
|
682
|
+
return void 0;
|
|
683
|
+
}
|
|
684
|
+
return entry;
|
|
685
|
+
}
|
|
672
686
|
/**
|
|
673
687
|
* Parse a JSON entry (when encryption is disabled).
|
|
674
688
|
*/
|
|
@@ -1150,8 +1164,267 @@ var RememberAccessorToken = /* @__PURE__ */ Symbol(
|
|
|
1150
1164
|
"plugin:remember:accessor"
|
|
1151
1165
|
);
|
|
1152
1166
|
|
|
1167
|
+
// plugins/plugin-remember/src/tools/remember-tools.factory.ts
|
|
1168
|
+
var import_sdk10 = require("@frontmcp/sdk");
|
|
1169
|
+
|
|
1170
|
+
// plugins/plugin-remember/src/tools/forget.tool.ts
|
|
1171
|
+
var import_lazy_zod2 = require("@frontmcp/lazy-zod");
|
|
1172
|
+
var import_sdk6 = require("@frontmcp/sdk");
|
|
1173
|
+
|
|
1174
|
+
// plugins/plugin-remember/src/tools/remember-scope.description.ts
|
|
1175
|
+
var REMEMBER_SCOPE_DESCRIPTION = "Whose memory to use (default: session). session: this session; without one (stateless HTTP, MCP 2026-07-28), the signed-in caller across its requests. user: the signed-in caller, across all of its sessions. tool: the tool running the call, for the same caller as session; each memory tool has its own, so the other memory tools do not see what one of them stores in tool scope. global: shared by every caller. An anonymous caller cannot use user scope, nor session or tool scope without a session.";
|
|
1176
|
+
|
|
1177
|
+
// plugins/plugin-remember/src/tools/remember-tool-names.ts
|
|
1178
|
+
function rememberToolNames(prefix = "") {
|
|
1179
|
+
return {
|
|
1180
|
+
rememberThis: `${prefix}remember_this`,
|
|
1181
|
+
recall: `${prefix}recall`,
|
|
1182
|
+
forget: `${prefix}forget`,
|
|
1183
|
+
listMemories: `${prefix}list_memories`
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// plugins/plugin-remember/src/tools/forget.tool.ts
|
|
1188
|
+
var forgetInputSchema = {
|
|
1189
|
+
key: import_lazy_zod2.z.string().min(1).describe("What memory to forget"),
|
|
1190
|
+
scope: import_lazy_zod2.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)
|
|
1191
|
+
};
|
|
1192
|
+
var forgetOutputSchema = import_lazy_zod2.z.object({
|
|
1193
|
+
success: import_lazy_zod2.z.boolean(),
|
|
1194
|
+
key: import_lazy_zod2.z.string(),
|
|
1195
|
+
scope: import_lazy_zod2.z.string(),
|
|
1196
|
+
existed: import_lazy_zod2.z.boolean()
|
|
1197
|
+
});
|
|
1198
|
+
function forgetDescription() {
|
|
1199
|
+
return "Forget a previously remembered value. Use this when the user wants to delete stored preferences or information.";
|
|
1200
|
+
}
|
|
1201
|
+
function forgetToolMetadata(names = rememberToolNames()) {
|
|
1202
|
+
return {
|
|
1203
|
+
name: names.forget,
|
|
1204
|
+
description: forgetDescription(),
|
|
1205
|
+
inputSchema: forgetInputSchema,
|
|
1206
|
+
outputSchema: forgetOutputSchema,
|
|
1207
|
+
annotations: { readOnlyHint: false }
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
var ForgetTool = class extends import_sdk6.ToolContext {
|
|
1211
|
+
async execute(input) {
|
|
1212
|
+
const remember = this.get(RememberAccessorToken);
|
|
1213
|
+
const config = this.get(RememberConfigToken);
|
|
1214
|
+
const scope = input.scope ?? "session";
|
|
1215
|
+
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1216
|
+
if (!allowedScopes.includes(scope)) {
|
|
1217
|
+
throw this.fail(new RememberScopeNotAllowedError(scope, allowedScopes));
|
|
1218
|
+
}
|
|
1219
|
+
const existed = await remember.knows(input.key, { scope });
|
|
1220
|
+
await remember.forget(input.key, { scope });
|
|
1221
|
+
return {
|
|
1222
|
+
success: true,
|
|
1223
|
+
key: input.key,
|
|
1224
|
+
scope,
|
|
1225
|
+
existed
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
ForgetTool = __decorateClass([
|
|
1230
|
+
(0, import_sdk6.Tool)(forgetToolMetadata())
|
|
1231
|
+
], ForgetTool);
|
|
1232
|
+
|
|
1233
|
+
// plugins/plugin-remember/src/tools/list-memories.tool.ts
|
|
1234
|
+
var import_lazy_zod3 = require("@frontmcp/lazy-zod");
|
|
1235
|
+
var import_sdk7 = require("@frontmcp/sdk");
|
|
1236
|
+
var listMemoriesInputSchema = {
|
|
1237
|
+
scope: import_lazy_zod3.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),
|
|
1238
|
+
pattern: import_lazy_zod3.z.string().optional().describe('Pattern to filter keys (e.g., "user_*")'),
|
|
1239
|
+
limit: import_lazy_zod3.z.number().positive().max(100).optional().describe("Maximum number of keys to return (default: 50)")
|
|
1240
|
+
};
|
|
1241
|
+
var listMemoriesOutputSchema = import_lazy_zod3.z.object({
|
|
1242
|
+
keys: import_lazy_zod3.z.array(import_lazy_zod3.z.string()),
|
|
1243
|
+
scope: import_lazy_zod3.z.string(),
|
|
1244
|
+
count: import_lazy_zod3.z.number(),
|
|
1245
|
+
truncated: import_lazy_zod3.z.boolean()
|
|
1246
|
+
});
|
|
1247
|
+
function listMemoriesDescription(names = rememberToolNames()) {
|
|
1248
|
+
return `List the remembered keys in one scope (default: session). Use this to see what memories are stored before you ${names.recall} or ${names.forget} one.`;
|
|
1249
|
+
}
|
|
1250
|
+
function listMemoriesToolMetadata(names = rememberToolNames()) {
|
|
1251
|
+
return {
|
|
1252
|
+
name: names.listMemories,
|
|
1253
|
+
description: listMemoriesDescription(names),
|
|
1254
|
+
inputSchema: listMemoriesInputSchema,
|
|
1255
|
+
outputSchema: listMemoriesOutputSchema,
|
|
1256
|
+
annotations: { readOnlyHint: true }
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
var ListMemoriesTool = class extends import_sdk7.ToolContext {
|
|
1260
|
+
async execute(input) {
|
|
1261
|
+
const remember = this.get(RememberAccessorToken);
|
|
1262
|
+
const config = this.get(RememberConfigToken);
|
|
1263
|
+
const scope = input.scope ?? "session";
|
|
1264
|
+
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1265
|
+
if (!allowedScopes.includes(scope)) {
|
|
1266
|
+
throw this.fail(new RememberScopeNotAllowedError(scope, allowedScopes));
|
|
1267
|
+
}
|
|
1268
|
+
const limit = input.limit ?? 50;
|
|
1269
|
+
let keys = await remember.list({ scope, pattern: input.pattern });
|
|
1270
|
+
const truncated = keys.length > limit;
|
|
1271
|
+
if (truncated) {
|
|
1272
|
+
keys = keys.slice(0, limit);
|
|
1273
|
+
}
|
|
1274
|
+
return {
|
|
1275
|
+
keys,
|
|
1276
|
+
scope,
|
|
1277
|
+
count: keys.length,
|
|
1278
|
+
truncated
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
ListMemoriesTool = __decorateClass([
|
|
1283
|
+
(0, import_sdk7.Tool)(listMemoriesToolMetadata())
|
|
1284
|
+
], ListMemoriesTool);
|
|
1285
|
+
|
|
1286
|
+
// plugins/plugin-remember/src/tools/recall.tool.ts
|
|
1287
|
+
var import_lazy_zod4 = require("@frontmcp/lazy-zod");
|
|
1288
|
+
var import_sdk8 = require("@frontmcp/sdk");
|
|
1289
|
+
var recallInputSchema = {
|
|
1290
|
+
key: import_lazy_zod4.z.string().min(1).describe("What memory to recall"),
|
|
1291
|
+
scope: import_lazy_zod4.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)
|
|
1292
|
+
};
|
|
1293
|
+
var recallOutputSchema = import_lazy_zod4.z.object({
|
|
1294
|
+
found: import_lazy_zod4.z.boolean(),
|
|
1295
|
+
key: import_lazy_zod4.z.string(),
|
|
1296
|
+
value: import_lazy_zod4.z.unknown().optional(),
|
|
1297
|
+
scope: import_lazy_zod4.z.string(),
|
|
1298
|
+
createdAt: import_lazy_zod4.z.number().optional(),
|
|
1299
|
+
expiresAt: import_lazy_zod4.z.number().optional()
|
|
1300
|
+
});
|
|
1301
|
+
function recallDescription(names = rememberToolNames()) {
|
|
1302
|
+
return `Recall something that was previously remembered. Use this to retrieve stored preferences, settings, or any information that was saved with ${names.rememberThis}.`;
|
|
1303
|
+
}
|
|
1304
|
+
function recallToolMetadata(names = rememberToolNames()) {
|
|
1305
|
+
return {
|
|
1306
|
+
name: names.recall,
|
|
1307
|
+
description: recallDescription(names),
|
|
1308
|
+
inputSchema: recallInputSchema,
|
|
1309
|
+
outputSchema: recallOutputSchema,
|
|
1310
|
+
annotations: { readOnlyHint: true }
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
var RecallTool = class extends import_sdk8.ToolContext {
|
|
1314
|
+
async execute(input) {
|
|
1315
|
+
const remember = this.get(RememberAccessorToken);
|
|
1316
|
+
const config = this.get(RememberConfigToken);
|
|
1317
|
+
const scope = input.scope ?? "session";
|
|
1318
|
+
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1319
|
+
if (!allowedScopes.includes(scope)) {
|
|
1320
|
+
throw this.fail(new RememberScopeNotAllowedError(scope, allowedScopes));
|
|
1321
|
+
}
|
|
1322
|
+
const entry = await remember.getEntry(input.key, { scope });
|
|
1323
|
+
if (!entry) {
|
|
1324
|
+
return {
|
|
1325
|
+
found: false,
|
|
1326
|
+
key: input.key,
|
|
1327
|
+
scope
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
return {
|
|
1331
|
+
found: true,
|
|
1332
|
+
key: input.key,
|
|
1333
|
+
value: entry.value,
|
|
1334
|
+
scope,
|
|
1335
|
+
createdAt: entry.createdAt,
|
|
1336
|
+
expiresAt: entry.expiresAt
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1340
|
+
RecallTool = __decorateClass([
|
|
1341
|
+
(0, import_sdk8.Tool)(recallToolMetadata())
|
|
1342
|
+
], RecallTool);
|
|
1343
|
+
|
|
1344
|
+
// plugins/plugin-remember/src/tools/remember-this.tool.ts
|
|
1345
|
+
var import_lazy_zod5 = require("@frontmcp/lazy-zod");
|
|
1346
|
+
var import_sdk9 = require("@frontmcp/sdk");
|
|
1347
|
+
var rememberThisInputSchema = {
|
|
1348
|
+
key: import_lazy_zod5.z.string().min(1).describe('What to call this memory (e.g., "user_preference", "last_action")'),
|
|
1349
|
+
value: import_lazy_zod5.z.unknown().describe("The value to remember (any JSON-serializable data)"),
|
|
1350
|
+
scope: import_lazy_zod5.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),
|
|
1351
|
+
ttl: import_lazy_zod5.z.number().positive().optional().describe("Forget after this many seconds"),
|
|
1352
|
+
brand: import_lazy_zod5.z.enum(["preference", "cache", "state", "conversation", "custom"]).optional().describe("Type hint for the stored value")
|
|
1353
|
+
};
|
|
1354
|
+
var rememberThisOutputSchema = import_lazy_zod5.z.object({
|
|
1355
|
+
success: import_lazy_zod5.z.boolean(),
|
|
1356
|
+
key: import_lazy_zod5.z.string(),
|
|
1357
|
+
scope: import_lazy_zod5.z.string(),
|
|
1358
|
+
expiresAt: import_lazy_zod5.z.number().optional()
|
|
1359
|
+
});
|
|
1360
|
+
function rememberThisDescription(names = rememberToolNames()) {
|
|
1361
|
+
return `Remember something for later: store a value under a key that ${names.recall} can read back, in the scope you choose (this session by default; user scope for the signed-in user across sessions). It lasts until it is forgotten or its ttl runs out. Use this when the user asks you to remember preferences, settings, or any information they want to persist.`;
|
|
1362
|
+
}
|
|
1363
|
+
function rememberThisToolMetadata(names = rememberToolNames()) {
|
|
1364
|
+
return {
|
|
1365
|
+
name: names.rememberThis,
|
|
1366
|
+
description: rememberThisDescription(names),
|
|
1367
|
+
inputSchema: rememberThisInputSchema,
|
|
1368
|
+
outputSchema: rememberThisOutputSchema,
|
|
1369
|
+
annotations: { readOnlyHint: false }
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
var RememberThisTool = class extends import_sdk9.ToolContext {
|
|
1373
|
+
async execute(input) {
|
|
1374
|
+
const remember = this.get(RememberAccessorToken);
|
|
1375
|
+
const config = this.get(RememberConfigToken);
|
|
1376
|
+
const scope = input.scope ?? "session";
|
|
1377
|
+
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1378
|
+
if (!allowedScopes.includes(scope)) {
|
|
1379
|
+
throw this.fail(new RememberScopeNotAllowedError(scope, allowedScopes));
|
|
1380
|
+
}
|
|
1381
|
+
await remember.set(input.key, input.value, {
|
|
1382
|
+
scope,
|
|
1383
|
+
ttl: input.ttl,
|
|
1384
|
+
brand: input.brand
|
|
1385
|
+
});
|
|
1386
|
+
const expiresAt = input.ttl ? Date.now() + input.ttl * 1e3 : void 0;
|
|
1387
|
+
return {
|
|
1388
|
+
success: true,
|
|
1389
|
+
key: input.key,
|
|
1390
|
+
scope,
|
|
1391
|
+
expiresAt
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
RememberThisTool = __decorateClass([
|
|
1396
|
+
(0, import_sdk9.Tool)(rememberThisToolMetadata())
|
|
1397
|
+
], RememberThisTool);
|
|
1398
|
+
|
|
1399
|
+
// plugins/plugin-remember/src/tools/remember-tools.factory.ts
|
|
1400
|
+
function createRememberTools(prefix = "") {
|
|
1401
|
+
if (!prefix) return [RememberThisTool, RecallTool, ForgetTool, ListMemoriesTool];
|
|
1402
|
+
const names = rememberToolNames(prefix);
|
|
1403
|
+
let PrefixedRememberThisTool = class extends RememberThisTool {
|
|
1404
|
+
};
|
|
1405
|
+
PrefixedRememberThisTool = __decorateClass([
|
|
1406
|
+
(0, import_sdk10.Tool)(rememberThisToolMetadata(names))
|
|
1407
|
+
], PrefixedRememberThisTool);
|
|
1408
|
+
let PrefixedRecallTool = class extends RecallTool {
|
|
1409
|
+
};
|
|
1410
|
+
PrefixedRecallTool = __decorateClass([
|
|
1411
|
+
(0, import_sdk10.Tool)(recallToolMetadata(names))
|
|
1412
|
+
], PrefixedRecallTool);
|
|
1413
|
+
let PrefixedForgetTool = class extends ForgetTool {
|
|
1414
|
+
};
|
|
1415
|
+
PrefixedForgetTool = __decorateClass([
|
|
1416
|
+
(0, import_sdk10.Tool)(forgetToolMetadata(names))
|
|
1417
|
+
], PrefixedForgetTool);
|
|
1418
|
+
let PrefixedListMemoriesTool = class extends ListMemoriesTool {
|
|
1419
|
+
};
|
|
1420
|
+
PrefixedListMemoriesTool = __decorateClass([
|
|
1421
|
+
(0, import_sdk10.Tool)(listMemoriesToolMetadata(names))
|
|
1422
|
+
], PrefixedListMemoriesTool);
|
|
1423
|
+
return [PrefixedRememberThisTool, PrefixedRecallTool, PrefixedForgetTool, PrefixedListMemoriesTool];
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1153
1426
|
// plugins/plugin-remember/src/remember.plugin.ts
|
|
1154
|
-
var RememberPlugin = class extends
|
|
1427
|
+
var RememberPlugin = class extends import_sdk11.DynamicPlugin {
|
|
1155
1428
|
options;
|
|
1156
1429
|
constructor(options = {}) {
|
|
1157
1430
|
super();
|
|
@@ -1166,6 +1439,11 @@ __publicField(RememberPlugin, "defaultOptions", {
|
|
|
1166
1439
|
keyPrefix: "remember:",
|
|
1167
1440
|
encryption: { enabled: true }
|
|
1168
1441
|
});
|
|
1442
|
+
/**
|
|
1443
|
+
* The memory tools, when `tools.enabled` is set: `remember_this`, `recall`, `forget` and
|
|
1444
|
+
* `list_memories`, under `tools.prefix`.
|
|
1445
|
+
*/
|
|
1446
|
+
__publicField(RememberPlugin, "dynamicTools", (options) => options.tools?.enabled ? createRememberTools(options.tools.prefix) : []);
|
|
1169
1447
|
/**
|
|
1170
1448
|
* Dynamic providers based on plugin options.
|
|
1171
1449
|
*/
|
|
@@ -1180,10 +1458,10 @@ __publicField(RememberPlugin, "dynamicProviders", (options) => {
|
|
|
1180
1458
|
providers.push({
|
|
1181
1459
|
name: "remember:store:global",
|
|
1182
1460
|
provide: RememberStoreToken,
|
|
1183
|
-
inject: () => [
|
|
1461
|
+
inject: () => [import_sdk11.FrontMcpConfig],
|
|
1184
1462
|
useFactory: (frontmcpConfig) => {
|
|
1185
|
-
const storeConfig = (0,
|
|
1186
|
-
if ((0,
|
|
1463
|
+
const storeConfig = (0, import_sdk11.getGlobalStoreConfig)("RememberPlugin", frontmcpConfig);
|
|
1464
|
+
if ((0, import_sdk11.isVercelKvProvider)(storeConfig)) {
|
|
1187
1465
|
return new RememberVercelKvProvider({
|
|
1188
1466
|
url: storeConfig.url,
|
|
1189
1467
|
token: storeConfig.token,
|
|
@@ -1264,14 +1542,14 @@ __publicField(RememberPlugin, "dynamicProviders", (options) => {
|
|
|
1264
1542
|
providers.push({
|
|
1265
1543
|
name: "remember:accessor",
|
|
1266
1544
|
provide: RememberAccessorToken,
|
|
1267
|
-
scope:
|
|
1268
|
-
inject: () => [RememberStoreToken,
|
|
1545
|
+
scope: import_sdk11.ProviderScope.CONTEXT,
|
|
1546
|
+
inject: () => [RememberStoreToken, import_sdk11.FRONTMCP_CONTEXT, RememberConfigToken, import_sdk11.FrontMcpLogger],
|
|
1269
1547
|
useFactory: (store, ctx, cfg, logger) => createRememberAccessor(store, ctx, cfg, logger)
|
|
1270
1548
|
});
|
|
1271
1549
|
return providers;
|
|
1272
1550
|
});
|
|
1273
1551
|
RememberPlugin = __decorateClass([
|
|
1274
|
-
(0,
|
|
1552
|
+
(0, import_sdk11.Plugin)({
|
|
1275
1553
|
name: "remember",
|
|
1276
1554
|
description: "Help your LLM remember things across sessions",
|
|
1277
1555
|
providers: [
|
|
@@ -1297,223 +1575,20 @@ RememberPlugin = __decorateClass([
|
|
|
1297
1575
|
], RememberPlugin);
|
|
1298
1576
|
|
|
1299
1577
|
// plugins/plugin-remember/src/remember.types.ts
|
|
1300
|
-
var
|
|
1301
|
-
var rememberScopeSchema =
|
|
1578
|
+
var import_lazy_zod6 = require("@frontmcp/lazy-zod");
|
|
1579
|
+
var rememberScopeSchema = import_lazy_zod6.z.enum(["session", "user", "tool", "global"]);
|
|
1302
1580
|
function brand(data, _brand) {
|
|
1303
1581
|
return data;
|
|
1304
1582
|
}
|
|
1305
|
-
var rememberEntrySchema =
|
|
1306
|
-
value:
|
|
1307
|
-
brand:
|
|
1308
|
-
createdAt:
|
|
1309
|
-
updatedAt:
|
|
1310
|
-
expiresAt:
|
|
1311
|
-
metadata:
|
|
1583
|
+
var rememberEntrySchema = import_lazy_zod6.z.object({
|
|
1584
|
+
value: import_lazy_zod6.z.unknown(),
|
|
1585
|
+
brand: import_lazy_zod6.z.enum(["approval", "preference", "cache", "state", "conversation", "custom"]).optional(),
|
|
1586
|
+
createdAt: import_lazy_zod6.z.number(),
|
|
1587
|
+
updatedAt: import_lazy_zod6.z.number(),
|
|
1588
|
+
expiresAt: import_lazy_zod6.z.number().optional(),
|
|
1589
|
+
metadata: import_lazy_zod6.z.record(import_lazy_zod6.z.string(), import_lazy_zod6.z.unknown()).optional()
|
|
1312
1590
|
});
|
|
1313
1591
|
|
|
1314
|
-
// plugins/plugin-remember/src/tools/remember-this.tool.ts
|
|
1315
|
-
var import_lazy_zod3 = require("@frontmcp/lazy-zod");
|
|
1316
|
-
var import_sdk7 = require("@frontmcp/sdk");
|
|
1317
|
-
|
|
1318
|
-
// plugins/plugin-remember/src/tools/remember-scope.description.ts
|
|
1319
|
-
var REMEMBER_SCOPE_DESCRIPTION = "Whose memory to use (default: session). session: this session; without one (stateless HTTP, MCP 2026-07-28), the signed-in caller across its requests. user: the signed-in caller, across all of its sessions. tool: the tool running the call, for the same caller as session; each memory tool has its own, so the other memory tools do not see what one of them stores in tool scope. global: shared by every caller. An anonymous caller cannot use user scope, nor session or tool scope without a session.";
|
|
1320
|
-
|
|
1321
|
-
// plugins/plugin-remember/src/tools/remember-this.tool.ts
|
|
1322
|
-
var rememberThisInputSchema = {
|
|
1323
|
-
key: import_lazy_zod3.z.string().min(1).describe('What to call this memory (e.g., "user_preference", "last_action")'),
|
|
1324
|
-
value: import_lazy_zod3.z.unknown().describe("The value to remember (any JSON-serializable data)"),
|
|
1325
|
-
scope: import_lazy_zod3.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),
|
|
1326
|
-
ttl: import_lazy_zod3.z.number().positive().optional().describe("Forget after this many seconds"),
|
|
1327
|
-
brand: import_lazy_zod3.z.enum(["preference", "cache", "state", "conversation", "custom"]).optional().describe("Type hint for the stored value")
|
|
1328
|
-
};
|
|
1329
|
-
var rememberThisOutputSchema = import_lazy_zod3.z.object({
|
|
1330
|
-
success: import_lazy_zod3.z.boolean(),
|
|
1331
|
-
key: import_lazy_zod3.z.string(),
|
|
1332
|
-
scope: import_lazy_zod3.z.string(),
|
|
1333
|
-
expiresAt: import_lazy_zod3.z.number().optional()
|
|
1334
|
-
});
|
|
1335
|
-
var RememberThisTool = class extends import_sdk7.ToolContext {
|
|
1336
|
-
async execute(input) {
|
|
1337
|
-
const remember = this.get(RememberAccessorToken);
|
|
1338
|
-
const config = this.get(RememberConfigToken);
|
|
1339
|
-
const scope = input.scope ?? "session";
|
|
1340
|
-
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1341
|
-
if (!allowedScopes.includes(scope)) {
|
|
1342
|
-
throw this.fail(new Error(`Scope '${scope}' is not allowed. Allowed scopes: ${allowedScopes.join(", ")}`));
|
|
1343
|
-
}
|
|
1344
|
-
await remember.set(input.key, input.value, {
|
|
1345
|
-
scope,
|
|
1346
|
-
ttl: input.ttl,
|
|
1347
|
-
brand: input.brand
|
|
1348
|
-
});
|
|
1349
|
-
const expiresAt = input.ttl ? Date.now() + input.ttl * 1e3 : void 0;
|
|
1350
|
-
return {
|
|
1351
|
-
success: true,
|
|
1352
|
-
key: input.key,
|
|
1353
|
-
scope,
|
|
1354
|
-
expiresAt
|
|
1355
|
-
};
|
|
1356
|
-
}
|
|
1357
|
-
};
|
|
1358
|
-
RememberThisTool = __decorateClass([
|
|
1359
|
-
(0, import_sdk7.Tool)({
|
|
1360
|
-
name: "remember_this",
|
|
1361
|
-
description: "Remember something for later: store a value under a key that recall can read back, in the scope you choose (this session by default; user scope for the signed-in user across sessions). It lasts until it is forgotten or its ttl runs out. Use this when the user asks you to remember preferences, settings, or any information they want to persist.",
|
|
1362
|
-
inputSchema: rememberThisInputSchema,
|
|
1363
|
-
outputSchema: rememberThisOutputSchema,
|
|
1364
|
-
annotations: {
|
|
1365
|
-
readOnlyHint: false
|
|
1366
|
-
}
|
|
1367
|
-
})
|
|
1368
|
-
], RememberThisTool);
|
|
1369
|
-
|
|
1370
|
-
// plugins/plugin-remember/src/tools/recall.tool.ts
|
|
1371
|
-
var import_lazy_zod4 = require("@frontmcp/lazy-zod");
|
|
1372
|
-
var import_sdk8 = require("@frontmcp/sdk");
|
|
1373
|
-
var recallInputSchema = {
|
|
1374
|
-
key: import_lazy_zod4.z.string().min(1).describe("What memory to recall"),
|
|
1375
|
-
scope: import_lazy_zod4.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)
|
|
1376
|
-
};
|
|
1377
|
-
var recallOutputSchema = import_lazy_zod4.z.object({
|
|
1378
|
-
found: import_lazy_zod4.z.boolean(),
|
|
1379
|
-
key: import_lazy_zod4.z.string(),
|
|
1380
|
-
value: import_lazy_zod4.z.unknown().optional(),
|
|
1381
|
-
scope: import_lazy_zod4.z.string(),
|
|
1382
|
-
createdAt: import_lazy_zod4.z.number().optional(),
|
|
1383
|
-
expiresAt: import_lazy_zod4.z.number().optional()
|
|
1384
|
-
});
|
|
1385
|
-
var RecallTool = class extends import_sdk8.ToolContext {
|
|
1386
|
-
async execute(input) {
|
|
1387
|
-
const remember = this.get(RememberAccessorToken);
|
|
1388
|
-
const config = this.get(RememberConfigToken);
|
|
1389
|
-
const scope = input.scope ?? "session";
|
|
1390
|
-
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1391
|
-
if (!allowedScopes.includes(scope)) {
|
|
1392
|
-
this.fail(new Error(`Scope '${scope}' is not allowed. Allowed scopes: ${allowedScopes.join(", ")}`));
|
|
1393
|
-
}
|
|
1394
|
-
const entry = await remember.getEntry(input.key, { scope });
|
|
1395
|
-
if (!entry) {
|
|
1396
|
-
return {
|
|
1397
|
-
found: false,
|
|
1398
|
-
key: input.key,
|
|
1399
|
-
scope
|
|
1400
|
-
};
|
|
1401
|
-
}
|
|
1402
|
-
return {
|
|
1403
|
-
found: true,
|
|
1404
|
-
key: input.key,
|
|
1405
|
-
value: entry.value,
|
|
1406
|
-
scope,
|
|
1407
|
-
createdAt: entry.createdAt,
|
|
1408
|
-
expiresAt: entry.expiresAt
|
|
1409
|
-
};
|
|
1410
|
-
}
|
|
1411
|
-
};
|
|
1412
|
-
RecallTool = __decorateClass([
|
|
1413
|
-
(0, import_sdk8.Tool)({
|
|
1414
|
-
name: "recall",
|
|
1415
|
-
description: "Recall something that was previously remembered. Use this to retrieve stored preferences, settings, or any information that was saved with remember_this.",
|
|
1416
|
-
inputSchema: recallInputSchema,
|
|
1417
|
-
outputSchema: recallOutputSchema,
|
|
1418
|
-
annotations: {
|
|
1419
|
-
readOnlyHint: true
|
|
1420
|
-
}
|
|
1421
|
-
})
|
|
1422
|
-
], RecallTool);
|
|
1423
|
-
|
|
1424
|
-
// plugins/plugin-remember/src/tools/forget.tool.ts
|
|
1425
|
-
var import_lazy_zod5 = require("@frontmcp/lazy-zod");
|
|
1426
|
-
var import_sdk9 = require("@frontmcp/sdk");
|
|
1427
|
-
var forgetInputSchema = {
|
|
1428
|
-
key: import_lazy_zod5.z.string().min(1).describe("What memory to forget"),
|
|
1429
|
-
scope: import_lazy_zod5.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION)
|
|
1430
|
-
};
|
|
1431
|
-
var forgetOutputSchema = import_lazy_zod5.z.object({
|
|
1432
|
-
success: import_lazy_zod5.z.boolean(),
|
|
1433
|
-
key: import_lazy_zod5.z.string(),
|
|
1434
|
-
scope: import_lazy_zod5.z.string(),
|
|
1435
|
-
existed: import_lazy_zod5.z.boolean()
|
|
1436
|
-
});
|
|
1437
|
-
var ForgetTool = class extends import_sdk9.ToolContext {
|
|
1438
|
-
async execute(input) {
|
|
1439
|
-
const remember = this.get(RememberAccessorToken);
|
|
1440
|
-
const config = this.get(RememberConfigToken);
|
|
1441
|
-
const scope = input.scope ?? "session";
|
|
1442
|
-
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1443
|
-
if (!allowedScopes.includes(scope)) {
|
|
1444
|
-
throw this.fail(new Error(`Scope '${scope}' is not allowed. Allowed scopes: ${allowedScopes.join(", ")}`));
|
|
1445
|
-
}
|
|
1446
|
-
const existed = await remember.knows(input.key, { scope });
|
|
1447
|
-
await remember.forget(input.key, { scope });
|
|
1448
|
-
return {
|
|
1449
|
-
success: true,
|
|
1450
|
-
key: input.key,
|
|
1451
|
-
scope,
|
|
1452
|
-
existed
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
};
|
|
1456
|
-
ForgetTool = __decorateClass([
|
|
1457
|
-
(0, import_sdk9.Tool)({
|
|
1458
|
-
name: "forget",
|
|
1459
|
-
description: "Forget a previously remembered value. Use this when the user wants to delete stored preferences or information.",
|
|
1460
|
-
inputSchema: forgetInputSchema,
|
|
1461
|
-
outputSchema: forgetOutputSchema,
|
|
1462
|
-
annotations: {
|
|
1463
|
-
readOnlyHint: false
|
|
1464
|
-
}
|
|
1465
|
-
})
|
|
1466
|
-
], ForgetTool);
|
|
1467
|
-
|
|
1468
|
-
// plugins/plugin-remember/src/tools/list-memories.tool.ts
|
|
1469
|
-
var import_lazy_zod6 = require("@frontmcp/lazy-zod");
|
|
1470
|
-
var import_sdk10 = require("@frontmcp/sdk");
|
|
1471
|
-
var listMemoriesInputSchema = {
|
|
1472
|
-
scope: import_lazy_zod6.z.enum(["session", "user", "tool", "global"]).optional().describe(REMEMBER_SCOPE_DESCRIPTION),
|
|
1473
|
-
pattern: import_lazy_zod6.z.string().optional().describe('Pattern to filter keys (e.g., "user_*")'),
|
|
1474
|
-
limit: import_lazy_zod6.z.number().positive().max(100).optional().describe("Maximum number of keys to return (default: 50)")
|
|
1475
|
-
};
|
|
1476
|
-
var listMemoriesOutputSchema = import_lazy_zod6.z.object({
|
|
1477
|
-
keys: import_lazy_zod6.z.array(import_lazy_zod6.z.string()),
|
|
1478
|
-
scope: import_lazy_zod6.z.string(),
|
|
1479
|
-
count: import_lazy_zod6.z.number(),
|
|
1480
|
-
truncated: import_lazy_zod6.z.boolean()
|
|
1481
|
-
});
|
|
1482
|
-
var ListMemoriesTool = class extends import_sdk10.ToolContext {
|
|
1483
|
-
async execute(input) {
|
|
1484
|
-
const remember = this.get(RememberAccessorToken);
|
|
1485
|
-
const config = this.get(RememberConfigToken);
|
|
1486
|
-
const scope = input.scope ?? "session";
|
|
1487
|
-
const allowedScopes = config.tools?.allowedScopes ?? ["session", "user", "tool", "global"];
|
|
1488
|
-
if (!allowedScopes.includes(scope)) {
|
|
1489
|
-
throw this.fail(new Error(`Scope '${scope}' is not allowed. Allowed scopes: ${allowedScopes.join(", ")}`));
|
|
1490
|
-
}
|
|
1491
|
-
const limit = input.limit ?? 50;
|
|
1492
|
-
let keys = await remember.list({ scope, pattern: input.pattern });
|
|
1493
|
-
const truncated = keys.length > limit;
|
|
1494
|
-
if (truncated) {
|
|
1495
|
-
keys = keys.slice(0, limit);
|
|
1496
|
-
}
|
|
1497
|
-
return {
|
|
1498
|
-
keys,
|
|
1499
|
-
scope,
|
|
1500
|
-
count: keys.length,
|
|
1501
|
-
truncated
|
|
1502
|
-
};
|
|
1503
|
-
}
|
|
1504
|
-
};
|
|
1505
|
-
ListMemoriesTool = __decorateClass([
|
|
1506
|
-
(0, import_sdk10.Tool)({
|
|
1507
|
-
name: "list_memories",
|
|
1508
|
-
description: "List the remembered keys in one scope (default: session). Use this to see what memories are stored before you recall or forget one.",
|
|
1509
|
-
inputSchema: listMemoriesInputSchema,
|
|
1510
|
-
outputSchema: listMemoriesOutputSchema,
|
|
1511
|
-
annotations: {
|
|
1512
|
-
readOnlyHint: true
|
|
1513
|
-
}
|
|
1514
|
-
})
|
|
1515
|
-
], ListMemoriesTool);
|
|
1516
|
-
|
|
1517
1592
|
// plugins/plugin-remember/src/remember.context-extension.ts
|
|
1518
1593
|
function getRemember(ctx) {
|
|
1519
1594
|
return ctx.get(RememberAccessorToken);
|
|
@@ -1536,6 +1611,7 @@ function tryGetRemember(ctx) {
|
|
|
1536
1611
|
RememberMemoryProvider,
|
|
1537
1612
|
RememberPlugin,
|
|
1538
1613
|
RememberRedisProvider,
|
|
1614
|
+
RememberScopeNotAllowedError,
|
|
1539
1615
|
RememberStoreToken,
|
|
1540
1616
|
RememberThisTool,
|
|
1541
1617
|
RememberVercelKvProvider,
|