mindgraph-mcp 0.23.0 → 0.24.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
@@ -22,30 +22,85 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  mod
23
23
  ));
24
24
 
25
+ // src/call-ledger.ts
26
+ var import_node_crypto = __toESM(require("crypto"));
27
+ var import_node_fs = __toESM(require("fs"));
28
+ var import_node_os = __toESM(require("os"));
29
+ var import_node_path = __toESM(require("path"));
30
+ var TTL_MS = 10 * 6e4;
31
+ function callsDir(options) {
32
+ return import_node_path.default.join(
33
+ options.runtimeDir || process.env.MINDGRAPH_RUNTIME_DIR || import_node_path.default.join(import_node_os.default.homedir(), ".mindgraph", "runtime"),
34
+ "calls"
35
+ );
36
+ }
37
+ function stableJson(value) {
38
+ if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
39
+ if (value && typeof value === "object") {
40
+ return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
41
+ }
42
+ return JSON.stringify(value) ?? "null";
43
+ }
44
+ function bareToolName(name) {
45
+ const cut = name.lastIndexOf("__");
46
+ return cut === -1 ? name : name.slice(cut + 2);
47
+ }
48
+ function callKey(toolName, toolInput) {
49
+ return import_node_crypto.default.createHash("sha256").update(`${bareToolName(toolName)}\0${stableJson(toolInput)}`).digest("hex");
50
+ }
51
+ function resolvePendingCall(toolName, toolInput, options = {}) {
52
+ const now = (options.now ?? Date.now)();
53
+ const dir = callsDir(options);
54
+ const prefix = `${callKey(toolName, toolInput)}.`;
55
+ let names;
56
+ try {
57
+ names = import_node_fs.default.readdirSync(dir).filter((name) => name.startsWith(prefix) && name.endsWith(".json"));
58
+ } catch {
59
+ return void 0;
60
+ }
61
+ let matches = [];
62
+ for (const name of names) {
63
+ try {
64
+ const record = JSON.parse(
65
+ import_node_fs.default.readFileSync(import_node_path.default.join(dir, name), "utf8")
66
+ );
67
+ if (typeof record.createdAt === "number" && now - record.createdAt <= TTL_MS && record.fills && typeof record.fills === "object") {
68
+ matches.push(record);
69
+ }
70
+ } catch {
71
+ }
72
+ }
73
+ if (matches.length > 1) {
74
+ const projectDir = options.projectDir ?? process.env.CLAUDE_PROJECT_DIR;
75
+ matches = projectDir ? matches.filter((record) => record.projectDir === projectDir) : [];
76
+ }
77
+ return matches.length === 1 ? matches[0].fills : void 0;
78
+ }
79
+
25
80
  // src/index.ts
26
81
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
27
82
  var import_mindgraph3 = require("mindgraph");
28
83
 
29
84
  // src/hook-env.ts
30
- var import_node_crypto = __toESM(require("crypto"));
31
- var import_node_fs = __toESM(require("fs"));
32
- var import_node_os = __toESM(require("os"));
33
- var import_node_path = __toESM(require("path"));
85
+ var import_node_crypto2 = __toESM(require("crypto"));
86
+ var import_node_fs2 = __toESM(require("fs"));
87
+ var import_node_os2 = __toESM(require("os"));
88
+ var import_node_path2 = __toESM(require("path"));
34
89
  function stableAgentId() {
35
90
  let user = "user";
36
91
  try {
37
- user = import_node_os.default.userInfo().username || "user";
92
+ user = import_node_os2.default.userInfo().username || "user";
38
93
  } catch {
39
94
  }
40
- const digest = import_node_crypto.default.createHash("sha256").update(`${user}@${import_node_os.default.hostname()}`).digest("hex").slice(0, 12);
95
+ const digest = import_node_crypto2.default.createHash("sha256").update(`${user}@${import_node_os2.default.hostname()}`).digest("hex").slice(0, 12);
41
96
  return `u-${digest}`;
42
97
  }
43
98
  function hookEnvPath(dir) {
44
- return import_node_path.default.join(dir || import_node_path.default.join(import_node_os.default.homedir(), ".mindgraph"), "hooks.json");
99
+ return import_node_path2.default.join(dir || import_node_path2.default.join(import_node_os2.default.homedir(), ".mindgraph"), "hooks.json");
45
100
  }
