@memoraone/mcp 0.1.39 → 0.1.41

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.
Files changed (4) hide show
  1. package/dist/cli.cjs +9811 -3314
  2. package/dist/daemon.cjs +116 -9
  3. package/dist/index.cjs +269 -162
  4. package/package.json +12 -10
package/dist/index.cjs CHANGED
@@ -39,8 +39,8 @@ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
39
39
 
40
40
  // src/config.ts
41
41
  var process2 = __toESM(require("process"), 1);
42
- var fs = __toESM(require("fs"), 1);
43
- var path = __toESM(require("path"), 1);
42
+ var fs2 = __toESM(require("fs"), 1);
43
+ var path3 = __toESM(require("path"), 1);
44
44
  var dotenv = __toESM(require("dotenv"), 1);
45
45
  var import_v4 = require("zod/v4");
46
46
 
@@ -62,9 +62,130 @@ function resolveApiUrl(env2) {
62
62
  return DEFAULT_API_URL;
63
63
  }
64
64
 
65
+ // src/socketPaths.ts
66
+ var os = __toESM(require("os"), 1);
67
+ var path2 = __toESM(require("path"), 1);
68
+ var fs = __toESM(require("fs"), 1);
69
+
70
+ // src/bindingIdentity.ts
71
+ var crypto = __toESM(require("crypto"), 1);
72
+ var path = __toESM(require("path"), 1);
73
+ var BINDING_SOCKET_HASH_LENGTH = 16;
74
+ function hashBindingIdentity(repositoryBindingId, workspaceRoot, ideType) {
75
+ const input = [
76
+ repositoryBindingId.trim(),
77
+ path.resolve(workspaceRoot),
78
+ ideType
79
+ ].join("|");
80
+ return crypto.createHash("sha256").update(input).digest("hex").slice(0, BINDING_SOCKET_HASH_LENGTH);
81
+ }
82
+ function bindingsMatch(a, b) {
83
+ const envA = a.environment ?? void 0;
84
+ const envB = b.environment ?? void 0;
85
+ return a.repositoryBindingId === b.repositoryBindingId && a.projectId.trim().toLowerCase() === b.projectId.trim().toLowerCase() && path.resolve(a.workspaceRoot) === path.resolve(b.workspaceRoot) && (a.installationPublicId ?? void 0) === (b.installationPublicId ?? void 0) && envA === envB && a.status === b.status;
86
+ }
87
+ function formatMissingInitializeWorkspaceError(options) {
88
+ const lines = [
89
+ "[memoraone-mcp] Could not resolve workspace from MCP initialize params."
90
+ ];
91
+ if (options?.rootsListAttempted) {
92
+ lines.push(
93
+ "Cursor initialize lacked workspaceFolders/rootUri; roots/list was attempted but returned no usable repo root."
94
+ );
95
+ if (options.rootsListUris && options.rootsListUris.length > 0) {
96
+ lines.push(`roots/list URIs: ${options.rootsListUris.join(", ")}`);
97
+ }
98
+ lines.push(
99
+ "Global Cursor MCP cannot safely bind per-window repos without a workspace signal from Cursor (initialize roots or roots/list)."
100
+ );
101
+ lines.push(
102
+ "Reload MCP in this Cursor window, or ensure this repo has a managed .cursor/mcp.json from setup-ide-files --cursor."
103
+ );
104
+ return lines.join("\n");
105
+ }
106
+ lines.push(
107
+ "Reload MCP in this Cursor window so initialize includes workspaceFolders, rootUri, or a usable roots/list response for this repo."
108
+ );
109
+ return lines.join("\n");
110
+ }
111
+
112
+ // src/socketPaths.ts
113
+ var BASE_DIR = process.env.MEMORAONE_MCP_LOCK_DIR || path2.join(os.homedir(), ".memoraone-mcp");
114
+ var HASH_SOCKET_FILENAME_RE = new RegExp(
115
+ `^mcp-[0-9a-f]{${BINDING_SOCKET_HASH_LENGTH}}\\.sock$`,
116
+ "i"
117
+ );
118
+ var IDE_TYPES = [
119
+ "cursor",
120
+ "copilot-vscode",
121
+ "jetbrains",
122
+ "claude-code",
123
+ "windsurf",
124
+ "opencode",
125
+ "codex",
126
+ "zed",
127
+ "kiro",
128
+ "visual-studio",
129
+ "cline",
130
+ "roo-code",
131
+ // dormant: unsupported for setup/connect
132
+ "auggie",
133
+ "continue",
134
+ // dormant: unsupported for setup/connect
135
+ "copilot-cli",
136
+ "kiro-cli",
137
+ "cline-cli",
138
+ "continue-cli",
139
+ // dormant: unsupported (no writer; wire id only)
140
+ "claude-desktop",
141
+ "gemini-cli",
142
+ // dormant: individual-user CLI unsupported; writer kept internal
143
+ "antigravity",
144
+ "antigravity-cli",
145
+ // Antigravity CLI (agy); shares MCP config with IDE; identity from clientInfo
146
+ "goose",
147
+ "junie",
148
+ "xcode",
149
+ "copilot-jetbrains",
150
+ "copilot-visual-studio"
151
+ ];
152
+ var IDE_TYPE_SET = new Set(IDE_TYPES);
153
+ var IDE_TYPE_CLI_CHOICES = IDE_TYPES.join("|");
154
+ var IDE_TYPE_ALTERNATION = [...IDE_TYPES].sort((a, b) => b.length - a.length).join("|");
155
+ var LEGACY_SOCKET_FILENAME_RE = new RegExp(
156
+ `^mcp-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:-([0-9a-f]{12}))?(?:-(${IDE_TYPE_ALTERNATION}))?\\.sock$`,
157
+ "i"
158
+ );
159
+ var IDE_FROM_COMMAND_LINE_RE = new RegExp(
160
+ `--ide\\s+(${IDE_TYPE_ALTERNATION})(?:\\s|$)`
161
+ );
162
+ function parseIdeType(value) {
163
+ if (value === void 0 || value.trim() === "" || !IDE_TYPE_SET.has(value)) {
164
+ return void 0;
165
+ }
166
+ return value;
167
+ }
168
+ function resolveIdeTypeFromEnv(env2 = process.env) {
169
+ return parseIdeType(env2.MEMORAONE_IDE_TYPE);
170
+ }
171
+ function resolveBindingIdeType(env2 = process.env, ideTypeOverride) {
172
+ if (ideTypeOverride !== void 0) {
173
+ return ideTypeOverride;
174
+ }
175
+ return resolveIdeTypeFromEnv(env2) ?? "";
176
+ }
177
+ function getBindingSocketFilename(binding, env2 = process.env, ideTypeOverride) {
178
+ const ideType = resolveBindingIdeType(env2, ideTypeOverride);
179
+ const hash = hashBindingIdentity(binding.repositoryBindingId, binding.workspaceRoot, ideType);
180
+ return `mcp-${hash}.sock`;
181
+ }
182
+ function getBindingSocketPath(binding, env2 = process.env, ideTypeOverride) {
183
+ return path2.join(BASE_DIR, getBindingSocketFilename(binding, env2, ideTypeOverride));
184
+ }
185
+
65
186
  // src/config.ts
