@plur-ai/mcp 0.9.9 → 0.9.11

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
@@ -4,8 +4,8 @@
4
4
  import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from "fs";
5
5
  import { join } from "path";
6
6
  import { fileURLToPath } from "url";
7
- import { homedir } from "os";
8
- var VERSION = "0.9.9";
7
+ import { homedir, platform } from "os";
8
+ var VERSION = "0.9.11";
9
9
  var HELP = `plur-mcp v${VERSION} \u2014 persistent memory for AI agents
10
10
 
11
11
  Usage:
@@ -53,7 +53,9 @@ function extractManifestVersion(skillMdPath) {
53
53
  return null;
54
54
  }
55
55
  }
56
- var CLI = "npx @plur-ai/cli";
56
+ var _shimName = platform() === "win32" ? "plur-hook.cmd" : "plur-hook";
57
+ var _shimCandidate = join(homedir(), ".plur", "bin", _shimName);
58
+ var CLI = existsSync(_shimCandidate) ? _shimCandidate : "npx @plur-ai/cli";
57
59
  var PLUR_HOOKS = {
58
60
  // --- Session lifecycle ---
59
61
  UserPromptSubmit: [{
@@ -277,7 +279,7 @@ if (arg === "init") {
277
279
  process.exit(0);
278
280
  }
279
281
  if (arg === "serve" || arg === void 0) {
280
- const { runStdio } = await import("./server-X5ZMO46X.js");
282
+ const { runStdio } = await import("./server-FHZHOMM5.js");
281
283
  runStdio().catch((err) => {
282
284
  console.error("Failed to start PLUR MCP server:", err);
283
285
  process.exit(1);
@@ -14,10 +14,10 @@ import {
14
14
  import { Plur as Plur2, checkForUpdate } from "@plur-ai/core";
15
15
 
16
16
  // src/tools.ts
17
- import { extractMetaEngrams, validateMetaEngram, confidenceBand, generateProfile, getProfileForInjection, selectModelForOperation } from "@plur-ai/core";
17
+ import { extractMetaEngrams, validateMetaEngram, confidenceBand, generateProfile, getProfileForInjection, selectModelForOperation, getCachedUpdateCheck, minorVersionsBehind, scanForTensions, CapabilityCanary } from "@plur-ai/core";
18
18
 
19
19
  // src/version.ts
20
- var VERSION = "0.9.9";
20
+ var VERSION = "0.9.11";
21
21
 
22
22
  // src/tools.ts
23
23
  function makeHttpLlm(baseUrl, apiKey, model = "gpt-4o-mini") {
@@ -86,6 +86,17 @@ function sanitizeStatement(raw) {
86
86
  }
87
87
  return raw.slice(0, cut).trimEnd();
88
88
  }
89
+ var mcpCanary = new CapabilityCanary({ threshold: 10 });
90
+ mcpCanary.expect({
91
+ id: "session_start_hook",
92
+ description: "Automatic memory injection via hooks",
93
+ fix: "Run: npx @plur-ai/mcp init"
94
+ });
95
+ mcpCanary.expect({
96
+ id: "learn_activity",
97
+ description: "Learning from corrections",
98
+ fix: "Call plur_learn when corrected. If using hooks, verify they are installed."
99
+ });
89
100
  function getToolDefinitions() {
90
101
  return [
91
102
  {
@@ -129,23 +140,29 @@ function getToolDefinitions() {
129
140
  const statement = sanitizeStatement(args.statement);
130
141
  try {
131
142
  const engram = await plur.learnRouted(statement, context);
143
+ const isOutbox = !!engram.structured_data?._outbox;
144
+ mcpCanary.signal("learn_activity");
132
145
  return {
133
146
  id: engram.id,
134
147
  statement: engram.statement,
135
148
  scope: engram.scope,
136
149
  type: engram.type,
137
150
  pinned: engram.pinned === true,
138
- decision: "ADD"
151
+ decision: "ADD",
152
+ ...isOutbox ? { outbox: true, warning: "Remote write failed; engram queued locally for retry on next session start or plur_sync." } : {}
139
153
  };
140
154
  } catch (err) {
141
155
  const engram = plur.learn(statement, context);
156
+ const isOutbox = !!engram.structured_data?._outbox;
157
+ mcpCanary.signal("learn_activity");
142
158
  return {
143
159
  id: engram.id,
144
160
  statement: engram.statement,
145
161
  scope: engram.scope,
146
162
  type: engram.type,
147
163
  decision: "ADD",
148
- warning: `Remote write failed (${err.message}); fell back to local. The id above is the local placeholder \u2014 the canonical engram is NOT on the server.`
164
+ ...isOutbox ? { outbox: true } : {},
165
+ warning: `Remote write failed (${err.message}); engram queued for retry.`
149
166
  };
150
167
  }
151
168
  }
@@ -412,10 +429,13 @@ function getToolDefinitions() {
412
429
  handler: async (args, plur) => {
413
430
  if (args.id) {
414
431
  const engram = plur.getById(args.id);
415
- if (!engram) throw new Error(`Engram not found: ${args.id}`);
416
- if (engram.status === "retired") return { success: false, error: `Already retired: ${args.id}` };
432
+ if (engram) {
433
+ if (engram.status === "retired") return { success: false, error: `Already retired: ${args.id}` };
434
+ await plur.forget(args.id);
435
+ return { success: true, retired: { id: engram.id, statement: engram.statement } };
436
+ }
417
437
  await plur.forget(args.id);
418
- return { success: true, retired: { id: engram.id, statement: engram.statement } };
438
+ return { success: true, retired: { id: args.id } };
419
439
  }
420
440
  if (args.search) {
421
441
  const matches = plur.recall(args.search, { limit: 100 });
@@ -648,7 +668,21 @@ function getToolDefinitions() {
648
668
  },
649
669
  handler: async (args, plur) => {
650
670
  const result = plur.sync(args.remote);
651
- return result;
671
+ let outbox_result;
672
+ try {
673
+ outbox_result = await plur.flushOutbox();
674
+ } catch {
675
+ }
676
+ return {
677
+ ...result,
678
+ ...outbox_result && (outbox_result.flushed > 0 || outbox_result.failed > 0) ? {
679
+ outbox: {
680
+ flushed: outbox_result.flushed,
681
+ pending: outbox_result.failed,
682
+ warnings: outbox_result.expired_warnings
683
+ }
684
+ } : {}
685
+ };
652
686
  }
653
687
  },
654
688
  {
@@ -821,6 +855,7 @@ function getToolDefinitions() {
821
855
  },
822
856
  handler: async (_args, plur) => {
823
857
  const status = plur.status();
858
+ const versionCheck = getCachedUpdateCheck("@plur-ai/mcp");
824
859
  return {
825
860
  version: VERSION,
826
861
  engram_count: status.engram_count,
@@ -829,7 +864,17 @@ function getToolDefinitions() {
829
864
  storage_root: status.storage_root,
830
865
  locked_count: status.locked_count,
831
866
  tension_count: status.tension_count,
832
- versioned_engram_count: status.versioned_engram_count ?? 0
867
+ versioned_engram_count: status.versioned_engram_count ?? 0,
868
+ outbox_count: status.outbox_count ?? 0,
869
+ // Version check (issue #151)
870
+ ...versionCheck?.updateAvailable && versionCheck.latest ? {
871
+ update_available: {
872
+ current: versionCheck.current,
873
+ latest: versionCheck.latest,
874
+ behind: minorVersionsBehind(versionCheck.current, versionCheck.latest)
875
+ }
876
+ } : {},
877
+ capabilities: mcpCanary.status()
833
878
  };
834
879
  }
835
880
  },
@@ -898,6 +943,13 @@ function getToolDefinitions() {
898
943
  " \u2022 Or opt out: set PLUR_DISABLE_EMBEDDINGS=1, or write `embeddings: { enabled: false }` to ~/.plur/config.yaml \u2014 hybrid search will run BM25-only"
899
944
  );
900
945
  }
946
+ const canaryStatuses = mcpCanary.status();
947
+ for (const cs of canaryStatuses) {
948
+ if (!cs.healthy) {
949
+ checks.push({ check: `capability: ${cs.capability}`, ok: false, detail: cs.warning });
950
+ if (cs.warning) remediation.push(cs.warning);
951
+ }
952
+ }
901
953
  return {
902
954
  ok: checks.every((c) => c.ok),
903
955
  checks,
@@ -905,6 +957,7 @@ function getToolDefinitions() {
905
957
  before_probe: before,
906
958
  after_probe: after
907
959
  },
960
+ capabilities: canaryStatuses,
908
961
  remediation: remediation.length > 0 ? remediation : ["All checks passed \u2014 PLUR is healthy."]
909
962
  };
910
963
  }
@@ -922,10 +975,17 @@ function getToolDefinitions() {
922
975
  required: ["task"]
923
976
  },
924
977
  handler: async (args, plur) => {
978
+ mcpCanary.tick();
979
+ mcpCanary.signal("session_start_hook");
925
980
  const crypto = await import("crypto");
926
981
  const session_id = crypto.randomUUID();
927
982
  const task = args.task;
928
983
  const tags = args.tags;
984
+ let outbox_result;
985
+ try {
986
+ outbox_result = await plur.flushOutbox();
987
+ } catch {
988
+ }
929
989
  const status = plur.status();
930
990
  const store_stats = {
931
991
  engram_count: status.engram_count,
@@ -967,6 +1027,19 @@ function getToolDefinitions() {
967
1027
  You have ${store_stats.engram_count} engrams but none matched this task. Call plur_learn to capture new learnings from this session.`;