46
101
  function loadHookEnv(dir) {
47
102
  try {
48
- const raw = import_node_fs.default.readFileSync(hookEnvPath(dir), "utf8");
103
+ const raw = import_node_fs2.default.readFileSync(hookEnvPath(dir), "utf8");
49
104
  const parsed = JSON.parse(raw);
50
105
  return {
51
106
  baseUrl: typeof parsed.baseUrl === "string" ? parsed.baseUrl : void 0,
@@ -357,6 +412,14 @@ function hiddenSections(payload) {
357
412
  function renderContext(response, maxChars) {
358
413
  const payload = obj(response);
359
414
  if (!payload) return void 0;
415
+ if (typeof payload.context_text === "string" && payload.context_text.length > 0) {
416
+ const text2 = payload.context_text;
417
+ if (maxChars !== void 0 && text2.length > maxChars) {
418
+ return `${text2.slice(0, maxChars)}
419
+ [truncated to ${maxChars} characters]`;
420
+ }
421
+ return text2;
422
+ }
360
423
  const graph = obj(payload.graph);
361
424
  const rawNodes = Array.isArray(graph?.nodes) ? graph.nodes : [];
362
425
  const shaped = rawNodes.filter(isNodeShaped);
@@ -579,15 +642,15 @@ function renderTraversal(response, maxChars) {
579
642
  const labelByUid = /* @__PURE__ */ new Map();
580
643
  for (const node of nodes) labelByUid.set(str(node.uid), str(node.label) || "?");
581
644
  if (paths.length > 0) {
582
- const items = paths.map((raw) => obj(raw)).filter((path5) => Boolean(path5)).map((path5, index) => {
583
- const uids = Array.isArray(path5.node_uids) ? path5.node_uids.map(String) : [];
584
- const labels = Array.isArray(path5.labels) ? path5.labels.map(String) : Array.isArray(path5.nodes) ? path5.nodes.map((hop) => {
645
+ const items = paths.map((raw) => obj(raw)).filter((path6) => Boolean(path6)).map((path6, index) => {
646
+ const uids = Array.isArray(path6.node_uids) ? path6.node_uids.map(String) : [];
647
+ const labels = Array.isArray(path6.labels) ? path6.labels.map(String) : Array.isArray(path6.nodes) ? path6.nodes.map((hop) => {
585
648
  const hopNode = obj(hop);
586
649
  return str(hopNode?.label) || labelByUid.get(str(hopNode?.uid) || "") || str(hop) || "?";
587
650
  }) : [];
588
651
  const route = labels.length > 0 ? labels.join(" \u2192 ") : uids.join(" \u2192 ") || "(path)";
589
- const cost = num(path5.cost) ?? num(path5.path_cost);
590
- const confidence = num(path5.path_confidence);
652
+ const cost = num(path6.cost) ?? num(path6.path_cost);
653
+ const confidence = num(path6.path_confidence);
591
654
  const meta = [
592
655
  cost !== void 0 ? `cost ${cost}` : void 0,
593
656
  confidence !== void 0 ? `confidence ${confidence}` : void 0
@@ -1589,7 +1652,7 @@ ${conversation}`
1589
1652
  }
1590
1653
 
1591
1654
  // src/memory-tool.ts
1592
- var import_node_crypto2 = require("crypto");
1655
+ var import_node_crypto3 = require("crypto");
1593
1656
  var RESULT_SCHEMA_VERSION = "mindgraph.memory.result.v1";
1594
1657
  var DEFAULT_OUTPUT_CHARS = 8e3;
1595
1658
  var MIN_OUTPUT_CHARS = 512;
@@ -1737,15 +1800,15 @@ function obj2(value) {
1737
1800
  function text(value) {
1738
1801
  return typeof value === "string" && value.length > 0 ? value : void 0;
1739
1802
  }
1740
- function stableJson(value) {
1741
- if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
1803
+ function stableJson2(value) {
1804
+ if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
1742
1805
  if (value && typeof value === "object") {
1743
- return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
1806
+ return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson2(item)}`).join(",")}}`;
1744
1807
  }
1745
1808
  return JSON.stringify(value);
1746
1809
  }
1747
1810
  function sha256(value) {
1748
- return (0, import_node_crypto2.createHash)("sha256").update(value).digest("hex");
1811
+ return (0, import_node_crypto3.createHash)("sha256").update(value).digest("hex");
1749
1812
  }
1750
1813
  function outputBudget(value) {
1751
1814
  if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_OUTPUT_CHARS;
@@ -2051,7 +2114,7 @@ async function handleMemoryTool(client2, args, config = {}) {
2051
2114
  scope_uids: Array.isArray(args.scope_uids) ? args.scope_uids.map(String) : void 0
2052
2115
  });
2053
2116
  const contextId = `ctx_${sha256(
2054
- stableJson({ mode, scope, strategy, query: text(args.query), rendered_hash: renderedHash })
2117
+ stableJson2({ mode, scope, strategy, query: text(args.query), rendered_hash: renderedHash })
2055
2118
  ).slice(0, 24)}`;
2056
2119
  const bounded = candidates.length > items.length || rendered2.includes("item(s) omitted");
2057
2120
  const result = {
@@ -2212,15 +2275,15 @@ async function readGovernedResource(client2, uri, governanceConfig, memoryConfig
2212
2275
  }
2213
2276
 
2214
2277
  // src/tools.ts
2215
- var import_node_crypto5 = require("crypto");
2278
+ var import_node_crypto6 = require("crypto");
2216
2279
 
2217
2280
  // src/codegraph.ts
2218
2281
  var import_node_child_process = require("child_process");
2219
- var import_node_fs2 = require("fs");
2282
+ var import_node_fs3 = require("fs");
2220
2283
  var import_promises = require("fs/promises");
2221
- var import_node_os2 = require("os");
2222
- var import_node_path2 = require("path");
2223
- var import_node_crypto3 = require("crypto");
2284
+ var import_node_os3 = require("os");
2285
+ var import_node_path3 = require("path");
2286
+ var import_node_crypto4 = require("crypto");
2224
2287
  var UnknownRepositoryError = class extends Error {
2225
2288
  constructor(repo) {
2226
2289
  super(
@@ -2251,14 +2314,14 @@ function unavailabilityCaveats(reason, message) {
2251
2314
  var DEFAULT_TIMEOUT_MS = 5e3;
2252
2315
  var DEFAULT_STATUS_TTL_MS = 6e4;
2253
2316
  var MAX_OUTPUT_BYTES = 5 * 1024 * 1024;
2254
- function normalizePath(path5) {
2255
- return path5.replaceAll("\\", "/").replace(/^\.\//, "");
2317
+ function normalizePath(path6) {
2318
+ return path6.replaceAll("\\", "/").replace(/^\.\//, "");
2256
2319
  }
2257
2320
  function normalizeSignature(signature) {
2258
2321
  return signature.replace(/\s+/g, " ").trim();
2259
2322
  }
2260
- function languageFromPath(path5) {
2261
- const extension = (0, import_node_path2.extname)(path5).toLowerCase();
2323
+ function languageFromPath(path6) {
2324
+ const extension = (0, import_node_path3.extname)(path6).toLowerCase();
2262
2325
  return {
2263
2326
  ".c": "c",
2264
2327
  ".cc": "cpp",
@@ -2307,30 +2370,30 @@ function normalizeRemote(remote) {
2307
2370
  }
2308
2371
  }
2309
2372
  function pathContains(root, candidate) {
2310
- const child = (0, import_node_path2.relative)(root, candidate);
2311
- return child === "" || child !== ".." && !child.startsWith(`..${import_node_path2.sep}`) && !(0, import_node_path2.isAbsolute)(child);
2373
+ const child = (0, import_node_path3.relative)(root, candidate);
2374
+ return child === "" || child !== ".." && !child.startsWith(`..${import_node_path3.sep}`) && !(0, import_node_path3.isAbsolute)(child);
2312
2375
  }
2313
2376
  function nearestExistingDirectory(candidate) {
2314
- let current = (0, import_node_path2.resolve)(candidate);
2377
+ let current = (0, import_node_path3.resolve)(candidate);
2315
2378
  for (; ; ) {
2316
- if ((0, import_node_fs2.existsSync)(current)) {
2379
+ if ((0, import_node_fs3.existsSync)(current)) {
2317
2380
  try {
2318
- return (0, import_node_fs2.statSync)(current).isDirectory() ? current : (0, import_node_path2.dirname)(current);
2381
+ return (0, import_node_fs3.statSync)(current).isDirectory() ? current : (0, import_node_path3.dirname)(current);
2319
2382
  } catch {
2320
2383
  }
2321
2384
  }
2322
- const parent = (0, import_node_path2.dirname)(current);
2385
+ const parent = (0, import_node_path3.dirname)(current);
2323
2386
  if (parent === current) return current;
2324
2387
  current = parent;
2325
2388
  }
2326
2389
  }
2327
2390
  function findWorkspaceFile(start, explicit) {
2328
- if (explicit) return (0, import_node_path2.resolve)(start, explicit);
2329
- let current = (0, import_node_path2.resolve)(start);
2391
+ if (explicit) return (0, import_node_path3.resolve)(start, explicit);
2392
+ let current = (0, import_node_path3.resolve)(start);
2330
2393
  for (; ; ) {
2331
- const candidate = (0, import_node_path2.join)(current, ".mindgraph", "workspace.json");
2332
- if ((0, import_node_fs2.existsSync)(candidate)) return candidate;
2333
- const parent = (0, import_node_path2.dirname)(current);
2394
+ const candidate = (0, import_node_path3.join)(current, ".mindgraph", "workspace.json");
2395
+ if ((0, import_node_fs3.existsSync)(candidate)) return candidate;
2396
+ const parent = (0, import_node_path3.dirname)(current);
2334
2397
  if (parent === current) return void 0;
2335
2398
  current = parent;
2336
2399
  }
@@ -2417,7 +2480,7 @@ var CodegraphAdapter = class {
2417
2480
  async resolveRepository(repo, fallbackSpaceUid) {
2418
2481
  const configured = await this.resolveRepositories(fallbackSpaceUid);
2419
2482
  const selected = repo && configured.find((candidate) => candidate.repoId === repo) || repo && configured.find(
2420
- (candidate) => candidate.repoRoot === repo || (0, import_node_path2.basename)(candidate.repoRoot) === repo
2483
+ (candidate) => candidate.repoRoot === repo || (0, import_node_path3.basename)(candidate.repoRoot) === repo
2421
2484
  ) || (!repo ? [...configured].sort((a, b) => b.repoRoot.length - a.repoRoot.length).find((candidate) => pathContains(candidate.repoRoot, this.cwd)) : void 0) || (!repo && configured.length === 1 ? configured[0] : void 0);
2422
2485
  if (selected) {
2423
2486
  return !repo && this.env.MINDGRAPH_REPO_ID ? this.resolveRepositoryIdentity(
@@ -2427,10 +2490,10 @@ var CodegraphAdapter = class {
2427
2490
  ) : selected;
2428
2491
  }
2429
2492
  if (repo) {
2430
- const requestedPath = await (0, import_promises.realpath)((0, import_node_path2.resolve)(this.cwd, repo)).catch(
2431
- () => (0, import_node_path2.resolve)(this.cwd, repo)
2493
+ const requestedPath = await (0, import_promises.realpath)((0, import_node_path3.resolve)(this.cwd, repo)).catch(
2494
+ () => (0, import_node_path3.resolve)(this.cwd, repo)
2432
2495
  );
2433
- if (!(0, import_node_fs2.existsSync)(requestedPath)) {
2496
+ if (!(0, import_node_fs3.existsSync)(requestedPath)) {
2434
2497
  const current = await this.currentRepository(fallbackSpaceUid);
2435
2498
  if (current.repoId === repo) return current;
2436
2499
  throw new UnknownRepositoryError(repo);
@@ -2446,8 +2509,8 @@ var CodegraphAdapter = class {
2446
2509
  }
2447
2510
  async currentRepository(fallbackSpaceUid) {
2448
2511
  const requestedRoot = this.env.MINDGRAPH_REPO_ROOT || this.cwd;
2449
- const requestedPath = await (0, import_promises.realpath)((0, import_node_path2.resolve)(this.cwd, requestedRoot)).catch(
2450
- () => (0, import_node_path2.resolve)(this.cwd, requestedRoot)
2512
+ const requestedPath = await (0, import_promises.realpath)((0, import_node_path3.resolve)(this.cwd, requestedRoot)).catch(
2513
+ () => (0, import_node_path3.resolve)(this.cwd, requestedRoot)
2451
2514
  );
2452
2515
  const repoRoot = await this.gitRoot(requestedPath) ?? requestedPath;
2453
2516
  return this.resolveRepositoryIdentity(
@@ -2468,7 +2531,7 @@ var CodegraphAdapter = class {
2468
2531
  );
2469
2532
  }
2470
2533
  async resolveRepositoryIdentity(root, explicitRepoId, spaceUid) {
2471
- const repoRoot = await (0, import_promises.realpath)(root).catch(() => (0, import_node_path2.resolve)(root));
2534
+ const repoRoot = await (0, import_promises.realpath)(root).catch(() => (0, import_node_path3.resolve)(root));
2472
2535
  const cacheKey = `${repoRoot}\0${explicitRepoId ?? ""}\0${spaceUid ?? ""}`;
2473
2536
  const cached = this.identityCache.get(cacheKey);
2474
2537
  if (cached) return cached;
@@ -2498,20 +2561,20 @@ var CodegraphAdapter = class {
2498
2561
  this.env
2499
2562
  ).catch(() => "");
2500
2563
  if (!rawCommonDir.trim()) {
2501
- return `local:${(0, import_node_path2.basename)(repoRoot)}`;
2564
+ return `local:${(0, import_node_path3.basename)(repoRoot)}`;
2502
2565
  }
2503
- const commonDir = (0, import_node_path2.resolve)(repoRoot, rawCommonDir.trim());
2504
- const identityDir = (0, import_node_path2.join)(commonDir, "mindgraph");
2505
- const identityFile = (0, import_node_path2.join)(identityDir, "repository-id");
2566
+ const commonDir = (0, import_node_path3.resolve)(repoRoot, rawCommonDir.trim());
2567
+ const identityDir = (0, import_node_path3.join)(commonDir, "mindgraph");
2568
+ const identityFile = (0, import_node_path3.join)(identityDir, "repository-id");
2506
2569
  try {
2507
- const existing = (0, import_node_fs2.readFileSync)(identityFile, "utf8").trim();
2570
+ const existing = (0, import_node_fs3.readFileSync)(identityFile, "utf8").trim();
2508
2571
  if (existing) return existing;
2509
2572
  } catch {
2510
2573
  }
2511
- (0, import_node_fs2.mkdirSync)(identityDir, { recursive: true, mode: 448 });
2512
- const generated = (0, import_node_crypto3.randomUUID)();
2574
+ (0, import_node_fs3.mkdirSync)(identityDir, { recursive: true, mode: 448 });
2575
+ const generated = (0, import_node_crypto4.randomUUID)();
2513
2576
  try {
2514
- (0, import_node_fs2.writeFileSync)(identityFile, `${generated}
2577
+ (0, import_node_fs3.writeFileSync)(identityFile, `${generated}
2515
2578
  `, {
2516
2579
  encoding: "utf8",
2517
2580
  flag: "wx",
@@ -2520,7 +2583,7 @@ var CodegraphAdapter = class {
2520
2583
  return generated;
2521
2584
  } catch (cause) {
2522
2585
  if (cause.code !== "EEXIST") throw cause;
2523
- const winner = (0, import_node_fs2.readFileSync)(identityFile, "utf8").trim();
2586
+ const winner = (0, import_node_fs3.readFileSync)(identityFile, "utf8").trim();
2524
2587
  if (!winner) throw new Error(`empty repository identity file: ${identityFile}`);
2525
2588
  return winner;
2526
2589
  }
@@ -2533,12 +2596,12 @@ var CodegraphAdapter = class {
2533
2596
  Math.min(this.timeoutMs, 2e3),
2534
2597
  this.env
2535
2598
  ).catch(() => "");
2536
- return raw.trim() ? (0, import_node_path2.resolve)(start, raw.trim()) : void 0;
2599
+ return raw.trim() ? (0, import_node_path3.resolve)(start, raw.trim()) : void 0;
2537
2600
  }
2538
2601
  /** Why the workspace map yielded no repositories — for callers that were
2539
2602
  * explicitly asked to fan out and would otherwise return silently empty. */
2540
2603
  workspaceDiagnostic() {
2541
- if (!this.workspaceFile || !(0, import_node_fs2.existsSync)(this.workspaceFile)) {
2604
+ if (!this.workspaceFile || !(0, import_node_fs3.existsSync)(this.workspaceFile)) {
2542
2605
  return "no .mindgraph/workspace.json was found between the working directory and the filesystem root";
2543
2606
  }
2544
2607
  return `${this.workspaceFile} is malformed or declares no repositories`;
@@ -2658,7 +2721,7 @@ var CodegraphAdapter = class {
2658
2721
  return this.resolveRepository(ref.repo || defaultRepo, fallbackSpaceUid);
2659
2722
  }
2660
2723
  if (ref.path) {
2661
- const requested = (0, import_node_path2.isAbsolute)(ref.path) ? (0, import_node_path2.resolve)(ref.path) : (0, import_node_path2.resolve)(this.cwd, ref.path);
2724
+ const requested = (0, import_node_path3.isAbsolute)(ref.path) ? (0, import_node_path3.resolve)(ref.path) : (0, import_node_path3.resolve)(this.cwd, ref.path);
2662
2725
  const absolute = await (0, import_promises.realpath)(requested).catch(() => requested);
2663
2726
  const configured = await this.resolveRepositories(fallbackSpaceUid);
2664
2727
  const defining = [...configured].sort((a, b) => b.repoRoot.length - a.repoRoot.length).find((candidate) => pathContains(candidate.repoRoot, absolute));
@@ -2735,19 +2798,19 @@ var CodegraphAdapter = class {
2735
2798
  }
2736
2799
  configuredRepositories() {
2737
2800
  const configured = [];
2738
- if (this.workspaceFile && (0, import_node_fs2.existsSync)(this.workspaceFile)) {
2801
+ if (this.workspaceFile && (0, import_node_fs3.existsSync)(this.workspaceFile)) {
2739
2802
  try {
2740
2803
  const parsed = JSON.parse(
2741
- (0, import_node_fs2.readFileSync)(this.workspaceFile, "utf8")
2804
+ (0, import_node_fs3.readFileSync)(this.workspaceFile, "utf8")
2742
2805
  );
2743
2806
  if (parsed.v === 1 && Array.isArray(parsed.repositories)) {
2744
- const configDirectory = (0, import_node_path2.dirname)(this.workspaceFile);
2745
- const base = (0, import_node_path2.basename)(configDirectory) === ".mindgraph" ? (0, import_node_path2.dirname)(configDirectory) : configDirectory;
2807
+ const configDirectory = (0, import_node_path3.dirname)(this.workspaceFile);
2808
+ const base = (0, import_node_path3.basename)(configDirectory) === ".mindgraph" ? (0, import_node_path3.dirname)(configDirectory) : configDirectory;
2746
2809
  for (const repository of parsed.repositories) {
2747
2810
  if (!repository || typeof repository.root !== "string") continue;
2748
2811
  configured.push({
2749
2812
  repoId: typeof repository.repo_id === "string" ? repository.repo_id : void 0,
2750
- repoRoot: (0, import_node_path2.resolve)(base, repository.root),
2813
+ repoRoot: (0, import_node_path3.resolve)(base, repository.root),
2751
2814
  spaceUid: typeof repository.space_uid === "string" ? repository.space_uid : void 0
2752
2815
  });
2753
2816
  }
@@ -2762,7 +2825,7 @@ var CodegraphAdapter = class {
2762
2825
  for (const [repoId, config] of Object.entries(parsed)) {
2763
2826
  configured.push({
2764
2827
  repoId,
2765
- repoRoot: (0, import_node_path2.resolve)(
2828
+ repoRoot: (0, import_node_path3.resolve)(
2766
2829
  this.cwd,
2767
2830
  typeof config === "string" ? config : config.root
2768
2831
  ),
@@ -2790,9 +2853,9 @@ var CodegraphAdapter = class {
2790
2853
  const hits = await this.runJson(args);
2791
2854
  let candidates = hits.map(asNode).map(toCandidate).filter((item) => item !== null);
2792
2855
  if (ref.path) {
2793
- const absolutePath = (0, import_node_path2.isAbsolute)(ref.path) ? await (0, import_promises.realpath)(ref.path).catch(() => ref.path) : void 0;
2856
+ const absolutePath = (0, import_node_path3.isAbsolute)(ref.path) ? await (0, import_promises.realpath)(ref.path).catch(() => ref.path) : void 0;
2794
2857
  const wanted = normalizePath(
2795
- absolutePath ? (0, import_node_path2.relative)(repository.repoRoot, absolutePath) : ref.path
2858
+ absolutePath ? (0, import_node_path3.relative)(repository.repoRoot, absolutePath) : ref.path
2796
2859
  );
2797
2860
  candidates = candidates.filter((candidate) => candidate.path === wanted);
2798
2861
  }
@@ -2893,7 +2956,7 @@ var CodegraphAdapter = class {
2893
2956
  const candidates = [
2894
2957
  this.env.MINDGRAPH_CODEGRAPH_BIN,
2895
2958
  "codegraph",
2896
- (0, import_node_path2.resolve)((0, import_node_os2.homedir)(), ".local", "bin", "codegraph")
2959
+ (0, import_node_path3.resolve)((0, import_node_os3.homedir)(), ".local", "bin", "codegraph")
2897
2960
  ].filter((candidate, index, all) => {
2898
2961
  return Boolean(candidate) && all.indexOf(candidate) === index;
2899
2962
  });
@@ -3494,9 +3557,9 @@ function primaryUids(value) {
3494
3557
  }
3495
3558
 
3496
3559
  // src/sync-tool.ts
3497
- var import_node_crypto4 = __toESM(require("crypto"));
3498
- var import_node_fs3 = __toESM(require("fs"));
3499
- var import_node_path3 = __toESM(require("path"));
3560
+ var import_node_crypto5 = __toESM(require("crypto"));
3561
+ var import_node_fs4 = __toESM(require("fs"));
3562
+ var import_node_path4 = __toESM(require("path"));
3500
3563
  var ok3 = (data) => ({
3501
3564
  content: [{ type: "text", text: JSON.stringify(data) }]
3502
3565
  });
@@ -3573,12 +3636,12 @@ var SYNC_TOOL = {
3573
3636
  }
3574
3637
  };
3575
3638
  function safePath(root, candidate) {
3576
- const absolute = import_node_path3.default.resolve(root, candidate);
3577
- const relative2 = import_node_path3.default.relative(root, absolute);
3578
- if (relative2.startsWith("..") || import_node_path3.default.isAbsolute(relative2)) {
3639
+ const absolute = import_node_path4.default.resolve(root, candidate);
3640
+ const relative2 = import_node_path4.default.relative(root, absolute);
3641
+ if (relative2.startsWith("..") || import_node_path4.default.isAbsolute(relative2)) {
3579
3642
  throw new Error(`path escapes repository root: ${candidate}`);
3580
3643
  }
3581
- if (import_node_fs3.default.existsSync(absolute)) {
3644
+ if (import_node_fs4.default.existsSync(absolute)) {
3582
3645
  if (!pathContains(realPathOf(root), realPathOf(absolute))) {
3583
3646
  throw new Error(`path escapes repository root via symlink: ${candidate}`);
3584
3647
  }
@@ -3587,26 +3650,26 @@ function safePath(root, candidate) {
3587
3650
  }
3588
3651
  function realPathOf(target) {
3589
3652
  try {
3590
- return import_node_fs3.default.realpathSync(target);
3653
+ return import_node_fs4.default.realpathSync(target);
3591
3654
  } catch {
3592
- return import_node_path3.default.resolve(target);
3655
+ return import_node_path4.default.resolve(target);
3593
3656
  }
3594
3657
  }
3595
3658
  function markdownFiles(target, realRoot, visited = /* @__PURE__ */ new Set()) {
3596
- if (!import_node_fs3.default.existsSync(target)) return [];
3659
+ if (!import_node_fs4.default.existsSync(target)) return [];
3597
3660
  const real = realPathOf(target);
3598
3661
  if (!pathContains(realRoot, real)) return [];
3599
- const stat = import_node_fs3.default.statSync(target);
3662
+ const stat = import_node_fs4.default.statSync(target);
3600
3663
  if (stat.isFile()) return target.endsWith(".md") ? [target] : [];
3601
3664
  if (!stat.isDirectory() || visited.has(real)) return [];
3602
3665
  visited.add(real);
3603
- return import_node_fs3.default.readdirSync(target, { withFileTypes: true }).flatMap((entry) => markdownFiles(import_node_path3.default.join(target, entry.name), realRoot, visited));
3666
+ return import_node_fs4.default.readdirSync(target, { withFileTypes: true }).flatMap((entry) => markdownFiles(import_node_path4.default.join(target, entry.name), realRoot, visited));
3604
3667
  }
3605
3668
  function fileDescriptor(root, absolute) {
3606
- const content = import_node_fs3.default.readFileSync(absolute, "utf8");
3669
+ const content = import_node_fs4.default.readFileSync(absolute, "utf8");
3607
3670
  return {
3608
- logical_path: import_node_path3.default.relative(root, absolute).split(import_node_path3.default.sep).join("/"),
3609
- content_hash: import_node_crypto4.default.createHash("sha256").update(content).digest("hex"),
3671
+ logical_path: import_node_path4.default.relative(root, absolute).split(import_node_path4.default.sep).join("/"),
3672
+ content_hash: import_node_crypto5.default.createHash("sha256").update(content).digest("hex"),
3610
3673
  bytes: Buffer.byteLength(content),
3611
3674
  content
3612
3675
  };
@@ -3675,7 +3738,7 @@ async function handleSyncTool(client2, args) {
3675
3738
  }
3676
3739
  if (action === "status" && request.logical_path && request.file_present !== false) {
3677
3740
  const absolute = safePath(root, String(request.logical_path));
3678
- request.file_present = import_node_fs3.default.existsSync(absolute);
3741
+ request.file_present = import_node_fs4.default.existsSync(absolute);
3679
3742
  if (request.file_present && !request.content_hash) {
3680
3743
  request.content_hash = fileDescriptor(root, absolute).content_hash;
3681
3744
  }
@@ -3748,10 +3811,10 @@ var RESOLUTION_PROPERTIES = {
3748
3811
  description: "Alias for confirm_new on a near-duplicate response"
3749
3812
  }
3750
3813
  };
3751
- function stableJson2(value) {
3752
- if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
3814
+ function stableJson3(value) {
3815
+ if (Array.isArray(value)) return `[${value.map(stableJson3).join(",")}]`;
3753
3816
  if (value && typeof value === "object") {
3754
- return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson2(item)}`).join(",")}}`;
3817
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson3(item)}`).join(",")}}`;
3755
3818
  }
3756
3819
  return JSON.stringify(value);
3757
3820
  }
@@ -3765,8 +3828,8 @@ function defaultWriteIdempotencyKey(tool, args) {
3765
3828
  ([key]) => key !== "invocation_context" && key !== "idempotency_key"
3766
3829
  )
3767
3830
  );
3768
- return (0, import_node_crypto5.createHash)("sha256").update(
3769
- stableJson2({
3831
+ return (0, import_node_crypto6.createHash)("sha256").update(
3832
+ stableJson3({
3770
3833
  harness_session_id: sessionId,
3771
3834
  harness_turn_id: context?.harnessTurnId ?? null,
3772
3835
  tool,
@@ -4478,6 +4541,15 @@ var TOOLS = [
4478
4541
  type: "string",
4479
4542
  description: "ISO-8601 date (e.g. '2021-06') for context: nodes with validity windows are annotated as of this date instead of today"
4480
4543
  },
4544
+ as_of: {
4545
+ type: "string",
4546
+ description: "ISO-8601 date for context: answer with what had been STATED by this date (a node is admitted when one of its sources was stated on or before it; fact dates never exclude it). Use for 'what did we know / what was the value as of <date>' questions."
4547
+ },
4548
+ retrieval_mode: {
4549
+ type: "string",
4550
+ enum: ["normal", "exhaustive"],
4551
+ description: "context: 'exhaustive' widens retrieval for list/count questions ('how many different \u2026 across', 'what two \u2026'); omitted lets the server's cue decide."
4552
+ },
4481
4553
  created_after: {
4482
4554
  type: "number",
4483
4555
  description: "Unix seconds \u2014 'recent' action: only nodes ingested after this time"
@@ -5706,6 +5778,8 @@ async function handleRetrieve(client2, args, profile) {
5706
5778
  salience_min,
5707
5779
  article_limit,
5708
5780
  valid_at,
5781
+ as_of,
5782
+ retrieval_mode,
5709
5783
  created_after,
5710
5784
  created_before,
5711
5785
  explain,
@@ -5734,9 +5808,15 @@ async function handleRetrieve(client2, args, profile) {
5734
5808
  // the advertised knob must not get a silent no-op).
5735
5809
  ...article_limit !== void 0 ? { article_limit } : include_documents === false || profile === "coding" && !include_documents ? { article_limit: 0 } : {},
5736
5810
  valid_at,
5811
+ as_of,
5812
+ retrieval_mode,
5737
5813
  include_graph,
5738
5814
  graph_expansion_limit: graph_expansion_limit ?? 3,
5739
- graph_max_depth: graph_max_depth ?? 2
5815
+ graph_max_depth: graph_max_depth ?? 2,
5816
+ // Evidence plan R2: the server's canonical rendering under a token
5817
+ // budget derived from the character budget; the local renderer is
5818
+ // the fallback for servers that predate it.
5819
+ ...format === "json" ? {} : { format: "text", max_tokens: Math.max(256, Math.floor((max_output_chars ?? 24e3) / 4)) }
5740
5820
  }),
5741
5821
  (raw) => renderContext(raw, max_output_chars)
5742
5822
  );
@@ -6210,7 +6290,12 @@ function buildMindGraphServer(wiring) {
6210
6290
  });
6211
6291
  server2.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
6212
6292
  const { name, arguments: args } = request.params;
6213
- const rawArgs = { ...args || {} };
6293
+ const rawArgs = {
6294
+ ...args || {},
6295
+ // H1: session, lease and invocation fields the local hook recorded for
6296
+ // this exact call (stdio only; hosted mode has no local hook).
6297
+ ...hosted ? {} : wiring.resolveHookFields?.(name, args || {})
6298
+ };
6214
6299
  const toolArgs = { ...rawArgs };
6215
6300
  let governanceConfig = wiring.governance;
6216
6301
  if (hosted) {
@@ -6275,16 +6360,16 @@ function buildMindGraphServer(wiring) {
6275
6360
  }
6276
6361
 
6277
6362
  // src/index.ts
6278
- var import_node_path5 = __toESM(require("path"));
6363
+ var import_node_path6 = __toESM(require("path"));
6279
6364
 
6280
6365
  // src/hook-installer.ts
6281
- var import_node_fs4 = __toESM(require("fs"));
6282
- var import_node_os3 = __toESM(require("os"));
6283
- var import_node_path4 = __toESM(require("path"));
6284
- var import_node_crypto6 = __toESM(require("crypto"));
6366
+ var import_node_fs5 = __toESM(require("fs"));
6367
+ var import_node_os4 = __toESM(require("os"));
6368
+ var import_node_path5 = __toESM(require("path"));
6369
+ var import_node_crypto7 = __toESM(require("crypto"));
6285
6370
  function storedFeatures(homeDir) {
6286
6371
  const { promptRecall, capture } = loadHookEnv(
6287
- import_node_path4.default.join(homeDir || import_node_os3.default.homedir(), ".mindgraph")
6372
+ import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), ".mindgraph")
6288
6373
  );
6289
6374
  return { promptRecall, capture };
6290
6375
  }
@@ -6298,24 +6383,24 @@ function windowsCommand(harness) {
6298
6383
  }
6299
6384
  var RUNNER_VERSION_RELATIVE = `${RUNNER_RELATIVE}.version`;
6300
6385
  function installHookRunner(sourceFile, homeDir, version) {
6301
- const target = import_node_path4.default.join(homeDir || import_node_os3.default.homedir(), RUNNER_RELATIVE);
6302
- import_node_fs4.default.mkdirSync(import_node_path4.default.dirname(target), { recursive: true });
6303
- const temporary = `${target}.${process.pid}.${import_node_crypto6.default.randomUUID()}.tmp`;
6304
- import_node_fs4.default.copyFileSync(sourceFile, temporary);
6305
- import_node_fs4.default.renameSync(temporary, target);
6306
- const versionPath = import_node_path4.default.join(homeDir || import_node_os3.default.homedir(), RUNNER_VERSION_RELATIVE);
6386
+ const target = import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), RUNNER_RELATIVE);
6387
+ import_node_fs5.default.mkdirSync(import_node_path5.default.dirname(target), { recursive: true });
6388
+ const temporary = `${target}.${process.pid}.${import_node_crypto7.default.randomUUID()}.tmp`;
6389
+ import_node_fs5.default.copyFileSync(sourceFile, temporary);
6390
+ import_node_fs5.default.renameSync(temporary, target);
6391
+ const versionPath = import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), RUNNER_VERSION_RELATIVE);
6307
6392
  if (version) {
6308
- import_node_fs4.default.writeFileSync(versionPath, `${version}
6393
+ import_node_fs5.default.writeFileSync(versionPath, `${version}
6309
6394
  `);
6310
6395
  } else {
6311
- import_node_fs4.default.rmSync(versionPath, { force: true });
6396
+ import_node_fs5.default.rmSync(versionPath, { force: true });
6312
6397
  }
6313
6398
  return target;
6314
6399
  }
6315
6400
  function installedHookRunnerVersion(homeDir) {
6316
6401
  try {
6317
- const raw = import_node_fs4.default.readFileSync(
6318
- import_node_path4.default.join(homeDir || import_node_os3.default.homedir(), RUNNER_VERSION_RELATIVE),
6402
+ const raw = import_node_fs5.default.readFileSync(
6403
+ import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), RUNNER_VERSION_RELATIVE),
6319
6404
  "utf8"
6320
6405
  ).trim();
6321
6406
  return raw || void 0;
@@ -6340,11 +6425,11 @@ function refreshHookRunner(serverVersion, sourceBundle, homeDir) {
6340
6425
  if (process.env.MINDGRAPH_HOOK_AUTOUPDATE === "off") {
6341
6426
  return { refreshed: false, reason: "disabled" };
6342
6427
  }
6343
- const home = homeDir || import_node_os3.default.homedir();
6344
- if (!import_node_fs4.default.existsSync(import_node_path4.default.join(home, RUNNER_RELATIVE))) {
6428
+ const home = homeDir || import_node_os4.default.homedir();
6429
+ if (!import_node_fs5.default.existsSync(import_node_path5.default.join(home, RUNNER_RELATIVE))) {
6345
6430
  return { refreshed: false, reason: "no_runner" };
6346
6431
  }
6347
- if (!import_node_fs4.default.existsSync(sourceBundle)) {
6432
+ if (!import_node_fs5.default.existsSync(sourceBundle)) {
6348
6433
  return { refreshed: false, reason: "no_source" };
6349
6434
  }
6350
6435
  const server2 = parseSemver(serverVersion);
@@ -6375,8 +6460,8 @@ function refreshOwnedClaudeHooks(projectDir = process.cwd(), homeDir) {
6375
6460
  for (const scope of scopes) {
6376
6461
  try {
6377
6462
  const file = settingsPath("claude-code", scope, projectDir, void 0, homeDir);
6378
- if (!import_node_fs4.default.existsSync(file)) continue;
6379
- if (!import_node_fs4.default.readFileSync(file, "utf8").includes(OWNER_MARKER)) continue;
6463
+ if (!import_node_fs5.default.existsSync(file)) continue;
6464
+ if (!import_node_fs5.default.readFileSync(file, "utf8").includes(OWNER_MARKER)) continue;
6380
6465
  installHooks(
6381
6466
  "claude-code",
6382
6467
  scope,
@@ -6396,15 +6481,15 @@ function versionSkewNote(serverVersion, homeDir) {
6396
6481
  if (!runnerVersion || runnerVersion === serverVersion) return void 0;
6397
6482
  return `NOTE: the installed MindGraph hook runner is v${runnerVersion} but this MCP server is v${serverVersion} \u2014 hook behavior and tool contracts may be out of sync. Tell the user to run: npx -y mindgraph-mcp@latest install-hooks (refreshes the pinned runner).`;
6398
6483
  }
6399
- function settingsPath(harness, scope, projectDir = process.cwd(), codexHomeDir = process.env.CODEX_HOME || import_node_path4.default.join(import_node_os3.default.homedir(), ".codex"), homeDir) {
6484
+ function settingsPath(harness, scope, projectDir = process.cwd(), codexHomeDir = process.env.CODEX_HOME || import_node_path5.default.join(import_node_os4.default.homedir(), ".codex"), homeDir) {
6400
6485
  if (harness === "codex") {
6401
- return scope === "user" ? import_node_path4.default.join(codexHomeDir, "hooks.json") : import_node_path4.default.join(projectDir, ".codex", "hooks.json");
6486
+ return scope === "user" ? import_node_path5.default.join(codexHomeDir, "hooks.json") : import_node_path5.default.join(projectDir, ".codex", "hooks.json");
6402
6487
  }
6403
- return scope === "user" ? import_node_path4.default.join(homeDir || import_node_os3.default.homedir(), ".claude", "settings.json") : import_node_path4.default.join(projectDir, ".claude", "settings.json");
6488
+ return scope === "user" ? import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), ".claude", "settings.json") : import_node_path5.default.join(projectDir, ".claude", "settings.json");
6404
6489
  }
6405
6490
  function readSettings(file) {
6406
- if (!import_node_fs4.default.existsSync(file)) return {};
6407
- return JSON.parse(import_node_fs4.default.readFileSync(file, "utf8"));
6491
+ if (!import_node_fs5.default.existsSync(file)) return {};
6492
+ return JSON.parse(import_node_fs5.default.readFileSync(file, "utf8"));
6408
6493
  }
6409
6494
  function ownedHook(harness, timeout, additionalContextLimit) {
6410
6495
  return {
@@ -6416,6 +6501,7 @@ function ownedHook(harness, timeout, additionalContextLimit) {
6416
6501
  ...additionalContextLimit === void 0 ? {} : { additionalContextLimit }
6417
6502
  };
6418
6503
  }
6504
+ var CLAUDE_POST_TOOL_MATCHER = "mcp__mindgraph__.*|Edit|MultiEdit|Write|NotebookEdit|Bash|Task|Agent";
6419
6505
  function desiredEntries(harness, features = {}) {
6420
6506
  const common = {
6421
6507
  SessionStart: [
@@ -6448,7 +6534,17 @@ function desiredEntries(harness, features = {}) {
6448
6534
  ],
6449
6535
  // PostToolUse awaits the lease renewal round-trip, which fires exactly
6450
6536
  // when the tenant is cold (post-idle reclaim) — 5s killed it mid-claim.
6451
- PostToolUse: [{ matcher: ".*", hooks: [ownedHook(harness, 10)] }],
6537
+ // Claude Code: only the tools the hook acts on (MindGraph calls, edits,
6538
+ // and the shell/agent calls that keep a lease alive). Read, Grep and Glob
6539
+ // are most of a session's tool calls and the hook did nothing useful for
6540
+ // them but start a process (roadmap H8). Codex names its tools
6541
+ // differently, so it keeps the catch-all.
6542
+ PostToolUse: [
6543
+ {
6544
+ matcher: harness === "claude-code" ? CLAUDE_POST_TOOL_MATCHER : ".*",
6545
+ hooks: [ownedHook(harness, 10)]
6546
+ }
6547
+ ],
6452
6548
  Stop: [{ hooks: [ownedHook(harness, 5)] }],
6453
6549
  // SessionEnd makes up to two sequential cloud calls (abandon_iteration +
6454
6550
  // session close) — the SAME cold-tenant latency SessionStart needs 30s
@@ -6482,13 +6578,13 @@ function entryHasOwnedHook(value) {
6482
6578
  return Array.isArray(hooks) && hooks.some((hook) => hookCommand(hook)?.includes(OWNER_MARKER));
6483
6579
  }
6484
6580
  function writeSettings(file, settings) {
6485
- import_node_fs4.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
6486
- const temporary = `${file}.${process.pid}.${import_node_crypto6.default.randomUUID()}.tmp`;
6487
- import_node_fs4.default.writeFileSync(temporary, `${JSON.stringify(settings, null, 2)}
6581
+ import_node_fs5.default.mkdirSync(import_node_path5.default.dirname(file), { recursive: true });
6582
+ const temporary = `${file}.${process.pid}.${import_node_crypto7.default.randomUUID()}.tmp`;
6583
+ import_node_fs5.default.writeFileSync(temporary, `${JSON.stringify(settings, null, 2)}
6488
6584
  `, {
6489
6585
  mode: 384
6490
6586
  });
6491
- import_node_fs4.default.renameSync(temporary, file);
6587
+ import_node_fs5.default.renameSync(temporary, file);
6492
6588
  }
6493
6589
  function installHooks(harness, scope, projectDir = process.cwd(), codexHomeDir, homeDir, features = {}) {
6494
6590
  const file = settingsPath(harness, scope, projectDir, codexHomeDir, homeDir);
@@ -6613,7 +6709,7 @@ if (PROFILE === "coding") {
6613
6709
  - Capture corrections, decisions with rationale, fixes that survived meaningful failed attempts, durable invariants/preferences, and blockers with evidence.
6614
6710
  - If a write returns \`near_duplicate\`, choose \`reuse_uid\` or \`supersedes_uid\`; use \`confirm_new\` only for genuinely distinct facts.
6615
6711
  - Do not capture routine mechanics, transient command output, facts cheaply derivable from code, unsupported speculation as high-confidence lessons, or completion without evidence.
6616
- - Adapter context is owned by ${HARNESS}; omit invocation_context because hooks replace it.`;
6712
+ - Adapter context is owned by ${HARNESS}; omit invocation_context because the adapter supplies it.`;
6617
6713
  } else {
6618
6714
  INSTRUCTIONS = INSTRUCTIONS.split("\n").filter(
6619
6715
  (line) => !line.includes("mindgraph_code") && !line.includes("`code`") && !line.includes("Typed code anchors")
@@ -6621,7 +6717,7 @@ if (PROFILE === "coding") {
6621
6717
  }
6622
6718
  var RUNNER_REFRESH = (() => {
6623
6719
  try {
6624
- return refreshHookRunner("0.23.0", import_node_path5.default.join(__dirname, "cli.js"));
6720
+ return refreshHookRunner("0.24.0", import_node_path6.default.join(__dirname, "cli.js"));
6625
6721
  } catch {
6626
6722
  return void 0;
6627
6723
  }
@@ -6635,12 +6731,12 @@ if (RUNNER_REFRESH?.refreshed) {
6635
6731
  }
6636
6732
  })();
6637
6733
  console.error(
6638
- `[mindgraph-mcp] refreshed pinned hook runner ${RUNNER_REFRESH.runnerVersion ? `v${RUNNER_REFRESH.runnerVersion}` : "(pre-sidecar)"} \u2192 v${"0.23.0"}` + (refreshedSettings.length > 0 ? `; refreshed owned hook entries in ${refreshedSettings.join(", ")}` : "")
6734
+ `[mindgraph-mcp] refreshed pinned hook runner ${RUNNER_REFRESH.runnerVersion ? `v${RUNNER_REFRESH.runnerVersion}` : "(pre-sidecar)"} \u2192 v${"0.24.0"}` + (refreshedSettings.length > 0 ? `; refreshed owned hook entries in ${refreshedSettings.join(", ")}` : "")
6639
6735
  );
6640
6736
  }
6641
6737
  var HOOK_SKEW_NOTE = (() => {
6642
6738
  try {
6643
- return versionSkewNote("0.23.0");
6739
+ return versionSkewNote("0.24.0");
6644
6740
  } catch {
6645
6741
  return void 0;
6646
6742
  }
@@ -6661,7 +6757,7 @@ var GOVERNANCE_CONFIG = {
6661
6757
  }
6662
6758
  };
6663
6759
  var MEMORY_RUNTIME_CONFIG = {
6664
- serverVersion: "0.23.0",
6760
+ serverVersion: "0.24.0",
6665
6761
  baseUrl: BASE_URL,
6666
6762
  profile: PROFILE,
6667
6763
  harness: HARNESS,
@@ -6670,18 +6766,19 @@ var MEMORY_RUNTIME_CONFIG = {
6670
6766
  };
6671
6767
  var server = buildMindGraphServer({
6672
6768
  client,
6673
- serverVersion: "0.23.0",
6769
+ serverVersion: "0.24.0",
6674
6770
  instructions: INSTRUCTIONS,
6675
6771
  profile: PROFILE,
6676
6772
  agentId: AGENT_ID,
6677
6773
  governance: GOVERNANCE_CONFIG,
6678
- memory: MEMORY_RUNTIME_CONFIG
6774
+ memory: MEMORY_RUNTIME_CONFIG,
6775
+ resolveHookFields: (name, args) => resolvePendingCall(name, args)
6679
6776
  });
6680
6777
  async function main() {
6681
6778
  const transport = new import_stdio.StdioServerTransport();
6682
6779
  await server.connect(transport);
6683
6780
  console.error(
6684
- `MindGraph MCP server v${"0.23.0"} running on stdio (${BASE_URL})`
6781
+ `MindGraph MCP server v${"0.24.0"} running on stdio (${BASE_URL})`
6685
6782
  );
6686
6783
  }
6687
6784
  main().catch((error2) => {