@plur-ai/mcp 0.4.1 → 0.5.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.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
var VERSION = "0.
|
|
4
|
+
var VERSION = "0.5.0";
|
|
5
5
|
var HELP = `plur-mcp v${VERSION} \u2014 persistent memory for AI agents
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
@@ -75,7 +75,7 @@ if (arg === "init") {
|
|
|
75
75
|
process.exit(0);
|
|
76
76
|
}
|
|
77
77
|
if (arg === "serve" || arg === void 0) {
|
|
78
|
-
const { runStdio } = await import("./server-
|
|
78
|
+
const { runStdio } = await import("./server-3QMSEZUP.js");
|
|
79
79
|
runStdio().catch((err) => {
|
|
80
80
|
console.error("Failed to start PLUR MCP server:", err);
|
|
81
81
|
process.exit(1);
|
|
@@ -36,6 +36,20 @@ function makeHttpLlm(baseUrl, apiKey, model = "gpt-4o-mini") {
|
|
|
36
36
|
return data.choices?.[0]?.message?.content ?? "";
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
+
var PLUR_GUIDE = `## PLUR Quick Start
|
|
40
|
+
|
|
41
|
+
Persistent memory for AI agents. Corrections, preferences, and conventions stored as engrams.
|
|
42
|
+
|
|
43
|
+
### Session Workflow
|
|
44
|
+
1. **plur_session_start** (you just called this) \u2014 get context
|
|
45
|
+
2. Work on your task
|
|
46
|
+
3. **plur_feedback** \u2014 rate which injected engrams helped
|
|
47
|
+
4. **plur_session_end** \u2014 capture summary + suggest new engrams
|
|
48
|
+
|
|
49
|
+
### Core Tools
|
|
50
|
+
- **plur_learn** \u2014 record patterns, preferences, insights
|
|
51
|
+
- **plur_recall_hybrid** \u2014 search engrams
|
|
52
|
+
- **plur_forget** \u2014 retire an outdated engram`;
|
|
39
53
|
function getToolDefinitions() {
|
|
40
54
|
return [
|
|
41
55
|
{
|
|
@@ -53,7 +67,33 @@ function getToolDefinitions() {
|
|
|
53
67
|
},
|
|
54
68
|
scope: { type: "string", description: "Namespace, e.g. global, project:myapp" },
|
|
55
69
|
domain: { type: "string", description: "Domain tag, e.g. software.deployment" },
|
|
56
|
-
source: { type: "string", description: "Origin of this knowledge" }
|
|
70
|
+
source: { type: "string", description: "Origin of this knowledge" },
|
|
71
|
+
tags: { type: "array", items: { type: "string" }, description: "Searchable keyword tags" },
|
|
72
|
+
rationale: { type: "string", description: "Why this knowledge matters" },
|
|
73
|
+
visibility: { type: "string", enum: ["private", "public", "template"], description: "Visibility level" },
|
|
74
|
+
knowledge_anchors: {
|
|
75
|
+
type: "array",
|
|
76
|
+
items: {
|
|
77
|
+
type: "object",
|
|
78
|
+
properties: {
|
|
79
|
+
path: { type: "string", description: "Path to related document" },
|
|
80
|
+
relevance: { type: "string", enum: ["primary", "supporting", "example"] },
|
|
81
|
+
snippet: { type: "string", description: "Short snippet (max 200 chars)" }
|
|
82
|
+
},
|
|
83
|
+
required: ["path"]
|
|
84
|
+
},
|
|
85
|
+
description: "Links to related knowledge documents"
|
|
86
|
+
},
|
|
87
|
+
dual_coding: {
|
|
88
|
+
type: "object",
|
|
89
|
+
properties: {
|
|
90
|
+
example: { type: "string", description: "Concrete example" },
|
|
91
|
+
analogy: { type: "string", description: "Analogy to aid understanding" }
|
|
92
|
+
},
|
|
93
|
+
description: "Dual coding for richer encoding"
|
|
94
|
+
},
|
|
95
|
+
abstract: { type: "string", description: "Abstract engram ID this was derived from" },
|
|
96
|
+
derived_from: { type: "string", description: "Source engram ID this was derived from" }
|
|
57
97
|
},
|
|
58
98
|
required: ["statement"]
|
|
59
99
|
},
|
|
@@ -62,7 +102,14 @@ function getToolDefinitions() {
|
|
|
62
102
|
type: args.type,
|
|
63
103
|
scope: args.scope,
|
|
64
104
|
domain: args.domain,
|
|
65
|
-
source: args.source
|
|
105
|
+
source: args.source,
|
|
106
|
+
tags: args.tags,
|
|
107
|
+
rationale: args.rationale,
|
|
108
|
+
visibility: args.visibility,
|
|
109
|
+
knowledge_anchors: args.knowledge_anchors,
|
|
110
|
+
dual_coding: args.dual_coding,
|
|
111
|
+
abstract: args.abstract,
|
|
112
|
+
derived_from: args.derived_from
|
|
66
113
|
});
|
|
67
114
|
return { id: engram.id, statement: engram.statement, scope: engram.scope, type: engram.type };
|
|
68
115
|
}
|
|
@@ -160,7 +207,8 @@ function getToolDefinitions() {
|
|
|
160
207
|
directives: result.directives,
|
|
161
208
|
consider: result.consider,
|
|
162
209
|
count: result.count,
|
|
163
|
-
tokens_used: result.tokens_used
|
|
210
|
+
tokens_used: result.tokens_used,
|
|
211
|
+
injected_ids: result.injected_ids
|
|
164
212
|
};
|
|
165
213
|
}
|
|
166
214
|
},
|
|
@@ -187,46 +235,91 @@ function getToolDefinitions() {
|
|
|
187
235
|
consider: result.consider,
|
|
188
236
|
count: result.count,
|
|
189
237
|
tokens_used: result.tokens_used,
|
|
238
|
+
injected_ids: result.injected_ids,
|
|
190
239
|
mode: "hybrid"
|
|
191
240
|
};
|
|
192
241
|
}
|
|
193
242
|
},
|
|
194
243
|
{
|
|
195
244
|
name: "plur_feedback",
|
|
196
|
-
description: "Rate an engram's usefulness \u2014 trains injection relevance over time",
|
|
245
|
+
description: "Rate an engram's usefulness \u2014 trains injection relevance over time. Supports single or batch mode.",
|
|
197
246
|
annotations: { title: "Feedback", destructiveHint: false, idempotentHint: true },
|
|
198
247
|
inputSchema: {
|
|
199
248
|
type: "object",
|
|
200
249
|
properties: {
|
|
201
|
-
id: { type: "string", description: "Engram ID (
|
|
250
|
+
id: { type: "string", description: "Engram ID (single mode)" },
|
|
202
251
|
signal: {
|
|
203
252
|
type: "string",
|
|
204
253
|
enum: ["positive", "negative", "neutral"],
|
|
205
|
-
description: "Feedback signal
|
|
254
|
+
description: "Feedback signal (single mode)"
|
|
255
|
+
},
|
|
256
|
+
signals: {
|
|
257
|
+
type: "array",
|
|
258
|
+
items: {
|
|
259
|
+
type: "object",
|
|
260
|
+
properties: {
|
|
261
|
+
id: { type: "string", description: "Engram ID" },
|
|
262
|
+
signal: { type: "string", enum: ["positive", "negative", "neutral"] }
|
|
263
|
+
},
|
|
264
|
+
required: ["id", "signal"]
|
|
265
|
+
},
|
|
266
|
+
description: "Batch feedback signals"
|
|
206
267
|
}
|
|
207
|
-
}
|
|
208
|
-
required: ["id", "signal"]
|
|
268
|
+
}
|
|
209
269
|
},
|
|
210
270
|
handler: async (args, plur) => {
|
|
271
|
+
if (args.signals && Array.isArray(args.signals)) {
|
|
272
|
+
const results = [];
|
|
273
|
+
const summary = { positive: 0, negative: 0, neutral: 0 };
|
|
274
|
+
for (const { id, signal } of args.signals) {
|
|
275
|
+
try {
|
|
276
|
+
plur.feedback(id, signal);
|
|
277
|
+
results.push({ id, signal, success: true });
|
|
278
|
+
summary[signal]++;
|
|
279
|
+
} catch (err) {
|
|
280
|
+
results.push({ id, signal, success: false, error: err.message });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return { mode: "batch", results, summary };
|
|
284
|
+
}
|
|
211
285
|
plur.feedback(args.id, args.signal);
|
|
212
286
|
return { success: true, id: args.id, signal: args.signal };
|
|
213
287
|
}
|
|
214
288
|
},
|
|
215
289
|
{
|
|
216
290
|
name: "plur_forget",
|
|
217
|
-
description: "Retire an engram \u2014 marks it as no longer active without deleting history",
|
|
291
|
+
description: "Retire an engram by ID or search term \u2014 marks it as no longer active without deleting history",
|
|
218
292
|
annotations: { title: "Forget", destructiveHint: true, idempotentHint: true },
|
|
219
293
|
inputSchema: {
|
|
220
294
|
type: "object",
|
|
221
295
|
properties: {
|
|
222
|
-
id: { type: "string", description: "
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
required: ["id"]
|
|
296
|
+
id: { type: "string", description: "Exact engram ID to retire" },
|
|
297
|
+
search: { type: "string", description: "Search term to find engram to retire" }
|
|
298
|
+
}
|
|
226
299
|
},
|
|
227
300
|
handler: async (args, plur) => {
|
|
228
|
-
|
|
229
|
-
|
|
301
|
+
if (args.id) {
|
|
302
|
+
const engram = plur.getById(args.id);
|
|
303
|
+
if (!engram) throw new Error(`Engram not found: ${args.id}`);
|
|
304
|
+
if (engram.status === "retired") return { success: false, error: `Already retired: ${args.id}` };
|
|
305
|
+
plur.forget(args.id);
|
|
306
|
+
return { success: true, retired: { id: engram.id, statement: engram.statement } };
|
|
307
|
+
}
|
|
308
|
+
if (args.search) {
|
|
309
|
+
const matches = plur.recall(args.search, { limit: 100 });
|
|
310
|
+
if (matches.length === 0) return { success: false, error: `No active engrams matching "${args.search}"` };
|
|
311
|
+
if (matches.length === 1) {
|
|
312
|
+
plur.forget(matches[0].id);
|
|
313
|
+
return { success: true, retired: { id: matches[0].id, statement: matches[0].statement } };
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
success: false,
|
|
317
|
+
matches: matches.slice(0, 20).map((e) => ({ id: e.id, statement: e.statement })),
|
|
318
|
+
total: matches.length,
|
|
319
|
+
error: `${matches.length} matches. Specify exact ID.`
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
throw new Error("Provide either id or search parameter");
|
|
230
323
|
}
|
|
231
324
|
},
|
|
232
325
|
{
|
|
@@ -561,22 +654,218 @@ function getToolDefinitions() {
|
|
|
561
654
|
storage_root: status.storage_root
|
|
562
655
|
};
|
|
563
656
|
}
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
name: "plur_session_start",
|
|
660
|
+
description: "Start a session \u2014 inject relevant engrams for your task. Call at the beginning of every session.",
|
|
661
|
+
annotations: { title: "Session Start", readOnlyHint: true, idempotentHint: false },
|
|
662
|
+
inputSchema: {
|
|
663
|
+
type: "object",
|
|
664
|
+
properties: {
|
|
665
|
+
task: { type: "string", description: "What you are working on (triggers engram injection)" },
|
|
666
|
+
tags: { type: "array", items: { type: "string" }, description: "Tags to filter injected engrams" }
|
|
667
|
+
},
|
|
668
|
+
required: ["task"]
|
|
669
|
+
},
|
|
670
|
+
handler: async (args, plur) => {
|
|
671
|
+
const crypto = await import("crypto");
|
|
672
|
+
const session_id = crypto.randomUUID();
|
|
673
|
+
const task = args.task;
|
|
674
|
+
const tags = args.tags;
|
|
675
|
+
let engrams = null;
|
|
676
|
+
try {
|
|
677
|
+
const result = await plur.injectHybrid(task, {
|
|
678
|
+
scope: tags?.length ? `tags:${tags.join(",")}` : void 0
|
|
679
|
+
});
|
|
680
|
+
if (result.count > 0) {
|
|
681
|
+
const lines = [];
|
|
682
|
+
if (result.directives) lines.push("## DIRECTIVES\n", result.directives);
|
|
683
|
+
if (result.constraints) lines.push("\n## CONSTRAINTS\n", result.constraints);
|
|
684
|
+
if (result.consider) lines.push("\n## ALSO CONSIDER\n", result.consider);
|
|
685
|
+
engrams = { text: lines.join("\n"), count: result.count, injected_ids: result.injected_ids };
|
|
686
|
+
}
|
|
687
|
+
} catch {
|
|
688
|
+
const result = plur.inject(task, {
|
|
689
|
+
scope: tags?.length ? `tags:${tags.join(",")}` : void 0
|
|
690
|
+
});
|
|
691
|
+
if (result.count > 0) {
|
|
692
|
+
const lines = [];
|
|
693
|
+
if (result.directives) lines.push("## DIRECTIVES\n", result.directives);
|
|
694
|
+
if (result.constraints) lines.push("\n## CONSTRAINTS\n", result.constraints);
|
|
695
|
+
if (result.consider) lines.push("\n## ALSO CONSIDER\n", result.consider);
|
|
696
|
+
engrams = { text: lines.join("\n"), count: result.count, injected_ids: result.injected_ids };
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
session_id,
|
|
701
|
+
engrams,
|
|
702
|
+
guide: engrams ? "Session started. Workflow: work \u2192 plur_feedback \u2192 plur_session_end." : PLUR_GUIDE
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
name: "plur_session_end",
|
|
708
|
+
description: "End a session \u2014 captures an episode and creates engrams from suggestions. Call before the conversation ends.",
|
|
709
|
+
annotations: { title: "Session End", destructiveHint: false, idempotentHint: false },
|
|
710
|
+
inputSchema: {
|
|
711
|
+
type: "object",
|
|
712
|
+
properties: {
|
|
713
|
+
summary: { type: "string", description: "What happened in this session" },
|
|
714
|
+
session_id: { type: "string", description: "Session ID from plur_session_start" },
|
|
715
|
+
engram_suggestions: {
|
|
716
|
+
type: "array",
|
|
717
|
+
items: {
|
|
718
|
+
type: "object",
|
|
719
|
+
properties: {
|
|
720
|
+
statement: { type: "string", description: "The knowledge assertion" },
|
|
721
|
+
type: { type: "string", enum: ["behavioral", "terminological", "procedural", "architectural"] }
|
|
722
|
+
},
|
|
723
|
+
required: ["statement"]
|
|
724
|
+
},
|
|
725
|
+
description: "New learnings to capture as engrams"
|
|
726
|
+
}
|
|
727
|
+
},
|
|
728
|
+
required: ["summary"]
|
|
729
|
+
},
|
|
730
|
+
handler: async (args, plur) => {
|
|
731
|
+
const summary = args.summary;
|
|
732
|
+
const session_id = args.session_id;
|
|
733
|
+
const suggestions = args.engram_suggestions;
|
|
734
|
+
let engrams_created = 0;
|
|
735
|
+
if (suggestions?.length) {
|
|
736
|
+
for (const s of suggestions) {
|
|
737
|
+
plur.learn(s.statement, { type: s.type });
|
|
738
|
+
engrams_created++;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
const episode = plur.capture(summary, {
|
|
742
|
+
session_id,
|
|
743
|
+
channel: "mcp"
|
|
744
|
+
});
|
|
745
|
+
return {
|
|
746
|
+
engrams_created,
|
|
747
|
+
episode_id: episode.id
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
name: "plur_stores_add",
|
|
753
|
+
description: "Register an additional engram store at a filesystem path with a scope identifier",
|
|
754
|
+
annotations: { title: "Add store", destructiveHint: false, idempotentHint: true },
|
|
755
|
+
inputSchema: {
|
|
756
|
+
type: "object",
|
|
757
|
+
properties: {
|
|
758
|
+
path: { type: "string", description: "Filesystem path to engrams.yaml" },
|
|
759
|
+
scope: { type: "string", description: "Scope identifier (e.g. space:1-datafund, module:trading)" },
|
|
760
|
+
shared: { type: "boolean", description: "Whether this store is git-committed / team-visible" },
|
|
761
|
+
readonly: { type: "boolean", description: "Whether this store is read-only (e.g. purchased packs)" }
|
|
762
|
+
},
|
|
763
|
+
required: ["path", "scope"]
|
|
764
|
+
},
|
|
765
|
+
handler: async (args, plur) => {
|
|
766
|
+
plur.addStore(args.path, args.scope, {
|
|
767
|
+
shared: args.shared,
|
|
768
|
+
readonly: args.readonly
|
|
769
|
+
});
|
|
770
|
+
return { success: true, path: args.path, scope: args.scope };
|
|
771
|
+
}
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
name: "plur_stores_list",
|
|
775
|
+
description: "List all configured engram stores with their scope, path, and engram count",
|
|
776
|
+
annotations: { title: "List stores", readOnlyHint: true, idempotentHint: true },
|
|
777
|
+
inputSchema: { type: "object", properties: {} },
|
|
778
|
+
handler: async (_args, plur) => {
|
|
779
|
+
const stores = plur.listStores();
|
|
780
|
+
return { stores, count: stores.length };
|
|
781
|
+
}
|
|
782
|
+
},
|
|
783
|
+
{
|
|
784
|
+
name: "plur_promote",
|
|
785
|
+
description: "Activate candidate engrams so they appear in injection results",
|
|
786
|
+
annotations: { title: "Promote", destructiveHint: false, idempotentHint: true },
|
|
787
|
+
inputSchema: {
|
|
788
|
+
type: "object",
|
|
789
|
+
properties: {
|
|
790
|
+
id: { type: "string", description: "Single engram ID to promote" },
|
|
791
|
+
ids: { type: "array", items: { type: "string" }, description: "Multiple engram IDs to promote" }
|
|
792
|
+
}
|
|
793
|
+
},
|
|
794
|
+
handler: async (args, plur) => {
|
|
795
|
+
const targetIds = args.ids ?? (args.id ? [args.id] : []);
|
|
796
|
+
if (targetIds.length === 0) throw new Error("Provide id or ids");
|
|
797
|
+
const promoted = [];
|
|
798
|
+
const errors = [];
|
|
799
|
+
for (const id of targetIds) {
|
|
800
|
+
const engram = plur.getById(id);
|
|
801
|
+
if (!engram) {
|
|
802
|
+
errors.push({ id, error: "Not found" });
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
if (engram.status === "active") {
|
|
806
|
+
errors.push({ id, error: "Already active" });
|
|
807
|
+
continue;
|
|
808
|
+
}
|
|
809
|
+
if (engram.status === "retired") {
|
|
810
|
+
errors.push({ id, error: "Cannot promote retired" });
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
813
|
+
engram.status = "active";
|
|
814
|
+
engram.activation.retrieval_strength = 0.7;
|
|
815
|
+
engram.activation.storage_strength = 1;
|
|
816
|
+
engram.activation.last_accessed = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
817
|
+
plur.updateEngram(engram);
|
|
818
|
+
promoted.push({ id, statement: engram.statement });
|
|
819
|
+
}
|
|
820
|
+
return { promoted, errors, success: errors.length === 0 };
|
|
821
|
+
}
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
name: "plur_packs_export",
|
|
825
|
+
description: "Export personal engrams as a shareable pack",
|
|
826
|
+
annotations: { title: "Export pack", destructiveHint: false, idempotentHint: false },
|
|
827
|
+
inputSchema: {
|
|
828
|
+
type: "object",
|
|
829
|
+
properties: {
|
|
830
|
+
name: { type: "string", description: "Pack name" },
|
|
831
|
+
description: { type: "string", description: "Pack description" },
|
|
832
|
+
filter_domain: { type: "string", description: "Filter engrams by domain prefix" },
|
|
833
|
+
filter_scope: { type: "string", description: "Filter engrams by scope" },
|
|
834
|
+
output_dir: { type: "string", description: "Output directory for the pack (default: ~/.plur/exports/)" }
|
|
835
|
+
},
|
|
836
|
+
required: ["name"]
|
|
837
|
+
},
|
|
838
|
+
handler: async (args, plur) => {
|
|
839
|
+
const name = args.name;
|
|
840
|
+
const engrams = plur.list({
|
|
841
|
+
domain: args.filter_domain,
|
|
842
|
+
scope: args.filter_scope
|
|
843
|
+
}).filter((e) => e.visibility !== "private" || !args.filter_domain);
|
|
844
|
+
const outputDir = args.output_dir || `${plur.status().storage_root}/exports`;
|
|
845
|
+
const result = plur.exportPack(engrams, outputDir, {
|
|
846
|
+
name,
|
|
847
|
+
version: "1.0.0",
|
|
848
|
+
description: args.description,
|
|
849
|
+
creator: "plur-mcp"
|
|
850
|
+
});
|
|
851
|
+
return { path: result.path, engram_count: result.engram_count, name };
|
|
852
|
+
}
|
|
564
853
|
}
|
|
565
854
|
];
|
|
566
855
|
}
|
|
567
856
|
|
|
568
857
|
// src/server.ts
|
|
569
858
|
import { z } from "zod";
|
|
570
|
-
var VERSION = "0.
|
|
859
|
+
var VERSION = "0.5.0";
|
|
571
860
|
var INSTRUCTIONS = `PLUR is your persistent memory. It stores corrections, preferences, and conventions as engrams that persist across sessions.
|
|
572
861
|
|
|
573
862
|
Use PLUR proactively:
|
|
574
|
-
- Call
|
|
575
|
-
- Call plur_learn when the user corrects you, states a preference
|
|
863
|
+
- Call plur_session_start at session start with a task description \u2014 loads relevant context
|
|
864
|
+
- Call plur_learn when the user corrects you, states a preference, or you discover a convention
|
|
576
865
|
- Call plur_feedback after using recalled engrams to train relevance
|
|
577
|
-
- Call
|
|
866
|
+
- Call plur_session_end before the conversation ends \u2014 captures learnings and session summary
|
|
578
867
|
|
|
579
|
-
|
|
868
|
+
Do not ask permission to use these tools \u2014 they are your memory system.`;
|
|
580
869
|
var GUIDE_RESOURCE = `# PLUR \u2014 Agent Guide
|
|
581
870
|
|
|
582
871
|
## What is PLUR?
|
|
@@ -585,32 +874,37 @@ Persistent memory for AI agents. Corrections, preferences, and conventions are s
|
|
|
585
874
|
|
|
586
875
|
## Quick Start
|
|
587
876
|
|
|
588
|
-
1. \`
|
|
589
|
-
2. \`
|
|
590
|
-
3. \`
|
|
591
|
-
4. \`
|
|
877
|
+
1. \`plur_session_start\` \u2014 start a session, inject relevant context
|
|
878
|
+
2. \`plur_learn\` \u2014 store a new learning
|
|
879
|
+
3. \`plur_feedback\` \u2014 rate injected engrams
|
|
880
|
+
4. \`plur_session_end\` \u2014 capture summary and new learnings
|
|
592
881
|
|
|
593
882
|
## When to Call Each Tool
|
|
594
883
|
|
|
595
884
|
| Trigger | Tool |
|
|
596
885
|
|---------|------|
|
|
597
|
-
| Session starts | \`
|
|
886
|
+
| Session starts | \`plur_session_start\` with task description |
|
|
598
887
|
| User corrects you | \`plur_learn\` with the correction |
|
|
599
888
|
| User states preference ("always X", "never Y") | \`plur_learn\` with scope and type |
|
|
600
889
|
| You used a recalled engram successfully | \`plur_feedback\` with "positive" |
|
|
601
890
|
| A recalled engram was wrong or irrelevant | \`plur_feedback\` with "negative" |
|
|
602
891
|
| User says "forget X" or a memory is outdated | \`plur_forget\` |
|
|
603
892
|
| You need to check what's stored | \`plur_status\` or \`plur_packs_list\` |
|
|
604
|
-
| End of session | \`
|
|
893
|
+
| End of session | \`plur_session_end\` with summary and suggestions |
|
|
605
894
|
|
|
606
895
|
## Tool Categories
|
|
607
896
|
|
|
897
|
+
### Session Management
|
|
898
|
+
- **plur_session_start** \u2014 start a session, inject relevant context
|
|
899
|
+
- **plur_session_end** \u2014 end a session, capture summary and new learnings
|
|
900
|
+
|
|
608
901
|
### Core Memory
|
|
609
902
|
- **plur_learn** \u2014 store a correction, preference, or convention
|
|
610
903
|
- **plur_recall** \u2014 BM25 keyword search
|
|
611
904
|
- **plur_recall_hybrid** \u2014 BM25 + embeddings (recommended default)
|
|
612
905
|
- **plur_feedback** \u2014 rate an engram (trains relevance)
|
|
613
906
|
- **plur_forget** \u2014 retire an outdated engram
|
|
907
|
+
- **plur_promote** \u2014 activate a candidate engram
|
|
614
908
|
|
|
615
909
|
### Context Injection
|
|
616
910
|
- **plur_inject** \u2014 select engrams for a task (BM25)
|
|
@@ -624,6 +918,11 @@ Persistent memory for AI agents. Corrections, preferences, and conventions are s
|
|
|
624
918
|
- **plur_ingest** \u2014 extract engrams from text content
|
|
625
919
|
- **plur_packs_install** \u2014 install curated engram packs
|
|
626
920
|
- **plur_packs_list** \u2014 list installed packs
|
|
921
|
+
- **plur_packs_export** \u2014 export engrams as a shareable pack
|
|
922
|
+
|
|
923
|
+
### Multi-Store
|
|
924
|
+
- **plur_stores_add** \u2014 register an additional engram store
|
|
925
|
+
- **plur_stores_list** \u2014 list all configured stores
|
|
627
926
|
|
|
628
927
|
### Sync & Status
|
|
629
928
|
- **plur_sync** \u2014 sync engrams across devices via git
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plur-ai/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"plur-mcp": "dist/index.js"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
14
14
|
"zod": "^3.23.0",
|
|
15
|
-
"@plur-ai/core": "0.
|
|
15
|
+
"@plur-ai/core": "0.5.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/node": "^25.5.0"
|