@memoraone/mcp 0.1.47 → 0.1.49
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 +440 -314
- package/dist/daemon.cjs +223 -84
- package/dist/index.cjs +212 -73
- package/dist/pluginPairing.cjs +223 -254
- package/package.json +1 -1
package/dist/daemon.cjs
CHANGED
|
@@ -32,7 +32,7 @@ __export(daemon_exports, {
|
|
|
32
32
|
runDaemon: () => runDaemon
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(daemon_exports);
|
|
35
|
-
var
|
|
35
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
36
36
|
var net = __toESM(require("net"), 1);
|
|
37
37
|
var import_stdio2 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
38
38
|
|
|
@@ -169,11 +169,9 @@ function ensureBaseDir() {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// src/projectBinding.ts
|
|
172
|
-
var fs7 = __toESM(require("fs/promises"), 1);
|
|
173
172
|
var path10 = __toESM(require("path"), 1);
|
|
174
173
|
|
|
175
174
|
// src/localState/resolveLocalBinding.ts
|
|
176
|
-
var fs6 = __toESM(require("fs/promises"), 1);
|
|
177
175
|
var path9 = __toESM(require("path"), 1);
|
|
178
176
|
|
|
179
177
|
// src/localState/bindingStore.ts
|
|
@@ -416,7 +414,7 @@ async function acquireLocalLock(lockName, options = {}) {
|
|
|
416
414
|
`[memoraone-mcp] Failed to acquire lock ${lockName} after ${maxRetries} retries`
|
|
417
415
|
);
|
|
418
416
|
}
|
|
419
|
-
await new Promise((
|
|
417
|
+
await new Promise((resolve11) => setTimeout(resolve11, retryDelayMs));
|
|
420
418
|
continue;
|
|
421
419
|
}
|
|
422
420
|
throw err;
|
|
@@ -980,9 +978,9 @@ var MemoraClient = class {
|
|
|
980
978
|
...options?.headers ?? {}
|
|
981
979
|
};
|
|
982
980
|
}
|
|
983
|
-
async perform(method,
|
|
981
|
+
async perform(method, path16, body, options, retried = false) {
|
|
984
982
|
const nonce = crypto2.randomBytes(8).toString("hex");
|
|
985
|
-
const url = `${this.baseUrl}${
|
|
983
|
+
const url = `${this.baseUrl}${path16.startsWith("/") ? path16 : `/${path16}`}`;
|
|
986
984
|
this.resolveProjectId();
|
|
987
985
|
console.error(
|
|
988
986
|
`[memoraone-mcp][info] requestJson nonce=${nonce} stage=before_fetch method=${method} url=${url}`
|
|
@@ -1009,7 +1007,7 @@ var MemoraClient = class {
|
|
|
1009
1007
|
if (res.status === 401 && !options?.skipAuthRefresh && !retried) {
|
|
1010
1008
|
try {
|
|
1011
1009
|
await this.refreshAccessToken();
|
|
1012
|
-
return this.perform(method,
|
|
1010
|
+
return this.perform(method, path16, body, options, true);
|
|
1013
1011
|
} catch (err) {
|
|
1014
1012
|
if (err instanceof ReconnectRequiredError) {
|
|
1015
1013
|
await this.markReconnectRequired();
|
|
@@ -1029,22 +1027,22 @@ var MemoraClient = class {
|
|
|
1029
1027
|
}
|
|
1030
1028
|
return res.text ? JSON.parse(res.text) : null;
|
|
1031
1029
|
}
|
|
1032
|
-
async post(
|
|
1033
|
-
console.error(`[memoraone-mcp][info] MemoraClient.post ENTER path=${
|
|
1034
|
-
const result = await this.perform("POST",
|
|
1035
|
-
console.error(`[memoraone-mcp][info] MemoraClient.post EXIT path=${
|
|
1030
|
+
async post(path16, body, options) {
|
|
1031
|
+
console.error(`[memoraone-mcp][info] MemoraClient.post ENTER path=${path16}`);
|
|
1032
|
+
const result = await this.perform("POST", path16, body, options);
|
|
1033
|
+
console.error(`[memoraone-mcp][info] MemoraClient.post EXIT path=${path16}`);
|
|
1036
1034
|
return result;
|
|
1037
1035
|
}
|
|
1038
|
-
async get(
|
|
1039
|
-
return this.perform("GET",
|
|
1036
|
+
async get(path16, options) {
|
|
1037
|
+
return this.perform("GET", path16, void 0, options);
|
|
1040
1038
|
}
|
|
1041
1039
|
};
|
|
1042
1040
|
var memoraClient_default = MemoraClient;
|
|
1043
1041
|
|
|
1044
1042
|
// src/localState/localConnectClient.ts
|
|
1045
|
-
async function requestJson2(baseUrl, method,
|
|
1043
|
+
async function requestJson2(baseUrl, method, path16, options = {}) {
|
|
1046
1044
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
1047
|
-
const url = `${baseUrl.replace(/\/+$/, "")}${
|
|
1045
|
+
const url = `${baseUrl.replace(/\/+$/, "")}${path16.startsWith("/") ? path16 : `/${path16}`}`;
|
|
1048
1046
|
const res = await fetchImpl(url, {
|
|
1049
1047
|
method,
|
|
1050
1048
|
headers: {
|
|
@@ -1149,19 +1147,9 @@ async function refreshInstallationAccessToken(options) {
|
|
|
1149
1147
|
}
|
|
1150
1148
|
|
|
1151
1149
|
// src/localState/resolveLocalBinding.ts
|
|
1152
|
-
async function detectLegacyM1Warning(workspaceRoot) {
|
|
1153
|
-
const candidate = path9.join(path9.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
|
|
1154
|
-
try {
|
|
1155
|
-
await fs6.access(candidate);
|
|
1156
|
-
return candidate;
|
|
1157
|
-
} catch {
|
|
1158
|
-
return void 0;
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
1150
|
async function ensureRepositoryBindingForRoot(workspaceRoot, options = {}) {
|
|
1162
1151
|
const resolved = path9.resolve(workspaceRoot);
|
|
1163
1152
|
const identity = await captureRootFilesystemIdentity(resolved, options.identityDeps);
|
|
1164
|
-
const legacyM1WarningPath = await detectLegacyM1Warning(resolved);
|
|
1165
1153
|
const index = await loadPathIndex(options.homeDir);
|
|
1166
1154
|
const lookup = lookupPathIndex(index, resolved, identity);
|
|
1167
1155
|
if (lookup.kind === "path") {
|
|
@@ -1185,8 +1173,7 @@ async function ensureRepositoryBindingForRoot(workspaceRoot, options = {}) {
|
|
|
1185
1173
|
return {
|
|
1186
1174
|
repositoryBindingId: record.repositoryBindingId,
|
|
1187
1175
|
identity,
|
|
1188
|
-
created: false
|
|
1189
|
-
legacyM1WarningPath
|
|
1176
|
+
created: false
|
|
1190
1177
|
};
|
|
1191
1178
|
}
|
|
1192
1179
|
}
|
|
@@ -1210,8 +1197,7 @@ async function ensureRepositoryBindingForRoot(workspaceRoot, options = {}) {
|
|
|
1210
1197
|
repositoryBindingId: record.repositoryBindingId,
|
|
1211
1198
|
identity,
|
|
1212
1199
|
created: false,
|
|
1213
|
-
renamedFrom: lookup.previousPath
|
|
1214
|
-
legacyM1WarningPath
|
|
1200
|
+
renamedFrom: lookup.previousPath
|
|
1215
1201
|
};
|
|
1216
1202
|
}
|
|
1217
1203
|
}
|
|
@@ -1224,13 +1210,36 @@ async function ensureRepositoryBindingForRoot(workspaceRoot, options = {}) {
|
|
|
1224
1210
|
return {
|
|
1225
1211
|
repositoryBindingId,
|
|
1226
1212
|
identity,
|
|
1227
|
-
created: true
|
|
1228
|
-
|
|
1213
|
+
created: true
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
async function lookupLocalBindingIdentity(workspaceRoot, options = {}) {
|
|
1217
|
+
const resolved = path9.resolve(workspaceRoot);
|
|
1218
|
+
const identity = await captureRootFilesystemIdentity(resolved, options.identityDeps);
|
|
1219
|
+
const index = await loadPathIndex(options.homeDir);
|
|
1220
|
+
const lookup = lookupPathIndex(index, resolved, identity);
|
|
1221
|
+
if (lookup.kind !== "path") {
|
|
1222
|
+
return { status: "unbound", workspaceRoot: resolved };
|
|
1223
|
+
}
|
|
1224
|
+
const record = await readBindingRecord(lookup.repositoryBindingId, options.homeDir);
|
|
1225
|
+
if (!record) {
|
|
1226
|
+
return { status: "unbound", workspaceRoot: resolved };
|
|
1227
|
+
}
|
|
1228
|
+
if (path9.resolve(record.workspaceRoot) !== resolved) {
|
|
1229
|
+
return { status: "unbound", workspaceRoot: resolved };
|
|
1230
|
+
}
|
|
1231
|
+
if (!identityMatchesStored(record.filesystemIdentity, identity)) {
|
|
1232
|
+
return { status: "unbound", workspaceRoot: resolved };
|
|
1233
|
+
}
|
|
1234
|
+
return {
|
|
1235
|
+
status: "resolved",
|
|
1236
|
+
workspaceRoot: resolved,
|
|
1237
|
+
repositoryBindingId: record.repositoryBindingId
|
|
1229
1238
|
};
|
|
1230
1239
|
}
|
|
1231
1240
|
async function resolveLocalBinding(workspaceRoot, options = {}) {
|
|
1232
1241
|
const resolved = path9.resolve(workspaceRoot);
|
|
1233
|
-
const { repositoryBindingId
|
|
1242
|
+
const { repositoryBindingId } = await ensureRepositoryBindingForRoot(
|
|
1234
1243
|
resolved,
|
|
1235
1244
|
{ ...options, createIfMissing: false }
|
|
1236
1245
|
);
|
|
@@ -1273,14 +1282,12 @@ async function resolveLocalBinding(workspaceRoot, options = {}) {
|
|
|
1273
1282
|
installationPublicId: record.installationPublicId ?? creds.installationPublicId,
|
|
1274
1283
|
environment: record.environment,
|
|
1275
1284
|
bindingSource: "local-binding",
|
|
1276
|
-
status: record.status
|
|
1277
|
-
legacyM1WarningPath
|
|
1285
|
+
status: record.status
|
|
1278
1286
|
};
|
|
1279
1287
|
}
|
|
1280
1288
|
|
|
1281
1289
|
// src/projectBinding.ts
|
|
1282
1290
|
var uuidRegex2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1283
|
-
var CANONICAL_M1_FILENAME = "memoraone.m1";
|
|
1284
1291
|
function normalizeEnvironment(raw) {
|
|
1285
1292
|
if (raw === void 0 || raw === null || typeof raw !== "string") {
|
|
1286
1293
|
return void 0;
|
|
@@ -1296,23 +1303,9 @@ function toResolvedBinding(local) {
|
|
|
1296
1303
|
installationPublicId: local.installationPublicId,
|
|
1297
1304
|
environment: local.environment,
|
|
1298
1305
|
bindingSource: "local-binding",
|
|
1299
|
-
status: local.status
|
|
1300
|
-
legacyM1WarningPath: local.legacyM1WarningPath
|
|
1306
|
+
status: local.status
|
|
1301
1307
|
};
|
|
1302
1308
|
}
|
|
1303
|
-
async function warnLegacyM1IfPresent(workspaceRoot) {
|
|
1304
|
-
const candidate = path10.join(path10.resolve(workspaceRoot), CANONICAL_M1_FILENAME);
|
|
1305
|
-
try {
|
|
1306
|
-
await fs7.access(candidate);
|
|
1307
|
-
process.stderr.write(
|
|
1308
|
-
`[memoraone-mcp] warning: ignoring legacy ${CANONICAL_M1_FILENAME} (not used for credentials or binding)
|
|
1309
|
-
`
|
|
1310
|
-
);
|
|
1311
|
-
return candidate;
|
|
1312
|
-
} catch {
|
|
1313
|
-
return void 0;
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
1309
|
async function resolveAuthoritativeBinding(workspaceRoot, _options = {}) {
|
|
1317
1310
|
const candidates = normalizeWorkspaceSearchRoots(workspaceRoot);
|
|
1318
1311
|
if (candidates.length === 0) {
|
|
@@ -1322,7 +1315,6 @@ async function resolveAuthoritativeBinding(workspaceRoot, _options = {}) {
|
|
|
1322
1315
|
}
|
|
1323
1316
|
const bindings = [];
|
|
1324
1317
|
for (const root of candidates) {
|
|
1325
|
-
await warnLegacyM1IfPresent(root);
|
|
1326
1318
|
try {
|
|
1327
1319
|
const local = await resolveLocalBinding(root);
|
|
1328
1320
|
bindings.push(toResolvedBinding(local));
|
|
@@ -1481,7 +1473,7 @@ function decodeResolvedBinding(value) {
|
|
|
1481
1473
|
}
|
|
1482
1474
|
|
|
1483
1475
|
// src/bindingSidecar.ts
|
|
1484
|
-
var
|
|
1476
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
1485
1477
|
var path11 = __toESM(require("path"), 1);
|
|
1486
1478
|
function bindingSidecarPath(socketPath) {
|
|
1487
1479
|
if (socketPath.endsWith(".sock")) {
|
|
@@ -1506,11 +1498,11 @@ function writeBindingSidecar(socketPath, binding, ideType = resolveBindingIdeTyp
|
|
|
1506
1498
|
if (/["']?(accessToken|refreshToken|apiKey|clientRedeemKey|clientRefreshKey)["']?\s*:/.test(text)) {
|
|
1507
1499
|
throw new Error("[memoraone-mcp] Refusing to write sidecar containing secrets");
|
|
1508
1500
|
}
|
|
1509
|
-
|
|
1501
|
+
fs6.writeFileSync(bindingSidecarPath(socketPath), text, "utf8");
|
|
1510
1502
|
}
|
|
1511
1503
|
function removeBindingSidecar(socketPath) {
|
|
1512
1504
|
try {
|
|
1513
|
-
|
|
1505
|
+
fs6.unlinkSync(bindingSidecarPath(socketPath));
|
|
1514
1506
|
} catch {
|
|
1515
1507
|
}
|
|
1516
1508
|
}
|
|
@@ -1522,7 +1514,7 @@ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
|
1522
1514
|
|
|
1523
1515
|
// src/config.ts
|
|
1524
1516
|
var process2 = __toESM(require("process"), 1);
|
|
1525
|
-
var
|
|
1517
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
1526
1518
|
var path12 = __toESM(require("path"), 1);
|
|
1527
1519
|
var dotenv = __toESM(require("dotenv"), 1);
|
|
1528
1520
|
var import_v4 = require("zod/v4");
|
|
@@ -1547,7 +1539,7 @@ function resolveApiUrl(env2) {
|
|
|
1547
1539
|
|
|
1548
1540
|
// src/config.ts
|
|
1549
1541
|
var dotenvPath = path12.resolve(process2.cwd(), ".env");
|
|
1550
|
-
if (
|
|
1542
|
+
if (fs7.existsSync(dotenvPath)) {
|
|
1551
1543
|
try {
|
|
1552
1544
|
dotenv.config({ path: dotenvPath });
|
|
1553
1545
|
} catch (err) {
|
|
@@ -1793,6 +1785,145 @@ async function resolveBindingFromInitializeParams(params, options = {}) {
|
|
|
1793
1785
|
});
|
|
1794
1786
|
}
|
|
1795
1787
|
|
|
1788
|
+
// src/pluginStartupBindingWait.ts
|
|
1789
|
+
var path14 = __toESM(require("path"), 1);
|
|
1790
|
+
var MEMORAONE_PLUGIN_ENV = "MEMORAONE_PLUGIN";
|
|
1791
|
+
var MEMORAONE_CURSOR_PLUGIN = "cursor";
|
|
1792
|
+
var PLUGIN_STARTUP_BINDING_WAIT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1793
|
+
var PLUGIN_STARTUP_BINDING_WAIT_INTERVAL_MS = 250;
|
|
1794
|
+
var UNBOUND_MESSAGE_MARKERS = [
|
|
1795
|
+
"No local MemoraOne binding for this workspace",
|
|
1796
|
+
"No local binding for workspace"
|
|
1797
|
+
];
|
|
1798
|
+
var CREDENTIALS_MISSING_MARKER = "Installation credentials missing";
|
|
1799
|
+
function errorMessage(err) {
|
|
1800
|
+
return err instanceof Error ? err.message : String(err);
|
|
1801
|
+
}
|
|
1802
|
+
function isUnboundPluginStartupBindingMessage(message) {
|
|
1803
|
+
return UNBOUND_MESSAGE_MARKERS.some((marker) => message.includes(marker));
|
|
1804
|
+
}
|
|
1805
|
+
function isCredentialsMissingMessage(message) {
|
|
1806
|
+
return message.includes(CREDENTIALS_MISSING_MARKER);
|
|
1807
|
+
}
|
|
1808
|
+
async function pendingBindingWindowOpen(isPendingBinding) {
|
|
1809
|
+
if (!isPendingBinding) {
|
|
1810
|
+
return false;
|
|
1811
|
+
}
|
|
1812
|
+
try {
|
|
1813
|
+
return Boolean(await isPendingBinding());
|
|
1814
|
+
} catch {
|
|
1815
|
+
return false;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
function shouldWaitForPluginStartupBinding(options = {}) {
|
|
1819
|
+
const env2 = options.env ?? process.env;
|
|
1820
|
+
if (env2[MEMORAONE_PLUGIN_ENV] !== MEMORAONE_CURSOR_PLUGIN) {
|
|
1821
|
+
return false;
|
|
1822
|
+
}
|
|
1823
|
+
if (options.daemonBindingHint) {
|
|
1824
|
+
return false;
|
|
1825
|
+
}
|
|
1826
|
+
return true;
|
|
1827
|
+
}
|
|
1828
|
+
function collectPluginStartupBindingRoots(options) {
|
|
1829
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1830
|
+
const roots = [];
|
|
1831
|
+
const add = (raw) => {
|
|
1832
|
+
if (raw === void 0 || raw === null || raw.trim() === "") {
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
const resolved = path14.resolve(raw);
|
|
1836
|
+
if (seen.has(resolved)) {
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1839
|
+
seen.add(resolved);
|
|
1840
|
+
roots.push(resolved);
|
|
1841
|
+
};
|
|
1842
|
+
for (const root of options.initializeRoots ?? []) {
|
|
1843
|
+
add(root);
|
|
1844
|
+
}
|
|
1845
|
+
for (const uri of options.rootsListUris ?? []) {
|
|
1846
|
+
add(uriToPath(uri));
|
|
1847
|
+
}
|
|
1848
|
+
add(getRepoScopedWorkspaceHint(options.env));
|
|
1849
|
+
return roots;
|
|
1850
|
+
}
|
|
1851
|
+
async function hasPendingPluginStartupBinding(workspaceRoots, options = {}) {
|
|
1852
|
+
for (const root of workspaceRoots) {
|
|
1853
|
+
try {
|
|
1854
|
+
const identity = await lookupLocalBindingIdentity(root, {
|
|
1855
|
+
homeDir: options.homeDir
|
|
1856
|
+
});
|
|
1857
|
+
if (identity.status !== "resolved") {
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
const record = await readBindingRecord(
|
|
1861
|
+
identity.repositoryBindingId,
|
|
1862
|
+
options.homeDir
|
|
1863
|
+
);
|
|
1864
|
+
if (record?.status === "pending") {
|
|
1865
|
+
return true;
|
|
1866
|
+
}
|
|
1867
|
+
} catch {
|
|
1868
|
+
continue;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
return false;
|
|
1872
|
+
}
|
|
1873
|
+
async function isRetryablePluginStartupBindingError(err, options = {}) {
|
|
1874
|
+
const message = errorMessage(err);
|
|
1875
|
+
if (isUnboundPluginStartupBindingMessage(message)) {
|
|
1876
|
+
return true;
|
|
1877
|
+
}
|
|
1878
|
+
if (isCredentialsMissingMessage(message) && await pendingBindingWindowOpen(options.isPendingBinding)) {
|
|
1879
|
+
return true;
|
|
1880
|
+
}
|
|
1881
|
+
return false;
|
|
1882
|
+
}
|
|
1883
|
+
function defaultSleep(ms) {
|
|
1884
|
+
return new Promise((resolve11) => {
|
|
1885
|
+
setTimeout(resolve11, ms);
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
async function waitForPluginStartupBinding(resolve11, options = {}) {
|
|
1889
|
+
const now = options.now ?? Date.now;
|
|
1890
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
1891
|
+
const timeoutMs = options.timeoutMs ?? PLUGIN_STARTUP_BINDING_WAIT_TIMEOUT_MS;
|
|
1892
|
+
const intervalMs = options.intervalMs ?? PLUGIN_STARTUP_BINDING_WAIT_INTERVAL_MS;
|
|
1893
|
+
const startedAt = now();
|
|
1894
|
+
let waitingLogged = false;
|
|
1895
|
+
let lastError;
|
|
1896
|
+
while (true) {
|
|
1897
|
+
try {
|
|
1898
|
+
const binding = await resolve11();
|
|
1899
|
+
if (waitingLogged) {
|
|
1900
|
+
options.log?.(
|
|
1901
|
+
`local MemoraOne binding available after Cursor plugin pairing (${now() - startedAt}ms)`
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1904
|
+
return binding;
|
|
1905
|
+
} catch (err) {
|
|
1906
|
+
lastError = err;
|
|
1907
|
+
const retryable = await isRetryablePluginStartupBindingError(err, {
|
|
1908
|
+
isPendingBinding: options.isPendingBinding
|
|
1909
|
+
});
|
|
1910
|
+
if (!retryable) {
|
|
1911
|
+
throw err;
|
|
1912
|
+
}
|
|
1913
|
+
if (now() - startedAt >= timeoutMs) {
|
|
1914
|
+
throw lastError;
|
|
1915
|
+
}
|
|
1916
|
+
if (!waitingLogged) {
|
|
1917
|
+
options.log?.(
|
|
1918
|
+
"waiting for local MemoraOne binding after Cursor plugin pairing"
|
|
1919
|
+
);
|
|
1920
|
+
waitingLogged = true;
|
|
1921
|
+
}
|
|
1922
|
+
await sleep(intervalMs);
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1796
1927
|
// src/bridgeClientRoots.ts
|
|
1797
1928
|
var readline = __toESM(require("readline"), 1);
|
|
1798
1929
|
var TRUTHY = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
@@ -2227,9 +2358,9 @@ function buildPersonalContextPath(parsed2) {
|
|
|
2227
2358
|
}
|
|
2228
2359
|
async function handleGetPersonalContext(client, args) {
|
|
2229
2360
|
const parsed2 = getPersonalContextInputSchema.parse(args ?? {});
|
|
2230
|
-
const
|
|
2361
|
+
const path16 = buildPersonalContextPath(parsed2);
|
|
2231
2362
|
try {
|
|
2232
|
-
const result = await client.get(
|
|
2363
|
+
const result = await client.get(path16);
|
|
2233
2364
|
return { ok: true, result };
|
|
2234
2365
|
} catch (err) {
|
|
2235
2366
|
if (err instanceof MemoraOneHttpError) {
|
|
@@ -2701,8 +2832,8 @@ async function handleCreateConceptVersion(client, args) {
|
|
|
2701
2832
|
if (input.tags !== void 0) body.tags = input.tags;
|
|
2702
2833
|
if (input.parent_id !== void 0) body.parent_id = input.parent_id;
|
|
2703
2834
|
try {
|
|
2704
|
-
const
|
|
2705
|
-
return projectCreatedConceptVersionResponse(await client.post(
|
|
2835
|
+
const path16 = `/concepts/${encodeURIComponent(input.id)}/versions`;
|
|
2836
|
+
return projectCreatedConceptVersionResponse(await client.post(path16, body));
|
|
2706
2837
|
} catch (error) {
|
|
2707
2838
|
rethrowToolRequestError("memora_create_concept_version", error);
|
|
2708
2839
|
}
|
|
@@ -2736,8 +2867,8 @@ function handleBindingStatus(binding, options = {}) {
|
|
|
2736
2867
|
|
|
2737
2868
|
// src/heartbeat.ts
|
|
2738
2869
|
var crypto5 = __toESM(require("crypto"), 1);
|
|
2739
|
-
var
|
|
2740
|
-
var
|
|
2870
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
2871
|
+
var path15 = __toESM(require("path"), 1);
|
|
2741
2872
|
|
|
2742
2873
|
// src/localState/mcpSessionId.ts
|
|
2743
2874
|
var import_node_crypto4 = require("crypto");
|
|
@@ -2770,13 +2901,13 @@ function resolvePackageVersion() {
|
|
|
2770
2901
|
if (fromEnv) return fromEnv;
|
|
2771
2902
|
const moduleDir = typeof __dirname !== "undefined" ? __dirname : void 0;
|
|
2772
2903
|
const candidates = [
|
|
2773
|
-
...moduleDir ? [
|
|
2774
|
-
|
|
2775
|
-
|
|
2904
|
+
...moduleDir ? [path15.join(moduleDir, "..", "package.json"), path15.join(moduleDir, "package.json")] : [],
|
|
2905
|
+
path15.join(process.cwd(), "package.json"),
|
|
2906
|
+
path15.join(process.cwd(), "packages", "mcp", "package.json")
|
|
2776
2907
|
];
|
|
2777
2908
|
for (const candidate of candidates) {
|
|
2778
2909
|
try {
|
|
2779
|
-
const pkg = JSON.parse(
|
|
2910
|
+
const pkg = JSON.parse(fs8.readFileSync(candidate, "utf8"));
|
|
2780
2911
|
if (typeof pkg.version === "string" && pkg.version.trim()) {
|
|
2781
2912
|
return pkg.version.trim();
|
|
2782
2913
|
}
|
|
@@ -3291,8 +3422,8 @@ function registerToolWithWorklog(server, runtime, sessionContext, toolName, desc
|
|
|
3291
3422
|
async function main(opts = {}) {
|
|
3292
3423
|
let bindingReadyResolve = null;
|
|
3293
3424
|
let bindingReadyReject = null;
|
|
3294
|
-
const bindingReady = new Promise((
|
|
3295
|
-
bindingReadyResolve =
|
|
3425
|
+
const bindingReady = new Promise((resolve11, reject) => {
|
|
3426
|
+
bindingReadyResolve = resolve11;
|
|
3296
3427
|
bindingReadyReject = reject;
|
|
3297
3428
|
});
|
|
3298
3429
|
const devMode = Boolean(config2.devMode);
|
|
@@ -3373,12 +3504,25 @@ async function main(opts = {}) {
|
|
|
3373
3504
|
console.error("[memoraone-mcp][init-debug] Workspace resolution strategy: initialize.rootUri");
|
|
3374
3505
|
}
|
|
3375
3506
|
}
|
|
3376
|
-
const
|
|
3507
|
+
const resolveBinding = () => resolveBindingFromInitializeParams(params, {
|
|
3377
3508
|
fallbackWorkspaceRoots: getEnvWorkspaceRootCandidates(),
|
|
3378
3509
|
rootsListUris,
|
|
3379
3510
|
rootsListAttempted,
|
|
3380
3511
|
...getBridgeBindingResolveOptions()
|
|
3381
3512
|
});
|
|
3513
|
+
const binding = shouldWaitForPluginStartupBinding({
|
|
3514
|
+
env: process.env,
|
|
3515
|
+
daemonBindingHint: opts.daemonBindingHint
|
|
3516
|
+
}) ? await waitForPluginStartupBinding(resolveBinding, {
|
|
3517
|
+
isPendingBinding: () => hasPendingPluginStartupBinding(
|
|
3518
|
+
collectPluginStartupBindingRoots({
|
|
3519
|
+
initializeRoots,
|
|
3520
|
+
rootsListUris,
|
|
3521
|
+
env: process.env
|
|
3522
|
+
})
|
|
3523
|
+
),
|
|
3524
|
+
log: (msg) => console.error(`[memoraone-mcp] ${msg}`)
|
|
3525
|
+
}) : await resolveBinding();
|
|
3382
3526
|
workspaceRoot = binding.workspaceRoot;
|
|
3383
3527
|
return binding;
|
|
3384
3528
|
};
|
|
@@ -3652,11 +3796,6 @@ async function main(opts = {}) {
|
|
|
3652
3796
|
if (debugLog) {
|
|
3653
3797
|
console.error("[memoraone-mcp][debug] Resolved installation credentials from OS keyring");
|
|
3654
3798
|
}
|
|
3655
|
-
if (binding.legacyM1WarningPath) {
|
|
3656
|
-
console.error(
|
|
3657
|
-
`[memoraone-mcp] warning: ignoring legacy memoraone.m1 at ${binding.legacyM1WarningPath}`
|
|
3658
|
-
);
|
|
3659
|
-
}
|
|
3660
3799
|
const projectId = binding.projectId;
|
|
3661
3800
|
const existing = getBoundProjectId();
|
|
3662
3801
|
if (existing !== null && existing !== projectId) {
|
|
@@ -3765,10 +3904,10 @@ async function main(opts = {}) {
|
|
|
3765
3904
|
console.error("[memoraone-mcp] MCP server ready");
|
|
3766
3905
|
}
|
|
3767
3906
|
if (opts.sessionSocket) {
|
|
3768
|
-
await new Promise((
|
|
3907
|
+
await new Promise((resolve11) => {
|
|
3769
3908
|
opts.sessionSocket.once("close", () => {
|
|
3770
3909
|
shutdown("session closed", false);
|
|
3771
|
-
|
|
3910
|
+
resolve11();
|
|
3772
3911
|
});
|
|
3773
3912
|
});
|
|
3774
3913
|
}
|
|
@@ -3808,11 +3947,11 @@ function parseBindingFromEnv(repositoryBindingId) {
|
|
|
3808
3947
|
}
|
|
3809
3948
|
async function ensureSocketClean(socketPath) {
|
|
3810
3949
|
try {
|
|
3811
|
-
|
|
3950
|
+
fs9.accessSync(socketPath);
|
|
3812
3951
|
} catch {
|
|
3813
3952
|
return;
|
|
3814
3953
|
}
|
|
3815
|
-
return new Promise((
|
|
3954
|
+
return new Promise((resolve11) => {
|
|
3816
3955
|
const client = net.createConnection({ path: socketPath }, () => {
|
|
3817
3956
|
client.destroy();
|
|
3818
3957
|
log("daemon already running, exiting");
|
|
@@ -3820,11 +3959,11 @@ async function ensureSocketClean(socketPath) {
|
|
|
3820
3959
|
});
|
|
3821
3960
|
client.on("error", () => {
|
|
3822
3961
|
try {
|
|
3823
|
-
|
|
3962
|
+
fs9.unlinkSync(socketPath);
|
|
3824
3963
|
log("stale socket removed");
|
|
3825
3964
|
} catch {
|
|
3826
3965
|
}
|
|
3827
|
-
|
|
3966
|
+
resolve11();
|
|
3828
3967
|
});
|
|
3829
3968
|
});
|
|
3830
3969
|
}
|
|
@@ -3851,8 +3990,8 @@ async function runDaemon() {
|
|
|
3851
3990
|
await ensureSocketClean(socketPath);
|
|
3852
3991
|
const cleanupSocketFile = () => {
|
|
3853
3992
|
try {
|
|
3854
|
-
if (
|
|
3855
|
-
|
|
3993
|
+
if (fs9.existsSync(socketPath)) {
|
|
3994
|
+
fs9.unlinkSync(socketPath);
|
|
3856
3995
|
log("socket removed");
|
|
3857
3996
|
}
|
|
3858
3997
|
removeBindingSidecar(socketPath);
|
|
@@ -3915,14 +4054,14 @@ async function runDaemon() {
|
|
|
3915
4054
|
process.on("SIGINT", () => shutdownNow("SIGINT"));
|
|
3916
4055
|
process.on("SIGTERM", () => shutdownNow("SIGTERM"));
|
|
3917
4056
|
process.on("exit", cleanupSocketFile);
|
|
3918
|
-
return new Promise((
|
|
4057
|
+
return new Promise((resolve11) => {
|
|
3919
4058
|
server.listen(socketPath, () => {
|
|
3920
4059
|
writeBindingSidecar(socketPath, binding, ideType ?? "");
|
|
3921
4060
|
log(`daemon started, listening on ${socketPath}`);
|
|
3922
4061
|
void daemonHeartbeat.start().catch((err) => {
|
|
3923
4062
|
log(`daemon heartbeat start error: ${String(err)}`);
|
|
3924
4063
|
});
|
|
3925
|
-
|
|
4064
|
+
resolve11();
|
|
3926
4065
|
});
|
|
3927
4066
|
});
|
|
3928
4067
|
}
|