rrce-workflow 0.2.27 → 0.2.28

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/index.js +426 -180
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -583,7 +583,7 @@ var init_types = __esm({
583
583
  });
584
584
 
585
585
  // src/mcp/config.ts
586
- import * as fs12 from "fs";
586
+ import * as fs11 from "fs";
587
587
  import * as path11 from "path";
588
588
  function getMCPConfigPath() {
589
589
  const workspaceRoot = detectWorkspaceRoot();
@@ -595,8 +595,8 @@ function ensureMCPGlobalPath() {
595
595
  const rrceHome = getEffectiveRRCEHome(workspaceRoot);
596
596
  if (rrceHome.startsWith(".") || rrceHome.includes(".rrce-workflow/")) {
597
597
  const configPath = path11.join(workspaceRoot, ".rrce-workflow", "config.yaml");
598
- if (fs12.existsSync(configPath)) {
599
- const content = fs12.readFileSync(configPath, "utf-8");
598
+ if (fs11.existsSync(configPath)) {
599
+ const content = fs11.readFileSync(configPath, "utf-8");
600
600
  const modeMatch = content.match(/mode:\s*(global|workspace)/);
601
601
  if (modeMatch?.[1] === "workspace") {
602
602
  return {
@@ -614,11 +614,11 @@ function ensureMCPGlobalPath() {
614
614
  }
615
615
  function loadMCPConfig() {
616
616
  const configPath = getMCPConfigPath();
617
- if (!fs12.existsSync(configPath)) {
617
+ if (!fs11.existsSync(configPath)) {
618
618
  return { ...DEFAULT_MCP_CONFIG };
619
619
  }
620
620
  try {
621
- const content = fs12.readFileSync(configPath, "utf-8");
621
+ const content = fs11.readFileSync(configPath, "utf-8");
622
622
  return parseMCPConfig(content);
623
623
  } catch {
624
624
  return { ...DEFAULT_MCP_CONFIG };
@@ -627,11 +627,11 @@ function loadMCPConfig() {
627
627
  function saveMCPConfig(config) {
628
628
  const configPath = getMCPConfigPath();
629
629
  const dir = path11.dirname(configPath);
630
- if (!fs12.existsSync(dir)) {
631
- fs12.mkdirSync(dir, { recursive: true });
630
+ if (!fs11.existsSync(dir)) {
631
+ fs11.mkdirSync(dir, { recursive: true });
632
632
  }
633
633
  const content = serializeMCPConfig(config);
634
- fs12.writeFileSync(configPath, content);
634
+ fs11.writeFileSync(configPath, content);
635
635
  }
636
636
  function parseMCPConfig(content) {
637
637
  const config = { ...DEFAULT_MCP_CONFIG, projects: [] };
@@ -794,7 +794,7 @@ __export(logger_exports, {
794
794
  getLogFilePath: () => getLogFilePath,
795
795
  logger: () => logger
796
796
  });
797
- import * as fs13 from "fs";
797
+ import * as fs12 from "fs";
798
798
  import * as path12 from "path";
799
799
  function getLogFilePath() {
800
800
  const workspaceRoot = detectWorkspaceRoot();
@@ -831,10 +831,10 @@ ${JSON.stringify(data, null, 2)}`;
831
831
  logMessage += "\n";
832
832
  try {
833
833
  const dir = path12.dirname(this.logPath);
834
- if (!fs13.existsSync(dir)) {
835
- fs13.mkdirSync(dir, { recursive: true });
834
+ if (!fs12.existsSync(dir)) {
835
+ fs12.mkdirSync(dir, { recursive: true });
836
836
  }
837
- fs13.appendFileSync(this.logPath, logMessage);
837
+ fs12.appendFileSync(this.logPath, logMessage);
838
838
  } catch (e) {
839
839
  console.error(`[Logger Failure] Could not write to ${this.logPath}`, e);
840
840
  console.error(logMessage);
@@ -858,7 +858,7 @@ ${JSON.stringify(data, null, 2)}`;
858
858
  });
859
859
 
860
860
  // src/mcp/resources.ts
861
- import * as fs14 from "fs";
861
+ import * as fs13 from "fs";
862
862
  import * as path13 from "path";
863
863
  function getExposedProjects() {
864
864
  const config = loadMCPConfig();
@@ -887,10 +887,10 @@ function getProjectContext(projectName) {
887
887
  return null;
888
888
  }
889
889
  const contextPath = path13.join(project.knowledgePath, "project-context.md");
890
- if (!fs14.existsSync(contextPath)) {
890
+ if (!fs13.existsSync(contextPath)) {
891
891
  return null;
892
892
  }
893
- return fs14.readFileSync(contextPath, "utf-8");
893
+ return fs13.readFileSync(contextPath, "utf-8");
894
894
  }
895
895
  function getProjectTasks(projectName) {
896
896
  const config = loadMCPConfig();
@@ -903,18 +903,18 @@ function getProjectTasks(projectName) {
903
903
  }
904
904
  const projects = scanForProjects();
905
905
  const project = projects.find((p) => p.name === projectName);
906
- if (!project?.tasksPath || !fs14.existsSync(project.tasksPath)) {
906
+ if (!project?.tasksPath || !fs13.existsSync(project.tasksPath)) {
907
907
  return [];
908
908
  }
909
909
  const tasks = [];
910
910
  try {
911
- const taskDirs = fs14.readdirSync(project.tasksPath, { withFileTypes: true });
911
+ const taskDirs = fs13.readdirSync(project.tasksPath, { withFileTypes: true });
912
912
  for (const dir of taskDirs) {
913
913
  if (!dir.isDirectory()) continue;
914
914
  const metaPath = path13.join(project.tasksPath, dir.name, "meta.json");
915
- if (fs14.existsSync(metaPath)) {
915
+ if (fs13.existsSync(metaPath)) {
916
916
  try {
917
- const meta = JSON.parse(fs14.readFileSync(metaPath, "utf-8"));
917
+ const meta = JSON.parse(fs13.readFileSync(metaPath, "utf-8"));
918
918
  tasks.push(meta);
919
919
  } catch {
920
920
  }
@@ -933,11 +933,11 @@ function searchKnowledge(query) {
933
933
  const permissions = getProjectPermissions(config, project.name);
934
934
  if (!permissions.knowledge || !project.knowledgePath) continue;
935
935
  try {
936
- const files = fs14.readdirSync(project.knowledgePath);
936
+ const files = fs13.readdirSync(project.knowledgePath);
937
937
  for (const file of files) {
938
938
  if (!file.endsWith(".md")) continue;
939
939
  const filePath = path13.join(project.knowledgePath, file);
940
- const content = fs14.readFileSync(filePath, "utf-8");
940
+ const content = fs13.readFileSync(filePath, "utf-8");
941
941
  const lines = content.split("\n");
942
942
  const matches = [];
943
943
  for (const line of lines) {
@@ -1357,34 +1357,105 @@ var init_server = __esm({
1357
1357
  });
1358
1358
 
1359
1359
  // src/mcp/install.ts
1360
- import * as fs15 from "fs";
1360
+ import * as fs14 from "fs";
1361
1361
  import * as path14 from "path";
1362
1362
  import * as os from "os";
1363
- function checkInstallStatus() {
1363
+ function checkInstallStatus(workspacePath) {
1364
1364
  return {
1365
- antigravity: checkConfigFile(ANTIGRAVITY_CONFIG),
1366
- claude: checkConfigFile(CLAUDE_CONFIG)
1365
+ antigravity: checkAntigravityConfig(),
1366
+ claude: checkClaudeConfig(),
1367
+ vscodeGlobal: checkVSCodeGlobalConfig(),
1368
+ vscodeWorkspace: workspacePath ? checkVSCodeWorkspaceConfig(workspacePath) : false
1367
1369
  };
1368
1370
  }
1369
- function checkConfigFile(configPath) {
1370
- if (!fs15.existsSync(configPath)) return false;
1371
+ function checkAntigravityConfig() {
1372
+ if (!fs14.existsSync(ANTIGRAVITY_CONFIG)) return false;
1373
+ try {
1374
+ const content = JSON.parse(fs14.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
1375
+ return !!content.mcpServers?.["rrce"];
1376
+ } catch {
1377
+ return false;
1378
+ }
1379
+ }
1380
+ function checkClaudeConfig() {
1381
+ if (!fs14.existsSync(CLAUDE_CONFIG)) return false;
1371
1382
  try {
1372
- const content = JSON.parse(fs15.readFileSync(configPath, "utf-8"));
1383
+ const content = JSON.parse(fs14.readFileSync(CLAUDE_CONFIG, "utf-8"));
1373
1384
  return !!content.mcpServers?.["rrce"];
1374
1385
  } catch {
1375
1386
  return false;
1376
1387
  }
1377
1388
  }
1378
- function installToConfig(target) {
1379
- const configPath = target === "antigravity" ? ANTIGRAVITY_CONFIG : CLAUDE_CONFIG;
1380
- const dir = path14.dirname(configPath);
1381
- if (!fs15.existsSync(dir)) {
1382
- fs15.mkdirSync(dir, { recursive: true });
1389
+ function checkVSCodeGlobalConfig() {
1390
+ if (!fs14.existsSync(VSCODE_GLOBAL_CONFIG)) return false;
1391
+ try {
1392
+ const content = JSON.parse(fs14.readFileSync(VSCODE_GLOBAL_CONFIG, "utf-8"));
1393
+ return !!content["mcp.servers"]?.["rrce"];
1394
+ } catch {
1395
+ return false;
1396
+ }
1397
+ }
1398
+ function checkVSCodeWorkspaceConfig(workspacePath) {
1399
+ const configPath = path14.join(workspacePath, ".vscode", "mcp.json");
1400
+ if (!fs14.existsSync(configPath)) return false;
1401
+ try {
1402
+ const content = JSON.parse(fs14.readFileSync(configPath, "utf-8"));
1403
+ return !!content.servers?.["rrce"];
1404
+ } catch {
1405
+ return false;
1406
+ }
1407
+ }
1408
+ function isInstalledAnywhere(workspacePath) {
1409
+ const status = checkInstallStatus(workspacePath);
1410
+ return status.antigravity || status.claude || status.vscodeGlobal || status.vscodeWorkspace;
1411
+ }
1412
+ function installToConfig(target, workspacePath) {
1413
+ switch (target) {
1414
+ case "antigravity":
1415
+ return installToAntigravity();
1416
+ case "claude":
1417
+ return installToClaude();
1418
+ case "vscode-global":
1419
+ return installToVSCodeGlobal();
1420
+ case "vscode-workspace":
1421
+ return workspacePath ? installToVSCodeWorkspace(workspacePath) : false;
1422
+ default:
1423
+ return false;
1424
+ }
1425
+ }
1426
+ function installToAntigravity() {
1427
+ const dir = path14.dirname(ANTIGRAVITY_CONFIG);
1428
+ if (!fs14.existsSync(dir)) {
1429
+ fs14.mkdirSync(dir, { recursive: true });
1430
+ }
1431
+ let config = { mcpServers: {} };
1432
+ if (fs14.existsSync(ANTIGRAVITY_CONFIG)) {
1433
+ try {
1434
+ config = JSON.parse(fs14.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
1435
+ } catch {
1436
+ }
1437
+ }
1438
+ if (!config.mcpServers) config.mcpServers = {};
1439
+ config.mcpServers["rrce"] = {
1440
+ command: "npx",
1441
+ args: ["-y", "rrce-workflow", "mcp", "start"]
1442
+ };
1443
+ try {
1444
+ fs14.writeFileSync(ANTIGRAVITY_CONFIG, JSON.stringify(config, null, 2));
1445
+ return true;
1446
+ } catch {
1447
+ return false;
1448
+ }
1449
+ }
1450
+ function installToClaude() {
1451
+ const dir = path14.dirname(CLAUDE_CONFIG);
1452
+ if (!fs14.existsSync(dir)) {
1453
+ fs14.mkdirSync(dir, { recursive: true });
1383
1454
  }
1384
1455
  let config = { mcpServers: {} };
1385
- if (fs15.existsSync(configPath)) {
1456
+ if (fs14.existsSync(CLAUDE_CONFIG)) {
1386
1457
  try {
1387
- config = JSON.parse(fs15.readFileSync(configPath, "utf-8"));
1458
+ config = JSON.parse(fs14.readFileSync(CLAUDE_CONFIG, "utf-8"));
1388
1459
  } catch {
1389
1460
  }
1390
1461
  }
@@ -1392,21 +1463,84 @@ function installToConfig(target) {
1392
1463
  config.mcpServers["rrce"] = {
1393
1464
  command: "npx",
1394
1465
  args: ["-y", "rrce-workflow", "mcp", "start"]
1395
- // -y to avoid interactive prompts
1396
1466
  };
1397
1467
  try {
1398
- fs15.writeFileSync(configPath, JSON.stringify(config, null, 2));
1468
+ fs14.writeFileSync(CLAUDE_CONFIG, JSON.stringify(config, null, 2));
1469
+ return true;
1470
+ } catch {
1471
+ return false;
1472
+ }
1473
+ }
1474
+ function installToVSCodeGlobal() {
1475
+ const dir = path14.dirname(VSCODE_GLOBAL_CONFIG);
1476
+ if (!fs14.existsSync(dir)) {
1477
+ fs14.mkdirSync(dir, { recursive: true });
1478
+ }
1479
+ let settings = {};
1480
+ if (fs14.existsSync(VSCODE_GLOBAL_CONFIG)) {
1481
+ try {
1482
+ settings = JSON.parse(fs14.readFileSync(VSCODE_GLOBAL_CONFIG, "utf-8"));
1483
+ } catch {
1484
+ }
1485
+ }
1486
+ if (!settings["mcp.servers"]) settings["mcp.servers"] = {};
1487
+ settings["mcp.servers"]["rrce"] = {
1488
+ command: "npx",
1489
+ args: ["-y", "rrce-workflow", "mcp", "start"]
1490
+ };
1491
+ try {
1492
+ fs14.writeFileSync(VSCODE_GLOBAL_CONFIG, JSON.stringify(settings, null, 2));
1399
1493
  return true;
1400
1494
  } catch {
1401
1495
  return false;
1402
1496
  }
1403
1497
  }
1404
- var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG;
1498
+ function installToVSCodeWorkspace(workspacePath) {
1499
+ const vscodeDir = path14.join(workspacePath, ".vscode");
1500
+ const configPath = path14.join(vscodeDir, "mcp.json");
1501
+ if (!fs14.existsSync(vscodeDir)) {
1502
+ fs14.mkdirSync(vscodeDir, { recursive: true });
1503
+ }
1504
+ let config = { servers: {} };
1505
+ if (fs14.existsSync(configPath)) {
1506
+ try {
1507
+ config = JSON.parse(fs14.readFileSync(configPath, "utf-8"));
1508
+ } catch {
1509
+ }
1510
+ }
1511
+ if (!config.servers) config.servers = {};
1512
+ config.servers["rrce"] = {
1513
+ command: "npx",
1514
+ args: ["-y", "rrce-workflow", "mcp", "start"]
1515
+ };
1516
+ try {
1517
+ fs14.writeFileSync(configPath, JSON.stringify(config, null, 2));
1518
+ return true;
1519
+ } catch {
1520
+ return false;
1521
+ }
1522
+ }
1523
+ function getTargetLabel(target) {
1524
+ switch (target) {
1525
+ case "antigravity":
1526
+ return "Antigravity IDE";
1527
+ case "claude":
1528
+ return "Claude Desktop";
1529
+ case "vscode-global":
1530
+ return "VSCode (Global)";
1531
+ case "vscode-workspace":
1532
+ return "VSCode (Workspace)";
1533
+ default:
1534
+ return target;
1535
+ }
1536
+ }
1537
+ var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, VSCODE_GLOBAL_CONFIG;
1405
1538
  var init_install = __esm({
1406
1539
  "src/mcp/install.ts"() {
1407
1540
  "use strict";
1408
1541
  ANTIGRAVITY_CONFIG = path14.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
1409
1542
  CLAUDE_CONFIG = path14.join(os.homedir(), ".config/claude/claude_desktop_config.json");
1543
+ VSCODE_GLOBAL_CONFIG = path14.join(os.homedir(), ".config/Code/User/settings.json");
1410
1544
  }
1411
1545
  });
1412
1546
 
@@ -1415,8 +1549,8 @@ var mcp_exports = {};
1415
1549
  __export(mcp_exports, {
1416
1550
  runMCP: () => runMCP
1417
1551
  });
1418
- import { intro as intro2, outro as outro6, select as select4, multiselect as multiselect3, confirm as confirm4, spinner as spinner6, note as note7, cancel as cancel6, isCancel as isCancel7, text as text2 } from "@clack/prompts";
1419
- import pc8 from "picocolors";
1552
+ import { intro, outro as outro5, select as select3, multiselect as multiselect3, confirm as confirm4, spinner as spinner5, note as note6, cancel as cancel5, isCancel as isCancel6, text as text2 } from "@clack/prompts";
1553
+ import pc7 from "picocolors";
1420
1554
  async function runMCP(subcommand2) {
1421
1555
  if (subcommand2) {
1422
1556
  switch (subcommand2) {
@@ -1436,42 +1570,69 @@ async function runMCP(subcommand2) {
1436
1570
  return;
1437
1571
  }
1438
1572
  }
1439
- intro2(pc8.bgCyan(pc8.black(" RRCE MCP Hub ")));
1573
+ intro(pc7.bgCyan(pc7.black(" RRCE MCP Hub ")));
1574
+ const workspacePath = detectWorkspaceRoot();
1440
1575
  const globalPathCheck = await ensureMCPGlobalPath();
1441
1576
  if (!globalPathCheck.configured) {
1442
1577
  const configured = await handleConfigureGlobalPath();
1443
1578
  if (!configured) {
1444
- outro6(pc8.yellow("MCP requires a global storage path. Setup cancelled."));
1579
+ outro5(pc7.yellow("MCP requires a global storage path. Setup cancelled."));
1445
1580
  return;
1446
1581
  }
1447
1582
  }
1448
- const status = checkInstallStatus();
1449
- if (!status.antigravity && !status.claude) {
1583
+ const status = checkInstallStatus(workspacePath);
1584
+ const installed = isInstalledAnywhere(workspacePath);
1585
+ if (!installed) {
1586
+ note6(
1587
+ `${pc7.bold("Welcome to RRCE MCP Hub!")}
1588
+
1589
+ MCP (Model Context Protocol) allows AI assistants to access your
1590
+ project knowledge in real-time. Let's get you set up.`,
1591
+ "Getting Started"
1592
+ );
1450
1593
  const shouldInstall = await confirm4({
1451
- message: "MCP server is not installed in your IDEs. Install now?",
1594
+ message: "Install MCP server to your IDE(s)?",
1452
1595
  initialValue: true
1453
1596
  });
1454
- if (shouldInstall && !isCancel7(shouldInstall)) {
1455
- await handleInstallWizard();
1597
+ if (shouldInstall && !isCancel6(shouldInstall)) {
1598
+ await handleInstallWizard(workspacePath);
1599
+ await handleConfigure();
1600
+ const shouldStart = await confirm4({
1601
+ message: "Start the MCP server now?",
1602
+ initialValue: true
1603
+ });
1604
+ if (shouldStart && !isCancel6(shouldStart)) {
1605
+ await handleStartServer();
1606
+ }
1456
1607
  }
1608
+ outro5(pc7.green("MCP Hub setup complete!"));
1609
+ return;
1610
+ }
1611
+ const config = loadMCPConfig();
1612
+ const exposedCount = config.projects.filter((p) => p.expose).length;
1613
+ if (exposedCount === 0 && !config.defaults.includeNew) {
1614
+ note6("MCP is installed but no projects are exposed. Let's configure that.", "Configuration Needed");
1615
+ await handleConfigure();
1457
1616
  }
1458
1617
  let running = true;
1459
1618
  while (running) {
1460
1619
  const serverStatus = getMCPServerStatus();
1461
- const serverLabel = serverStatus.running ? pc8.green("Running") : pc8.dim("Stopped");
1462
- const action = await select4({
1620
+ const serverLabel = serverStatus.running ? pc7.green("\u25CF Running") : pc7.dim("\u25CB Stopped");
1621
+ const currentStatus = checkInstallStatus(workspacePath);
1622
+ const installedCount = [currentStatus.antigravity, currentStatus.claude, currentStatus.vscodeGlobal, currentStatus.vscodeWorkspace].filter(Boolean).length;
1623
+ const action = await select3({
1463
1624
  message: "What would you like to do?",
1464
1625
  options: [
1465
- { value: "start", label: `\u25B6\uFE0F Start MCP server`, hint: `Current status: ${serverLabel}` },
1626
+ { value: "start", label: `\u25B6\uFE0F Start MCP server`, hint: serverLabel },
1466
1627
  { value: "configure", label: "\u2699\uFE0F Configure projects", hint: "Choose which projects to expose" },
1467
- { value: "install", label: "\u{1F4E5} Install to IDE", hint: "Add to Antigravity or Claude Desktop" },
1628
+ { value: "install", label: "\u{1F4E5} Install to IDE", hint: `${installedCount} IDE(s) configured` },
1468
1629
  { value: "status", label: "\u{1F4CB} View status", hint: "See details" },
1469
1630
  { value: "help", label: "\u2753 Help", hint: "Learn about MCP Hub" },
1470
1631
  { value: "exit", label: "\u21A9 Exit", hint: "Return to shell" }
1471
1632
  ]
1472
1633
  });
1473
- if (isCancel7(action)) {
1474
- cancel6("MCP Hub closed.");
1634
+ if (isCancel6(action)) {
1635
+ cancel5("MCP Hub closed.");
1475
1636
  return;
1476
1637
  }
1477
1638
  switch (action) {
@@ -1482,7 +1643,7 @@ async function runMCP(subcommand2) {
1482
1643
  await handleConfigure();
1483
1644
  break;
1484
1645
  case "install":
1485
- await handleInstallWizard();
1646
+ await handleInstallWizard(workspacePath);
1486
1647
  break;
1487
1648
  case "status":
1488
1649
  await handleShowStatus();
@@ -1495,46 +1656,72 @@ async function runMCP(subcommand2) {
1495
1656
  break;
1496
1657
  }
1497
1658
  }
1498
- outro6(pc8.green("MCP Hub closed."));
1659
+ outro5(pc7.green("MCP Hub closed."));
1499
1660
  }
1500
- async function handleInstallWizard() {
1501
- const status = checkInstallStatus();
1661
+ async function handleInstallWizard(workspacePath) {
1662
+ const status = checkInstallStatus(workspacePath);
1502
1663
  const options = [
1503
- { value: "antigravity", label: "Antigravity IDE", hint: status.antigravity ? "Installed" : "Not installed" },
1504
- { value: "claude", label: "Claude Desktop", hint: status.claude ? "Installed" : "Not installed" }
1664
+ {
1665
+ value: "antigravity",
1666
+ label: "Antigravity IDE",
1667
+ hint: status.antigravity ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")
1668
+ },
1669
+ {
1670
+ value: "vscode-global",
1671
+ label: "VSCode (Global)",
1672
+ hint: status.vscodeGlobal ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")
1673
+ },
1674
+ {
1675
+ value: "vscode-workspace",
1676
+ label: "VSCode (This Workspace)",
1677
+ hint: status.vscodeWorkspace ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")
1678
+ },
1679
+ {
1680
+ value: "claude",
1681
+ label: "Claude Desktop",
1682
+ hint: status.claude ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")
1683
+ }
1505
1684
  ];
1506
1685
  const selected = await multiselect3({
1507
1686
  message: "Select where to install RRCE MCP Server:",
1508
1687
  options,
1509
1688
  initialValues: [
1510
1689
  ...status.antigravity ? ["antigravity"] : [],
1690
+ ...status.vscodeGlobal ? ["vscode-global"] : [],
1691
+ ...status.vscodeWorkspace ? ["vscode-workspace"] : [],
1511
1692
  ...status.claude ? ["claude"] : []
1512
1693
  ],
1513
1694
  required: false
1514
1695
  });
1515
- if (isCancel7(selected)) return;
1696
+ if (isCancel6(selected)) return;
1516
1697
  const targets = selected;
1517
1698
  const results = [];
1518
1699
  for (const target of targets) {
1519
- const success = installToConfig(target);
1520
- results.push(`${target}: ${success ? pc8.green("Success") : pc8.red("Failed")}`);
1700
+ const success = installToConfig(target, workspacePath);
1701
+ const label = getTargetLabel(target);
1702
+ results.push(`${label}: ${success ? pc7.green("\u2713 Success") : pc7.red("\u2717 Failed")}`);
1521
1703
  }
1522
1704
  if (results.length > 0) {
1523
- note7(results.join("\n"), "Installation Results");
1705
+ note6(results.join("\n"), "Installation Results");
1524
1706
  }
1525
1707
  }
1526
1708
  async function handleStartServer() {
1527
1709
  const fs16 = await import("fs");
1528
1710
  const { getLogFilePath: getLogFilePath2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
1529
1711
  const config = loadMCPConfig();
1530
- const exposedCount = config.projects.filter((p) => p.expose).length;
1531
- if (exposedCount === 0 && !config.defaults.includeNew) {
1712
+ const projects = scanForProjects();
1713
+ const exposedProjects = projects.filter((p) => {
1714
+ const cfg = config.projects.find((c) => c.name === p.name);
1715
+ return cfg?.expose ?? config.defaults.includeNew;
1716
+ });
1717
+ if (exposedProjects.length === 0) {
1532
1718
  const shouldConfig = await confirm4({
1533
1719
  message: "No projects are currently exposed. Configure now?",
1534
1720
  initialValue: true
1535
1721
  });
1536
- if (shouldConfig && !isCancel7(shouldConfig)) {
1722
+ if (shouldConfig && !isCancel6(shouldConfig)) {
1537
1723
  await handleConfigure();
1724
+ return handleStartServer();
1538
1725
  }
1539
1726
  }
1540
1727
  const portInput = await text2({
@@ -1545,7 +1732,7 @@ async function handleStartServer() {
1545
1732
  if (isNaN(Number(value))) return "Port must be a number";
1546
1733
  }
1547
1734
  });
1548
- if (isCancel7(portInput)) return;
1735
+ if (isCancel6(portInput)) return;
1549
1736
  const newPort = parseInt(portInput, 10);
1550
1737
  if (newPort !== config.server.port) {
1551
1738
  config.server.port = newPort;
@@ -1553,23 +1740,33 @@ async function handleStartServer() {
1553
1740
  }
1554
1741
  console.clear();
1555
1742
  const logPath = getLogFilePath2();
1556
- const renderHeader = () => {
1743
+ const workspacePath = detectWorkspaceRoot();
1744
+ const exposedNames = exposedProjects.map((p) => p.name).slice(0, 5);
1745
+ const exposedLabel = exposedNames.length > 0 ? exposedNames.join(", ") + (exposedProjects.length > 5 ? ` (+${exposedProjects.length - 5} more)` : "") : pc7.dim("(none)");
1746
+ const render = (logs = []) => {
1557
1747
  console.clear();
1558
- console.log(pc8.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
1559
- console.log(pc8.cyan("\u2551 RRCE MCP Hub Running \u2551"));
1560
- console.log(pc8.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
1561
- console.log(pc8.dim("Server is running in Stdio mode (JSON-RPC)."));
1562
- console.log(pc8.dim(`Port: ${newPort} | PID: ${process.pid}`));
1563
- console.log(pc8.dim(`Logging to: ${logPath}`));
1564
- console.log(pc8.dim("---------------------------------------------"));
1748
+ console.log(pc7.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
1749
+ console.log(pc7.cyan("\u2551") + pc7.bold(pc7.white(" RRCE MCP Hub Running ")) + pc7.cyan("\u2551"));
1750
+ console.log(pc7.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
1751
+ const logLines = logs.slice(-10);
1752
+ const emptyLines = 10 - logLines.length;
1753
+ for (let i = 0; i < emptyLines; i++) {
1754
+ console.log(pc7.cyan("\u2551") + " ".repeat(63) + pc7.cyan("\u2551"));
1755
+ }
1756
+ for (const line of logLines) {
1757
+ const truncated = line.substring(0, 61).padEnd(61);
1758
+ console.log(pc7.cyan("\u2551") + " " + pc7.dim(truncated) + " " + pc7.cyan("\u2551"));
1759
+ }
1760
+ console.log(pc7.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
1761
+ const infoLine = ` \u{1F4CB} ${exposedLabel} \u2502 Port: ${newPort} \u2502 PID: ${process.pid}`.substring(0, 61).padEnd(61);
1762
+ console.log(pc7.cyan("\u2551") + pc7.yellow(infoLine) + " " + pc7.cyan("\u2551"));
1763
+ console.log(pc7.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
1764
+ const cmdLine = ` q:Quit p:Projects i:Install r:Reload c:Clear ?:Help`;
1765
+ console.log(pc7.cyan("\u2551") + pc7.dim(cmdLine.padEnd(63)) + pc7.cyan("\u2551"));
1766
+ console.log(pc7.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
1565
1767
  };
1566
- const renderFooter = () => {
1567
- console.log(pc8.dim("---------------------------------------------"));
1568
- console.log(pc8.bgBlue(pc8.white(pc8.bold(" COMMANDS "))));
1569
- console.log(`${pc8.bold("q")}: Stop & Quit ${pc8.bold("g")}: Configure Projects ${pc8.bold("p")}: Change Port`);
1570
- };
1571
- renderHeader();
1572
- renderFooter();
1768
+ let logBuffer = [];
1769
+ render(logBuffer);
1573
1770
  try {
1574
1771
  await startMCPServer();
1575
1772
  let lastSize = 0;
@@ -1584,14 +1781,59 @@ async function handleStartServer() {
1584
1781
  process.stdin.setEncoding("utf8");
1585
1782
  }
1586
1783
  return new Promise((resolve) => {
1784
+ const cleanup = () => {
1785
+ isRunning = false;
1786
+ clearInterval(interval);
1787
+ if (process.stdin.setRawMode) {
1788
+ process.stdin.setRawMode(false);
1789
+ }
1790
+ process.stdin.removeListener("data", onKey);
1791
+ process.stdin.pause();
1792
+ stopMCPServer();
1793
+ console.log("");
1794
+ };
1587
1795
  const onKey = async (key) => {
1588
1796
  if (key === "" || key.toLowerCase() === "q") {
1589
1797
  cleanup();
1590
1798
  resolve();
1799
+ return;
1800
+ }
1801
+ if (key.toLowerCase() === "p") {
1802
+ cleanup();
1803
+ console.clear();
1804
+ await handleConfigure();
1805
+ resolve();
1806
+ return;
1591
1807
  }
1592
- if (key.toLowerCase() === "p" || key.toLowerCase() === "g") {
1808
+ if (key.toLowerCase() === "i") {
1593
1809
  cleanup();
1810
+ console.clear();
1811
+ await handleInstallWizard(workspacePath);
1594
1812
  resolve();
1813
+ return;
1814
+ }
1815
+ if (key.toLowerCase() === "r") {
1816
+ logBuffer.push("[INFO] Reloading configuration...");
1817
+ render(logBuffer);
1818
+ return;
1819
+ }
1820
+ if (key.toLowerCase() === "c") {
1821
+ logBuffer = [];
1822
+ render(logBuffer);
1823
+ return;
1824
+ }
1825
+ if (key === "?") {
1826
+ logBuffer.push("\u2500".repeat(40));
1827
+ logBuffer.push("Commands:");
1828
+ logBuffer.push(" q - Stop server and return to menu");
1829
+ logBuffer.push(" p - Reconfigure exposed projects");
1830
+ logBuffer.push(" i - Install to additional IDEs");
1831
+ logBuffer.push(" r - Reload configuration");
1832
+ logBuffer.push(" c - Clear log display");
1833
+ logBuffer.push(" ? - Show this help");
1834
+ logBuffer.push("\u2500".repeat(40));
1835
+ render(logBuffer);
1836
+ return;
1595
1837
  }
1596
1838
  };
1597
1839
  process.stdin.on("data", onKey);
@@ -1600,35 +1842,27 @@ async function handleStartServer() {
1600
1842
  if (fs16.existsSync(logPath)) {
1601
1843
  const stats = fs16.statSync(logPath);
1602
1844
  if (stats.size > lastSize) {
1603
- const stream = fs16.createReadStream(logPath, {
1604
- start: lastSize,
1605
- end: stats.size,
1606
- encoding: "utf-8"
1607
- });
1608
- stream.on("data", (chunk) => {
1609
- process.stderr.write(chunk);
1610
- });
1845
+ const buffer = Buffer.alloc(stats.size - lastSize);
1846
+ const fd = fs16.openSync(logPath, "r");
1847
+ fs16.readSync(fd, buffer, 0, buffer.length, lastSize);
1848
+ fs16.closeSync(fd);
1849
+ const newContent = buffer.toString("utf-8");
1850
+ const newLines = newContent.split("\n").filter((l) => l.trim());
1851
+ logBuffer.push(...newLines);
1852
+ if (logBuffer.length > 100) {
1853
+ logBuffer = logBuffer.slice(-100);
1854
+ }
1611
1855
  lastSize = stats.size;
1856
+ render(logBuffer);
1612
1857
  }
1613
1858
  }
1614
1859
  }, 500);
1615
- const cleanup = () => {
1616
- isRunning = false;
1617
- clearInterval(interval);
1618
- if (process.stdin.setRawMode) {
1619
- process.stdin.setRawMode(false);
1620
- }
1621
- process.stdin.removeListener("data", onKey);
1622
- process.stdin.pause();
1623
- stopMCPServer();
1624
- console.log("");
1625
- };
1626
1860
  });
1627
1861
  } catch (error) {
1628
1862
  if (process.stdin.setRawMode) {
1629
1863
  process.stdin.setRawMode(false);
1630
1864
  }
1631
- console.error(pc8.red("\nFailed to start server:"));
1865
+ console.error(pc7.red("\nFailed to start server:"));
1632
1866
  console.error(error);
1633
1867
  }
1634
1868
  }
@@ -1636,11 +1870,11 @@ async function handleConfigureGlobalPath() {
1636
1870
  const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
1637
1871
  const fs16 = await import("fs");
1638
1872
  const path16 = await import("path");
1639
- note7(
1640
- `MCP Hub requires a ${pc8.bold("global storage path")} to store its configuration
1873
+ note6(
1874
+ `MCP Hub requires a ${pc7.bold("global storage path")} to store its configuration
1641
1875
  and coordinate across projects.
1642
1876
 
1643
- Your current setup uses ${pc8.cyan("workspace")} mode, which stores data
1877
+ Your current setup uses ${pc7.cyan("workspace")} mode, which stores data
1644
1878
  locally in each project. MCP needs a central location.`,
1645
1879
  "Global Path Required"
1646
1880
  );
@@ -1654,8 +1888,8 @@ locally in each project. MCP needs a central location.`,
1654
1888
  }
1655
1889
  const config = loadMCPConfig();
1656
1890
  saveMCPConfig(config);
1657
- note7(
1658
- `${pc8.green("\u2713")} Global path configured: ${pc8.cyan(resolvedPath)}
1891
+ note6(
1892
+ `${pc7.green("\u2713")} Global path configured: ${pc7.cyan(resolvedPath)}
1659
1893
 
1660
1894
  MCP config will be stored at:
1661
1895
  ${path16.join(resolvedPath, "mcp.yaml")}`,
@@ -1663,54 +1897,63 @@ ${path16.join(resolvedPath, "mcp.yaml")}`,
1663
1897
  );
1664
1898
  return true;
1665
1899
  } catch (error) {
1666
- note7(
1667
- `${pc8.red("\u2717")} Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
1900
+ note6(
1901
+ `${pc7.red("\u2717")} Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
1668
1902
  "Error"
1669
1903
  );
1670
1904
  return false;
1671
1905
  }
1672
1906
  }
1673
1907
  async function handleShowStatus() {
1674
- const s = spinner6();
1908
+ const s = spinner5();
1675
1909
  s.start("Loading projects...");
1676
1910
  const config = loadMCPConfig();
1677
1911
  const projects = scanForProjects();
1912
+ const workspacePath = detectWorkspaceRoot();
1913
+ const installStatus = checkInstallStatus(workspacePath);
1678
1914
  s.stop("Projects loaded");
1679
1915
  if (projects.length === 0) {
1680
- note7('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
1916
+ note6('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
1681
1917
  return;
1682
1918
  }
1683
1919
  const lines = [
1684
- `${pc8.bold("Project Status")}`,
1920
+ `${pc7.bold("Installation Status")}`,
1921
+ "",
1922
+ ` Antigravity: ${installStatus.antigravity ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")}`,
1923
+ ` VSCode (Global): ${installStatus.vscodeGlobal ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")}`,
1924
+ ` VSCode (Workspace): ${installStatus.vscodeWorkspace ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")}`,
1925
+ ` Claude Desktop: ${installStatus.claude ? pc7.green("\u2713 Installed") : pc7.dim("Not installed")}`,
1926
+ "",
1927
+ `${pc7.bold("Project Status")}`,
1685
1928
  ""
1686
1929
  ];
1687
1930
  for (const project of projects) {
1688
1931
  const projectConfig = config.projects.find((p) => p.name === project.name);
1689
1932
  const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
1690
- const status = isExposed ? pc8.green("\u2713 exposed") : pc8.dim("\u25CB hidden");
1691
- const source = pc8.dim(`(${project.source})`);
1933
+ const status = isExposed ? pc7.green("\u2713 exposed") : pc7.dim("\u25CB hidden");
1934
+ const source = pc7.dim(`(${project.source})`);
1692
1935
  lines.push(` ${status} ${project.name} ${source}`);
1693
1936
  }
1694
1937
  lines.push("");
1695
- lines.push(pc8.dim(`Config: ${getMCPConfigPath()}`));
1938
+ lines.push(pc7.dim(`Config: ${getMCPConfigPath()}`));
1696
1939
  const serverStatus = getMCPServerStatus();
1697
1940
  if (serverStatus.running) {
1698
- lines.push(pc8.green(`Server: running on port ${serverStatus.port}`));
1941
+ lines.push(pc7.green(`Server: running on port ${serverStatus.port}`));
1699
1942
  } else {
1700
- lines.push(pc8.dim("Server: not running"));
1943
+ lines.push(pc7.dim("Server: not running"));
1701
1944
  }
1702
- note7(lines.join("\n"), "MCP Hub Status");
1945
+ note6(lines.join("\n"), "MCP Hub Status");
1703
1946
  }
1704
1947
  async function handleConfigure() {
1705
1948
  const { logger: logger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
1706
- const s = spinner6();
1949
+ const s = spinner5();
1707
1950
  s.start("Scanning for projects...");
1708
1951
  const config = loadMCPConfig();
1709
1952
  const projects = scanForProjects();
1710
1953
  logger2.info("Configure: Loaded config", { projects: config.projects, defaultMode: config.defaults.includeNew });
1711
1954
  s.stop("Projects found");
1712
1955
  if (projects.length === 0) {
1713
- note7('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
1956
+ note6('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
1714
1957
  return;
1715
1958
  }
1716
1959
  const options = projects.map((project) => {
@@ -1718,7 +1961,7 @@ async function handleConfigure() {
1718
1961
  const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
1719
1962
  return {
1720
1963
  value: project.name,
1721
- label: `${project.name} ${pc8.dim(`(${project.source})`)}`,
1964
+ label: `${project.name} ${pc7.dim(`(${project.source})`)}`,
1722
1965
  hint: project.dataPath
1723
1966
  };
1724
1967
  });
@@ -1732,7 +1975,7 @@ async function handleConfigure() {
1732
1975
  initialValues: currentlyExposed,
1733
1976
  required: false
1734
1977
  });
1735
- if (isCancel7(selected)) {
1978
+ if (isCancel6(selected)) {
1736
1979
  return;
1737
1980
  }
1738
1981
  const selectedNames = selected;
@@ -1744,8 +1987,8 @@ async function handleConfigure() {
1744
1987
  saveMCPConfig(config);
1745
1988
  logger2.info("Configure: Config saved", config);
1746
1989
  const exposedCount = selectedNames.length;
1747
- note7(
1748
- `${pc8.green("\u2713")} Configuration saved!
1990
+ note6(
1991
+ `${pc7.green("\u2713")} Configuration saved!
1749
1992
 
1750
1993
  Exposed projects: ${exposedCount}
1751
1994
  Hidden projects: ${projects.length - exposedCount}`,
@@ -1755,65 +1998,57 @@ Hidden projects: ${projects.length - exposedCount}`,
1755
1998
  async function handleStopServer() {
1756
1999
  const status = getMCPServerStatus();
1757
2000
  if (!status.running) {
1758
- note7("MCP server is not running.", "Status");
2001
+ note6("MCP server is not running.", "Status");
1759
2002
  return;
1760
2003
  }
1761
2004
  const confirmed = await confirm4({
1762
2005
  message: "Stop the MCP server?",
1763
2006
  initialValue: true
1764
2007
  });
1765
- if (isCancel7(confirmed) || !confirmed) {
2008
+ if (isCancel6(confirmed) || !confirmed) {
1766
2009
  return;
1767
2010
  }
1768
2011
  stopMCPServer();
1769
- note7(pc8.green("MCP server stopped."), "Server Stopped");
2012
+ note6(pc7.green("MCP server stopped."), "Server Stopped");
1770
2013
  }
1771
2014
  function showHelp() {
1772
2015
  const help = `
1773
- ${pc8.bold("RRCE MCP Hub")} - Cross-project AI assistant server
2016
+ ${pc7.bold("RRCE MCP Hub")} - Cross-project AI assistant server
1774
2017
 
1775
- ${pc8.bold("ABOUT")}
2018
+ ${pc7.bold("ABOUT")}
1776
2019
  MCP (Model Context Protocol) allows AI assistants like Claude to
1777
2020
  access your project knowledge in real-time. The RRCE MCP Hub
1778
2021
  provides a central server that exposes selected projects.
1779
2022
 
1780
- ${pc8.bold("MENU OPTIONS")}
1781
- ${pc8.cyan("View project status")} See which projects are exposed
1782
- ${pc8.cyan("Configure projects")} Choose which projects to expose
1783
- ${pc8.cyan("Start MCP server")} Start the server for AI access
1784
- ${pc8.cyan("Stop MCP server")} Stop the running server
2023
+ ${pc7.bold("MENU OPTIONS")}
2024
+ ${pc7.cyan("Start MCP server")} Start the server for AI access
2025
+ ${pc7.cyan("Configure projects")} Choose which projects to expose
2026
+ ${pc7.cyan("Install to IDE")} Add to Antigravity, VSCode, or Claude
2027
+ ${pc7.cyan("View status")} See which projects are exposed
1785
2028
 
1786
- ${pc8.bold("DIRECT COMMANDS")}
1787
- ${pc8.dim("rrce-workflow mcp start")} Start server directly
1788
- ${pc8.dim("rrce-workflow mcp stop")} Stop server directly
1789
- ${pc8.dim("rrce-workflow mcp status")} Show status directly
1790
- ${pc8.dim("rrce-workflow mcp help")} Show this help
2029
+ ${pc7.bold("DIRECT COMMANDS")}
2030
+ ${pc7.dim("rrce-workflow mcp start")} Start server directly
2031
+ ${pc7.dim("rrce-workflow mcp stop")} Stop server directly
2032
+ ${pc7.dim("rrce-workflow mcp status")} Show status directly
2033
+ ${pc7.dim("rrce-workflow mcp help")} Show this help
1791
2034
 
1792
- ${pc8.bold("CLAUDE DESKTOP SETUP")}
1793
- Add to ${pc8.cyan("~/.config/claude/claude_desktop_config.json")}:
1794
- ${pc8.dim(`{
1795
- "mcpServers": {
1796
- "rrce": {
1797
- "command": "npx",
1798
- "args": ["rrce-workflow", "mcp", "start"]
1799
- }
1800
- }
1801
- }`)}
2035
+ ${pc7.bold("IDE INSTALLATION")}
2036
+ ${pc7.cyan("Antigravity")} ~/.gemini/antigravity/mcp_config.json
2037
+ ${pc7.cyan("VSCode Global")} ~/.config/Code/User/settings.json
2038
+ ${pc7.cyan("VSCode Workspace")} .vscode/mcp.json
2039
+ ${pc7.cyan("Claude Desktop")} ~/.config/claude/claude_desktop_config.json
1802
2040
 
1803
- ${pc8.bold("RESOURCES EXPOSED")}
1804
- ${pc8.cyan("rrce://projects")} List all exposed projects
1805
- ${pc8.cyan("rrce://projects/{name}/context")} Get project context
1806
- ${pc8.cyan("rrce://projects/{name}/tasks")} Get project tasks
2041
+ ${pc7.bold("SERVER COMMANDS")} (while running)
2042
+ ${pc7.cyan("q")} Stop and quit ${pc7.cyan("p")} Reconfigure projects
2043
+ ${pc7.cyan("i")} Install to IDE ${pc7.cyan("r")} Reload config
2044
+ ${pc7.cyan("c")} Clear logs ${pc7.cyan("?")} Show help
1807
2045
 
1808
- ${pc8.bold("PROMPTS (Agent Commands)")}
1809
- ${pc8.cyan("init")} Initialize project context
1810
- ${pc8.cyan("research")} Research requirements for a task
1811
- ${pc8.cyan("plan")} Create execution plan
1812
- ${pc8.cyan("execute")} Implement planned work
1813
- ${pc8.cyan("docs")} Generate documentation
1814
- ${pc8.cyan("sync")} Sync knowledge with codebase
2046
+ ${pc7.bold("RESOURCES EXPOSED")}
2047
+ ${pc7.cyan("rrce://projects")} List all exposed projects
2048
+ ${pc7.cyan("rrce://projects/{name}/context")} Get project context
2049
+ ${pc7.cyan("rrce://projects/{name}/tasks")} Get project tasks
1815
2050
  `;
1816
- note7(help.trim(), "Help");
2051
+ note6(help.trim(), "Help");
1817
2052
  }
1818
2053
  var init_mcp = __esm({
1819
2054
  "src/mcp/index.ts"() {
@@ -1822,13 +2057,14 @@ var init_mcp = __esm({
1822
2057
  init_detection();
1823
2058
  init_server();
1824
2059
  init_install();
2060
+ init_paths();
1825
2061
  }
1826
2062
  });
1827
2063
 
1828
2064
  // src/commands/wizard/index.ts
1829
- import { intro, select as select3, spinner as spinner5, note as note6, outro as outro5, isCancel as isCancel6 } from "@clack/prompts";
1830
- import pc7 from "picocolors";
1831
- import * as fs11 from "fs";
2065
+ import { intro as intro2, select as select4, spinner as spinner6, note as note7, outro as outro6, isCancel as isCancel7 } from "@clack/prompts";
2066
+ import pc8 from "picocolors";
2067
+ import * as fs15 from "fs";
1832
2068
 
1833
2069
  // src/lib/git.ts
1834
2070
  import { execSync } from "child_process";
@@ -2430,18 +2666,19 @@ function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot,
2430
2666
  }
2431
2667
 
2432
2668
  // src/commands/wizard/index.ts
2669
+ init_mcp();
2433
2670
  async function runWizard() {
2434
- intro(pc7.cyan(pc7.inverse(" RRCE-Workflow Setup ")));
2435
- const s = spinner5();
2671
+ intro2(pc8.cyan(pc8.inverse(" RRCE-Workflow Setup ")));
2672
+ const s = spinner6();
2436
2673
  s.start("Detecting environment");
2437
2674
  const workspacePath = detectWorkspaceRoot();
2438
2675
  const workspaceName = getWorkspaceName(workspacePath);
2439
2676
  const gitUser = getGitUser();
2440
2677
  await new Promise((r) => setTimeout(r, 800));
2441
2678
  s.stop("Environment detected");
2442
- note6(
2443
- `Git User: ${pc7.bold(gitUser || "(not found)")}
2444
- Workspace: ${pc7.bold(workspaceName)}`,
2679
+ note7(
2680
+ `Git User: ${pc8.bold(gitUser || "(not found)")}
2681
+ Workspace: ${pc8.bold(workspaceName)}`,
2445
2682
  "Context"
2446
2683
  );
2447
2684
  const detectedProjects = scanForProjects({
@@ -2449,44 +2686,53 @@ Workspace: ${pc7.bold(workspaceName)}`,
2449
2686
  workspacePath
2450
2687
  });
2451
2688
  const configFilePath = getConfigPath(workspacePath);
2452
- const isAlreadyConfigured = fs11.existsSync(configFilePath);
2689
+ const isAlreadyConfigured = fs15.existsSync(configFilePath);
2453
2690
  let currentStorageMode = null;
2454
2691
  if (isAlreadyConfigured) {
2455
2692
  try {
2456
- const configContent = fs11.readFileSync(configFilePath, "utf-8");
2693
+ const configContent = fs15.readFileSync(configFilePath, "utf-8");
2457
2694
  const modeMatch = configContent.match(/mode:\s*(global|workspace)/);
2458
2695
  currentStorageMode = modeMatch?.[1] ?? null;
2459
2696
  } catch {
2460
2697
  }
2461
2698
  }
2462
2699
  const localDataPath = getLocalWorkspacePath(workspacePath);
2463
- const hasLocalData = fs11.existsSync(localDataPath);
2700
+ const hasLocalData = fs15.existsSync(localDataPath);
2464
2701
  if (isAlreadyConfigured) {
2465
2702
  const menuOptions = [];
2703
+ menuOptions.push({
2704
+ value: "mcp",
2705
+ label: "\u{1F50C} Configure MCP Server",
2706
+ hint: "Expose projects to AI assistants (VSCode, Antigravity, Claude)"
2707
+ });
2466
2708
  if (detectedProjects.length > 0) {
2467
2709
  menuOptions.push({
2468
2710
  value: "link",
2469
- label: "Link other project knowledge",
2711
+ label: "\u{1F517} Link other project knowledge",
2470
2712
  hint: `${detectedProjects.length} projects detected (global + sibling)`
2471
2713
  });
2472
2714
  }
2473
2715
  if (currentStorageMode === "workspace" && hasLocalData) {
2474
2716
  menuOptions.push({
2475
2717
  value: "sync-global",
2476
- label: "Sync to global storage",
2718
+ label: "\u2601\uFE0F Sync to global storage",
2477
2719
  hint: "Share knowledge with other projects"
2478
2720
  });
2479
2721
  }
2480
- menuOptions.push({ value: "update", label: "Update from package", hint: "Get latest prompts & templates" });
2481
- menuOptions.push({ value: "exit", label: "Exit" });
2482
- const action = await select3({
2722
+ menuOptions.push({ value: "update", label: "\u{1F4E6} Update from package", hint: "Get latest prompts & templates" });
2723
+ menuOptions.push({ value: "exit", label: "\u21A9 Exit" });
2724
+ const action = await select4({
2483
2725
  message: "This workspace is already configured. What would you like to do?",
2484
2726
  options: menuOptions
2485
2727
  });
2486
- if (isCancel6(action) || action === "exit") {
2487
- outro5("Exited.");
2728
+ if (isCancel7(action) || action === "exit") {
2729
+ outro6("Exited.");
2488
2730
  process.exit(0);
2489
2731
  }
2732
+ if (action === "mcp") {
2733
+ await runMCP();
2734
+ return;
2735
+ }
2490
2736
  if (action === "link") {
2491
2737
  await runLinkProjectsFlow(workspacePath, workspaceName);
2492
2738
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.27",
3
+ "version": "0.2.28",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",