@memoraone/mcp 0.1.31 → 0.1.33
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 +205 -71
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var require_package = __commonJS({
|
|
|
30
30
|
"package.json"(exports2, module2) {
|
|
31
31
|
module2.exports = {
|
|
32
32
|
name: "@memoraone/mcp",
|
|
33
|
-
version: "0.1.
|
|
33
|
+
version: "0.1.33",
|
|
34
34
|
type: "module",
|
|
35
35
|
main: "dist/index.cjs",
|
|
36
36
|
bin: {
|
|
@@ -562,8 +562,8 @@ var StdioLineReader = class {
|
|
|
562
562
|
if (this.closed) {
|
|
563
563
|
return null;
|
|
564
564
|
}
|
|
565
|
-
return new Promise((
|
|
566
|
-
this.waiters.push(
|
|
565
|
+
return new Promise((resolve9) => {
|
|
566
|
+
this.waiters.push(resolve9);
|
|
567
567
|
});
|
|
568
568
|
}
|
|
569
569
|
/** Re-queue lines read during an intermediate protocol step (e.g. roots/list) for the main bridge loop. */
|
|
@@ -822,9 +822,9 @@ function summarizeJsonRpcMethod(line) {
|
|
|
822
822
|
}
|
|
823
823
|
}
|
|
824
824
|
function connectWithRetry(socketPath, log, maxRetries, retryDelayMs, connect2) {
|
|
825
|
-
return new Promise((
|
|
825
|
+
return new Promise((resolve9, reject) => {
|
|
826
826
|
const tryConnect = (attempt) => {
|
|
827
|
-
connect2(socketPath).then(
|
|
827
|
+
connect2(socketPath).then(resolve9).catch((err) => {
|
|
828
828
|
if (attempt >= maxRetries) {
|
|
829
829
|
reject(err);
|
|
830
830
|
return;
|
|
@@ -897,8 +897,8 @@ var BridgeDaemonRouter = class {
|
|
|
897
897
|
this.maxRetries = options.maxRetries ?? 5;
|
|
898
898
|
this.retryDelayMs = options.retryDelayMs ?? 200;
|
|
899
899
|
this.lineReader = options.lineReader ?? null;
|
|
900
|
-
this.connectImpl = options.connect ?? ((socketPath) => new Promise((
|
|
901
|
-
const socket = net.connect(socketPath, () =>
|
|
900
|
+
this.connectImpl = options.connect ?? ((socketPath) => new Promise((resolve9, reject) => {
|
|
901
|
+
const socket = net.connect(socketPath, () => resolve9(socket));
|
|
902
902
|
socket.on("error", reject);
|
|
903
903
|
}));
|
|
904
904
|
this.spawnDaemonImpl = options.spawnDaemon ?? (async (binding) => {
|
|
@@ -1142,9 +1142,9 @@ async function runBridgeProxy(options) {
|
|
|
1142
1142
|
}
|
|
1143
1143
|
|
|
1144
1144
|
// src/setupIdeFiles.ts
|
|
1145
|
-
var
|
|
1145
|
+
var fs8 = __toESM(require("fs/promises"), 1);
|
|
1146
1146
|
var os4 = __toESM(require("os"), 1);
|
|
1147
|
-
var
|
|
1147
|
+
var path10 = __toESM(require("path"), 1);
|
|
1148
1148
|
|
|
1149
1149
|
// src/cleanup.ts
|
|
1150
1150
|
var fs5 = __toESM(require("fs/promises"), 1);
|
|
@@ -1161,16 +1161,38 @@ var path6 = __toESM(require("path"), 1);
|
|
|
1161
1161
|
var import_node_child_process2 = require("child_process");
|
|
1162
1162
|
var import_node_util = require("util");
|
|
1163
1163
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
|
|
1164
|
-
|
|
1164
|
+
var MEMORAONE_PROD_API_URL = "https://api.memoraone.com";
|
|
1165
|
+
var MEMORAONE_LOCAL_API_URL = "http://localhost:3001";
|
|
1166
|
+
var MEMORAONE_STAGING_API_URL = "https://memora-api-staging-phbtrzocjq-uk.a.run.app";
|
|
1167
|
+
var MEMORAONE_STAGING_API_URL_PREFIX = "https://memora-api-staging-";
|
|
1168
|
+
function cursorMcpApiUrl(environment) {
|
|
1169
|
+
if (environment === "local") return MEMORAONE_LOCAL_API_URL;
|
|
1170
|
+
if (environment === "staging") return MEMORAONE_STAGING_API_URL;
|
|
1171
|
+
return MEMORAONE_PROD_API_URL;
|
|
1172
|
+
}
|
|
1173
|
+
function buildMemoraoneCursorMcpServer(options) {
|
|
1165
1174
|
const env = {
|
|
1166
|
-
MEMORAONE_API_URL:
|
|
1175
|
+
MEMORAONE_API_URL: cursorMcpApiUrl(options.environment),
|
|
1167
1176
|
MEMORAONE_IDE_TYPE: "cursor"
|
|
1168
1177
|
};
|
|
1169
|
-
if (workspaceRoot !== void 0) {
|
|
1170
|
-
env[MEMORAONE_WORKSPACE_ROOT_ENV] = path6.resolve(workspaceRoot);
|
|
1178
|
+
if (options.workspaceRoot !== void 0) {
|
|
1179
|
+
env[MEMORAONE_WORKSPACE_ROOT_ENV] = path6.resolve(options.workspaceRoot);
|
|
1180
|
+
}
|
|
1181
|
+
if (options.environment === "local") {
|
|
1182
|
+
if (!options.cliPath) {
|
|
1183
|
+
throw new Error("[setup-ide-files] Local Cursor MCP config requires a built CLI path.");
|
|
1184
|
+
}
|
|
1185
|
+
return {
|
|
1186
|
+
command: "node",
|
|
1187
|
+
args: [options.cliPath],
|
|
1188
|
+
env
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
if (!options.npxPath) {
|
|
1192
|
+
throw new Error("[setup-ide-files] Cursor MCP config requires a resolved npx path.");
|
|
1171
1193
|
}
|
|
1172
1194
|
return {
|
|
1173
|
-
command: npxPath,
|
|
1195
|
+
command: options.npxPath,
|
|
1174
1196
|
args: ["-y", "@memoraone/mcp@latest"],
|
|
1175
1197
|
env
|
|
1176
1198
|
};
|
|
@@ -1269,12 +1291,24 @@ async function resolveNpxPath() {
|
|
|
1269
1291
|
}
|
|
1270
1292
|
return null;
|
|
1271
1293
|
}
|
|
1272
|
-
function mergeCursorRepoMcpConfigObject(existing,
|
|
1294
|
+
function mergeCursorRepoMcpConfigObject(existing, writeOptions) {
|
|
1295
|
+
const environment = writeOptions.environment ?? "production";
|
|
1273
1296
|
const base = existing && typeof existing === "object" ? { ...existing } : { mcpServers: {} };
|
|
1274
1297
|
const mcpServers = typeof base.mcpServers === "object" && base.mcpServers !== null && !Array.isArray(base.mcpServers) ? { ...base.mcpServers } : {};
|
|
1275
|
-
mcpServers.memoraone = buildMemoraoneCursorMcpServer(
|
|
1298
|
+
mcpServers.memoraone = buildMemoraoneCursorMcpServer({
|
|
1299
|
+
environment,
|
|
1300
|
+
npxPath: writeOptions.npxPath,
|
|
1301
|
+
cliPath: writeOptions.cliPath,
|
|
1302
|
+
workspaceRoot: writeOptions.repoRoot
|
|
1303
|
+
});
|
|
1276
1304
|
return { ...base, mcpServers };
|
|
1277
1305
|
}
|
|
1306
|
+
function isMemoraoneManagedApiUrl(url) {
|
|
1307
|
+
if (typeof url !== "string" || url.length === 0) return false;
|
|
1308
|
+
if (url === MEMORAONE_PROD_API_URL) return true;
|
|
1309
|
+
if (url === MEMORAONE_LOCAL_API_URL) return true;
|
|
1310
|
+
return url.startsWith(MEMORAONE_STAGING_API_URL_PREFIX);
|
|
1311
|
+
}
|
|
1278
1312
|
function isManagedMemoraoneCursorServer(server) {
|
|
1279
1313
|
if (!server || typeof server !== "object") return false;
|
|
1280
1314
|
const s = server;
|
|
@@ -1282,7 +1316,7 @@ function isManagedMemoraoneCursorServer(server) {
|
|
|
1282
1316
|
if (s.args[0] !== "-y" || s.args[1] !== "@memoraone/mcp@latest") return false;
|
|
1283
1317
|
const env = s.env;
|
|
1284
1318
|
if (!env || typeof env !== "object") return false;
|
|
1285
|
-
return
|
|
1319
|
+
return memoraoneEnvMatchesManagedCleanupShape(env);
|
|
1286
1320
|
}
|
|
1287
1321
|
function cursorConfigHasManagedMemoraone(parsed) {
|
|
1288
1322
|
if (!parsed || typeof parsed !== "object") return false;
|
|
@@ -1290,8 +1324,8 @@ function cursorConfigHasManagedMemoraone(parsed) {
|
|
|
1290
1324
|
if (!mcpServers || typeof mcpServers !== "object" || Array.isArray(mcpServers)) return false;
|
|
1291
1325
|
return isManagedMemoraoneCursorServer(mcpServers.memoraone);
|
|
1292
1326
|
}
|
|
1293
|
-
function
|
|
1294
|
-
return env.
|
|
1327
|
+
function memoraoneEnvMatchesManagedCleanupShape(env) {
|
|
1328
|
+
return env.MEMORAONE_IDE_TYPE === "cursor" && isMemoraoneManagedApiUrl(env.MEMORAONE_API_URL);
|
|
1295
1329
|
}
|
|
1296
1330
|
function getCursorRepoMcpConfigPath(repoRoot) {
|
|
1297
1331
|
return path6.join(repoRoot, ".cursor", "mcp.json");
|
|
@@ -1386,9 +1420,13 @@ function logCursorMcpConfigAudit(prefix, audit) {
|
|
|
1386
1420
|
}
|
|
1387
1421
|
}
|
|
1388
1422
|
function logCursorMcpCliSummary(info, dryRun) {
|
|
1389
|
-
const { repoConfigPath, repoOutcome, npxPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
|
|
1423
|
+
const { repoConfigPath, repoOutcome, npxPath, cliPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
|
|
1390
1424
|
console.log(`[setup-ide-files] Cursor repo MCP config: ${repoConfigPath}`);
|
|
1391
|
-
|
|
1425
|
+
if (cliPath) {
|
|
1426
|
+
console.log(`[setup-ide-files] Resolved local CLI: ${cliPath}`);
|
|
1427
|
+
} else if (npxPath) {
|
|
1428
|
+
console.log(`[setup-ide-files] Resolved npx: ${npxPath}`);
|
|
1429
|
+
}
|
|
1392
1430
|
if (repoBackupPath) {
|
|
1393
1431
|
console.log(`[setup-ide-files] Cursor repo MCP config backup: ${repoBackupPath}`);
|
|
1394
1432
|
}
|
|
@@ -2085,7 +2123,7 @@ async function buildJetBrainsMemoraoneServer(options) {
|
|
|
2085
2123
|
async function verifyJetBrainsMcpHandshake(options) {
|
|
2086
2124
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
2087
2125
|
const { server } = options;
|
|
2088
|
-
return new Promise((
|
|
2126
|
+
return new Promise((resolve9) => {
|
|
2089
2127
|
let settled = false;
|
|
2090
2128
|
const finish = (ok, detail) => {
|
|
2091
2129
|
if (settled) return;
|
|
@@ -2095,7 +2133,7 @@ async function verifyJetBrainsMcpHandshake(options) {
|
|
|
2095
2133
|
child.kill();
|
|
2096
2134
|
} catch {
|
|
2097
2135
|
}
|
|
2098
|
-
|
|
2136
|
+
resolve9({ ok, detail });
|
|
2099
2137
|
};
|
|
2100
2138
|
const child = (0, import_node_child_process4.spawn)(server.command, [...server.args], {
|
|
2101
2139
|
env: { ...process.env, ...server.env },
|
|
@@ -2299,6 +2337,60 @@ function logJetBrainsMcpCliSummary(info, dryRun) {
|
|
|
2299
2337
|
);
|
|
2300
2338
|
}
|
|
2301
2339
|
|
|
2340
|
+
// src/resolveBuiltCliPath.ts
|
|
2341
|
+
var fs7 = __toESM(require("fs/promises"), 1);
|
|
2342
|
+
var path9 = __toESM(require("path"), 1);
|
|
2343
|
+
var MONOREPO_CLI_REL = path9.join("packages", "mcp", "dist", "cli.cjs");
|
|
2344
|
+
async function pathExists3(filePath) {
|
|
2345
|
+
try {
|
|
2346
|
+
await fs7.access(filePath);
|
|
2347
|
+
return true;
|
|
2348
|
+
} catch {
|
|
2349
|
+
return false;
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
async function findMonorepoCliFrom(startDir) {
|
|
2353
|
+
let current = path9.resolve(startDir);
|
|
2354
|
+
const root = path9.parse(current).root;
|
|
2355
|
+
while (true) {
|
|
2356
|
+
const candidate = path9.join(current, MONOREPO_CLI_REL);
|
|
2357
|
+
if (await pathExists3(candidate)) {
|
|
2358
|
+
return path9.resolve(candidate);
|
|
2359
|
+
}
|
|
2360
|
+
if (current === root) break;
|
|
2361
|
+
current = path9.dirname(current);
|
|
2362
|
+
}
|
|
2363
|
+
return null;
|
|
2364
|
+
}
|
|
2365
|
+
async function resolveBuiltCliPathAsync(options) {
|
|
2366
|
+
const searchDirs = [];
|
|
2367
|
+
if (options?.searchFrom !== void 0) {
|
|
2368
|
+
const dirs = Array.isArray(options.searchFrom) ? options.searchFrom : [options.searchFrom];
|
|
2369
|
+
searchDirs.push(...dirs);
|
|
2370
|
+
}
|
|
2371
|
+
searchDirs.push(process.cwd());
|
|
2372
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2373
|
+
for (const dir of searchDirs) {
|
|
2374
|
+
const key = path9.resolve(dir);
|
|
2375
|
+
if (seen.has(key)) continue;
|
|
2376
|
+
seen.add(key);
|
|
2377
|
+
const found = await findMonorepoCliFrom(key);
|
|
2378
|
+
if (found) return found;
|
|
2379
|
+
}
|
|
2380
|
+
const here = process.argv[1] ? path9.dirname(path9.resolve(process.argv[1])) : process.cwd();
|
|
2381
|
+
const candidates = [
|
|
2382
|
+
path9.join(here, "cli.cjs"),
|
|
2383
|
+
path9.join(here, "..", "dist", "cli.cjs"),
|
|
2384
|
+
path9.join(here, "..", "..", "dist", "cli.cjs")
|
|
2385
|
+
];
|
|
2386
|
+
for (const candidate of candidates) {
|
|
2387
|
+
if (await pathExists3(candidate)) {
|
|
2388
|
+
return path9.resolve(candidate);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
return null;
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2302
2394
|
// src/setupIdeFiles.ts
|
|
2303
2395
|
var MANAGED_MARKER = "<!-- MemoraOne managed IDE helper -->";
|
|
2304
2396
|
var GITIGNORE_MEMORAONE_COMMENT = "# MemoraOne local project binding / API key";
|
|
@@ -2314,15 +2406,15 @@ function buildMemoraoneMcpServer(ideType, command = "npx") {
|
|
|
2314
2406
|
};
|
|
2315
2407
|
}
|
|
2316
2408
|
function assertUnderRepoRoot(repoRoot, absPath) {
|
|
2317
|
-
const normRoot =
|
|
2318
|
-
const normPath =
|
|
2319
|
-
if (normPath !==
|
|
2409
|
+
const normRoot = path10.resolve(repoRoot) + path10.sep;
|
|
2410
|
+
const normPath = path10.resolve(absPath);
|
|
2411
|
+
if (normPath !== path10.resolve(repoRoot) && !normPath.startsWith(normRoot)) {
|
|
2320
2412
|
throw new Error(`[setup-ide-files] Refusing to write outside repo root: ${absPath}`);
|
|
2321
2413
|
}
|
|
2322
2414
|
}
|
|
2323
|
-
async function
|
|
2415
|
+
async function pathExists4(filePath) {
|
|
2324
2416
|
try {
|
|
2325
|
-
await
|
|
2417
|
+
await fs8.access(filePath);
|
|
2326
2418
|
return true;
|
|
2327
2419
|
} catch {
|
|
2328
2420
|
return false;
|
|
@@ -2343,12 +2435,12 @@ ${GITIGNORE_MEMORAONE_ENTRY}
|
|
|
2343
2435
|
}
|
|
2344
2436
|
async function ensureGitignoreMemoraone(repoRoot, opts) {
|
|
2345
2437
|
if (opts.noGitignore) return "skipped";
|
|
2346
|
-
const abs =
|
|
2438
|
+
const abs = path10.join(repoRoot, ".gitignore");
|
|
2347
2439
|
assertUnderRepoRoot(repoRoot, abs);
|
|
2348
2440
|
let prior = "";
|
|
2349
2441
|
let existed = false;
|
|
2350
2442
|
try {
|
|
2351
|
-
prior = await
|
|
2443
|
+
prior = await fs8.readFile(abs, "utf8");
|
|
2352
2444
|
existed = true;
|
|
2353
2445
|
} catch (err) {
|
|
2354
2446
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
@@ -2359,22 +2451,22 @@ async function ensureGitignoreMemoraone(repoRoot, opts) {
|
|
|
2359
2451
|
const separator = existed && prior.length > 0 ? prior.endsWith("\n") ? "\n" : "\n\n" : "";
|
|
2360
2452
|
const next = (existed ? prior : "") + separator + block;
|
|
2361
2453
|
if (opts.dryRun) return existed ? "updated" : "created";
|
|
2362
|
-
await
|
|
2454
|
+
await fs8.writeFile(abs, next, "utf8");
|
|
2363
2455
|
return existed ? "updated" : "created";
|
|
2364
2456
|
}
|
|
2365
2457
|
async function findRepoRoot(startDir) {
|
|
2366
|
-
let current =
|
|
2367
|
-
const root =
|
|
2458
|
+
let current = path10.resolve(startDir);
|
|
2459
|
+
const root = path10.parse(current).root;
|
|
2368
2460
|
while (true) {
|
|
2369
|
-
const gitPath =
|
|
2370
|
-
const m1Path =
|
|
2371
|
-
if (await
|
|
2461
|
+
const gitPath = path10.join(current, ".git");
|
|
2462
|
+
const m1Path = path10.join(current, "memoraone.m1");
|
|
2463
|
+
if (await pathExists4(gitPath) || await pathExists4(m1Path)) {
|
|
2372
2464
|
return current;
|
|
2373
2465
|
}
|
|
2374
2466
|
if (current === root) {
|
|
2375
2467
|
return null;
|
|
2376
2468
|
}
|
|
2377
|
-
current =
|
|
2469
|
+
current = path10.dirname(current);
|
|
2378
2470
|
}
|
|
2379
2471
|
}
|
|
2380
2472
|
function stripLeadingLineComments3(text) {
|
|
@@ -2427,47 +2519,47 @@ function buildVscodeMcpJsonBody(existing) {
|
|
|
2427
2519
|
const merged = { ...base, servers };
|
|
2428
2520
|
return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
|
|
2429
2521
|
}
|
|
2430
|
-
function buildCursorMcpJsonBody(existing,
|
|
2431
|
-
const merged = mergeCursorRepoMcpConfigObject(existing,
|
|
2522
|
+
function buildCursorMcpJsonBody(existing, writeOptions) {
|
|
2523
|
+
const merged = mergeCursorRepoMcpConfigObject(existing, writeOptions);
|
|
2432
2524
|
return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
|
|
2433
2525
|
}
|
|
2434
2526
|
async function writeManagedMarkdown(repoRoot, relPath, fullContent, opts) {
|
|
2435
|
-
const abs =
|
|
2527
|
+
const abs = path10.join(repoRoot, relPath);
|
|
2436
2528
|
assertUnderRepoRoot(repoRoot, abs);
|
|
2437
2529
|
let prior = "";
|
|
2438
2530
|
let existed = false;
|
|
2439
2531
|
try {
|
|
2440
|
-
prior = await
|
|
2532
|
+
prior = await fs8.readFile(abs, "utf8");
|
|
2441
2533
|
existed = true;
|
|
2442
2534
|
} catch (err) {
|
|
2443
2535
|
if (err?.code !== "ENOENT") throw err;
|
|
2444
2536
|
}
|
|
2445
2537
|
if (!existed) {
|
|
2446
2538
|
if (opts.dryRun) return "created";
|
|
2447
|
-
await
|
|
2448
|
-
await
|
|
2539
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2540
|
+
await fs8.writeFile(abs, fullContent, "utf8");
|
|
2449
2541
|
return "created";
|
|
2450
2542
|
}
|
|
2451
2543
|
if (prior.includes(MANAGED_MARKER)) {
|
|
2452
2544
|
if (prior === fullContent) return "skipped";
|
|
2453
2545
|
if (opts.dryRun) return "updated";
|
|
2454
|
-
await
|
|
2455
|
-
await
|
|
2546
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2547
|
+
await fs8.writeFile(abs, fullContent, "utf8");
|
|
2456
2548
|
return "updated";
|
|
2457
2549
|
}
|
|
2458
2550
|
if (!opts.force) return "skipped-untracked";
|
|
2459
2551
|
if (opts.dryRun) return "updated";
|
|
2460
|
-
await
|
|
2461
|
-
await
|
|
2552
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2553
|
+
await fs8.writeFile(abs, fullContent, "utf8");
|
|
2462
2554
|
return "updated";
|
|
2463
2555
|
}
|
|
2464
2556
|
async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
2465
|
-
const abs =
|
|
2557
|
+
const abs = path10.join(repoRoot, relPath);
|
|
2466
2558
|
assertUnderRepoRoot(repoRoot, abs);
|
|
2467
2559
|
let raw = "";
|
|
2468
2560
|
let existed = false;
|
|
2469
2561
|
try {
|
|
2470
|
-
raw = await
|
|
2562
|
+
raw = await fs8.readFile(abs, "utf8");
|
|
2471
2563
|
existed = true;
|
|
2472
2564
|
} catch (err) {
|
|
2473
2565
|
if (err?.code !== "ENOENT") throw err;
|
|
@@ -2475,8 +2567,8 @@ async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
|
2475
2567
|
if (!existed) {
|
|
2476
2568
|
const body = buildBody(null);
|
|
2477
2569
|
if (opts.dryRun) return "created";
|
|
2478
|
-
await
|
|
2479
|
-
await
|
|
2570
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2571
|
+
await fs8.writeFile(abs, body, "utf8");
|
|
2480
2572
|
return "created";
|
|
2481
2573
|
}
|
|
2482
2574
|
const managed = raw.includes(MANAGED_MARKER);
|
|
@@ -2491,8 +2583,8 @@ async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
|
|
|
2491
2583
|
const next = buildBody(parsed);
|
|
2492
2584
|
if (managed && next === raw) return "skipped";
|
|
2493
2585
|
if (opts.dryRun) return "updated";
|
|
2494
|
-
await
|
|
2495
|
-
await
|
|
2586
|
+
await fs8.mkdir(path10.dirname(abs), { recursive: true });
|
|
2587
|
+
await fs8.writeFile(abs, next, "utf8");
|
|
2496
2588
|
return "updated";
|
|
2497
2589
|
}
|
|
2498
2590
|
function parseSetupIdeFlags(argv) {
|
|
@@ -2506,6 +2598,8 @@ function parseSetupIdeFlags(argv) {
|
|
|
2506
2598
|
let cleanup = false;
|
|
2507
2599
|
let devMode = false;
|
|
2508
2600
|
let repair = false;
|
|
2601
|
+
let local = false;
|
|
2602
|
+
let staging = false;
|
|
2509
2603
|
const unknown = [];
|
|
2510
2604
|
for (const a of argv) {
|
|
2511
2605
|
if (a === "--cursor") cursor = true;
|
|
@@ -2518,6 +2612,8 @@ function parseSetupIdeFlags(argv) {
|
|
|
2518
2612
|
else if (a === "--cleanup") cleanup = true;
|
|
2519
2613
|
else if (a === "--dev") devMode = true;
|
|
2520
2614
|
else if (a === "--repair") repair = true;
|
|
2615
|
+
else if (a === "--local") local = true;
|
|
2616
|
+
else if (a === "--staging") staging = true;
|
|
2521
2617
|
else if (a.startsWith("-")) unknown.push(a);
|
|
2522
2618
|
}
|
|
2523
2619
|
const specific = cursor || vscode || jetbrains;
|
|
@@ -2527,7 +2623,16 @@ function parseSetupIdeFlags(argv) {
|
|
|
2527
2623
|
} else {
|
|
2528
2624
|
targets = { cursor, vscode, jetbrains };
|
|
2529
2625
|
}
|
|
2530
|
-
|
|
2626
|
+
let flagError;
|
|
2627
|
+
if (local && staging) {
|
|
2628
|
+
flagError = "[setup-ide-files] --local and --staging are mutually exclusive.";
|
|
2629
|
+
}
|
|
2630
|
+
return { targets, force, dryRun, noGitignore, cleanup, devMode, repair, local, staging, all, unknown, flagError };
|
|
2631
|
+
}
|
|
2632
|
+
function cursorEnvironmentFromFlags(local, staging) {
|
|
2633
|
+
if (local) return "local";
|
|
2634
|
+
if (staging) return "staging";
|
|
2635
|
+
return "production";
|
|
2531
2636
|
}
|
|
2532
2637
|
function summarizeOutcomes(outcomes) {
|
|
2533
2638
|
const created = [];
|
|
@@ -2728,20 +2833,44 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2728
2833
|
|
|
2729
2834
|
` + cursorRuleBody();
|
|
2730
2835
|
if (o.targets.cursor) {
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2836
|
+
const cursorEnvironment = o.cursorEnvironment ?? "production";
|
|
2837
|
+
let npxPath = null;
|
|
2838
|
+
let cliPath;
|
|
2839
|
+
if (cursorEnvironment === "local") {
|
|
2840
|
+
let resolvedCliPath = o.cursorLocalCliPathOverride;
|
|
2841
|
+
if (resolvedCliPath === void 0) {
|
|
2842
|
+
resolvedCliPath = await resolveBuiltCliPathAsync({ searchFrom: [repoRoot, o.cwd] });
|
|
2843
|
+
}
|
|
2844
|
+
if (!resolvedCliPath) {
|
|
2845
|
+
return {
|
|
2846
|
+
exitCode: 1,
|
|
2847
|
+
repoRoot,
|
|
2848
|
+
outcomes,
|
|
2849
|
+
error: "[setup-ide-files] Local mode requires a built CLI at packages/mcp/dist/cli.cjs. Run pnpm build first."
|
|
2850
|
+
};
|
|
2851
|
+
}
|
|
2852
|
+
cliPath = resolvedCliPath;
|
|
2734
2853
|
} else {
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2854
|
+
if (o.npxPathOverride !== void 0) {
|
|
2855
|
+
npxPath = o.npxPathOverride;
|
|
2856
|
+
} else {
|
|
2857
|
+
npxPath = await resolveNpxPath();
|
|
2858
|
+
}
|
|
2859
|
+
if (!npxPath) {
|
|
2860
|
+
return {
|
|
2861
|
+
exitCode: 1,
|
|
2862
|
+
repoRoot,
|
|
2863
|
+
outcomes,
|
|
2864
|
+
error: "[setup-ide-files] Could not resolve a working npx executable. Install Node.js/npm or ensure npx is on PATH before configuring Cursor MCP."
|
|
2865
|
+
};
|
|
2866
|
+
}
|
|
2744
2867
|
}
|
|
2868
|
+
const cursorWriteOptions = {
|
|
2869
|
+
environment: cursorEnvironment,
|
|
2870
|
+
npxPath: npxPath ?? void 0,
|
|
2871
|
+
cliPath,
|
|
2872
|
+
repoRoot
|
|
2873
|
+
};
|
|
2745
2874
|
outcomes[".cursor/rules/memoraone-mcp.mdc"] = await writeManagedMarkdown(
|
|
2746
2875
|
repoRoot,
|
|
2747
2876
|
".cursor/rules/memoraone-mcp.mdc",
|
|
@@ -2751,7 +2880,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2751
2880
|
outcomes[".cursor/mcp.json"] = await writeIdeMcpJson(
|
|
2752
2881
|
repoRoot,
|
|
2753
2882
|
".cursor/mcp.json",
|
|
2754
|
-
(existing) => buildCursorMcpJsonBody(existing,
|
|
2883
|
+
(existing) => buildCursorMcpJsonBody(existing, cursorWriteOptions),
|
|
2755
2884
|
{ force: o.force, dryRun: o.dryRun }
|
|
2756
2885
|
);
|
|
2757
2886
|
const repoConfigPath = getCursorRepoMcpConfigPath(repoRoot);
|
|
@@ -2795,7 +2924,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2795
2924
|
cursorMcp = {
|
|
2796
2925
|
repoConfigPath,
|
|
2797
2926
|
repoOutcome,
|
|
2798
|
-
npxPath,
|
|
2927
|
+
...cursorEnvironment === "local" ? { cliPath } : { npxPath },
|
|
2799
2928
|
globalConfigPath,
|
|
2800
2929
|
globalMemoraoneRemoved,
|
|
2801
2930
|
globalBackupPath
|
|
@@ -2863,7 +2992,11 @@ description: MemoraOne MCP \u2014 IDE agent instructions
|
|
|
2863
2992
|
return { exitCode: 0, repoRoot, outcomes, cursorMcp, jetbrainsMcp, daemonCleanup };
|
|
2864
2993
|
}
|
|
2865
2994
|
async function cliSetupIdeFiles(argv) {
|
|
2866
|
-
const { targets, force, dryRun, noGitignore, cleanup, devMode, repair, unknown } = parseSetupIdeFlags(argv);
|
|
2995
|
+
const { targets, force, dryRun, noGitignore, cleanup, devMode, repair, local, staging, unknown, flagError } = parseSetupIdeFlags(argv);
|
|
2996
|
+
if (flagError) {
|
|
2997
|
+
console.error(flagError);
|
|
2998
|
+
return 1;
|
|
2999
|
+
}
|
|
2867
3000
|
if (unknown.length) {
|
|
2868
3001
|
console.error(`[setup-ide-files] Unknown option(s): ${unknown.join(", ")}`);
|
|
2869
3002
|
return 1;
|
|
@@ -2875,7 +3008,8 @@ async function cliSetupIdeFiles(argv) {
|
|
|
2875
3008
|
dryRun,
|
|
2876
3009
|
noGitignore,
|
|
2877
3010
|
devMode,
|
|
2878
|
-
repair
|
|
3011
|
+
repair,
|
|
3012
|
+
cursorEnvironment: cursorEnvironmentFromFlags(local, staging)
|
|
2879
3013
|
});
|
|
2880
3014
|
if (result.error) {
|
|
2881
3015
|
console.error(result.error);
|
|
@@ -2930,7 +3064,7 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
2930
3064
|
}
|
|
2931
3065
|
if (args.includes("--help") || args.includes("-h")) {
|
|
2932
3066
|
console.log(
|
|
2933
|
-
"Usage: memoraone-mcp [--version] [--help] [--daemon --project-id <uuid> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair]\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
|
|
3067
|
+
"Usage: memoraone-mcp [--version] [--help] [--daemon --project-id <uuid> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair]\n Cursor API environment (with --cursor or --all): --local (node + built cli.cjs + localhost) | --staging (npx + staging API)\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
|
|
2934
3068
|
);
|
|
2935
3069
|
process.exit(0);
|
|
2936
3070
|
}
|