@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 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.2",
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);