968
1028
  }
969
1029
  const isFreshInstall = store_stats.engram_count === 0 && store_stats.episode_count === 0;
1030
+ const versionCheck = getCachedUpdateCheck("@plur-ai/mcp");
1031
+ let version_warning;
1032
+ if (versionCheck?.updateAvailable && versionCheck.latest) {
1033
+ const behind = minorVersionsBehind(versionCheck.current, versionCheck.latest);
1034
+ if (behind > 2) {
1035
+ version_warning = `CRITICAL: Running PLUR v${versionCheck.current} \u2014 latest is v${versionCheck.latest} (${behind} minor versions behind). Known bugs may be present. Update immediately: npx @plur-ai/mcp@latest`;
1036
+ guide = `\u26A0\uFE0F ${version_warning}
1037
+
1038
+ ${guide}`;
1039
+ } else {
1040
+ version_warning = `Update available: PLUR v${versionCheck.current} \u2192 v${versionCheck.latest}. Run: npx @plur-ai/mcp@latest`;
1041
+ }
1042
+ }
970
1043
  return {
971
1044
  session_id,
972
1045
  engrams: engrams ?? [],
@@ -975,7 +1048,17 @@ You have ${store_stats.engram_count} engrams but none matched this task. Call pl
975
1048
  // Ask LLM to check back — MCP can't push, but we can request a follow-up
976
1049
  follow_up: store_stats.engram_count === 0 ? "This is a fresh store with 0 engrams. After your first exchange with the user, review what you learned and call plur_learn for any corrections, preferences, or patterns. Build the memory from this session." : void 0,
977
1050
  // On fresh install, suggest hook setup for reliable injection
978
- setup_hint: isFreshInstall ? "IMPORTANT: For reliable memory injection, ask the user to run: npx @plur-ai/cli init \u2014 this installs Claude Code hooks that automatically inject engrams at conversation start and after context compaction. Without hooks, memory injection depends on you remembering to call plur_session_start." : void 0
1051
+ setup_hint: isFreshInstall ? "IMPORTANT: For reliable memory injection, ask the user to run: npx @plur-ai/cli init \u2014 this installs Claude Code hooks that automatically inject engrams at conversation start and after context compaction. Without hooks, memory injection depends on you remembering to call plur_session_start." : void 0,
1052
+ // Outbox flush results (issue #26)
1053
+ ...outbox_result && (outbox_result.flushed > 0 || outbox_result.failed > 0) ? {
1054
+ outbox: {
1055
+ flushed: outbox_result.flushed,
1056
+ pending: outbox_result.failed,
1057
+ warnings: outbox_result.expired_warnings
1058
+ }
1059
+ } : {},
1060
+ // Version staleness warning (issue #151)
1061
+ ...version_warning ? { version_warning, version: VERSION } : {}
979
1062
  };
