@plur-ai/mcp 0.19.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@ function recordTelemetry(event) {
10
10
  }
11
11
 
12
12
  // src/version.ts
13
- var VERSION = "0.19.0";
13
+ var VERSION = "0.19.1";
14
14
 
15
15
  // src/tools.ts
16
16
  import { existsSync, unlinkSync } from "fs";
@@ -1889,12 +1889,12 @@ You have ${store_stats.engram_count} engrams but none matched this task. Call pl
1889
1889
  if (versionCheck?.updateAvailable && versionCheck.latest) {
1890
1890
  const behind = minorVersionsBehind(versionCheck.current, versionCheck.latest);
1891
1891
  if (behind > 2) {
1892
- 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`;
1892
+ 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: upgrade @plur-ai/cli and re-run plur init (configs pin versions; running @latest no longer updates them)`;
1893
1893
  guide = `\u26A0\uFE0F ${version_warning}
1894
1894
 
1895
1895
  ${guide}`;
1896
1896
  } else {
1897
- version_warning = `Update available: PLUR v${versionCheck.current} \u2192 v${versionCheck.latest}. Run: npx @plur-ai/mcp@latest`;
1897
+ version_warning = `Update available: PLUR v${versionCheck.current} \u2192 v${versionCheck.latest}. Run: npm i -g @plur-ai/cli@latest && plur init (configs pin versions)`;
1898
1898
  }
1899
1899
  }
