@gethmy/mcp 2.8.0 → 2.8.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.
package/dist/index.js CHANGED
@@ -2374,6 +2374,294 @@ async function onboardNewUser(params) {
2374
2374
  };
2375
2375
  }
2376
2376
 
2377
+ // src/skills.ts
2378
+ import {
2379
+ existsSync as existsSync4,
2380
+ mkdirSync as mkdirSync3,
2381
+ readFileSync as readFileSync4,
2382
+ renameSync,
2383
+ writeFileSync as writeFileSync3
2384
+ } from "node:fs";
2385
+ import { homedir as homedir3 } from "node:os";
2386
+ import { dirname, join as join4 } from "node:path";
2387
+
2388
+ // src/hmy-config.ts
2389
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
2390
+ import { homedir as homedir2 } from "node:os";
2391
+ import { join as join3 } from "node:path";
2392
+ var DEFAULTS = { updateCheck: true, pin: null };
2393
+ function getHmyConfigPath() {
2394
+ return join3(homedir2(), ".hmy", "config.yaml");
2395
+ }
2396
+ function loadHmyConfig() {
2397
+ const path = getHmyConfigPath();
2398
+ if (!existsSync3(path))
2399
+ return { ...DEFAULTS };
2400
+ try {
2401
+ return parseHmyConfig(readFileSync3(path, "utf-8"));
2402
+ } catch {
2403
+ return { ...DEFAULTS };
2404
+ }
2405
+ }
2406
+ function parseHmyConfig(text) {
2407
+ const cfg = { ...DEFAULTS };
2408
+ for (const rawLine of text.split(`
2409
+ `)) {
2410
+ const line = rawLine.trim();
2411
+ if (!line || line.startsWith("#"))
2412
+ continue;
2413
+ const sep2 = line.indexOf(":");
2414
+ if (sep2 === -1)
2415
+ continue;
2416
+ const key = line.slice(0, sep2).trim();
2417
+ let value = line.slice(sep2 + 1).trim();
2418
+ const hash = value.indexOf(" #");
2419
+ if (hash !== -1)
2420
+ value = value.slice(0, hash).trim();
2421
+ value = value.replace(/^["']|["']$/g, "");
2422
+ switch (key) {
2423
+ case "update_check":
2424
+ cfg.updateCheck = value !== "false";
2425
+ break;
2426
+ case "pin":
2427
+ case "pin_version":
2428
+ cfg.pin = value || null;
2429
+ break;
2430
+ }
2431
+ }
2432
+ return cfg;
2433
+ }
2434
+
2435
+ // src/skills.ts
2436
+ var HARMONY_WORKFLOW_PROMPT = `# Harmony Card Workflow
2437
+
2438
+ Start work on a Harmony card. Card reference: $ARGUMENTS
2439
+
2440
+ ## 1. Find & Fetch Card
2441
+
2442
+ Parse the reference and fetch the card:
2443
+ - \`#42\` or \`42\` → \`harmony_get_card_by_short_id\` with \`shortId: 42\`
2444
+ - UUID → \`harmony_get_card\` with \`cardId\`
2445
+ - Name/text → \`harmony_search_cards\` with \`query\`
2446
+
2447
+ ## 2. Get Board State
2448
+
2449
+ Call \`harmony_get_board\` to get columns and labels. From the response:
2450
+ - Find the "In Progress" (or "Progress") column ID
2451
+ - Find the "agent" label ID
2452
+
2453
+ ## 3. Setup Card for Work
2454
+
2455
+ Execute these in sequence:
2456
+ 1. \`harmony_move_card\` → Move to "In Progress" column
2457
+ 2. \`harmony_add_label_to_card\` → Add "agent" label
2458
+ 3. \`harmony_start_agent_session\`:
2459
+ - \`cardId\`: Card UUID
2460
+ - \`agentIdentifier\`: Your agent identifier
2461
+ - \`agentName\`: Your agent name
2462
+ - \`currentTask\`: "Analyzing card requirements"
2463
+
2464
+ ## 4. Generate Work Prompt
2465
+
2466
+ Call \`harmony_generate_prompt\` with:
2467
+ - \`cardId\` or \`shortId\` (+ \`projectId\` if using shortId)
2468
+ - \`variant\`: Select based on task:
2469
+ - \`"execute"\` (default) → Clear tasks, bug fixes, well-defined work
2470
+ - \`"analysis"\` → Complex features, unclear requirements
2471
+ - \`"draft"\` → Medium complexity, want feedback first
2472
+
2473
+ The generated prompt provides role framing, focus areas, subtasks, linked cards, and suggested outputs.
2474
+
2475
+ ## 5. Display Card Summary
2476
+
2477
+ Show the user: Card title, short ID, role, priority, labels, due date, description, and subtasks.
2478
+
2479
+ ## 6. Implement Solution
2480
+
2481
+ Work on the card following the generated prompt's guidance. Update progress at milestones:
2482
+ - \`harmony_update_agent_progress\` with \`progressPercent\` (0-100), \`currentTask\`, \`status\`, \`blockers\`
2483
+
2484
+ **Progress checkpoints:** 20% (exploration), 50% (implementation), 80% (testing), 100% (done)
2485
+
2486
+ ## 7. Complete Work
2487
+
2488
+ When finished:
2489
+ 1. \`harmony_end_agent_session\` with \`status: "completed"\`, \`progressPercent: 100\`
2490
+ 2. \`harmony_move_card\` to "Review" column
2491
+ 3. Summarize accomplishments
2492
+
2493
+ If pausing: \`harmony_end_agent_session\` with \`status: "paused"\`
2494
+
2495
+ ## Key Tools Reference
2496
+
2497
+ **Cards:** \`harmony_get_card\`, \`harmony_get_card_by_short_id\`, \`harmony_search_cards\`, \`harmony_create_card\`, \`harmony_update_card\`, \`harmony_move_card\`, \`harmony_delete_card\`, \`harmony_assign_card\`
2498
+
2499
+ **Subtasks:** \`harmony_create_subtask\`, \`harmony_toggle_subtask\`, \`harmony_delete_subtask\`
2500
+
2501
+ **Labels:** \`harmony_add_label_to_card\`, \`harmony_remove_label_from_card\`, \`harmony_create_label\`
2502
+
2503
+ **Links:** \`harmony_add_link_to_card\`, \`harmony_remove_link_from_card\`, \`harmony_get_card_links\`
2504
+
2505
+ **Board:** \`harmony_get_board\`, \`harmony_list_projects\`, \`harmony_get_context\`, \`harmony_set_project_context\`
2506
+
2507
+ **Sessions:** \`harmony_start_agent_session\`, \`harmony_update_agent_progress\`, \`harmony_end_agent_session\`, \`harmony_get_agent_session\`
2508
+
2509
+ **AI:** \`harmony_generate_prompt\`, \`harmony_process_command\`
2510
+ `;
2511
+ function buildSkillFile(skill) {
2512
+ const content = stripSkillPreamble(skill.content);
2513
+ if (skill.skillVersion !== undefined && !hasMetadataVersion(content)) {
2514
+ return injectMetadataVersion(content, skill.skillVersion);
2515
+ }
2516
+ return content;
2517
+ }
2518
+ var PREAMBLE_START = "<!-- hmy-skills-preamble:start -->";
2519
+ var PREAMBLE_END = "<!-- hmy-skills-preamble:end -->";
2520
+ function stripSkillPreamble(content) {
2521
+ const start = content.indexOf(PREAMBLE_START);
2522
+ const end = content.indexOf(PREAMBLE_END);
2523
+ if (start === -1 || end === -1 || end < start)
2524
+ return content;
2525
+ const stripped = content.slice(0, start) + content.slice(end + PREAMBLE_END.length);
2526
+ return `${stripped.replace(/\n{3,}/g, `
2527
+
2528
+ `).replace(/\s+$/, "")}
2529
+ `;
2530
+ }
2531
+ function atomicWrite(filePath, content) {
2532
+ const dir = dirname(filePath);
2533
+ if (!existsSync4(dir))
2534
+ mkdirSync3(dir, { recursive: true });
2535
+ const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
2536
+ writeFileSync3(tmp, content);
2537
+ renameSync(tmp, filePath);
2538
+ }
2539
+ function hasMetadataVersion(content) {
2540
+ return parseSkillVersion(content) !== null;
2541
+ }
2542
+ function injectMetadataVersion(content, version) {
2543
+ const fmMatch = content.match(/^(---\n[\s\S]*?\n)(---\n)([\s\S]*)$/);
2544
+ if (!fmMatch)
2545
+ return content;
2546
+ const [, head, close, body] = fmMatch;
2547
+ const block = `metadata:
2548
+ version: "${version}"
2549
+ `;
2550
+ return `${head}${block}${close}${body}`;
2551
+ }
2552
+ function parseSkillVersion(content) {
2553
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
2554
+ if (fmMatch) {
2555
+ const fm = fmMatch[1];
2556
+ const verMatch = fm.match(/^metadata:[\s\S]*?\n[ \t]+version:[ \t]*["']?(\d+)["']?\s*$/m);
2557
+ if (verMatch)
2558
+ return verMatch[1];
2559
+ }
2560
+ const legacy = content.match(/<!-- skills-version:(\d+) -->/);
2561
+ return legacy ? legacy[1] : null;
2562
+ }
2563
+ function findSkillFiles(paths, knownNames) {
2564
+ const results = [];
2565
+ for (const filePath of paths) {
2566
+ if (!existsSync4(filePath))
2567
+ continue;
2568
+ for (const name of knownNames) {
2569
+ if (filePath.includes(`/${name}/`) || filePath.includes(`/${name}.md`)) {
2570
+ results.push({ name, filePath });
2571
+ break;
2572
+ }
2573
+ }
2574
+ }
2575
+ return results;
2576
+ }
2577
+ var HMY_DIR = join4(homedir3(), ".hmy");
2578
+ var HMY_VERSION_FILE = join4(HMY_DIR, "VERSION");
2579
+ var LAST_CHECK_FILE = join4(HMY_DIR, "last-update-check");
2580
+ var CHECK_TTL_MS = 24 * 60 * 60 * 1000;
2581
+ function checkedRecently(now = Date.now()) {
2582
+ try {
2583
+ if (!existsSync4(LAST_CHECK_FILE))
2584
+ return false;
2585
+ const ts = Number.parseInt(readFileSync4(LAST_CHECK_FILE, "utf-8").trim(), 10);
2586
+ if (!Number.isFinite(ts))
2587
+ return false;
2588
+ return now - ts < CHECK_TTL_MS;
2589
+ } catch {
2590
+ return false;
2591
+ }
2592
+ }
2593
+ function recordCheck(now = Date.now()) {
2594
+ try {
2595
+ if (!existsSync4(HMY_DIR))
2596
+ mkdirSync3(HMY_DIR, { recursive: true });
2597
+ writeFileSync3(LAST_CHECK_FILE, String(now));
2598
+ } catch {}
2599
+ }
2600
+ async function refreshSkills(opts = {}) {
2601
+ try {
2602
+ if (!isConfigured())
2603
+ return { updated: false };
2604
+ const cfg = loadHmyConfig();
2605
+ if (!cfg.updateCheck || cfg.pin)
2606
+ return { updated: false };
2607
+ if (!opts.force && checkedRecently())
2608
+ return { updated: false };
2609
+ const status = areSkillsInstalled();
2610
+ if (!status.installed)
2611
+ return { updated: false };
2612
+ const client3 = new HarmonyApiClient;
2613
+ const versionInfo = await client3.fetchSkillsVersion();
2614
+ recordCheck();
2615
+ const skillFiles = findSkillFiles(status.paths, versionInfo.skills);
2616
+ if (skillFiles.length > 0) {
2617
+ const samplePath = skillFiles[0].filePath;
2618
+ for (const name of versionInfo.skills) {
2619
+ if (skillFiles.some((sf) => sf.name === name))
2620
+ continue;
2621
+ let siblingPath;
2622
+ if (samplePath.endsWith("SKILL.md")) {
2623
+ const parentDir = dirname(dirname(samplePath));
2624
+ siblingPath = `${parentDir}/${name}/SKILL.md`;
2625
+ } else {
2626
+ const parentDir = dirname(samplePath);
2627
+ siblingPath = `${parentDir}/${name}.md`;
2628
+ }
2629
+ if (existsSync4(siblingPath)) {
2630
+ skillFiles.push({ name, filePath: siblingPath });
2631
+ }
2632
+ }
2633
+ }
2634
+ if (skillFiles.length === 0)
2635
+ return { updated: false };
2636
+ let updated = false;
2637
+ for (const { name, filePath } of skillFiles) {
2638
+ try {
2639
+ const currentContent = readFileSync4(filePath, "utf-8");
2640
+ const localVersion = parseSkillVersion(currentContent);
2641
+ const fetched = await client3.fetchSkill(name);
2642
+ const remoteVersion = fetched.skillVersion;
2643
+ if (remoteVersion !== undefined && localVersion !== null && Number(localVersion) >= remoteVersion) {
2644
+ continue;
2645
+ }
2646
+ atomicWrite(filePath, buildSkillFile(fetched));
2647
+ updated = true;
2648
+ } catch (err) {
2649
+ const msg = err instanceof Error ? err.message : String(err);
2650
+ console.error(`Harmony: skill "${name}" refresh failed: ${msg}`);
2651
+ }
2652
+ }
2653
+ if (updated) {
2654
+ try {
2655
+ atomicWrite(HMY_VERSION_FILE, versionInfo.version);
2656
+ } catch {}
2657
+ console.error("Harmony: Refreshed skills from server");
2658
+ }
2659
+ return { updated };
2660
+ } catch {
2661
+ return { updated: false };
2662
+ }
2663
+ }
2664
+
2377
2665
  // src/server.ts
2378
2666
  var memorySessions = new Map;
2379
2667
  function parseLabelList(raw) {
@@ -2511,7 +2799,11 @@ var TOOLS = {
2511
2799
  enum: ["low", "medium", "high", "urgent"],
2512
2800
  description: "Priority level"
2513
2801
  },
2514
- assigneeId: { type: "string", description: "Assignee user ID" }
2802
+ assigneeId: { type: "string", description: "Assignee user ID" },
2803
+ planId: {
2804
+ type: "string",
2805
+ description: "Plan ID to link this card to (optional). Links the card to that plan via its plan_id."
2806
+ }
2515
2807
  },
2516
2808
  required: ["title"]
2517
2809
  }
@@ -3826,7 +4118,7 @@ function registerHandlers(server, deps) {
3826
4118
  {
3827
4119
  uri,
3828
4120
  mimeType: "text/markdown",
3829
- text: fetched.content
4121
+ text: stripSkillPreamble(fetched.content)
3830
4122
  }
3831
4123
  ]
3832
4124
  };
@@ -3876,7 +4168,8 @@ async function handleToolCall(name, args, deps) {
3876
4168
  columnId: args.columnId,
3877
4169
  description: args.description,
3878
4170
  priority: args.priority,
3879
- assigneeId: args.assigneeId
4171
+ assigneeId: args.assigneeId,
4172
+ planId: args.planId
3880
4173
  });
3881
4174
  return { success: true, ...result };
3882
4175
  }
