@memoraone/mcp 0.1.29 → 0.1.31
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 +2060 -515
- package/dist/daemon.cjs +426 -146
- package/dist/index.cjs +371 -120
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,8 +33,6 @@ __export(index_exports, {
|
|
|
33
33
|
main: () => main
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
|
-
var path6 = __toESM(require("path"), 1);
|
|
37
|
-
var import_node_url2 = require("url");
|
|
38
36
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
39
37
|
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
40
38
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
@@ -202,12 +200,12 @@ var MemoraClient = class {
|
|
|
202
200
|
...options?.headers ?? {}
|
|
203
201
|
};
|
|
204
202
|
}
|
|
205
|
-
async post(
|
|
203
|
+
async post(path9, body, options) {
|
|
206
204
|
console.error(
|
|
207
|
-
`[memoraone-mcp][info] MemoraClient.post ENTER path=${
|
|
205
|
+
`[memoraone-mcp][info] MemoraClient.post ENTER path=${path9}`
|
|
208
206
|
);
|
|
209
207
|
const nonce = crypto.randomBytes(8).toString("hex");
|
|
210
|
-
const url = `${this.baseUrl}${
|
|
208
|
+
const url = `${this.baseUrl}${path9.startsWith("/") ? path9 : `/${path9}`}`;
|
|
211
209
|
this.resolveProjectId();
|
|
212
210
|
console.error(
|
|
213
211
|
`[memoraone-mcp][info] requestJson nonce=${nonce} stage=before_fetch method=POST url=${url}`
|
|
@@ -240,13 +238,13 @@ var MemoraClient = class {
|
|
|
240
238
|
throw new MemoraOneHttpError(res.status, res.statusText, res.text);
|
|
241
239
|
}
|
|
242
240
|
console.error(
|
|
243
|
-
`[memoraone-mcp][info] MemoraClient.post EXIT path=${
|
|
241
|
+
`[memoraone-mcp][info] MemoraClient.post EXIT path=${path9}`
|
|
244
242
|
);
|
|
245
243
|
return res.text ? JSON.parse(res.text) : null;
|
|
246
244
|
}
|
|
247
|
-
async get(
|
|
245
|
+
async get(path9, options) {
|
|
248
246
|
const nonce = crypto.randomBytes(8).toString("hex");
|
|
249
|
-
const url = `${this.baseUrl}${
|
|
247
|
+
const url = `${this.baseUrl}${path9.startsWith("/") ? path9 : `/${path9}`}`;
|
|
250
248
|
this.resolveProjectId();
|
|
251
249
|
console.error(
|
|
252
250
|
`[memoraone-mcp][info] requestJson nonce=${nonce} stage=before_fetch method=GET url=${url}`
|
|
@@ -276,9 +274,45 @@ var MemoraClient = class {
|
|
|
276
274
|
};
|
|
277
275
|
var memoraClient_default = MemoraClient;
|
|
278
276
|
|
|
277
|
+
// src/initializeBinding.ts
|
|
278
|
+
var path5 = __toESM(require("path"), 1);
|
|
279
|
+
var import_node_url = require("url");
|
|
280
|
+
|
|
281
|
+
// src/bindingIdentity.ts
|
|
282
|
+
var crypto2 = __toESM(require("crypto"), 1);
|
|
283
|
+
var path2 = __toESM(require("path"), 1);
|
|
284
|
+
var BINDING_SOCKET_HASH_LENGTH = 16;
|
|
285
|
+
function bindingsMatch(a, b) {
|
|
286
|
+
return a.projectId.trim().toLowerCase() === b.projectId.trim().toLowerCase() && path2.resolve(a.workspaceRoot) === path2.resolve(b.workspaceRoot) && path2.resolve(a.m1Path) === path2.resolve(b.m1Path);
|
|
287
|
+
}
|
|
288
|
+
function formatMissingInitializeWorkspaceError(options) {
|
|
289
|
+
const lines = [
|
|
290
|
+
"[memoraone-mcp] Could not resolve workspace from MCP initialize params."
|
|
291
|
+
];
|
|
292
|
+
if (options?.rootsListAttempted) {
|
|
293
|
+
lines.push(
|
|
294
|
+
"Cursor initialize lacked workspaceFolders/rootUri; roots/list was attempted but returned no usable repo root."
|
|
295
|
+
);
|
|
296
|
+
if (options.rootsListUris && options.rootsListUris.length > 0) {
|
|
297
|
+
lines.push(`roots/list URIs: ${options.rootsListUris.join(", ")}`);
|
|
298
|
+
}
|
|
299
|
+
lines.push(
|
|
300
|
+
"Global Cursor MCP cannot safely bind per-window repos without a workspace signal from Cursor (initialize roots or roots/list)."
|
|
301
|
+
);
|
|
302
|
+
lines.push(
|
|
303
|
+
"Reload MCP in this Cursor window, or ensure this repo has a managed .cursor/mcp.json from setup-ide-files --cursor."
|
|
304
|
+
);
|
|
305
|
+
return lines.join("\n");
|
|
306
|
+
}
|
|
307
|
+
lines.push(
|
|
308
|
+
"Reload MCP in this Cursor window so initialize includes workspaceFolders, rootUri, or a usable roots/list response for this repo."
|
|
309
|
+
);
|
|
310
|
+
return lines.join("\n");
|
|
311
|
+
}
|
|
312
|
+
|
|
279
313
|
// src/projectBinding.ts
|
|
280
314
|
var fs2 = __toESM(require("fs/promises"), 1);
|
|
281
|
-
var
|
|
315
|
+
var path3 = __toESM(require("path"), 1);
|
|
282
316
|
var uuidRegex2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
283
317
|
function normalizeEnvironment(raw) {
|
|
284
318
|
if (raw === void 0 || raw === null || typeof raw !== "string") {
|
|
@@ -311,7 +345,7 @@ async function resolveProjectIdFromExplicitM1Path() {
|
|
|
311
345
|
if (raw === void 0 || raw.trim() === "") {
|
|
312
346
|
return null;
|
|
313
347
|
}
|
|
314
|
-
const markerPath =
|
|
348
|
+
const markerPath = path3.resolve(raw);
|
|
315
349
|
try {
|
|
316
350
|
const content = await fs2.readFile(markerPath, "utf8");
|
|
317
351
|
const { projectId, apiKey, environment } = parseAndValidateM1(content, markerPath);
|
|
@@ -324,20 +358,20 @@ async function resolveProjectIdFromExplicitM1Path() {
|
|
|
324
358
|
}
|
|
325
359
|
}
|
|
326
360
|
async function findM1WalkingUp(workspaceRoot) {
|
|
327
|
-
let current =
|
|
361
|
+
let current = path3.resolve(workspaceRoot);
|
|
328
362
|
while (true) {
|
|
329
|
-
const markerPath =
|
|
363
|
+
const markerPath = path3.join(current, "memoraone.m1");
|
|
330
364
|
try {
|
|
331
365
|
const content = await fs2.readFile(markerPath, "utf8");
|
|
332
366
|
const { projectId, apiKey, environment } = parseAndValidateM1(content, markerPath);
|
|
333
|
-
const repoRoot =
|
|
367
|
+
const repoRoot = path3.dirname(markerPath);
|
|
334
368
|
return environment === void 0 ? { projectId, apiKey, repoRoot, markerPath } : { projectId, apiKey, environment, repoRoot, markerPath };
|
|
335
369
|
} catch (err) {
|
|
336
370
|
if (err?.code !== "ENOENT") {
|
|
337
371
|
throw err;
|
|
338
372
|
}
|
|
339
373
|
}
|
|
340
|
-
const parent =
|
|
374
|
+
const parent = path3.dirname(current);
|
|
341
375
|
if (parent === current) {
|
|
342
376
|
break;
|
|
343
377
|
}
|
|
@@ -360,7 +394,7 @@ function normalizeWorkspaceSearchRoots(workspaceRoot) {
|
|
|
360
394
|
if (trimmed === "") {
|
|
361
395
|
continue;
|
|
362
396
|
}
|
|
363
|
-
const resolved =
|
|
397
|
+
const resolved = path3.resolve(trimmed);
|
|
364
398
|
if (!seen.has(resolved)) {
|
|
365
399
|
seen.add(resolved);
|
|
366
400
|
out.push(resolved);
|
|
@@ -382,29 +416,33 @@ function resolveApiKeyWithSource(fileApiKey) {
|
|
|
382
416
|
}
|
|
383
417
|
return { apiKey: null, apiKeySource: "none" };
|
|
384
418
|
}
|
|
385
|
-
async function resolveAuthoritativeBinding(workspaceRoot) {
|
|
386
|
-
const
|
|
387
|
-
if (
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
419
|
+
async function resolveAuthoritativeBinding(workspaceRoot, options = {}) {
|
|
420
|
+
const respectExplicitM1Path = options.respectExplicitM1Path !== false;
|
|
421
|
+
if (respectExplicitM1Path) {
|
|
422
|
+
const explicitBinding = await resolveProjectIdFromExplicitM1Path();
|
|
423
|
+
if (explicitBinding) {
|
|
424
|
+
const resolved = resolveApiKeyWithSource(explicitBinding.apiKey);
|
|
425
|
+
return {
|
|
426
|
+
projectId: explicitBinding.projectId,
|
|
427
|
+
workspaceRoot: path3.dirname(explicitBinding.foundAt),
|
|
428
|
+
m1Path: explicitBinding.foundAt,
|
|
429
|
+
apiKey: resolved.apiKey,
|
|
430
|
+
...explicitBinding.environment !== void 0 ? { environment: explicitBinding.environment } : {},
|
|
431
|
+
bindingSource: "explicit-m1-path",
|
|
432
|
+
apiKeySource: resolved.apiKeySource
|
|
433
|
+
};
|
|
434
|
+
}
|
|
398
435
|
}
|
|
399
436
|
const candidates = normalizeWorkspaceSearchRoots(workspaceRoot);
|
|
400
437
|
if (candidates.length === 0) {
|
|
401
438
|
throw new Error("Could not find memoraone.m1 in workspace.\nOpen a folder containing memoraone.m1.");
|
|
402
439
|
}
|
|
440
|
+
const bindings = [];
|
|
403
441
|
for (const root of candidates) {
|
|
404
442
|
const binding = await findM1WalkingUp(root);
|
|
405
443
|
if (binding) {
|
|
406
444
|
const resolved = resolveApiKeyWithSource(binding.apiKey);
|
|
407
|
-
|
|
445
|
+
bindings.push({
|
|
408
446
|
projectId: binding.projectId,
|
|
409
447
|
workspaceRoot: binding.repoRoot,
|
|
410
448
|
m1Path: binding.markerPath,
|
|
@@ -412,21 +450,232 @@ async function resolveAuthoritativeBinding(workspaceRoot) {
|
|
|
412
450
|
...binding.environment !== void 0 ? { environment: binding.environment } : {},
|
|
413
451
|
bindingSource: "workspace-search",
|
|
414
452
|
apiKeySource: resolved.apiKeySource
|
|
415
|
-
};
|
|
453
|
+
});
|
|
416
454
|
}
|
|
417
455
|
}
|
|
418
|
-
|
|
456
|
+
if (bindings.length === 0) {
|
|
457
|
+
throw new Error("Could not find memoraone.m1 in workspace.\nOpen a folder containing memoraone.m1.");
|
|
458
|
+
}
|
|
459
|
+
const distinctProjectIds = new Set(bindings.map((b) => b.projectId));
|
|
460
|
+
if (distinctProjectIds.size > 1) {
|
|
461
|
+
const lines = bindings.map(
|
|
462
|
+
(b) => ` - workspace=${b.workspaceRoot} project=${b.projectId} m1=${b.m1Path}`
|
|
463
|
+
);
|
|
464
|
+
throw new Error(
|
|
465
|
+
"[memoraone-mcp] Ambiguous workspace binding: multiple open roots map to different MemoraOne projects.\n" + lines.join("\n") + "\nOpen one repo per Cursor window, or use repo-scoped .cursor/mcp.json from setup-ide-files --cursor."
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
return bindings[0];
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// src/socketPaths.ts
|
|
472
|
+
var os = __toESM(require("os"), 1);
|
|
473
|
+
var path4 = __toESM(require("path"), 1);
|
|
474
|
+
var fs3 = __toESM(require("fs"), 1);
|
|
475
|
+
var BASE_DIR = process.env.MEMORAONE_MCP_LOCK_DIR || path4.join(os.homedir(), ".memoraone-mcp");
|
|
476
|
+
var HASH_SOCKET_FILENAME_RE = new RegExp(
|
|
477
|
+
`^mcp-[0-9a-f]{${BINDING_SOCKET_HASH_LENGTH}}\\.sock$`,
|
|
478
|
+
"i"
|
|
479
|
+
);
|
|
480
|
+
var IDE_TYPES = ["cursor", "copilot-vscode", "jetbrains"];
|
|
481
|
+
var IDE_TYPE_SET = new Set(IDE_TYPES);
|
|
482
|
+
function parseIdeType(value) {
|
|
483
|
+
if (value === void 0 || value.trim() === "" || !IDE_TYPE_SET.has(value)) {
|
|
484
|
+
return void 0;
|
|
485
|
+
}
|
|
486
|
+
return value;
|
|
487
|
+
}
|
|
488
|
+
function resolveIdeTypeFromEnv(env2 = process.env) {
|
|
489
|
+
return parseIdeType(env2.MEMORAONE_IDE_TYPE);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// src/initializeBinding.ts
|
|
493
|
+
var MEMORAONE_WORKSPACE_ROOT_ENV = "MEMORAONE_WORKSPACE_ROOT";
|
|
494
|
+
function getBridgeBindingResolveOptions(env2 = process.env) {
|
|
495
|
+
const ideType = resolveIdeTypeFromEnv(env2);
|
|
496
|
+
if (ideType === "cursor") {
|
|
497
|
+
return { respectExplicitM1Path: false, allowEnvWorkspaceFallback: false };
|
|
498
|
+
}
|
|
499
|
+
return { respectExplicitM1Path: true, allowEnvWorkspaceFallback: true };
|
|
500
|
+
}
|
|
501
|
+
function uriToPath(uri) {
|
|
502
|
+
if (uri.startsWith("file://")) {
|
|
503
|
+
return (0, import_node_url.fileURLToPath)(uri);
|
|
504
|
+
}
|
|
505
|
+
return uri;
|
|
506
|
+
}
|
|
507
|
+
function getEnvWorkspaceRootCandidates() {
|
|
508
|
+
const raw = process.env.WORKSPACE_FOLDER_PATHS;
|
|
509
|
+
const parts = [];
|
|
510
|
+
if (raw !== void 0 && raw.trim() !== "") {
|
|
511
|
+
for (const p of raw.split(path5.delimiter).map((s) => s.trim()).filter(Boolean)) {
|
|
512
|
+
parts.push(path5.resolve(p));
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
parts.push(process.cwd());
|
|
516
|
+
const seen = /* @__PURE__ */ new Set();
|
|
517
|
+
const deduped = [];
|
|
518
|
+
for (const p of parts) {
|
|
519
|
+
if (!seen.has(p)) {
|
|
520
|
+
seen.add(p);
|
|
521
|
+
deduped.push(p);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return deduped;
|
|
525
|
+
}
|
|
526
|
+
function extractWorkspaceRootsFromInitialize(params) {
|
|
527
|
+
if (!params) {
|
|
528
|
+
return [];
|
|
529
|
+
}
|
|
530
|
+
const seen = /* @__PURE__ */ new Set();
|
|
531
|
+
const roots = [];
|
|
532
|
+
const addRoot = (uri) => {
|
|
533
|
+
if (uri === void 0 || uri.trim() === "") {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
const resolved = path5.resolve(uriToPath(uri));
|
|
537
|
+
if (!seen.has(resolved)) {
|
|
538
|
+
seen.add(resolved);
|
|
539
|
+
roots.push(resolved);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
if (Array.isArray(params.workspaceFolders) && params.workspaceFolders.length > 0) {
|
|
543
|
+
for (const folder of params.workspaceFolders) {
|
|
544
|
+
addRoot(folder?.uri);
|
|
545
|
+
}
|
|
546
|
+
return roots;
|
|
547
|
+
}
|
|
548
|
+
if (params.rootUri) {
|
|
549
|
+
addRoot(params.rootUri);
|
|
550
|
+
}
|
|
551
|
+
return roots;
|
|
552
|
+
}
|
|
553
|
+
function getRepoScopedWorkspaceHint(env2 = process.env) {
|
|
554
|
+
const raw = env2[MEMORAONE_WORKSPACE_ROOT_ENV];
|
|
555
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
return path5.resolve(raw.trim());
|
|
559
|
+
}
|
|
560
|
+
function formatWorkspaceAmbiguityError(bindings) {
|
|
561
|
+
const lines = bindings.map(
|
|
562
|
+
(b) => ` - workspace=${b.workspaceRoot} project=${b.projectId} m1=${b.m1Path}`
|
|
563
|
+
);
|
|
564
|
+
return "[memoraone-mcp] Ambiguous workspace binding: multiple open roots map to different MemoraOne projects.\n" + lines.join("\n") + `
|
|
565
|
+
Open one repo per Cursor window, or ensure this repo's managed .cursor/mcp.json includes ${MEMORAONE_WORKSPACE_ROOT_ENV} from setup-ide-files --cursor.`;
|
|
566
|
+
}
|
|
567
|
+
function formatRepoHintInitializeMismatchError(repoHintRoot, initializeBinding) {
|
|
568
|
+
return `[memoraone-mcp] Repo-scoped workspace hint conflicts with MCP initialize workspace.
|
|
569
|
+
${MEMORAONE_WORKSPACE_ROOT_ENV}: ${repoHintRoot}
|
|
570
|
+
initialize: project=${initializeBinding.projectId} workspace=${initializeBinding.workspaceRoot} m1=${initializeBinding.m1Path}
|
|
571
|
+
Reload MCP in the Cursor window for this repo, or re-run setup-ide-files --cursor here if the hint is stale.`;
|
|
572
|
+
}
|
|
573
|
+
function formatRepoHintNotInRootsListError(repoHintRoot, rootsListPaths) {
|
|
574
|
+
return `[memoraone-mcp] Repo-scoped workspace hint does not match any Cursor roots/list entry.
|
|
575
|
+
${MEMORAONE_WORKSPACE_ROOT_ENV}: ${repoHintRoot}
|
|
576
|
+
roots/list paths: ${rootsListPaths.join(", ")}
|
|
577
|
+
Reload MCP in the Cursor window for this repo, or re-run setup-ide-files --cursor if the hint is stale.`;
|
|
578
|
+
}
|
|
579
|
+
function formatBindingMismatchError(daemonHint, sessionBinding) {
|
|
580
|
+
return `[memoraone-mcp] Project binding mismatch between daemon and MCP initialize workspace.
|
|
581
|
+
daemon: project=${daemonHint.projectId} workspace=${daemonHint.workspaceRoot} m1=${daemonHint.m1Path}
|
|
582
|
+
initialize: project=${sessionBinding.projectId} workspace=${sessionBinding.workspaceRoot} m1=${sessionBinding.m1Path}
|
|
583
|
+
Reconnect or reload the MCP server in this IDE window so the bridge can bind to the correct project.`;
|
|
584
|
+
}
|
|
585
|
+
async function resolveBindingFromWorkspaceRoots(workspaceRoots, options = {}) {
|
|
586
|
+
if (workspaceRoots.length === 0) {
|
|
587
|
+
throw new Error("Could not find memoraone.m1 in workspace.\nOpen a folder containing memoraone.m1.");
|
|
588
|
+
}
|
|
589
|
+
const bindings = [];
|
|
590
|
+
for (const root of workspaceRoots) {
|
|
591
|
+
try {
|
|
592
|
+
bindings.push(
|
|
593
|
+
await resolveAuthoritativeBinding(root, {
|
|
594
|
+
respectExplicitM1Path: options.respectExplicitM1Path
|
|
595
|
+
})
|
|
596
|
+
);
|
|
597
|
+
} catch (err) {
|
|
598
|
+
if (err instanceof Error && err.message.includes("Could not find memoraone.m1")) {
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
throw err;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (bindings.length === 0) {
|
|
605
|
+
throw new Error("Could not find memoraone.m1 in workspace.\nOpen a folder containing memoraone.m1.");
|
|
606
|
+
}
|
|
607
|
+
const distinctProjectIds = new Set(bindings.map((b) => b.projectId));
|
|
608
|
+
if (distinctProjectIds.size > 1) {
|
|
609
|
+
throw new Error(formatWorkspaceAmbiguityError(bindings));
|
|
610
|
+
}
|
|
611
|
+
return bindings[0];
|
|
612
|
+
}
|
|
613
|
+
async function resolveBindingFromInitializeParams(params, options = {}) {
|
|
614
|
+
const env2 = options.env ?? process.env;
|
|
615
|
+
const resolveOpts = {
|
|
616
|
+
respectExplicitM1Path: options.respectExplicitM1Path,
|
|
617
|
+
allowEnvWorkspaceFallback: options.allowEnvWorkspaceFallback
|
|
618
|
+
};
|
|
619
|
+
const repoHint = getRepoScopedWorkspaceHint(env2);
|
|
620
|
+
const initializeRoots = extractWorkspaceRootsFromInitialize(params);
|
|
621
|
+
if (initializeRoots.length > 0) {
|
|
622
|
+
const binding = await resolveBindingFromWorkspaceRoots(initializeRoots, resolveOpts);
|
|
623
|
+
if (repoHint !== null) {
|
|
624
|
+
const hintBinding = await resolveAuthoritativeBinding(repoHint, {
|
|
625
|
+
respectExplicitM1Path: false
|
|
626
|
+
});
|
|
627
|
+
if (!bindingsMatch(binding, hintBinding)) {
|
|
628
|
+
throw new Error(formatRepoHintInitializeMismatchError(repoHint, binding));
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return binding;
|
|
632
|
+
}
|
|
633
|
+
const rootsListUris = options.rootsListUris ?? [];
|
|
634
|
+
const rootsListPaths = rootsListUris.map((uri) => uriToPath(uri)).filter(Boolean);
|
|
635
|
+
if (rootsListPaths.length > 1 && repoHint !== null) {
|
|
636
|
+
const hintResolved = path5.resolve(repoHint);
|
|
637
|
+
const matchingRoot = rootsListPaths.find((root) => path5.resolve(root) === hintResolved);
|
|
638
|
+
if (!matchingRoot) {
|
|
639
|
+
throw new Error(formatRepoHintNotInRootsListError(repoHint, rootsListPaths));
|
|
640
|
+
}
|
|
641
|
+
return resolveAuthoritativeBinding(repoHint, { respectExplicitM1Path: false });
|
|
642
|
+
}
|
|
643
|
+
if (rootsListPaths.length > 0) {
|
|
644
|
+
return resolveBindingFromWorkspaceRoots(rootsListPaths, resolveOpts);
|
|
645
|
+
}
|
|
646
|
+
if (repoHint !== null) {
|
|
647
|
+
return resolveAuthoritativeBinding(repoHint, { respectExplicitM1Path: false });
|
|
648
|
+
}
|
|
649
|
+
if (options.allowEnvWorkspaceFallback === false) {
|
|
650
|
+
throw new Error(
|
|
651
|
+
formatMissingInitializeWorkspaceError({
|
|
652
|
+
rootsListAttempted: options.rootsListAttempted === true,
|
|
653
|
+
rootsListUris
|
|
654
|
+
})
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
const fallbackRoots = options.fallbackWorkspaceRoots ?? getEnvWorkspaceRootCandidates();
|
|
658
|
+
return resolveAuthoritativeBinding(fallbackRoots, {
|
|
659
|
+
respectExplicitM1Path: options.respectExplicitM1Path
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// src/bridgeClientRoots.ts
|
|
664
|
+
var readline = __toESM(require("readline"), 1);
|
|
665
|
+
var TRUTHY = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
666
|
+
function isInitializeDebugEnabled(env2 = process.env) {
|
|
667
|
+
return TRUTHY.has(String(env2.MEMORAONE_DEBUG_INIT ?? "").trim().toLowerCase());
|
|
419
668
|
}
|
|
420
669
|
|
|
421
670
|
// src/sourceRegistration.ts
|
|
422
|
-
var
|
|
423
|
-
var
|
|
671
|
+
var path6 = __toESM(require("path"), 1);
|
|
672
|
+
var import_node_url2 = require("url");
|
|
424
673
|
var LOG_PREFIX = "[memoraone-mcp][source-registration]";
|
|
425
674
|
function buildRepoSourcePayload(normalizedRepoPath, ideType) {
|
|
426
675
|
const body = {
|
|
427
676
|
kind: "repo",
|
|
428
|
-
label:
|
|
429
|
-
uri: (0,
|
|
677
|
+
label: path6.basename(normalizedRepoPath),
|
|
678
|
+
uri: (0, import_node_url2.pathToFileURL)(normalizedRepoPath).href
|
|
430
679
|
};
|
|
431
680
|
if (ideType) {
|
|
432
681
|
body.metadata = {
|
|
@@ -444,7 +693,7 @@ async function registerRepoSource(client, projectId, repoPath, ideType) {
|
|
|
444
693
|
);
|
|
445
694
|
return;
|
|
446
695
|
}
|
|
447
|
-
const normalizedRepoPath =
|
|
696
|
+
const normalizedRepoPath = path6.resolve(String(repoPath));
|
|
448
697
|
const body = buildRepoSourcePayload(normalizedRepoPath, ideType);
|
|
449
698
|
const primaryPath = `/v1/projects/${projectId}/sources`;
|
|
450
699
|
const alternatePath = `/v1/projects/${projectId}/sources/register`;
|
|
@@ -604,11 +853,11 @@ var bindingStatusShape = {};
|
|
|
604
853
|
|
|
605
854
|
// src/tools/handlers/postEvent.ts
|
|
606
855
|
var import_v412 = require("zod/v4");
|
|
607
|
-
var
|
|
856
|
+
var crypto4 = __toESM(require("crypto"), 1);
|
|
608
857
|
|
|
609
858
|
// src/runContext.ts
|
|
610
859
|
var import_node_async_hooks = require("async_hooks");
|
|
611
|
-
var
|
|
860
|
+
var crypto3 = __toESM(require("crypto"), 1);
|
|
612
861
|
var sessionContextStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
613
862
|
function createSessionRunContext(initial = {}) {
|
|
614
863
|
return {
|
|
@@ -661,7 +910,7 @@ function resolveRunId(passed) {
|
|
|
661
910
|
return getCurrentRunId();
|
|
662
911
|
}
|
|
663
912
|
function generateRunId() {
|
|
664
|
-
return
|
|
913
|
+
return crypto3.randomBytes(16).toString("hex");
|
|
665
914
|
}
|
|
666
915
|
|
|
667
916
|
// src/tools/handlers/postEvent.ts
|
|
@@ -701,7 +950,7 @@ function buildPostEventContentFields(content) {
|
|
|
701
950
|
return { message: JSON.stringify(content) };
|
|
702
951
|
}
|
|
703
952
|
async function handlePostEvent(client, args) {
|
|
704
|
-
const nonce =
|
|
953
|
+
const nonce = crypto4.randomBytes(8).toString("hex");
|
|
705
954
|
console.error(
|
|
706
955
|
`[memoraone-mcp][debug] tool=memora_post_event toolCallId=unknown nonce=${nonce} stage=before_post`
|
|
707
956
|
);
|
|
@@ -856,9 +1105,9 @@ function buildPersonalContextPath(parsed2) {
|
|
|
856
1105
|
}
|
|
857
1106
|
async function handleGetPersonalContext(client, args) {
|
|
858
1107
|
const parsed2 = getPersonalContextInputSchema.parse(args ?? {});
|
|
859
|
-
const
|
|
1108
|
+
const path9 = buildPersonalContextPath(parsed2);
|
|
860
1109
|
try {
|
|
861
|
-
const result = await client.get(
|
|
1110
|
+
const result = await client.get(path9);
|
|
862
1111
|
return { ok: true, result };
|
|
863
1112
|
} catch (err) {
|
|
864
1113
|
if (err instanceof MemoraOneHttpError) {
|
|
@@ -1099,9 +1348,9 @@ async function handleListProjects(client) {
|
|
|
1099
1348
|
var import_v421 = require("zod/v4");
|
|
1100
1349
|
|
|
1101
1350
|
// src/repoFingerprint.ts
|
|
1102
|
-
var
|
|
1103
|
-
var
|
|
1104
|
-
var
|
|
1351
|
+
var fs4 = __toESM(require("fs"), 1);
|
|
1352
|
+
var path7 = __toESM(require("path"), 1);
|
|
1353
|
+
var crypto5 = __toESM(require("crypto"), 1);
|
|
1105
1354
|
var parseBooleanFlag3 = (value) => {
|
|
1106
1355
|
if (!value) {
|
|
1107
1356
|
return false;
|
|
@@ -1126,20 +1375,20 @@ var normalizeRemoteUrl = (remoteUrl) => {
|
|
|
1126
1375
|
return normalized.toLowerCase();
|
|
1127
1376
|
};
|
|
1128
1377
|
var sha256 = (value) => {
|
|
1129
|
-
return
|
|
1378
|
+
return crypto5.createHash("sha256").update(value).digest("hex");
|
|
1130
1379
|
};
|
|
1131
1380
|
var resolveGitDir = (gitPath) => {
|
|
1132
1381
|
try {
|
|
1133
|
-
const stat2 =
|
|
1382
|
+
const stat2 = fs4.statSync(gitPath);
|
|
1134
1383
|
if (stat2.isDirectory()) {
|
|
1135
1384
|
return gitPath;
|
|
1136
1385
|
}
|
|
1137
1386
|
if (stat2.isFile()) {
|
|
1138
|
-
const content =
|
|
1387
|
+
const content = fs4.readFileSync(gitPath, "utf8");
|
|
1139
1388
|
const match = content.match(/^gitdir:\s*(.+)$/m);
|
|
1140
1389
|
if (match) {
|
|
1141
1390
|
const gitDir = match[1].trim();
|
|
1142
|
-
return
|
|
1391
|
+
return path7.resolve(path7.dirname(gitPath), gitDir);
|
|
1143
1392
|
}
|
|
1144
1393
|
}
|
|
1145
1394
|
} catch {
|
|
@@ -1148,16 +1397,16 @@ var resolveGitDir = (gitPath) => {
|
|
|
1148
1397
|
return null;
|
|
1149
1398
|
};
|
|
1150
1399
|
var findGitRoot = (start) => {
|
|
1151
|
-
let current =
|
|
1400
|
+
let current = path7.resolve(start);
|
|
1152
1401
|
while (true) {
|
|
1153
|
-
const gitPath =
|
|
1154
|
-
if (
|
|
1402
|
+
const gitPath = path7.join(current, ".git");
|
|
1403
|
+
if (fs4.existsSync(gitPath)) {
|
|
1155
1404
|
const gitDir = resolveGitDir(gitPath);
|
|
1156
1405
|
if (gitDir) {
|
|
1157
1406
|
return { gitRoot: current, gitDir };
|
|
1158
1407
|
}
|
|
1159
1408
|
}
|
|
1160
|
-
const parent =
|
|
1409
|
+
const parent = path7.dirname(current);
|
|
1161
1410
|
if (parent === current) {
|
|
1162
1411
|
break;
|
|
1163
1412
|
}
|
|
@@ -1166,9 +1415,9 @@ var findGitRoot = (start) => {
|
|
|
1166
1415
|
return null;
|
|
1167
1416
|
};
|
|
1168
1417
|
var readOriginRemote = (gitDir) => {
|
|
1169
|
-
const configPath =
|
|
1418
|
+
const configPath = path7.join(gitDir, "config");
|
|
1170
1419
|
try {
|
|
1171
|
-
const content =
|
|
1420
|
+
const content = fs4.readFileSync(configPath, "utf8");
|
|
1172
1421
|
const lines = content.split(/\r?\n/);
|
|
1173
1422
|
let inOrigin = false;
|
|
1174
1423
|
for (const line of lines) {
|
|
@@ -1192,7 +1441,7 @@ var readOriginRemote = (gitDir) => {
|
|
|
1192
1441
|
function resolveRepoFingerprint(cwd2) {
|
|
1193
1442
|
const found = findGitRoot(cwd2);
|
|
1194
1443
|
if (!found) {
|
|
1195
|
-
const fallbackPath =
|
|
1444
|
+
const fallbackPath = path7.resolve(cwd2);
|
|
1196
1445
|
const fingerprint2 = sha256(fallbackPath);
|
|
1197
1446
|
debugLog(`repo fingerprint=${fingerprint2} source=path-fallback`);
|
|
1198
1447
|
return {
|
|
@@ -1214,7 +1463,7 @@ function resolveRepoFingerprint(cwd2) {
|
|
|
1214
1463
|
source: "git-remote"
|
|
1215
1464
|
};
|
|
1216
1465
|
}
|
|
1217
|
-
const fingerprint = sha256(
|
|
1466
|
+
const fingerprint = sha256(path7.resolve(gitRoot));
|
|
1218
1467
|
debugLog(`repo fingerprint=${fingerprint} source=path-fallback`);
|
|
1219
1468
|
return {
|
|
1220
1469
|
fingerprint,
|
|
@@ -1224,8 +1473,8 @@ function resolveRepoFingerprint(cwd2) {
|
|
|
1224
1473
|
}
|
|
1225
1474
|
|
|
1226
1475
|
// src/workspaceMap.ts
|
|
1227
|
-
var
|
|
1228
|
-
var
|
|
1476
|
+
var fs5 = __toESM(require("fs/promises"), 1);
|
|
1477
|
+
var path8 = __toESM(require("path"), 1);
|
|
1229
1478
|
var import_node_os = __toESM(require("os"), 1);
|
|
1230
1479
|
var parseBooleanFlag4 = (value) => {
|
|
1231
1480
|
if (!value) {
|
|
@@ -1244,11 +1493,11 @@ var debugLog2 = (message) => {
|
|
|
1244
1493
|
};
|
|
1245
1494
|
var fingerprintRegex = /^[0-9a-f]{64}$/i;
|
|
1246
1495
|
function getWorkspaceMapPath() {
|
|
1247
|
-
return
|
|
1496
|
+
return path8.join(import_node_os.default.homedir(), ".memoraone", "workspaces.json");
|
|
1248
1497
|
}
|
|
1249
1498
|
var ensureWorkspaceDir = async () => {
|
|
1250
|
-
const dir =
|
|
1251
|
-
await
|
|
1499
|
+
const dir = path8.dirname(getWorkspaceMapPath());
|
|
1500
|
+
await fs5.mkdir(dir, { recursive: true });
|
|
1252
1501
|
};
|
|
1253
1502
|
async function acquireWorkspaceMapLock() {
|
|
1254
1503
|
const filePath = getWorkspaceMapPath();
|
|
@@ -1262,10 +1511,10 @@ async function acquireWorkspaceMapLock() {
|
|
|
1262
1511
|
while (!lockAcquired && retries < maxRetries) {
|
|
1263
1512
|
try {
|
|
1264
1513
|
try {
|
|
1265
|
-
const stat2 = await
|
|
1514
|
+
const stat2 = await fs5.stat(lockPath);
|
|
1266
1515
|
const ageMs = Date.now() - stat2.mtimeMs;
|
|
1267
1516
|
if (ageMs > maxLockAgeMs) {
|
|
1268
|
-
await
|
|
1517
|
+
await fs5.unlink(lockPath);
|
|
1269
1518
|
debugLog2(`removed stale workspace map lock (age: ${ageMs}ms)`);
|
|
1270
1519
|
}
|
|
1271
1520
|
} catch (err) {
|
|
@@ -1273,14 +1522,14 @@ async function acquireWorkspaceMapLock() {
|
|
|
1273
1522
|
throw err;
|
|
1274
1523
|
}
|
|
1275
1524
|
}
|
|
1276
|
-
const fd = await
|
|
1525
|
+
const fd = await fs5.open(lockPath, "wx");
|
|
1277
1526
|
await fd.close();
|
|
1278
1527
|
lockAcquired = true;
|
|
1279
1528
|
} catch (err) {
|
|
1280
1529
|
if (err?.code === "EEXIST") {
|
|
1281
1530
|
retries++;
|
|
1282
1531
|
if (retries < maxRetries) {
|
|
1283
|
-
await new Promise((
|
|
1532
|
+
await new Promise((resolve7) => setTimeout(resolve7, retryDelayMs));
|
|
1284
1533
|
continue;
|
|
1285
1534
|
}
|
|
1286
1535
|
throw new Error(
|
|
@@ -1292,7 +1541,7 @@ async function acquireWorkspaceMapLock() {
|
|
|
1292
1541
|
}
|
|
1293
1542
|
return async () => {
|
|
1294
1543
|
try {
|
|
1295
|
-
await
|
|
1544
|
+
await fs5.unlink(lockPath);
|
|
1296
1545
|
} catch (err) {
|
|
1297
1546
|
if (err?.code !== "ENOENT") {
|
|
1298
1547
|
debugLog2(`failed to release workspace map lock: ${String(err)}`);
|
|
@@ -1348,7 +1597,7 @@ var validateWorkspaceMap = (map, filePath) => {
|
|
|
1348
1597
|
async function readWorkspaceMap() {
|
|
1349
1598
|
const filePath = getWorkspaceMapPath();
|
|
1350
1599
|
try {
|
|
1351
|
-
const content = await
|
|
1600
|
+
const content = await fs5.readFile(filePath, "utf8");
|
|
1352
1601
|
const parsed2 = JSON.parse(content);
|
|
1353
1602
|
validateWorkspaceMap(parsed2, filePath);
|
|
1354
1603
|
const typed = parsed2;
|
|
@@ -1393,8 +1642,8 @@ async function writeWorkspaceMap(map) {
|
|
|
1393
1642
|
await ensureWorkspaceDir();
|
|
1394
1643
|
const tempPath = `${filePath}.tmp`;
|
|
1395
1644
|
const content = JSON.stringify(map, null, 2);
|
|
1396
|
-
await
|
|
1397
|
-
await
|
|
1645
|
+
await fs5.writeFile(tempPath, content, "utf8");
|
|
1646
|
+
await fs5.rename(tempPath, filePath);
|
|
1398
1647
|
}
|
|
1399
1648
|
async function setProjectIdForFingerprint(args) {
|
|
1400
1649
|
const { fingerprint, projectKey, source, linked_at } = args;
|
|
@@ -1474,9 +1723,9 @@ function handleBindingStatus(binding) {
|
|
|
1474
1723
|
}
|
|
1475
1724
|
|
|
1476
1725
|
// src/heartbeat.ts
|
|
1477
|
-
var
|
|
1726
|
+
var crypto6 = __toESM(require("crypto"), 1);
|
|
1478
1727
|
function fingerprintApiKey(apiKey) {
|
|
1479
|
-
return
|
|
1728
|
+
return crypto6.createHash("sha256").update(apiKey).digest("hex").slice(0, 12);
|
|
1480
1729
|
}
|
|
1481
1730
|
function isHeartbeatDebugEnabled() {
|
|
1482
1731
|
const value = String(process.env.MEMORAONE_DEBUG_HEARTBEAT ?? "").trim().toLowerCase();
|
|
@@ -1561,21 +1810,6 @@ var notInitializedResult = {
|
|
|
1561
1810
|
]
|
|
1562
1811
|
};
|
|
1563
1812
|
var initializeDiagDumped = false;
|
|
1564
|
-
var uriToPath = (uri) => {
|
|
1565
|
-
if (uri.startsWith("file://")) {
|
|
1566
|
-
return (0, import_node_url2.fileURLToPath)(uri);
|
|
1567
|
-
}
|
|
1568
|
-
return uri;
|
|
1569
|
-
};
|
|
1570
|
-
function getCursorWorkspaceRootFromEnv() {
|
|
1571
|
-
const raw = process.env.WORKSPACE_FOLDER_PATHS;
|
|
1572
|
-
if (raw === void 0 || raw.trim() === "") {
|
|
1573
|
-
return void 0;
|
|
1574
|
-
}
|
|
1575
|
-
const parts = raw.split(path6.delimiter).map((p) => p.trim()).filter(Boolean);
|
|
1576
|
-
const first = parts[0];
|
|
1577
|
-
return first ? path6.resolve(first) : void 0;
|
|
1578
|
-
}
|
|
1579
1813
|
function redactSensitiveFields(obj) {
|
|
1580
1814
|
if (obj === null || obj === void 0) return obj;
|
|
1581
1815
|
if (typeof obj !== "object") return obj;
|
|
@@ -1654,8 +1888,8 @@ function registerToolWithWorklog(server, runtime, sessionContext, toolName, desc
|
|
|
1654
1888
|
async function main(opts = {}) {
|
|
1655
1889
|
let bindingReadyResolve = null;
|
|
1656
1890
|
let bindingReadyReject = null;
|
|
1657
|
-
const bindingReady = new Promise((
|
|
1658
|
-
bindingReadyResolve =
|
|
1891
|
+
const bindingReady = new Promise((resolve7, reject) => {
|
|
1892
|
+
bindingReadyResolve = resolve7;
|
|
1659
1893
|
bindingReadyReject = reject;
|
|
1660
1894
|
});
|
|
1661
1895
|
const devMode = Boolean(config2.devMode);
|
|
@@ -1666,7 +1900,7 @@ async function main(opts = {}) {
|
|
|
1666
1900
|
projectId: null,
|
|
1667
1901
|
apiKeySource: null,
|
|
1668
1902
|
apiKeyFingerprint: null,
|
|
1669
|
-
authoritativeBinding:
|
|
1903
|
+
authoritativeBinding: null,
|
|
1670
1904
|
ideType: void 0
|
|
1671
1905
|
};
|
|
1672
1906
|
let workspaceRoot;
|
|
@@ -1674,42 +1908,53 @@ async function main(opts = {}) {
|
|
|
1674
1908
|
name: "memoraone-mcp",
|
|
1675
1909
|
version: "1.0.0"
|
|
1676
1910
|
});
|
|
1677
|
-
const
|
|
1678
|
-
|
|
1911
|
+
const resolveSessionBindingFromInitialize = async (params) => {
|
|
1912
|
+
const initializeRoots = extractWorkspaceRootsFromInitialize(params);
|
|
1913
|
+
if (initializeRoots.length === 0 && opts.daemonBindingHint) {
|
|
1914
|
+
if (isInitializeDebugEnabled()) {
|
|
1915
|
+
console.error(
|
|
1916
|
+
"[memoraone-mcp][init-debug] Workspace resolution strategy: daemonBindingHint (bridge pre-resolved)"
|
|
1917
|
+
);
|
|
1918
|
+
}
|
|
1919
|
+
return opts.daemonBindingHint;
|
|
1920
|
+
}
|
|
1921
|
+
let rootsListUris;
|
|
1922
|
+
let rootsListAttempted = false;
|
|
1679
1923
|
try {
|
|
1680
1924
|
const rootsResult = await server.server.listRoots({});
|
|
1925
|
+
rootsListAttempted = true;
|
|
1681
1926
|
const roots = Array.isArray(rootsResult?.roots) ? rootsResult.roots : [];
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1927
|
+
if (isInitializeDebugEnabled()) {
|
|
1928
|
+
console.error(`[memoraone-mcp][init-debug] roots/list returned ${roots.length}: ${JSON.stringify(roots)}`);
|
|
1929
|
+
}
|
|
1930
|
+
if (roots.length > 0) {
|
|
1931
|
+
rootsListUris = roots.map((root) => root?.uri).filter((uri) => Boolean(uri));
|
|
1932
|
+
if (rootsListUris.length > 0 && isInitializeDebugEnabled()) {
|
|
1933
|
+
console.error("[memoraone-mcp][init-debug] Workspace resolution strategy: roots/list");
|
|
1934
|
+
}
|
|
1686
1935
|
}
|
|
1687
1936
|
} catch (e) {
|
|
1688
|
-
|
|
1937
|
+
if (isInitializeDebugEnabled()) {
|
|
1938
|
+
console.error("[memoraone-mcp][init-debug] roots/list failed:", String(e));
|
|
1939
|
+
}
|
|
1689
1940
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1941
|
+
if (isInitializeDebugEnabled()) {
|
|
1942
|
+
console.error(`[memoraone-mcp][init-debug] process.cwd(): ${process.cwd()}`);
|
|
1943
|
+
console.error(
|
|
1944
|
+
`[memoraone-mcp][init-debug] WORKSPACE_FOLDER_PATHS: ${process.env.WORKSPACE_FOLDER_PATHS ?? "(unset)"}`
|
|
1945
|
+
);
|
|
1695
1946
|
if (params.workspaceFolders?.length) {
|
|
1696
|
-
|
|
1697
|
-
console.error("[memoraone-mcp] Workspace resolution strategy: initialize.workspaceFolders");
|
|
1947
|
+
console.error("[memoraone-mcp][init-debug] Workspace resolution strategy: initialize.workspaceFolders");
|
|
1698
1948
|
} else if (params.rootUri) {
|
|
1699
|
-
|
|
1700
|
-
console.error("[memoraone-mcp] Workspace resolution strategy: initialize.rootUri");
|
|
1701
|
-
} else {
|
|
1702
|
-
const cursorRoot = getCursorWorkspaceRootFromEnv();
|
|
1703
|
-
if (cursorRoot !== void 0) {
|
|
1704
|
-
fallbackWorkspaceRoot = cursorRoot;
|
|
1705
|
-
console.error("[memoraone-mcp] Workspace resolution strategy: env.WORKSPACE_FOLDER_PATHS");
|
|
1706
|
-
} else {
|
|
1707
|
-
fallbackWorkspaceRoot = process.cwd();
|
|
1708
|
-
console.error("[memoraone-mcp] Workspace resolution strategy: process.cwd() fallback");
|
|
1709
|
-
}
|
|
1949
|
+
console.error("[memoraone-mcp][init-debug] Workspace resolution strategy: initialize.rootUri");
|
|
1710
1950
|
}
|
|
1711
1951
|
}
|
|
1712
|
-
const binding = await
|
|
1952
|
+
const binding = await resolveBindingFromInitializeParams(params, {
|
|
1953
|
+
fallbackWorkspaceRoots: getEnvWorkspaceRootCandidates(),
|
|
1954
|
+
rootsListUris,
|
|
1955
|
+
rootsListAttempted,
|
|
1956
|
+
...getBridgeBindingResolveOptions()
|
|
1957
|
+
});
|
|
1713
1958
|
workspaceRoot = binding.workspaceRoot;
|
|
1714
1959
|
return binding;
|
|
1715
1960
|
};
|
|
@@ -1889,7 +2134,7 @@ async function main(opts = {}) {
|
|
|
1889
2134
|
if (runtime.ideType && opts.onSessionIdeTypeKnown) {
|
|
1890
2135
|
opts.onSessionIdeTypeKnown(runtime.ideType);
|
|
1891
2136
|
}
|
|
1892
|
-
if (!initializeDiagDumped) {
|
|
2137
|
+
if (isInitializeDebugEnabled() && !initializeDiagDumped) {
|
|
1893
2138
|
initializeDiagDumped = true;
|
|
1894
2139
|
const folders = Array.isArray(params.workspaceFolders) ? params.workspaceFolders.map((f) => ({ name: f?.name, uri: f?.uri })) : params.workspaceFolders;
|
|
1895
2140
|
const capKeys = params.capabilities && typeof params.capabilities === "object" ? Object.keys(params.capabilities) : [];
|
|
@@ -1921,7 +2166,13 @@ async function main(opts = {}) {
|
|
|
1921
2166
|
String(process.env.MEMORAONE_DEBUG_AUTH ?? "").trim().toLowerCase()
|
|
1922
2167
|
);
|
|
1923
2168
|
const debugLog3 = config2.devMode || debugAuth;
|
|
1924
|
-
const binding =
|
|
2169
|
+
const binding = await resolveSessionBindingFromInitialize(params);
|
|
2170
|
+
if (opts.daemonBindingHint && !bindingsMatch(opts.daemonBindingHint, binding)) {
|
|
2171
|
+
const errMsg = formatBindingMismatchError(opts.daemonBindingHint, binding);
|
|
2172
|
+
console.error(`[memoraone-mcp][ERROR] ${errMsg}`);
|
|
2173
|
+
bindingReadyReject?.(new Error(errMsg));
|
|
2174
|
+
throw new Error(errMsg);
|
|
2175
|
+
}
|
|
1925
2176
|
const apiKeyToUse = binding.apiKey;
|
|
1926
2177
|
if (!apiKeyToUse) {
|
|
1927
2178
|
throw new Error(
|
|
@@ -2045,10 +2296,10 @@ async function main(opts = {}) {
|
|
|
2045
2296
|
console.error("[memoraone-mcp] MCP server ready");
|
|
2046
2297
|
}
|
|
2047
2298
|
if (opts.sessionSocket) {
|
|
2048
|
-
await new Promise((
|
|
2299
|
+
await new Promise((resolve7) => {
|
|
2049
2300
|
opts.sessionSocket.once("close", () => {
|
|
2050
2301
|
shutdown("session closed", false);
|
|
2051
|
-
|
|
2302
|
+
resolve7();
|
|
2052
2303
|
});
|
|
2053
2304
|
});
|
|
2054
2305
|
}
|