1900
1900
  if (scope_source === "project-config") {
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSy
5
5
  import { join } from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import { homedir, platform } from "os";
8
- var VERSION = "0.19.0";
8
+ var VERSION = "0.19.1";
9
9
  var HELP = `plur-mcp v${VERSION} \u2014 persistent memory for AI agents
10
10
 
11
11
  Usage:
@@ -27,7 +27,7 @@ Docs: https://plur.ai \xB7 https://github.com/plur-ai/plur
27
27
  `;
28
28
  var MCP_SERVER_CONFIG = {
29
29
  command: "npx",
30
- args: ["-y", "@plur-ai/mcp@latest"]
30
+ args: ["-y", `@plur-ai/mcp@${VERSION}`]
31
31
  };
32
32
  function compareSemver(a, b) {
33
33
  const stripPrerelease = (v) => v.split("-")[0].split("+")[0];
@@ -143,16 +143,37 @@ function findMcpConfig() {
143
143
  if (existsSync(globalMcp)) return globalMcp;
144
144
  return projectMcp;
145
145
  }
146
- function writeMcpConfig(configPath) {
147
- let config = {};
148
- if (existsSync(configPath)) {
149
- try {
150
- config = JSON.parse(readFileSync(configPath, "utf8"));
151
- } catch {
146
+ function readJsonObjectForWrite(path) {
147
+ if (!existsSync(path)) return { data: {}, ok: true };
148
+ try {
149
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
150
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
151
+ return { data: parsed, ok: true };
152
152
  }
153
+ } catch {
153
154
  }
155
+ return { data: {}, ok: false };
156
+ }
157
+ function writeMcpConfig(configPath) {
158
+ const { data, ok } = readJsonObjectForWrite(configPath);
159
+ if (!ok) {
160
+ return `skipped \u2014 ${configPath} exists but is not a JSON object; writing would discard your other MCP servers. Fix it by hand, then re-run \`plur-mcp init\``;
161
+ }
162
+ const config = data;
154
163
  const servers = config.mcpServers ?? {};
155
- if (servers.plur) {
164
+ const existing = servers.plur;
165
+ if (existing) {
166
+ const args = existing.args ?? [];
167
+ const spec = args.filter((a) => a !== "-y" && !a.startsWith("-"))[0] ?? "";
168
+ if (existing.command === "npx" && /^@plur-ai\/mcp(@latest)?$/.test(spec)) {
169
+ const healed = { ...existing, ...MCP_SERVER_CONFIG };
170
+ if (JSON.stringify(healed) !== JSON.stringify(existing)) {
171
+ servers.plur = healed;
172
+ config.mcpServers = servers;
173
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
174
+ return `upgraded stale npx entry in ${configPath}`;
175
+ }
176
+ }
156
177
  return `already configured in ${configPath}`;
157
178
  }
158
179
  servers.plur = MCP_SERVER_CONFIG;
@@ -166,13 +187,11 @@ function installHooks() {
166
187
  const projectSettings = join(process.cwd(), ".claude", "settings.json");
167
188
  const globalSettings = join(homedir(), ".claude", "settings.json");
168
189
  const settingsPath = existsSync(join(process.cwd(), ".claude")) ? projectSettings : globalSettings;
169
- let settings = {};
170
- if (existsSync(settingsPath)) {
171
- try {
172
- settings = JSON.parse(readFileSync(settingsPath, "utf8"));
173
- } catch {
174
- }
190
+ const settingsRead = readJsonObjectForWrite(settingsPath);
191
+ if (!settingsRead.ok) {
192
+ return `skipped \u2014 ${settingsPath} exists but is not a JSON object; writing would discard your other settings. Fix it by hand, then re-run \`plur-mcp init\``;
175
193
  }
194
+ const settings = settingsRead.data;
176
195
  const hooks = settings.hooks ?? {};
177
196
  for (const entries of Object.values(hooks)) {
178
197
  for (const entry of entries) {
@@ -302,7 +321,7 @@ if (arg === "packs") {
302
321
  process.exit(0);
303
322
  }
304
323
  if (arg === "serve" || arg === void 0) {
305
- const { runStdio } = await import("./server-R6ILAGUI.js");
324
+ const { runStdio } = await import("./server-4JQ4LH5S.js");
306
325
  runStdio().catch((err) => {
307
326
  console.error("Failed to start PLUR MCP server:", err);
308
327
  process.exit(1);
@@ -7,7 +7,7 @@ import {
7
7
  resolveToolProfile,
8
8
  setActiveToolProfile,
9
9
  validateToolArgs
10
- } from "./chunk-M6Y4L55Z.js";
10
+ } from "./chunk-WKGNAQGB.js";
11
11
 
12
12
  // src/server.ts
13
13
  import { Server, ProtocolError, ProtocolErrorCode } from "@modelcontextprotocol/server";
@@ -192,7 +192,7 @@ async function createServer(plur, options) {
192
192
  const tools = getToolDefinitions(profile);
193
193
  const announceUpdate = (r) => {
194
194
  if (r.updateAvailable) {
195
- console.error(`[plur] Update available: ${r.current} \u2192 ${r.latest}. Run: npx @plur-ai/mcp@latest`);
195
+ console.error(`[plur] Update available: ${r.current} \u2192 ${r.latest}. Run: npm i -g @plur-ai/cli@latest && plur init (configs pin versions)`);
196
196
  }
197
197
  };
198
198
  checkForUpdate("@plur-ai/mcp", VERSION, announceUpdate);
@@ -412,6 +412,48 @@ Please:
412
412
  return server;
413
413
  }
414
414
  async function runStdio() {
415
+ const LOG_WINDOW_MS = 6e4;
416
+ const LOG_MAX_PER_WINDOW = 20;
417
+ let logWindowStart = 0;
418
+ let logCount = 0;
419
+ let suppressed = 0;
420
+ const logFault = (kind, err) => {
421
+ const now = Date.now();
422
+ if (now - logWindowStart > LOG_WINDOW_MS) {
423
+ if (suppressed > 0) {
424
+ process.stderr.write(`[plur:mcp] (${suppressed} further fault log lines suppressed in the last minute)
425
+ `);
426
+ }
427
+ logWindowStart = now;
428
+ logCount = 0;
429
+ suppressed = 0;
430
+ }
431
+ if (logCount >= LOG_MAX_PER_WINDOW) {
432
+ suppressed++;
433
+ return;
434
+ }
435
+ logCount++;
436
+ const detail = err instanceof Error ? err.stack ?? err.message : String(err);
437
+ process.stderr.write(`[plur:mcp] ${kind} (#1070): ${detail}
438
+ `);
439
+ };
440
+ process.on("unhandledRejection", (err) => logFault("unhandled rejection \u2014 server stays up", err));
441
+ process.on("uncaughtException", (err) => {
442
+ logFault("UNCAUGHT EXCEPTION \u2014 exiting so lock recovery and the harness can see the failure", err);
443
+ setTimeout(() => process.exit(1), 100);
444
+ });
445
+ const induceMs = Number(process.env.PLUR_TEST_INDUCE_UNHANDLED_REJECTION_MS ?? "");
446
+ if (Number.isFinite(induceMs) && induceMs > 0) {
447
+ setTimeout(() => {
448
+ void Promise.reject(new Error("induced test rejection (#1070)"));
449
+ }, induceMs);
450
+ }
451
+ const induceThrowMs = Number(process.env.PLUR_TEST_INDUCE_UNCAUGHT_EXCEPTION_MS ?? "");
452
+ if (Number.isFinite(induceThrowMs) && induceThrowMs > 0) {
453
+ setTimeout(() => {
454
+ throw new Error("induced test exception (#1070)");
455
+ }, induceThrowMs);
456
+ }
415
457
  const profile = resolveToolProfile();
416
458
  const server = await createServer(void 0, { profile });
417
459
  registerFlushOnExit({});
@@ -2,7 +2,7 @@ import {
2
2
  CURSOR_CORE_TOOL_NAMES,
3
3
  getToolDefinitions,
4
4
  validateToolArgs
5
- } from "./chunk-M6Y4L55Z.js";
5
+ } from "./chunk-WKGNAQGB.js";
6
6
 
7
7
  // src/tools-export.ts
8
8
  function getToolSchemas(profile) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@plur-ai/mcp",
3
3
  "mcpName": "io.github.plur-ai/plur",
4
- "version": "0.19.0",
4
+ "version": "0.19.1",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "plur-mcp": "dist/index.js"
@@ -16,7 +16,7 @@
16
16
  "@modelcontextprotocol/client": "2.0.0-beta.4",
17
17
  "@modelcontextprotocol/core": "2.0.0-beta.4",
18
18
  "zod": "^3.23.0",
19
- "@plur-ai/core": "0.19.0"
19
+ "@plur-ai/core": "0.19.1"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^25.5.0"