@@ -4902,13 +5195,16 @@ function createConfigDeps() {
4902
5195
  class HarmonyMCPServer {
4903
5196
  server;
4904
5197
  constructor() {
4905
- this.server = new Server({ name: "@gethmy/mcp", version: "2.0.0" }, { capabilities: { tools: {}, resources: {} } });
5198
+ this.server = new Server({ name: "@gethmy/mcp", version: "2.0.0" }, { capabilities: { tools: {}, resources: { listChanged: true } } });
4906
5199
  registerHandlers(this.server, createConfigDeps());
4907
5200
  }
4908
- async run() {
5201
+ async run(opts = {}) {
4909
5202
  const transport = new StdioServerTransport;
4910
5203
  await this.server.connect(transport);
4911
5204
  console.error("Harmony MCP server running on stdio");
5205
+ if (opts.skillsUpdated) {
5206
+ this.server.sendResourceListChanged().catch(() => {});
5207
+ }
4912
5208
  const configDeps = createConfigDeps();
4913
5209
  initAutoSession(async (client3, cardId, status) => {
4914
5210
  await runEndSessionPipeline(client3, configDeps, cardId, status);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gethmy/mcp",
3
- "version": "2.8.0",
3
+ "version": "2.8.1",
4
4
  "description": "MCP server for Harmony Kanban board - enables AI coding agents to manage your boards",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -60,7 +60,7 @@
60
60
  "serve:remote": "bun src/remote.ts",
61
61
  "dev": "bun --watch src/index.ts",
62
62
  "test": "bun run test:unit && bun run test:integration",
63
- "test:unit": "bun test src/__tests__/active-learning.test.ts src/__tests__/context-assembly.test.ts src/__tests__/prompt-builder.test.ts src/__tests__/memory-audit.test.ts src/__tests__/skills.test.ts src/__tests__/tool-dispatch.test.ts src/__tests__/mcp-integration.test.ts",
63
+ "test:unit": "bun test src/__tests__/active-learning.test.ts src/__tests__/context-assembly.test.ts src/__tests__/prompt-builder.test.ts src/__tests__/memory-audit.test.ts src/__tests__/skills.test.ts src/__tests__/hmy-config.test.ts src/__tests__/tool-dispatch.test.ts src/__tests__/mcp-integration.test.ts",
64
64
  "test:integration": "bun test src/__tests__/integration-memory-system.test.ts src/__tests__/integration-memory-crud.test.ts",
65
65
  "typecheck": "tsc --noEmit",
66
66
  "prepublishOnly": "bun run build"
package/src/api-client.ts CHANGED
@@ -454,6 +454,7 @@ export class HarmonyApiClient {
454
454
  description?: string;
455
455
  priority?: string;
456
456
  assigneeId?: string;
457
+ planId?: string;
457
458
  },
458
459
  ): Promise<{ card: unknown }> {
459
460
  return this.request("POST", "/cards", { projectId, ...data });
package/src/cli.ts CHANGED
@@ -34,9 +34,9 @@ program
34
34
  console.error("Run: npx @gethmy/mcp setup");
35
35
  process.exit(1);
36
36
  }
37
- await refreshSkills();
37
+ const { updated } = await refreshSkills();
38
38
  const server = new HarmonyMCPServer();
39
- await server.run();
39
+ await server.run({ skillsUpdated: updated });
40
40
  });
41
41
 
42
42
  program
@@ -0,0 +1,70 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+
5
+ /**
6
+ * User-facing knobs for the skill auto-update, stored at `~/.hmy/config.yaml`.
7
+ *
8
+ * This file used to be read only by the bash auto-update preamble. Now that
9
+ * the MCP server owns auto-update (refreshSkills at `serve` startup), the
10
+ * server reads it directly. We intentionally avoid a YAML dependency: the file
11
+ * is a flat `key: value` list, so a tiny line parser is enough and keeps the
12
+ * install footprint small.
13
+ */
14
+ export interface HmyConfig {
15
+ /** Master switch. `update_check: false` disables auto-update entirely. */
16
+ updateCheck: boolean;
17
+ /**
18
+ * Freeze to a specific skills version. When set, the server skips
19
+ * auto-update so the user stays on whatever is currently installed.
20
+ */
21
+ pin: string | null;
22
+ }
23
+
24
+ const DEFAULTS: HmyConfig = { updateCheck: true, pin: null };
25
+
26
+ export function getHmyConfigPath(): string {
27
+ return join(homedir(), ".hmy", "config.yaml");
28
+ }
29
+
30
+ /** Read `~/.hmy/config.yaml`, falling back to defaults on any error. */
31
+ export function loadHmyConfig(): HmyConfig {
32
+ const path = getHmyConfigPath();
33
+ if (!existsSync(path)) return { ...DEFAULTS };
34
+ try {
35
+ return parseHmyConfig(readFileSync(path, "utf-8"));
36
+ } catch {
37
+ return { ...DEFAULTS };
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Parse the flat `key: value` config body. Unknown keys are ignored;
43
+ * surrounding quotes and inline comments after a `#` are stripped. Exported
44
+ * for tests.
45
+ */
46
+ export function parseHmyConfig(text: string): HmyConfig {
47
+ const cfg: HmyConfig = { ...DEFAULTS };
48
+ for (const rawLine of text.split("\n")) {
49
+ const line = rawLine.trim();
50
+ if (!line || line.startsWith("#")) continue;
51
+ const sep = line.indexOf(":");
52
+ if (sep === -1) continue;
53
+ const key = line.slice(0, sep).trim();
54
+ let value = line.slice(sep + 1).trim();
55
+ // Drop trailing inline comment, then surrounding quotes.
56
+ const hash = value.indexOf(" #");
57
+ if (hash !== -1) value = value.slice(0, hash).trim();
58
+ value = value.replace(/^["']|["']$/g, "");
59
+ switch (key) {
60
+ case "update_check":
61
+ cfg.updateCheck = value !== "false";
62
+ break;
63
+ case "pin":
64
+ case "pin_version":
65
+ cfg.pin = value || null;
66
+ break;
67
+ }
68
+ }
69
+ return cfg;
70
+ }
package/src/server.ts CHANGED
@@ -48,6 +48,7 @@ import {
48
48
  sessionScopeFor,
49
49
  } from "./memory-session.js";
50
50
  import { onboardNewUser } from "./onboard.js";
51
+ import { stripSkillPreamble } from "./skills.js";
51
52
 
52
53
  /**
53
54
  * Dependencies injected into tool handlers.
@@ -286,6 +287,11 @@ export const TOOLS = {
286
287
  description: "Priority level",
287
288
  },
288
289
  assigneeId: { type: "string", description: "Assignee user ID" },
290
+ planId: {
291
+ type: "string",
292
+ description:
293
+ "Plan ID to link this card to (optional). Links the card to that plan via its plan_id.",
294
+ },
289
295
  },
290
296
  required: ["title"],
291
297
  },
@@ -1781,7 +1787,9 @@ export function registerHandlers(server: Server, deps: ToolDeps): void {
1781
1787
  {
1782
1788
  uri,
1783
1789
  mimeType: "text/markdown",
1784
- text: fetched.content,
1790
+ // Strip the legacy auto-update bash block if a stale render still
1791
+ // carries it — the agent shouldn't be handed curl→chmod→exec.
1792
+ text: stripSkillPreamble(fetched.content),
1785
1793
  },
1786
1794
  ],
1787
1795
  };
@@ -1863,6 +1871,7 @@ async function handleToolCall(
1863
1871
  description: args.description as string | undefined,
1864
1872
  priority: args.priority as string | undefined,
1865
1873
  assigneeId: args.assigneeId as string | undefined,
1874
+ planId: args.planId as string | undefined,
1866
1875
  });
1867
1876
  return { success: true, ...result };
1868
1877
  }
@@ -3383,17 +3392,32 @@ export class HarmonyMCPServer {
3383
3392
  constructor() {
3384
3393
  this.server = new Server(
3385
3394
  { name: "@gethmy/mcp", version: "2.0.0" },
3386
- { capabilities: { tools: {}, resources: {} } },
3395
+ // resources.listChanged lets us notify the client when a startup skill
3396
+ // refresh rewrites SKILL.md files, so it re-reads them this session.
3397
+ { capabilities: { tools: {}, resources: { listChanged: true } } },
3387
3398
  );
3388
3399
 
3389
3400
  registerHandlers(this.server, createConfigDeps());
3390
3401
  }
3391
3402
 
3392
- async run() {
3403
+ /**
3404
+ * @param opts.skillsUpdated Set when the pre-connect skill refresh
3405
+ * (cli.ts) rewrote files. Triggers a resources/list_changed notification
3406
+ * once the transport is connected so the client picks up the new skills.
3407
+ */
3408
+ async run(opts: { skillsUpdated?: boolean } = {}) {
3393
3409
  const transport = new StdioServerTransport();
3394
3410
  await this.server.connect(transport);
3395
3411
  console.error("Harmony MCP server running on stdio");
3396
3412
 
3413
+ if (opts.skillsUpdated) {
3414
+ // Client is connected now — tell it the skill resources changed.
3415
+ this.server.sendResourceListChanged().catch(() => {
3416
+ // Best-effort: a missed notification just means the new skills load
3417
+ // on the next session instead of this one.
3418
+ });
3419
+ }
3420
+
3397
3421
  // Initialize auto-session tracking with MCP client identity detection
3398
3422
  const configDeps = createConfigDeps();
3399
3423
  initAutoSession(