@memoraone/mcp 0.1.32 → 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.
Files changed (2) hide show
  1. package/dist/cli.cjs +193 -68
  2. 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.32",
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((resolve8) => {
566
- this.waiters.push(resolve8);
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((resolve8, reject) => {
825
+ return new Promise((resolve9, reject) => {
826
826
  const tryConnect = (attempt) => {
827
- connect2(socketPath).then(resolve8).catch((err) => {
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((resolve8, reject) => {
901
- const socket = net.connect(socketPath, () => resolve8(socket));
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 fs7 = __toESM(require("fs/promises"), 1);
1145
+ var fs8 = __toESM(require("fs/promises"), 1);
1146
1146
  var os4 = __toESM(require("os"), 1);
1147
- var path9 = __toESM(require("path"), 1);
1147
+ var path10 = __toESM(require("path"), 1);
1148
1148
 
1149
1149
  // src/cleanup.ts
1150
1150
  var fs5 = __toESM(require("fs/promises"), 1);
@@ -1163,17 +1163,36 @@ 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
1165
  var MEMORAONE_LOCAL_API_URL = "http://localhost:3001";
1166
+ var MEMORAONE_STAGING_API_URL = "https://memora-api-staging-phbtrzocjq-uk.a.run.app";
1166
1167
  var MEMORAONE_STAGING_API_URL_PREFIX = "https://memora-api-staging-";
1167
- function buildMemoraoneCursorMcpServer(npxPath, workspaceRoot) {
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) {
1168
1174
  const env = {
1169
- MEMORAONE_API_URL: MEMORAONE_PROD_API_URL,
1175
+ MEMORAONE_API_URL: cursorMcpApiUrl(options.environment),
1170
1176
  MEMORAONE_IDE_TYPE: "cursor"
1171
1177
  };
1172
- if (workspaceRoot !== void 0) {
1173
- 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.");
1174
1193
  }
1175
1194
  return {
1176
- command: npxPath,
1195
+ command: options.npxPath,
1177
1196
  args: ["-y", "@memoraone/mcp@latest"],
1178
1197
  env
1179
1198
  };
@@ -1272,10 +1291,16 @@ async function resolveNpxPath() {
1272
1291
  }
1273
1292
  return null;
1274
1293
  }
1275
- function mergeCursorRepoMcpConfigObject(existing, npxPath, repoRoot) {
1294
+ function mergeCursorRepoMcpConfigObject(existing, writeOptions) {
1295
+ const environment = writeOptions.environment ?? "production";
1276
1296
  const base = existing && typeof existing === "object" ? { ...existing } : { mcpServers: {} };
1277
1297
  const mcpServers = typeof base.mcpServers === "object" && base.mcpServers !== null && !Array.isArray(base.mcpServers) ? { ...base.mcpServers } : {};
1278
- mcpServers.memoraone = buildMemoraoneCursorMcpServer(npxPath, repoRoot);
1298
+ mcpServers.memoraone = buildMemoraoneCursorMcpServer({
1299
+ environment,
1300
+ npxPath: writeOptions.npxPath,
1301
+ cliPath: writeOptions.cliPath,
1302
+ workspaceRoot: writeOptions.repoRoot
1303
+ });
1279
1304
  return { ...base, mcpServers };
1280
1305
  }
1281
1306
  function isMemoraoneManagedApiUrl(url) {
@@ -1395,9 +1420,13 @@ function logCursorMcpConfigAudit(prefix, audit) {
1395
1420
  }
1396
1421
  }
1397
1422
  function logCursorMcpCliSummary(info, dryRun) {
1398
- const { repoConfigPath, repoOutcome, npxPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
1423
+ const { repoConfigPath, repoOutcome, npxPath, cliPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
1399
1424
  console.log(`[setup-ide-files] Cursor repo MCP config: ${repoConfigPath}`);
1400
- console.log(`[setup-ide-files] Resolved npx: ${npxPath}`);
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
+ }
1401
1430
  if (repoBackupPath) {
1402
1431
  console.log(`[setup-ide-files] Cursor repo MCP config backup: ${repoBackupPath}`);
1403
1432
  }
@@ -2094,7 +2123,7 @@ async function buildJetBrainsMemoraoneServer(options) {
2094
2123
  async function verifyJetBrainsMcpHandshake(options) {
2095
2124
  const timeoutMs = options.timeoutMs ?? 15e3;
2096
2125
  const { server } = options;
2097
- return new Promise((resolve8) => {
2126
+ return new Promise((resolve9) => {
2098
2127
  let settled = false;
2099
2128
  const finish = (ok, detail) => {
2100
2129
  if (settled) return;
@@ -2104,7 +2133,7 @@ async function verifyJetBrainsMcpHandshake(options) {
2104
2133
  child.kill();
2105
2134
  } catch {
2106
2135
  }
2107
- resolve8({ ok, detail });
2136
+ resolve9({ ok, detail });
2108
2137
  };
2109
2138
  const child = (0, import_node_child_process4.spawn)(server.command, [...server.args], {
2110
2139
  env: { ...process.env, ...server.env },
@@ -2308,6 +2337,60 @@ function logJetBrainsMcpCliSummary(info, dryRun) {
2308
2337
  );
2309
2338
  }
2310
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
+
2311
2394
  // src/setupIdeFiles.ts
2312
2395
  var MANAGED_MARKER = "<!-- MemoraOne managed IDE helper -->";
2313
2396
  var GITIGNORE_MEMORAONE_COMMENT = "# MemoraOne local project binding / API key";
@@ -2323,15 +2406,15 @@ function buildMemoraoneMcpServer(ideType, command = "npx") {
2323
2406
  };
2324
2407
  }
2325
2408
  function assertUnderRepoRoot(repoRoot, absPath) {
2326
- const normRoot = path9.resolve(repoRoot) + path9.sep;
2327
- const normPath = path9.resolve(absPath);
2328
- if (normPath !== path9.resolve(repoRoot) && !normPath.startsWith(normRoot)) {
2409
+ const normRoot = path10.resolve(repoRoot) + path10.sep;
2410
+ const normPath = path10.resolve(absPath);
2411
+ if (normPath !== path10.resolve(repoRoot) && !normPath.startsWith(normRoot)) {
2329
2412
  throw new Error(`[setup-ide-files] Refusing to write outside repo root: ${absPath}`);
2330
2413
  }
2331
2414
  }
2332
- async function pathExists3(filePath) {
2415
+ async function pathExists4(filePath) {
2333
2416
  try {
2334
- await fs7.access(filePath);
2417
+ await fs8.access(filePath);
2335
2418
  return true;
2336
2419
  } catch {
2337
2420
  return false;
@@ -2352,12 +2435,12 @@ ${GITIGNORE_MEMORAONE_ENTRY}
2352
2435
  }
2353
2436
  async function ensureGitignoreMemoraone(repoRoot, opts) {
2354
2437
  if (opts.noGitignore) return "skipped";
2355
- const abs = path9.join(repoRoot, ".gitignore");
2438
+ const abs = path10.join(repoRoot, ".gitignore");
2356
2439
  assertUnderRepoRoot(repoRoot, abs);
2357
2440
  let prior = "";
2358
2441
  let existed = false;
2359
2442
  try {
2360
- prior = await fs7.readFile(abs, "utf8");
2443
+ prior = await fs8.readFile(abs, "utf8");
2361
2444
  existed = true;
2362
2445
  } catch (err) {
2363
2446
  const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
@@ -2368,22 +2451,22 @@ async function ensureGitignoreMemoraone(repoRoot, opts) {
2368
2451
  const separator = existed && prior.length > 0 ? prior.endsWith("\n") ? "\n" : "\n\n" : "";
2369
2452
  const next = (existed ? prior : "") + separator + block;
2370
2453
  if (opts.dryRun) return existed ? "updated" : "created";
2371
- await fs7.writeFile(abs, next, "utf8");
2454
+ await fs8.writeFile(abs, next, "utf8");
2372
2455
  return existed ? "updated" : "created";
2373
2456
  }
2374
2457
  async function findRepoRoot(startDir) {
2375
- let current = path9.resolve(startDir);
2376
- const root = path9.parse(current).root;
2458
+ let current = path10.resolve(startDir);
2459
+ const root = path10.parse(current).root;
2377
2460
  while (true) {
2378
- const gitPath = path9.join(current, ".git");
2379
- const m1Path = path9.join(current, "memoraone.m1");
2380
- if (await pathExists3(gitPath) || await pathExists3(m1Path)) {
2461
+ const gitPath = path10.join(current, ".git");
2462
+ const m1Path = path10.join(current, "memoraone.m1");
2463
+ if (await pathExists4(gitPath) || await pathExists4(m1Path)) {
2381
2464
  return current;
2382
2465
  }
2383
2466
  if (current === root) {
2384
2467
  return null;
2385
2468
  }
2386
- current = path9.dirname(current);
2469
+ current = path10.dirname(current);
2387
2470
  }
2388
2471
  }
2389
2472
  function stripLeadingLineComments3(text) {
@@ -2436,47 +2519,47 @@ function buildVscodeMcpJsonBody(existing) {
2436
2519
  const merged = { ...base, servers };
2437
2520
  return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
2438
2521
  }
2439
- function buildCursorMcpJsonBody(existing, npxPath, repoRoot) {
2440
- const merged = mergeCursorRepoMcpConfigObject(existing, npxPath, repoRoot);
2522
+ function buildCursorMcpJsonBody(existing, writeOptions) {
2523
+ const merged = mergeCursorRepoMcpConfigObject(existing, writeOptions);
2441
2524
  return mcpJsonHeader() + JSON.stringify(merged, null, 2) + "\n";
2442
2525
  }
2443
2526
  async function writeManagedMarkdown(repoRoot, relPath, fullContent, opts) {
2444
- const abs = path9.join(repoRoot, relPath);
2527
+ const abs = path10.join(repoRoot, relPath);
2445
2528
  assertUnderRepoRoot(repoRoot, abs);
2446
2529
  let prior = "";
2447
2530
  let existed = false;
2448
2531
  try {
2449
- prior = await fs7.readFile(abs, "utf8");
2532
+ prior = await fs8.readFile(abs, "utf8");
2450
2533
  existed = true;
2451
2534
  } catch (err) {
2452
2535
  if (err?.code !== "ENOENT") throw err;
2453
2536
  }
2454
2537
  if (!existed) {
2455
2538
  if (opts.dryRun) return "created";
2456
- await fs7.mkdir(path9.dirname(abs), { recursive: true });
2457
- await fs7.writeFile(abs, fullContent, "utf8");
2539
+ await fs8.mkdir(path10.dirname(abs), { recursive: true });
2540
+ await fs8.writeFile(abs, fullContent, "utf8");
2458
2541
  return "created";
2459
2542
  }
2460
2543
  if (prior.includes(MANAGED_MARKER)) {
2461
2544
  if (prior === fullContent) return "skipped";
2462
2545
  if (opts.dryRun) return "updated";
2463
- await fs7.mkdir(path9.dirname(abs), { recursive: true });
2464
- await fs7.writeFile(abs, fullContent, "utf8");
2546
+ await fs8.mkdir(path10.dirname(abs), { recursive: true });
2547
+ await fs8.writeFile(abs, fullContent, "utf8");
2465
2548
  return "updated";
2466
2549
  }
2467
2550
  if (!opts.force) return "skipped-untracked";
2468
2551
  if (opts.dryRun) return "updated";
2469
- await fs7.mkdir(path9.dirname(abs), { recursive: true });
2470
- await fs7.writeFile(abs, fullContent, "utf8");
2552
+ await fs8.mkdir(path10.dirname(abs), { recursive: true });
2553
+ await fs8.writeFile(abs, fullContent, "utf8");
2471
2554
  return "updated";
2472
2555
  }
2473
2556
  async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
2474
- const abs = path9.join(repoRoot, relPath);
2557
+ const abs = path10.join(repoRoot, relPath);
2475
2558
  assertUnderRepoRoot(repoRoot, abs);
2476
2559
  let raw = "";
2477
2560
  let existed = false;
2478
2561
  try {
2479
- raw = await fs7.readFile(abs, "utf8");
2562
+ raw = await fs8.readFile(abs, "utf8");
2480
2563
  existed = true;
2481
2564
  } catch (err) {
2482
2565
  if (err?.code !== "ENOENT") throw err;
@@ -2484,8 +2567,8 @@ async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
2484
2567
  if (!existed) {
2485
2568
  const body = buildBody(null);
2486
2569
  if (opts.dryRun) return "created";
2487
- await fs7.mkdir(path9.dirname(abs), { recursive: true });
2488
- await fs7.writeFile(abs, body, "utf8");
2570
+ await fs8.mkdir(path10.dirname(abs), { recursive: true });
2571
+ await fs8.writeFile(abs, body, "utf8");
2489
2572
  return "created";
2490
2573
  }
2491
2574
  const managed = raw.includes(MANAGED_MARKER);
@@ -2500,8 +2583,8 @@ async function writeIdeMcpJson(repoRoot, relPath, buildBody, opts) {
2500
2583
  const next = buildBody(parsed);
2501
2584
  if (managed && next === raw) return "skipped";
2502
2585
  if (opts.dryRun) return "updated";
2503
- await fs7.mkdir(path9.dirname(abs), { recursive: true });
2504
- await fs7.writeFile(abs, next, "utf8");
2586
+ await fs8.mkdir(path10.dirname(abs), { recursive: true });
2587
+ await fs8.writeFile(abs, next, "utf8");
2505
2588
  return "updated";
2506
2589
  }
2507
2590
  function parseSetupIdeFlags(argv) {
@@ -2515,6 +2598,8 @@ function parseSetupIdeFlags(argv) {
2515
2598
  let cleanup = false;
2516
2599
  let devMode = false;
2517
2600
  let repair = false;
2601
+ let local = false;
2602
+ let staging = false;
2518
2603
  const unknown = [];
2519
2604
  for (const a of argv) {
2520
2605
  if (a === "--cursor") cursor = true;
@@ -2527,6 +2612,8 @@ function parseSetupIdeFlags(argv) {
2527
2612
  else if (a === "--cleanup") cleanup = true;
2528
2613
  else if (a === "--dev") devMode = true;
2529
2614
  else if (a === "--repair") repair = true;
2615
+ else if (a === "--local") local = true;
2616
+ else if (a === "--staging") staging = true;
2530
2617
  else if (a.startsWith("-")) unknown.push(a);
2531
2618
  }
2532
2619
  const specific = cursor || vscode || jetbrains;
@@ -2536,7 +2623,16 @@ function parseSetupIdeFlags(argv) {
2536
2623
  } else {
2537
2624
  targets = { cursor, vscode, jetbrains };
2538
2625
  }
2539
- return { targets, force, dryRun, noGitignore, cleanup, devMode, repair, unknown };
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";
2540
2636
  }
2541
2637
  function summarizeOutcomes(outcomes) {
2542
2638
  const created = [];
@@ -2737,20 +2833,44 @@ description: MemoraOne MCP \u2014 IDE agent instructions
2737
2833
 
2738
2834
  ` + cursorRuleBody();
2739
2835
  if (o.targets.cursor) {
2740
- let npxPath;
2741
- if (o.npxPathOverride !== void 0) {
2742
- npxPath = o.npxPathOverride;
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;
2743
2853
  } else {
2744
- npxPath = await resolveNpxPath();
2745
- }
2746
- if (!npxPath) {
2747
- return {
2748
- exitCode: 1,
2749
- repoRoot,
2750
- outcomes,
2751
- 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."
2752
- };
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
+ }
2753
2867
  }
2868
+ const cursorWriteOptions = {
2869
+ environment: cursorEnvironment,
2870
+ npxPath: npxPath ?? void 0,
2871
+ cliPath,
2872
+ repoRoot
2873
+ };
2754
2874
  outcomes[".cursor/rules/memoraone-mcp.mdc"] = await writeManagedMarkdown(
2755
2875
  repoRoot,
2756
2876
  ".cursor/rules/memoraone-mcp.mdc",
@@ -2760,7 +2880,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
2760
2880
  outcomes[".cursor/mcp.json"] = await writeIdeMcpJson(
2761
2881
  repoRoot,
2762
2882
  ".cursor/mcp.json",
2763
- (existing) => buildCursorMcpJsonBody(existing, npxPath, repoRoot),
2883
+ (existing) => buildCursorMcpJsonBody(existing, cursorWriteOptions),
2764
2884
  { force: o.force, dryRun: o.dryRun }
2765
2885
  );
2766
2886
  const repoConfigPath = getCursorRepoMcpConfigPath(repoRoot);
@@ -2804,7 +2924,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
2804
2924
  cursorMcp = {
2805
2925
  repoConfigPath,
2806
2926
  repoOutcome,
2807
- npxPath,
2927
+ ...cursorEnvironment === "local" ? { cliPath } : { npxPath },
2808
2928
  globalConfigPath,
2809
2929
  globalMemoraoneRemoved,
2810
2930
  globalBackupPath
@@ -2872,7 +2992,11 @@ description: MemoraOne MCP \u2014 IDE agent instructions
2872
2992
  return { exitCode: 0, repoRoot, outcomes, cursorMcp, jetbrainsMcp, daemonCleanup };
2873
2993
  }
2874
2994
  async function cliSetupIdeFiles(argv) {
2875
- 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
+ }
2876
3000
  if (unknown.length) {
2877
3001
  console.error(`[setup-ide-files] Unknown option(s): ${unknown.join(", ")}`);
2878
3002
  return 1;
@@ -2884,7 +3008,8 @@ async function cliSetupIdeFiles(argv) {
2884
3008
  dryRun,
2885
3009
  noGitignore,
2886
3010
  devMode,
2887
- repair
3011
+ repair,
3012
+ cursorEnvironment: cursorEnvironmentFromFlags(local, staging)
2888
3013
  });
2889
3014
  if (result.error) {
2890
3015
  console.error(result.error);
@@ -2939,7 +3064,7 @@ if (args.includes("--version") || args.includes("-v")) {
2939
3064
  }
2940
3065
  if (args.includes("--help") || args.includes("-h")) {
2941
3066
  console.log(
2942
- "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]"
2943
3068
  );
2944
3069
  process.exit(0);
2945
3070
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoraone/mcp",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {