@memoraone/mcp 0.1.53 → 0.1.55
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 +229 -45
- package/dist/daemon.cjs +42 -10
- package/dist/gateway.cjs +14035 -0
- package/dist/index.cjs +44 -10
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -231,7 +231,7 @@ var require_package = __commonJS({
|
|
|
231
231
|
"package.json"(exports2, module2) {
|
|
232
232
|
module2.exports = {
|
|
233
233
|
name: "@memoraone/mcp",
|
|
234
|
-
version: "0.1.
|
|
234
|
+
version: "0.1.55",
|
|
235
235
|
type: "module",
|
|
236
236
|
main: "dist/index.cjs",
|
|
237
237
|
exports: {
|
|
@@ -531,7 +531,7 @@ async function acquireLocalLock(lockName, options = {}) {
|
|
|
531
531
|
`[memoraone-mcp] Failed to acquire lock ${lockName} after ${maxRetries} retries`
|
|
532
532
|
);
|
|
533
533
|
}
|
|
534
|
-
await new Promise((
|
|
534
|
+
await new Promise((resolve45) => setTimeout(resolve45, retryDelayMs));
|
|
535
535
|
continue;
|
|
536
536
|
}
|
|
537
537
|
throw err;
|
|
@@ -1092,9 +1092,9 @@ var init_memoraClient = __esm({
|
|
|
1092
1092
|
});
|
|
1093
1093
|
|
|
1094
1094
|
// src/localState/localConnectClient.ts
|
|
1095
|
-
async function requestJson(baseUrl, method,
|
|
1095
|
+
async function requestJson(baseUrl, method, path49, options = {}) {
|
|
1096
1096
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
1097
|
-
const url = `${baseUrl.replace(/\/+$/, "")}${
|
|
1097
|
+
const url = `${baseUrl.replace(/\/+$/, "")}${path49.startsWith("/") ? path49 : `/${path49}`}`;
|
|
1098
1098
|
const res = await fetchImpl(url, {
|
|
1099
1099
|
method,
|
|
1100
1100
|
headers: {
|
|
@@ -1511,7 +1511,10 @@ async function reconcileResolvedBindingWithDisk(cached, options = {}) {
|
|
|
1511
1511
|
);
|
|
1512
1512
|
}
|
|
1513
1513
|
const workspaceRoot = path10.resolve(record.workspaceRoot);
|
|
1514
|
-
const identity = await captureRootFilesystemIdentity(
|
|
1514
|
+
const identity = await captureRootFilesystemIdentity(
|
|
1515
|
+
workspaceRoot,
|
|
1516
|
+
options.identityDeps
|
|
1517
|
+
);
|
|
1515
1518
|
if (!identitiesMatch(record.filesystemIdentity, identity)) {
|
|
1516
1519
|
throw new ReconnectRequiredError(
|
|
1517
1520
|
"[memoraone-mcp] Workspace filesystem identity changed. Run: memoraone-mcp connect <code>"
|
|
@@ -3918,7 +3921,7 @@ function formatOptionalJetBrainsHandshakeUnavailableDetail(detail) {
|
|
|
3918
3921
|
async function verifyJetBrainsMcpHandshake(options) {
|
|
3919
3922
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
3920
3923
|
const { server } = options;
|
|
3921
|
-
return new Promise((
|
|
3924
|
+
return new Promise((resolve45) => {
|
|
3922
3925
|
let settled = false;
|
|
3923
3926
|
const finish = (ok, detail, optionalUnavailable) => {
|
|
3924
3927
|
if (settled) return;
|
|
@@ -3928,7 +3931,7 @@ async function verifyJetBrainsMcpHandshake(options) {
|
|
|
3928
3931
|
child.kill();
|
|
3929
3932
|
} catch {
|
|
3930
3933
|
}
|
|
3931
|
-
|
|
3934
|
+
resolve45({ ok, detail, optionalUnavailable });
|
|
3932
3935
|
};
|
|
3933
3936
|
const child = (0, import_node_child_process4.spawn)(server.command, [...server.args], {
|
|
3934
3937
|
env: { ...process.env, ...server.env },
|
|
@@ -12961,13 +12964,13 @@ function writeEvent(event, stdoutWrite) {
|
|
|
12961
12964
|
}
|
|
12962
12965
|
function delay(ms, signal) {
|
|
12963
12966
|
if (ms <= 0 || signal?.aborted) return Promise.resolve();
|
|
12964
|
-
return new Promise((
|
|
12967
|
+
return new Promise((resolve45) => {
|
|
12965
12968
|
const timer = setTimeout(finish, ms);
|
|
12966
12969
|
const onAbort = () => finish();
|
|
12967
12970
|
function finish() {
|
|
12968
12971
|
clearTimeout(timer);
|
|
12969
12972
|
signal?.removeEventListener("abort", onAbort);
|
|
12970
|
-
|
|
12973
|
+
resolve45();
|
|
12971
12974
|
}
|
|
12972
12975
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
12973
12976
|
});
|
|
@@ -13270,13 +13273,180 @@ var init_runtimeIdentityCommand = __esm({
|
|
|
13270
13273
|
}
|
|
13271
13274
|
});
|
|
13272
13275
|
|
|
13276
|
+
// src/gatewayConfig.ts
|
|
13277
|
+
function resolveGatewayPort(env2 = process.env) {
|
|
13278
|
+
const raw = env2.MEMORAONE_GATEWAY_PORT?.trim();
|
|
13279
|
+
if (!raw) return GATEWAY_PORT;
|
|
13280
|
+
const parsed2 = Number.parseInt(raw, 10);
|
|
13281
|
+
if (!Number.isInteger(parsed2) || parsed2 < 1 || parsed2 > 65535) {
|
|
13282
|
+
throw new Error(
|
|
13283
|
+
`[memoraone-mcp] Invalid MEMORAONE_GATEWAY_PORT=${JSON.stringify(raw)} (expected 1\u201365535)`
|
|
13284
|
+
);
|
|
13285
|
+
}
|
|
13286
|
+
return parsed2;
|
|
13287
|
+
}
|
|
13288
|
+
function resolveGatewayListenConfig(env2 = process.env) {
|
|
13289
|
+
return {
|
|
13290
|
+
host: GATEWAY_HOST,
|
|
13291
|
+
port: resolveGatewayPort(env2)
|
|
13292
|
+
};
|
|
13293
|
+
}
|
|
13294
|
+
function getGatewayBaseUrl(env2 = process.env) {
|
|
13295
|
+
const { host, port } = resolveGatewayListenConfig(env2);
|
|
13296
|
+
return `http://${host}:${port}`;
|
|
13297
|
+
}
|
|
13298
|
+
function getGatewayHealthUrl(env2 = process.env) {
|
|
13299
|
+
return `${getGatewayBaseUrl(env2)}${GATEWAY_HEALTH_PATH}`;
|
|
13300
|
+
}
|
|
13301
|
+
function buildGatewaySpawnArgs(scriptPath) {
|
|
13302
|
+
return [scriptPath, "--gateway"];
|
|
13303
|
+
}
|
|
13304
|
+
var path47, GATEWAY_HOST, GATEWAY_PORT, GATEWAY_LOCK_NAME, GATEWAY_HEALTH_PATH;
|
|
13305
|
+
var init_gatewayConfig = __esm({
|
|
13306
|
+
"src/gatewayConfig.ts"() {
|
|
13307
|
+
path47 = __toESM(require("path"), 1);
|
|
13308
|
+
GATEWAY_HOST = "127.0.0.1";
|
|
13309
|
+
GATEWAY_PORT = 17355;
|
|
13310
|
+
GATEWAY_LOCK_NAME = "gateway";
|
|
13311
|
+
GATEWAY_HEALTH_PATH = "/health";
|
|
13312
|
+
}
|
|
13313
|
+
});
|
|
13314
|
+
|
|
13315
|
+
// src/gatewayEnsure.ts
|
|
13316
|
+
var gatewayEnsure_exports = {};
|
|
13317
|
+
__export(gatewayEnsure_exports, {
|
|
13318
|
+
cliEnsureGateway: () => cliEnsureGateway,
|
|
13319
|
+
ensureGateway: () => ensureGateway,
|
|
13320
|
+
probeGatewayHealth: () => probeGatewayHealth
|
|
13321
|
+
});
|
|
13322
|
+
async function probeGatewayHealth(env2 = process.env) {
|
|
13323
|
+
const url = getGatewayHealthUrl(env2);
|
|
13324
|
+
try {
|
|
13325
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(750) });
|
|
13326
|
+
if (!res.ok) {
|
|
13327
|
+
return { healthy: false, reason: `HTTP ${res.status}` };
|
|
13328
|
+
}
|
|
13329
|
+
const body = await res.json();
|
|
13330
|
+
if (body?.ok !== true || typeof body.pid !== "number") {
|
|
13331
|
+
return { healthy: false, reason: "invalid health body" };
|
|
13332
|
+
}
|
|
13333
|
+
return { healthy: true, body: { ok: true, pid: body.pid } };
|
|
13334
|
+
} catch (err) {
|
|
13335
|
+
return { healthy: false, reason: String(err) };
|
|
13336
|
+
}
|
|
13337
|
+
}
|
|
13338
|
+
function defaultSpawnGateway(cliPath, env2) {
|
|
13339
|
+
return new Promise((resolve45, reject) => {
|
|
13340
|
+
let child;
|
|
13341
|
+
try {
|
|
13342
|
+
child = (0, import_node_child_process7.spawn)(process.execPath, buildGatewaySpawnArgs(cliPath), {
|
|
13343
|
+
detached: true,
|
|
13344
|
+
stdio: "ignore",
|
|
13345
|
+
env: { ...env2 }
|
|
13346
|
+
});
|
|
13347
|
+
} catch (err) {
|
|
13348
|
+
reject(err);
|
|
13349
|
+
return;
|
|
13350
|
+
}
|
|
13351
|
+
child.once("error", reject);
|
|
13352
|
+
child.unref();
|
|
13353
|
+
setImmediate(() => resolve45());
|
|
13354
|
+
});
|
|
13355
|
+
}
|
|
13356
|
+
async function waitUntilHealthy(probe, env2, waitTimeoutMs, pollIntervalMs) {
|
|
13357
|
+
const started = Date.now();
|
|
13358
|
+
let lastReason = "not started";
|
|
13359
|
+
while (Date.now() - started < waitTimeoutMs) {
|
|
13360
|
+
const result = await probe(env2);
|
|
13361
|
+
if (result.healthy) return result.body;
|
|
13362
|
+
lastReason = result.reason;
|
|
13363
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
13364
|
+
}
|
|
13365
|
+
const { host, port } = resolveGatewayListenConfig(env2);
|
|
13366
|
+
throw new Error(
|
|
13367
|
+
`[memoraone-mcp] Gateway did not become healthy on ${host}:${port} within ${waitTimeoutMs}ms (${lastReason})`
|
|
13368
|
+
);
|
|
13369
|
+
}
|
|
13370
|
+
async function ensureGateway(options = {}) {
|
|
13371
|
+
const env2 = options.env ?? process.env;
|
|
13372
|
+
const probe = options.probe ?? probeGatewayHealth;
|
|
13373
|
+
const spawnGateway = options.spawnGateway ?? defaultSpawnGateway;
|
|
13374
|
+
const waitTimeoutMs = options.waitTimeoutMs ?? 1e4;
|
|
13375
|
+
const pollIntervalMs = options.pollIntervalMs ?? 50;
|
|
13376
|
+
const listen = resolveGatewayListenConfig(env2);
|
|
13377
|
+
const lockRetryDelayMs = options.lockRetryDelayMs ?? 50;
|
|
13378
|
+
const lockMaxRetries = options.lockMaxRetries ?? Math.ceil(waitTimeoutMs / lockRetryDelayMs) + 40;
|
|
13379
|
+
const first = await probe(env2);
|
|
13380
|
+
if (first.healthy) {
|
|
13381
|
+
return { reused: true, pid: first.body.pid, listen };
|
|
13382
|
+
}
|
|
13383
|
+
return withLocalLock(
|
|
13384
|
+
GATEWAY_LOCK_NAME,
|
|
13385
|
+
async () => {
|
|
13386
|
+
const second = await probe(env2);
|
|
13387
|
+
if (second.healthy) {
|
|
13388
|
+
return { reused: true, pid: second.body.pid, listen };
|
|
13389
|
+
}
|
|
13390
|
+
const cliPath = options.cliPath ?? await resolveBuiltCliPathAsync() ?? process.argv[1];
|
|
13391
|
+
if (!cliPath) {
|
|
13392
|
+
throw new Error("[memoraone-mcp] Unable to resolve CLI path to spawn gateway");
|
|
13393
|
+
}
|
|
13394
|
+
log(`spawning gateway on ${listen.host}:${listen.port} via ${cliPath}`);
|
|
13395
|
+
await spawnGateway(cliPath, env2);
|
|
13396
|
+
const body = await waitUntilHealthy(probe, env2, waitTimeoutMs, pollIntervalMs);
|
|
13397
|
+
return { reused: false, pid: body.pid, listen };
|
|
13398
|
+
},
|
|
13399
|
+
{
|
|
13400
|
+
homeDir: options.homeDir,
|
|
13401
|
+
maxRetries: lockMaxRetries,
|
|
13402
|
+
retryDelayMs: lockRetryDelayMs,
|
|
13403
|
+
// Hold can be long while waiting for health; keep stale threshold above wait.
|
|
13404
|
+
maxLockAgeMs: Math.max(3e4, waitTimeoutMs + 5e3)
|
|
13405
|
+
}
|
|
13406
|
+
);
|
|
13407
|
+
}
|
|
13408
|
+
async function cliEnsureGateway(_argv = [], options = {}) {
|
|
13409
|
+
try {
|
|
13410
|
+
const result = await ensureGateway(options);
|
|
13411
|
+
const mode = result.reused ? "reused" : "started";
|
|
13412
|
+
process.stdout.write(
|
|
13413
|
+
`${JSON.stringify({
|
|
13414
|
+
status: "ok",
|
|
13415
|
+
mode,
|
|
13416
|
+
pid: result.pid,
|
|
13417
|
+
host: result.listen.host,
|
|
13418
|
+
port: result.listen.port
|
|
13419
|
+
})}
|
|
13420
|
+
`
|
|
13421
|
+
);
|
|
13422
|
+
return 0;
|
|
13423
|
+
} catch (err) {
|
|
13424
|
+
process.stderr.write(`[memoraone-mcp] ensure-gateway failed: ${String(err)}
|
|
13425
|
+
`);
|
|
13426
|
+
return 1;
|
|
13427
|
+
}
|
|
13428
|
+
}
|
|
13429
|
+
var import_node_child_process7, log;
|
|
13430
|
+
var init_gatewayEnsure = __esm({
|
|
13431
|
+
"src/gatewayEnsure.ts"() {
|
|
13432
|
+
import_node_child_process7 = require("child_process");
|
|
13433
|
+
init_localLocks();
|
|
13434
|
+
init_resolveBuiltCliPath();
|
|
13435
|
+
init_gatewayConfig();
|
|
13436
|
+
log = (msg) => {
|
|
13437
|
+
process.stderr.write(`[memoraone-mcp][ensure-gateway] ${msg}
|
|
13438
|
+
`);
|
|
13439
|
+
};
|
|
13440
|
+
}
|
|
13441
|
+
});
|
|
13442
|
+
|
|
13273
13443
|
// src/bridgeClientRoots.ts
|
|
13274
13444
|
function isInitializeDebugEnabled(env2 = process.env) {
|
|
13275
13445
|
return TRUTHY.has(String(env2.MEMORAONE_DEBUG_INIT ?? "").trim().toLowerCase());
|
|
13276
13446
|
}
|
|
13277
|
-
function logInitializeDebug(
|
|
13447
|
+
function logInitializeDebug(log2, env2, msg) {
|
|
13278
13448
|
if (isInitializeDebugEnabled(env2)) {
|
|
13279
|
-
|
|
13449
|
+
log2(`[init-debug] ${msg}`);
|
|
13280
13450
|
}
|
|
13281
13451
|
}
|
|
13282
13452
|
function clientDeclaresRootsCapability(params) {
|
|
@@ -13326,7 +13496,7 @@ function extractRootsUrisFromListResult(result) {
|
|
|
13326
13496
|
}
|
|
13327
13497
|
async function requestClientRootsListUris(options) {
|
|
13328
13498
|
const env2 = options.env ?? process.env;
|
|
13329
|
-
const
|
|
13499
|
+
const log2 = options.log ?? (() => {
|
|
13330
13500
|
});
|
|
13331
13501
|
const requestId = nextBridgeRequestId++;
|
|
13332
13502
|
const deferredLines = [];
|
|
@@ -13337,7 +13507,7 @@ async function requestClientRootsListUris(options) {
|
|
|
13337
13507
|
params: {}
|
|
13338
13508
|
};
|
|
13339
13509
|
logInitializeDebug(
|
|
13340
|
-
|
|
13510
|
+
log2,
|
|
13341
13511
|
env2,
|
|
13342
13512
|
`sending roots/list id=${requestId} clientDeclaresRoots=${clientDeclaresRootsCapability(options.initializeParams)}`
|
|
13343
13513
|
);
|
|
@@ -13356,12 +13526,12 @@ async function requestClientRootsListUris(options) {
|
|
|
13356
13526
|
try {
|
|
13357
13527
|
message = JSON.parse(trimmed);
|
|
13358
13528
|
} catch (err) {
|
|
13359
|
-
logInitializeDebug(
|
|
13529
|
+
logInitializeDebug(log2, env2, `ignored non-JSON line while waiting for roots/list: ${String(err)}`);
|
|
13360
13530
|
continue;
|
|
13361
13531
|
}
|
|
13362
13532
|
if (message.id !== requestId) {
|
|
13363
13533
|
logInitializeDebug(
|
|
13364
|
-
|
|
13534
|
+
log2,
|
|
13365
13535
|
env2,
|
|
13366
13536
|
`deferred JSON-RPC while waiting for roots/list id=${requestId}: ${trimmed.slice(0, 200)}`
|
|
13367
13537
|
);
|
|
@@ -13374,7 +13544,7 @@ async function requestClientRootsListUris(options) {
|
|
|
13374
13544
|
);
|
|
13375
13545
|
}
|
|
13376
13546
|
const uris = extractRootsUrisFromListResult(message.result);
|
|
13377
|
-
logInitializeDebug(
|
|
13547
|
+
logInitializeDebug(log2, env2, `roots/list id=${requestId} returned ${uris.length}: ${JSON.stringify(uris)}`);
|
|
13378
13548
|
return { uris, deferredLines };
|
|
13379
13549
|
}
|
|
13380
13550
|
}
|
|
@@ -13410,8 +13580,8 @@ var init_bridgeClientRoots = __esm({
|
|
|
13410
13580
|
if (this.closed) {
|
|
13411
13581
|
return null;
|
|
13412
13582
|
}
|
|
13413
|
-
return new Promise((
|
|
13414
|
-
this.waiters.push(
|
|
13583
|
+
return new Promise((resolve45) => {
|
|
13584
|
+
this.waiters.push(resolve45);
|
|
13415
13585
|
});
|
|
13416
13586
|
}
|
|
13417
13587
|
/** Re-queue lines read during an intermediate protocol step (e.g. roots/list) for the main bridge loop. */
|
|
@@ -13480,7 +13650,7 @@ function collectPluginStartupBindingRoots(options) {
|
|
|
13480
13650
|
if (raw === void 0 || raw === null || raw.trim() === "") {
|
|
13481
13651
|
return;
|
|
13482
13652
|
}
|
|
13483
|
-
const resolved =
|
|
13653
|
+
const resolved = path48.resolve(raw);
|
|
13484
13654
|
if (seen.has(resolved)) {
|
|
13485
13655
|
return;
|
|
13486
13656
|
}
|
|
@@ -13529,11 +13699,11 @@ async function isRetryablePluginStartupBindingError(err, options = {}) {
|
|
|
13529
13699
|
return false;
|
|
13530
13700
|
}
|
|
13531
13701
|
function defaultSleep(ms) {
|
|
13532
|
-
return new Promise((
|
|
13533
|
-
setTimeout(
|
|
13702
|
+
return new Promise((resolve45) => {
|
|
13703
|
+
setTimeout(resolve45, ms);
|
|
13534
13704
|
});
|
|
13535
13705
|
}
|
|
13536
|
-
async function waitForPluginStartupBinding(
|
|
13706
|
+
async function waitForPluginStartupBinding(resolve45, options = {}) {
|
|
13537
13707
|
const now = options.now ?? Date.now;
|
|
13538
13708
|
const sleep = options.sleep ?? defaultSleep;
|
|
13539
13709
|
const timeoutMs = options.timeoutMs ?? PLUGIN_STARTUP_BINDING_WAIT_TIMEOUT_MS;
|
|
@@ -13543,7 +13713,7 @@ async function waitForPluginStartupBinding(resolve44, options = {}) {
|
|
|
13543
13713
|
let lastError;
|
|
13544
13714
|
while (true) {
|
|
13545
13715
|
try {
|
|
13546
|
-
const binding = await
|
|
13716
|
+
const binding = await resolve45();
|
|
13547
13717
|
if (waitingLogged) {
|
|
13548
13718
|
options.log?.(
|
|
13549
13719
|
`local MemoraOne binding available after Cursor plugin pairing (${now() - startedAt}ms)`
|
|
@@ -13587,10 +13757,10 @@ async function waitForPluginStartupBinding(resolve44, options = {}) {
|
|
|
13587
13757
|
}
|
|
13588
13758
|
}
|
|
13589
13759
|
}
|
|
13590
|
-
var
|
|
13760
|
+
var path48, MEMORAONE_PLUGIN_ENV, MEMORAONE_CURSOR_PLUGIN, PLUGIN_STARTUP_BINDING_WAIT_TIMEOUT_MS, PLUGIN_STARTUP_BINDING_WAIT_INTERVAL_MS, UNBOUND_MESSAGE_MARKERS, CREDENTIALS_MISSING_MARKER, PLUGIN_STARTUP_SETUP_REQUIRED;
|
|
13591
13761
|
var init_pluginStartupBindingWait = __esm({
|
|
13592
13762
|
"src/pluginStartupBindingWait.ts"() {
|
|
13593
|
-
|
|
13763
|
+
path48 = __toESM(require("path"), 1);
|
|
13594
13764
|
init_initializeBinding();
|
|
13595
13765
|
init_bindingStore();
|
|
13596
13766
|
init_resolveLocalBinding();
|
|
@@ -13826,15 +13996,15 @@ function extractInitializeProtocolVersion(line) {
|
|
|
13826
13996
|
}
|
|
13827
13997
|
return "2024-11-05";
|
|
13828
13998
|
}
|
|
13829
|
-
function connectWithRetry(socketPath,
|
|
13830
|
-
return new Promise((
|
|
13999
|
+
function connectWithRetry(socketPath, log2, maxRetries, retryDelayMs, connect2) {
|
|
14000
|
+
return new Promise((resolve45, reject) => {
|
|
13831
14001
|
const tryConnect = (attempt) => {
|
|
13832
|
-
connect2(socketPath).then(
|
|
14002
|
+
connect2(socketPath).then(resolve45).catch((err) => {
|
|
13833
14003
|
if (attempt >= maxRetries) {
|
|
13834
14004
|
reject(err);
|
|
13835
14005
|
return;
|
|
13836
14006
|
}
|
|
13837
|
-
|
|
14007
|
+
log2(`connect attempt ${attempt + 1} failed, retrying in ${retryDelayMs}ms: ${String(err)}`);
|
|
13838
14008
|
setTimeout(() => tryConnect(attempt + 1), retryDelayMs);
|
|
13839
14009
|
});
|
|
13840
14010
|
};
|
|
@@ -13851,13 +14021,13 @@ async function resolveBridgeSessionBinding(params, env2 = process.env, options =
|
|
|
13851
14021
|
...bridgeOptions
|
|
13852
14022
|
});
|
|
13853
14023
|
}
|
|
13854
|
-
async function stopDaemonsForStaleBinding(stale, env2,
|
|
14024
|
+
async function stopDaemonsForStaleBinding(stale, env2, log2, ideTypeOverride) {
|
|
13855
14025
|
const ideType = resolveBindingIdeType(env2, ideTypeOverride);
|
|
13856
14026
|
let processes;
|
|
13857
14027
|
try {
|
|
13858
14028
|
processes = await defaultListDaemonProcesses();
|
|
13859
14029
|
} catch (err) {
|
|
13860
|
-
|
|
14030
|
+
log2(`could not list daemon processes while replacing stale binding: ${String(err)}`);
|
|
13861
14031
|
return;
|
|
13862
14032
|
}
|
|
13863
14033
|
for (const proc of processes) {
|
|
@@ -13866,11 +14036,11 @@ async function stopDaemonsForStaleBinding(stale, env2, log, ideTypeOverride) {
|
|
|
13866
14036
|
if (!matchesByBinding && !matchesByProject) continue;
|
|
13867
14037
|
try {
|
|
13868
14038
|
process.kill(proc.pid, "SIGTERM");
|
|
13869
|
-
|
|
14039
|
+
log2(
|
|
13870
14040
|
`stopped stale daemon pid=${proc.pid} binding=${stale.repositoryBindingId} project=${stale.projectId}`
|
|
13871
14041
|
);
|
|
13872
14042
|
} catch (err) {
|
|
13873
|
-
|
|
14043
|
+
log2(`failed to stop stale daemon pid=${proc.pid}: ${String(err)}`);
|
|
13874
14044
|
}
|
|
13875
14045
|
}
|
|
13876
14046
|
}
|
|
@@ -13937,14 +14107,14 @@ async function runBridgeProxy(options) {
|
|
|
13937
14107
|
ensureBaseDir();
|
|
13938
14108
|
const stdin = options.stdin ?? process.stdin;
|
|
13939
14109
|
const stdout = options.stdout ?? process.stdout;
|
|
13940
|
-
const
|
|
14110
|
+
const log2 = options.log ?? defaultLog;
|
|
13941
14111
|
const lineReader = options.lineReader ?? new StdioLineReader(stdin);
|
|
13942
14112
|
const router = new BridgeDaemonRouter({ ...options, stdout, lineReader });
|
|
13943
14113
|
try {
|
|
13944
14114
|
while (true) {
|
|
13945
14115
|
const line = await lineReader.readLine();
|
|
13946
14116
|
if (line === null) {
|
|
13947
|
-
|
|
14117
|
+
log2("stdin EOF; closing daemon socket");
|
|
13948
14118
|
break;
|
|
13949
14119
|
}
|
|
13950
14120
|
const trimmed = line.trim();
|
|
@@ -13958,7 +14128,7 @@ async function runBridgeProxy(options) {
|
|
|
13958
14128
|
throw new Error(`[memoraone-mcp] Invalid JSON-RPC on stdin: ${String(err)}`);
|
|
13959
14129
|
}
|
|
13960
14130
|
if (message.method === "initialize") {
|
|
13961
|
-
|
|
14131
|
+
log2("resolve binding from initialize request before daemon connect");
|
|
13962
14132
|
const params = message.params ?? {};
|
|
13963
14133
|
const sessionKind = await router.ensureDaemonForInitialize(params);
|
|
13964
14134
|
if (sessionKind === "setup_required") {
|
|
@@ -13976,7 +14146,7 @@ async function runBridgeProxy(options) {
|
|
|
13976
14146
|
if (!router.hasClientInitialize()) {
|
|
13977
14147
|
const method = typeof message.method === "string" && message.method.trim() !== "" ? message.method : "(unknown)";
|
|
13978
14148
|
if (message.id !== void 0 && message.id !== null) {
|
|
13979
|
-
|
|
14149
|
+
log2(
|
|
13980
14150
|
`pre-initialize request method=${method}; responding Method not found (legacy stdio probe)`
|
|
13981
14151
|
);
|
|
13982
14152
|
writePreInitializeJsonRpcError(
|
|
@@ -13985,7 +14155,7 @@ async function runBridgeProxy(options) {
|
|
|
13985
14155
|
method
|
|
13986
14156
|
);
|
|
13987
14157
|
} else {
|
|
13988
|
-
|
|
14158
|
+
log2(`ignoring pre-initialize notification method=${method}`);
|
|
13989
14159
|
}
|
|
13990
14160
|
continue;
|
|
13991
14161
|
}
|
|
@@ -13995,12 +14165,12 @@ async function runBridgeProxy(options) {
|
|
|
13995
14165
|
router.close();
|
|
13996
14166
|
}
|
|
13997
14167
|
}
|
|
13998
|
-
var net, readline4,
|
|
14168
|
+
var net, readline4, import_node_child_process8, defaultLog, JSONRPC_METHOD_NOT_FOUND, SETUP_REQUIRED_FINISH_SETUP_TOOL, BridgeDaemonRouter;
|
|
13999
14169
|
var init_bridgeProxy = __esm({
|
|
14000
14170
|
"src/bridgeProxy.ts"() {
|
|
14001
14171
|
net = __toESM(require("net"), 1);
|
|
14002
14172
|
readline4 = __toESM(require("readline"), 1);
|
|
14003
|
-
|
|
14173
|
+
import_node_child_process8 = require("child_process");
|
|
14004
14174
|
init_bindingIdentity();
|
|
14005
14175
|
init_bindingSidecar();
|
|
14006
14176
|
init_bridgeClientRoots();
|
|
@@ -14041,13 +14211,13 @@ var init_bridgeProxy = __esm({
|
|
|
14041
14211
|
this.maxRetries = options.maxRetries ?? 5;
|
|
14042
14212
|
this.retryDelayMs = options.retryDelayMs ?? 200;
|
|
14043
14213
|
this.lineReader = options.lineReader ?? null;
|
|
14044
|
-
this.connectImpl = options.connect ?? ((socketPath) => new Promise((
|
|
14045
|
-
const socket = net.connect(socketPath, () =>
|
|
14214
|
+
this.connectImpl = options.connect ?? ((socketPath) => new Promise((resolve45, reject) => {
|
|
14215
|
+
const socket = net.connect(socketPath, () => resolve45(socket));
|
|
14046
14216
|
socket.on("error", reject);
|
|
14047
14217
|
}));
|
|
14048
14218
|
this.spawnDaemonImpl = options.spawnDaemon ?? (async (binding) => {
|
|
14049
14219
|
const ideType = this.activeIdeType;
|
|
14050
|
-
const child = (0,
|
|
14220
|
+
const child = (0, import_node_child_process8.spawn)(
|
|
14051
14221
|
process.execPath,
|
|
14052
14222
|
buildDaemonSpawnArgs(this.cliPath, binding.repositoryBindingId, this.env, ideType),
|
|
14053
14223
|
{
|
|
@@ -14258,7 +14428,7 @@ var init_bridgeProxy = __esm({
|
|
|
14258
14428
|
}
|
|
14259
14429
|
waitForDaemonJsonRpcResponse(id, timeoutMs = 3e4) {
|
|
14260
14430
|
const key = this.waiterKey(id);
|
|
14261
|
-
return new Promise((
|
|
14431
|
+
return new Promise((resolve45, reject) => {
|
|
14262
14432
|
const timer = setTimeout(() => {
|
|
14263
14433
|
this.pendingDaemonResponseWaiters.delete(key);
|
|
14264
14434
|
reject(
|
|
@@ -14267,7 +14437,7 @@ var init_bridgeProxy = __esm({
|
|
|
14267
14437
|
)
|
|
14268
14438
|
);
|
|
14269
14439
|
}, timeoutMs);
|
|
14270
|
-
this.pendingDaemonResponseWaiters.set(key, { resolve:
|
|
14440
|
+
this.pendingDaemonResponseWaiters.set(key, { resolve: resolve45, reject, timer });
|
|
14271
14441
|
});
|
|
14272
14442
|
}
|
|
14273
14443
|
notifyDaemonResponseWaiters(line) {
|
|
@@ -14457,6 +14627,8 @@ if (args.includes("--help") || args.includes("-h")) {
|
|
|
14457
14627
|
memoraone-mcp connect <code> [--api-url <url>] [--verbose]
|
|
14458
14628
|
memoraone-mcp plugin-pair --workspace-root <path> --source <cursor|jetbrains> [--api-url <url>]
|
|
14459
14629
|
memoraone-mcp runtime-identity --workspace-root <path>
|
|
14630
|
+
memoraone-mcp ensure-gateway
|
|
14631
|
+
memoraone-mcp --gateway
|
|
14460
14632
|
memoraone-mcp [--daemon --binding-id <mrb_\u2026> [--ide ${IDE_TYPE_CLI_CHOICES}]]
|
|
14461
14633
|
memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains|--claude-code|--windsurf|--opencode|--codex|--kiro|--kiro-cli|--cline|--cline-cli|--claude-desktop|--zed|--visual-studio|--copilot-cli|--auggie|--antigravity|--goose|--junie|--xcode|--copilot-jetbrains|--copilot-visual-studio] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair] [--workspace-root <path>] [--api-url <url>] [--verbose]
|
|
14462
14634
|
Cursor API environment (with --cursor or --all): --local (node + built cli.cjs + local API) | --staging (npx + staging API)
|
|
@@ -14507,6 +14679,18 @@ if (args[0] === "cleanup") {
|
|
|
14507
14679
|
`);
|
|
14508
14680
|
process.exit(1);
|
|
14509
14681
|
});
|
|
14682
|
+
} else if (args[0] === "ensure-gateway") {
|
|
14683
|
+
Promise.resolve().then(() => (init_gatewayEnsure(), gatewayEnsure_exports)).then(({ cliEnsureGateway: cliEnsureGateway2 }) => cliEnsureGateway2(args.slice(1))).then((code) => process.exit(code)).catch((err) => {
|
|
14684
|
+
process.stderr.write(`[memoraone-mcp] ensure-gateway fatal: ${String(err)}
|
|
14685
|
+
`);
|
|
14686
|
+
process.exit(1);
|
|
14687
|
+
});
|
|
14688
|
+
} else if (args.includes("--gateway")) {
|
|
14689
|
+
import("./gateway.cjs").then(({ runGateway }) => runGateway()).catch((err) => {
|
|
14690
|
+
process.stderr.write(`[memoraone-mcp] gateway fatal: ${String(err)}
|
|
14691
|
+
`);
|
|
14692
|
+
process.exit(1);
|
|
14693
|
+
});
|
|
14510
14694
|
} else if (args.includes("--daemon")) {
|
|
14511
14695
|
import("./daemon.cjs").then(({ runDaemon }) => runDaemon()).catch((err) => {
|
|
14512
14696
|
process.stderr.write(`[memoraone-mcp] daemon fatal: ${String(err)}
|
package/dist/daemon.cjs
CHANGED
|
@@ -1609,7 +1609,10 @@ async function reconcileResolvedBindingWithDisk(cached, options = {}) {
|
|
|
1609
1609
|
);
|
|
1610
1610
|
}
|
|
1611
1611
|
const workspaceRoot = path10.resolve(record.workspaceRoot);
|
|
1612
|
-
const identity = await captureRootFilesystemIdentity(
|
|
1612
|
+
const identity = await captureRootFilesystemIdentity(
|
|
1613
|
+
workspaceRoot,
|
|
1614
|
+
options.identityDeps
|
|
1615
|
+
);
|
|
1613
1616
|
if (!identitiesMatch(record.filesystemIdentity, identity)) {
|
|
1614
1617
|
throw new ReconnectRequiredError(
|
|
1615
1618
|
"[memoraone-mcp] Workspace filesystem identity changed. Run: memoraone-mcp connect <code>"
|
|
@@ -1774,8 +1777,6 @@ function removeBindingSidecar(socketPath) {
|
|
|
1774
1777
|
}
|
|
1775
1778
|
|
|
1776
1779
|
// src/index.ts
|
|
1777
|
-
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
1778
|
-
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
1779
1780
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
1780
1781
|
|
|
1781
1782
|
// src/config.ts
|
|
@@ -1873,6 +1874,10 @@ var config2 = {
|
|
|
1873
1874
|
heartbeatIntervalMs: Number.parseInt(parsed.data.MEMORAONE_HEARTBEAT_INTERVAL_MS ?? "1000", 10)
|
|
1874
1875
|
};
|
|
1875
1876
|
|
|
1877
|
+
// src/memoraMcpServer.ts
|
|
1878
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
1879
|
+
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
1880
|
+
|
|
1876
1881
|
// src/initializeBinding.ts
|
|
1877
1882
|
var path13 = __toESM(require("path"), 1);
|
|
1878
1883
|
var import_node_url = require("url");
|
|
@@ -12280,7 +12285,7 @@ function inferIdeType(params, options = {}) {
|
|
|
12280
12285
|
return void 0;
|
|
12281
12286
|
}
|
|
12282
12287
|
|
|
12283
|
-
// src/
|
|
12288
|
+
// src/memoraMcpServer.ts
|
|
12284
12289
|
var notInitializedResult = {
|
|
12285
12290
|
content: [
|
|
12286
12291
|
{
|
|
@@ -12365,7 +12370,7 @@ function registerToolWithWorklog(server, runtime, sessionContext, toolName, desc
|
|
|
12365
12370
|
});
|
|
12366
12371
|
server.tool(toolName, description, schema, wrapped);
|
|
12367
12372
|
}
|
|
12368
|
-
|
|
12373
|
+
function createMemoraMcpServer(opts = {}) {
|
|
12369
12374
|
let bindingReadyResolve = null;
|
|
12370
12375
|
let bindingReadyReject = null;
|
|
12371
12376
|
const bindingReady = new Promise((resolve42, reject) => {
|
|
@@ -12398,7 +12403,10 @@ async function main(opts = {}) {
|
|
|
12398
12403
|
"[memoraone-mcp][init-debug] Workspace resolution strategy: daemonBindingHint (bridge pre-resolved, reconciled from disk)"
|
|
12399
12404
|
);
|
|
12400
12405
|
}
|
|
12401
|
-
const reconciled = await reconcileResolvedBindingWithDisk(
|
|
12406
|
+
const reconciled = await reconcileResolvedBindingWithDisk(
|
|
12407
|
+
opts.daemonBindingHint,
|
|
12408
|
+
opts.bindingResolveOptions ?? {}
|
|
12409
|
+
);
|
|
12402
12410
|
runtime.bindingCacheRefreshed = reconciled.cacheRefreshed;
|
|
12403
12411
|
if (reconciled.cacheRefreshed) {
|
|
12404
12412
|
console.error(
|
|
@@ -12851,11 +12859,35 @@ async function main(opts = {}) {
|
|
|
12851
12859
|
if (devMode) {
|
|
12852
12860
|
console.error("[memoraone-mcp] Starting MCP server with", registeredToolNames.length, "tools");
|
|
12853
12861
|
}
|
|
12854
|
-
|
|
12862
|
+
return {
|
|
12863
|
+
server,
|
|
12864
|
+
runtime,
|
|
12865
|
+
sessionContext,
|
|
12866
|
+
sessionLabel,
|
|
12867
|
+
bindingReady,
|
|
12868
|
+
getWorkspaceRoot: () => workspaceRoot
|
|
12869
|
+
};
|
|
12870
|
+
}
|
|
12871
|
+
|
|
12872
|
+
// src/index.ts
|
|
12873
|
+
async function main(opts = {}) {
|
|
12874
|
+
const {
|
|
12875
|
+
transport: customTransport,
|
|
12876
|
+
sessionSocket,
|
|
12877
|
+
...serverOpts
|
|
12878
|
+
} = opts;
|
|
12879
|
+
const {
|
|
12880
|
+
server,
|
|
12881
|
+
runtime,
|
|
12882
|
+
sessionLabel,
|
|
12883
|
+
bindingReady
|
|
12884
|
+
} = createMemoraMcpServer(serverOpts);
|
|
12885
|
+
const devMode = Boolean(config2.devMode);
|
|
12886
|
+
const transport = customTransport ?? new import_stdio.StdioServerTransport();
|
|
12855
12887
|
await server.connect(transport);
|
|
12856
12888
|
const activeClient = await bindingReady;
|
|
12857
12889
|
let ownedHeartbeat = null;
|
|
12858
|
-
const daemonSession = Boolean(
|
|
12890
|
+
const daemonSession = Boolean(sessionSocket);
|
|
12859
12891
|
if (activeClient) {
|
|
12860
12892
|
if (config2.heartbeatEnabled && daemonSession) {
|
|
12861
12893
|
console.error(
|
|
@@ -12902,9 +12934,9 @@ async function main(opts = {}) {
|
|
|
12902
12934
|
if (devMode) {
|
|
12903
12935
|
console.error("[memoraone-mcp] MCP server ready");
|
|
12904
12936
|
}
|
|
12905
|
-
if (
|
|
12937
|
+
if (sessionSocket) {
|
|
12906
12938
|
await new Promise((resolve42) => {
|
|
12907
|
-
|
|
12939
|
+
sessionSocket.once("close", () => {
|
|
12908
12940
|
shutdown("session closed", false);
|
|
12909
12941
|
resolve42();
|
|
12910
12942
|
});
|