rrce-workflow 0.2.26 → 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.
- package/dist/index.js +493 -180
- 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
|
|
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 (
|
|
599
|
-
const content =
|
|
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 (!
|
|
617
|
+
if (!fs11.existsSync(configPath)) {
|
|
618
618
|
return { ...DEFAULT_MCP_CONFIG };
|
|
619
619
|
}
|
|
620
620
|
try {
|
|
621
|
-
const content =
|
|
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 (!
|
|
631
|
-
|
|
630
|
+
if (!fs11.existsSync(dir)) {
|
|
631
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
632
632
|
}
|
|
633
633
|
const content = serializeMCPConfig(config);
|
|
634
|
-
|
|
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
|
|
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 (!
|
|
835
|
-
|
|
834
|
+
if (!fs12.existsSync(dir)) {
|
|
835
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
836
836
|
}
|
|
837
|
-
|
|
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
|
|
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 (!
|
|
890
|
+
if (!fs13.existsSync(contextPath)) {
|
|
891
891
|
return null;
|
|
892
892
|
}
|
|
893
|
-
return
|
|
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 || !
|
|
906
|
+
if (!project?.tasksPath || !fs13.existsSync(project.tasksPath)) {
|
|
907
907
|
return [];
|
|
908
908
|
}
|
|
909
909
|
const tasks = [];
|
|
910
910
|
try {
|
|
911
|
-
const taskDirs =
|
|
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 (
|
|
915
|
+
if (fs13.existsSync(metaPath)) {
|
|
916
916
|
try {
|
|
917
|
-
const meta = JSON.parse(
|
|
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 =
|
|
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 =
|
|
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) {
|
|
@@ -1149,6 +1149,23 @@ function registerToolHandlers(server) {
|
|
|
1149
1149
|
properties: { project: { type: "string", description: "Name of the project to get context for" } },
|
|
1150
1150
|
required: ["project"]
|
|
1151
1151
|
}
|
|
1152
|
+
},
|
|
1153
|
+
{
|
|
1154
|
+
name: "list_agents",
|
|
1155
|
+
description: "List available RRCE agents/workflows",
|
|
1156
|
+
inputSchema: { type: "object", properties: {} }
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
name: "get_agent_prompt",
|
|
1160
|
+
description: "Get the instructions/prompt for a specific agent",
|
|
1161
|
+
inputSchema: {
|
|
1162
|
+
type: "object",
|
|
1163
|
+
properties: {
|
|
1164
|
+
agent: { type: "string", description: "Name of the agent (e.g. init, plan, execute)" },
|
|
1165
|
+
args: { type: "object", description: "Arguments for the agent prompt", additionalProperties: true }
|
|
1166
|
+
},
|
|
1167
|
+
required: ["agent"]
|
|
1168
|
+
}
|
|
1152
1169
|
}
|
|
1153
1170
|
]
|
|
1154
1171
|
}));
|
|
@@ -1179,6 +1196,56 @@ function registerToolHandlers(server) {
|
|
|
1179
1196
|
}
|
|
1180
1197
|
return { content: [{ type: "text", text: context }] };
|
|
1181
1198
|
}
|
|
1199
|
+
case "list_agents": {
|
|
1200
|
+
const prompts = getAllPrompts();
|
|
1201
|
+
return {
|
|
1202
|
+
content: [{
|
|
1203
|
+
type: "text",
|
|
1204
|
+
text: JSON.stringify(prompts.map((p) => ({
|
|
1205
|
+
name: p.name,
|
|
1206
|
+
description: p.description,
|
|
1207
|
+
arguments: p.arguments
|
|
1208
|
+
})), null, 2)
|
|
1209
|
+
}]
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
case "get_agent_prompt": {
|
|
1213
|
+
const params = args;
|
|
1214
|
+
const agentName = params.agent;
|
|
1215
|
+
const promptDef = getPromptDef(agentName);
|
|
1216
|
+
if (!promptDef) {
|
|
1217
|
+
throw new Error(`Agent not found: ${agentName}`);
|
|
1218
|
+
}
|
|
1219
|
+
const renderArgs = params.args || {};
|
|
1220
|
+
const stringArgs = {};
|
|
1221
|
+
for (const [key, val] of Object.entries(renderArgs)) {
|
|
1222
|
+
stringArgs[key] = String(val);
|
|
1223
|
+
}
|
|
1224
|
+
const content = renderPrompt(promptDef.content, stringArgs);
|
|
1225
|
+
const projects = getExposedProjects();
|
|
1226
|
+
const activeProject = detectActiveProject();
|
|
1227
|
+
const projectList = projects.map((p) => {
|
|
1228
|
+
const isActive = activeProject && p.dataPath === activeProject.dataPath;
|
|
1229
|
+
return `- ${p.name} (${p.source}) ${isActive ? "**[ACTIVE]**" : ""}`;
|
|
1230
|
+
}).join("\n");
|
|
1231
|
+
let contextPreamble = `
|
|
1232
|
+
Context - Available Projects (MCP Hub):
|
|
1233
|
+
${projectList}
|
|
1234
|
+
`;
|
|
1235
|
+
if (activeProject) {
|
|
1236
|
+
contextPreamble += `
|
|
1237
|
+
Current Active Workspace: ${activeProject.name} (${activeProject.path})
|
|
1238
|
+
`;
|
|
1239
|
+
contextPreamble += `IMPORTANT: Treat '${activeProject.path}' as the {{WORKSPACE_ROOT}}. All relative path operations (file reads/writes) MUST be performed relative to this directory.
|
|
1240
|
+
`;
|
|
1241
|
+
}
|
|
1242
|
+
contextPreamble += `
|
|
1243
|
+
Note: If the user's request refers to a project not listed here, ask them to expose it via 'rrce-workflow mcp configure'.
|
|
1244
|
+
|
|
1245
|
+
---
|
|
1246
|
+
`;
|
|
1247
|
+
return { content: [{ type: "text", text: contextPreamble + content }] };
|
|
1248
|
+
}
|
|
1182
1249
|
default:
|
|
1183
1250
|
throw new Error(`Unknown tool: ${name}`);
|
|
1184
1251
|
}
|
|
@@ -1290,34 +1357,81 @@ var init_server = __esm({
|
|
|
1290
1357
|
});
|
|
1291
1358
|
|
|
1292
1359
|
// src/mcp/install.ts
|
|
1293
|
-
import * as
|
|
1360
|
+
import * as fs14 from "fs";
|
|
1294
1361
|
import * as path14 from "path";
|
|
1295
1362
|
import * as os from "os";
|
|
1296
|
-
function checkInstallStatus() {
|
|
1363
|
+
function checkInstallStatus(workspacePath) {
|
|
1297
1364
|
return {
|
|
1298
|
-
antigravity:
|
|
1299
|
-
claude:
|
|
1365
|
+
antigravity: checkAntigravityConfig(),
|
|
1366
|
+
claude: checkClaudeConfig(),
|
|
1367
|
+
vscodeGlobal: checkVSCodeGlobalConfig(),
|
|
1368
|
+
vscodeWorkspace: workspacePath ? checkVSCodeWorkspaceConfig(workspacePath) : false
|
|
1300
1369
|
};
|
|
1301
1370
|
}
|
|
1302
|
-
function
|
|
1303
|
-
if (!
|
|
1371
|
+
function checkAntigravityConfig() {
|
|
1372
|
+
if (!fs14.existsSync(ANTIGRAVITY_CONFIG)) return false;
|
|
1304
1373
|
try {
|
|
1305
|
-
const content = JSON.parse(
|
|
1374
|
+
const content = JSON.parse(fs14.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
|
|
1306
1375
|
return !!content.mcpServers?.["rrce"];
|
|
1307
1376
|
} catch {
|
|
1308
1377
|
return false;
|
|
1309
1378
|
}
|
|
1310
1379
|
}
|
|
1311
|
-
function
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1380
|
+
function checkClaudeConfig() {
|
|
1381
|
+
if (!fs14.existsSync(CLAUDE_CONFIG)) return false;
|
|
1382
|
+
try {
|
|
1383
|
+
const content = JSON.parse(fs14.readFileSync(CLAUDE_CONFIG, "utf-8"));
|
|
1384
|
+
return !!content.mcpServers?.["rrce"];
|
|
1385
|
+
} catch {
|
|
1386
|
+
return false;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
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 });
|
|
1316
1430
|
}
|
|
1317
1431
|
let config = { mcpServers: {} };
|
|
1318
|
-
if (
|
|
1432
|
+
if (fs14.existsSync(ANTIGRAVITY_CONFIG)) {
|
|
1319
1433
|
try {
|
|
1320
|
-
config = JSON.parse(
|
|
1434
|
+
config = JSON.parse(fs14.readFileSync(ANTIGRAVITY_CONFIG, "utf-8"));
|
|
1321
1435
|
} catch {
|
|
1322
1436
|
}
|
|
1323
1437
|
}
|
|
@@ -1325,21 +1439,108 @@ function installToConfig(target) {
|
|
|
1325
1439
|
config.mcpServers["rrce"] = {
|
|
1326
1440
|
command: "npx",
|
|
1327
1441
|
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
1328
|
-
// -y to avoid interactive prompts
|
|
1329
1442
|
};
|
|
1330
1443
|
try {
|
|
1331
|
-
|
|
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 });
|
|
1454
|
+
}
|
|
1455
|
+
let config = { mcpServers: {} };
|
|
1456
|
+
if (fs14.existsSync(CLAUDE_CONFIG)) {
|
|
1457
|
+
try {
|
|
1458
|
+
config = JSON.parse(fs14.readFileSync(CLAUDE_CONFIG, "utf-8"));
|
|
1459
|
+
} catch {
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
if (!config.mcpServers) config.mcpServers = {};
|
|
1463
|
+
config.mcpServers["rrce"] = {
|
|
1464
|
+
command: "npx",
|
|
1465
|
+
args: ["-y", "rrce-workflow", "mcp", "start"]
|
|
1466
|
+
};
|
|
1467
|
+
try {
|
|
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));
|
|
1332
1493
|
return true;
|
|
1333
1494
|
} catch {
|
|
1334
1495
|
return false;
|
|
1335
1496
|
}
|
|
1336
1497
|
}
|
|
1337
|
-
|
|
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;
|
|
1338
1538
|
var init_install = __esm({
|
|
1339
1539
|
"src/mcp/install.ts"() {
|
|
1340
1540
|
"use strict";
|
|
1341
1541
|
ANTIGRAVITY_CONFIG = path14.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
|
|
1342
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");
|
|
1343
1544
|
}
|
|
1344
1545
|
});
|
|
1345
1546
|
|
|
@@ -1348,8 +1549,8 @@ var mcp_exports = {};
|
|
|
1348
1549
|
__export(mcp_exports, {
|
|
1349
1550
|
runMCP: () => runMCP
|
|
1350
1551
|
});
|
|
1351
|
-
import { intro
|
|
1352
|
-
import
|
|
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";
|
|
1353
1554
|
async function runMCP(subcommand2) {
|
|
1354
1555
|
if (subcommand2) {
|
|
1355
1556
|
switch (subcommand2) {
|
|
@@ -1369,42 +1570,69 @@ async function runMCP(subcommand2) {
|
|
|
1369
1570
|
return;
|
|
1370
1571
|
}
|
|
1371
1572
|
}
|
|
1372
|
-
|
|
1573
|
+
intro(pc7.bgCyan(pc7.black(" RRCE MCP Hub ")));
|
|
1574
|
+
const workspacePath = detectWorkspaceRoot();
|
|
1373
1575
|
const globalPathCheck = await ensureMCPGlobalPath();
|
|
1374
1576
|
if (!globalPathCheck.configured) {
|
|
1375
1577
|
const configured = await handleConfigureGlobalPath();
|
|
1376
1578
|
if (!configured) {
|
|
1377
|
-
|
|
1579
|
+
outro5(pc7.yellow("MCP requires a global storage path. Setup cancelled."));
|
|
1378
1580
|
return;
|
|
1379
1581
|
}
|
|
1380
1582
|
}
|
|
1381
|
-
const status = checkInstallStatus();
|
|
1382
|
-
|
|
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
|
+
);
|
|
1383
1593
|
const shouldInstall = await confirm4({
|
|
1384
|
-
message: "MCP server
|
|
1594
|
+
message: "Install MCP server to your IDE(s)?",
|
|
1385
1595
|
initialValue: true
|
|
1386
1596
|
});
|
|
1387
|
-
if (shouldInstall && !
|
|
1388
|
-
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
|
+
}
|
|
1389
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();
|
|
1390
1616
|
}
|
|
1391
1617
|
let running = true;
|
|
1392
1618
|
while (running) {
|
|
1393
1619
|
const serverStatus = getMCPServerStatus();
|
|
1394
|
-
const serverLabel = serverStatus.running ?
|
|
1395
|
-
const
|
|
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({
|
|
1396
1624
|
message: "What would you like to do?",
|
|
1397
1625
|
options: [
|
|
1398
|
-
{ value: "start", label: `\u25B6\uFE0F Start MCP server`, hint:
|
|
1626
|
+
{ value: "start", label: `\u25B6\uFE0F Start MCP server`, hint: serverLabel },
|
|
1399
1627
|
{ value: "configure", label: "\u2699\uFE0F Configure projects", hint: "Choose which projects to expose" },
|
|
1400
|
-
{ value: "install", label: "\u{1F4E5} Install to IDE", hint:
|
|
1628
|
+
{ value: "install", label: "\u{1F4E5} Install to IDE", hint: `${installedCount} IDE(s) configured` },
|
|
1401
1629
|
{ value: "status", label: "\u{1F4CB} View status", hint: "See details" },
|
|
1402
1630
|
{ value: "help", label: "\u2753 Help", hint: "Learn about MCP Hub" },
|
|
1403
1631
|
{ value: "exit", label: "\u21A9 Exit", hint: "Return to shell" }
|
|
1404
1632
|
]
|
|
1405
1633
|
});
|
|
1406
|
-
if (
|
|
1407
|
-
|
|
1634
|
+
if (isCancel6(action)) {
|
|
1635
|
+
cancel5("MCP Hub closed.");
|
|
1408
1636
|
return;
|
|
1409
1637
|
}
|
|
1410
1638
|
switch (action) {
|
|
@@ -1415,7 +1643,7 @@ async function runMCP(subcommand2) {
|
|
|
1415
1643
|
await handleConfigure();
|
|
1416
1644
|
break;
|
|
1417
1645
|
case "install":
|
|
1418
|
-
await handleInstallWizard();
|
|
1646
|
+
await handleInstallWizard(workspacePath);
|
|
1419
1647
|
break;
|
|
1420
1648
|
case "status":
|
|
1421
1649
|
await handleShowStatus();
|
|
@@ -1428,46 +1656,72 @@ async function runMCP(subcommand2) {
|
|
|
1428
1656
|
break;
|
|
1429
1657
|
}
|
|
1430
1658
|
}
|
|
1431
|
-
|
|
1659
|
+
outro5(pc7.green("MCP Hub closed."));
|
|
1432
1660
|
}
|
|
1433
|
-
async function handleInstallWizard() {
|
|
1434
|
-
const status = checkInstallStatus();
|
|
1661
|
+
async function handleInstallWizard(workspacePath) {
|
|
1662
|
+
const status = checkInstallStatus(workspacePath);
|
|
1435
1663
|
const options = [
|
|
1436
|
-
{
|
|
1437
|
-
|
|
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
|
+
}
|
|
1438
1684
|
];
|
|
1439
1685
|
const selected = await multiselect3({
|
|
1440
1686
|
message: "Select where to install RRCE MCP Server:",
|
|
1441
1687
|
options,
|
|
1442
1688
|
initialValues: [
|
|
1443
1689
|
...status.antigravity ? ["antigravity"] : [],
|
|
1690
|
+
...status.vscodeGlobal ? ["vscode-global"] : [],
|
|
1691
|
+
...status.vscodeWorkspace ? ["vscode-workspace"] : [],
|
|
1444
1692
|
...status.claude ? ["claude"] : []
|
|
1445
1693
|
],
|
|
1446
1694
|
required: false
|
|
1447
1695
|
});
|
|
1448
|
-
if (
|
|
1696
|
+
if (isCancel6(selected)) return;
|
|
1449
1697
|
const targets = selected;
|
|
1450
1698
|
const results = [];
|
|
1451
1699
|
for (const target of targets) {
|
|
1452
|
-
const success = installToConfig(target);
|
|
1453
|
-
|
|
1700
|
+
const success = installToConfig(target, workspacePath);
|
|
1701
|
+
const label = getTargetLabel(target);
|
|
1702
|
+
results.push(`${label}: ${success ? pc7.green("\u2713 Success") : pc7.red("\u2717 Failed")}`);
|
|
1454
1703
|
}
|
|
1455
1704
|
if (results.length > 0) {
|
|
1456
|
-
|
|
1705
|
+
note6(results.join("\n"), "Installation Results");
|
|
1457
1706
|
}
|
|
1458
1707
|
}
|
|
1459
1708
|
async function handleStartServer() {
|
|
1460
1709
|
const fs16 = await import("fs");
|
|
1461
1710
|
const { getLogFilePath: getLogFilePath2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
1462
1711
|
const config = loadMCPConfig();
|
|
1463
|
-
const
|
|
1464
|
-
|
|
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) {
|
|
1465
1718
|
const shouldConfig = await confirm4({
|
|
1466
1719
|
message: "No projects are currently exposed. Configure now?",
|
|
1467
1720
|
initialValue: true
|
|
1468
1721
|
});
|
|
1469
|
-
if (shouldConfig && !
|
|
1722
|
+
if (shouldConfig && !isCancel6(shouldConfig)) {
|
|
1470
1723
|
await handleConfigure();
|
|
1724
|
+
return handleStartServer();
|
|
1471
1725
|
}
|
|
1472
1726
|
}
|
|
1473
1727
|
const portInput = await text2({
|
|
@@ -1478,7 +1732,7 @@ async function handleStartServer() {
|
|
|
1478
1732
|
if (isNaN(Number(value))) return "Port must be a number";
|
|
1479
1733
|
}
|
|
1480
1734
|
});
|
|
1481
|
-
if (
|
|
1735
|
+
if (isCancel6(portInput)) return;
|
|
1482
1736
|
const newPort = parseInt(portInput, 10);
|
|
1483
1737
|
if (newPort !== config.server.port) {
|
|
1484
1738
|
config.server.port = newPort;
|
|
@@ -1486,23 +1740,33 @@ async function handleStartServer() {
|
|
|
1486
1740
|
}
|
|
1487
1741
|
console.clear();
|
|
1488
1742
|
const logPath = getLogFilePath2();
|
|
1489
|
-
const
|
|
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 = []) => {
|
|
1490
1747
|
console.clear();
|
|
1491
|
-
console.log(
|
|
1492
|
-
console.log(
|
|
1493
|
-
console.log(
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
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"));
|
|
1503
1767
|
};
|
|
1504
|
-
|
|
1505
|
-
|
|
1768
|
+
let logBuffer = [];
|
|
1769
|
+
render(logBuffer);
|
|
1506
1770
|
try {
|
|
1507
1771
|
await startMCPServer();
|
|
1508
1772
|
let lastSize = 0;
|
|
@@ -1517,14 +1781,59 @@ async function handleStartServer() {
|
|
|
1517
1781
|
process.stdin.setEncoding("utf8");
|
|
1518
1782
|
}
|
|
1519
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
|
+
};
|
|
1520
1795
|
const onKey = async (key) => {
|
|
1521
1796
|
if (key === "" || key.toLowerCase() === "q") {
|
|
1522
1797
|
cleanup();
|
|
1523
1798
|
resolve();
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
if (key.toLowerCase() === "p") {
|
|
1802
|
+
cleanup();
|
|
1803
|
+
console.clear();
|
|
1804
|
+
await handleConfigure();
|
|
1805
|
+
resolve();
|
|
1806
|
+
return;
|
|
1524
1807
|
}
|
|
1525
|
-
if (key.toLowerCase() === "
|
|
1808
|
+
if (key.toLowerCase() === "i") {
|
|
1526
1809
|
cleanup();
|
|
1810
|
+
console.clear();
|
|
1811
|
+
await handleInstallWizard(workspacePath);
|
|
1527
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;
|
|
1528
1837
|
}
|
|
1529
1838
|
};
|
|
1530
1839
|
process.stdin.on("data", onKey);
|
|
@@ -1533,35 +1842,27 @@ async function handleStartServer() {
|
|
|
1533
1842
|
if (fs16.existsSync(logPath)) {
|
|
1534
1843
|
const stats = fs16.statSync(logPath);
|
|
1535
1844
|
if (stats.size > lastSize) {
|
|
1536
|
-
const
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
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
|
+
}
|
|
1544
1855
|
lastSize = stats.size;
|
|
1856
|
+
render(logBuffer);
|
|
1545
1857
|
}
|
|
1546
1858
|
}
|
|
1547
1859
|
}, 500);
|
|
1548
|
-
const cleanup = () => {
|
|
1549
|
-
isRunning = false;
|
|
1550
|
-
clearInterval(interval);
|
|
1551
|
-
if (process.stdin.setRawMode) {
|
|
1552
|
-
process.stdin.setRawMode(false);
|
|
1553
|
-
}
|
|
1554
|
-
process.stdin.removeListener("data", onKey);
|
|
1555
|
-
process.stdin.pause();
|
|
1556
|
-
stopMCPServer();
|
|
1557
|
-
console.log("");
|
|
1558
|
-
};
|
|
1559
1860
|
});
|
|
1560
1861
|
} catch (error) {
|
|
1561
1862
|
if (process.stdin.setRawMode) {
|
|
1562
1863
|
process.stdin.setRawMode(false);
|
|
1563
1864
|
}
|
|
1564
|
-
console.error(
|
|
1865
|
+
console.error(pc7.red("\nFailed to start server:"));
|
|
1565
1866
|
console.error(error);
|
|
1566
1867
|
}
|
|
1567
1868
|
}
|
|
@@ -1569,11 +1870,11 @@ async function handleConfigureGlobalPath() {
|
|
|
1569
1870
|
const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
|
|
1570
1871
|
const fs16 = await import("fs");
|
|
1571
1872
|
const path16 = await import("path");
|
|
1572
|
-
|
|
1573
|
-
`MCP Hub requires a ${
|
|
1873
|
+
note6(
|
|
1874
|
+
`MCP Hub requires a ${pc7.bold("global storage path")} to store its configuration
|
|
1574
1875
|
and coordinate across projects.
|
|
1575
1876
|
|
|
1576
|
-
Your current setup uses ${
|
|
1877
|
+
Your current setup uses ${pc7.cyan("workspace")} mode, which stores data
|
|
1577
1878
|
locally in each project. MCP needs a central location.`,
|
|
1578
1879
|
"Global Path Required"
|
|
1579
1880
|
);
|
|
@@ -1587,8 +1888,8 @@ locally in each project. MCP needs a central location.`,
|
|
|
1587
1888
|
}
|
|
1588
1889
|
const config = loadMCPConfig();
|
|
1589
1890
|
saveMCPConfig(config);
|
|
1590
|
-
|
|
1591
|
-
`${
|
|
1891
|
+
note6(
|
|
1892
|
+
`${pc7.green("\u2713")} Global path configured: ${pc7.cyan(resolvedPath)}
|
|
1592
1893
|
|
|
1593
1894
|
MCP config will be stored at:
|
|
1594
1895
|
${path16.join(resolvedPath, "mcp.yaml")}`,
|
|
@@ -1596,54 +1897,63 @@ ${path16.join(resolvedPath, "mcp.yaml")}`,
|
|
|
1596
1897
|
);
|
|
1597
1898
|
return true;
|
|
1598
1899
|
} catch (error) {
|
|
1599
|
-
|
|
1600
|
-
`${
|
|
1900
|
+
note6(
|
|
1901
|
+
`${pc7.red("\u2717")} Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
|
|
1601
1902
|
"Error"
|
|
1602
1903
|
);
|
|
1603
1904
|
return false;
|
|
1604
1905
|
}
|
|
1605
1906
|
}
|
|
1606
1907
|
async function handleShowStatus() {
|
|
1607
|
-
const s =
|
|
1908
|
+
const s = spinner5();
|
|
1608
1909
|
s.start("Loading projects...");
|
|
1609
1910
|
const config = loadMCPConfig();
|
|
1610
1911
|
const projects = scanForProjects();
|
|
1912
|
+
const workspacePath = detectWorkspaceRoot();
|
|
1913
|
+
const installStatus = checkInstallStatus(workspacePath);
|
|
1611
1914
|
s.stop("Projects loaded");
|
|
1612
1915
|
if (projects.length === 0) {
|
|
1613
|
-
|
|
1916
|
+
note6('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
|
|
1614
1917
|
return;
|
|
1615
1918
|
}
|
|
1616
1919
|
const lines = [
|
|
1617
|
-
`${
|
|
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")}`,
|
|
1618
1928
|
""
|
|
1619
1929
|
];
|
|
1620
1930
|
for (const project of projects) {
|
|
1621
1931
|
const projectConfig = config.projects.find((p) => p.name === project.name);
|
|
1622
1932
|
const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
|
|
1623
|
-
const status = isExposed ?
|
|
1624
|
-
const source =
|
|
1933
|
+
const status = isExposed ? pc7.green("\u2713 exposed") : pc7.dim("\u25CB hidden");
|
|
1934
|
+
const source = pc7.dim(`(${project.source})`);
|
|
1625
1935
|
lines.push(` ${status} ${project.name} ${source}`);
|
|
1626
1936
|
}
|
|
1627
1937
|
lines.push("");
|
|
1628
|
-
lines.push(
|
|
1938
|
+
lines.push(pc7.dim(`Config: ${getMCPConfigPath()}`));
|
|
1629
1939
|
const serverStatus = getMCPServerStatus();
|
|
1630
1940
|
if (serverStatus.running) {
|
|
1631
|
-
lines.push(
|
|
1941
|
+
lines.push(pc7.green(`Server: running on port ${serverStatus.port}`));
|
|
1632
1942
|
} else {
|
|
1633
|
-
lines.push(
|
|
1943
|
+
lines.push(pc7.dim("Server: not running"));
|
|
1634
1944
|
}
|
|
1635
|
-
|
|
1945
|
+
note6(lines.join("\n"), "MCP Hub Status");
|
|
1636
1946
|
}
|
|
1637
1947
|
async function handleConfigure() {
|
|
1638
1948
|
const { logger: logger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
1639
|
-
const s =
|
|
1949
|
+
const s = spinner5();
|
|
1640
1950
|
s.start("Scanning for projects...");
|
|
1641
1951
|
const config = loadMCPConfig();
|
|
1642
1952
|
const projects = scanForProjects();
|
|
1643
1953
|
logger2.info("Configure: Loaded config", { projects: config.projects, defaultMode: config.defaults.includeNew });
|
|
1644
1954
|
s.stop("Projects found");
|
|
1645
1955
|
if (projects.length === 0) {
|
|
1646
|
-
|
|
1956
|
+
note6('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
|
|
1647
1957
|
return;
|
|
1648
1958
|
}
|
|
1649
1959
|
const options = projects.map((project) => {
|
|
@@ -1651,7 +1961,7 @@ async function handleConfigure() {
|
|
|
1651
1961
|
const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
|
|
1652
1962
|
return {
|
|
1653
1963
|
value: project.name,
|
|
1654
|
-
label: `${project.name} ${
|
|
1964
|
+
label: `${project.name} ${pc7.dim(`(${project.source})`)}`,
|
|
1655
1965
|
hint: project.dataPath
|
|
1656
1966
|
};
|
|
1657
1967
|
});
|
|
@@ -1665,7 +1975,7 @@ async function handleConfigure() {
|
|
|
1665
1975
|
initialValues: currentlyExposed,
|
|
1666
1976
|
required: false
|
|
1667
1977
|
});
|
|
1668
|
-
if (
|
|
1978
|
+
if (isCancel6(selected)) {
|
|
1669
1979
|
return;
|
|
1670
1980
|
}
|
|
1671
1981
|
const selectedNames = selected;
|
|
@@ -1677,8 +1987,8 @@ async function handleConfigure() {
|
|
|
1677
1987
|
saveMCPConfig(config);
|
|
1678
1988
|
logger2.info("Configure: Config saved", config);
|
|
1679
1989
|
const exposedCount = selectedNames.length;
|
|
1680
|
-
|
|
1681
|
-
`${
|
|
1990
|
+
note6(
|
|
1991
|
+
`${pc7.green("\u2713")} Configuration saved!
|
|
1682
1992
|
|
|
1683
1993
|
Exposed projects: ${exposedCount}
|
|
1684
1994
|
Hidden projects: ${projects.length - exposedCount}`,
|
|
@@ -1688,65 +1998,57 @@ Hidden projects: ${projects.length - exposedCount}`,
|
|
|
1688
1998
|
async function handleStopServer() {
|
|
1689
1999
|
const status = getMCPServerStatus();
|
|
1690
2000
|
if (!status.running) {
|
|
1691
|
-
|
|
2001
|
+
note6("MCP server is not running.", "Status");
|
|
1692
2002
|
return;
|
|
1693
2003
|
}
|
|
1694
2004
|
const confirmed = await confirm4({
|
|
1695
2005
|
message: "Stop the MCP server?",
|
|
1696
2006
|
initialValue: true
|
|
1697
2007
|
});
|
|
1698
|
-
if (
|
|
2008
|
+
if (isCancel6(confirmed) || !confirmed) {
|
|
1699
2009
|
return;
|
|
1700
2010
|
}
|
|
1701
2011
|
stopMCPServer();
|
|
1702
|
-
|
|
2012
|
+
note6(pc7.green("MCP server stopped."), "Server Stopped");
|
|
1703
2013
|
}
|
|
1704
2014
|
function showHelp() {
|
|
1705
2015
|
const help = `
|
|
1706
|
-
${
|
|
2016
|
+
${pc7.bold("RRCE MCP Hub")} - Cross-project AI assistant server
|
|
1707
2017
|
|
|
1708
|
-
${
|
|
2018
|
+
${pc7.bold("ABOUT")}
|
|
1709
2019
|
MCP (Model Context Protocol) allows AI assistants like Claude to
|
|
1710
2020
|
access your project knowledge in real-time. The RRCE MCP Hub
|
|
1711
2021
|
provides a central server that exposes selected projects.
|
|
1712
2022
|
|
|
1713
|
-
${
|
|
1714
|
-
${
|
|
1715
|
-
${
|
|
1716
|
-
${
|
|
1717
|
-
${
|
|
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
|
|
1718
2028
|
|
|
1719
|
-
${
|
|
1720
|
-
${
|
|
1721
|
-
${
|
|
1722
|
-
${
|
|
1723
|
-
${
|
|
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
|
|
1724
2034
|
|
|
1725
|
-
${
|
|
1726
|
-
|
|
1727
|
-
${
|
|
1728
|
-
"
|
|
1729
|
-
|
|
1730
|
-
"command": "npx",
|
|
1731
|
-
"args": ["rrce-workflow", "mcp", "start"]
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
}`)}
|
|
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
|
|
1735
2040
|
|
|
1736
|
-
${
|
|
1737
|
-
${
|
|
1738
|
-
${
|
|
1739
|
-
${
|
|
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
|
|
1740
2045
|
|
|
1741
|
-
${
|
|
1742
|
-
${
|
|
1743
|
-
${
|
|
1744
|
-
${
|
|
1745
|
-
${pc8.cyan("execute")} Implement planned work
|
|
1746
|
-
${pc8.cyan("docs")} Generate documentation
|
|
1747
|
-
${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
|
|
1748
2050
|
`;
|
|
1749
|
-
|
|
2051
|
+
note6(help.trim(), "Help");
|
|
1750
2052
|
}
|
|
1751
2053
|
var init_mcp = __esm({
|
|
1752
2054
|
"src/mcp/index.ts"() {
|
|
@@ -1755,13 +2057,14 @@ var init_mcp = __esm({
|
|
|
1755
2057
|
init_detection();
|
|
1756
2058
|
init_server();
|
|
1757
2059
|
init_install();
|
|
2060
|
+
init_paths();
|
|
1758
2061
|
}
|
|
1759
2062
|
});
|
|
1760
2063
|
|
|
1761
2064
|
// src/commands/wizard/index.ts
|
|
1762
|
-
import { intro, select as
|
|
1763
|
-
import
|
|
1764
|
-
import * as
|
|
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";
|
|
1765
2068
|
|
|
1766
2069
|
// src/lib/git.ts
|
|
1767
2070
|
import { execSync } from "child_process";
|
|
@@ -2363,18 +2666,19 @@ function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot,
|
|
|
2363
2666
|
}
|
|
2364
2667
|
|
|
2365
2668
|
// src/commands/wizard/index.ts
|
|
2669
|
+
init_mcp();
|
|
2366
2670
|
async function runWizard() {
|
|
2367
|
-
|
|
2368
|
-
const s =
|
|
2671
|
+
intro2(pc8.cyan(pc8.inverse(" RRCE-Workflow Setup ")));
|
|
2672
|
+
const s = spinner6();
|
|
2369
2673
|
s.start("Detecting environment");
|
|
2370
2674
|
const workspacePath = detectWorkspaceRoot();
|
|
2371
2675
|
const workspaceName = getWorkspaceName(workspacePath);
|
|
2372
2676
|
const gitUser = getGitUser();
|
|
2373
2677
|
await new Promise((r) => setTimeout(r, 800));
|
|
2374
2678
|
s.stop("Environment detected");
|
|
2375
|
-
|
|
2376
|
-
`Git User: ${
|
|
2377
|
-
Workspace: ${
|
|
2679
|
+
note7(
|
|
2680
|
+
`Git User: ${pc8.bold(gitUser || "(not found)")}
|
|
2681
|
+
Workspace: ${pc8.bold(workspaceName)}`,
|
|
2378
2682
|
"Context"
|
|
2379
2683
|
);
|
|
2380
2684
|
const detectedProjects = scanForProjects({
|
|
@@ -2382,44 +2686,53 @@ Workspace: ${pc7.bold(workspaceName)}`,
|
|
|
2382
2686
|
workspacePath
|
|
2383
2687
|
});
|
|
2384
2688
|
const configFilePath = getConfigPath(workspacePath);
|
|
2385
|
-
const isAlreadyConfigured =
|
|
2689
|
+
const isAlreadyConfigured = fs15.existsSync(configFilePath);
|
|
2386
2690
|
let currentStorageMode = null;
|
|
2387
2691
|
if (isAlreadyConfigured) {
|
|
2388
2692
|
try {
|
|
2389
|
-
const configContent =
|
|
2693
|
+
const configContent = fs15.readFileSync(configFilePath, "utf-8");
|
|
2390
2694
|
const modeMatch = configContent.match(/mode:\s*(global|workspace)/);
|
|
2391
2695
|
currentStorageMode = modeMatch?.[1] ?? null;
|
|
2392
2696
|
} catch {
|
|
2393
2697
|
}
|
|
2394
2698
|
}
|
|
2395
2699
|
const localDataPath = getLocalWorkspacePath(workspacePath);
|
|
2396
|
-
const hasLocalData =
|
|
2700
|
+
const hasLocalData = fs15.existsSync(localDataPath);
|
|
2397
2701
|
if (isAlreadyConfigured) {
|
|
2398
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
|
+
});
|
|
2399
2708
|
if (detectedProjects.length > 0) {
|
|
2400
2709
|
menuOptions.push({
|
|
2401
2710
|
value: "link",
|
|
2402
|
-
label: "Link other project knowledge",
|
|
2711
|
+
label: "\u{1F517} Link other project knowledge",
|
|
2403
2712
|
hint: `${detectedProjects.length} projects detected (global + sibling)`
|
|
2404
2713
|
});
|
|
2405
2714
|
}
|
|
2406
2715
|
if (currentStorageMode === "workspace" && hasLocalData) {
|
|
2407
2716
|
menuOptions.push({
|
|
2408
2717
|
value: "sync-global",
|
|
2409
|
-
label: "Sync to global storage",
|
|
2718
|
+
label: "\u2601\uFE0F Sync to global storage",
|
|
2410
2719
|
hint: "Share knowledge with other projects"
|
|
2411
2720
|
});
|
|
2412
2721
|
}
|
|
2413
|
-
menuOptions.push({ value: "update", label: "Update from package", hint: "Get latest prompts & templates" });
|
|
2414
|
-
menuOptions.push({ value: "exit", label: "Exit" });
|
|
2415
|
-
const action = await
|
|
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({
|
|
2416
2725
|
message: "This workspace is already configured. What would you like to do?",
|
|
2417
2726
|
options: menuOptions
|
|
2418
2727
|
});
|
|
2419
|
-
if (
|
|
2420
|
-
|
|
2728
|
+
if (isCancel7(action) || action === "exit") {
|
|
2729
|
+
outro6("Exited.");
|
|
2421
2730
|
process.exit(0);
|
|
2422
2731
|
}
|
|
2732
|
+
if (action === "mcp") {
|
|
2733
|
+
await runMCP();
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2423
2736
|
if (action === "link") {
|
|
2424
2737
|
await runLinkProjectsFlow(workspacePath, workspaceName);
|
|
2425
2738
|
return;
|