980
1063
  }
981
1064
  },
@@ -999,14 +1082,21 @@ Include at least one engram_suggestion if ANYTHING was learned. An empty suggest
999
1082
  engram_suggestions: {
1000
1083
  type: "array",
1001
1084
  items: {
1002
- type: "object",
1003
- properties: {
1004
- statement: { type: "string", description: "A concise, reusable assertion. Write it as advice to your future self." },
1005
- type: { type: "string", enum: ["behavioral", "terminological", "procedural", "architectural"] }
1006
- },
1007
- required: ["statement"]
1085
+ // Prefer {statement, type} objects. Bare strings are tolerated
1086
+ // and treated as {statement: <string>} (issue #231).
1087
+ anyOf: [
1088
+ { type: "string" },
1089
+ {
1090
+ type: "object",
1091
+ properties: {
1092
+ statement: { type: "string", description: "A concise, reusable assertion. Write it as advice to your future self." },
1093
+ type: { type: "string", enum: ["behavioral", "terminological", "procedural", "architectural"] }
1094
+ },
1095
+ required: ["statement"]
1096
+ }
1097
+ ]
1008
1098
  },
1009
- description: "Learnings from this session. Review the conversation for corrections, preferences, patterns, and technical facts before calling."
1099
+ description: 'Learnings from this session. Preferred shape is {statement: "...", type?: "..."}; bare strings are also accepted and treated as the statement. Review the conversation for corrections, preferences, patterns, and technical facts before calling.'
1010
1100
  }
