@memoraone/mcp 0.1.33 → 0.1.34

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 +325 -30
  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.33",
33
+ version: "0.1.34",
34
34
  type: "module",
35
35
  main: "dist/index.cjs",
36
36
  bin: {
@@ -1419,8 +1419,9 @@ function logCursorMcpConfigAudit(prefix, audit) {
1419
1419
  );
1420
1420
  }
1421
1421
  }
1422
- function logCursorMcpCliSummary(info, dryRun) {
1422
+ function logCursorMcpCliSummary(info, dryRun, opts) {
1423
1423
  const { repoConfigPath, repoOutcome, npxPath, cliPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
1424
+ const interactive = opts?.forInteractivePostSetup === true;
1424
1425
  console.log(`[setup-ide-files] Cursor repo MCP config: ${repoConfigPath}`);
1425
1426
  if (cliPath) {
1426
1427
  console.log(`[setup-ide-files] Resolved local CLI: ${cliPath}`);
@@ -1430,16 +1431,18 @@ function logCursorMcpCliSummary(info, dryRun) {
1430
1431
  if (repoBackupPath) {
1431
1432
  console.log(`[setup-ide-files] Cursor repo MCP config backup: ${repoBackupPath}`);
1432
1433
  }
1433
- if (repoOutcome === "created") {
1434
- console.log(
1435
- dryRun ? `[setup-ide-files] Cursor repo MCP config would be created: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config created: ${repoConfigPath}`
1436
- );
1437
- } else if (repoOutcome === "updated") {
1438
- console.log(
1439
- dryRun ? `[setup-ide-files] Cursor repo MCP config would be updated: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config updated: ${repoConfigPath}`
1440
- );
1441
- } else if (repoOutcome === "skipped") {
1442
- console.log(`[setup-ide-files] Cursor repo MCP config unchanged: ${repoConfigPath}`);
1434
+ if (!interactive) {
1435
+ if (repoOutcome === "created") {
1436
+ console.log(
1437
+ dryRun ? `[setup-ide-files] Cursor repo MCP config would be created: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config created: ${repoConfigPath}`
1438
+ );
1439
+ } else if (repoOutcome === "updated") {
1440
+ console.log(
1441
+ dryRun ? `[setup-ide-files] Cursor repo MCP config would be updated: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config updated: ${repoConfigPath}`
1442
+ );
1443
+ } else if (repoOutcome === "skipped") {
1444
+ console.log(`[setup-ide-files] Cursor repo MCP config unchanged: ${repoConfigPath}`);
1445
+ }
1443
1446
  }
1444
1447
  if (globalMemoraoneRemoved && globalConfigPath) {
1445
1448
  console.log(
@@ -1456,9 +1459,11 @@ function logCursorMcpCliSummary(info, dryRun) {
1456
1459
  console.log(
1457
1460
  "[setup-ide-files] Each Cursor window uses this repo\u2019s .cursor/mcp.json (separate MCP process per repo)."
1458
1461
  );
1459
- console.log(
1460
- "[setup-ide-files] Fully quit Cursor and reopen this repo for MCP changes to take effect."
1461
- );
1462
+ if (!interactive) {
1463
+ console.log(
1464
+ "[setup-ide-files] Fully quit Cursor and reopen this repo for MCP changes to take effect."
1465
+ );
1466
+ }
1462
1467
  }
1463
1468
 
1464
1469
  // src/cleanup.ts
@@ -2391,6 +2396,234 @@ async function resolveBuiltCliPathAsync(options) {
2391
2396
  return null;
2392
2397
  }
2393
2398
 
2399
+ // src/openCursorMcpSettings.ts
2400
+ var import_node_child_process5 = require("child_process");
2401
+ var readline4 = __toESM(require("readline/promises"), 1);
2402
+ var import_node_util3 = require("util");
2403
+
2404
+ // src/terminalPresentation.ts
2405
+ var ANSI = {
2406
+ reset: "\x1B[0m",
2407
+ bold: "\x1B[1m",
2408
+ dim: "\x1B[2m",
2409
+ green: "\x1B[32m",
2410
+ yellow: "\x1B[33m",
2411
+ cyan: "\x1B[36m"
2412
+ };
2413
+ function isCiLikeEnv(env = process.env) {
2414
+ if (env.CI === "true" || env.CI === "1") return true;
2415
+ if (env.GITHUB_ACTIONS === "true" || env.GITHUB_ACTIONS === "1") return true;
2416
+ if (env.GITLAB_CI === "true" || env.GITLAB_CI === "1") return true;
2417
+ if (env.CIRCLECI === "true" || env.CIRCLECI === "1") return true;
2418
+ if (env.BUILDKITE === "true" || env.BUILDKITE === "1") return true;
2419
+ if (typeof env.CI === "string" && env.CI.trim() !== "" && env.CI !== "0" && env.CI !== "false") {
2420
+ return true;
2421
+ }
2422
+ return false;
2423
+ }
2424
+ function shouldEnableAnsiColor(opts = {}) {
2425
+ if (typeof opts.color === "boolean") return opts.color;
2426
+ const env = opts.env ?? process.env;
2427
+ if (env.NO_COLOR !== void 0) return false;
2428
+ if (isCiLikeEnv(env)) return false;
2429
+ const tty = opts.stdoutIsTty ?? process.stdout.isTTY === true;
2430
+ return tty;
2431
+ }
2432
+ function shouldUseUnicodeSymbols(opts = {}) {
2433
+ if (typeof opts.unicode === "boolean") return opts.unicode;
2434
+ const env = opts.env ?? process.env;
2435
+ const tty = opts.stdoutIsTty ?? process.stdout.isTTY === true;
2436
+ if (!tty) return false;
2437
+ if (env.TERM === "dumb") return false;
2438
+ if (process.platform === "win32") {
2439
+ return Boolean(
2440
+ env.WT_SESSION || env.WT_PROFILE_ID || env.ConEmuANSI === "ON" || env.TERM_PROGRAM === "vscode" || env.TERM_PROGRAM === "cursor" || typeof env.TERM === "string" && env.TERM !== "" && env.TERM !== "dumb"
2441
+ );
2442
+ }
2443
+ return true;
2444
+ }
2445
+ function paint(enabled, code, text) {
2446
+ if (!enabled || text === "") return text;
2447
+ return `${code}${text}${ANSI.reset}`;
2448
+ }
2449
+ function createTerminalPresentation(opts = {}) {
2450
+ const color = shouldEnableAnsiColor(opts);
2451
+ const unicode = shouldUseUnicodeSymbols(opts);
2452
+ const successSymbol = unicode ? "\u2713" : "[OK]";
2453
+ const warningSymbol = unicode ? "\u26A0" : "[WARN]";
2454
+ const nextActionPrefix = unicode ? "\u2192" : "Next:";
2455
+ return {
2456
+ color,
2457
+ unicode,
2458
+ bold: (text) => paint(color, ANSI.bold, text),
2459
+ green: (text) => paint(color, ANSI.green, text),
2460
+ cyan: (text) => paint(color, ANSI.cyan, text),
2461
+ yellow: (text) => paint(color, ANSI.yellow, text),
2462
+ dim: (text) => paint(color, ANSI.dim, text),
2463
+ successSymbol,
2464
+ warningSymbol,
2465
+ nextActionPrefix,
2466
+ successLine: (message) => paint(color, ANSI.green, `${successSymbol} ${message}`),
2467
+ warningLine: (message) => paint(color, ANSI.yellow, `${warningSymbol} ${message}`),
2468
+ nextActionLine: (message) => `${nextActionPrefix} ${message}`,
2469
+ heading: (text) => paint(color, ANSI.bold, text),
2470
+ indent: (text) => ` ${text}`
2471
+ };
2472
+ }
2473
+
2474
+ // src/openCursorMcpSettings.ts
2475
+ var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process5.execFile);
2476
+ var OPEN_CURSOR_MCP_SETTINGS_PROMPT = "Open Cursor MCP settings now? [Y/n] ";
2477
+ function resolvePresentation(deps) {
2478
+ if (deps.presentation) return deps.presentation;
2479
+ const opts = {
2480
+ env: deps.env ?? process.env,
2481
+ stdoutIsTty: deps.stdoutIsTty ?? process.stdout.isTTY === true,
2482
+ color: deps.color,
2483
+ unicode: deps.unicode
2484
+ };
2485
+ return createTerminalPresentation(opts);
2486
+ }
2487
+ function shouldPromptOpenCursorMcpSettings(opts) {
2488
+ if (!opts.explicitCursor) return false;
2489
+ if (opts.all) return false;
2490
+ if (opts.dryRun) return false;
2491
+ if (!opts.stdinIsTty) return false;
2492
+ if (isCiLikeEnv(opts.env ?? process.env)) return false;
2493
+ return true;
2494
+ }
2495
+ function isYesDefaultAnswer(answer) {
2496
+ const trimmed = answer.trim();
2497
+ if (trimmed === "") return true;
2498
+ if (/^y(es)?$/i.test(trimmed)) return true;
2499
+ if (/^n(o)?$/i.test(trimmed)) return false;
2500
+ return false;
2501
+ }
2502
+ async function confirmYesDefault(question, deps = {}) {
2503
+ if (deps.ask) {
2504
+ return isYesDefaultAnswer(await deps.ask(question));
2505
+ }
2506
+ const input2 = deps.input ?? process.stdin;
2507
+ const output2 = deps.output ?? process.stdout;
2508
+ if (!("isTTY" in input2) || !input2.isTTY) {
2509
+ return false;
2510
+ }
2511
+ const rl = readline4.createInterface({ input: input2, output: output2 });
2512
+ try {
2513
+ const answer = await rl.question(question.endsWith(" ") ? question : `${question} `);
2514
+ return isYesDefaultAnswer(answer);
2515
+ } finally {
2516
+ rl.close();
2517
+ }
2518
+ }
2519
+ function collectOutcomePaths(outcomes) {
2520
+ const created = [];
2521
+ const updated = [];
2522
+ for (const [file, outcome] of Object.entries(outcomes)) {
2523
+ if (outcome === "created") created.push(file);
2524
+ else if (outcome === "updated") updated.push(file);
2525
+ }
2526
+ return { created, updated };
2527
+ }
2528
+ function formatCursorSetupCompletedSummary(opts, presentation = createTerminalPresentation({ color: false, unicode: false })) {
2529
+ const { created, updated } = collectOutcomePaths(opts.outcomes);
2530
+ const tp = presentation;
2531
+ const lines = [
2532
+ tp.successLine("MemoraOne setup completed for Cursor"),
2533
+ "",
2534
+ tp.heading("Repository"),
2535
+ tp.indent(tp.cyan(opts.repoRoot)),
2536
+ "",
2537
+ tp.heading("Changes")
2538
+ ];
2539
+ if (created.length === 0 && updated.length === 0) {
2540
+ lines.push(tp.indent(tp.dim("No file changes needed")));
2541
+ } else {
2542
+ if (created.length) {
2543
+ lines.push(tp.indent(`Created: ${created.join(", ")}`));
2544
+ }
2545
+ if (updated.length) {
2546
+ lines.push(tp.indent(`Updated: ${updated.join(", ")}`));
2547
+ }
2548
+ }
2549
+ return lines;
2550
+ }
2551
+ function printCursorSetupCompletedSummary(opts, println = console.log, presentation) {
2552
+ const tp = presentation ?? createTerminalPresentation();
2553
+ for (const line of formatCursorSetupCompletedSummary(opts, tp)) {
2554
+ println(line);
2555
+ }
2556
+ }
2557
+ function macosOpenCursorMcpSettingsAppleScript() {
2558
+ return [
2559
+ 'tell application "Cursor" to activate',
2560
+ "delay 0.5",
2561
+ 'tell application "System Events"',
2562
+ 'keystroke "p" using {command down, shift down}',
2563
+ "delay 0.4",
2564
+ 'keystroke "View: Open MCP Settings"',
2565
+ "delay 0.4",
2566
+ "key code 36",
2567
+ "end tell"
2568
+ ].join("\n");
2569
+ }
2570
+ async function openCursorMcpSettingsViaOsascript(execFileImpl = execFileAsync3) {
2571
+ await execFileImpl("osascript", ["-e", macosOpenCursorMcpSettingsAppleScript()], {
2572
+ timeout: 3e4
2573
+ });
2574
+ }
2575
+ function manualCursorMcpSettingsSteps(platform) {
2576
+ const chord = platform === "darwin" ? "Command + Shift + P" : "Ctrl + Shift + P";
2577
+ return [
2578
+ "To finish setup manually:",
2579
+ "1. Open this repository in Cursor.",
2580
+ `2. Press ${chord}.`,
2581
+ '3. Run "View: Open MCP Settings".',
2582
+ '4. Find "memoraone" and enable it.',
2583
+ "5. Confirm it turns green.",
2584
+ "6. Return to MemoraOne Studio and refresh Sources."
2585
+ ];
2586
+ }
2587
+ function printManualCursorMcpSettingsSteps(platform, println = console.log) {
2588
+ for (const line of manualCursorMcpSettingsSteps(platform)) {
2589
+ println(line);
2590
+ }
2591
+ }
2592
+ function formatOpenCursorMcpSettingsPrompt(presentation = createTerminalPresentation({ color: false, unicode: false })) {
2593
+ return `${presentation.indent(OPEN_CURSOR_MCP_SETTINGS_PROMPT.trimEnd())} `;
2594
+ }
2595
+ async function runOpenCursorMcpSettingsFlow(deps = {}) {
2596
+ const platform = deps.platform ?? process.platform;
2597
+ const println = deps.println ?? console.log;
2598
+ const tp = resolvePresentation(deps);
2599
+ const confirm = deps.confirm ?? ((question) => confirmYesDefault(question));
2600
+ println("");
2601
+ println(tp.heading("Next"));
2602
+ const yes = await confirm(formatOpenCursorMcpSettingsPrompt(tp));
2603
+ if (!yes) {
2604
+ printManualCursorMcpSettingsSteps(platform, println);
2605
+ return;
2606
+ }
2607
+ if (platform === "darwin") {
2608
+ println(tp.warningLine("macOS may request Automation or Accessibility permission."));
2609
+ try {
2610
+ const open = deps.openViaOsascript ?? (() => openCursorMcpSettingsViaOsascript(deps.execFile ?? execFileAsync3));
2611
+ await open();
2612
+ println(tp.successLine('Confirm "memoraone" is enabled and green'));
2613
+ println(tp.nextActionLine("Return to MemoraOne Studio and refresh Sources"));
2614
+ } catch (err) {
2615
+ const detail = err instanceof Error ? err.message : String(err);
2616
+ println(tp.warningLine(`Could not open Cursor MCP settings automatically (${detail}).`));
2617
+ println(
2618
+ "Permission may be required at: System Settings \u2192 Privacy & Security \u2192 Accessibility"
2619
+ );
2620
+ printManualCursorMcpSettingsSteps("darwin", println);
2621
+ }
2622
+ return;
2623
+ }
2624
+ printManualCursorMcpSettingsSteps(platform, println);
2625
+ }
2626
+
2394
2627
  // src/setupIdeFiles.ts
2395
2628
  var MANAGED_MARKER = "<!-- MemoraOne managed IDE helper -->";
2396
2629
  var GITIGNORE_MEMORAONE_COMMENT = "# MemoraOne local project binding / API key";
@@ -2627,7 +2860,21 @@ function parseSetupIdeFlags(argv) {
2627
2860
  if (local && staging) {
2628
2861
  flagError = "[setup-ide-files] --local and --staging are mutually exclusive.";
2629
2862
  }
2630
- return { targets, force, dryRun, noGitignore, cleanup, devMode, repair, local, staging, all, unknown, flagError };
2863
+ return {
2864
+ targets,
2865
+ force,
2866
+ dryRun,
2867
+ noGitignore,
2868
+ cleanup,
2869
+ devMode,
2870
+ repair,
2871
+ local,
2872
+ staging,
2873
+ all,
2874
+ explicitCursor: cursor,
2875
+ unknown,
2876
+ flagError
2877
+ };
2631
2878
  }
2632
2879
  function cursorEnvironmentFromFlags(local, staging) {
2633
2880
  if (local) return "local";
@@ -2892,7 +3139,7 @@ description: MemoraOne MCP \u2014 IDE agent instructions
2892
3139
  homeDir: o.homeDir,
2893
3140
  explicitPath: o.cursorGlobalMcpConfigPath
2894
3141
  });
2895
- if (!globalDetection.ok) {
3142
+ if (globalDetection.ok === false) {
2896
3143
  return {
2897
3144
  exitCode: 1,
2898
3145
  repoRoot,
@@ -2991,8 +3238,22 @@ description: MemoraOne MCP \u2014 IDE agent instructions
2991
3238
  }
2992
3239
  return { exitCode: 0, repoRoot, outcomes, cursorMcp, jetbrainsMcp, daemonCleanup };
2993
3240
  }
2994
- async function cliSetupIdeFiles(argv) {
2995
- const { targets, force, dryRun, noGitignore, cleanup, devMode, repair, local, staging, unknown, flagError } = parseSetupIdeFlags(argv);
3241
+ async function cliSetupIdeFiles(argv, options = {}) {
3242
+ const {
3243
+ targets,
3244
+ force,
3245
+ dryRun,
3246
+ noGitignore,
3247
+ cleanup,
3248
+ devMode,
3249
+ repair,
3250
+ local,
3251
+ staging,
3252
+ all,
3253
+ explicitCursor,
3254
+ unknown,
3255
+ flagError
3256
+ } = parseSetupIdeFlags(argv);
2996
3257
  if (flagError) {
2997
3258
  console.error(flagError);
2998
3259
  return 1;
@@ -3001,15 +3262,27 @@ async function cliSetupIdeFiles(argv) {
3001
3262
  console.error(`[setup-ide-files] Unknown option(s): ${unknown.join(", ")}`);
3002
3263
  return 1;
3003
3264
  }
3265
+ const cwd = options.cwd ?? process.cwd();
3266
+ const openDeps = options.openCursorMcpSettings ?? {};
3267
+ const stdinIsTty = openDeps.stdinIsTty ?? process.stdin.isTTY === true;
3268
+ const env = openDeps.env ?? process.env;
3269
+ const promptOpenCursorSettings = shouldPromptOpenCursorMcpSettings({
3270
+ explicitCursor,
3271
+ all,
3272
+ dryRun,
3273
+ stdinIsTty,
3274
+ env
3275
+ });
3004
3276
  const result = await runSetupIdeFiles({
3005
- cwd: process.cwd(),
3277
+ cwd,
3006
3278
  targets,
3007
3279
  force,
3008
3280
  dryRun,
3009
- noGitignore,
3281
+ noGitignore: options.setupOverrides?.noGitignore ?? noGitignore,
3010
3282
  devMode,
3011
3283
  repair,
3012
- cursorEnvironment: cursorEnvironmentFromFlags(local, staging)
3284
+ cursorEnvironment: cursorEnvironmentFromFlags(local, staging),
3285
+ ...options.setupOverrides
3013
3286
  });
3014
3287
  if (result.error) {
3015
3288
  console.error(result.error);
@@ -3026,23 +3299,45 @@ async function cliSetupIdeFiles(argv) {
3026
3299
  logSetupIdeCleanupSummary(result.daemonCleanup);
3027
3300
  }
3028
3301
  if (targets.cursor && result.cursorMcp) {
3029
- logCursorMcpCliSummary(result.cursorMcp, dryRun);
3302
+ logCursorMcpCliSummary(result.cursorMcp, dryRun, {
3303
+ forInteractivePostSetup: promptOpenCursorSettings
3304
+ });
3030
3305
  }
3031
3306
  if (targets.jetbrains && result.jetbrainsMcp) {
3032
3307
  logJetBrainsMcpCliSummary(result.jetbrainsMcp, dryRun);
3033
3308
  }
3034
- summarizeOutcomes(result.outcomes);
3035
- if (dryRun) {
3036
- console.log("[setup-ide-files] Dry run: no files written.");
3037
- if (result.daemonCleanup && !result.daemonCleanup.skipped) {
3038
- console.log("[setup-ide-files] Dry run: no daemons stopped, no sockets removed.");
3309
+ if (promptOpenCursorSettings && result.repoRoot) {
3310
+ const presentation = openDeps.presentation ?? createTerminalPresentation({
3311
+ env,
3312
+ stdoutIsTty: openDeps.stdoutIsTty ?? process.stdout.isTTY === true,
3313
+ color: openDeps.color,
3314
+ unicode: openDeps.unicode
3315
+ });
3316
+ printCursorSetupCompletedSummary(
3317
+ { repoRoot: result.repoRoot, outcomes: result.outcomes },
3318
+ openDeps.println,
3319
+ presentation
3320
+ );
3321
+ await runOpenCursorMcpSettingsFlow({
3322
+ ...openDeps,
3323
+ stdinIsTty,
3324
+ env,
3325
+ presentation
3326
+ });
3327
+ } else {
3328
+ summarizeOutcomes(result.outcomes);
3329
+ if (dryRun) {
3330
+ console.log("[setup-ide-files] Dry run: no files written.");
3331
+ if (result.daemonCleanup && !result.daemonCleanup.skipped) {
3332
+ console.log("[setup-ide-files] Dry run: no daemons stopped, no sockets removed.");
3333
+ }
3039
3334
  }
3335
+ console.log(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
3040
3336
  }
3041
- console.log(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
3042
3337
  if (cleanup) {
3043
3338
  console.log("[setup-ide-files] Running additional full-project cleanup (--cleanup)...");
3044
3339
  const cleanupResult = await runCleanup({
3045
- cwd: process.cwd(),
3340
+ cwd,
3046
3341
  dryRun,
3047
3342
  allProjects: false,
3048
3343
  assumeYes: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoraone/mcp",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {