@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.mjs CHANGED
@@ -1178,6 +1178,155 @@ function setupPackages(opts) {
1178
1178
  }
1179
1179
  }
1180
1180
 
1181
+ // src/tools/questions.ts
1182
+ import { z as z7 } from "zod";
1183
+
1184
+ // src/question-adapter.ts
1185
+ function truncate(str, maxLength) {
1186
+ if (str.length <= maxLength) return str;
1187
+ return str.substring(0, maxLength - 1) + "\u2026";
1188
+ }
1189
+ function generateHeader(id) {
1190
+ const parts = id.split("-");
1191
+ if (parts.length >= 2) {
1192
+ const prefix = parts[0].toUpperCase().substring(0, 4);
1193
+ const num = parts[1];
1194
+ return truncate(`${prefix}-${num}`, 12);
1195
+ }
1196
+ return truncate(
1197
+ id.toUpperCase().replace(/[^A-Z0-9]/g, "").substring(0, 12),
1198
+ 12
1199
+ );
1200
+ }
1201
+ function generateDefaultOptions(type) {
1202
+ switch (type) {
1203
+ case "confirm":
1204
+ return [
1205
+ { label: "Yes", description: "Enable or confirm this option" },
1206
+ { label: "No", description: "Disable or decline this option" }
1207
+ ];
1208
+ case "text":
1209
+ return [
1210
+ { label: "Specify", description: "I will provide a specific value" },
1211
+ { label: "Skip", description: "Use default or skip this question" }
1212
+ ];
1213
+ default:
1214
+ return [
1215
+ { label: "Option 1", description: "First option" },
1216
+ { label: "Option 2", description: "Second option" }
1217
+ ];
1218
+ }
1219
+ }
1220
+ function adaptQuestion(q) {
1221
+ const header = generateHeader(q.id);
1222
+ const multiSelect = q.type === "multi-select";
1223
+ let options;
1224
+ if (q.options && q.options.length >= 2) {
1225
+ options = q.options.map((opt) => ({
1226
+ label: truncate(opt.label, 50),
1227
+ description: opt.value !== opt.label ? opt.value : void 0
1228
+ }));
1229
+ } else if (q.options && q.options.length === 1) {
1230
+ options = [
1231
+ ...q.options.map((opt) => ({ label: truncate(opt.label, 50), description: opt.value })),
1232
+ { label: "Other", description: "Specify a different value" }
1233
+ ];
1234
+ } else {
1235
+ options = generateDefaultOptions(q.type);
1236
+ }
1237
+ if (options.length < 2) {
1238
+ options.push({ label: "Other", description: "Alternative option" });
1239
+ }
1240
+ options = options.slice(0, 6);
1241
+ return {
1242
+ question: q.question + (q.help ? `
1243
+
1244
+ ${q.help}` : ""),
1245
+ header,
1246
+ multi_select: multiSelect,
1247
+ options
1248
+ };
1249
+ }
1250
+ function adaptQuestions(questions, answers = {}) {
1251
+ const adapted = [];
1252
+ for (const q of questions) {
1253
+ if (q.dependsOn) {
1254
+ const dependsAnswer = answers[q.dependsOn.questionId];
1255
+ if (dependsAnswer === void 0) {
1256
+ continue;
1257
+ }
1258
+ const expectedValues = Array.isArray(q.dependsOn.value) ? q.dependsOn.value : [q.dependsOn.value];
1259
+ const answerValue = Array.isArray(dependsAnswer) ? dependsAnswer[0] : dependsAnswer;
1260
+ if (!expectedValues.includes(answerValue)) {
1261
+ continue;
1262
+ }
1263
+ }
1264
+ adapted.push(adaptQuestion(q));
1265
+ }
1266
+ return adapted;
1267
+ }
1268
+
1269
+ // src/tools/questions.ts
1270
+ var ManifestQuestionSchema = z7.object({
1271
+ id: z7.string(),
1272
+ question: z7.string(),
1273
+ type: z7.enum(["text", "select", "multi-select", "confirm"]),
1274
+ required: z7.boolean().optional(),
1275
+ options: z7.array(
1276
+ z7.object({
1277
+ label: z7.string(),
1278
+ value: z7.string()
1279
+ })
1280
+ ).optional(),
1281
+ default: z7.union([z7.string(), z7.boolean(), z7.array(z7.string())]).optional(),
1282
+ help: z7.string().optional(),
1283
+ dependsOn: z7.object({
1284
+ questionId: z7.string(),
1285
+ value: z7.union([z7.string(), z7.array(z7.string())])
1286
+ }).optional()
1287
+ });
1288
+ function registerQuestionTools(server2) {
1289
+ server2.tool(
1290
+ "stackwright_pro_present_phase_questions",
1291
+ "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.",
1292
+ {
1293
+ phase: z7.string().describe('Phase name for display context, e.g. "designer", "api", "auth"'),
1294
+ questions: z7.array(ManifestQuestionSchema).describe("Questions in Question Manifest format as produced by specialist otters"),
1295
+ answers: z7.record(z7.union([z7.string(), z7.array(z7.string()), z7.boolean()])).optional().describe("Previously collected answers used to resolve dependsOn conditions")
1296
+ },
1297
+ async ({ phase, questions, answers }) => {
1298
+ const adapted = adaptQuestions(questions, answers ?? {});
1299
+ if (adapted.length === 0) {
1300
+ return {
1301
+ content: [
1302
+ {
1303
+ type: "text",
1304
+ text: JSON.stringify({
1305
+ phase,
1306
+ skipped: true,
1307
+ reason: "No questions to present (all filtered by dependsOn conditions)",
1308
+ answers: []
1309
+ })
1310
+ }
1311
+ ]
1312
+ };
1313
+ }
1314
+ return {
1315
+ content: [
1316
+ {
1317
+ type: "text",
1318
+ text: JSON.stringify({
1319
+ phase,
1320
+ adapted_questions: adapted,
1321
+ 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."
1322
+ })
1323
+ }
1324
+ ]
1325
+ };
1326
+ }
1327
+ );
1328
+ }
1329
+
1181
1330
  // package.json
1182
1331
  var package_default = {
1183
1332
  dependencies: {
@@ -1199,7 +1348,7 @@ var package_default = {
1199
1348
  "test:coverage": "vitest run --coverage"
1200
1349
  },
1201
1350
  name: "@stackwright-pro/mcp",
1202
- version: "0.2.0-alpha.2",
1351
+ version: "0.2.0-alpha.4",
1203
1352
  description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
1204
1353
  license: "PROPRIETARY",
1205
1354
  main: "./dist/server.js",
@@ -1231,6 +1380,7 @@ registerIsrTools(server);
1231
1380
  registerDashboardTools(server);
1232
1381
  registerClarificationTools(server);
1233
1382
  registerPackageTools(server);
1383
+ registerQuestionTools(server);
1234
1384
  async function main() {
1235
1385
  const transport = new StdioServerTransport();
1236
1386
  await server.connect(transport);