1011
1101
  },
1012
1102
  required: ["summary", "engram_suggestions"]
@@ -1016,9 +1106,23 @@ Include at least one engram_suggestion if ANYTHING was learned. An empty suggest
1016
1106
  const session_id = args.session_id;
1017
1107
  const suggestions = args.engram_suggestions;
1018
1108
  let engrams_created = 0;
1019
- if (suggestions?.length) {
1020
- for (const s of suggestions) {
1021
- plur.learn(s.statement, { type: s.type });
1109
+ if (Array.isArray(suggestions) && suggestions.length) {
1110
+ for (let i = 0; i < suggestions.length; i++) {
1111
+ const s = suggestions[i];
1112
+ let statement;
1113
+ let type;
1114
+ if (typeof s === "string") {
1115
+ statement = s;
1116
+ } else if (s && typeof s === "object") {
1117
+ statement = s.statement;
1118
+ type = s.type;
1119
+ }
1120
+ if (typeof statement !== "string" || statement.length === 0) {
1121
+ throw new Error(
1122
+ `engram_suggestions[${i}] must be a string or {statement: string, type?: string}, got ${typeof s}`
1123
+ );
1124
+ }
1125
+ plur.learn(statement, { type });
1022
1126
  engrams_created++;
1023
1127
  }
1024
1128
  }
@@ -1077,8 +1181,13 @@ Include at least one engram_suggestion if ANYTHING was learned. An empty suggest
1077
1181
  annotations: { title: "List stores", readOnlyHint: true, idempotentHint: true },
1078
1182
  inputSchema: { type: "object", properties: {} },
1079
1183
  handler: async (_args, plur) => {
1080
- const stores = plur.listStores();
1081
- return { stores, count: stores.length };
1184
+ const stores = await plur.listStoresAsync();
1185
+ const outboxCount = plur.outboxCount();
1186
+ return {
1187
+ stores,
1188
+ count: stores.length,
1189
+ ...outboxCount > 0 ? { outbox_pending: outboxCount } : {}
1190
+ };
1082
1191
  }
1083
1192
  },
1084
1193
  {
@@ -1123,13 +1232,19 @@ Include at least one engram_suggestion if ANYTHING was learned. An empty suggest
1123
1232
  },
1124
1233
  {
1125
1234
  name: "plur_tensions",
1126
- description: "List engram pairs that have conflicting knowledge \u2014 shows tensions in your memory that may need resolution",
1235
+ description: "List or scan for engram pairs that have conflicting knowledge. Without scan mode, shows previously detected conflicts. With scan:true, runs an active LLM-powered contradiction scan and returns only high-confidence tensions.",
1127
1236
  annotations: { title: "Tensions", readOnlyHint: true, idempotentHint: true },
1128
1237
  inputSchema: {
1129
1238
  type: "object",
1130
1239
  properties: {
1131
1240
  scope: { type: "string", description: "Filter by scope" },
1132
- domain: { type: "string", description: "Filter by domain prefix" }
1241
+ domain: { type: "string", description: "Filter by domain prefix" },
1242
+ scan: { type: "boolean", description: "Run an active contradiction scan using an LLM judge. Requires OPENAI_API_KEY or OPENROUTER_API_KEY env var, or explicit llm_base_url + llm_api_key args." },
1243
+ llm_base_url: { type: "string", description: "OpenAI-compatible API base URL for scan mode (e.g. https://api.openai.com/v1)" },
1244
+ llm_api_key: { type: "string", description: "API key for the LLM (scan mode)" },
1245
+ llm_model: { type: "string", description: "Model name for scan mode (default: gpt-4o-mini)" },
1246
+ min_confidence: { type: "number", description: "Minimum confidence threshold for scan mode (0\u20131, default: 0.7)" },
1247
+ max_pairs: { type: "number", description: "Maximum candidate pairs to evaluate in scan mode (default: 50)" }
1133
1248
  }
1134
1249
  },
1135
1250
  handler: async (args, plur) => {
@@ -1137,6 +1252,30 @@ Include at least one engram_suggestion if ANYTHING was learned. An empty suggest
1137
1252
  scope: args.scope,
1138
1253
  domain: args.domain
1139
1254
  });
1255
+ if (args.scan) {
1256
+ const llm = args.llm_base_url && args.llm_api_key ? makeHttpLlm(args.llm_base_url, args.llm_api_key, args.llm_model) : getLlmFunction();
1257
+ if (!llm) {
1258
+ return {
1259
+ error: "scan mode requires an LLM. Set OPENAI_API_KEY or OPENROUTER_API_KEY, or pass llm_base_url + llm_api_key.",
1260
+ tensions: [],
1261
+ count: 0
1262
+ };
1263
+ }
1264
+ const result = await scanForTensions(engrams, llm, {
1265
+ min_confidence: args.min_confidence,
1266
+ max_pairs: args.max_pairs
1267
+ });
1268
+ return {
1269
+ pairs_checked: result.pairs_checked,
1270
+ count: result.new_tensions,
1271
+ tensions: result.tensions.map((t) => ({
1272
+ engram_a: { id: t.id_a, statement: t.statement_a },
1273
+ engram_b: { id: t.id_b, statement: t.statement_b },
1274
+ confidence: t.confidence,
1275
+ reason: t.reason
1276
+ }))
1277
+ };
1278
+ }
1140
1279
  const tensions = [];
1141
1280
  const seen = /* @__PURE__ */ new Set();
1142
1281
  for (const engram of engrams) {
@@ -1150,11 +1289,13 @@ Include at least one engram_suggestion if ANYTHING was learned. An empty suggest
1150
1289
  tensions.push({
1151
1290
  engram_a: { id: engram.id, statement: engram.statement, type: engram.type },
1152
1291
  engram_b: { id: other.id, statement: other.statement, type: other.type },
1153
- detected_at: engram.activation.last_accessed
1292
+ detected_at: engram.activation.last_accessed,
1293
+ purge_hint: "These conflicts are from the legacy detection system. Run plur_tensions_purge to clear them, then use scan:true for active contradiction detection."
1154
1294
  });
1155
1295
  }
1156
1296
  }