66
- var dotenvPath = path.resolve(process2.cwd(), ".env");
67
- if (fs.existsSync(dotenvPath)) {
187
+ var dotenvPath = path3.resolve(process2.cwd(), ".env");
188
+ if (fs2.existsSync(dotenvPath)) {
68
189
  try {
69
190
  dotenv.config({ path: dotenvPath });
70
191
  } catch (err) {
@@ -78,7 +199,7 @@ var EnvSchema = import_v4.z.object({
78
199
  MEMORAONE_AGENT_NAME: import_v4.z.string().min(1).optional(),
79
200
  MEMORAONE_AGENT_TYPE: import_v4.z.string().min(1).optional(),
80
201
  MEMORAONE_SOURCE: import_v4.z.string().min(1).optional(),
81
- MEMORAONE_IDE_TYPE: import_v4.z.enum(["cursor", "copilot-vscode", "jetbrains", "claude-code", "windsurf", "opencode", "codex"]).optional(),
202
+ MEMORAONE_IDE_TYPE: import_v4.z.enum(IDE_TYPES).optional(),
82
203
  MEMORAONE_WORKLOG: import_v4.z.string().min(1).optional(),
83
204
  MEMORAONE_HEARTBEAT: import_v4.z.string().min(1).optional(),
84
205
  MEMORAONE_HEARTBEAT_INTERVAL_MS: import_v4.z.string().min(1).optional()
@@ -133,7 +254,7 @@ var config2 = {
133
254
  };
134
255
 
135
256
  // src/client/memoraClient.ts
136
- var crypto = __toESM(require("crypto"), 1);
257
+ var crypto2 = __toESM(require("crypto"), 1);
137
258
 
138
259
  // src/localState/installationCredentials.ts
139
260
  var import_node_crypto2 = require("crypto");
@@ -346,39 +467,39 @@ function hasUsableAccessToken(payload) {
346
467
  }
347
468
 
348
469
  // src/localState/localLocks.ts
349
- var fs3 = __toESM(require("fs/promises"), 1);
470
+ var fs4 = __toESM(require("fs/promises"), 1);
350
471
 
351
472
  // src/localState/atomicFs.ts
352
- var fs2 = __toESM(require("fs/promises"), 1);
353
- var path2 = __toESM(require("path"), 1);
473
+ var fs3 = __toESM(require("fs/promises"), 1);
474
+ var path4 = __toESM(require("path"), 1);
354
475
  var import_node_crypto3 = require("crypto");
355
476
  var STATE_DIR_MODE = 448;
356
477
  var STATE_FILE_MODE = 384;
357
478
  async function ensurePrivateDir(dirPath) {
358
- await fs2.mkdir(dirPath, { recursive: true, mode: STATE_DIR_MODE });
479
+ await fs3.mkdir(dirPath, { recursive: true, mode: STATE_DIR_MODE });
359
480
  try {
360
- await fs2.chmod(dirPath, STATE_DIR_MODE);
481
+ await fs3.chmod(dirPath, STATE_DIR_MODE);
361
482
  } catch {
362
483
  }
363
484
  }
364
485
  async function writeFileAtomic(filePath, content, options = {}) {
365
486
  const mode = options.mode ?? STATE_FILE_MODE;
366
- const dir = path2.dirname(filePath);
487
+ const dir = path4.dirname(filePath);
367
488
  await ensurePrivateDir(dir);
368
- const tmpPath = path2.join(
489
+ const tmpPath = path4.join(
369
490
  dir,
370
- `.${path2.basename(filePath)}.${process.pid}.${(0, import_node_crypto3.randomBytes)(8).toString("hex")}.tmp`
491
+ `.${path4.basename(filePath)}.${process.pid}.${(0, import_node_crypto3.randomBytes)(8).toString("hex")}.tmp`
371
492
  );
372
493
  try {
373
- await fs2.writeFile(tmpPath, content, { encoding: "utf8", mode });
374
- await fs2.rename(tmpPath, filePath);
494
+ await fs3.writeFile(tmpPath, content, { encoding: "utf8", mode });
495
+ await fs3.rename(tmpPath, filePath);
375
496
  try {
376
- await fs2.chmod(filePath, mode);
497
+ await fs3.chmod(filePath, mode);
377
498
  } catch {
378
499
  }
379
500
  } catch (err) {
380
501
  try {
381
- await fs2.unlink(tmpPath);
502
+ await fs3.unlink(tmpPath);
382
503
  } catch {
383
504
  }
384
505
  throw err;
@@ -386,7 +507,7 @@ async function writeFileAtomic(filePath, content, options = {}) {
386
507
  }
387
508
  async function readJsonFile(filePath) {
388
509
  try {
389
- const raw = await fs2.readFile(filePath, "utf8");
510
+ const raw = await fs3.readFile(filePath, "utf8");
390
511
  return JSON.parse(raw);
391
512
  } catch (err) {
392
513
  if (err?.code === "ENOENT") {
@@ -404,26 +525,26 @@ async function writeJsonAtomic(filePath, value, options = {}) {
404
525
  }
405
526
 
406
527
  // src/localState/statePaths.ts
407
- var os = __toESM(require("os"), 1);
408
- var path3 = __toESM(require("path"), 1);
528
+ var os2 = __toESM(require("os"), 1);
529
+ var path5 = __toESM(require("path"), 1);
409
530
  var MEMORAONE_STATE_DIRNAME = ".memoraone";
410
- function getMemoraoneStateDir(homeDir = os.homedir()) {
411
- return path3.join(homeDir, MEMORAONE_STATE_DIRNAME);
531
+ function getMemoraoneStateDir(homeDir = os2.homedir()) {
532
+ return path5.join(homeDir, MEMORAONE_STATE_DIRNAME);
412
533
  }
413
- function getPathIndexPath(homeDir = os.homedir()) {
414
- return path3.join(getMemoraoneStateDir(homeDir), "path-index.json");
534
+ function getPathIndexPath(homeDir = os2.homedir()) {
535
+ return path5.join(getMemoraoneStateDir(homeDir), "path-index.json");
415
536
  }
416
- function getBindingsDir(homeDir = os.homedir()) {
417
- return path3.join(getMemoraoneStateDir(homeDir), "bindings");
537
+ function getBindingsDir(homeDir = os2.homedir()) {
538
+ return path5.join(getMemoraoneStateDir(homeDir), "bindings");
418
539
  }
419
- function getBindingFilePath(repositoryBindingId, homeDir = os.homedir()) {
420
- return path3.join(getBindingsDir(homeDir), `${repositoryBindingId}.json`);
540
+ function getBindingFilePath(repositoryBindingId, homeDir = os2.homedir()) {
541
+ return path5.join(getBindingsDir(homeDir), `${repositoryBindingId}.json`);
421
542
  }
422
- function getLocksDir(homeDir = os.homedir()) {
423
- return path3.join(getMemoraoneStateDir(homeDir), "locks");
543
+ function getLocksDir(homeDir = os2.homedir()) {
544
+ return path5.join(getMemoraoneStateDir(homeDir), "locks");
424
545
  }
425
- function getLockPath(lockName, homeDir = os.homedir()) {
426
- return path3.join(getLocksDir(homeDir), `${lockName}.lock`);
546
+ function getLockPath(lockName, homeDir = os2.homedir()) {
547
+ return path5.join(getLocksDir(homeDir), `${lockName}.lock`);
427
548
  }
428
549
 
429
550
  // src/localState/localLocks.ts
@@ -438,16 +559,16 @@ async function acquireLocalLock(lockName, options = {}) {
438
559
  while (retries <= maxRetries) {
439
560
  try {
440
561
  try {
441
- const stat3 = await fs3.stat(lockPath);
562
+ const stat3 = await fs4.stat(lockPath);
442
563
  if (Date.now() - stat3.mtimeMs > maxLockAgeMs) {
443
- await fs3.unlink(lockPath);
564
+ await fs4.unlink(lockPath);
444
565
  }
445
566
  } catch (err) {
446
567
  if (err?.code !== "ENOENT") {
447
568
  throw err;
448
569
  }
449
570
  }
450
- const fd = await fs3.open(lockPath, "wx");
571
+ const fd = await fs4.open(lockPath, "wx");
451
572
  await fd.writeFile(
452
573
  JSON.stringify({
453
574
  pid: process.pid,
@@ -458,7 +579,7 @@ async function acquireLocalLock(lockName, options = {}) {
458
579
  await fd.close();
459
580
  return async () => {
460
581
  try {
461
- await fs3.unlink(lockPath);
582
+ await fs4.unlink(lockPath);
462
583
  } catch (err) {
463
584
  if (err?.code !== "ENOENT") {
464
585
  }
@@ -597,8 +718,8 @@ async function refreshInstallationAccessToken(options) {
597
718
  }
598
719
 
599
720
  // src/localState/bindingStore.ts
600
- var fs4 = __toESM(require("fs/promises"), 1);
601
- var path4 = __toESM(require("path"), 1);
721
+ var fs5 = __toESM(require("fs/promises"), 1);
722
+ var path6 = __toESM(require("path"), 1);
602
723
 
603
724
  // src/localState/bindingRecord.ts
604
725
  var BINDING_RECORD_VERSION = 1;
@@ -829,7 +950,7 @@ var MemoraClient = class {
829
950
  };
830
951
  }
831
952
  async perform(method, path14, body, options, retried = false) {
832
- const nonce = crypto.randomBytes(8).toString("hex");
953
+ const nonce = crypto2.randomBytes(8).toString("hex");
833
954
  const url = `${this.baseUrl}${path14.startsWith("/") ? path14 : `/${path14}`}`;
834
955
  this.resolveProjectId();
835
956
  console.error(
@@ -893,20 +1014,20 @@ var MemoraClient = class {
893
1014
  var memoraClient_default = MemoraClient;
894
1015
 
895
1016
  // src/projectBinding.ts
896
- var fs7 = __toESM(require("fs/promises"), 1);
897
- var path8 = __toESM(require("path"), 1);
1017
+ var fs8 = __toESM(require("fs/promises"), 1);
1018
+ var path10 = __toESM(require("path"), 1);
898
1019
 
899
1020
  // src/localState/resolveLocalBinding.ts
900
- var fs6 = __toESM(require("fs/promises"), 1);
901
- var path7 = __toESM(require("path"), 1);
1021
+ var fs7 = __toESM(require("fs/promises"), 1);
1022
+ var path9 = __toESM(require("path"), 1);
902
1023
 
903
1024
  // src/localState/pathIndex.ts
904
- var path6 = __toESM(require("path"), 1);
1025
+ var path8 = __toESM(require("path"), 1);
905
1026
 
906
1027
  // src/localState/rootFilesystemIdentity.ts
907
- var fs5 = __toESM(require("fs/promises"), 1);
908
- var os2 = __toESM(require("os"), 1);
909
- var path5 = __toESM(require("path"), 1);
1028
+ var fs6 = __toESM(require("fs/promises"), 1);
1029
+ var os3 = __toESM(require("os"), 1);
1030
+ var path7 = __toESM(require("path"), 1);
910
1031
  var import_node_child_process = require("child_process");
911
1032
  var import_node_util = require("util");
912
1033
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
@@ -931,13 +1052,13 @@ async function readDarwinDeviceId() {
931
1052
  }
932
1053
  async function readLinuxDeviceId() {
933
1054
  try {
934
- const content = await fs5.readFile("/etc/machine-id", "utf8");
1055
+ const content = await fs6.readFile("/etc/machine-id", "utf8");
935
1056
  const id = content.trim();
936
1057
  if (id) return id;
937
1058
  } catch {
938
1059
  }
939
1060
  try {
940
- const content = await fs5.readFile("/var/lib/dbus/machine-id", "utf8");
1061
+ const content = await fs6.readFile("/var/lib/dbus/machine-id", "utf8");
941
1062
  const id = content.trim();
942
1063
  if (id) return id;
943
1064
  } catch {
@@ -957,7 +1078,7 @@ async function readWindowsDeviceId() {
957
1078
  }
958
1079
  return match[1].trim();
959
1080
  }
960
- async function resolveDeviceId(platform2 = os2.platform()) {
1081
+ async function resolveDeviceId(platform2 = os3.platform()) {
961
1082
  if (platform2 === "darwin") return readDarwinDeviceId();
962
1083
  if (platform2 === "linux") return readLinuxDeviceId();
963
1084
  if (platform2 === "win32") return readWindowsDeviceId();
@@ -970,10 +1091,10 @@ async function resolveDeviceId(platform2 = os2.platform()) {
970
1091
  throw new Error(`[memoraone-mcp] Unsupported platform for device ID: ${platform2}`);
971
1092
  }
972
1093
  async function captureRootFilesystemIdentity(rootPath, deps = {}) {
973
- const resolved = path5.resolve(rootPath);
974
- const platform2 = deps.platform ?? os2.platform();
1094
+ const resolved = path7.resolve(rootPath);
1095
+ const platform2 = deps.platform ?? os3.platform();
975
1096
  const statRoot = deps.statRoot ?? (async (p) => {
976
- const st2 = await fs5.stat(p);
1097
+ const st2 = await fs6.stat(p);
977
1098
  return {
978
1099
  ino: st2.ino,
979
1100
  dev: st2.dev,
@@ -1057,7 +1178,7 @@ async function savePathIndex(index, homeDir) {
1057
1178
  await writeJsonAtomic(getPathIndexPath(homeDir), next);
1058
1179
  }
1059
1180
  function lookupPathIndex(index, workspaceRoot, identity) {
1060
- const resolved = path6.resolve(workspaceRoot);
1181
+ const resolved = path8.resolve(workspaceRoot);
1061
1182
  const byPathId = index.byPath[resolved];
1062
1183
  if (byPathId) {
1063
1184
  return { kind: "path", repositoryBindingId: assertRepositoryBindingId(byPathId) };
@@ -1083,14 +1204,14 @@ function lookupPathIndex(index, workspaceRoot, identity) {
1083
1204
  }
1084
1205
  async function upsertPathIndexEntry(options) {
1085
1206
  const repositoryBindingId = assertRepositoryBindingId(options.repositoryBindingId);
1086
- const resolved = path6.resolve(options.workspaceRoot);
1207
+ const resolved = path8.resolve(options.workspaceRoot);
1087
1208
  const identityKey = filesystemIdentityKey(options.identity);
1088
1209
  return withLocalLock(
1089
1210
  "path-index",
1090
1211
  async () => {
1091
1212
  const index = await loadPathIndex(options.homeDir);
1092
- if (options.previousPath && path6.resolve(options.previousPath) !== resolved) {
1093
- delete index.byPath[path6.resolve(options.previousPath)];
1213
+ if (options.previousPath && path8.resolve(options.previousPath) !== resolved) {
1214
+ delete index.byPath[path8.resolve(options.previousPath)];
1094
1215
  }
1095
1216
  for (const [p, id] of Object.entries(index.byPath)) {
1096
1217
  if (id === repositoryBindingId && p !== resolved) {
@@ -1116,16 +1237,16 @@ function identityMatchesStored(stored, current) {
1116
1237
 
1117
1238
  // src/localState/resolveLocalBinding.ts
1118
1239
  async function detectLegacyM1Warning(workspaceRoot) {
1119
- const candidate = path7.join(path7.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
1240
+ const candidate = path9.join(path9.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
1120
1241
  try {
1121
- await fs6.access(candidate);
1242
+ await fs7.access(candidate);
1122
1243
  return candidate;
1123
1244
  } catch {
1124
1245
  return void 0;
1125
1246
  }
1126
1247
  }
1127
1248
  async function ensureRepositoryBindingForRoot(workspaceRoot, options = {}) {
1128
- const resolved = path7.resolve(workspaceRoot);
1249
+ const resolved = path9.resolve(workspaceRoot);
1129
1250
  const identity = await captureRootFilesystemIdentity(resolved, options.identityDeps);
1130
1251
  const legacyM1WarningPath = await detectLegacyM1Warning(resolved);
1131
1252
  const index = await loadPathIndex(options.homeDir);
@@ -1133,7 +1254,7 @@ async function ensureRepositoryBindingForRoot(workspaceRoot, options = {}) {
1133
1254
  if (lookup.kind === "path") {
1134
1255
  const record = await readBindingRecord(lookup.repositoryBindingId, options.homeDir);
1135
1256
  if (record && identityMatchesStored(record.filesystemIdentity, identity)) {
1136
- if (path7.resolve(record.workspaceRoot) !== resolved) {
1257
+ if (path9.resolve(record.workspaceRoot) !== resolved) {
1137
1258
  const updated = {
1138
1259
  ...record,
1139
1260
  workspaceRoot: resolved,
@@ -1195,7 +1316,7 @@ async function ensureRepositoryBindingForRoot(workspaceRoot, options = {}) {
1195
1316
  };
1196
1317
  }
1197
1318
  async function resolveLocalBinding(workspaceRoot, options = {}) {
1198
- const resolved = path7.resolve(workspaceRoot);
1319
+ const resolved = path9.resolve(workspaceRoot);
1199
1320
  const { repositoryBindingId, legacyM1WarningPath } = await ensureRepositoryBindingForRoot(
1200
1321
  resolved,
1201
1322
  { ...options, createIfMissing: false }
@@ -1259,9 +1380,9 @@ function toResolvedBinding(local) {
1259
1380
  };
1260
1381
  }
1261
1382
  async function warnLegacyM1IfPresent(workspaceRoot) {
1262
- const candidate = path8.join(path8.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
1383
+ const candidate = path10.join(path10.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
1263
1384
  try {
1264
- await fs7.access(candidate);
1385
+ await fs8.access(candidate);
1265
1386
  process.stderr.write(
1266
1387
  `[memoraone-mcp] warning: ignoring legacy ${CANONICAL_M1_FILENAME} (not used for credentials or binding)
1267
1388
  `
@@ -1318,7 +1439,7 @@ function normalizeWorkspaceSearchRoots(workspaceRoot) {
1318
1439
  if (raw === void 0) continue;
1319
1440
  const trimmed = String(raw).trim();
1320
1441
  if (trimmed === "") continue;
1321
- const resolved = path8.resolve(trimmed);
1442
+ const resolved = path10.resolve(trimmed);
1322
1443
  if (!seen.has(resolved)) {
1323
1444
  seen.add(resolved);
1324
1445
  out.push(resolved);
@@ -1329,7 +1450,7 @@ function normalizeWorkspaceSearchRoots(workspaceRoot) {
1329
1450
  function bindingRelevantValuesMatch(a, b) {
1330
1451
  const envA = a.environment ?? void 0;
1331
1452
  const envB = b.environment ?? void 0;
1332
- return a.repositoryBindingId === b.repositoryBindingId && a.projectId.trim().toLowerCase() === b.projectId.trim().toLowerCase() && path8.resolve(a.workspaceRoot) === path8.resolve(b.workspaceRoot) && (a.installationPublicId ?? void 0) === (b.installationPublicId ?? void 0) && envA === envB && a.status === b.status;
1453
+ return a.repositoryBindingId === b.repositoryBindingId && a.projectId.trim().toLowerCase() === b.projectId.trim().toLowerCase() && path10.resolve(a.workspaceRoot) === path10.resolve(b.workspaceRoot) && (a.installationPublicId ?? void 0) === (b.installationPublicId ?? void 0) && envA === envB && a.status === b.status;
1333
1454
  }
1334
1455
  async function reconcileResolvedBindingWithDisk(cached) {
1335
1456
  const repositoryBindingId = assertRepositoryBindingId(cached.repositoryBindingId);
@@ -1339,7 +1460,7 @@ async function reconcileResolvedBindingWithDisk(cached) {
1339
1460
  `[memoraone-mcp] Cached binding missing for ${repositoryBindingId}. Run: memoraone-mcp connect <code>`
1340
1461
  );
1341
1462
  }
1342
- const workspaceRoot = path8.resolve(record.workspaceRoot);
1463
+ const workspaceRoot = path10.resolve(record.workspaceRoot);
1343
1464
  const identity = await captureRootFilesystemIdentity(workspaceRoot);
1344
1465
  if (!identitiesMatch(record.filesystemIdentity, identity)) {
1345
1466
  throw new ReconnectRequiredError(
@@ -1381,93 +1502,6 @@ function encodeResolvedBinding(binding) {
1381
1502
  // src/initializeBinding.ts
1382
1503
  var path11 = __toESM(require("path"), 1);
1383
1504
  var import_node_url = require("url");
1384
-
1385
- // src/bindingIdentity.ts
1386
- var crypto2 = __toESM(require("crypto"), 1);
1387
- var path9 = __toESM(require("path"), 1);
1388
- var BINDING_SOCKET_HASH_LENGTH = 16;
1389
- function hashBindingIdentity(repositoryBindingId, workspaceRoot, ideType) {
1390
- const input = [
1391
- repositoryBindingId.trim(),
1392
- path9.resolve(workspaceRoot),
1393
- ideType
1394
- ].join("|");
1395
- return crypto2.createHash("sha256").update(input).digest("hex").slice(0, BINDING_SOCKET_HASH_LENGTH);
1396
- }
1397
- function bindingsMatch(a, b) {
1398
- const envA = a.environment ?? void 0;
1399
- const envB = b.environment ?? void 0;
1400
- return a.repositoryBindingId === b.repositoryBindingId && a.projectId.trim().toLowerCase() === b.projectId.trim().toLowerCase() && path9.resolve(a.workspaceRoot) === path9.resolve(b.workspaceRoot) && (a.installationPublicId ?? void 0) === (b.installationPublicId ?? void 0) && envA === envB && a.status === b.status;
1401
- }
1402
- function formatMissingInitializeWorkspaceError(options) {
1403
- const lines = [
1404
- "[memoraone-mcp] Could not resolve workspace from MCP initialize params."
1405
- ];
1406
- if (options?.rootsListAttempted) {
1407
- lines.push(
1408
- "Cursor initialize lacked workspaceFolders/rootUri; roots/list was attempted but returned no usable repo root."
1409
- );
1410
- if (options.rootsListUris && options.rootsListUris.length > 0) {
1411
- lines.push(`roots/list URIs: ${options.rootsListUris.join(", ")}`);
1412
- }
1413
- lines.push(
1414
- "Global Cursor MCP cannot safely bind per-window repos without a workspace signal from Cursor (initialize roots or roots/list)."
1415
- );
1416
- lines.push(
1417
- "Reload MCP in this Cursor window, or ensure this repo has a managed .cursor/mcp.json from setup-ide-files --cursor."
1418
- );
1419
- return lines.join("\n");
1420
- }
1421
- lines.push(
1422
- "Reload MCP in this Cursor window so initialize includes workspaceFolders, rootUri, or a usable roots/list response for this repo."
1423
- );
1424
- return lines.join("\n");
1425
- }
1426
-
1427
- // src/socketPaths.ts
1428
- var os3 = __toESM(require("os"), 1);
1429
- var path10 = __toESM(require("path"), 1);
1430
- var fs8 = __toESM(require("fs"), 1);
1431
- var BASE_DIR = process.env.MEMORAONE_MCP_LOCK_DIR || path10.join(os3.homedir(), ".memoraone-mcp");
1432
- var HASH_SOCKET_FILENAME_RE = new RegExp(
1433
- `^mcp-[0-9a-f]{${BINDING_SOCKET_HASH_LENGTH}}\\.sock$`,
1434
- "i"
1435
- );
1436
- var IDE_TYPES = [
1437
- "cursor",
1438
- "copilot-vscode",
1439
- "jetbrains",
1440
- "claude-code",
1441
- "windsurf",
1442
- "opencode",
1443
- "codex"
1444
- ];
1445
- var IDE_TYPE_SET = new Set(IDE_TYPES);
1446
- function parseIdeType(value) {
1447
- if (value === void 0 || value.trim() === "" || !IDE_TYPE_SET.has(value)) {
1448
- return void 0;
1449
- }
1450
- return value;
1451
- }
1452
- function resolveIdeTypeFromEnv(env2 = process.env) {
1453
- return parseIdeType(env2.MEMORAONE_IDE_TYPE);
1454
- }
1455
- function resolveBindingIdeType(env2 = process.env, ideTypeOverride) {
1456
- if (ideTypeOverride !== void 0) {
1457
- return ideTypeOverride;
1458
- }
1459
- return resolveIdeTypeFromEnv(env2) ?? "";
1460
- }
1461
- function getBindingSocketFilename(binding, env2 = process.env, ideTypeOverride) {
1462
- const ideType = resolveBindingIdeType(env2, ideTypeOverride);
1463
- const hash = hashBindingIdentity(binding.repositoryBindingId, binding.workspaceRoot, ideType);
1464
- return `mcp-${hash}.sock`;
1465
- }
1466
- function getBindingSocketPath(binding, env2 = process.env, ideTypeOverride) {
1467
- return path10.join(BASE_DIR, getBindingSocketFilename(binding, env2, ideTypeOverride));
1468
- }
1469
-
1470
- // src/initializeBinding.ts
1471
1505
  var MEMORAONE_WORKSPACE_ROOT_ENV = "MEMORAONE_WORKSPACE_ROOT";
1472
1506
  function getBridgeBindingResolveOptions(env2 = process.env) {
1473
1507
  const ideType = resolveIdeTypeFromEnv(env2);
@@ -2908,6 +2942,72 @@ function createDaemonHeartbeat(opts) {
2908
2942
  }
2909
2943
 
2910
2944
  // src/ideType.ts
2945
+ var RELIABLE_CLIENT_INFO_NAMES = /* @__PURE__ */ new Map([
2946
+ // Existing
2947
+ ["claude-code", "claude-code"],
2948
+ ["devin", "windsurf"],
2949
+ ["windsurf", "windsurf"],
2950
+ // Zed
2951
+ ["zed", "zed"],
2952
+ // Kiro IDE (exact only — not generic "kiro …" mcp-remote wrappers)
2953
+ ["kiro", "kiro"],
2954
+ // Visual Studio (never Visual Studio Code)
2955
+ ["visual studio", "visual-studio"],
2956
+ ["visual-studio", "visual-studio"],
2957
+ // Cline IDE
2958
+ ["cline", "cline"],
2959
+ // Roo Code
2960
+ ["roo code", "roo-code"],
2961
+ ["roo-code", "roo-code"],
2962
+ // Auggie / Augment Code (canonical wire ID: auggie)
2963
+ ["auggie", "auggie"],
2964
+ ["augment", "auggie"],
2965
+ ["augment code", "auggie"],
2966
+ ["augment-code", "auggie"],
2967
+ // Continue IDE (not bare "continue")
2968
+ ["continue-client", "continue"],
2969
+ // Continue CLI
2970
+ ["continue-cli-client", "continue-cli"],
2971
+ ["continue-cli", "continue-cli"],
2972
+ ["continue cli", "continue-cli"],
2973
+ // Copilot CLI (not GitHub Copilot in VS Code)
2974
+ ["github-copilot-developer", "copilot-cli"],
2975
+ ["copilot-cli", "copilot-cli"],
2976
+ ["copilot cli", "copilot-cli"],
2977
+ // Kiro CLI (explicit CLI names only — not Amazon Q / Q-DEV-CLI)
2978
+ ["kiro-cli", "kiro-cli"],
2979
+ ["kiro cli", "kiro-cli"],
2980
+ // Cline CLI
2981
+ ["cline-cli", "cline-cli"],
2982
+ ["cline cli", "cline-cli"],
2983
+ // Claude Desktop (never bare "claude"; never claude-code)
2984
+ ["claude-ai", "claude-desktop"],
2985
+ ["claude-desktop", "claude-desktop"],
2986
+ ["claude desktop", "claude-desktop"],
2987
+ // Gemini CLI (not bare "gemini")
2988
+ ["gemini-cli", "gemini-cli"],
2989
+ ["gemini cli", "gemini-cli"],
2990
+ // Google Antigravity IDE vs CLI (shared MCP config; clientInfo distinguishes)
2991
+ ["antigravity", "antigravity"],
2992
+ ["antigravity ide", "antigravity"],
2993
+ ["antigravity-client", "antigravity-cli"],
2994
+ // Goose
2995
+ ["goose", "goose"],
2996
+ // JetBrains Junie (distinct from generic jetbrains / copilot-jetbrains)
2997
+ ["junie", "junie"],
2998
+ // GitHub Copilot for Xcode
2999
+ ["xcode", "xcode"],
3000
+ ["copilot-xcode", "xcode"],
3001
+ ["github-copilot-xcode", "xcode"],
3002
+ // GitHub Copilot for JetBrains (distinct from jetbrains AI Assistant)
3003
+ ["copilot-jetbrains", "copilot-jetbrains"],
3004
+ ["github-copilot-jetbrains", "copilot-jetbrains"],
3005
+ ["github copilot jetbrains", "copilot-jetbrains"],
3006
+ // GitHub Copilot in Visual Studio (distinct from visual-studio / copilot-vscode)
3007
+ ["copilot-visual-studio", "copilot-visual-studio"],
3008
+ ["github-copilot-visual-studio", "copilot-visual-studio"],
3009
+ ["github copilot visual studio", "copilot-visual-studio"]
3010
+ ]);
2911
3011
  function mapReliableClientInfoName(name) {
2912
3012
  if (typeof name !== "string") {
2913
3013
  return void 0;
@@ -2916,13 +3016,11 @@ function mapReliableClientInfoName(name) {
2916
3016
  if (normalized === "") {
2917
3017
  return void 0;
2918
3018
  }
2919
- if (normalized === "claude-code") {
2920
- return "claude-code";
2921
- }
2922
- if (normalized === "devin") {
2923
- return "windsurf";
3019
+ const exact = RELIABLE_CLIENT_INFO_NAMES.get(normalized);
3020
+ if (exact) {
3021
+ return exact;
2924
3022
  }
2925
- if (normalized === "windsurf" || /^windsurf[\s_-].+$/.test(normalized)) {
3023
+ if (/^windsurf[\s_-].+$/.test(normalized)) {
2926
3024
  return "windsurf";
2927
3025
  }
2928
3026
  return void 0;
@@ -2937,6 +3035,15 @@ function mapReliableHostIdentity(env2) {
2937
3035
  if (env2.__CFBundleIdentifier === "com.exafunction.windsurf") {
2938
3036
  return "windsurf";
2939
3037
  }
3038
+ if (env2.__CFBundleIdentifier === "com.anthropic.claudefordesktop") {
3039
+ return "claude-desktop";
3040
+ }
3041
+ if (env2.__CFBundleIdentifier === "dev.zed.Zed") {
3042
+ return "zed";
3043
+ }
3044
+ if (Object.prototype.hasOwnProperty.call(env2, "COPILOT_CLI")) {
3045
+ return "copilot-cli";
3046
+ }
2940
3047
  return void 0;
2941
3048
  }
2942
3049
  function inferIdeType(params, options = {}) {
@@ -2978,7 +3085,7 @@ function inferIdeType(params, options = {}) {
2978
3085
  if (hasJetBrainsSignals) {
2979
3086
  return "jetbrains";
2980
3087
  }
2981
- const hasVsCodeSignals = envKeys.some((key) => key.startsWith("VSCODE_")) || /(visual studio code|vscode|vs code|github copilot)/.test(clientInfoName) || /(visual studio code|vscode|vs code)/.test(argv);
3088
+ const hasVsCodeSignals = envKeys.some((key) => key.startsWith("VSCODE_")) || /(visual studio code|vscode|vs code)/.test(clientInfoName) || /(visual studio code|vscode|vs code)/.test(argv);
2982
3089
  if (hasVsCodeSignals) {
2983
3090
  return "copilot-vscode";
2984
3091
  }