@stackwright-pro/mcp 0.2.0-alpha.2 → 0.2.0-alpha.4
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/server.js +151 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +151 -1
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -2
package/dist/server.js
CHANGED
|
@@ -1202,6 +1202,155 @@ function setupPackages(opts) {
|
|
|
1202
1202
|
}
|
|
1203
1203
|
}
|
|
1204
1204
|
|
|
1205
|
+
// src/tools/questions.ts
|
|
1206
|
+
var import_zod7 = require("zod");
|
|
1207
|
+
|
|
1208
|
+
// src/question-adapter.ts
|
|
1209
|
+
function truncate(str, maxLength) {
|
|
1210
|
+
if (str.length <= maxLength) return str;
|
|
1211
|
+
return str.substring(0, maxLength - 1) + "\u2026";
|
|
1212
|
+
}
|
|
1213
|
+
function generateHeader(id) {
|
|
1214
|
+
const parts = id.split("-");
|
|
1215
|
+
if (parts.length >= 2) {
|
|
1216
|
+
const prefix = parts[0].toUpperCase().substring(0, 4);
|
|
1217
|
+
const num = parts[1];
|
|
1218
|
+
return truncate(`${prefix}-${num}`, 12);
|
|
1219
|
+
}
|
|
1220
|
+
return truncate(
|
|
1221
|
+
id.toUpperCase().replace(/[^A-Z0-9]/g, "").substring(0, 12),
|
|
1222
|
+
12
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
function generateDefaultOptions(type) {
|
|
1226
|
+
switch (type) {
|
|
1227
|
+
case "confirm":
|
|
1228
|
+
return [
|
|
1229
|
+
{ label: "Yes", description: "Enable or confirm this option" },
|
|
1230
|
+
{ label: "No", description: "Disable or decline this option" }
|
|
1231
|
+
];
|
|
1232
|
+
case "text":
|
|
1233
|
+
return [
|
|
1234
|
+
{ label: "Specify", description: "I will provide a specific value" },
|
|
1235
|
+
{ label: "Skip", description: "Use default or skip this question" }
|
|
1236
|
+
];
|
|
1237
|
+
default:
|
|
1238
|
+
return [
|
|
1239
|
+
{ label: "Option 1", description: "First option" },
|
|
1240
|
+
{ label: "Option 2", description: "Second option" }
|
|
1241
|
+
];
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
function adaptQuestion(q) {
|
|
1245
|
+
const header = generateHeader(q.id);
|
|
1246
|
+
const multiSelect = q.type === "multi-select";
|
|
1247
|
+
let options;
|
|
1248
|
+
if (q.options && q.options.length >= 2) {
|
|
1249
|
+
options = q.options.map((opt) => ({
|
|
1250
|
+
label: truncate(opt.label, 50),
|
|
1251
|
+
description: opt.value !== opt.label ? opt.value : void 0
|
|
1252
|
+
}));
|
|
1253
|
+
} else if (q.options && q.options.length === 1) {
|
|
1254
|
+
options = [
|
|
1255
|
+
...q.options.map((opt) => ({ label: truncate(opt.label, 50), description: opt.value })),
|
|
1256
|
+
{ label: "Other", description: "Specify a different value" }
|
|
1257
|
+
];
|
|
1258
|
+
} else {
|
|
1259
|
+
options = generateDefaultOptions(q.type);
|
|
1260
|
+
}
|
|
1261
|
+
if (options.length < 2) {
|
|
1262
|
+
options.push({ label: "Other", description: "Alternative option" });
|
|
1263
|
+
}
|
|
1264
|
+
options = options.slice(0, 6);
|
|
1265
|
+
return {
|
|
1266
|
+
question: q.question + (q.help ? `
|
|
1267
|
+
|
|
1268
|
+
${q.help}` : ""),
|
|
1269
|
+
header,
|
|
1270
|
+
multi_select: multiSelect,
|
|
1271
|
+
options
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
function adaptQuestions(questions, answers = {}) {
|
|
1275
|
+
const adapted = [];
|
|
1276
|
+
for (const q of questions) {
|
|
1277
|
+
if (q.dependsOn) {
|
|
1278
|
+
const dependsAnswer = answers[q.dependsOn.questionId];
|
|
1279
|
+
if (dependsAnswer === void 0) {
|
|
1280
|
+
continue;
|
|
1281
|
+
}
|
|
1282
|
+
const expectedValues = Array.isArray(q.dependsOn.value) ? q.dependsOn.value : [q.dependsOn.value];
|
|
1283
|
+
const answerValue = Array.isArray(dependsAnswer) ? dependsAnswer[0] : dependsAnswer;
|
|
1284
|
+
if (!expectedValues.includes(answerValue)) {
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
adapted.push(adaptQuestion(q));
|
|
1289
|
+
}
|
|
1290
|
+
return adapted;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
// src/tools/questions.ts
|
|
1294
|
+
var ManifestQuestionSchema = import_zod7.z.object({
|
|
1295
|
+
id: import_zod7.z.string(),
|
|
1296
|
+
question: import_zod7.z.string(),
|
|
1297
|
+
type: import_zod7.z.enum(["text", "select", "multi-select", "confirm"]),
|
|
1298
|
+
required: import_zod7.z.boolean().optional(),
|
|
1299
|
+
options: import_zod7.z.array(
|
|
1300
|
+
import_zod7.z.object({
|
|
1301
|
+
label: import_zod7.z.string(),
|
|
1302
|
+
value: import_zod7.z.string()
|
|
1303
|
+
})
|
|
1304
|
+
).optional(),
|
|
1305
|
+
default: import_zod7.z.union([import_zod7.z.string(), import_zod7.z.boolean(), import_zod7.z.array(import_zod7.z.string())]).optional(),
|
|
1306
|
+
help: import_zod7.z.string().optional(),
|
|
1307
|
+
dependsOn: import_zod7.z.object({
|
|
1308
|
+
questionId: import_zod7.z.string(),
|
|
1309
|
+
value: import_zod7.z.union([import_zod7.z.string(), import_zod7.z.array(import_zod7.z.string())])
|
|
1310
|
+
}).optional()
|
|
1311
|
+
});
|
|
1312
|
+
function registerQuestionTools(server2) {
|
|
1313
|
+
server2.tool(
|
|
1314
|
+
"stackwright_pro_present_phase_questions",
|
|
1315
|
+
"Adapt manifest-format questions from a specialist otter and present them to the user via ask_user_question. Use this instead of calling ask_user_question directly \u2014 it handles label truncation, header generation, confirm/text defaults, and correct array formatting automatically.",
|
|
1316
|
+
{
|
|
1317
|
+
phase: import_zod7.z.string().describe('Phase name for display context, e.g. "designer", "api", "auth"'),
|
|
1318
|
+
questions: import_zod7.z.array(ManifestQuestionSchema).describe("Questions in Question Manifest format as produced by specialist otters"),
|
|
1319
|
+
answers: import_zod7.z.record(import_zod7.z.union([import_zod7.z.string(), import_zod7.z.array(import_zod7.z.string()), import_zod7.z.boolean()])).optional().describe("Previously collected answers used to resolve dependsOn conditions")
|
|
1320
|
+
},
|
|
1321
|
+
async ({ phase, questions, answers }) => {
|
|
1322
|
+
const adapted = adaptQuestions(questions, answers ?? {});
|
|
1323
|
+
if (adapted.length === 0) {
|
|
1324
|
+
return {
|
|
1325
|
+
content: [
|
|
1326
|
+
{
|
|
1327
|
+
type: "text",
|
|
1328
|
+
text: JSON.stringify({
|
|
1329
|
+
phase,
|
|
1330
|
+
skipped: true,
|
|
1331
|
+
reason: "No questions to present (all filtered by dependsOn conditions)",
|
|
1332
|
+
answers: []
|
|
1333
|
+
})
|
|
1334
|
+
}
|
|
1335
|
+
]
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
return {
|
|
1339
|
+
content: [
|
|
1340
|
+
{
|
|
1341
|
+
type: "text",
|
|
1342
|
+
text: JSON.stringify({
|
|
1343
|
+
phase,
|
|
1344
|
+
adapted_questions: adapted,
|
|
1345
|
+
instruction: "Call ask_user_question with the adapted_questions array below. Pass the array value directly as the questions parameter \u2014 do not stringify it."
|
|
1346
|
+
})
|
|
1347
|
+
}
|
|
1348
|
+
]
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1205
1354
|
// package.json
|
|
1206
1355
|
var package_default = {
|
|
1207
1356
|
dependencies: {
|
|
@@ -1223,7 +1372,7 @@ var package_default = {
|
|
|
1223
1372
|
"test:coverage": "vitest run --coverage"
|
|
1224
1373
|
},
|
|
1225
1374
|
name: "@stackwright-pro/mcp",
|
|
1226
|
-
version: "0.2.0-alpha.
|
|
1375
|
+
version: "0.2.0-alpha.4",
|
|
1227
1376
|
description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
|
|
1228
1377
|
license: "PROPRIETARY",
|
|
1229
1378
|
main: "./dist/server.js",
|
|
@@ -1255,6 +1404,7 @@ registerIsrTools(server);
|
|
|
1255
1404
|
registerDashboardTools(server);
|
|
1256
1405
|
registerClarificationTools(server);
|
|
1257
1406
|
registerPackageTools(server);
|
|
1407
|
+
registerQuestionTools(server);
|
|
1258
1408
|
async function main() {
|
|
1259
1409
|
const transport = new import_stdio.StdioServerTransport();
|
|
1260
1410
|
await server.connect(transport);
|