1157
- return { tensions, count: tensions.length };
1297
+ const purge_hint = tensions.length > 0 ? "These are legacy conflict relations. Run plur_tensions_purge to clear them." : void 0;
1298
+ return { tensions, count: tensions.length, ...purge_hint ? { purge_hint } : {} };
1158
1299
  }
1159
1300
  },
1160
1301
  {
@@ -1364,7 +1505,7 @@ Include at least one engram_suggestion if ANYTHING was learned. An empty suggest
1364
1505
  },
1365
1506
  {
1366
1507
  name: "plur_batch_decay",
1367
- description: "Apply ACT-R decay to all engrams. Run weekly. Returns status transitions only.",
1508
+ description: "Apply ACT-R decay to all local engrams. Run weekly. Only decays engrams in the local YAML store \u2014 remote-store engrams are not decayed client-side. Returns status transitions only.",
1368
1509
  annotations: { title: "Batch decay", destructiveHint: false, idempotentHint: false },
1369
1510
  inputSchema: {
1370
1511
  type: "object",
@@ -1521,6 +1662,31 @@ Use \`scope\` to namespace engrams per project:
1521
1662
 
1522
1663
  Override with \`PLUR_PATH\` environment variable.
1523
1664
  `;
1665
+ function jsonSchemaPropToZod(prop) {
1666
+ if (!prop || typeof prop !== "object") return z.unknown();
1667
+ const variants = prop.anyOf ?? prop.oneOf;
1668
+ if (Array.isArray(variants) && variants.length > 0) {
1669
+ const zodVariants = variants.map(jsonSchemaPropToZod);
1670
+ if (zodVariants.length === 1) return zodVariants[0];
1671
+ return z.union(zodVariants);
1672
+ }
1673
+ if (prop.type === "string") return prop.enum ? z.enum(prop.enum) : z.string();
1674
+ if (prop.type === "number" || prop.type === "integer") return z.number();
1675
+ if (prop.type === "boolean") return z.boolean();
1676
+ if (prop.type === "array") {
1677
+ const itemSchema = prop.items ? jsonSchemaPropToZod(prop.items) : z.unknown();
1678
+ return z.array(itemSchema);
1679
+ }
1680
+ if (prop.type === "object" && prop.properties) {
1681
+ const shape = {};
1682
+ for (const [k, p] of Object.entries(prop.properties)) {
1683
+ const field = jsonSchemaPropToZod(p);
1684
+ shape[k] = prop.required?.includes(k) ? field : field.optional();
1685
+ }
1686
+ return z.object(shape).passthrough();
1687
+ }
1688
+ return z.unknown();
1689
+ }
1524
1690
  async function createServer(plur) {
1525
1691
  const instance = plur ?? new Plur2();
1526
1692
  const tools = getToolDefinitions();
@@ -1553,7 +1719,7 @@ async function createServer(plur) {
1553
1719
  const tool = tools.find((t) => t.name === request.params.name);
1554
1720
  if (!tool) {
1555
1721
  return {
1556
- content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }],
1722
+ content: [{ type: "text", text: JSON.stringify({ error: `Unknown tool: ${request.params.name}`, success: false }) }],
1557
1723
  isError: true
1558
1724
  };
1559
1725
  }
@@ -1563,18 +1729,14 @@ async function createServer(plur) {
1563
1729
  if (schema?.properties) {
1564
1730
  const shape = {};
1565
1731
  for (const [key, prop] of Object.entries(schema.properties)) {
1566
- let field;
1567
- if (prop.type === "string") field = prop.enum ? z.enum(prop.enum) : z.string();
1568
- else if (prop.type === "number") field = z.number();
1569
- else if (prop.type === "boolean") field = z.boolean();
1570
- else if (prop.type === "array") field = z.array(z.unknown());
1571
- else field = z.unknown();
1732
+ const field = jsonSchemaPropToZod(prop);
1572
1733
  shape[key] = schema.required?.includes(key) ? field : field.optional();
1573
1734
  }
1574
1735
  const parsed = z.object(shape).passthrough().safeParse(args);
1575
1736
  if (!parsed.success) {
1737
+ const details = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ");
1576
1738
  return {
1577
- content: [{ type: "text", text: `Invalid arguments: ${parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ")}` }],
1739
+ content: [{ type: "text", text: JSON.stringify({ error: `Invalid arguments: ${details}`, success: false }) }],
1578
1740
  isError: true
1579
1741
  };
1580
1742
  }
@@ -1585,7 +1747,7 @@ async function createServer(plur) {
1585
1747
  const message = err?.message ?? String(err);
1586
1748
  server.sendLoggingMessage({ level: "error", data: `Tool ${request.params.name} failed: ${message}` });
1587
1749
  return {
1588
- content: [{ type: "text", text: `Error: ${message}` }],
1750
+ content: [{ type: "text", text: JSON.stringify({ error: message, success: false }) }],
1589
1751
  isError: true
1590
1752
  };
1591
1753
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plur-ai/mcp",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "plur-mcp": "dist/index.js"
@@ -13,7 +13,7 @@
13
13
  "dependencies": {
14
14
  "@modelcontextprotocol/sdk": "^1.12.0",
15
15
  "zod": "^3.23.0",
16
- "@plur-ai/core": "0.9.9"
16
+ "@plur-ai/core": "0.9.11"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/node": "^25.5.0"