@memoraone/mcp 0.1.37 → 0.1.38

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 +237 -134
  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.37",
33
+ version: "0.1.38",
34
34
  type: "module",
35
35
  main: "dist/index.cjs",
36
36
  bin: {
@@ -2236,45 +2236,46 @@ function logCursorMcpConfigAudit(prefix, audit) {
2236
2236
  function logCursorMcpCliSummary(info, dryRun, opts) {
2237
2237
  const { repoConfigPath, repoOutcome, npxPath, cliPath, repoBackupPath, globalConfigPath, globalMemoraoneRemoved, globalBackupPath } = info;
2238
2238
  const interactive = opts?.forInteractivePostSetup === true;
2239
- console.log(`[setup-ide-files] Cursor repo MCP config: ${repoConfigPath}`);
2239
+ const println = opts?.println ?? console.log;
2240
+ println(`[setup-ide-files] Cursor repo MCP config: ${repoConfigPath}`);
2240
2241
  if (cliPath) {
2241
- console.log(`[setup-ide-files] Resolved local CLI: ${cliPath}`);
2242
+ println(`[setup-ide-files] Resolved local CLI: ${cliPath}`);
2242
2243
  } else if (npxPath) {
2243
- console.log(`[setup-ide-files] Resolved npx: ${npxPath}`);
2244
+ println(`[setup-ide-files] Resolved npx: ${npxPath}`);
2244
2245
  }
2245
2246
  if (repoBackupPath) {
2246
- console.log(`[setup-ide-files] Cursor repo MCP config backup: ${repoBackupPath}`);
2247
+ println(`[setup-ide-files] Cursor repo MCP config backup: ${repoBackupPath}`);
2247
2248
  }
2248
2249
  if (!interactive) {
2249
2250
  if (repoOutcome === "created") {
2250
- console.log(
2251
+ println(
2251
2252
  dryRun ? `[setup-ide-files] Cursor repo MCP config would be created: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config created: ${repoConfigPath}`
2252
2253
  );
2253
2254
  } else if (repoOutcome === "updated") {
2254
- console.log(
2255
+ println(
2255
2256
  dryRun ? `[setup-ide-files] Cursor repo MCP config would be updated: ${repoConfigPath}` : `[setup-ide-files] Cursor repo MCP config updated: ${repoConfigPath}`
2256
2257
  );
2257
2258
  } else if (repoOutcome === "skipped") {
2258
- console.log(`[setup-ide-files] Cursor repo MCP config unchanged: ${repoConfigPath}`);
2259
+ println(`[setup-ide-files] Cursor repo MCP config unchanged: ${repoConfigPath}`);
2259
2260
  }
2260
2261
  }
2261
2262
  if (globalMemoraoneRemoved && globalConfigPath) {
2262
- console.log(
2263
+ println(
2263
2264
  dryRun ? `[setup-ide-files] Would remove memoraone from Cursor global MCP config: ${globalConfigPath}` : `[setup-ide-files] Removed memoraone from Cursor global MCP config: ${globalConfigPath}`
2264
2265
  );
2265
2266
  if (globalBackupPath) {
2266
- console.log(`[setup-ide-files] Cursor global MCP config backup: ${globalBackupPath}`);
2267
+ println(`[setup-ide-files] Cursor global MCP config backup: ${globalBackupPath}`);
2267
2268
  }
2268
2269
  } else if (globalConfigPath) {
2269
- console.log(
2270
+ println(
2270
2271
  `[setup-ide-files] Cursor global MCP config unchanged (no managed memoraone to remove): ${globalConfigPath}`
2271
2272
  );
2272
2273
  }
2273
- console.log(
2274
+ println(
2274
2275
  "[setup-ide-files] Each Cursor window uses this repo\u2019s .cursor/mcp.json (separate MCP process per repo)."
2275
2276
  );
2276
2277
  if (!interactive) {
2277
- console.log(
2278
+ println(
2278
2279
  "[setup-ide-files] Fully quit Cursor and reopen this repo for MCP changes to take effect."
2279
2280
  );
2280
2281
  }
@@ -3472,12 +3473,21 @@ async function buildJetBrainsMemoraoneServer(options) {
3472
3473
  apiUrl: options.apiUrl
3473
3474
  });
3474
3475
  }
3476
+ function isOptionalJetBrainsHandshakeUnavailable(detail) {
3477
+ if (!detail) return false;
3478
+ if (detail.includes("-32601")) return true;
3479
+ if (/Method not found/i.test(detail)) return true;
3480
+ return false;
3481
+ }
3482
+ function formatOptionalJetBrainsHandshakeUnavailableDetail(detail) {
3483
+ return "MCP handshake optional verification unavailable while configuration succeeded" + (detail ? ` (${detail})` : "");
3484
+ }
3475
3485
  async function verifyJetBrainsMcpHandshake(options) {
3476
3486
  const timeoutMs = options.timeoutMs ?? 15e3;
3477
3487
  const { server } = options;
3478
3488
  return new Promise((resolve17) => {
3479
3489
  let settled = false;
3480
- const finish = (ok, detail) => {
3490
+ const finish = (ok, detail, optionalUnavailable) => {
3481
3491
  if (settled) return;
3482
3492
  settled = true;
3483
3493
  clearTimeout(timer);
@@ -3485,7 +3495,7 @@ async function verifyJetBrainsMcpHandshake(options) {
3485
3495
  child.kill();
3486
3496
  } catch {
3487
3497
  }
3488
- resolve17({ ok, detail });
3498
+ resolve17({ ok, detail, optionalUnavailable });
3489
3499
  };
3490
3500
  const child = (0, import_node_child_process5.spawn)(server.command, [...server.args], {
3491
3501
  env: { ...process.env, ...server.env },
@@ -3525,7 +3535,12 @@ async function verifyJetBrainsMcpHandshake(options) {
3525
3535
  finish(true, "initialize OK; tools/list OK");
3526
3536
  }
3527
3537
  if (msg.error) {
3528
- finish(false, `JSON-RPC error: ${JSON.stringify(msg.error)}`);
3538
+ const errDetail = `JSON-RPC error: ${JSON.stringify(msg.error)}`;
3539
+ if (isOptionalJetBrainsHandshakeUnavailable(errDetail)) {
3540
+ finish(true, errDetail, true);
3541
+ } else {
3542
+ finish(false, errDetail);
3543
+ }
3529
3544
  }
3530
3545
  }
3531
3546
  });
@@ -3637,47 +3652,60 @@ async function setupJetBrainsMcpConfig(options) {
3637
3652
  if (options.verify !== false) {
3638
3653
  const verify = await verifyJetBrainsMcpHandshake({ server: memoraone });
3639
3654
  verifyOk = verify.ok;
3640
- verifyDetail = verify.detail;
3641
- repairActions.push({ type: "verify-handshake", ok: verify.ok, detail: verify.detail });
3655
+ verifyDetail = verify.optionalUnavailable ? formatOptionalJetBrainsHandshakeUnavailableDetail(verify.detail) : verify.detail;
3656
+ repairActions.push({
3657
+ type: "verify-handshake",
3658
+ ok: verify.ok,
3659
+ detail: verifyDetail ?? verify.detail
3660
+ });
3642
3661
  }
3643
3662
  return { outcome, backupPath, repairActions, verifyOk, verifyDetail, memoraone };
3644
3663
  }
3645
- function logJetBrainsMcpCliSummary(info, dryRun) {
3664
+ function formatJetBrainsHandshakeLogLine(action) {
3665
+ const optional = /optional verification unavailable/i.test(action.detail) || isOptionalJetBrainsHandshakeUnavailable(action.detail);
3666
+ if (optional) {
3667
+ if (/optional verification unavailable/i.test(action.detail)) {
3668
+ return `[setup-ide-files] ${action.detail}`;
3669
+ }
3670
+ return `[setup-ide-files] ${formatOptionalJetBrainsHandshakeUnavailableDetail(action.detail)}`;
3671
+ }
3672
+ if (action.ok) {
3673
+ return `[setup-ide-files] MCP handshake verification: ${action.detail}`;
3674
+ }
3675
+ return `[setup-ide-files] MCP handshake verification skipped/failed: ${action.detail}`;
3676
+ }
3677
+ function logJetBrainsMcpCliSummary(info, dryRun, println = console.log) {
3646
3678
  for (const action of info.repairActions) {
3647
3679
  if (action.type === "found-config") {
3648
- console.log(`[setup-ide-files] Found JetBrains MCP config (${action.location.kind}): ${action.location.path}`);
3680
+ println(`[setup-ide-files] Found JetBrains MCP config (${action.location.kind}): ${action.location.path}`);
3649
3681
  } else if (action.type === "repaired-zero-byte") {
3650
- console.log(`[setup-ide-files] Repaired zero-byte MCP config: ${action.path}`);
3651
- console.log(`[setup-ide-files] Backup: ${action.backupPath}`);
3682
+ println(`[setup-ide-files] Repaired zero-byte MCP config: ${action.path}`);
3683
+ println(`[setup-ide-files] Backup: ${action.backupPath}`);
3652
3684
  } else if (action.type === "backed-up-conflicting-project-config") {
3653
- console.log(`[setup-ide-files] Backed up conflicting project MCP config: ${action.path}`);
3654
- console.log(`[setup-ide-files] Backup: ${action.backupPath}`);
3685
+ println(`[setup-ide-files] Backed up conflicting project MCP config: ${action.path}`);
3686
+ println(`[setup-ide-files] Backup: ${action.backupPath}`);
3655
3687
  } else if (action.type === "removed-project-memoraone") {
3656
- console.log(`[setup-ide-files] Removed project-scoped memoraone definition: ${action.path}`);
3688
+ println(`[setup-ide-files] Removed project-scoped memoraone definition: ${action.path}`);
3657
3689
  } else if (action.type === "verify-handshake") {
3658
- if (action.ok) {
3659
- console.log(`[setup-ide-files] MCP handshake verification: ${action.detail}`);
3660
- } else {
3661
- console.log(`[setup-ide-files] MCP handshake verification skipped/failed: ${action.detail}`);
3662
- }
3690
+ println(formatJetBrainsHandshakeLogLine(action));
3663
3691
  }
3664
3692
  }
3665
3693
  const prefix = dryRun ? "would be " : "";
3666
3694
  if (info.outcome === "created") {
3667
- console.log(`[setup-ide-files] JetBrains global MCP config ${prefix}created: ${info.activeConfigPath}`);
3695
+ println(`[setup-ide-files] JetBrains global MCP config ${prefix}created: ${info.activeConfigPath}`);
3668
3696
  } else if (info.outcome === "updated") {
3669
- console.log(`[setup-ide-files] JetBrains global MCP config ${prefix}updated: ${info.activeConfigPath}`);
3697
+ println(`[setup-ide-files] JetBrains global MCP config ${prefix}updated: ${info.activeConfigPath}`);
3670
3698
  } else {
3671
- console.log(`[setup-ide-files] JetBrains global MCP config unchanged: ${info.activeConfigPath}`);
3699
+ println(`[setup-ide-files] JetBrains global MCP config unchanged: ${info.activeConfigPath}`);
3672
3700
  }
3673
3701
  if (info.backupPath) {
3674
- console.log(`[setup-ide-files] JetBrains global MCP config backup: ${info.backupPath}`);
3702
+ println(`[setup-ide-files] JetBrains global MCP config backup: ${info.backupPath}`);
3675
3703
  }
3676
3704
  if (info.npxPath) {
3677
- console.log(`[setup-ide-files] Resolved npx: ${info.npxPath}`);
3705
+ println(`[setup-ide-files] Resolved npx: ${info.npxPath}`);
3678
3706
  }
3679
- console.log(`[setup-ide-files] Final active JetBrains MCP config: ${info.activeConfigPath}`);
3680
- console.log(
3707
+ println(`[setup-ide-files] Final active JetBrains MCP config: ${info.activeConfigPath}`);
3708
+ println(
3681
3709
  "[setup-ide-files] Fully quit JetBrains IDE and reopen this repo for MCP changes to take effect."
3682
3710
  );
3683
3711
  }
@@ -3750,6 +3778,7 @@ function createTerminalPresentation(opts = {}) {
3750
3778
  warningSymbol,
3751
3779
  nextActionPrefix,
3752
3780
  successLine: (message) => paint(color, ANSI.green, `${successSymbol} ${message}`),
3781
+ checkLine: (message) => `${paint(color, ANSI.green, successSymbol)} ${message}`,
3753
3782
  warningLine: (message) => paint(color, ANSI.yellow, `${warningSymbol} ${message}`),
3754
3783
  nextActionLine: (message) => `${nextActionPrefix} ${message}`,
3755
3784
  heading: (text) => paint(color, ANSI.bold, text),
@@ -3802,44 +3831,6 @@ async function confirmYesDefault(question, deps = {}) {
3802
3831
  rl.close();
3803
3832
  }
3804
3833
  }
3805
- function collectOutcomePaths(outcomes) {
3806
- const created = [];
3807
- const updated = [];
3808
- for (const [file, outcome] of Object.entries(outcomes)) {
3809
- if (outcome === "created") created.push(file);
3810
- else if (outcome === "updated") updated.push(file);
3811
- }
3812
- return { created, updated };
3813
- }
3814
- function formatCursorSetupCompletedSummary(opts, presentation = createTerminalPresentation({ color: false, unicode: false })) {
3815
- const { created, updated } = collectOutcomePaths(opts.outcomes);
3816
- const tp = presentation;
3817
- const lines = [
3818
- tp.successLine("MemoraOne setup completed for Cursor"),
3819
- "",
3820
- tp.heading("Repository"),
3821
- tp.indent(tp.cyan(opts.repoRoot)),
3822
- "",
3823
- tp.heading("Changes")
3824
- ];
3825
- if (created.length === 0 && updated.length === 0) {
3826
- lines.push(tp.indent(tp.dim("No file changes needed")));
3827
- } else {
3828
- if (created.length) {
3829
- lines.push(tp.indent(`Created: ${created.join(", ")}`));
3830
- }
3831
- if (updated.length) {
3832
- lines.push(tp.indent(`Updated: ${updated.join(", ")}`));
3833
- }
3834
- }
3835
- return lines;
3836
- }
3837
- function printCursorSetupCompletedSummary(opts, println = console.log, presentation) {
3838
- const tp = presentation ?? createTerminalPresentation();
3839
- for (const line of formatCursorSetupCompletedSummary(opts, tp)) {
3840
- println(line);
3841
- }
3842
- }
3843
3834
  function macosOpenCursorMcpSettingsAppleScript() {
3844
3835
  return [
3845
3836
  'tell application "Cursor" to activate',
@@ -3910,6 +3901,39 @@ async function runOpenCursorMcpSettingsFlow(deps = {}) {
3910
3901
  printManualCursorMcpSettingsSteps(platform2, println);
3911
3902
  }
3912
3903
 
3904
+ // src/setupSuccessOutput.ts
3905
+ var RESTART_LINE = "Restart your IDEs to finish setup.";
3906
+ function formatSetupSuccessLines(opts = {}) {
3907
+ const tp = opts.presentation ?? createTerminalPresentation(opts.presentationOptions ?? { color: false, unicode: true });
3908
+ const targets = opts.targets ?? {};
3909
+ const lines = [];
3910
+ if (opts.repositoryConnected) {
3911
+ lines.push(tp.checkLine("Repository connected"));
3912
+ }
3913
+ if (targets.cursor) {
3914
+ lines.push(tp.checkLine("Cursor configured"));
3915
+ }
3916
+ if (targets.vscode) {
3917
+ lines.push(tp.checkLine("VS Code configured"));
3918
+ }
3919
+ if (targets.jetbrains) {
3920
+ lines.push(tp.checkLine("JetBrains configured"));
3921
+ }
3922
+ const hasIde = Boolean(targets.cursor || targets.vscode || targets.jetbrains);
3923
+ lines.push("");
3924
+ lines.push(tp.checkLine("MemoraOne is ready"));
3925
+ if (hasIde) {
3926
+ lines.push("");
3927
+ lines.push(RESTART_LINE);
3928
+ }
3929
+ return lines;
3930
+ }
3931
+ function printSetupSuccess(opts, println = console.log) {
3932
+ for (const line of formatSetupSuccessLines(opts)) {
3933
+ println(line);
3934
+ }
3935
+ }
3936
+
3913
3937
  // src/setupIdeFiles.ts
3914
3938
  var MANAGED_MARKER = "<!-- MemoraOne managed IDE helper -->";
3915
3939
  function buildMemoraoneMcpServer(ideType, options = {}) {
@@ -4130,6 +4154,7 @@ function parseSetupIdeFlags(argv) {
4130
4154
  let repair = false;
4131
4155
  let local = false;
4132
4156
  let staging = false;
4157
+ let verbose = false;
4133
4158
  let workspaceRoot;
4134
4159
  let apiUrl;
4135
4160
  const unknown = [];
@@ -4148,6 +4173,7 @@ function parseSetupIdeFlags(argv) {
4148
4173
  else if (a === "--repair") repair = true;
4149
4174
  else if (a === "--local") local = true;
4150
4175
  else if (a === "--staging") staging = true;
4176
+ else if (a === "--verbose") verbose = true;
4151
4177
  else if (a === "--workspace-root") {
4152
4178
  const value = argv[++i];
4153
4179
  if (!value || value.startsWith("-")) {
@@ -4205,10 +4231,37 @@ function parseSetupIdeFlags(argv) {
4205
4231
  workspaceRoot,
4206
4232
  apiUrl,
4207
4233
  explicitCursor: cursor,
4234
+ verbose,
4208
4235
  unknown,
4209
4236
  flagError
4210
4237
  };
4211
4238
  }
4239
+ function logSetupIdeFilesVerboseSuccess(opts, println = console.log) {
4240
+ const { targets, dryRun, result } = opts;
4241
+ if (result.repoRoot) {
4242
+ println(`[setup-ide-files] Repo root: ${result.repoRoot}`);
4243
+ }
4244
+ if (result.daemonCleanup && !result.daemonCleanup.skipped) {
4245
+ logSetupIdeCleanupSummary(result.daemonCleanup, println);
4246
+ }
4247
+ if (targets.cursor && result.cursorMcp) {
4248
+ logCursorMcpCliSummary(result.cursorMcp, dryRun, {
4249
+ forInteractivePostSetup: opts.forInteractivePostSetup,
4250
+ println
4251
+ });
4252
+ }
4253
+ if (targets.jetbrains && result.jetbrainsMcp) {
4254
+ logJetBrainsMcpCliSummary(result.jetbrainsMcp, dryRun, println);
4255
+ }
4256
+ summarizeOutcomes(result.outcomes, println);
4257
+ if (dryRun) {
4258
+ println("[setup-ide-files] Dry run: no files written.");
4259
+ if (result.daemonCleanup && !result.daemonCleanup.skipped) {
4260
+ println("[setup-ide-files] Dry run: no daemons stopped, no sockets removed.");
4261
+ }
4262
+ }
4263
+ println(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
4264
+ }
4212
4265
  async function resolveSetupApiUrl(o, repoRoot) {
4213
4266
  if (o.apiUrl) return normalizeApiUrl2(o.apiUrl);
4214
4267
  const binding = await findBindingRecordByWorkspaceRoot(repoRoot, o.homeDir);
@@ -4235,7 +4288,7 @@ function cursorEnvironmentFromFlags(local, staging) {
4235
4288
  if (staging) return "staging";
4236
4289
  return "production";
4237
4290
  }
4238
- function summarizeOutcomes(outcomes) {
4291
+ function summarizeOutcomes(outcomes, println = console.log) {
4239
4292
  const created = [];
4240
4293
  const updated = [];
4241
4294
  const skipped = [];
@@ -4253,7 +4306,7 @@ function summarizeOutcomes(outcomes) {
4253
4306
  if (skippedUntracked.length) {
4254
4307
  lines.push(` skipped (unmanaged existing file, use --force): ${skippedUntracked.join(", ")}`);
4255
4308
  }
4256
- console.log(lines.join("\n"));
4309
+ println(lines.join("\n"));
4257
4310
  }
4258
4311
  function ideTypesFromSetupTargets(targets) {
4259
4312
  const ides = [];
@@ -4294,28 +4347,28 @@ function aggregateCleanupResults(results) {
4294
4347
  error
4295
4348
  };
4296
4349
  }
4297
- function logSetupIdeCleanupSummary(cleanup) {
4350
+ function logSetupIdeCleanupSummary(cleanup, println = console.log) {
4298
4351
  if (cleanup.skipped) return;
4299
- console.log(`[setup-ide-files] Project id: ${cleanup.projectId}`);
4352
+ println(`[setup-ide-files] Project id: ${cleanup.projectId}`);
4300
4353
  if (cleanup.foundDaemonCount > 0) {
4301
- console.log(`[setup-ide-files] Found ${cleanup.foundDaemonCount} stale daemon(s)`);
4354
+ println(`[setup-ide-files] Found ${cleanup.foundDaemonCount} stale daemon(s)`);
4302
4355
  if (cleanup.dryRun) {
4303
- console.log(`[setup-ide-files] Would stop ${cleanup.foundDaemonCount} stale daemon(s)`);
4356
+ println(`[setup-ide-files] Would stop ${cleanup.foundDaemonCount} stale daemon(s)`);
4304
4357
  } else if (cleanup.stoppedDaemonCount > 0) {
4305
- console.log(`[setup-ide-files] Stopped ${cleanup.stoppedDaemonCount} stale daemon(s)`);
4358
+ println(`[setup-ide-files] Stopped ${cleanup.stoppedDaemonCount} stale daemon(s)`);
4306
4359
  }
4307
4360
  } else {
4308
- console.log("[setup-ide-files] No stale daemons found for this project and IDE target(s).");
4361
+ println("[setup-ide-files] No stale daemons found for this project and IDE target(s).");
4309
4362
  }
4310
4363
  if (cleanup.removedSocketCount > 0) {
4311
4364
  if (cleanup.dryRun) {
4312
- console.log(`[setup-ide-files] Would remove ${cleanup.removedSocketCount} stale socket(s)`);
4365
+ println(`[setup-ide-files] Would remove ${cleanup.removedSocketCount} stale socket(s)`);
4313
4366
  } else {
4314
- console.log(`[setup-ide-files] Removed ${cleanup.removedSocketCount} stale socket(s)`);
4367
+ println(`[setup-ide-files] Removed ${cleanup.removedSocketCount} stale socket(s)`);
4315
4368
  }
4316
4369
  }
4317
4370
  if (cleanup.skippedUnrelatedDaemonCount > 0) {
4318
- console.log(
4371
+ println(
4319
4372
  `[setup-ide-files] Skipped ${cleanup.skippedUnrelatedDaemonCount} unrelated project daemon(s)`
4320
4373
  );
4321
4374
  }
@@ -4672,6 +4725,7 @@ async function cliSetupIdeFiles(argv, options = {}) {
4672
4725
  workspaceRoot,
4673
4726
  apiUrl,
4674
4727
  explicitCursor,
4728
+ verbose,
4675
4729
  unknown,
4676
4730
  flagError
4677
4731
  } = parseSetupIdeFlags(argv);
@@ -4687,6 +4741,7 @@ async function cliSetupIdeFiles(argv, options = {}) {
4687
4741
  const openDeps = options.openCursorMcpSettings ?? {};
4688
4742
  const stdinIsTty = openDeps.stdinIsTty ?? process.stdin.isTTY === true;
4689
4743
  const env2 = openDeps.env ?? process.env;
4744
+ const println = options.println ?? openDeps.println ?? console.log;
4690
4745
  const promptOpenCursorSettings = shouldPromptOpenCursorMcpSettings({
4691
4746
  explicitCursor,
4692
4747
  all,
@@ -4712,55 +4767,42 @@ async function cliSetupIdeFiles(argv, options = {}) {
4712
4767
  if (result.error) {
4713
4768
  console.error(result.error);
4714
4769
  if (result.repoRoot) {
4715
- console.log(`[setup-ide-files] Repo root: ${result.repoRoot}`);
4770
+ println(`[setup-ide-files] Repo root: ${result.repoRoot}`);
4716
4771
  }
4717
4772
  summarizeOutcomes(result.outcomes);
4718
4773
  return result.exitCode;
4719
4774
  }
4720
- if (result.repoRoot) {
4721
- console.log(`[setup-ide-files] Repo root: ${result.repoRoot}`);
4722
- }
4723
- if (result.daemonCleanup && !result.daemonCleanup.skipped) {
4724
- logSetupIdeCleanupSummary(result.daemonCleanup);
4725
- }
4726
- if (targets.cursor && result.cursorMcp) {
4727
- logCursorMcpCliSummary(result.cursorMcp, dryRun, {
4728
- forInteractivePostSetup: promptOpenCursorSettings
4729
- });
4730
- }
4731
- if (targets.jetbrains && result.jetbrainsMcp) {
4732
- logJetBrainsMcpCliSummary(result.jetbrainsMcp, dryRun);
4775
+ const presentation = openDeps.presentation ?? createTerminalPresentation({
4776
+ env: env2,
4777
+ stdoutIsTty: openDeps.stdoutIsTty ?? process.stdout.isTTY === true,
4778
+ color: openDeps.color,
4779
+ unicode: openDeps.unicode
4780
+ });
4781
+ const showVerbose = verbose || dryRun;
4782
+ if (showVerbose) {
4783
+ logSetupIdeFilesVerboseSuccess(
4784
+ {
4785
+ targets,
4786
+ dryRun,
4787
+ result,
4788
+ forInteractivePostSetup: promptOpenCursorSettings
4789
+ },
4790
+ println
4791
+ );
4792
+ } else {
4793
+ printSetupSuccess({ targets, presentation }, println);
4733
4794
  }
4734
4795
  if (promptOpenCursorSettings && result.repoRoot) {
4735
- const presentation = openDeps.presentation ?? createTerminalPresentation({
4736
- env: env2,
4737
- stdoutIsTty: openDeps.stdoutIsTty ?? process.stdout.isTTY === true,
4738
- color: openDeps.color,
4739
- unicode: openDeps.unicode
4740
- });
4741
- printCursorSetupCompletedSummary(
4742
- { repoRoot: result.repoRoot, outcomes: result.outcomes },
4743
- openDeps.println,
4744
- presentation
4745
- );
4746
4796
  await runOpenCursorMcpSettingsFlow({
4747
4797
  ...openDeps,
4748
4798
  stdinIsTty,
4749
4799
  env: env2,
4750
- presentation
4800
+ presentation,
4801
+ println
4751
4802
  });
4752
- } else {
4753
- summarizeOutcomes(result.outcomes);
4754
- if (dryRun) {
4755
- console.log("[setup-ide-files] Dry run: no files written.");
4756
- if (result.daemonCleanup && !result.daemonCleanup.skipped) {
4757
- console.log("[setup-ide-files] Dry run: no daemons stopped, no sockets removed.");
4758
- }
4759
- }
4760
- console.log(`[setup-ide-files] ${restartIdeInstruction(targets)}`);
4761
4803
  }
4762
4804
  if (cleanup) {
4763
- console.log("[setup-ide-files] Running additional full-project cleanup (--cleanup)...");
4805
+ println("[setup-ide-files] Running additional full-project cleanup (--cleanup)...");
4764
4806
  const cleanupResult = await runCleanup({
4765
4807
  cwd: cwd2,
4766
4808
  dryRun,
@@ -5146,6 +5188,19 @@ async function runConnectCommand(options) {
5146
5188
  message: `Repository connection exists for binding ${ensured.repositoryBindingId} (project ${redeemed.project_id}), but IDE configuration failed: ${detail}. Credentials and binding were kept. ${repair}`
5147
5189
  };
5148
5190
  }
5191
+ return {
5192
+ exitCode: 0,
5193
+ repositoryBindingId: ensured.repositoryBindingId,
5194
+ projectId: redeemed.project_id,
5195
+ installationPublicId: redeemed.installation_public_id,
5196
+ recovered: redeemed.recovered,
5197
+ createdBinding: ensured.created,
5198
+ legacyM1WarningPath: ensured.legacyM1WarningPath,
5199
+ executionMode: resolvedMode,
5200
+ configuredTargets: targets,
5201
+ setupResult,
5202
+ message: baseSuccess
5203
+ };
5149
5204
  }
5150
5205
  return {
5151
5206
  exitCode: 0,
@@ -5162,12 +5217,20 @@ async function runConnectCommand(options) {
5162
5217
  function parseConnectArgv(argv) {
5163
5218
  let code;
5164
5219
  let apiUrl;
5220
+ let verbose = false;
5165
5221
  for (let i = 0; i < argv.length; i++) {
5166
5222
  const a = argv[i];
5223
+ if (a === "--verbose") {
5224
+ verbose = true;
5225
+ continue;
5226
+ }
5167
5227
  if (a === "--api-url") {
5168
5228
  const value = argv[++i];
5169
5229
  if (!value || value.startsWith("-")) {
5170
- return { error: "Usage: memoraone-mcp connect <code> [--api-url <url>]" };
5230
+ return {
5231
+ verbose,
5232
+ error: "Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]"
5233
+ };
5171
5234
  }
5172
5235
  apiUrl = value;
5173
5236
  continue;
@@ -5175,23 +5238,29 @@ function parseConnectArgv(argv) {
5175
5238
  if (a.startsWith("--api-url=")) {
5176
5239
  const value = a.slice("--api-url=".length);
5177
5240
  if (!value) {
5178
- return { error: "Usage: memoraone-mcp connect <code> [--api-url <url>]" };
5241
+ return {
5242
+ verbose,
5243
+ error: "Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]"
5244
+ };
5179
5245
  }
5180
5246
  apiUrl = value;
5181
5247
  continue;
5182
5248
  }
5183
5249
  if (a.startsWith("-")) {
5184
- return { error: `Unknown connect option: ${a}` };
5250
+ return { verbose, error: `Unknown connect option: ${a}` };
5185
5251
  }
5186
5252
  if (!code) {
5187
5253
  code = a;
5188
5254
  continue;
5189
5255
  }
5190
- return { error: "Usage: memoraone-mcp connect <code> [--api-url <url>]" };
5256
+ return {
5257
+ verbose,
5258
+ error: "Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]"
5259
+ };
5191
5260
  }
5192
- return { code, apiUrl };
5261
+ return { code, apiUrl, verbose };
5193
5262
  }
5194
- async function cliConnect(argv) {
5263
+ async function cliConnect(argv, options = {}) {
5195
5264
  const parsed2 = parseConnectArgv(argv);
5196
5265
  if (parsed2.error) {
5197
5266
  process.stderr.write(`${parsed2.error}
@@ -5199,19 +5268,53 @@ async function cliConnect(argv) {
5199
5268
  return 1;
5200
5269
  }
5201
5270
  if (!parsed2.code) {
5202
- process.stderr.write("Usage: memoraone-mcp connect <code> [--api-url <url>]\n");
5271
+ process.stderr.write("Usage: memoraone-mcp connect <code> [--api-url <url>] [--verbose]\n");
5203
5272
  return 1;
5204
5273
  }
5274
+ const println = options.println ?? ((line) => process.stdout.write(`${line}
5275
+ `));
5205
5276
  try {
5206
5277
  const result = await runConnectCommand({
5207
5278
  code: parsed2.code,
5208
- cwd: process.cwd(),
5279
+ cwd: options.cwd ?? process.cwd(),
5209
5280
  apiUrl: parsed2.apiUrl,
5210
- packageVersion: process.env.npm_package_version ?? null
5281
+ packageVersion: process.env.npm_package_version ?? null,
5282
+ env: options.env,
5283
+ ...options.connectOptions
5211
5284
  });
5212
5285
  if (result.exitCode === 0) {
5213
- process.stdout.write(`${result.message}
5214
- `);
5286
+ if (parsed2.verbose) {
5287
+ println(result.message);
5288
+ if (result.projectId) {
5289
+ println(`[memoraone-mcp] Project id: ${result.projectId}`);
5290
+ }
5291
+ println(`[memoraone-mcp] Repository root: ${options.cwd ?? process.cwd()}`);
5292
+ if (result.setupResult && result.configuredTargets) {
5293
+ logSetupIdeFilesVerboseSuccess(
5294
+ {
5295
+ targets: result.configuredTargets,
5296
+ dryRun: false,
5297
+ result: result.setupResult
5298
+ },
5299
+ println
5300
+ );
5301
+ }
5302
+ } else {
5303
+ const presentation = createTerminalPresentation({
5304
+ env: options.env ?? process.env,
5305
+ stdoutIsTty: options.stdoutIsTty ?? process.stdout.isTTY === true,
5306
+ color: options.color,
5307
+ unicode: options.unicode
5308
+ });
5309
+ printSetupSuccess(
5310
+ {
5311
+ repositoryConnected: true,
5312
+ targets: result.configuredTargets,
5313
+ presentation
5314
+ },
5315
+ println
5316
+ );
5317
+ }
5215
5318
  } else {
5216
5319
  process.stderr.write(`[memoraone-mcp] ${result.message}
5217
5320
  `);
@@ -5233,7 +5336,7 @@ if (args.includes("--version") || args.includes("-v")) {
5233
5336
  }
5234
5337
  if (args.includes("--help") || args.includes("-h")) {
5235
5338
  console.log(
5236
- "Usage: memoraone-mcp [--version] [--help]\n memoraone-mcp connect <code> [--api-url <url>]\n memoraone-mcp [--daemon --binding-id <mrb_\u2026> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair] [--workspace-root <path>] [--api-url <url>]\n Cursor API environment (with --cursor or --all): --local (node + built cli.cjs + local API) | --staging (npx + staging API)\n --workspace-root: configure an explicit bound workspace (skips .git discovery; for fileless Local MCP repair)\n --api-url: developer-only local/dev API endpoint (defaults from binding or http://localhost:3001; never Studio :3000)\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
5339
+ "Usage: memoraone-mcp [--version] [--help]\n memoraone-mcp connect <code> [--api-url <url>] [--verbose]\n memoraone-mcp [--daemon --binding-id <mrb_\u2026> [--ide cursor|copilot-vscode|jetbrains]]\n memoraone-mcp setup-ide-files [--all|--cursor|--vscode|--jetbrains] [--force] [--dry-run] [--no-gitignore] [--cleanup] [--dev] [--repair] [--workspace-root <path>] [--api-url <url>] [--verbose]\n Cursor API environment (with --cursor or --all): --local (node + built cli.cjs + local API) | --staging (npx + staging API)\n --workspace-root: configure an explicit bound workspace (skips .git discovery; for fileless Local MCP repair)\n --api-url: developer-only local/dev API endpoint (defaults from binding or http://localhost:3001; never Studio :3000)\n --verbose: show developer diagnostics (paths, backups, daemon cleanup, handshake)\n memoraone-mcp cleanup [--project-id <uuid>] [--ide cursor|copilot-vscode|jetbrains] [--dry-run] [--all-projects] [--yes]"
5237
5340
  );
5238
5341
  process.exit(0);
5239
5342
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoraone/mcp",
3
- "version": "0.1.37",
3
+ "version": "0.1.38",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {