@plur-ai/mcp 0.3.1 → 0.4.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.3.1";
4
+ var VERSION = "0.4.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-ZY2JHPOE.js");
78
+ const { runStdio } = await import("./server-NPKYZFJ3.js");
79
79
  runStdio().catch((err) => {
80
80
  console.error("Failed to start PLUR MCP server:", err);
81
81
  process.exit(1);
@@ -11,9 +11,31 @@ import {
11
11
  ErrorCode,
12
12
  McpError
13
13
  } from "@modelcontextprotocol/sdk/types.js";
14
- import { Plur, checkForUpdate } from "@plur-ai/core";
14
+ import { Plur as Plur2, checkForUpdate } from "@plur-ai/core";
15
15
 
16
16
  // src/tools.ts
17
+ import { extractMetaEngrams, validateMetaEngram, confidenceBand } from "@plur-ai/core";
18
+ function makeHttpLlm(baseUrl, apiKey, model = "gpt-4o-mini") {
19
+ return async (prompt) => {
20
+ const response = await fetch(`${baseUrl.replace(/\/$/, "")}/chat/completions`, {
21
+ method: "POST",
22
+ headers: {
23
+ "Content-Type": "application/json",
24
+ "Authorization": `Bearer ${apiKey}`
25
+ },
26
+ body: JSON.stringify({
27
+ model,
28
+ messages: [{ role: "user", content: prompt }],
29
+ temperature: 0.1
30
+ })
31
+ });
32
+ if (!response.ok) {
33
+ throw new Error(`LLM API error: ${response.status} ${response.statusText}`);
34
+ }
35
+ const data = await response.json();
36
+ return data.choices?.[0]?.message?.content ?? "";
37
+ };
38
+ }
17
39
  function getToolDefinitions() {
18
40
  return [
19
41
  {
@@ -374,6 +396,154 @@ function getToolDefinitions() {
374
396
  return plur.syncStatus();
375
397
  }
376
398
  },
399
+ {
400
+ name: "plur_extract_meta",
401
+ description: "Extract meta-engrams from stored engrams using the 6-stage pipeline (structural analysis \u2192 clustering \u2192 alignment \u2192 formulation \u2192 hierarchy). Requires an LLM API endpoint.",
402
+ annotations: { title: "Extract meta-engrams", destructiveHint: false, idempotentHint: false },
403
+ inputSchema: {
404
+ type: "object",
405
+ properties: {
406
+ llm_base_url: { type: "string", description: "OpenAI-compatible API base URL (e.g. https://api.openai.com/v1)" },
407
+ llm_api_key: { type: "string", description: "API key for the LLM" },
408
+ llm_model: { type: "string", description: "Model name (default: gpt-4o-mini)" },
409
+ domain: { type: "string", description: "Filter source engrams by domain prefix" },
410
+ scope: { type: "string", description: "Filter source engrams by scope" },
411
+ run_validation: { type: "boolean", description: "Whether to run cross-domain validation (default: false)" },
412
+ dry_run: { type: "boolean", description: "If true, extract but do not persist meta-engrams (default: false)" }
413
+ },
414
+ required: ["llm_base_url", "llm_api_key"]
415
+ },
416
+ handler: async (args, plur) => {
417
+ const llm = makeHttpLlm(
418
+ args.llm_base_url,
419
+ args.llm_api_key,
420
+ args.llm_model
421
+ );
422
+ const sourceEngrams = plur.list({
423
+ domain: args.domain,
424
+ scope: args.scope
425
+ });
426
+ const existingMetas = plur.list().filter((e) => e.id.startsWith("META-"));
427
+ const result = await extractMetaEngrams(sourceEngrams, llm, {
428
+ run_validation: args.run_validation,
429
+ existing_metas: existingMetas
430
+ });
431
+ const isDryRun = args.dry_run === true;
432
+ let saveStats = null;
433
+ if (!isDryRun && result.results.length > 0) {
434
+ saveStats = plur.saveMetaEngrams(result.results);
435
+ }
436
+ return {
437
+ engrams_analyzed: result.engrams_analyzed,
438
+ clusters_found: result.clusters_found,
439
+ alignments_passed: result.alignments_passed,
440
+ meta_engrams_extracted: result.meta_engrams_extracted,
441
+ rejected_as_platitudes: result.rejected_as_platitudes,
442
+ duration_ms: result.duration_ms,
443
+ dry_run: isDryRun,
444
+ ...saveStats ? { saved: saveStats.saved, skipped: saveStats.skipped } : {},
445
+ results: result.results.map((m) => ({
446
+ id: m.id,
447
+ statement: m.statement,
448
+ domain: m.domain,
449
+ confidence: m.structured_data?.meta?.confidence?.composite ?? 0,
450
+ confidence_band: confidenceBand(m.structured_data?.meta?.confidence?.composite ?? 0),
451
+ hierarchy_level: m.structured_data?.meta?.hierarchy?.level ?? "mop"
452
+ }))
453
+ };
454
+ }
455
+ },
456
+ {
457
+ name: "plur_meta_engrams",
458
+ description: "List existing meta-engrams (engrams with META- prefix) with their structural templates and confidence scores",
459
+ annotations: { title: "List meta-engrams", readOnlyHint: true, idempotentHint: true },
460
+ inputSchema: {
461
+ type: "object",
462
+ properties: {
463
+ domain: { type: "string", description: "Filter by domain prefix (e.g. meta, meta.trading)" },
464
+ min_confidence: { type: "number", description: "Minimum composite confidence score (0-1)" },
465
+ hierarchy_level: { type: "string", enum: ["mop", "top"], description: "Filter by hierarchy level" },
466
+ limit: { type: "number", description: "Max results to return (default 20)" }
467
+ }
468
+ },
469
+ handler: async (args, plur) => {
470
+ const allEngrams = plur.list();
471
+ const metaEngrams = allEngrams.filter((e) => e.id.startsWith("META-"));
472
+ const minConfidence = args.min_confidence ?? 0;
473
+ const levelFilter = args.hierarchy_level;
474
+ const domainFilter = args.domain;
475
+ const limit = args.limit ?? 20;
476
+ const filtered = metaEngrams.filter((m) => {
477
+ const mf = m.structured_data?.meta;
478
+ if (!mf) return false;
479
+ if (mf.confidence?.composite < minConfidence) return false;
480
+ if (levelFilter && mf.hierarchy?.level !== levelFilter) return false;
481
+ if (domainFilter && !m.domain?.startsWith(domainFilter)) return false;
482
+ return true;
483
+ }).slice(0, limit);
484
+ return {
485
+ results: filtered.map((m) => {
486
+ const mf = m.structured_data?.meta;
487
+ return {
488
+ id: m.id,
489
+ statement: m.statement,
490
+ domain: m.domain,
491
+ template: mf?.structure?.template,
492
+ hierarchy_level: mf?.hierarchy?.level,
493
+ confidence: mf?.confidence?.composite,
494
+ confidence_band: confidenceBand(mf?.confidence?.composite ?? 0),
495
+ evidence_count: mf?.confidence?.evidence_count,
496
+ domain_count: mf?.confidence?.domain_count,
497
+ validated_domains: mf?.domain_coverage?.validated
498
+ };
499
+ }),
500
+ count: filtered.length,
501
+ total_meta_engrams: metaEngrams.length
502
+ };
503
+ }
504
+ },
505
+ {
506
+ name: "plur_validate_meta",
507
+ description: "Test a meta-engram template against engrams from a new domain \u2014 updates confidence and domain_coverage",
508
+ annotations: { title: "Validate meta-engram", destructiveHint: false, idempotentHint: false },
509
+ inputSchema: {
510
+ type: "object",
511
+ properties: {
512
+ meta_engram_id: { type: "string", description: "META- engram ID to validate" },
513
+ test_domain: { type: "string", description: "Domain to test against (e.g. medicine)" },
514
+ llm_base_url: { type: "string", description: "OpenAI-compatible API base URL" },
515
+ llm_api_key: { type: "string", description: "API key for the LLM" },
516
+ llm_model: { type: "string", description: "Model name (default: gpt-4o-mini)" }
517
+ },
518
+ required: ["meta_engram_id", "test_domain", "llm_base_url", "llm_api_key"]
519
+ },
520
+ handler: async (args, plur) => {
521
+ const allEngrams = plur.list();
522
+ const meta = allEngrams.find((e) => e.id === args.meta_engram_id);
523
+ if (!meta) {
524
+ throw new Error(`Meta-engram not found: ${args.meta_engram_id}`);
525
+ }
526
+ const testDomain = args.test_domain;
527
+ const testEngrams = plur.list({ domain: testDomain });
528
+ const llm = makeHttpLlm(
529
+ args.llm_base_url,
530
+ args.llm_api_key,
531
+ args.llm_model
532
+ );
533
+ const result = await validateMetaEngram(meta, testEngrams, testDomain, llm);
534
+ plur.updateEngram(meta);
535
+ return {
536
+ meta_engram_id: result.meta_engram_id,
537
+ test_domain: result.test_domain,
538
+ prediction_held: result.prediction_held,
539
+ matching_engram_id: result.matching_engram_id,
540
+ alignment_score: result.alignment_score,
541
+ rationale: result.rationale,
542
+ updated_confidence: meta.structured_data?.meta?.confidence?.composite,
543
+ updated_confidence_band: confidenceBand(meta.structured_data?.meta?.confidence?.composite ?? 0)
544
+ };
545
+ }
546
+ },
377
547
  {
378
548
  name: "plur_status",
379
549
  description: "Return system health \u2014 engram count, episode count, pack count, storage root",
@@ -397,7 +567,7 @@ function getToolDefinitions() {
397
567
 
398
568
  // src/server.ts
399
569
  import { z } from "zod";
400
- var VERSION = "0.3.1";
570
+ var VERSION = "0.4.0";
401
571
  var INSTRUCTIONS = `PLUR is your persistent memory. It stores corrections, preferences, and conventions as engrams that persist across sessions.
402
572
 
403
573
  Use PLUR proactively:
@@ -479,7 +649,7 @@ Use \`scope\` to namespace engrams per project:
479
649
  Override with \`PLUR_PATH\` environment variable.
480
650
  `;
481
651
  async function createServer(plur) {
482
- const instance = plur ?? new Plur();
652
+ const instance = plur ?? new Plur2();
483
653
  const tools = getToolDefinitions();
484
654
  checkForUpdate("@plur-ai/mcp", VERSION, (r) => {
485
655
  if (r.updateAvailable) {
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@plur-ai/mcp",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "bin": {
6
- "plur-mcp": "dist/index.js",
7
- "plur": "dist/index.js"
6
+ "plur-mcp": "dist/index.js"
8
7
  },
9
8
  "main": "dist/index.js",
10
9
  "files": [
@@ -13,7 +12,7 @@
13
12
  "dependencies": {
14
13
  "@modelcontextprotocol/sdk": "^1.12.0",
15
14
  "zod": "^3.23.0",
16
- "@plur-ai/core": "0.3.1"
15
+ "@plur-ai/core": "0.4.0"
17
16
  },
18
17
  "devDependencies": {
19
18
  "@types/node": "^25.5.0"