@memoraone/mcp 0.1.39 → 0.1.40
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/cli.cjs +9811 -3314
- package/dist/daemon.cjs +116 -9
- package/dist/index.cjs +269 -162
- 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
|
|
43
|
-
var
|
|
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 =
|
|
67
|
-
if (
|
|
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(
|
|
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
|
|
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
|
|
470
|
+
var fs4 = __toESM(require("fs/promises"), 1);
|
|
350
471
|
|
|
351
472
|
// src/localState/atomicFs.ts
|
|
352
|
-
var
|
|
353
|
-
var
|
|
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
|
|
479
|
+
await fs3.mkdir(dirPath, { recursive: true, mode: STATE_DIR_MODE });
|
|
359
480
|
try {
|
|
360
|
-
await
|
|
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 =
|
|
487
|
+
const dir = path4.dirname(filePath);
|
|
367
488
|
await ensurePrivateDir(dir);
|
|
368
|
-
const tmpPath =
|
|
489
|
+
const tmpPath = path4.join(
|
|
369
490
|
dir,
|
|
370
|
-
`.${
|
|
491
|
+
`.${path4.basename(filePath)}.${process.pid}.${(0, import_node_crypto3.randomBytes)(8).toString("hex")}.tmp`
|
|
371
492
|
);
|
|
372
493
|
try {
|
|
373
|
-
await
|
|
374
|
-
await
|
|
494
|
+
await fs3.writeFile(tmpPath, content, { encoding: "utf8", mode });
|
|
495
|
+
await fs3.rename(tmpPath, filePath);
|
|
375
496
|
try {
|
|
376
|
-
await
|
|
497
|
+
await fs3.chmod(filePath, mode);
|
|
377
498
|
} catch {
|
|
378
499
|
}
|
|
379
500
|
} catch (err) {
|
|
380
501
|
try {
|
|
381
|
-
await
|
|
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
|
|
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
|
|
408
|
-
var
|
|
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 =
|
|
411
|
-
return
|
|
531
|
+
function getMemoraoneStateDir(homeDir = os2.homedir()) {
|
|
532
|
+
return path5.join(homeDir, MEMORAONE_STATE_DIRNAME);
|
|
412
533
|
}
|
|
413
|
-
function getPathIndexPath(homeDir =
|
|
414
|
-
return
|
|
534
|
+
function getPathIndexPath(homeDir = os2.homedir()) {
|
|
535
|
+
return path5.join(getMemoraoneStateDir(homeDir), "path-index.json");
|
|
415
536
|
}
|
|
416
|
-
function getBindingsDir(homeDir =
|
|
417
|
-
return
|
|
537
|
+
function getBindingsDir(homeDir = os2.homedir()) {
|
|
538
|
+
return path5.join(getMemoraoneStateDir(homeDir), "bindings");
|
|
418
539
|
}
|
|
419
|
-
function getBindingFilePath(repositoryBindingId, homeDir =
|
|
420
|
-
return
|
|
540
|
+
function getBindingFilePath(repositoryBindingId, homeDir = os2.homedir()) {
|
|
541
|
+
return path5.join(getBindingsDir(homeDir), `${repositoryBindingId}.json`);
|
|
421
542
|
}
|
|
422
|
-
function getLocksDir(homeDir =
|
|
423
|
-
return
|
|
543
|
+
function getLocksDir(homeDir = os2.homedir()) {
|
|
544
|
+
return path5.join(getMemoraoneStateDir(homeDir), "locks");
|
|
424
545
|
}
|
|
425
|
-
function getLockPath(lockName, homeDir =
|
|
426
|
-
return
|
|
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
|
|
562
|
+
const stat3 = await fs4.stat(lockPath);
|
|
442
563
|
if (Date.now() - stat3.mtimeMs > maxLockAgeMs) {
|
|
443
|
-
await
|
|
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
|
|
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
|
|
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
|
|
601
|
-
var
|
|
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 =
|
|
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
|
|
897
|
-
var
|
|
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
|
|
901
|
-
var
|
|
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
|
|
1025
|
+
var path8 = __toESM(require("path"), 1);
|
|
905
1026
|
|
|
906
1027
|
// src/localState/rootFilesystemIdentity.ts
|
|
907
|
-
var
|
|
908
|
-
var
|
|
909
|
-
var
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
974
|
-
const platform2 = deps.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
|
|
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 =
|
|
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 =
|
|
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 &&
|
|
1093
|
-
delete index.byPath[
|
|
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 =
|
|
1240
|
+
const candidate = path9.join(path9.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
|
|
1120
1241
|
try {
|
|
1121
|
-
await
|
|
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 =
|
|
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 (
|
|
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 =
|
|
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 =
|
|
1383
|
+
const candidate = path10.join(path10.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
|
|
1263
1384
|
try {
|
|
1264
|
-
await
|
|
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 =
|
|
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() &&
|
|
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 =
|
|
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
|
-
|
|
2920
|
-
|
|
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 (
|
|
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
|
|
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
|
}
|