rrce-workflow 0.2.34 → 0.2.36
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 +674 -522
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -935,6 +935,10 @@ function parseMCPConfig(content) {
|
|
|
935
935
|
continue;
|
|
936
936
|
}
|
|
937
937
|
if (currentProject) {
|
|
938
|
+
const pathMatch = trimmed.match(/^path:\s*["']?([^"'\n]+)["']?/);
|
|
939
|
+
if (pathMatch) {
|
|
940
|
+
currentProject.path = pathMatch[1].trim();
|
|
941
|
+
}
|
|
938
942
|
const exposeMatch = trimmed.match(/^expose:\s*(true|false)/);
|
|
939
943
|
if (exposeMatch) {
|
|
940
944
|
currentProject.expose = exposeMatch[1] === "true";
|
|
@@ -981,7 +985,12 @@ projects:
|
|
|
981
985
|
} else {
|
|
982
986
|
for (const project of config.projects) {
|
|
983
987
|
content += ` - name: "${project.name}"
|
|
984
|
-
|
|
988
|
+
`;
|
|
989
|
+
if (project.path) {
|
|
990
|
+
content += ` path: "${project.path}"
|
|
991
|
+
`;
|
|
992
|
+
}
|
|
993
|
+
content += ` expose: ${project.expose}
|
|
985
994
|
permissions:
|
|
986
995
|
knowledge: ${project.permissions.knowledge}
|
|
987
996
|
tasks: ${project.permissions.tasks}
|
|
@@ -991,16 +1000,31 @@ projects:
|
|
|
991
1000
|
}
|
|
992
1001
|
return content;
|
|
993
1002
|
}
|
|
994
|
-
function setProjectConfig(config, name, expose, permissions) {
|
|
995
|
-
|
|
1003
|
+
function setProjectConfig(config, name, expose, permissions, projectPath) {
|
|
1004
|
+
let existing = config.projects.find((p) => {
|
|
1005
|
+
if (projectPath && p.path) {
|
|
1006
|
+
return p.path === projectPath;
|
|
1007
|
+
}
|
|
1008
|
+
if (!projectPath && !p.path) {
|
|
1009
|
+
return p.name === name;
|
|
1010
|
+
}
|
|
1011
|
+
if (projectPath && !p.path && p.name === name) {
|
|
1012
|
+
return true;
|
|
1013
|
+
}
|
|
1014
|
+
return false;
|
|
1015
|
+
});
|
|
996
1016
|
if (existing) {
|
|
997
1017
|
existing.expose = expose;
|
|
1018
|
+
if (projectPath && !existing.path) {
|
|
1019
|
+
existing.path = projectPath;
|
|
1020
|
+
}
|
|
998
1021
|
if (permissions) {
|
|
999
1022
|
existing.permissions = { ...existing.permissions, ...permissions };
|
|
1000
1023
|
}
|
|
1001
1024
|
} else {
|
|
1002
1025
|
config.projects.push({
|
|
1003
1026
|
name,
|
|
1027
|
+
path: projectPath,
|
|
1004
1028
|
expose,
|
|
1005
1029
|
permissions: permissions ? { ...DEFAULT_PERMISSIONS, ...permissions } : { ...DEFAULT_PERMISSIONS }
|
|
1006
1030
|
});
|
|
@@ -1011,15 +1035,25 @@ function removeProjectConfig(config, name) {
|
|
|
1011
1035
|
config.projects = config.projects.filter((p) => p.name !== name);
|
|
1012
1036
|
return config;
|
|
1013
1037
|
}
|
|
1014
|
-
function isProjectExposed(config, name) {
|
|
1015
|
-
const project = config.projects.find((p) =>
|
|
1038
|
+
function isProjectExposed(config, name, projectPath) {
|
|
1039
|
+
const project = config.projects.find((p) => {
|
|
1040
|
+
if (projectPath && p.path) return p.path === projectPath;
|
|
1041
|
+
if (!projectPath && !p.path) return p.name === name;
|
|
1042
|
+
if (projectPath && !p.path) return p.name === name;
|
|
1043
|
+
return false;
|
|
1044
|
+
});
|
|
1016
1045
|
if (project) {
|
|
1017
1046
|
return project.expose;
|
|
1018
1047
|
}
|
|
1019
1048
|
return config.defaults.includeNew;
|
|
1020
1049
|
}
|
|
1021
|
-
function getProjectPermissions(config, name) {
|
|
1022
|
-
const project = config.projects.find((p) =>
|
|
1050
|
+
function getProjectPermissions(config, name, projectPath) {
|
|
1051
|
+
const project = config.projects.find((p) => {
|
|
1052
|
+
if (projectPath && p.path) return p.path === projectPath;
|
|
1053
|
+
if (!projectPath && !p.path) return p.name === name;
|
|
1054
|
+
if (projectPath && !p.path) return p.name === name;
|
|
1055
|
+
return false;
|
|
1056
|
+
});
|
|
1023
1057
|
return project?.permissions ?? config.defaults.permissions;
|
|
1024
1058
|
}
|
|
1025
1059
|
var init_config = __esm({
|
|
@@ -1031,11 +1065,6 @@ var init_config = __esm({
|
|
|
1031
1065
|
});
|
|
1032
1066
|
|
|
1033
1067
|
// src/mcp/logger.ts
|
|
1034
|
-
var logger_exports = {};
|
|
1035
|
-
__export(logger_exports, {
|
|
1036
|
-
getLogFilePath: () => getLogFilePath,
|
|
1037
|
-
logger: () => logger
|
|
1038
|
-
});
|
|
1039
1068
|
import * as fs8 from "fs";
|
|
1040
1069
|
import * as path9 from "path";
|
|
1041
1070
|
function getLogFilePath() {
|
|
@@ -1105,7 +1134,7 @@ import * as path10 from "path";
|
|
|
1105
1134
|
function getExposedProjects() {
|
|
1106
1135
|
const config = loadMCPConfig();
|
|
1107
1136
|
const allProjects = scanForProjects();
|
|
1108
|
-
return allProjects.filter((project) => isProjectExposed(config, project.name));
|
|
1137
|
+
return allProjects.filter((project) => isProjectExposed(config, project.name, project.dataPath));
|
|
1109
1138
|
}
|
|
1110
1139
|
function detectActiveProject() {
|
|
1111
1140
|
const exposed = getExposedProjects();
|
|
@@ -1116,16 +1145,16 @@ function detectActiveProject() {
|
|
|
1116
1145
|
}
|
|
1117
1146
|
function getProjectContext(projectName) {
|
|
1118
1147
|
const config = loadMCPConfig();
|
|
1119
|
-
|
|
1148
|
+
const projects = scanForProjects();
|
|
1149
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.dataPath));
|
|
1150
|
+
if (!project) {
|
|
1120
1151
|
return null;
|
|
1121
1152
|
}
|
|
1122
|
-
const permissions = getProjectPermissions(config, projectName);
|
|
1153
|
+
const permissions = getProjectPermissions(config, projectName, project.dataPath);
|
|
1123
1154
|
if (!permissions.knowledge) {
|
|
1124
1155
|
return null;
|
|
1125
1156
|
}
|
|
1126
|
-
|
|
1127
|
-
const project = projects.find((p) => p.name === projectName);
|
|
1128
|
-
if (!project?.knowledgePath) {
|
|
1157
|
+
if (!project.knowledgePath) {
|
|
1129
1158
|
return null;
|
|
1130
1159
|
}
|
|
1131
1160
|
const contextPath = path10.join(project.knowledgePath, "project-context.md");
|
|
@@ -1136,16 +1165,16 @@ function getProjectContext(projectName) {
|
|
|
1136
1165
|
}
|
|
1137
1166
|
function getProjectTasks(projectName) {
|
|
1138
1167
|
const config = loadMCPConfig();
|
|
1139
|
-
|
|
1168
|
+
const projects = scanForProjects();
|
|
1169
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.dataPath));
|
|
1170
|
+
if (!project) {
|
|
1140
1171
|
return [];
|
|
1141
1172
|
}
|
|
1142
|
-
const permissions = getProjectPermissions(config, projectName);
|
|
1173
|
+
const permissions = getProjectPermissions(config, projectName, project.dataPath);
|
|
1143
1174
|
if (!permissions.tasks) {
|
|
1144
1175
|
return [];
|
|
1145
1176
|
}
|
|
1146
|
-
|
|
1147
|
-
const project = projects.find((p) => p.name === projectName);
|
|
1148
|
-
if (!project?.tasksPath || !fs9.existsSync(project.tasksPath)) {
|
|
1177
|
+
if (!project.tasksPath || !fs9.existsSync(project.tasksPath)) {
|
|
1149
1178
|
return [];
|
|
1150
1179
|
}
|
|
1151
1180
|
const tasks = [];
|
|
@@ -1172,7 +1201,7 @@ function searchKnowledge(query) {
|
|
|
1172
1201
|
const results = [];
|
|
1173
1202
|
const queryLower = query.toLowerCase();
|
|
1174
1203
|
for (const project of projects) {
|
|
1175
|
-
const permissions = getProjectPermissions(config, project.name);
|
|
1204
|
+
const permissions = getProjectPermissions(config, project.name, project.dataPath);
|
|
1176
1205
|
if (!permissions.knowledge || !project.knowledgePath) continue;
|
|
1177
1206
|
try {
|
|
1178
1207
|
const files = fs9.readdirSync(project.knowledgePath);
|
|
@@ -1209,100 +1238,12 @@ var init_resources = __esm({
|
|
|
1209
1238
|
}
|
|
1210
1239
|
});
|
|
1211
1240
|
|
|
1212
|
-
// src/mcp/
|
|
1213
|
-
|
|
1214
|
-
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
1215
|
-
return prompts.map((p) => {
|
|
1216
|
-
const args = [];
|
|
1217
|
-
if (p.frontmatter["required-args"]) {
|
|
1218
|
-
args.push(...p.frontmatter["required-args"].map((a) => ({
|
|
1219
|
-
name: a.name,
|
|
1220
|
-
description: a.prompt || a.name,
|
|
1221
|
-
required: true
|
|
1222
|
-
})));
|
|
1223
|
-
}
|
|
1224
|
-
if (p.frontmatter["optional-args"]) {
|
|
1225
|
-
args.push(...p.frontmatter["optional-args"].map((a) => ({
|
|
1226
|
-
name: a.name,
|
|
1227
|
-
description: a.prompt || a.name,
|
|
1228
|
-
required: false
|
|
1229
|
-
})));
|
|
1230
|
-
}
|
|
1231
|
-
return {
|
|
1232
|
-
name: p.frontmatter.name,
|
|
1233
|
-
description: p.frontmatter.description,
|
|
1234
|
-
arguments: args,
|
|
1235
|
-
content: p.content
|
|
1236
|
-
};
|
|
1237
|
-
});
|
|
1238
|
-
}
|
|
1239
|
-
function getPromptDef(name) {
|
|
1240
|
-
return getAllPrompts().find((p) => p.name === name);
|
|
1241
|
-
}
|
|
1242
|
-
function renderPrompt(content, args) {
|
|
1243
|
-
let rendered = content;
|
|
1244
|
-
for (const [key, val] of Object.entries(args)) {
|
|
1245
|
-
rendered = rendered.replace(new RegExp(`{{${key}}}`, "g"), val);
|
|
1246
|
-
}
|
|
1247
|
-
return rendered;
|
|
1248
|
-
}
|
|
1249
|
-
var init_prompts2 = __esm({
|
|
1250
|
-
"src/mcp/prompts.ts"() {
|
|
1251
|
-
"use strict";
|
|
1252
|
-
init_prompts();
|
|
1253
|
-
}
|
|
1254
|
-
});
|
|
1255
|
-
|
|
1256
|
-
// src/mcp/server.ts
|
|
1257
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
1258
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1241
|
+
// src/mcp/handlers/resources.ts
|
|
1242
|
+
import "@modelcontextprotocol/sdk/server/index.js";
|
|
1259
1243
|
import {
|
|
1260
|
-
CallToolRequestSchema,
|
|
1261
1244
|
ListResourcesRequestSchema,
|
|
1262
|
-
|
|
1263
|
-
ReadResourceRequestSchema,
|
|
1264
|
-
ListPromptsRequestSchema,
|
|
1265
|
-
GetPromptRequestSchema
|
|
1245
|
+
ReadResourceRequestSchema
|
|
1266
1246
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
1267
|
-
async function startMCPServer(options = {}) {
|
|
1268
|
-
try {
|
|
1269
|
-
logger.info("Starting MCP Server...");
|
|
1270
|
-
process.on("uncaughtException", (error) => {
|
|
1271
|
-
logger.error("Uncaught Exception", error);
|
|
1272
|
-
console.error("Uncaught Exception:", error);
|
|
1273
|
-
});
|
|
1274
|
-
process.on("unhandledRejection", (reason) => {
|
|
1275
|
-
logger.error("Unhandled Rejection", reason);
|
|
1276
|
-
console.error("Unhandled Rejection:", reason);
|
|
1277
|
-
});
|
|
1278
|
-
const config = loadMCPConfig();
|
|
1279
|
-
mcpServer = new Server(
|
|
1280
|
-
{ name: "rrce-mcp-hub", version: "1.0.0" },
|
|
1281
|
-
{ capabilities: { resources: {}, tools: {}, prompts: {} } }
|
|
1282
|
-
);
|
|
1283
|
-
mcpServer.onerror = (error) => {
|
|
1284
|
-
logger.error("MCP Server Error", error);
|
|
1285
|
-
};
|
|
1286
|
-
registerResourceHandlers(mcpServer);
|
|
1287
|
-
registerToolHandlers(mcpServer);
|
|
1288
|
-
registerPromptHandlers(mcpServer);
|
|
1289
|
-
if (!options.interactive) {
|
|
1290
|
-
const transport = new StdioServerTransport();
|
|
1291
|
-
await mcpServer.connect(transport);
|
|
1292
|
-
} else {
|
|
1293
|
-
logger.info("Running in interactive mode (Stdio transport detached)");
|
|
1294
|
-
}
|
|
1295
|
-
serverState = { running: true, port: config.server.port, pid: process.pid };
|
|
1296
|
-
const exposed = getExposedProjects().map((p) => p.name).join(", ");
|
|
1297
|
-
logger.info(`RRCE MCP Hub started (pid: ${process.pid})`, { exposedProjects: exposed });
|
|
1298
|
-
console.error(`RRCE MCP Hub started (pid: ${process.pid})`);
|
|
1299
|
-
console.error(`Exposed projects: ${exposed}`);
|
|
1300
|
-
return { port: config.server.port, pid: process.pid };
|
|
1301
|
-
} catch (error) {
|
|
1302
|
-
logger.error("Failed to start MCP server", error);
|
|
1303
|
-
throw error;
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
1247
|
function registerResourceHandlers(server) {
|
|
1307
1248
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
1308
1249
|
logger.debug("Listing resources");
|
|
@@ -1316,7 +1257,7 @@ function registerResourceHandlers(server) {
|
|
|
1316
1257
|
});
|
|
1317
1258
|
for (const project of projects) {
|
|
1318
1259
|
const config = loadMCPConfig();
|
|
1319
|
-
const permissions = getProjectPermissions(config, project.name);
|
|
1260
|
+
const permissions = getProjectPermissions(config, project.name, project.dataPath);
|
|
1320
1261
|
if (permissions.knowledge) {
|
|
1321
1262
|
resources.push({
|
|
1322
1263
|
uri: `rrce://projects/${project.name}/context`,
|
|
@@ -1371,6 +1312,65 @@ function registerResourceHandlers(server) {
|
|
|
1371
1312
|
}
|
|
1372
1313
|
});
|
|
1373
1314
|
}
|
|
1315
|
+
var init_resources2 = __esm({
|
|
1316
|
+
"src/mcp/handlers/resources.ts"() {
|
|
1317
|
+
"use strict";
|
|
1318
|
+
init_logger();
|
|
1319
|
+
init_config();
|
|
1320
|
+
init_resources();
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
|
|
1324
|
+
// src/mcp/prompts.ts
|
|
1325
|
+
function getAllPrompts() {
|
|
1326
|
+
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
1327
|
+
return prompts.map((p) => {
|
|
1328
|
+
const args = [];
|
|
1329
|
+
if (p.frontmatter["required-args"]) {
|
|
1330
|
+
args.push(...p.frontmatter["required-args"].map((a) => ({
|
|
1331
|
+
name: a.name,
|
|
1332
|
+
description: a.prompt || a.name,
|
|
1333
|
+
required: true
|
|
1334
|
+
})));
|
|
1335
|
+
}
|
|
1336
|
+
if (p.frontmatter["optional-args"]) {
|
|
1337
|
+
args.push(...p.frontmatter["optional-args"].map((a) => ({
|
|
1338
|
+
name: a.name,
|
|
1339
|
+
description: a.prompt || a.name,
|
|
1340
|
+
required: false
|
|
1341
|
+
})));
|
|
1342
|
+
}
|
|
1343
|
+
return {
|
|
1344
|
+
name: p.frontmatter.name,
|
|
1345
|
+
description: p.frontmatter.description,
|
|
1346
|
+
arguments: args,
|
|
1347
|
+
content: p.content
|
|
1348
|
+
};
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
function getPromptDef(name) {
|
|
1352
|
+
return getAllPrompts().find((p) => p.name === name);
|
|
1353
|
+
}
|
|
1354
|
+
function renderPrompt(content, args) {
|
|
1355
|
+
let rendered = content;
|
|
1356
|
+
for (const [key, val] of Object.entries(args)) {
|
|
1357
|
+
rendered = rendered.replace(new RegExp(`{{${key}}}`, "g"), val);
|
|
1358
|
+
}
|
|
1359
|
+
return rendered;
|
|
1360
|
+
}
|
|
1361
|
+
var init_prompts2 = __esm({
|
|
1362
|
+
"src/mcp/prompts.ts"() {
|
|
1363
|
+
"use strict";
|
|
1364
|
+
init_prompts();
|
|
1365
|
+
}
|
|
1366
|
+
});
|
|
1367
|
+
|
|
1368
|
+
// src/mcp/handlers/tools.ts
|
|
1369
|
+
import "@modelcontextprotocol/sdk/server/index.js";
|
|
1370
|
+
import {
|
|
1371
|
+
ListToolsRequestSchema,
|
|
1372
|
+
CallToolRequestSchema
|
|
1373
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
1374
1374
|
function registerToolHandlers(server) {
|
|
1375
1375
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
1376
1376
|
const tools = [
|
|
@@ -1523,6 +1523,21 @@ To fix this:
|
|
|
1523
1523
|
}
|
|
1524
1524
|
});
|
|
1525
1525
|
}
|
|
1526
|
+
var init_tools = __esm({
|
|
1527
|
+
"src/mcp/handlers/tools.ts"() {
|
|
1528
|
+
"use strict";
|
|
1529
|
+
init_logger();
|
|
1530
|
+
init_resources();
|
|
1531
|
+
init_prompts2();
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1534
|
+
|
|
1535
|
+
// src/mcp/handlers/prompts.ts
|
|
1536
|
+
import "@modelcontextprotocol/sdk/server/index.js";
|
|
1537
|
+
import {
|
|
1538
|
+
ListPromptsRequestSchema,
|
|
1539
|
+
GetPromptRequestSchema
|
|
1540
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
1526
1541
|
function registerPromptHandlers(server) {
|
|
1527
1542
|
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
1528
1543
|
logger.debug("Listing prompts");
|
|
@@ -1604,6 +1619,65 @@ Note: If the user's request refers to a project not listed here, ask them to exp
|
|
|
1604
1619
|
}
|
|
1605
1620
|
});
|
|
1606
1621
|
}
|
|
1622
|
+
var init_prompts3 = __esm({
|
|
1623
|
+
"src/mcp/handlers/prompts.ts"() {
|
|
1624
|
+
"use strict";
|
|
1625
|
+
init_logger();
|
|
1626
|
+
init_resources();
|
|
1627
|
+
init_prompts2();
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1630
|
+
|
|
1631
|
+
// src/mcp/server.ts
|
|
1632
|
+
var server_exports = {};
|
|
1633
|
+
__export(server_exports, {
|
|
1634
|
+
getMCPServerStatus: () => getMCPServerStatus,
|
|
1635
|
+
startMCPServer: () => startMCPServer,
|
|
1636
|
+
stopMCPServer: () => stopMCPServer
|
|
1637
|
+
});
|
|
1638
|
+
import { Server as Server4 } from "@modelcontextprotocol/sdk/server/index.js";
|
|
1639
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1640
|
+
async function startMCPServer(options = {}) {
|
|
1641
|
+
try {
|
|
1642
|
+
logger.info("Starting MCP Server...");
|
|
1643
|
+
process.on("uncaughtException", (error) => {
|
|
1644
|
+
logger.error("Uncaught Exception", error);
|
|
1645
|
+
console.error("Uncaught Exception:", error);
|
|
1646
|
+
});
|
|
1647
|
+
process.on("unhandledRejection", (reason) => {
|
|
1648
|
+
logger.error("Unhandled Rejection", reason);
|
|
1649
|
+
console.error("Unhandled Rejection:", reason);
|
|
1650
|
+
});
|
|
1651
|
+
const config = loadMCPConfig();
|
|
1652
|
+
mcpServer = new Server4(
|
|
1653
|
+
{ name: "rrce-mcp-hub", version: "1.0.0" },
|
|
1654
|
+
{ capabilities: { resources: {}, tools: {}, prompts: {} } }
|
|
1655
|
+
);
|
|
1656
|
+
mcpServer.onerror = (error) => {
|
|
1657
|
+
logger.error("MCP Server Error", error);
|
|
1658
|
+
};
|
|
1659
|
+
registerResourceHandlers(mcpServer);
|
|
1660
|
+
registerToolHandlers(mcpServer);
|
|
1661
|
+
registerPromptHandlers(mcpServer);
|
|
1662
|
+
if (!options.interactive) {
|
|
1663
|
+
const transport = new StdioServerTransport();
|
|
1664
|
+
await mcpServer.connect(transport);
|
|
1665
|
+
} else {
|
|
1666
|
+
logger.info("Running in interactive mode (Stdio transport detached)");
|
|
1667
|
+
}
|
|
1668
|
+
serverState = { running: true, port: config.server.port, pid: process.pid };
|
|
1669
|
+
const exposed = getExposedProjects().map((p) => p.name).join(", ");
|
|
1670
|
+
logger.info(`RRCE MCP Hub started (pid: ${process.pid})`, { exposedProjects: exposed });
|
|
1671
|
+
if (!options.interactive) {
|
|
1672
|
+
console.error(`RRCE MCP Hub started (pid: ${process.pid})`);
|
|
1673
|
+
console.error(`Exposed projects: ${exposed}`);
|
|
1674
|
+
}
|
|
1675
|
+
return { port: config.server.port, pid: process.pid };
|
|
1676
|
+
} catch (error) {
|
|
1677
|
+
logger.error("Failed to start MCP server", error);
|
|
1678
|
+
throw error;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1607
1681
|
function stopMCPServer() {
|
|
1608
1682
|
if (mcpServer) {
|
|
1609
1683
|
logger.info("Stopping MCP Server...");
|
|
@@ -1612,7 +1686,6 @@ function stopMCPServer() {
|
|
|
1612
1686
|
}
|
|
1613
1687
|
serverState = { running: false };
|
|
1614
1688
|
logger.info("RRCE MCP Hub stopped");
|
|
1615
|
-
console.error("RRCE MCP Hub stopped");
|
|
1616
1689
|
}
|
|
1617
1690
|
function getMCPServerStatus() {
|
|
1618
1691
|
return { ...serverState };
|
|
@@ -1624,8 +1697,9 @@ var init_server = __esm({
|
|
|
1624
1697
|
init_logger();
|
|
1625
1698
|
init_config();
|
|
1626
1699
|
init_resources();
|
|
1627
|
-
|
|
1628
|
-
|
|
1700
|
+
init_resources2();
|
|
1701
|
+
init_tools();
|
|
1702
|
+
init_prompts3();
|
|
1629
1703
|
serverState = { running: false };
|
|
1630
1704
|
mcpServer = null;
|
|
1631
1705
|
}
|
|
@@ -1819,34 +1893,196 @@ var init_install = __esm({
|
|
|
1819
1893
|
}
|
|
1820
1894
|
});
|
|
1821
1895
|
|
|
1822
|
-
// src/mcp/
|
|
1823
|
-
import "
|
|
1824
|
-
import
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1896
|
+
// src/mcp/commands/configure.ts
|
|
1897
|
+
import { spinner, note as note2, multiselect, isCancel as isCancel2 } from "@clack/prompts";
|
|
1898
|
+
import pc3 from "picocolors";
|
|
1899
|
+
async function handleConfigure() {
|
|
1900
|
+
const s = spinner();
|
|
1901
|
+
s.start("Scanning for projects...");
|
|
1902
|
+
const config = loadMCPConfig();
|
|
1903
|
+
const projects = scanForProjects();
|
|
1904
|
+
logger.info("Configure: Loaded config", { projects: config.projects, defaultMode: config.defaults.includeNew });
|
|
1905
|
+
s.stop("Projects found");
|
|
1906
|
+
if (projects.length === 0) {
|
|
1907
|
+
note2('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
|
|
1908
|
+
return;
|
|
1831
1909
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1910
|
+
const options = projects.map((project) => {
|
|
1911
|
+
const projectConfig = config.projects.find(
|
|
1912
|
+
(p) => p.path && p.path === project.dataPath || !p.path && p.name === project.name
|
|
1913
|
+
);
|
|
1914
|
+
const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
|
|
1915
|
+
return {
|
|
1916
|
+
value: project.dataPath,
|
|
1917
|
+
// Use precise data path as unique identifier
|
|
1918
|
+
label: `${project.name} ${pc3.dim(`(${project.source})`)}`,
|
|
1919
|
+
hint: project.dataPath
|
|
1920
|
+
};
|
|
1921
|
+
});
|
|
1922
|
+
const currentlyExposed = projects.filter((p) => {
|
|
1923
|
+
const cfg = config.projects.find(
|
|
1924
|
+
(c) => c.path && c.path === p.dataPath || !c.path && c.name === p.name
|
|
1925
|
+
);
|
|
1926
|
+
return cfg?.expose ?? config.defaults.includeNew;
|
|
1927
|
+
}).map((p) => p.dataPath);
|
|
1928
|
+
const selected = await multiselect({
|
|
1929
|
+
message: "Select projects to expose via MCP:",
|
|
1930
|
+
options,
|
|
1931
|
+
initialValues: currentlyExposed,
|
|
1932
|
+
required: false
|
|
1933
|
+
});
|
|
1934
|
+
if (isCancel2(selected)) {
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
const selectedPaths = selected;
|
|
1938
|
+
logger.info("Configure: User selected projects by path", selectedPaths);
|
|
1939
|
+
for (const project of projects) {
|
|
1940
|
+
const shouldExpose = selectedPaths.includes(project.dataPath);
|
|
1941
|
+
setProjectConfig(config, project.name, shouldExpose, void 0, project.dataPath);
|
|
1942
|
+
}
|
|
1943
|
+
saveMCPConfig(config);
|
|
1944
|
+
logger.info("Configure: Config saved", config);
|
|
1945
|
+
const exposedCount = selectedPaths.length;
|
|
1946
|
+
note2(
|
|
1947
|
+
`${pc3.green("\u2713")} Configuration saved!
|
|
1948
|
+
|
|
1949
|
+
Exposed projects: ${exposedCount}
|
|
1950
|
+
Hidden projects: ${projects.length - exposedCount}`,
|
|
1951
|
+
"Configuration Updated"
|
|
1952
|
+
);
|
|
1953
|
+
}
|
|
1954
|
+
async function handleConfigureGlobalPath() {
|
|
1955
|
+
const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
|
|
1956
|
+
const fs17 = await import("fs");
|
|
1957
|
+
const path16 = await import("path");
|
|
1958
|
+
note2(
|
|
1959
|
+
`MCP Hub requires a ${pc3.bold("global storage path")} to store its configuration
|
|
1960
|
+
and coordinate across projects.
|
|
1961
|
+
|
|
1962
|
+
Your current setup uses ${pc3.cyan("workspace")} mode, which stores data
|
|
1963
|
+
locally in each project. MCP needs a central location.`,
|
|
1964
|
+
"Global Path Required"
|
|
1965
|
+
);
|
|
1966
|
+
const resolvedPath = await resolveGlobalPath2();
|
|
1967
|
+
if (!resolvedPath) {
|
|
1968
|
+
return false;
|
|
1969
|
+
}
|
|
1970
|
+
try {
|
|
1971
|
+
if (!fs17.existsSync(resolvedPath)) {
|
|
1972
|
+
fs17.mkdirSync(resolvedPath, { recursive: true });
|
|
1973
|
+
}
|
|
1974
|
+
const config = loadMCPConfig();
|
|
1975
|
+
saveMCPConfig(config);
|
|
1976
|
+
note2(
|
|
1977
|
+
`${pc3.green("\u2713")} Global path configured: ${pc3.cyan(resolvedPath)}
|
|
1978
|
+
|
|
1979
|
+
MCP config will be stored at:
|
|
1980
|
+
${path16.join(resolvedPath, "mcp.yaml")}`,
|
|
1981
|
+
"Configuration Saved"
|
|
1982
|
+
);
|
|
1983
|
+
return true;
|
|
1984
|
+
} catch (error) {
|
|
1985
|
+
note2(
|
|
1986
|
+
`${pc3.red("\u2717")} Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
|
|
1987
|
+
"Error"
|
|
1988
|
+
);
|
|
1989
|
+
return false;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
var init_configure = __esm({
|
|
1993
|
+
"src/mcp/commands/configure.ts"() {
|
|
1994
|
+
"use strict";
|
|
1995
|
+
init_config();
|
|
1996
|
+
init_detection();
|
|
1997
|
+
init_logger();
|
|
1998
|
+
}
|
|
1999
|
+
});
|
|
2000
|
+
|
|
2001
|
+
// src/mcp/commands/install-wizard.ts
|
|
2002
|
+
import { multiselect as multiselect2, note as note3, isCancel as isCancel3 } from "@clack/prompts";
|
|
2003
|
+
import pc4 from "picocolors";
|
|
2004
|
+
async function runInstallWizard(workspacePath) {
|
|
2005
|
+
const status = checkInstallStatus(workspacePath);
|
|
2006
|
+
const options = [
|
|
2007
|
+
{
|
|
2008
|
+
value: "antigravity",
|
|
2009
|
+
label: "Antigravity IDE",
|
|
2010
|
+
hint: status.antigravity ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
|
|
2011
|
+
},
|
|
2012
|
+
{
|
|
2013
|
+
value: "vscode-global",
|
|
2014
|
+
label: "VSCode (Global Settings)",
|
|
2015
|
+
hint: status.vscodeGlobal ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
|
|
2016
|
+
},
|
|
2017
|
+
{
|
|
2018
|
+
value: "vscode-workspace",
|
|
2019
|
+
label: "VSCode (Workspace Config)",
|
|
2020
|
+
hint: status.vscodeWorkspace ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
|
|
2021
|
+
},
|
|
2022
|
+
{
|
|
2023
|
+
value: "claude",
|
|
2024
|
+
label: "Claude Desktop",
|
|
2025
|
+
hint: status.claude ? pc4.green("\u2713 Installed") : pc4.dim("Not installed")
|
|
2026
|
+
}
|
|
2027
|
+
];
|
|
2028
|
+
const selected = await multiselect2({
|
|
2029
|
+
message: "Select where to install RRCE MCP Server:",
|
|
2030
|
+
options,
|
|
2031
|
+
initialValues: [
|
|
2032
|
+
...status.antigravity ? ["antigravity"] : [],
|
|
2033
|
+
...status.vscodeGlobal ? ["vscode-global"] : [],
|
|
2034
|
+
...status.vscodeWorkspace ? ["vscode-workspace"] : [],
|
|
2035
|
+
...status.claude ? ["claude"] : []
|
|
2036
|
+
],
|
|
2037
|
+
required: false
|
|
2038
|
+
});
|
|
2039
|
+
if (isCancel3(selected)) return;
|
|
2040
|
+
const targets = selected;
|
|
2041
|
+
const results = [];
|
|
2042
|
+
for (const target of targets) {
|
|
2043
|
+
const success = installToConfig(target, workspacePath);
|
|
2044
|
+
const label = getTargetLabel(target);
|
|
2045
|
+
results.push(`${label}: ${success ? pc4.green("\u2713 Success") : pc4.red("\u2717 Failed")}`);
|
|
2046
|
+
}
|
|
2047
|
+
if (results.length > 0) {
|
|
2048
|
+
note3(results.join("\n"), "Installation Results");
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
var init_install_wizard = __esm({
|
|
2052
|
+
"src/mcp/commands/install-wizard.ts"() {
|
|
2053
|
+
"use strict";
|
|
2054
|
+
init_install();
|
|
2055
|
+
}
|
|
2056
|
+
});
|
|
2057
|
+
|
|
2058
|
+
// src/mcp/ui/Header.tsx
|
|
2059
|
+
import "react";
|
|
2060
|
+
import { Box, Text } from "ink";
|
|
2061
|
+
import { jsx } from "react/jsx-runtime";
|
|
2062
|
+
var Header;
|
|
2063
|
+
var init_Header = __esm({
|
|
2064
|
+
"src/mcp/ui/Header.tsx"() {
|
|
2065
|
+
"use strict";
|
|
2066
|
+
Header = () => /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingBottom: 1, children: /* @__PURE__ */ jsx(Box, { borderStyle: "double", borderColor: "cyan", paddingX: 2, justifyContent: "center", children: /* @__PURE__ */ jsx(Text, { bold: true, color: "white", children: " RRCE MCP Hub " }) }) });
|
|
2067
|
+
}
|
|
2068
|
+
});
|
|
2069
|
+
|
|
2070
|
+
// src/mcp/ui/StatusBoard.tsx
|
|
2071
|
+
import "react";
|
|
2072
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
2073
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
2074
|
+
var StatusBoard;
|
|
2075
|
+
var init_StatusBoard = __esm({
|
|
2076
|
+
"src/mcp/ui/StatusBoard.tsx"() {
|
|
2077
|
+
"use strict";
|
|
2078
|
+
StatusBoard = ({ exposedLabel, port, pid }) => {
|
|
2079
|
+
return /* @__PURE__ */ jsx2(Box2, { borderStyle: "single", borderColor: "cyan", paddingX: 1, children: /* @__PURE__ */ jsxs(Text2, { children: [
|
|
2080
|
+
"\u{1F4CB} ",
|
|
2081
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: exposedLabel }),
|
|
2082
|
+
" ",
|
|
2083
|
+
"\u2502",
|
|
2084
|
+
" Port: ",
|
|
2085
|
+
/* @__PURE__ */ jsx2(Text2, { color: "green", children: port }),
|
|
1850
2086
|
" ",
|
|
1851
2087
|
"\u2502",
|
|
1852
2088
|
" PID: ",
|
|
@@ -2009,12 +2245,15 @@ var init_App = __esm({
|
|
|
2009
2245
|
if (input === "q" || key.ctrl && input === "c") {
|
|
2010
2246
|
stopMCPServer();
|
|
2011
2247
|
onExit();
|
|
2248
|
+
exit();
|
|
2012
2249
|
}
|
|
2013
2250
|
if (input === "p") {
|
|
2014
2251
|
onConfigure();
|
|
2252
|
+
exit();
|
|
2015
2253
|
}
|
|
2016
2254
|
if (input === "i") {
|
|
2017
2255
|
onInstall();
|
|
2256
|
+
exit();
|
|
2018
2257
|
}
|
|
2019
2258
|
if (input === "c") {
|
|
2020
2259
|
setLogs([]);
|
|
@@ -2039,13 +2278,206 @@ var init_App = __esm({
|
|
|
2039
2278
|
}
|
|
2040
2279
|
});
|
|
2041
2280
|
|
|
2281
|
+
// src/mcp/commands/start.ts
|
|
2282
|
+
import { confirm, isCancel as isCancel4, text } from "@clack/prompts";
|
|
2283
|
+
async function handleStartServer() {
|
|
2284
|
+
const React7 = await import("react");
|
|
2285
|
+
const { render } = await import("ink");
|
|
2286
|
+
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
2287
|
+
const config = loadMCPConfig();
|
|
2288
|
+
const projects = scanForProjects();
|
|
2289
|
+
const exposedProjects = projects.filter((p) => {
|
|
2290
|
+
const cfg = config.projects.find(
|
|
2291
|
+
(c) => c.path && c.path === p.dataPath || !c.path && c.name === p.name
|
|
2292
|
+
);
|
|
2293
|
+
return cfg?.expose ?? config.defaults.includeNew;
|
|
2294
|
+
});
|
|
2295
|
+
if (exposedProjects.length === 0) {
|
|
2296
|
+
const shouldConfig = await confirm({
|
|
2297
|
+
message: "No projects are currently exposed. Configure now?",
|
|
2298
|
+
initialValue: true
|
|
2299
|
+
});
|
|
2300
|
+
if (shouldConfig && !isCancel4(shouldConfig)) {
|
|
2301
|
+
await handleConfigure();
|
|
2302
|
+
return handleStartServer();
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
const status = getMCPServerStatus();
|
|
2306
|
+
let initialPort = config.server.port;
|
|
2307
|
+
if (!status.running) {
|
|
2308
|
+
const portInput = await text({
|
|
2309
|
+
message: "Select port for MCP Server",
|
|
2310
|
+
initialValue: config.server.port.toString(),
|
|
2311
|
+
placeholder: "3200",
|
|
2312
|
+
validate(value) {
|
|
2313
|
+
if (isNaN(Number(value))) return "Port must be a number";
|
|
2314
|
+
}
|
|
2315
|
+
});
|
|
2316
|
+
if (isCancel4(portInput)) return;
|
|
2317
|
+
const newPort = parseInt(portInput, 10);
|
|
2318
|
+
if (newPort !== config.server.port) {
|
|
2319
|
+
config.server.port = newPort;
|
|
2320
|
+
saveMCPConfig(config);
|
|
2321
|
+
initialPort = newPort;
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
console.clear();
|
|
2325
|
+
let keepRunning = true;
|
|
2326
|
+
while (keepRunning) {
|
|
2327
|
+
let nextAction = "exit";
|
|
2328
|
+
process.stdin.resume();
|
|
2329
|
+
const app = render(React7.createElement(App2, {
|
|
2330
|
+
initialPort,
|
|
2331
|
+
onExit: () => {
|
|
2332
|
+
nextAction = "exit";
|
|
2333
|
+
},
|
|
2334
|
+
onConfigure: () => {
|
|
2335
|
+
nextAction = "configure";
|
|
2336
|
+
},
|
|
2337
|
+
onInstall: () => {
|
|
2338
|
+
nextAction = "install";
|
|
2339
|
+
}
|
|
2340
|
+
}), {
|
|
2341
|
+
exitOnCtrlC: false
|
|
2342
|
+
// We handle this in App
|
|
2343
|
+
});
|
|
2344
|
+
await app.waitUntilExit();
|
|
2345
|
+
if (nextAction === "exit") {
|
|
2346
|
+
keepRunning = false;
|
|
2347
|
+
} else if (nextAction === "configure") {
|
|
2348
|
+
console.clear();
|
|
2349
|
+
await handleConfigure();
|
|
2350
|
+
} else if (nextAction === "install") {
|
|
2351
|
+
console.clear();
|
|
2352
|
+
const workspacePath = detectWorkspaceRoot();
|
|
2353
|
+
await runInstallWizard(workspacePath);
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
var init_start = __esm({
|
|
2358
|
+
"src/mcp/commands/start.ts"() {
|
|
2359
|
+
"use strict";
|
|
2360
|
+
init_config();
|
|
2361
|
+
init_detection();
|
|
2362
|
+
init_server();
|
|
2363
|
+
init_paths();
|
|
2364
|
+
init_configure();
|
|
2365
|
+
init_install_wizard();
|
|
2366
|
+
}
|
|
2367
|
+
});
|
|
2368
|
+
|
|
2369
|
+
// src/mcp/commands/status.ts
|
|
2370
|
+
import { spinner as spinner2, note as note4 } from "@clack/prompts";
|
|
2371
|
+
import pc5 from "picocolors";
|
|
2372
|
+
async function handleShowStatus() {
|
|
2373
|
+
const s = spinner2();
|
|
2374
|
+
s.start("Loading projects...");
|
|
2375
|
+
const config = loadMCPConfig();
|
|
2376
|
+
const projects = scanForProjects();
|
|
2377
|
+
const workspacePath = detectWorkspaceRoot();
|
|
2378
|
+
const installStatus = checkInstallStatus(workspacePath);
|
|
2379
|
+
s.stop("Projects loaded");
|
|
2380
|
+
if (projects.length === 0) {
|
|
2381
|
+
note4('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
|
|
2382
|
+
return;
|
|
2383
|
+
}
|
|
2384
|
+
const lines = [
|
|
2385
|
+
`${pc5.bold("Installation Status")}`,
|
|
2386
|
+
"",
|
|
2387
|
+
` Antigravity: ${installStatus.antigravity ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
|
|
2388
|
+
` VSCode (Global): ${installStatus.vscodeGlobal ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
|
|
2389
|
+
` VSCode (Workspace): ${installStatus.vscodeWorkspace ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
|
|
2390
|
+
` Claude Desktop: ${installStatus.claude ? pc5.green("\u2713 Installed") : pc5.dim("Not installed")}`,
|
|
2391
|
+
"",
|
|
2392
|
+
`${pc5.bold("Project Status")}`,
|
|
2393
|
+
""
|
|
2394
|
+
];
|
|
2395
|
+
for (const project of projects) {
|
|
2396
|
+
const projectConfig = config.projects.find((p) => p.name === project.name);
|
|
2397
|
+
const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
|
|
2398
|
+
const status = isExposed ? pc5.green("\u2713 exposed") : pc5.dim("\u25CB hidden");
|
|
2399
|
+
const source = pc5.dim(`(${project.source})`);
|
|
2400
|
+
lines.push(` ${status} ${project.name} ${source}`);
|
|
2401
|
+
}
|
|
2402
|
+
lines.push("");
|
|
2403
|
+
lines.push(pc5.dim(`Config: ${getMCPConfigPath()}`));
|
|
2404
|
+
const serverStatus = getMCPServerStatus();
|
|
2405
|
+
if (serverStatus.running) {
|
|
2406
|
+
lines.push(pc5.green(`Server: running on port ${serverStatus.port}`));
|
|
2407
|
+
} else {
|
|
2408
|
+
lines.push(pc5.dim("Server: not running"));
|
|
2409
|
+
}
|
|
2410
|
+
note4(lines.join("\n"), "MCP Hub Status");
|
|
2411
|
+
}
|
|
2412
|
+
var init_status = __esm({
|
|
2413
|
+
"src/mcp/commands/status.ts"() {
|
|
2414
|
+
"use strict";
|
|
2415
|
+
init_config();
|
|
2416
|
+
init_detection();
|
|
2417
|
+
init_paths();
|
|
2418
|
+
init_server();
|
|
2419
|
+
init_install();
|
|
2420
|
+
}
|
|
2421
|
+
});
|
|
2422
|
+
|
|
2423
|
+
// src/mcp/commands/help.ts
|
|
2424
|
+
import { note as note5 } from "@clack/prompts";
|
|
2425
|
+
import pc6 from "picocolors";
|
|
2426
|
+
function showHelp() {
|
|
2427
|
+
const help = `
|
|
2428
|
+
${pc6.bold("RRCE MCP Hub")} - Cross-project AI assistant server
|
|
2429
|
+
|
|
2430
|
+
${pc6.bold("ABOUT")}
|
|
2431
|
+
MCP (Model Context Protocol) allows AI assistants like Claude to
|
|
2432
|
+
access your project knowledge in real-time. The RRCE MCP Hub
|
|
2433
|
+
provides a central server that exposes selected projects.
|
|
2434
|
+
|
|
2435
|
+
${pc6.bold("MENU OPTIONS")}
|
|
2436
|
+
${pc6.cyan("Start MCP server")} Start the server for AI access
|
|
2437
|
+
${pc6.cyan("Configure projects")} Choose which projects to expose
|
|
2438
|
+
${pc6.cyan("Install to IDE")} Add to Antigravity, VSCode, or Claude
|
|
2439
|
+
${pc6.cyan("View status")} See which projects are exposed
|
|
2440
|
+
|
|
2441
|
+
${pc6.bold("DIRECT COMMANDS")}
|
|
2442
|
+
${pc6.dim("rrce-workflow mcp start")} Start server directly
|
|
2443
|
+
${pc6.dim("rrce-workflow mcp stop")} Stop server directly
|
|
2444
|
+
${pc6.dim("rrce-workflow mcp status")} Show status directly
|
|
2445
|
+
${pc6.dim("rrce-workflow mcp help")} Show this help
|
|
2446
|
+
|
|
2447
|
+
${pc6.bold("IDE INSTALLATION")}
|
|
2448
|
+
${pc6.cyan("Antigravity")} ~/.gemini/antigravity/mcp_config.json
|
|
2449
|
+
${pc6.cyan("VSCode Global")} ~/.config/Code/User/settings.json
|
|
2450
|
+
${pc6.cyan("VSCode Workspace")} .vscode/mcp.json
|
|
2451
|
+
${pc6.cyan("Claude Desktop")} ~/.config/claude/claude_desktop_config.json
|
|
2452
|
+
|
|
2453
|
+
${pc6.bold("SERVER COMMANDS")} (while running)
|
|
2454
|
+
${pc6.cyan("q")} Stop and quit ${pc6.cyan("p")} Reconfigure projects
|
|
2455
|
+
${pc6.cyan("i")} Install to IDE ${pc6.cyan("r")} Reload config
|
|
2456
|
+
${pc6.cyan("c")} Clear logs ${pc6.cyan("?")} Show help
|
|
2457
|
+
|
|
2458
|
+
${pc6.bold("RESOURCES EXPOSED")}
|
|
2459
|
+
${pc6.cyan("rrce://projects")} List all exposed projects
|
|
2460
|
+
${pc6.cyan("rrce://projects/{name}/context")} Get project context
|
|
2461
|
+
${pc6.cyan("rrce://projects/{name}/tasks")} Get project tasks
|
|
2462
|
+
`;
|
|
2463
|
+
note5(help.trim(), "Help");
|
|
2464
|
+
}
|
|
2465
|
+
var init_help = __esm({
|
|
2466
|
+
"src/mcp/commands/help.ts"() {
|
|
2467
|
+
"use strict";
|
|
2468
|
+
}
|
|
2469
|
+
});
|
|
2470
|
+
|
|
2042
2471
|
// src/mcp/index.ts
|
|
2043
2472
|
var mcp_exports = {};
|
|
2044
2473
|
__export(mcp_exports, {
|
|
2474
|
+
handleConfigure: () => handleConfigure,
|
|
2475
|
+
handleConfigureGlobalPath: () => handleConfigureGlobalPath,
|
|
2476
|
+
handleStartServer: () => handleStartServer,
|
|
2045
2477
|
runMCP: () => runMCP
|
|
2046
2478
|
});
|
|
2047
|
-
import { intro, outro, select as select2,
|
|
2048
|
-
import
|
|
2479
|
+
import { intro, outro, select as select2, confirm as confirm2, note as note6, cancel, isCancel as isCancel5 } from "@clack/prompts";
|
|
2480
|
+
import pc7 from "picocolors";
|
|
2049
2481
|
async function runMCP(subcommand2) {
|
|
2050
2482
|
if (subcommand2) {
|
|
2051
2483
|
switch (subcommand2) {
|
|
@@ -2067,59 +2499,62 @@ async function runMCP(subcommand2) {
|
|
|
2067
2499
|
case "help":
|
|
2068
2500
|
showHelp();
|
|
2069
2501
|
return;
|
|
2502
|
+
case "configure":
|
|
2503
|
+
await handleConfigure();
|
|
2504
|
+
return;
|
|
2070
2505
|
}
|
|
2071
2506
|
}
|
|
2072
|
-
intro(
|
|
2507
|
+
intro(pc7.bgCyan(pc7.black(" RRCE MCP Hub ")));
|
|
2073
2508
|
const workspacePath = detectWorkspaceRoot();
|
|
2074
2509
|
const globalPathCheck = await ensureMCPGlobalPath();
|
|
2075
2510
|
if (!globalPathCheck.configured) {
|
|
2076
2511
|
const configured = await handleConfigureGlobalPath();
|
|
2077
2512
|
if (!configured) {
|
|
2078
|
-
outro(
|
|
2513
|
+
outro(pc7.yellow("MCP requires a global storage path. Setup cancelled."));
|
|
2079
2514
|
return;
|
|
2080
2515
|
}
|
|
2081
2516
|
}
|
|
2082
2517
|
const installed = isInstalledAnywhere(workspacePath);
|
|
2083
2518
|
if (!installed) {
|
|
2084
|
-
|
|
2085
|
-
`${
|
|
2519
|
+
note6(
|
|
2520
|
+
`${pc7.bold("Welcome to RRCE MCP Hub!")}
|
|
2086
2521
|
|
|
2087
2522
|
MCP (Model Context Protocol) allows AI assistants to access your
|
|
2088
2523
|
project knowledge in real-time. Let's get you set up.`,
|
|
2089
2524
|
"Getting Started"
|
|
2090
2525
|
);
|
|
2091
|
-
const shouldInstall = await
|
|
2526
|
+
const shouldInstall = await confirm2({
|
|
2092
2527
|
message: "Install MCP server to your IDE(s)?",
|
|
2093
2528
|
initialValue: true
|
|
2094
2529
|
});
|
|
2095
|
-
if (shouldInstall && !
|
|
2096
|
-
await
|
|
2530
|
+
if (shouldInstall && !isCancel5(shouldInstall)) {
|
|
2531
|
+
await runInstallWizard(workspacePath);
|
|
2097
2532
|
const config2 = loadMCPConfig();
|
|
2098
2533
|
const exposedCount2 = config2.projects.filter((p) => p.expose).length;
|
|
2099
2534
|
if (exposedCount2 === 0) {
|
|
2100
2535
|
await handleConfigure();
|
|
2101
2536
|
}
|
|
2102
|
-
const shouldStart = await
|
|
2537
|
+
const shouldStart = await confirm2({
|
|
2103
2538
|
message: "Start the MCP server now?",
|
|
2104
2539
|
initialValue: true
|
|
2105
2540
|
});
|
|
2106
|
-
if (shouldStart && !
|
|
2541
|
+
if (shouldStart && !isCancel5(shouldStart)) {
|
|
2107
2542
|
await handleStartServer();
|
|
2108
2543
|
}
|
|
2109
2544
|
}
|
|
2110
|
-
outro(
|
|
2545
|
+
outro(pc7.green("MCP Hub setup complete!"));
|
|
2111
2546
|
return;
|
|
2112
2547
|
}
|
|
2113
2548
|
const config = loadMCPConfig();
|
|
2114
2549
|
const exposedCount = config.projects.filter((p) => p.expose).length;
|
|
2115
2550
|
if (exposedCount === 0 && !config.defaults.includeNew) {
|
|
2116
|
-
|
|
2551
|
+
note6("MCP is installed but no projects are exposed. Let's configure that.", "Configuration Needed");
|
|
2117
2552
|
await handleConfigure();
|
|
2118
2553
|
}
|
|
2119
2554
|
let running = true;
|
|
2120
2555
|
while (running) {
|
|
2121
2556
|
const serverStatus = getMCPServerStatus();
|
|
2122
|
-
const serverLabel = serverStatus.running ?
|
|
2557
|
+
const serverLabel = serverStatus.running ? pc7.green("\u25CF Running") : pc7.dim("\u25CB Stopped");
|
|
2123
2558
|
const currentStatus = checkInstallStatus(workspacePath);
|
|
2124
2559
|
const installedCount = [currentStatus.antigravity, currentStatus.claude, currentStatus.vscodeGlobal, currentStatus.vscodeWorkspace].filter(Boolean).length;
|
|
2125
2560
|
const action = await select2({
|
|
@@ -2133,7 +2568,7 @@ project knowledge in real-time. Let's get you set up.`,
|
|
|
2133
2568
|
{ value: "exit", label: "\u21A9 Exit", hint: "Return to shell" }
|
|
2134
2569
|
]
|
|
2135
2570
|
});
|
|
2136
|
-
if (
|
|
2571
|
+
if (isCancel5(action)) {
|
|
2137
2572
|
cancel("MCP Hub closed.");
|
|
2138
2573
|
return;
|
|
2139
2574
|
}
|
|
@@ -2145,7 +2580,7 @@ project knowledge in real-time. Let's get you set up.`,
|
|
|
2145
2580
|
await handleConfigure();
|
|
2146
2581
|
break;
|
|
2147
2582
|
case "install":
|
|
2148
|
-
await
|
|
2583
|
+
await runInstallWizard(workspacePath);
|
|
2149
2584
|
break;
|
|
2150
2585
|
case "status":
|
|
2151
2586
|
await handleShowStatus();
|
|
@@ -2158,330 +2593,47 @@ project knowledge in real-time. Let's get you set up.`,
|
|
|
2158
2593
|
break;
|
|
2159
2594
|
}
|
|
2160
2595
|
}
|
|
2161
|
-
outro(
|
|
2162
|
-
}
|
|
2163
|
-
async function handleInstallWizard(workspacePath) {
|
|
2164
|
-
const status = checkInstallStatus(workspacePath);
|
|
2165
|
-
const options = [
|
|
2166
|
-
{
|
|
2167
|
-
value: "antigravity",
|
|
2168
|
-
label: "Antigravity IDE",
|
|
2169
|
-
hint: status.antigravity ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
|
|
2170
|
-
},
|
|
2171
|
-
{
|
|
2172
|
-
value: "vscode-global",
|
|
2173
|
-
label: "VSCode (Global Settings)",
|
|
2174
|
-
hint: status.vscodeGlobal ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
|
|
2175
|
-
},
|
|
2176
|
-
{
|
|
2177
|
-
value: "vscode-workspace",
|
|
2178
|
-
label: "VSCode (Workspace Config)",
|
|
2179
|
-
hint: status.vscodeWorkspace ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
|
|
2180
|
-
},
|
|
2181
|
-
{
|
|
2182
|
-
value: "claude",
|
|
2183
|
-
label: "Claude Desktop",
|
|
2184
|
-
hint: status.claude ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")
|
|
2185
|
-
}
|
|
2186
|
-
];
|
|
2187
|
-
const selected = await multiselect({
|
|
2188
|
-
message: "Select where to install RRCE MCP Server:",
|
|
2189
|
-
options,
|
|
2190
|
-
initialValues: [
|
|
2191
|
-
...status.antigravity ? ["antigravity"] : [],
|
|
2192
|
-
...status.vscodeGlobal ? ["vscode-global"] : [],
|
|
2193
|
-
...status.vscodeWorkspace ? ["vscode-workspace"] : [],
|
|
2194
|
-
...status.claude ? ["claude"] : []
|
|
2195
|
-
],
|
|
2196
|
-
required: false
|
|
2197
|
-
});
|
|
2198
|
-
if (isCancel2(selected)) return;
|
|
2199
|
-
const targets = selected;
|
|
2200
|
-
const results = [];
|
|
2201
|
-
for (const target of targets) {
|
|
2202
|
-
const success = installToConfig(target, workspacePath);
|
|
2203
|
-
const label = getTargetLabel(target);
|
|
2204
|
-
results.push(`${label}: ${success ? pc3.green("\u2713 Success") : pc3.red("\u2717 Failed")}`);
|
|
2205
|
-
}
|
|
2206
|
-
if (results.length > 0) {
|
|
2207
|
-
note2(results.join("\n"), "Installation Results");
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
async function handleStartServer() {
|
|
2211
|
-
const React7 = await import("react");
|
|
2212
|
-
const { render } = await import("ink");
|
|
2213
|
-
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
2214
|
-
const { loadMCPConfig: loadMCPConfig2, saveMCPConfig: saveMCPConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
2215
|
-
const config = loadMCPConfig2();
|
|
2216
|
-
const projects = scanForProjects();
|
|
2217
|
-
const exposedProjects = projects.filter((p) => {
|
|
2218
|
-
const cfg = config.projects.find((c) => c.name === p.name);
|
|
2219
|
-
return cfg?.expose ?? config.defaults.includeNew;
|
|
2220
|
-
});
|
|
2221
|
-
if (exposedProjects.length === 0) {
|
|
2222
|
-
const shouldConfig = await confirm({
|
|
2223
|
-
message: "No projects are currently exposed. Configure now?",
|
|
2224
|
-
initialValue: true
|
|
2225
|
-
});
|
|
2226
|
-
if (shouldConfig && !isCancel2(shouldConfig)) {
|
|
2227
|
-
await handleConfigure();
|
|
2228
|
-
return handleStartServer();
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
const status = getMCPServerStatus();
|
|
2232
|
-
let initialPort = config.server.port;
|
|
2233
|
-
if (!status.running) {
|
|
2234
|
-
const portInput = await text({
|
|
2235
|
-
message: "Select port for MCP Server",
|
|
2236
|
-
initialValue: config.server.port.toString(),
|
|
2237
|
-
placeholder: "3200",
|
|
2238
|
-
validate(value) {
|
|
2239
|
-
if (isNaN(Number(value))) return "Port must be a number";
|
|
2240
|
-
}
|
|
2241
|
-
});
|
|
2242
|
-
if (isCancel2(portInput)) return;
|
|
2243
|
-
const newPort = parseInt(portInput, 10);
|
|
2244
|
-
if (newPort !== config.server.port) {
|
|
2245
|
-
config.server.port = newPort;
|
|
2246
|
-
saveMCPConfig2(config);
|
|
2247
|
-
initialPort = newPort;
|
|
2248
|
-
}
|
|
2249
|
-
}
|
|
2250
|
-
console.clear();
|
|
2251
|
-
let keepRunning = true;
|
|
2252
|
-
while (keepRunning) {
|
|
2253
|
-
let nextAction = "exit";
|
|
2254
|
-
process.stdin.resume();
|
|
2255
|
-
const app = render(React7.createElement(App2, {
|
|
2256
|
-
initialPort,
|
|
2257
|
-
onExit: () => {
|
|
2258
|
-
nextAction = "exit";
|
|
2259
|
-
},
|
|
2260
|
-
onConfigure: () => {
|
|
2261
|
-
nextAction = "configure";
|
|
2262
|
-
},
|
|
2263
|
-
onInstall: () => {
|
|
2264
|
-
nextAction = "install";
|
|
2265
|
-
}
|
|
2266
|
-
}), {
|
|
2267
|
-
exitOnCtrlC: false
|
|
2268
|
-
// We handle this in App
|
|
2269
|
-
});
|
|
2270
|
-
await app.waitUntilExit();
|
|
2271
|
-
if (nextAction === "exit") {
|
|
2272
|
-
keepRunning = false;
|
|
2273
|
-
} else if (nextAction === "configure") {
|
|
2274
|
-
console.clear();
|
|
2275
|
-
await handleConfigure();
|
|
2276
|
-
} else if (nextAction === "install") {
|
|
2277
|
-
console.clear();
|
|
2278
|
-
const workspacePath = detectWorkspaceRoot();
|
|
2279
|
-
await handleInstallWizard(workspacePath);
|
|
2280
|
-
}
|
|
2281
|
-
}
|
|
2282
|
-
}
|
|
2283
|
-
async function handleConfigureGlobalPath() {
|
|
2284
|
-
const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
|
|
2285
|
-
const fs17 = await import("fs");
|
|
2286
|
-
const path16 = await import("path");
|
|
2287
|
-
note2(
|
|
2288
|
-
`MCP Hub requires a ${pc3.bold("global storage path")} to store its configuration
|
|
2289
|
-
and coordinate across projects.
|
|
2290
|
-
|
|
2291
|
-
Your current setup uses ${pc3.cyan("workspace")} mode, which stores data
|
|
2292
|
-
locally in each project. MCP needs a central location.`,
|
|
2293
|
-
"Global Path Required"
|
|
2294
|
-
);
|
|
2295
|
-
const resolvedPath = await resolveGlobalPath2();
|
|
2296
|
-
if (!resolvedPath) {
|
|
2297
|
-
return false;
|
|
2298
|
-
}
|
|
2299
|
-
try {
|
|
2300
|
-
if (!fs17.existsSync(resolvedPath)) {
|
|
2301
|
-
fs17.mkdirSync(resolvedPath, { recursive: true });
|
|
2302
|
-
}
|
|
2303
|
-
const config = loadMCPConfig();
|
|
2304
|
-
saveMCPConfig(config);
|
|
2305
|
-
note2(
|
|
2306
|
-
`${pc3.green("\u2713")} Global path configured: ${pc3.cyan(resolvedPath)}
|
|
2307
|
-
|
|
2308
|
-
MCP config will be stored at:
|
|
2309
|
-
${path16.join(resolvedPath, "mcp.yaml")}`,
|
|
2310
|
-
"Configuration Saved"
|
|
2311
|
-
);
|
|
2312
|
-
return true;
|
|
2313
|
-
} catch (error) {
|
|
2314
|
-
note2(
|
|
2315
|
-
`${pc3.red("\u2717")} Failed to create directory: ${error instanceof Error ? error.message : String(error)}`,
|
|
2316
|
-
"Error"
|
|
2317
|
-
);
|
|
2318
|
-
return false;
|
|
2319
|
-
}
|
|
2320
|
-
}
|
|
2321
|
-
async function handleShowStatus() {
|
|
2322
|
-
const s = spinner();
|
|
2323
|
-
s.start("Loading projects...");
|
|
2324
|
-
const config = loadMCPConfig();
|
|
2325
|
-
const projects = scanForProjects();
|
|
2326
|
-
const workspacePath = detectWorkspaceRoot();
|
|
2327
|
-
const installStatus = checkInstallStatus(workspacePath);
|
|
2328
|
-
s.stop("Projects loaded");
|
|
2329
|
-
if (projects.length === 0) {
|
|
2330
|
-
note2('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
|
|
2331
|
-
return;
|
|
2332
|
-
}
|
|
2333
|
-
const lines = [
|
|
2334
|
-
`${pc3.bold("Installation Status")}`,
|
|
2335
|
-
"",
|
|
2336
|
-
` Antigravity: ${installStatus.antigravity ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
|
|
2337
|
-
` VSCode (Global): ${installStatus.vscodeGlobal ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
|
|
2338
|
-
` VSCode (Workspace): ${installStatus.vscodeWorkspace ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
|
|
2339
|
-
` Claude Desktop: ${installStatus.claude ? pc3.green("\u2713 Installed") : pc3.dim("Not installed")}`,
|
|
2340
|
-
"",
|
|
2341
|
-
`${pc3.bold("Project Status")}`,
|
|
2342
|
-
""
|
|
2343
|
-
];
|
|
2344
|
-
for (const project of projects) {
|
|
2345
|
-
const projectConfig = config.projects.find((p) => p.name === project.name);
|
|
2346
|
-
const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
|
|
2347
|
-
const status = isExposed ? pc3.green("\u2713 exposed") : pc3.dim("\u25CB hidden");
|
|
2348
|
-
const source = pc3.dim(`(${project.source})`);
|
|
2349
|
-
lines.push(` ${status} ${project.name} ${source}`);
|
|
2350
|
-
}
|
|
2351
|
-
lines.push("");
|
|
2352
|
-
lines.push(pc3.dim(`Config: ${getMCPConfigPath()}`));
|
|
2353
|
-
const serverStatus = getMCPServerStatus();
|
|
2354
|
-
if (serverStatus.running) {
|
|
2355
|
-
lines.push(pc3.green(`Server: running on port ${serverStatus.port}`));
|
|
2356
|
-
} else {
|
|
2357
|
-
lines.push(pc3.dim("Server: not running"));
|
|
2358
|
-
}
|
|
2359
|
-
note2(lines.join("\n"), "MCP Hub Status");
|
|
2360
|
-
}
|
|
2361
|
-
async function handleConfigure() {
|
|
2362
|
-
const { logger: logger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
2363
|
-
const s = spinner();
|
|
2364
|
-
s.start("Scanning for projects...");
|
|
2365
|
-
const config = loadMCPConfig();
|
|
2366
|
-
const projects = scanForProjects();
|
|
2367
|
-
logger2.info("Configure: Loaded config", { projects: config.projects, defaultMode: config.defaults.includeNew });
|
|
2368
|
-
s.stop("Projects found");
|
|
2369
|
-
if (projects.length === 0) {
|
|
2370
|
-
note2('No RRCE projects detected. Run "rrce-workflow" in a project to set it up.', "No Projects");
|
|
2371
|
-
return;
|
|
2372
|
-
}
|
|
2373
|
-
const options = projects.map((project) => {
|
|
2374
|
-
const projectConfig = config.projects.find((p) => p.name === project.name);
|
|
2375
|
-
const isExposed = projectConfig?.expose ?? config.defaults.includeNew;
|
|
2376
|
-
return {
|
|
2377
|
-
value: project.name,
|
|
2378
|
-
label: `${project.name} ${pc3.dim(`(${project.source})`)}`,
|
|
2379
|
-
hint: project.dataPath
|
|
2380
|
-
};
|
|
2381
|
-
});
|
|
2382
|
-
const currentlyExposed = projects.filter((p) => {
|
|
2383
|
-
const cfg = config.projects.find((c) => c.name === p.name);
|
|
2384
|
-
return cfg?.expose ?? config.defaults.includeNew;
|
|
2385
|
-
}).map((p) => p.name);
|
|
2386
|
-
const selected = await multiselect({
|
|
2387
|
-
message: "Select projects to expose via MCP:",
|
|
2388
|
-
options,
|
|
2389
|
-
initialValues: currentlyExposed,
|
|
2390
|
-
required: false
|
|
2391
|
-
});
|
|
2392
|
-
if (isCancel2(selected)) {
|
|
2393
|
-
return;
|
|
2394
|
-
}
|
|
2395
|
-
const selectedNames = selected;
|
|
2396
|
-
logger2.info("Configure: User selected projects", selectedNames);
|
|
2397
|
-
for (const project of projects) {
|
|
2398
|
-
const shouldExpose = selectedNames.includes(project.name);
|
|
2399
|
-
setProjectConfig(config, project.name, shouldExpose);
|
|
2400
|
-
}
|
|
2401
|
-
saveMCPConfig(config);
|
|
2402
|
-
logger2.info("Configure: Config saved", config);
|
|
2403
|
-
const exposedCount = selectedNames.length;
|
|
2404
|
-
note2(
|
|
2405
|
-
`${pc3.green("\u2713")} Configuration saved!
|
|
2406
|
-
|
|
2407
|
-
Exposed projects: ${exposedCount}
|
|
2408
|
-
Hidden projects: ${projects.length - exposedCount}`,
|
|
2409
|
-
"Configuration Updated"
|
|
2410
|
-
);
|
|
2596
|
+
outro(pc7.green("MCP Hub closed."));
|
|
2411
2597
|
}
|
|
2412
2598
|
async function handleStopServer() {
|
|
2599
|
+
const { stopMCPServer: stopMCPServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
2413
2600
|
const status = getMCPServerStatus();
|
|
2414
2601
|
if (!status.running) {
|
|
2415
|
-
|
|
2602
|
+
note6("MCP server is not running.", "Status");
|
|
2416
2603
|
return;
|
|
2417
2604
|
}
|
|
2418
|
-
const confirmed = await
|
|
2605
|
+
const confirmed = await confirm2({
|
|
2419
2606
|
message: "Stop the MCP server?",
|
|
2420
2607
|
initialValue: true
|
|
2421
2608
|
});
|
|
2422
|
-
if (
|
|
2609
|
+
if (isCancel5(confirmed) || !confirmed) {
|
|
2423
2610
|
return;
|
|
2424
2611
|
}
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
}
|
|
2428
|
-
function showHelp() {
|
|
2429
|
-
const help = `
|
|
2430
|
-
${pc3.bold("RRCE MCP Hub")} - Cross-project AI assistant server
|
|
2431
|
-
|
|
2432
|
-
${pc3.bold("ABOUT")}
|
|
2433
|
-
MCP (Model Context Protocol) allows AI assistants like Claude to
|
|
2434
|
-
access your project knowledge in real-time. The RRCE MCP Hub
|
|
2435
|
-
provides a central server that exposes selected projects.
|
|
2436
|
-
|
|
2437
|
-
${pc3.bold("MENU OPTIONS")}
|
|
2438
|
-
${pc3.cyan("Start MCP server")} Start the server for AI access
|
|
2439
|
-
${pc3.cyan("Configure projects")} Choose which projects to expose
|
|
2440
|
-
${pc3.cyan("Install to IDE")} Add to Antigravity, VSCode, or Claude
|
|
2441
|
-
${pc3.cyan("View status")} See which projects are exposed
|
|
2442
|
-
|
|
2443
|
-
${pc3.bold("DIRECT COMMANDS")}
|
|
2444
|
-
${pc3.dim("rrce-workflow mcp start")} Start server directly
|
|
2445
|
-
${pc3.dim("rrce-workflow mcp stop")} Stop server directly
|
|
2446
|
-
${pc3.dim("rrce-workflow mcp status")} Show status directly
|
|
2447
|
-
${pc3.dim("rrce-workflow mcp help")} Show this help
|
|
2448
|
-
|
|
2449
|
-
${pc3.bold("IDE INSTALLATION")}
|
|
2450
|
-
${pc3.cyan("Antigravity")} ~/.gemini/antigravity/mcp_config.json
|
|
2451
|
-
${pc3.cyan("VSCode Global")} ~/.config/Code/User/settings.json
|
|
2452
|
-
${pc3.cyan("VSCode Workspace")} .vscode/mcp.json
|
|
2453
|
-
${pc3.cyan("Claude Desktop")} ~/.config/claude/claude_desktop_config.json
|
|
2454
|
-
|
|
2455
|
-
${pc3.bold("SERVER COMMANDS")} (while running)
|
|
2456
|
-
${pc3.cyan("q")} Stop and quit ${pc3.cyan("p")} Reconfigure projects
|
|
2457
|
-
${pc3.cyan("i")} Install to IDE ${pc3.cyan("r")} Reload config
|
|
2458
|
-
${pc3.cyan("c")} Clear logs ${pc3.cyan("?")} Show help
|
|
2459
|
-
|
|
2460
|
-
${pc3.bold("RESOURCES EXPOSED")}
|
|
2461
|
-
${pc3.cyan("rrce://projects")} List all exposed projects
|
|
2462
|
-
${pc3.cyan("rrce://projects/{name}/context")} Get project context
|
|
2463
|
-
${pc3.cyan("rrce://projects/{name}/tasks")} Get project tasks
|
|
2464
|
-
`;
|
|
2465
|
-
note2(help.trim(), "Help");
|
|
2612
|
+
stopMCPServer2();
|
|
2613
|
+
note6(pc7.green("MCP server stopped."), "Server Stopped");
|
|
2466
2614
|
}
|
|
2467
2615
|
var init_mcp = __esm({
|
|
2468
2616
|
"src/mcp/index.ts"() {
|
|
2469
2617
|
"use strict";
|
|
2470
2618
|
init_config();
|
|
2471
|
-
init_detection();
|
|
2472
2619
|
init_server();
|
|
2473
2620
|
init_install();
|
|
2474
2621
|
init_paths();
|
|
2622
|
+
init_start();
|
|
2623
|
+
init_configure();
|
|
2624
|
+
init_status();
|
|
2625
|
+
init_install_wizard();
|
|
2626
|
+
init_help();
|
|
2475
2627
|
}
|
|
2476
2628
|
});
|
|
2477
2629
|
|
|
2478
2630
|
// src/commands/wizard/setup-flow.ts
|
|
2479
|
-
import { group, select as select3, multiselect as
|
|
2480
|
-
import
|
|
2631
|
+
import { group, select as select3, multiselect as multiselect3, confirm as confirm3, spinner as spinner3, note as note7, outro as outro2, cancel as cancel2, isCancel as isCancel6 } from "@clack/prompts";
|
|
2632
|
+
import pc8 from "picocolors";
|
|
2481
2633
|
import * as fs12 from "fs";
|
|
2482
2634
|
import * as path12 from "path";
|
|
2483
2635
|
async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
2484
|
-
const s =
|
|
2636
|
+
const s = spinner3();
|
|
2485
2637
|
const config = await group(
|
|
2486
2638
|
{
|
|
2487
2639
|
storageMode: () => select3({
|
|
@@ -2492,7 +2644,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
2492
2644
|
],
|
|
2493
2645
|
initialValue: "global"
|
|
2494
2646
|
}),
|
|
2495
|
-
tools: () =>
|
|
2647
|
+
tools: () => multiselect3({
|
|
2496
2648
|
message: "Which AI tools do you use?",
|
|
2497
2649
|
options: [
|
|
2498
2650
|
{ value: "copilot", label: "GitHub Copilot", hint: "VSCode" },
|
|
@@ -2504,28 +2656,28 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
2504
2656
|
if (existingProjects.length === 0) {
|
|
2505
2657
|
return Promise.resolve([]);
|
|
2506
2658
|
}
|
|
2507
|
-
return
|
|
2659
|
+
return multiselect3({
|
|
2508
2660
|
message: "Link knowledge from other projects?",
|
|
2509
2661
|
options: existingProjects.map((project) => ({
|
|
2510
2662
|
value: `${project.name}:${project.source}`,
|
|
2511
2663
|
// Unique key
|
|
2512
|
-
label: `${project.name} ${
|
|
2513
|
-
hint:
|
|
2664
|
+
label: `${project.name} ${pc8.dim(`(${project.source})`)}`,
|
|
2665
|
+
hint: pc8.dim(
|
|
2514
2666
|
project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
|
|
2515
2667
|
)
|
|
2516
2668
|
})),
|
|
2517
2669
|
required: false
|
|
2518
2670
|
});
|
|
2519
2671
|
},
|
|
2520
|
-
addToGitignore: () =>
|
|
2672
|
+
addToGitignore: () => confirm3({
|
|
2521
2673
|
message: "Add generated folders to .gitignore? (as comments - uncomment if needed)",
|
|
2522
2674
|
initialValue: true
|
|
2523
2675
|
}),
|
|
2524
|
-
confirm: () =>
|
|
2676
|
+
confirm: () => confirm3({
|
|
2525
2677
|
message: "Create configuration?",
|
|
2526
2678
|
initialValue: true
|
|
2527
2679
|
}),
|
|
2528
|
-
exposeToMCP: () =>
|
|
2680
|
+
exposeToMCP: () => confirm3({
|
|
2529
2681
|
message: "Expose this project to MCP (AI Agent) server?",
|
|
2530
2682
|
initialValue: true
|
|
2531
2683
|
})
|
|
@@ -2570,7 +2722,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
2570
2722
|
`Storage: ${config.storageMode}`
|
|
2571
2723
|
];
|
|
2572
2724
|
if (customGlobalPath && customGlobalPath !== getDefaultRRCEHome()) {
|
|
2573
|
-
summary.push(`Global path: ${
|
|
2725
|
+
summary.push(`Global path: ${pc8.cyan(customGlobalPath)}`);
|
|
2574
2726
|
}
|
|
2575
2727
|
if (dataPaths.length > 0) {
|
|
2576
2728
|
summary.push(`Data paths:`);
|
|
@@ -2583,29 +2735,29 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
2583
2735
|
const linkedProjects = config.linkedProjects;
|
|
2584
2736
|
if (linkedProjects.length > 0) {
|
|
2585
2737
|
summary.push(`Linked projects: ${linkedProjects.join(", ")}`);
|
|
2586
|
-
summary.push(`Workspace file: ${
|
|
2738
|
+
summary.push(`Workspace file: ${pc8.cyan(`${workspaceName}.code-workspace`)}`);
|
|
2587
2739
|
}
|
|
2588
|
-
|
|
2740
|
+
note7(summary.join("\n"), "Setup Summary");
|
|
2589
2741
|
if (config.exposeToMCP) {
|
|
2590
|
-
|
|
2742
|
+
note7(`${pc8.green("\u2713")} Project exposed to MCP Hub`, "MCP Configuration");
|
|
2591
2743
|
if (linkedProjects.length > 0) {
|
|
2592
|
-
outro2(
|
|
2744
|
+
outro2(pc8.green(`\u2713 Setup complete! Open ${pc8.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
|
|
2593
2745
|
} else {
|
|
2594
|
-
outro2(
|
|
2746
|
+
outro2(pc8.green(`\u2713 Setup complete! Your agents are ready to use.`));
|
|
2595
2747
|
}
|
|
2596
2748
|
} else {
|
|
2597
|
-
const shouldConfigureMCP = await
|
|
2749
|
+
const shouldConfigureMCP = await confirm3({
|
|
2598
2750
|
message: "Would you like to configure the MCP server now?",
|
|
2599
2751
|
initialValue: true
|
|
2600
2752
|
});
|
|
2601
|
-
if (shouldConfigureMCP && !
|
|
2753
|
+
if (shouldConfigureMCP && !isCancel6(shouldConfigureMCP)) {
|
|
2602
2754
|
const { runMCP: runMCP2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
|
|
2603
2755
|
await runMCP2();
|
|
2604
2756
|
} else {
|
|
2605
2757
|
if (linkedProjects.length > 0) {
|
|
2606
|
-
outro2(
|
|
2758
|
+
outro2(pc8.green(`\u2713 Setup complete! Open ${pc8.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
|
|
2607
2759
|
} else {
|
|
2608
|
-
outro2(
|
|
2760
|
+
outro2(pc8.green(`\u2713 Setup complete! Your agents are ready to use.`));
|
|
2609
2761
|
}
|
|
2610
2762
|
}
|
|
2611
2763
|
}
|
|
@@ -2769,8 +2921,8 @@ var init_setup_flow = __esm({
|
|
|
2769
2921
|
});
|
|
2770
2922
|
|
|
2771
2923
|
// src/commands/wizard/link-flow.ts
|
|
2772
|
-
import { multiselect as
|
|
2773
|
-
import
|
|
2924
|
+
import { multiselect as multiselect4, spinner as spinner4, note as note8, outro as outro3, cancel as cancel3, isCancel as isCancel7 } from "@clack/prompts";
|
|
2925
|
+
import pc9 from "picocolors";
|
|
2774
2926
|
import * as fs13 from "fs";
|
|
2775
2927
|
async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
2776
2928
|
const projects = scanForProjects({
|
|
@@ -2778,23 +2930,23 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
|
2778
2930
|
workspacePath
|
|
2779
2931
|
});
|
|
2780
2932
|
if (projects.length === 0) {
|
|
2781
|
-
outro3(
|
|
2933
|
+
outro3(pc9.yellow("No other projects found. Try setting up another project first."));
|
|
2782
2934
|
return;
|
|
2783
2935
|
}
|
|
2784
2936
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
2785
|
-
const linkedProjects = await
|
|
2937
|
+
const linkedProjects = await multiselect4({
|
|
2786
2938
|
message: "Select projects to link:",
|
|
2787
2939
|
options: projects.map((project) => ({
|
|
2788
2940
|
value: `${project.name}:${project.source}`,
|
|
2789
2941
|
// Unique key
|
|
2790
|
-
label: `${project.name} ${
|
|
2791
|
-
hint:
|
|
2942
|
+
label: `${project.name} ${pc9.dim(`(${project.source})`)}`,
|
|
2943
|
+
hint: pc9.dim(
|
|
2792
2944
|
project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
|
|
2793
2945
|
)
|
|
2794
2946
|
})),
|
|
2795
2947
|
required: true
|
|
2796
2948
|
});
|
|
2797
|
-
if (
|
|
2949
|
+
if (isCancel7(linkedProjects)) {
|
|
2798
2950
|
cancel3("Cancelled.");
|
|
2799
2951
|
process.exit(0);
|
|
2800
2952
|
}
|
|
@@ -2806,7 +2958,7 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
|
2806
2958
|
const selectedProjects = projects.filter(
|
|
2807
2959
|
(p) => selectedKeys.includes(`${p.name}:${p.source}`)
|
|
2808
2960
|
);
|
|
2809
|
-
const s =
|
|
2961
|
+
const s = spinner4();
|
|
2810
2962
|
s.start("Linking projects");
|
|
2811
2963
|
const configFilePath = getConfigPath(workspacePath);
|
|
2812
2964
|
let configContent = fs13.readFileSync(configFilePath, "utf-8");
|
|
@@ -2842,12 +2994,12 @@ linked_projects:
|
|
|
2842
2994
|
const workspaceFile = `${workspaceName}.code-workspace`;
|
|
2843
2995
|
const summary = [
|
|
2844
2996
|
`Linked projects:`,
|
|
2845
|
-
...selectedProjects.map((p) => ` \u2713 ${p.name} ${
|
|
2997
|
+
...selectedProjects.map((p) => ` \u2713 ${p.name} ${pc9.dim(`(${p.source})`)}`),
|
|
2846
2998
|
``,
|
|
2847
|
-
`Workspace file: ${
|
|
2999
|
+
`Workspace file: ${pc9.cyan(workspaceFile)}`
|
|
2848
3000
|
];
|
|
2849
|
-
|
|
2850
|
-
outro3(
|
|
3001
|
+
note8(summary.join("\n"), "Link Summary");
|
|
3002
|
+
outro3(pc9.green(`\u2713 Projects linked! Open ${pc9.bold(workspaceFile)} in VSCode to access linked data.`));
|
|
2851
3003
|
}
|
|
2852
3004
|
var init_link_flow = __esm({
|
|
2853
3005
|
"src/commands/wizard/link-flow.ts"() {
|
|
@@ -2859,8 +3011,8 @@ var init_link_flow = __esm({
|
|
|
2859
3011
|
});
|
|
2860
3012
|
|
|
2861
3013
|
// src/commands/wizard/sync-flow.ts
|
|
2862
|
-
import { confirm as
|
|
2863
|
-
import
|
|
3014
|
+
import { confirm as confirm4, spinner as spinner5, note as note9, outro as outro4, cancel as cancel4, isCancel as isCancel8 } from "@clack/prompts";
|
|
3015
|
+
import pc10 from "picocolors";
|
|
2864
3016
|
import * as fs14 from "fs";
|
|
2865
3017
|
import * as path13 from "path";
|
|
2866
3018
|
async function runSyncToGlobalFlow(workspacePath, workspaceName) {
|
|
@@ -2872,25 +3024,25 @@ async function runSyncToGlobalFlow(workspacePath, workspaceName) {
|
|
|
2872
3024
|
(dir) => fs14.existsSync(path13.join(localPath, dir))
|
|
2873
3025
|
);
|
|
2874
3026
|
if (existingDirs.length === 0) {
|
|
2875
|
-
outro4(
|
|
3027
|
+
outro4(pc10.yellow("No data found in workspace storage to sync."));
|
|
2876
3028
|
return;
|
|
2877
3029
|
}
|
|
2878
|
-
|
|
3030
|
+
note9(
|
|
2879
3031
|
`The following will be copied to global storage:
|
|
2880
3032
|
${existingDirs.map((d) => ` \u2022 ${d}/`).join("\n")}
|
|
2881
3033
|
|
|
2882
|
-
Destination: ${
|
|
3034
|
+
Destination: ${pc10.cyan(globalPath)}`,
|
|
2883
3035
|
"Sync Preview"
|
|
2884
3036
|
);
|
|
2885
|
-
const shouldSync = await
|
|
3037
|
+
const shouldSync = await confirm4({
|
|
2886
3038
|
message: "Proceed with sync to global storage?",
|
|
2887
3039
|
initialValue: true
|
|
2888
3040
|
});
|
|
2889
|
-
if (
|
|
3041
|
+
if (isCancel8(shouldSync) || !shouldSync) {
|
|
2890
3042
|
outro4("Sync cancelled.");
|
|
2891
3043
|
return;
|
|
2892
3044
|
}
|
|
2893
|
-
const s =
|
|
3045
|
+
const s = spinner5();
|
|
2894
3046
|
s.start("Syncing to global storage");
|
|
2895
3047
|
try {
|
|
2896
3048
|
ensureDir(globalPath);
|
|
@@ -2905,12 +3057,12 @@ Destination: ${pc6.cyan(globalPath)}`,
|
|
|
2905
3057
|
`Synced directories:`,
|
|
2906
3058
|
...existingDirs.map((d) => ` \u2713 ${d}/`),
|
|
2907
3059
|
``,
|
|
2908
|
-
`Global path: ${
|
|
3060
|
+
`Global path: ${pc10.cyan(globalPath)}`,
|
|
2909
3061
|
``,
|
|
2910
3062
|
`Other projects can now link this knowledge!`
|
|
2911
3063
|
];
|
|
2912
|
-
|
|
2913
|
-
outro4(
|
|
3064
|
+
note9(summary.join("\n"), "Sync Summary");
|
|
3065
|
+
outro4(pc10.green("\u2713 Workspace knowledge synced to global storage!"));
|
|
2914
3066
|
} catch (error) {
|
|
2915
3067
|
s.stop("Error occurred");
|
|
2916
3068
|
cancel4(`Failed to sync: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -2926,12 +3078,12 @@ var init_sync_flow = __esm({
|
|
|
2926
3078
|
});
|
|
2927
3079
|
|
|
2928
3080
|
// src/commands/wizard/update-flow.ts
|
|
2929
|
-
import { confirm as
|
|
2930
|
-
import
|
|
3081
|
+
import { confirm as confirm5, spinner as spinner6, note as note10, outro as outro5, cancel as cancel5, isCancel as isCancel9 } from "@clack/prompts";
|
|
3082
|
+
import pc11 from "picocolors";
|
|
2931
3083
|
import * as fs15 from "fs";
|
|
2932
3084
|
import * as path14 from "path";
|
|
2933
3085
|
async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
2934
|
-
const s =
|
|
3086
|
+
const s = spinner6();
|
|
2935
3087
|
s.start("Checking for updates");
|
|
2936
3088
|
try {
|
|
2937
3089
|
const agentCoreDir = getAgentCoreDir();
|
|
@@ -2940,7 +3092,7 @@ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
|
2940
3092
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
2941
3093
|
const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
|
|
2942
3094
|
s.stop("Updates found");
|
|
2943
|
-
|
|
3095
|
+
note10(
|
|
2944
3096
|
`The following will be updated from the package:
|
|
2945
3097
|
\u2022 prompts/ (${prompts.length} agent prompts)
|
|
2946
3098
|
\u2022 templates/ (output templates)
|
|
@@ -2949,11 +3101,11 @@ Target locations:
|
|
|
2949
3101
|
${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
2950
3102
|
"Update Preview"
|
|
2951
3103
|
);
|
|
2952
|
-
const shouldUpdate = await
|
|
3104
|
+
const shouldUpdate = await confirm5({
|
|
2953
3105
|
message: "Proceed with update?",
|
|
2954
3106
|
initialValue: true
|
|
2955
3107
|
});
|
|
2956
|
-
if (
|
|
3108
|
+
if (isCancel9(shouldUpdate) || !shouldUpdate) {
|
|
2957
3109
|
outro5("Update cancelled.");
|
|
2958
3110
|
return;
|
|
2959
3111
|
}
|
|
@@ -2981,8 +3133,8 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
2981
3133
|
``,
|
|
2982
3134
|
`Your configuration and knowledge files were preserved.`
|
|
2983
3135
|
];
|
|
2984
|
-
|
|
2985
|
-
outro5(
|
|
3136
|
+
note10(summary.join("\n"), "Update Summary");
|
|
3137
|
+
outro5(pc11.green("\u2713 Successfully updated from package!"));
|
|
2986
3138
|
} catch (error) {
|
|
2987
3139
|
s.stop("Error occurred");
|
|
2988
3140
|
cancel5(`Failed to update: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -3015,21 +3167,21 @@ var wizard_exports = {};
|
|
|
3015
3167
|
__export(wizard_exports, {
|
|
3016
3168
|
runWizard: () => runWizard
|
|
3017
3169
|
});
|
|
3018
|
-
import { intro as intro2, select as select4, spinner as
|
|
3019
|
-
import
|
|
3170
|
+
import { intro as intro2, select as select4, spinner as spinner7, note as note11, outro as outro6, isCancel as isCancel10 } from "@clack/prompts";
|
|
3171
|
+
import pc12 from "picocolors";
|
|
3020
3172
|
import * as fs16 from "fs";
|
|
3021
3173
|
async function runWizard() {
|
|
3022
|
-
intro2(
|
|
3023
|
-
const s =
|
|
3174
|
+
intro2(pc12.cyan(pc12.inverse(" RRCE-Workflow Setup ")));
|
|
3175
|
+
const s = spinner7();
|
|
3024
3176
|
s.start("Detecting environment");
|
|
3025
3177
|
const workspacePath = detectWorkspaceRoot();
|
|
3026
3178
|
const workspaceName = getWorkspaceName(workspacePath);
|
|
3027
3179
|
const gitUser = getGitUser();
|
|
3028
3180
|
await new Promise((r) => setTimeout(r, 800));
|
|
3029
3181
|
s.stop("Environment detected");
|
|
3030
|
-
|
|
3031
|
-
`Git User: ${
|
|
3032
|
-
Workspace: ${
|
|
3182
|
+
note11(
|
|
3183
|
+
`Git User: ${pc12.bold(gitUser || "(not found)")}
|
|
3184
|
+
Workspace: ${pc12.bold(workspaceName)}`,
|
|
3033
3185
|
"Context"
|
|
3034
3186
|
);
|
|
3035
3187
|
const detectedProjects = scanForProjects({
|
|
@@ -3076,7 +3228,7 @@ Workspace: ${pc8.bold(workspaceName)}`,
|
|
|
3076
3228
|
message: "This workspace is already configured. What would you like to do?",
|
|
3077
3229
|
options: menuOptions
|
|
3078
3230
|
});
|
|
3079
|
-
if (
|
|
3231
|
+
if (isCancel10(action) || action === "exit") {
|
|
3080
3232
|
outro6("Exited.");
|
|
3081
3233
|
process.exit(0);
|
|
3082
3234
|
}
|
|
@@ -3118,12 +3270,12 @@ init_wizard();
|
|
|
3118
3270
|
|
|
3119
3271
|
// src/commands/selector.ts
|
|
3120
3272
|
init_prompts();
|
|
3121
|
-
import { intro as intro3, select as select5, note as
|
|
3122
|
-
import
|
|
3273
|
+
import { intro as intro3, select as select5, note as note12, cancel as cancel7, isCancel as isCancel11, outro as outro7 } from "@clack/prompts";
|
|
3274
|
+
import pc13 from "picocolors";
|
|
3123
3275
|
import * as path15 from "path";
|
|
3124
3276
|
async function runSelector() {
|
|
3125
3277
|
const workspaceName = path15.basename(process.cwd());
|
|
3126
|
-
intro3(
|
|
3278
|
+
intro3(pc13.cyan(pc13.inverse(` RRCE-Workflow | ${workspaceName} `)));
|
|
3127
3279
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
3128
3280
|
if (prompts.length === 0) {
|
|
3129
3281
|
cancel7("No agents found. Run `rrce-workflow` to set up.");
|
|
@@ -3149,7 +3301,7 @@ async function runSelector() {
|
|
|
3149
3301
|
}))
|
|
3150
3302
|
]
|
|
3151
3303
|
});
|
|
3152
|
-
if (
|
|
3304
|
+
if (isCancel11(selection)) {
|
|
3153
3305
|
cancel7("Selection cancelled.");
|
|
3154
3306
|
process.exit(0);
|
|
3155
3307
|
}
|
|
@@ -3164,9 +3316,9 @@ async function runSelector() {
|
|
|
3164
3316
|
return;
|
|
3165
3317
|
}
|
|
3166
3318
|
const prompt = selection;
|
|
3167
|
-
|
|
3319
|
+
note12(
|
|
3168
3320
|
`Use this agent in your IDE by invoking:
|
|
3169
|
-
${
|
|
3321
|
+
${pc13.bold(pc13.cyan(`@${prompt.frontmatter.name}`))}`,
|
|
3170
3322
|
"Agent Selected"
|
|
3171
3323
|
);
|
|
3172
3324
|
outro7("Done");
|