@stackwright-pro/mcp 0.2.0-alpha.80 → 0.2.0-alpha.81
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/integrity.js +14 -14
- package/dist/integrity.js.map +1 -1
- package/dist/integrity.mjs +14 -14
- package/dist/integrity.mjs.map +1 -1
- package/dist/server.js +426 -78
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +438 -78
- package/dist/server.mjs.map +1 -1
- package/package.json +5 -3
package/dist/server.mjs
CHANGED
|
@@ -1589,24 +1589,28 @@ import { join as join2 } from "path";
|
|
|
1589
1589
|
var OTTER_NAME_TO_PHASE = [
|
|
1590
1590
|
["designer", "designer"],
|
|
1591
1591
|
["theme", "theme"],
|
|
1592
|
+
["scaffold", "scaffold"],
|
|
1592
1593
|
["api", "api"],
|
|
1593
1594
|
["auth", "auth"],
|
|
1594
1595
|
["dashboard", "dashboard"],
|
|
1595
1596
|
["data", "data"],
|
|
1596
1597
|
["page", "pages"],
|
|
1597
1598
|
["workflow", "workflow"],
|
|
1599
|
+
["services", "services"],
|
|
1598
1600
|
["polish", "polish"],
|
|
1599
1601
|
["geo", "geo"]
|
|
1600
1602
|
];
|
|
1601
1603
|
var PHASE_TO_OTTER = {
|
|
1602
1604
|
designer: "stackwright-pro-designer-otter",
|
|
1603
1605
|
theme: "stackwright-pro-theme-otter",
|
|
1606
|
+
scaffold: "stackwright-pro-scaffold-otter",
|
|
1604
1607
|
api: "stackwright-pro-api-otter",
|
|
1605
1608
|
auth: "stackwright-pro-auth-otter",
|
|
1606
1609
|
pages: "stackwright-pro-page-otter",
|
|
1607
1610
|
dashboard: "stackwright-pro-dashboard-otter",
|
|
1608
1611
|
data: "stackwright-pro-data-otter",
|
|
1609
1612
|
workflow: "stackwright-pro-workflow-otter",
|
|
1613
|
+
services: "stackwright-services-otter",
|
|
1610
1614
|
polish: "stackwright-pro-polish-otter",
|
|
1611
1615
|
geo: "stackwright-pro-geo-otter"
|
|
1612
1616
|
};
|
|
@@ -1991,7 +1995,7 @@ function registerOrchestrationTools(server2) {
|
|
|
1991
1995
|
}
|
|
1992
1996
|
|
|
1993
1997
|
// src/tools/pipeline.ts
|
|
1994
|
-
import { z as
|
|
1998
|
+
import { z as z13 } from "zod";
|
|
1995
1999
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync5, mkdirSync as mkdirSync4, lstatSync as lstatSync5 } from "fs";
|
|
1996
2000
|
import { join as join4 } from "path";
|
|
1997
2001
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -2335,7 +2339,355 @@ function registerArtifactSigningTools(server2) {
|
|
|
2335
2339
|
}
|
|
2336
2340
|
|
|
2337
2341
|
// src/tools/pipeline.ts
|
|
2338
|
-
import { WorkflowFileSchema, authConfigSchema } from "@stackwright-pro/types";
|
|
2342
|
+
import { WorkflowFileSchema, authConfigSchema as authConfigSchema3 } from "@stackwright-pro/types";
|
|
2343
|
+
|
|
2344
|
+
// src/tools/get-schema.ts
|
|
2345
|
+
import { z as z12 } from "zod";
|
|
2346
|
+
import {
|
|
2347
|
+
WorkflowStepSchema as WorkflowStepSchema2,
|
|
2348
|
+
WorkflowDefinitionSchema as WorkflowDefinitionSchema2,
|
|
2349
|
+
WorkflowFieldSchema as WorkflowFieldSchema2,
|
|
2350
|
+
WorkflowActionSchema as WorkflowActionSchema2,
|
|
2351
|
+
authConfigSchema as authConfigSchema2
|
|
2352
|
+
} from "@stackwright-pro/types";
|
|
2353
|
+
|
|
2354
|
+
// src/tools/validate-yaml-fragment.ts
|
|
2355
|
+
import { z as z11 } from "zod";
|
|
2356
|
+
import { load as yamlLoad } from "js-yaml";
|
|
2357
|
+
import {
|
|
2358
|
+
WorkflowStepSchema,
|
|
2359
|
+
WorkflowDefinitionSchema,
|
|
2360
|
+
WorkflowFieldSchema,
|
|
2361
|
+
WorkflowActionSchema,
|
|
2362
|
+
authConfigSchema
|
|
2363
|
+
} from "@stackwright-pro/types";
|
|
2364
|
+
var SUPPORTED_SCHEMA_NAMES = [
|
|
2365
|
+
"workflow_step",
|
|
2366
|
+
"workflow_definition",
|
|
2367
|
+
"workflow_field",
|
|
2368
|
+
"workflow_action",
|
|
2369
|
+
"navigation_item",
|
|
2370
|
+
"auth_config"
|
|
2371
|
+
];
|
|
2372
|
+
var NavigationLinkSchema = z11.lazy(
|
|
2373
|
+
() => z11.object({
|
|
2374
|
+
label: z11.string().min(1),
|
|
2375
|
+
href: z11.string().min(1),
|
|
2376
|
+
children: z11.array(NavigationLinkSchema).optional()
|
|
2377
|
+
})
|
|
2378
|
+
);
|
|
2379
|
+
var NavigationSectionSchema = z11.object({
|
|
2380
|
+
section: z11.string().min(1),
|
|
2381
|
+
items: z11.array(NavigationLinkSchema)
|
|
2382
|
+
});
|
|
2383
|
+
var NavigationItemSchema = z11.union([
|
|
2384
|
+
NavigationLinkSchema,
|
|
2385
|
+
NavigationSectionSchema
|
|
2386
|
+
]);
|
|
2387
|
+
var FIELD_SYNONYMS = {
|
|
2388
|
+
workflow_step: {
|
|
2389
|
+
title: "label",
|
|
2390
|
+
name: "label (at step level, use label: not name:)",
|
|
2391
|
+
description: "message (use message: for step-level descriptive text)",
|
|
2392
|
+
style: 'theme.variant \u2014 use theme: { variant: "primary" } not style: "primary"',
|
|
2393
|
+
transitions: 'on_submit.transition \u2014 use on_submit: { transition: "next_step" } not transitions: [{then:...}]'
|
|
2394
|
+
},
|
|
2395
|
+
workflow_definition: {
|
|
2396
|
+
title: "label",
|
|
2397
|
+
name: "label (workflow-level label, not name:)",
|
|
2398
|
+
description: "description is valid here \u2014 but message: is not (that is a step field)",
|
|
2399
|
+
type: "id (workflows are identified by id:, not type:)"
|
|
2400
|
+
},
|
|
2401
|
+
workflow_field: {
|
|
2402
|
+
id: "name (field-level identifier is name:, NOT id:)",
|
|
2403
|
+
title: "label (field display text is label:, NOT title:)",
|
|
2404
|
+
description: "placeholder or label (no description field on WorkflowField)"
|
|
2405
|
+
},
|
|
2406
|
+
workflow_action: {
|
|
2407
|
+
style: 'theme.variant \u2014 use theme: { variant: "primary" } not style: "primary"',
|
|
2408
|
+
then: "transition (action-level next-step is transition:, NOT then:)",
|
|
2409
|
+
on_click: 'action: "service:..." (extract the service reference from on_click.action)',
|
|
2410
|
+
title: "label (action display text is label:, NOT title:)",
|
|
2411
|
+
name: "label (action display text is label:, NOT name:)"
|
|
2412
|
+
},
|
|
2413
|
+
navigation_item: {
|
|
2414
|
+
children: "items (NavigationSection uses items: not children: \u2014 also use section: instead of label: for section headers)",
|
|
2415
|
+
label: 'section (if this is a nav group/section, use section: "Title" and items: [...], not label:)',
|
|
2416
|
+
title: "section (NavigationSection header field is section:, NOT title:)"
|
|
2417
|
+
},
|
|
2418
|
+
auth_config: {
|
|
2419
|
+
method: 'type \u2014 auth config discriminates on type: "oidc" | "pki", NOT method:',
|
|
2420
|
+
provider_type: 'type \u2014 use type: "oidc" or type: "pki"',
|
|
2421
|
+
strategy: "type \u2014 top-level discriminator is type:, not strategy:"
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2424
|
+
function getSchema(name) {
|
|
2425
|
+
switch (name) {
|
|
2426
|
+
case "workflow_step":
|
|
2427
|
+
return WorkflowStepSchema;
|
|
2428
|
+
case "workflow_definition":
|
|
2429
|
+
return WorkflowDefinitionSchema;
|
|
2430
|
+
case "workflow_field":
|
|
2431
|
+
return WorkflowFieldSchema;
|
|
2432
|
+
case "workflow_action":
|
|
2433
|
+
return WorkflowActionSchema;
|
|
2434
|
+
case "navigation_item":
|
|
2435
|
+
return NavigationItemSchema;
|
|
2436
|
+
case "auth_config":
|
|
2437
|
+
return authConfigSchema;
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
function enrichErrors(issues, synonyms) {
|
|
2441
|
+
return issues.map((issue) => {
|
|
2442
|
+
const pathStr = issue.path.join(".");
|
|
2443
|
+
const lastSegment = issue.path[issue.path.length - 1];
|
|
2444
|
+
const fieldName = typeof lastSegment === "string" ? lastSegment : void 0;
|
|
2445
|
+
const didYouMean = fieldName ? synonyms[fieldName] : void 0;
|
|
2446
|
+
return {
|
|
2447
|
+
path: pathStr || "(root)",
|
|
2448
|
+
message: issue.message,
|
|
2449
|
+
...didYouMean ? { didYouMean } : {}
|
|
2450
|
+
};
|
|
2451
|
+
});
|
|
2452
|
+
}
|
|
2453
|
+
function handleValidateYamlFragment(input) {
|
|
2454
|
+
const { schemaName, yaml } = input;
|
|
2455
|
+
if (!SUPPORTED_SCHEMA_NAMES.includes(schemaName)) {
|
|
2456
|
+
return {
|
|
2457
|
+
valid: false,
|
|
2458
|
+
parseError: `Unknown schemaName: "${schemaName}". Supported: ${SUPPORTED_SCHEMA_NAMES.join(", ")}`
|
|
2459
|
+
};
|
|
2460
|
+
}
|
|
2461
|
+
const name = schemaName;
|
|
2462
|
+
let parsed;
|
|
2463
|
+
try {
|
|
2464
|
+
parsed = yamlLoad(yaml);
|
|
2465
|
+
} catch (err) {
|
|
2466
|
+
return {
|
|
2467
|
+
valid: false,
|
|
2468
|
+
parseError: `YAML parse error: ${err instanceof Error ? err.message : String(err)}`
|
|
2469
|
+
};
|
|
2470
|
+
}
|
|
2471
|
+
const schema = getSchema(name);
|
|
2472
|
+
const result = schema.safeParse(parsed);
|
|
2473
|
+
if (result.success) {
|
|
2474
|
+
return { valid: true };
|
|
2475
|
+
}
|
|
2476
|
+
const synonyms = FIELD_SYNONYMS[name];
|
|
2477
|
+
const errors = enrichErrors(result.error.issues, synonyms);
|
|
2478
|
+
return { valid: false, errors };
|
|
2479
|
+
}
|
|
2480
|
+
function registerValidateYamlFragmentTool(server2) {
|
|
2481
|
+
server2.tool(
|
|
2482
|
+
"stackwright_pro_validate_yaml_fragment",
|
|
2483
|
+
'Validates a YAML snippet against a canonical Zod schema before writing to disk. Returns actionable errors with "did you mean?" suggestions for common field-name drift (title vs label, id vs name, style vs theme.variant, etc.). Call this before stackwright_pro_safe_write to catch schema violations in-session.',
|
|
2484
|
+
{
|
|
2485
|
+
schemaName: z11.enum(SUPPORTED_SCHEMA_NAMES).describe(
|
|
2486
|
+
"Schema to validate against. One of: workflow_step, workflow_definition, workflow_field, workflow_action, navigation_item, auth_config"
|
|
2487
|
+
),
|
|
2488
|
+
yaml: z11.string().describe("YAML string to validate (can also be JSON \u2014 js-yaml parses both)")
|
|
2489
|
+
},
|
|
2490
|
+
async ({ schemaName, yaml }) => {
|
|
2491
|
+
const result = handleValidateYamlFragment({ schemaName, yaml });
|
|
2492
|
+
return {
|
|
2493
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
2494
|
+
};
|
|
2495
|
+
}
|
|
2496
|
+
);
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// src/tools/get-schema.ts
|
|
2500
|
+
var NavigationLinkSchema2 = z12.lazy(
|
|
2501
|
+
() => z12.object({
|
|
2502
|
+
label: z12.string().min(1),
|
|
2503
|
+
href: z12.string().min(1),
|
|
2504
|
+
children: z12.array(NavigationLinkSchema2).optional()
|
|
2505
|
+
})
|
|
2506
|
+
);
|
|
2507
|
+
var NavigationSectionSchema2 = z12.object({
|
|
2508
|
+
section: z12.string().min(1),
|
|
2509
|
+
items: z12.array(NavigationLinkSchema2)
|
|
2510
|
+
});
|
|
2511
|
+
var NavigationItemSchema2 = z12.union([
|
|
2512
|
+
NavigationLinkSchema2,
|
|
2513
|
+
NavigationSectionSchema2
|
|
2514
|
+
]);
|
|
2515
|
+
function getZodSchema(name) {
|
|
2516
|
+
switch (name) {
|
|
2517
|
+
case "workflow_step":
|
|
2518
|
+
return WorkflowStepSchema2;
|
|
2519
|
+
case "workflow_definition":
|
|
2520
|
+
return WorkflowDefinitionSchema2;
|
|
2521
|
+
case "workflow_field":
|
|
2522
|
+
return WorkflowFieldSchema2;
|
|
2523
|
+
case "workflow_action":
|
|
2524
|
+
return WorkflowActionSchema2;
|
|
2525
|
+
case "navigation_item":
|
|
2526
|
+
return NavigationItemSchema2;
|
|
2527
|
+
case "auth_config":
|
|
2528
|
+
return authConfigSchema2;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
function formatType(node, depth = 0) {
|
|
2532
|
+
if (node.const !== void 0) return JSON.stringify(node.const);
|
|
2533
|
+
if (node.enum) return node.enum.map((v) => JSON.stringify(v)).join(" | ");
|
|
2534
|
+
if (node.oneOf || node.anyOf) {
|
|
2535
|
+
const branches = node.oneOf ?? node.anyOf ?? [];
|
|
2536
|
+
return branches.map((b) => {
|
|
2537
|
+
const disc = b.properties ? Object.entries(b.properties).filter(([, v]) => v.const !== void 0).map(([k, v]) => `${k}: ${JSON.stringify(v.const)}`).join(", ") : "";
|
|
2538
|
+
return disc ? `{ ${disc}, ... }` : "{ ... }";
|
|
2539
|
+
}).join(" | ");
|
|
2540
|
+
}
|
|
2541
|
+
if (node.type === "array" && node.items) {
|
|
2542
|
+
return `${formatType(node.items, depth)}[]`;
|
|
2543
|
+
}
|
|
2544
|
+
if (node.type === "object" && node.properties && depth < 2) {
|
|
2545
|
+
const inner = Object.entries(node.properties).map(([k, v]) => `${k}: ${formatType(v, depth + 1)}`).join(", ");
|
|
2546
|
+
return `{ ${inner} }`;
|
|
2547
|
+
}
|
|
2548
|
+
const base = Array.isArray(node.type) ? node.type.join(" | ") : node.type ?? "unknown";
|
|
2549
|
+
const constraints = [];
|
|
2550
|
+
if (node.maxLength !== void 0) constraints.push(`max ${node.maxLength} chars`);
|
|
2551
|
+
if (node.minLength !== void 0) constraints.push(`min ${node.minLength} chars`);
|
|
2552
|
+
if (node.pattern) constraints.push(`pattern: ${node.pattern}`);
|
|
2553
|
+
if (node.minimum !== void 0) constraints.push(`min ${node.minimum}`);
|
|
2554
|
+
if (node.maximum !== void 0) constraints.push(`max ${node.maximum}`);
|
|
2555
|
+
return constraints.length > 0 ? `${base} (${constraints.join(", ")})` : base;
|
|
2556
|
+
}
|
|
2557
|
+
function formatObjectSchema(node, schemaName, synonyms) {
|
|
2558
|
+
const lines = [];
|
|
2559
|
+
const displayName = schemaName.split("_").map((w) => w[0].toUpperCase() + w.slice(1)).join("");
|
|
2560
|
+
lines.push(`${displayName}:`);
|
|
2561
|
+
if (node.oneOf || node.anyOf) {
|
|
2562
|
+
const branches = node.oneOf ?? node.anyOf ?? [];
|
|
2563
|
+
lines.push(" Discriminated union \u2014 choose one variant:");
|
|
2564
|
+
for (const branch of branches) {
|
|
2565
|
+
const req = new Set(branch.required ?? []);
|
|
2566
|
+
const disc = Object.entries(branch.properties ?? {}).filter(([, v]) => v.const !== void 0).map(([k, v]) => `${k}: ${JSON.stringify(v.const)}`).join(", ");
|
|
2567
|
+
lines.push(` VARIANT (${disc}):`);
|
|
2568
|
+
for (const [field, fieldNode] of Object.entries(branch.properties ?? {})) {
|
|
2569
|
+
if (fieldNode.const !== void 0) continue;
|
|
2570
|
+
const isRequired = req.has(field);
|
|
2571
|
+
const hint = synonyms[field] ? ` -- WARNING: use ${field}: not ${synonyms[field]}` : "";
|
|
2572
|
+
lines.push(
|
|
2573
|
+
` ${isRequired ? "REQUIRED" : "optional"}: ${field}: ${formatType(fieldNode)}${hint}`
|
|
2574
|
+
);
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
return lines.join("\n");
|
|
2578
|
+
}
|
|
2579
|
+
const required = new Set(node.required ?? []);
|
|
2580
|
+
const properties = node.properties ?? {};
|
|
2581
|
+
const requiredFields = Object.entries(properties).filter(([k]) => required.has(k));
|
|
2582
|
+
const optionalFields = Object.entries(properties).filter(([k]) => !required.has(k));
|
|
2583
|
+
if (requiredFields.length > 0) {
|
|
2584
|
+
lines.push(" REQUIRED:");
|
|
2585
|
+
for (const [field, fieldNode] of requiredFields) {
|
|
2586
|
+
const typeStr = formatType(fieldNode);
|
|
2587
|
+
const warn = synonyms[field] ? ` -- CAUTION: this schema uses ${field}` : "";
|
|
2588
|
+
lines.push(` ${field}: ${typeStr}${warn}`);
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
if (optionalFields.length > 0) {
|
|
2592
|
+
lines.push(" OPTIONAL:");
|
|
2593
|
+
for (const [field, fieldNode] of optionalFields) {
|
|
2594
|
+
const typeStr = formatType(fieldNode);
|
|
2595
|
+
lines.push(` ${field}: ${typeStr}`);
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
return lines.join("\n");
|
|
2599
|
+
}
|
|
2600
|
+
function handleGetSchema(input) {
|
|
2601
|
+
const { schemaName } = input;
|
|
2602
|
+
if (!SUPPORTED_SCHEMA_NAMES.includes(schemaName)) {
|
|
2603
|
+
return {
|
|
2604
|
+
error: `Unknown schemaName: "${schemaName}". Supported: ${SUPPORTED_SCHEMA_NAMES.join(", ")}`
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
const name = schemaName;
|
|
2608
|
+
const schema = getZodSchema(name);
|
|
2609
|
+
const synonyms = FIELD_SYNONYMS[name];
|
|
2610
|
+
let jsonSchema;
|
|
2611
|
+
try {
|
|
2612
|
+
const raw = z12.toJSONSchema(schema, { unrepresentable: "any" });
|
|
2613
|
+
jsonSchema = raw;
|
|
2614
|
+
} catch {
|
|
2615
|
+
jsonSchema = { type: "object", description: "Schema introspection unavailable for this type" };
|
|
2616
|
+
}
|
|
2617
|
+
const summary = formatObjectSchema(jsonSchema, name, synonyms);
|
|
2618
|
+
const synonymWarnings = Object.entries(synonyms).map(
|
|
2619
|
+
([wrong, correct]) => ` WARNING: use "${correct}" \u2014 NOT "${wrong}"`
|
|
2620
|
+
);
|
|
2621
|
+
const fullText = [
|
|
2622
|
+
summary,
|
|
2623
|
+
"",
|
|
2624
|
+
"FIELD NAME WARNINGS (common drift patterns):",
|
|
2625
|
+
...synonymWarnings
|
|
2626
|
+
].join("\n");
|
|
2627
|
+
const tokenEstimate = Math.ceil(fullText.length / 4);
|
|
2628
|
+
return {
|
|
2629
|
+
schemaName: name,
|
|
2630
|
+
summary,
|
|
2631
|
+
synonymWarnings,
|
|
2632
|
+
tokenEstimate
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
var PHASE_SCHEMA_NAMES = {
|
|
2636
|
+
workflow: ["workflow_step", "workflow_definition", "workflow_field", "workflow_action"],
|
|
2637
|
+
pages: ["navigation_item"],
|
|
2638
|
+
dashboard: ["navigation_item"],
|
|
2639
|
+
polish: ["navigation_item"],
|
|
2640
|
+
auth: ["auth_config"]
|
|
2641
|
+
};
|
|
2642
|
+
function buildSchemaReferenceBlock(phase) {
|
|
2643
|
+
const schemaNames = PHASE_SCHEMA_NAMES[phase];
|
|
2644
|
+
if (!schemaNames || schemaNames.length === 0) return null;
|
|
2645
|
+
const sections = [
|
|
2646
|
+
"CANONICAL_SCHEMA_REFERENCE (authoritative \u2014 use exact field names below):",
|
|
2647
|
+
""
|
|
2648
|
+
];
|
|
2649
|
+
for (const name of schemaNames) {
|
|
2650
|
+
const result = handleGetSchema({ schemaName: name });
|
|
2651
|
+
if ("error" in result) continue;
|
|
2652
|
+
sections.push(result.summary);
|
|
2653
|
+
if (result.synonymWarnings.length > 0) {
|
|
2654
|
+
sections.push(" Common mistakes to avoid:");
|
|
2655
|
+
sections.push(...result.synonymWarnings);
|
|
2656
|
+
}
|
|
2657
|
+
sections.push("");
|
|
2658
|
+
}
|
|
2659
|
+
return sections.join("\n");
|
|
2660
|
+
}
|
|
2661
|
+
function registerGetSchemaTool(server2) {
|
|
2662
|
+
server2.tool(
|
|
2663
|
+
"stackwright_pro_get_schema",
|
|
2664
|
+
'Returns a compact, LLM-friendly summary of a canonical schema derived programmatically from Zod. Includes required/optional fields, types, constraints, and "did you mean?" warnings for common field-name drift. Use before authoring YAML to confirm exact field names.',
|
|
2665
|
+
{
|
|
2666
|
+
schemaName: z12.enum(SUPPORTED_SCHEMA_NAMES).describe(
|
|
2667
|
+
"Schema to summarize. One of: workflow_step, workflow_definition, workflow_field, workflow_action, navigation_item, auth_config"
|
|
2668
|
+
)
|
|
2669
|
+
},
|
|
2670
|
+
async ({ schemaName }) => {
|
|
2671
|
+
const result = handleGetSchema({ schemaName });
|
|
2672
|
+
if ("error" in result) {
|
|
2673
|
+
return {
|
|
2674
|
+
content: [{ type: "text", text: JSON.stringify({ error: result.error }) }],
|
|
2675
|
+
isError: true
|
|
2676
|
+
};
|
|
2677
|
+
}
|
|
2678
|
+
return {
|
|
2679
|
+
content: [
|
|
2680
|
+
{
|
|
2681
|
+
type: "text",
|
|
2682
|
+
text: JSON.stringify(result, null, 2)
|
|
2683
|
+
}
|
|
2684
|
+
]
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
);
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
// src/tools/pipeline.ts
|
|
2339
2691
|
var PHASE_ORDER = [
|
|
2340
2692
|
"designer",
|
|
2341
2693
|
"theme",
|
|
@@ -2903,6 +3255,10 @@ ${JSON.stringify(content, null, 2)}`
|
|
|
2903
3255
|
const artifactSchema = PHASE_ARTIFACT_SCHEMA[phase];
|
|
2904
3256
|
parts.push("", "REQUIRED_ARTIFACT_SCHEMA:");
|
|
2905
3257
|
parts.push(artifactSchema);
|
|
3258
|
+
const schemaRef = buildSchemaReferenceBlock(phase);
|
|
3259
|
+
if (schemaRef) {
|
|
3260
|
+
parts.push("", schemaRef);
|
|
3261
|
+
}
|
|
2906
3262
|
parts.push("", "Execute using these answers and the upstream artifacts provided.");
|
|
2907
3263
|
const prompt = parts.join("\n");
|
|
2908
3264
|
const dependenciesSatisfied = missingDependencies.length === 0;
|
|
@@ -3287,7 +3643,7 @@ function handleValidateArtifact(input) {
|
|
|
3287
3643
|
auth: (artifact2) => {
|
|
3288
3644
|
const authConfig = artifact2["authConfig"];
|
|
3289
3645
|
if (!authConfig) return { success: true };
|
|
3290
|
-
const result =
|
|
3646
|
+
const result = authConfigSchema3.safeParse(authConfig);
|
|
3291
3647
|
if (!result.success) {
|
|
3292
3648
|
const issues = result.error.issues.slice(0, 3).map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
3293
3649
|
return { success: false, error: { message: issues } };
|
|
@@ -3359,21 +3715,21 @@ function registerPipelineTools(server2) {
|
|
|
3359
3715
|
"stackwright_pro_set_pipeline_state",
|
|
3360
3716
|
`Atomic read\u2192modify\u2192write pipeline state. ${DESC}`,
|
|
3361
3717
|
{
|
|
3362
|
-
phase:
|
|
3363
|
-
field:
|
|
3364
|
-
value: boolCoerce(
|
|
3718
|
+
phase: z13.string().optional().describe('Phase to update, e.g. "designer"'),
|
|
3719
|
+
field: z13.enum(["questionsCollected", "answered", "executed", "artifactWritten"]).optional().describe("Boolean field to set"),
|
|
3720
|
+
value: boolCoerce(z13.boolean().optional()).describe(
|
|
3365
3721
|
'Value for the field \u2014 must be a JSON boolean (true/false), NOT the string "true"/"false"'
|
|
3366
3722
|
),
|
|
3367
|
-
status:
|
|
3368
|
-
incrementRetry: boolCoerce(
|
|
3723
|
+
status: z13.enum(["setup", "questions", "execution", "done"]).optional().describe("Top-level status override"),
|
|
3724
|
+
incrementRetry: boolCoerce(z13.boolean().optional()).describe(
|
|
3369
3725
|
"Bump retryCount by 1 \u2014 must be a JSON boolean"
|
|
3370
3726
|
),
|
|
3371
3727
|
updates: jsonCoerce(
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
phase:
|
|
3375
|
-
field:
|
|
3376
|
-
value:
|
|
3728
|
+
z13.array(
|
|
3729
|
+
z13.object({
|
|
3730
|
+
phase: z13.string(),
|
|
3731
|
+
field: z13.enum(["questionsCollected", "answered", "executed", "artifactWritten"]),
|
|
3732
|
+
value: z13.boolean()
|
|
3377
3733
|
})
|
|
3378
3734
|
).optional()
|
|
3379
3735
|
).describe("Batch updates \u2014 apply multiple field changes in one atomic read\u2192modify\u2192write")
|
|
@@ -3393,7 +3749,7 @@ function registerPipelineTools(server2) {
|
|
|
3393
3749
|
"stackwright_pro_check_execution_ready",
|
|
3394
3750
|
`Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC}`,
|
|
3395
3751
|
{
|
|
3396
|
-
phase:
|
|
3752
|
+
phase: z13.string().optional().describe("If provided, check only this phase's readiness. Omit to check all phases.")
|
|
3397
3753
|
},
|
|
3398
3754
|
async ({ phase }) => res(handleCheckExecutionReady(void 0, phase))
|
|
3399
3755
|
);
|
|
@@ -3413,9 +3769,9 @@ function registerPipelineTools(server2) {
|
|
|
3413
3769
|
"stackwright_pro_write_phase_questions",
|
|
3414
3770
|
`Parse otter question-collection response \u2192 .stackwright/questions/{phase}.json. Specialists may also call this directly with a parsed questions array. ${DESC}`,
|
|
3415
3771
|
{
|
|
3416
|
-
phase:
|
|
3417
|
-
responseText:
|
|
3418
|
-
questions: jsonCoerce(
|
|
3772
|
+
phase: z13.string().optional().describe('Phase name, e.g. "designer" (required for direct write)'),
|
|
3773
|
+
responseText: z13.string().optional().describe("Raw LLM response from QUESTION_COLLECTION_MODE"),
|
|
3774
|
+
questions: jsonCoerce(z13.array(z13.any()).optional()).describe(
|
|
3419
3775
|
"Questions array for direct specialist write"
|
|
3420
3776
|
)
|
|
3421
3777
|
},
|
|
@@ -3457,16 +3813,16 @@ function registerPipelineTools(server2) {
|
|
|
3457
3813
|
server2.tool(
|
|
3458
3814
|
"stackwright_pro_build_specialist_prompt",
|
|
3459
3815
|
`Assemble execution prompt from answers + upstream artifacts. Foreman passes verbatim. ${DESC}`,
|
|
3460
|
-
{ phase:
|
|
3816
|
+
{ phase: z13.string().describe('Phase to build prompt for, e.g. "pages"') },
|
|
3461
3817
|
async ({ phase }) => res(handleBuildSpecialistPrompt({ phase }))
|
|
3462
3818
|
);
|
|
3463
3819
|
server2.tool(
|
|
3464
3820
|
"stackwright_pro_validate_artifact",
|
|
3465
3821
|
`Validate and write artifact to .stackwright/artifacts/. Returns retryPrompt on failure. ${DESC}`,
|
|
3466
3822
|
{
|
|
3467
|
-
phase:
|
|
3468
|
-
responseText:
|
|
3469
|
-
artifact: jsonCoerce(
|
|
3823
|
+
phase: z13.string().describe('Phase that produced this artifact, e.g. "designer"'),
|
|
3824
|
+
responseText: z13.string().optional().describe("Raw response text from the specialist otter (Foreman-mediated path, legacy)"),
|
|
3825
|
+
artifact: jsonCoerce(z13.record(z13.string(), z13.unknown()).optional()).describe(
|
|
3470
3826
|
"Artifact object to validate and write directly (specialist direct path \u2014 skips off-script detection and JSON parsing)"
|
|
3471
3827
|
)
|
|
3472
3828
|
},
|
|
@@ -3482,7 +3838,7 @@ function registerPipelineTools(server2) {
|
|
|
3482
3838
|
}
|
|
3483
3839
|
|
|
3484
3840
|
// src/tools/safe-write.ts
|
|
3485
|
-
import { z as
|
|
3841
|
+
import { z as z14 } from "zod";
|
|
3486
3842
|
import { writeFileSync as writeFileSync5, readFileSync as readFileSync5, existsSync as existsSync6, mkdirSync as mkdirSync5, lstatSync as lstatSync6 } from "fs";
|
|
3487
3843
|
import { normalize, isAbsolute, dirname, join as join5 } from "path";
|
|
3488
3844
|
var OTTER_WRITE_ALLOWLISTS = {
|
|
@@ -3882,10 +4238,10 @@ function registerSafeWriteTools(server2) {
|
|
|
3882
4238
|
"stackwright_pro_safe_write",
|
|
3883
4239
|
DESC,
|
|
3884
4240
|
{
|
|
3885
|
-
callerOtter:
|
|
3886
|
-
filePath:
|
|
3887
|
-
content:
|
|
3888
|
-
createDirectories: boolCoerce(
|
|
4241
|
+
callerOtter: z14.string().describe('The otter agent name requesting the write, e.g. "stackwright-pro-page-otter"'),
|
|
4242
|
+
filePath: z14.string().describe('Relative path from project root, e.g. "pages/dashboard/content.yml"'),
|
|
4243
|
+
content: z14.string().describe("File content to write"),
|
|
4244
|
+
createDirectories: boolCoerce(z14.boolean().optional().default(true)).describe(
|
|
3889
4245
|
"Create parent directories if they don't exist. Default: true"
|
|
3890
4246
|
)
|
|
3891
4247
|
},
|
|
@@ -3902,7 +4258,7 @@ function registerSafeWriteTools(server2) {
|
|
|
3902
4258
|
}
|
|
3903
4259
|
|
|
3904
4260
|
// src/tools/auth.ts
|
|
3905
|
-
import { z as
|
|
4261
|
+
import { z as z15 } from "zod";
|
|
3906
4262
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync7, mkdirSync as mkdirSync6 } from "fs";
|
|
3907
4263
|
import { join as join6 } from "path";
|
|
3908
4264
|
function buildHierarchy(roles) {
|
|
@@ -4774,38 +5130,38 @@ function registerAuthTools(server2) {
|
|
|
4774
5130
|
"stackwright_pro_configure_auth",
|
|
4775
5131
|
"Generate authentication middleware and configuration for a Next.js Stackwright application. Writes `middleware.ts` from a secure template, appends/updates the `auth:` section in `stackwright.yml`, and generates `.env.example` with required environment variables. \u26A0\uFE0F For CAC/PKI: generated `middleware.ts` carries a SECURITY REVIEW REQUIRED comment \u2014 certificate chain validation must be verified by a DoD security officer before production deployment. This is the ONLY approved path to generating `middleware.ts`. Never write TypeScript auth files directly.",
|
|
4776
5132
|
{
|
|
4777
|
-
method:
|
|
4778
|
-
provider:
|
|
5133
|
+
method: z15.enum(["cac", "oidc", "oauth2", "none"]),
|
|
5134
|
+
provider: z15.enum(["azure-ad", "okta", "ping", "cognito", "custom"]).optional(),
|
|
4779
5135
|
// CAC
|
|
4780
|
-
cacCaBundle:
|
|
4781
|
-
cacEdipiLookup:
|
|
4782
|
-
cacOcspEndpoint:
|
|
4783
|
-
cacCertHeader:
|
|
5136
|
+
cacCaBundle: z15.string().optional(),
|
|
5137
|
+
cacEdipiLookup: z15.string().optional(),
|
|
5138
|
+
cacOcspEndpoint: z15.string().optional(),
|
|
5139
|
+
cacCertHeader: z15.string().optional(),
|
|
4784
5140
|
// OIDC
|
|
4785
|
-
oidcDiscoveryUrl:
|
|
4786
|
-
oidcClientId:
|
|
4787
|
-
oidcClientSecret:
|
|
4788
|
-
oidcScopes:
|
|
4789
|
-
oidcRoleClaim:
|
|
5141
|
+
oidcDiscoveryUrl: z15.string().optional(),
|
|
5142
|
+
oidcClientId: z15.string().optional(),
|
|
5143
|
+
oidcClientSecret: z15.string().optional(),
|
|
5144
|
+
oidcScopes: z15.string().optional(),
|
|
5145
|
+
oidcRoleClaim: z15.string().optional(),
|
|
4790
5146
|
// OAuth2
|
|
4791
|
-
oauth2AuthUrl:
|
|
4792
|
-
oauth2TokenUrl:
|
|
4793
|
-
oauth2ClientId:
|
|
4794
|
-
oauth2ClientSecret:
|
|
4795
|
-
oauth2Scopes:
|
|
5147
|
+
oauth2AuthUrl: z15.string().optional(),
|
|
5148
|
+
oauth2TokenUrl: z15.string().optional(),
|
|
5149
|
+
oauth2ClientId: z15.string().optional(),
|
|
5150
|
+
oauth2ClientSecret: z15.string().optional(),
|
|
5151
|
+
oauth2Scopes: z15.string().optional(),
|
|
4796
5152
|
// RBAC
|
|
4797
|
-
rbacRoles: jsonCoerce(
|
|
4798
|
-
rbacDefaultRole:
|
|
5153
|
+
rbacRoles: jsonCoerce(z15.array(z15.string()).optional()),
|
|
5154
|
+
rbacDefaultRole: z15.string().optional(),
|
|
4799
5155
|
// Audit
|
|
4800
|
-
auditEnabled: boolCoerce(
|
|
4801
|
-
auditRetentionDays: numCoerce(
|
|
5156
|
+
auditEnabled: boolCoerce(z15.boolean().optional()),
|
|
5157
|
+
auditRetentionDays: numCoerce(z15.number().int().positive().optional()),
|
|
4802
5158
|
// Routes
|
|
4803
|
-
protectedRoutes: jsonCoerce(
|
|
5159
|
+
protectedRoutes: jsonCoerce(z15.array(z15.string()).optional()),
|
|
4804
5160
|
// Injection for tests
|
|
4805
|
-
_cwd:
|
|
4806
|
-
devOnly: boolCoerce(
|
|
4807
|
-
mockUsers: jsonCoerce(
|
|
4808
|
-
nextMajorVersion: numCoerce(
|
|
5161
|
+
_cwd: z15.string().optional(),
|
|
5162
|
+
devOnly: boolCoerce(z15.boolean().optional()),
|
|
5163
|
+
mockUsers: jsonCoerce(z15.array(z15.object({ name: z15.string(), email: z15.string() })).optional()),
|
|
5164
|
+
nextMajorVersion: numCoerce(z15.number().int().positive().optional())
|
|
4809
5165
|
},
|
|
4810
5166
|
async (params) => {
|
|
4811
5167
|
const cwd = params._cwd ?? process.cwd();
|
|
@@ -4821,59 +5177,59 @@ import { join as join7, basename } from "path";
|
|
|
4821
5177
|
var _checksums = /* @__PURE__ */ new Map([
|
|
4822
5178
|
[
|
|
4823
5179
|
"stackwright-pro-api-otter.json",
|
|
4824
|
-
"
|
|
5180
|
+
"1610b34c2bfd89aa18ef62fe052fe5aaba21cb2aa9c5d58a4fff06af2a1f0e6e"
|
|
4825
5181
|
],
|
|
4826
5182
|
[
|
|
4827
5183
|
"stackwright-pro-auth-otter.json",
|
|
4828
|
-
"
|
|
5184
|
+
"5a876d3614e62a7817e69bbe7fe7cc6976035ccaa0e7c29fb1e1a32caf8cea93"
|
|
4829
5185
|
],
|
|
4830
5186
|
[
|
|
4831
5187
|
"stackwright-pro-dashboard-otter.json",
|
|
4832
|
-
"
|
|
5188
|
+
"9550e565fb467d7956cf6b50e7b30a481e6e4b26d609dfe1f0d8f991fc6681de"
|
|
4833
5189
|
],
|
|
4834
5190
|
[
|
|
4835
5191
|
"stackwright-pro-data-otter.json",
|
|
4836
|
-
"
|
|
5192
|
+
"5cd8caca50bfcc00ebaf1f9a83158e5580e0e51d25495244f8465d9c20f31e17"
|
|
4837
5193
|
],
|
|
4838
5194
|
[
|
|
4839
5195
|
"stackwright-pro-designer-otter.json",
|
|
4840
|
-
"
|
|
5196
|
+
"d44b307299c2b65568a708920b819eec7d3b5fe1191ace24b166cbfb2d6e5209"
|
|
4841
5197
|
],
|
|
4842
5198
|
[
|
|
4843
5199
|
"stackwright-pro-domain-expert-otter.json",
|
|
4844
|
-
"
|
|
5200
|
+
"dc060aacdf67ee5758921c72225aa669a76cb962f0f8eedf1741f58f18e870d3"
|
|
4845
5201
|
],
|
|
4846
5202
|
[
|
|
4847
5203
|
"stackwright-pro-foreman-otter.json",
|
|
4848
|
-
"
|
|
5204
|
+
"ab3d821d9217ccbe112d68ce25798bfe637aef15814168037caa2a98994e8d2d"
|
|
4849
5205
|
],
|
|
4850
5206
|
[
|
|
4851
5207
|
"stackwright-pro-geo-otter.json",
|
|
4852
|
-
"
|
|
5208
|
+
"3c9fc96e79d9ac22be8a293cf3ec904c4ed033842864107515aacdf71285791c"
|
|
4853
5209
|
],
|
|
4854
5210
|
[
|
|
4855
5211
|
"stackwright-pro-page-otter.json",
|
|
4856
|
-
"
|
|
5212
|
+
"0057ea97f7c2e33a8673140f59a0237eb627d82c676af3fae4faa31033598e03"
|
|
4857
5213
|
],
|
|
4858
5214
|
[
|
|
4859
5215
|
"stackwright-pro-polish-otter.json",
|
|
4860
|
-
"
|
|
5216
|
+
"1e534dfbc5644a5efbc566d77b512929760715365d54ce030da177a535c23ea6"
|
|
4861
5217
|
],
|
|
4862
5218
|
[
|
|
4863
5219
|
"stackwright-pro-scaffold-otter.json",
|
|
4864
|
-
"
|
|
5220
|
+
"2ed0adb316aaecb849153d44f52b177de539f21d4a7ce5ae4cc1c3c7470e15d4"
|
|
4865
5221
|
],
|
|
4866
5222
|
[
|
|
4867
5223
|
"stackwright-pro-theme-otter.json",
|
|
4868
|
-
"
|
|
5224
|
+
"730bc16b24b4612552389fe9de662f233044bcbf5ef1e0f27f2cc1e1af4c989f"
|
|
4869
5225
|
],
|
|
4870
5226
|
[
|
|
4871
5227
|
"stackwright-pro-workflow-otter.json",
|
|
4872
|
-
"
|
|
5228
|
+
"8ece2a1f1ec30163600b5ce8b666c915ab0d00a1fa70c38ed58d1bb20cbd9979"
|
|
4873
5229
|
],
|
|
4874
5230
|
[
|
|
4875
5231
|
"stackwright-services-otter.json",
|
|
4876
|
-
"
|
|
5232
|
+
"2a36a07eaf34b59a2dab7059f3748a5742ff1f6b80b4bd6a739c59cf114703d6"
|
|
4877
5233
|
]
|
|
4878
5234
|
]);
|
|
4879
5235
|
Object.freeze(_checksums);
|
|
@@ -5089,7 +5445,7 @@ function registerIntegrityTools(server2) {
|
|
|
5089
5445
|
}
|
|
5090
5446
|
|
|
5091
5447
|
// src/tools/domain.ts
|
|
5092
|
-
import { z as
|
|
5448
|
+
import { z as z16 } from "zod";
|
|
5093
5449
|
import { readFileSync as readFileSync8, existsSync as existsSync8 } from "fs";
|
|
5094
5450
|
import { join as join8 } from "path";
|
|
5095
5451
|
function handleListCollections(input) {
|
|
@@ -5475,7 +5831,7 @@ function registerDomainTools(server2) {
|
|
|
5475
5831
|
"stackwright_pro_resolve_data_strategy",
|
|
5476
5832
|
"Look up the data freshness strategy configuration from the user's answer. Returns mechanism, revalidation seconds, required packages, and the exact MCP tool call to make. Replaces the strategy table in the data-otter prompt.",
|
|
5477
5833
|
{
|
|
5478
|
-
strategy:
|
|
5834
|
+
strategy: z16.string().describe(
|
|
5479
5835
|
'The data-1 answer value: "pulse-fast", "isr-fast", "isr-standard", or "isr-slow"'
|
|
5480
5836
|
)
|
|
5481
5837
|
},
|
|
@@ -5485,7 +5841,7 @@ function registerDomainTools(server2) {
|
|
|
5485
5841
|
"stackwright_pro_validate_workflow",
|
|
5486
5842
|
"Validate a workflow definition against the Stackwright workflow schema. Checks step ID uniqueness, transition targets, terminal state existence, and service references. Call this after the workflow otter produces output.",
|
|
5487
5843
|
{
|
|
5488
|
-
workflow: jsonCoerce(
|
|
5844
|
+
workflow: jsonCoerce(z16.record(z16.string(), z16.unknown()).optional()).describe(
|
|
5489
5845
|
"Parsed workflow object. If omitted, reads from .stackwright/artifacts/workflow-config.json"
|
|
5490
5846
|
)
|
|
5491
5847
|
},
|
|
@@ -5494,7 +5850,7 @@ function registerDomainTools(server2) {
|
|
|
5494
5850
|
}
|
|
5495
5851
|
|
|
5496
5852
|
// src/tools/type-schemas.ts
|
|
5497
|
-
import { z as
|
|
5853
|
+
import { z as z17 } from "zod";
|
|
5498
5854
|
function buildTypeSchemaSummary() {
|
|
5499
5855
|
return {
|
|
5500
5856
|
version: "1.0",
|
|
@@ -5571,7 +5927,7 @@ function registerTypeSchemasTool(server2) {
|
|
|
5571
5927
|
"stackwright_pro_get_type_schemas",
|
|
5572
5928
|
"Returns a structured summary of all canonical @stackwright-pro/types schemas, organized by domain. Use this to determine which otter owns a given schema and what artifact key to expect.",
|
|
5573
5929
|
{
|
|
5574
|
-
format:
|
|
5930
|
+
format: z17.enum(["full", "domains-only"]).optional().default("full").describe("full = complete summary with all fields; domains-only = just domain names")
|
|
5575
5931
|
},
|
|
5576
5932
|
async ({ format }) => {
|
|
5577
5933
|
const summary = buildTypeSchemaSummary();
|
|
@@ -5769,7 +6125,7 @@ function registerScaffoldCleanupTools(server2) {
|
|
|
5769
6125
|
}
|
|
5770
6126
|
|
|
5771
6127
|
// src/tools/contrast.ts
|
|
5772
|
-
import { z as
|
|
6128
|
+
import { z as z18 } from "zod";
|
|
5773
6129
|
function linearizeChannel(c255) {
|
|
5774
6130
|
const c = c255 / 255;
|
|
5775
6131
|
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
@@ -5941,8 +6297,8 @@ function registerContrastTools(server2) {
|
|
|
5941
6297
|
"stackwright_pro_check_contrast",
|
|
5942
6298
|
'Compute the exact WCAG 2.1 contrast ratio between a foreground and background color. Returns the ratio and AA/AAA pass/fail flags. Use this to verify any foreground/background color pair before writing it to the token set. Accepts #RGB, #RRGGBB, hsl(...), or shadcn HSL format ("H S% L%").',
|
|
5943
6299
|
{
|
|
5944
|
-
fg:
|
|
5945
|
-
bg:
|
|
6300
|
+
fg: z18.string().describe("Foreground (text) color \u2014 hex or HSL"),
|
|
6301
|
+
bg: z18.string().describe("Background color \u2014 hex or HSL")
|
|
5946
6302
|
},
|
|
5947
6303
|
async ({ fg, bg }) => {
|
|
5948
6304
|
let result;
|
|
@@ -5972,8 +6328,8 @@ function registerContrastTools(server2) {
|
|
|
5972
6328
|
"stackwright_pro_derive_accessible_palette",
|
|
5973
6329
|
'Given a seed color (treated as a background), derive the best accessible foreground (text) color that meets the target contrast ratio. Evaluates #ffffff and #000000 against the seed and picks whichever satisfies the target ratio with the highest contrast. Use this for every {name}-foreground token derivation instead of guessing white vs black. Accepts #RGB, #RRGGBB, hsl(...), or shadcn HSL format ("H S% L%").',
|
|
5974
6330
|
{
|
|
5975
|
-
seed:
|
|
5976
|
-
targetRatio: numCoerce(
|
|
6331
|
+
seed: z18.string().describe("Background (seed) color \u2014 hex or HSL"),
|
|
6332
|
+
targetRatio: numCoerce(z18.number().default(4.5)).describe(
|
|
5977
6333
|
"Minimum required contrast ratio (default 4.5 for WCAG AA)"
|
|
5978
6334
|
)
|
|
5979
6335
|
},
|
|
@@ -6010,9 +6366,11 @@ function registerContrastTools(server2) {
|
|
|
6010
6366
|
// package.json
|
|
6011
6367
|
var package_default = {
|
|
6012
6368
|
dependencies: {
|
|
6013
|
-
"@stackwright-pro/types": "workspace:*",
|
|
6014
6369
|
"@modelcontextprotocol/sdk": "^1.10.0",
|
|
6015
6370
|
"@stackwright-pro/cli-data-explorer": "workspace:*",
|
|
6371
|
+
"@stackwright-pro/types": "workspace:*",
|
|
6372
|
+
"@types/js-yaml": "^4.0.9",
|
|
6373
|
+
"js-yaml": "^4.2.0",
|
|
6016
6374
|
zod: "^4.4.3"
|
|
6017
6375
|
},
|
|
6018
6376
|
devDependencies: {
|
|
@@ -6030,7 +6388,7 @@ var package_default = {
|
|
|
6030
6388
|
"test:coverage": "vitest run --coverage"
|
|
6031
6389
|
},
|
|
6032
6390
|
name: "@stackwright-pro/mcp",
|
|
6033
|
-
version: "0.2.0-alpha.
|
|
6391
|
+
version: "0.2.0-alpha.81",
|
|
6034
6392
|
description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
|
|
6035
6393
|
license: "SEE LICENSE IN LICENSE",
|
|
6036
6394
|
main: "./dist/server.js",
|
|
@@ -6084,6 +6442,8 @@ registerIntegrityTools(server);
|
|
|
6084
6442
|
registerArtifactSigningTools(server);
|
|
6085
6443
|
registerDomainTools(server);
|
|
6086
6444
|
registerTypeSchemasTool(server);
|
|
6445
|
+
registerValidateYamlFragmentTool(server);
|
|
6446
|
+
registerGetSchemaTool(server);
|
|
6087
6447
|
registerScaffoldCleanupTools(server);
|
|
6088
6448
|
registerContrastTools(server);
|
|
6089
6449
|
async function main() {
|