@stackwright-pro/mcp 0.2.0-alpha.95 → 0.2.0-alpha.98

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
@@ -2705,7 +2705,8 @@ var MANIFEST_NAME_TO_PHASE = {
2705
2705
  "stackwright-pro-form-wizard-otter": "workflow",
2706
2706
  "stackwright-pro-geo-otter": "geo",
2707
2707
  "stackwright-pro-polish-otter": "polish",
2708
- "stackwright-services-otter": "services"
2708
+ "stackwright-services-otter": "services",
2709
+ "stackwright-pro-qa-otter": "qa"
2709
2710
  };
2710
2711
  function manifestNameToPhase(name) {
2711
2712
  return MANIFEST_NAME_TO_PHASE[name] ?? null;
@@ -2908,6 +2909,7 @@ function loadPipelineGraph() {
2908
2909
  }
2909
2910
 
2910
2911
  // src/tools/pipeline.ts
2912
+ import { emit } from "@stackwright-pro/telemetry";
2911
2913
  var PHASE_ORDER = [
2912
2914
  "designer",
2913
2915
  "theme",
@@ -2922,7 +2924,8 @@ var PHASE_ORDER = [
2922
2924
  "services",
2923
2925
  "pages",
2924
2926
  "dashboard",
2925
- "polish"
2927
+ "polish",
2928
+ "qa"
2926
2929
  ];
2927
2930
  var PHASE_ARTIFACT = {
2928
2931
  designer: "design-language.json",
@@ -2936,7 +2939,8 @@ var PHASE_ARTIFACT = {
2936
2939
  workflow: "workflow-config.json",
2937
2940
  services: "services-config.json",
2938
2941
  polish: "polish-manifest.json",
2939
- geo: "geo-manifest.json"
2942
+ geo: "geo-manifest.json",
2943
+ qa: "qa-findings.json"
2940
2944
  };
2941
2945
  var PHASE_TO_OTTER2 = {
2942
2946
  designer: "stackwright-pro-designer-otter",
@@ -2950,7 +2954,8 @@ var PHASE_TO_OTTER2 = {
2950
2954
  workflow: "stackwright-pro-form-wizard-otter",
2951
2955
  services: "stackwright-services-otter",
2952
2956
  polish: "stackwright-pro-polish-otter",
2953
- geo: "stackwright-pro-geo-otter"
2957
+ geo: "stackwright-pro-geo-otter",
2958
+ qa: "stackwright-pro-qa-otter"
2954
2959
  };
2955
2960
  function isValidPhase2(phase) {
2956
2961
  return PHASE_ORDER.includes(phase);
@@ -3119,6 +3124,28 @@ function handleSetPipelineState(input) {
3119
3124
  }
3120
3125
  }
3121
3126
  writeState(cwd, state);
3127
+ try {
3128
+ const completedPhases = Object.entries(state.phases).filter(([, ps]) => ps.artifactWritten).map(([p]) => p);
3129
+ emit(
3130
+ {
3131
+ type: "pipeline_state_change",
3132
+ state: state.status,
3133
+ phases: { ready: [], completed: completedPhases, blocked: [] }
3134
+ },
3135
+ { cwd }
3136
+ );
3137
+ if (input.field === "artifactWritten" && input.value === true && input.phase) {
3138
+ emit({ type: "phase_complete", phase: input.phase }, { cwd });
3139
+ }
3140
+ if (input.updates) {
3141
+ for (const update of input.updates) {
3142
+ if (update.field === "artifactWritten" && update.value === true) {
3143
+ emit({ type: "phase_complete", phase: update.phase }, { cwd });
3144
+ }
3145
+ }
3146
+ }
3147
+ } catch {
3148
+ }
3122
3149
  return { text: JSON.stringify(state), isError: false };
3123
3150
  } catch (err) {
3124
3151
  return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };
@@ -3494,7 +3521,10 @@ var PHASE_REQUIRED_KEYS = {
3494
3521
  workflow: ["version", "generatedBy"],
3495
3522
  services: ["version", "generatedBy", "flows"],
3496
3523
  polish: ["version", "generatedBy"],
3497
- geo: ["version", "generatedBy", "geoCollections"]
3524
+ geo: ["version", "generatedBy", "geoCollections"],
3525
+ // qa: skipped=true path only needs version+generatedBy+skipped;
3526
+ // skipped=false path also needs summary+findings — Zod validator enforces the conditional.
3527
+ qa: ["version", "generatedBy", "skipped"]
3498
3528
  };
3499
3529
  var PHASE_ARTIFACT_SCHEMA = {
3500
3530
  designer: JSON.stringify(
@@ -3784,9 +3814,44 @@ var PHASE_ARTIFACT_SCHEMA = {
3784
3814
  },
3785
3815
  null,
3786
3816
  2
3817
+ ),
3818
+ qa: JSON.stringify(
3819
+ {
3820
+ version: "1.0",
3821
+ generatedBy: "stackwright-pro-qa-otter",
3822
+ // skipped: true path — when dev server is unreachable at audit time
3823
+ // skipped: false path — full audit completed
3824
+ skipped: false,
3825
+ skipReason: null,
3826
+ wcagLevel: "<AA|AAA>",
3827
+ summary: {
3828
+ routesAudited: 3,
3829
+ serious: 0,
3830
+ moderate: 1,
3831
+ minor: 0
3832
+ },
3833
+ findings: [
3834
+ {
3835
+ id: "qa-001",
3836
+ route: "/dashboard",
3837
+ severity: "<serious|moderate|minor>",
3838
+ category: "<visual|a11y|design-contract|runtime>",
3839
+ finding: "Human-readable description of what was observed",
3840
+ evidence: {
3841
+ screenshot: ".stackwright/qa/screenshots/dashboard-light.png",
3842
+ consoleErrors: [],
3843
+ axeViolations: []
3844
+ },
3845
+ suggested_otters: ["stackwright-pro-theme-otter"],
3846
+ suggested_fix: "Specific, concrete next step the repair otter should take"
3847
+ }
3848
+ ]
3849
+ },
3850
+ null,
3851
+ 2
3787
3852
  )
3788
3853
  };
3789
- function handleValidateArtifact(input) {
3854
+ function _validateArtifactInner(input) {
3790
3855
  const cwd = input._cwd ?? process.cwd();
3791
3856
  const { phase, responseText, artifact: directArtifact } = input;
3792
3857
  if (!isValidPhase2(phase)) {
@@ -3924,6 +3989,40 @@ function handleValidateArtifact(input) {
3924
3989
  };
3925
3990
  }
3926
3991
  return { success: true };
3992
+ },
3993
+ // qa artifact — permissive validator: requires version + generatedBy + skipped.
3994
+ // When skipped=true: skipReason must be a string.
3995
+ // When skipped=false: findings must be an array and summary must be an object.
3996
+ qa: (artifact2) => {
3997
+ const skipped = artifact2["skipped"];
3998
+ if (typeof skipped !== "boolean") {
3999
+ return {
4000
+ success: false,
4001
+ error: { message: '"skipped" must be a boolean (true or false).' }
4002
+ };
4003
+ }
4004
+ if (skipped === true) {
4005
+ if (typeof artifact2["skipReason"] !== "string") {
4006
+ return {
4007
+ success: false,
4008
+ error: { message: 'When skipped=true, "skipReason" must be a string.' }
4009
+ };
4010
+ }
4011
+ return { success: true };
4012
+ }
4013
+ if (!Array.isArray(artifact2["findings"])) {
4014
+ return {
4015
+ success: false,
4016
+ error: { message: 'When skipped=false, "findings" must be an array.' }
4017
+ };
4018
+ }
4019
+ if (typeof artifact2["summary"] !== "object" || artifact2["summary"] === null) {
4020
+ return {
4021
+ success: false,
4022
+ error: { message: 'When skipped=false, "summary" must be an object.' }
4023
+ };
4024
+ }
4025
+ return { success: true };
3927
4026
  }
3928
4027
  };
3929
4028
  const zodValidator = PHASE_ZOD_VALIDATORS[phase];
@@ -3974,6 +4073,32 @@ function handleValidateArtifact(input) {
3974
4073
  return { text: JSON.stringify({ error: true, phase, message }), isError: true };
3975
4074
  }
3976
4075
  }
4076
+ function handleValidateArtifact(input) {
4077
+ const cwd = input._cwd ?? process.cwd();
4078
+ const { phase } = input;
4079
+ emit(
4080
+ { type: "tool_call", toolName: "stackwright_pro_validate_artifact", args: { phase }, phase },
4081
+ { cwd }
4082
+ );
4083
+ const result = _validateArtifactInner(input);
4084
+ try {
4085
+ const parsed = JSON.parse(result.text);
4086
+ if (parsed.valid === true && parsed.artifactPath) {
4087
+ emit({ type: "file_write", path: parsed.artifactPath, phase }, { cwd });
4088
+ }
4089
+ emit(
4090
+ {
4091
+ type: "tool_complete",
4092
+ toolName: "stackwright_pro_validate_artifact",
4093
+ success: parsed.valid === true,
4094
+ phase
4095
+ },
4096
+ { cwd }
4097
+ );
4098
+ } catch {
4099
+ }
4100
+ return result;
4101
+ }
3977
4102
  function registerPipelineTools(server2) {
3978
4103
  const DESC = "Writes state to .stackwright/ \u2014 the filesystem is the state machine.";
3979
4104
  const res = (r) => ({
@@ -4110,12 +4235,70 @@ function registerPipelineTools(server2) {
4110
4235
  return res(handleValidateArtifact({ phase, responseText: responseText ?? "" }));
4111
4236
  }
4112
4237
  );
4238
+ server2.tool(
4239
+ "stackwright_pro_emit_event",
4240
+ `Emit a telemetry event to .stackwright/pipeline-events.ndjson. Foreman calls this at phase boundaries and agent-invoke boundaries. Best-effort: failures are silent and never block. ${DESC}`,
4241
+ {
4242
+ type: z13.enum(["phase_start", "phase_complete", "agent_invoke_start", "agent_invoke_complete"]).describe("Event type to emit"),
4243
+ phase: z13.string().optional().describe("Current phase name"),
4244
+ targetOtter: z13.string().optional().describe("For agent_invoke_* events: which otter is being invoked"),
4245
+ success: z13.boolean().optional().describe("For agent_invoke_complete: did the invocation succeed?"),
4246
+ otter: z13.string().optional().describe('Which otter is emitting (defaults to "foreman")'),
4247
+ durationSec: z13.number().optional().describe("Duration in seconds (for *_complete events)")
4248
+ },
4249
+ async ({ type, phase, targetOtter, success, otter, durationSec }) => {
4250
+ let emitted = false;
4251
+ try {
4252
+ if (type === "phase_start") {
4253
+ if (!phase) {
4254
+ return res({
4255
+ text: JSON.stringify({ emitted: false, reason: "phase required for phase_start" }),
4256
+ isError: false
4257
+ });
4258
+ }
4259
+ emitted = emit({ type: "phase_start", phase, otter: otter ?? "foreman" });
4260
+ } else if (type === "phase_complete") {
4261
+ if (!phase) {
4262
+ return res({
4263
+ text: JSON.stringify({ emitted: false, reason: "phase required for phase_complete" }),
4264
+ isError: false
4265
+ });
4266
+ }
4267
+ emitted = emit({
4268
+ type: "phase_complete",
4269
+ phase,
4270
+ otter: otter ?? "foreman",
4271
+ ...durationSec != null ? { durationSec } : {}
4272
+ });
4273
+ } else if (type === "agent_invoke_start") {
4274
+ emitted = emit({
4275
+ type: "agent_invoke_start",
4276
+ targetOtter: targetOtter ?? "",
4277
+ phase,
4278
+ otter: otter ?? "foreman"
4279
+ });
4280
+ } else if (type === "agent_invoke_complete") {
4281
+ emitted = emit({
4282
+ type: "agent_invoke_complete",
4283
+ targetOtter: targetOtter ?? "",
4284
+ success: success ?? true,
4285
+ phase,
4286
+ otter: otter ?? "foreman",
4287
+ ...durationSec != null ? { durationSec } : {}
4288
+ });
4289
+ }
4290
+ } catch {
4291
+ }
4292
+ return res({ text: JSON.stringify({ emitted }), isError: false });
4293
+ }
4294
+ );
4113
4295
  }
4114
4296
 
4115
4297
  // src/tools/safe-write.ts
4116
4298
  import { z as z14 } from "zod";
4117
4299
  import { writeFileSync as writeFileSync5, readFileSync as readFileSync6, existsSync as existsSync6, mkdirSync as mkdirSync5, lstatSync as lstatSync7 } from "fs";
4118
4300
  import { normalize, isAbsolute, dirname, join as join6 } from "path";
4301
+ import { emit as emit2 } from "@stackwright-pro/telemetry";
4119
4302
  var OTTER_WRITE_ALLOWLISTS = {
4120
4303
  "stackwright-pro-designer-otter": [
4121
4304
  { prefix: ".stackwright/artifacts/", suffix: ".json", description: "Design language artifact" }
@@ -4211,6 +4394,25 @@ var OTTER_WRITE_ALLOWLISTS = {
4211
4394
  { prefix: ".stackwright/artifacts/", suffix: ".json", description: "Polish artifact" },
4212
4395
  { prefix: "README.md", suffix: "", description: "Project README rewrite" }
4213
4396
  ],
4397
+ // QA otter writes ONLY to the qa/ directory and the qa-findings artifact.
4398
+ // It never writes .tsx, .ts, .yml, or .json outside these paths.
4399
+ "stackwright-pro-qa-otter": [
4400
+ {
4401
+ prefix: ".stackwright/artifacts/qa-findings.json",
4402
+ suffix: "",
4403
+ description: "QA findings artifact"
4404
+ },
4405
+ {
4406
+ prefix: ".stackwright/qa/",
4407
+ suffix: ".md",
4408
+ description: "QA report markdown"
4409
+ },
4410
+ {
4411
+ prefix: ".stackwright/qa/screenshots/",
4412
+ suffix: ".png",
4413
+ description: "Route screenshots for evidence"
4414
+ }
4415
+ ],
4214
4416
  // domain-expert-otter is a reader/answerer only — it writes via stackwright_pro_save_phase_answers,
4215
4417
  // not via safe_write. Entry required here because the MCP tool availability guard boilerplate
4216
4418
  // in its system prompt mentions stackwright_pro_safe_write (triggering the coherence test).
@@ -4424,7 +4626,7 @@ function validateContent(filePath, content) {
4424
4626
  if (filePath === ".env" || filePath.startsWith(".env")) return validateEnvContent(content);
4425
4627
  return null;
4426
4628
  }
4427
- function handleSafeWrite(input) {
4629
+ function _safeWriteInner(input) {
4428
4630
  const cwd = input._cwd ?? process.cwd();
4429
4631
  const { callerOtter, filePath, content, createDirectories = true } = input;
4430
4632
  const check = checkPathAllowed(callerOtter, filePath);
@@ -4532,6 +4734,31 @@ function handleSafeWrite(input) {
4532
4734
  return { text: JSON.stringify(result), isError: true };
4533
4735
  }
4534
4736
  }
4737
+ function handleSafeWrite(input) {
4738
+ const cwd = input._cwd ?? process.cwd();
4739
+ const { filePath, callerOtter } = input;
4740
+ emit2(
4741
+ { type: "tool_call", toolName: "stackwright_pro_safe_write", args: { callerOtter, filePath } },
4742
+ { cwd }
4743
+ );
4744
+ const result = _safeWriteInner(input);
4745
+ try {
4746
+ const parsed = JSON.parse(result.text);
4747
+ if (parsed.success === true && parsed.path) {
4748
+ emit2({ type: "file_write", path: parsed.path, bytes: parsed.bytesWritten }, { cwd });
4749
+ }
4750
+ emit2(
4751
+ {
4752
+ type: "tool_complete",
4753
+ toolName: "stackwright_pro_safe_write",
4754
+ success: parsed.success === true
4755
+ },
4756
+ { cwd }
4757
+ );
4758
+ } catch {
4759
+ }
4760
+ return result;
4761
+ }
4535
4762
  function registerSafeWriteTools(server2) {
4536
4763
  const DESC = "Controlled file-write chokepoint. Every write from specialist otters goes through this tool with per-otter path allowlists. The LLM cannot write to arbitrary filesystem paths.";
4537
4764
  server2.tool(
@@ -5473,59 +5700,63 @@ import { join as join8, basename } from "path";
5473
5700
  var _checksums = /* @__PURE__ */ new Map([
5474
5701
  [
5475
5702
  "stackwright-pro-api-otter.json",
5476
- "822b35d7a330ed8ac0b42a63b0f70a41885aa9b5ea23cc5b8b998b549da4c05c"
5703
+ "b3ad28c4404af9fb3c2cfce258c707dadd37bc59ac236e1f46d6163cd8d5dc9b"
5477
5704
  ],
5478
5705
  [
5479
5706
  "stackwright-pro-auth-otter.json",
5480
- "d6cd5732667018d99456be77d5955e454da7a0999a0330b5f03a483aa1b9b33f"
5707
+ "1a21d9f23e250f23291124307e5a2a32af5a716566319a3290372dae3d02e637"
5481
5708
  ],
5482
5709
  [
5483
5710
  "stackwright-pro-dashboard-otter.json",
5484
- "e3b82555fcffbd77285bd304828814e9f9f7257130797c9de3785de97527668c"
5711
+ "d9277616db5680ce3d598908fa3a1b0d0f626e33948785a4c64703b85e463b31"
5485
5712
  ],
5486
5713
  [
5487
5714
  "stackwright-pro-data-otter.json",
5488
- "bb66eaab31c6872536dca4d3ff145724a46356946dd0665cc4f0346714d3bacb"
5715
+ "536cba95f32667e81ae4b6335378a095f91095598defff0de00af231ebdbc488"
5489
5716
  ],
5490
5717
  [
5491
5718
  "stackwright-pro-designer-otter.json",
5492
- "b54121c6a2ab5b1ad68c1262c58b2e04e6315feacd6bb8de8e78eb36f2fa6be6"
5719
+ "69a6c09fbb54f971c48eae7fd52faa63cf79be2923e435aca9ff802e8d541d0f"
5493
5720
  ],
5494
5721
  [
5495
5722
  "stackwright-pro-domain-expert-otter.json",
5496
- "1f21b8ff3450bdae29a4d31b31462ba22583995a448af3c11ab0a5071f46bd72"
5723
+ "14d77cade020f44d1b5a2b406e2599501f3466ee90ca4248500a441d419bc59c"
5497
5724
  ],
5498
5725
  [
5499
5726
  "stackwright-pro-foreman-otter.json",
5500
- "abb1cc5e40a8c5ff98057273f43a9e90e2791a15951090cd4d98407c0c3618e3"
5727
+ "4db4639e618cdd008d86c416bbc88bd4b2a7965e4bfcf01ec54b828f04ccb816"
5501
5728
  ],
5502
5729
  [
5503
5730
  "stackwright-pro-form-wizard-otter.json",
5504
- "975ad68e8fb6fe5a10373be278946fa4d9d7ec2238a0b2bd9e4a412e5b1fdd6d"
5731
+ "7f6f94192f26face57dc8b2e22e0a49d23ceeeb356ca4ebde05492f1b25e3c47"
5505
5732
  ],
5506
5733
  [
5507
5734
  "stackwright-pro-geo-otter.json",
5508
- "ac440da786d8c5ab1feddbf861449c3be3a433a04370578e1b2d35bf6ae7a601"
5735
+ "15f2327b69f75a9c772c2acad5a5d6d3daefb7b55a079aca3205ecd4f33ae349"
5509
5736
  ],
5510
5737
  [
5511
5738
  "stackwright-pro-page-otter.json",
5512
- "b70bd6e5d2a40230f7c24ff4a6113585a1614e5b6a215ece2bd47ff053c30f58"
5739
+ "c467c5d03b69d87fb1efa9482674a25e2f63782189db74b65309928d47456176"
5513
5740
  ],
5514
5741
  [
5515
5742
  "stackwright-pro-polish-otter.json",
5516
- "48ef3cf7f29ac6b5e8ab2004d4d41e2fb899e781689178d3905993241c84095a"
5743
+ "1cfea28e121e30181b0a7c8bda0700ffc892a6f919a0ec64996a4cf3f7735b51"
5744
+ ],
5745
+ [
5746
+ "stackwright-pro-qa-otter.json",
5747
+ "822075893bb4f8496f3dca7b0e68eda460a6fbde87480c13c194582eb7744318"
5517
5748
  ],
5518
5749
  [
5519
5750
  "stackwright-pro-scaffold-otter.json",
5520
- "e8662b63bbc9ce38851d94f9656bbebefdb7843d038862adb9fde2c23f9e77c2"
5751
+ "341d74ff2be24893ed174e869dc40c090f82e25e11d412d63519944512c37f15"
5521
5752
  ],
5522
5753
  [
5523
5754
  "stackwright-pro-theme-otter.json",
5524
- "fb62e56642f7f94c50ce173f3e1ce978b3f20ab1567e87403b901d6dd991a7db"
5755
+ "b0eccc1945e30b80a0f9a3209c5428e8e32cd09063bd9b2ef7ecb891343774f2"
5525
5756
  ],
5526
5757
  [
5527
5758
  "stackwright-services-otter.json",
5528
- "0a5dac670482871c718099767b30bf23d8ec57e942bd40a00ce295926d82c6bd"
5759
+ "8997bdd9a6fd3e6e02563578a1649480bc21acf919534ae41f73e70ade7cf500"
5529
5760
  ]
5530
5761
  ]);
5531
5762
  Object.freeze(_checksums);
@@ -5538,6 +5769,7 @@ for (const [name, digest] of CANONICAL_CHECKSUMS) {
5538
5769
  );
5539
5770
  }
5540
5771
  }
5772
+ var CANONICAL_OTTERS = Object.freeze([...CANONICAL_CHECKSUMS.keys()]);
5541
5773
  var MAX_OTTER_BYTES = 1 * 1024 * 1024;
5542
5774
  function computeSha256(data) {
5543
5775
  return createHash4("sha256").update(data).digest("hex");
@@ -6972,7 +7204,9 @@ var package_default = {
6972
7204
  "@stackwright-pro/cli-data-explorer": "workspace:*",
6973
7205
  "@stackwright-pro/openapi": "workspace:*",
6974
7206
  "@stackwright-pro/pulse": "workspace:*",
7207
+ "@stackwright-pro/telemetry": "workspace:*",
6975
7208
  "@stackwright-pro/types": "workspace:*",
7209
+ "@stackwright/mcp": "0.6.0-alpha.1",
6976
7210
  "@types/js-yaml": "^4.0.9",
6977
7211
  "js-yaml": "^4.2.0",
6978
7212
  zod: "^4.4.3"
@@ -6992,7 +7226,7 @@ var package_default = {
6992
7226
  "test:coverage": "vitest run --coverage"
6993
7227
  },
6994
7228
  name: "@stackwright-pro/mcp",
6995
- version: "0.2.0-alpha.95",
7229
+ version: "0.2.0-alpha.98",
6996
7230
  description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
6997
7231
  license: "SEE LICENSE IN LICENSE",
6998
7232
  main: "./dist/server.js",
@@ -7016,6 +7250,11 @@ var package_default = {
7016
7250
  types: "./dist/tools/type-schemas.d.ts",
7017
7251
  import: "./dist/tools/type-schemas.mjs",
7018
7252
  require: "./dist/tools/type-schemas.js"
7253
+ },
7254
+ "./pipeline-constants": {
7255
+ types: "./dist/pipeline-constants.d.ts",
7256
+ import: "./dist/pipeline-constants.mjs",
7257
+ require: "./dist/pipeline-constants.js"
7019
7258
  }
7020
7259
  },
7021
7260
  files: [
@@ -7027,6 +7266,20 @@ var package_default = {
7027
7266
  };
7028
7267
 
7029
7268
  // src/server.ts
7269
+ import {
7270
+ registerContentTypeTools,
7271
+ registerPageTools,
7272
+ registerSiteTools,
7273
+ registerProjectTools,
7274
+ registerGitOpsTools,
7275
+ registerBoardTools,
7276
+ registerCollectionTools,
7277
+ registerIntegrationTools,
7278
+ registerComposeTools,
7279
+ registerRenderTools,
7280
+ registerA11yTools,
7281
+ closeBrowser
7282
+ } from "@stackwright/mcp/register";
7030
7283
  var server = new McpServer({
7031
7284
  name: "stackwright-pro",
7032
7285
  version: package_default.version
@@ -7051,6 +7304,29 @@ registerGetSchemaTool(server);
7051
7304
  registerScaffoldCleanupTools(server);
7052
7305
  registerContrastTools(server);
7053
7306
  registerCompileTools(server);
7307
+ registerContentTypeTools(server);
7308
+ registerPageTools(server);
7309
+ registerSiteTools(server);
7310
+ registerProjectTools(server);
7311
+ registerGitOpsTools(server);
7312
+ registerBoardTools(server);
7313
+ registerCollectionTools(server);
7314
+ registerIntegrationTools(server);
7315
+ registerComposeTools(server);
7316
+ registerRenderTools(server);
7317
+ registerA11yTools(server);
7318
+ process.on("SIGINT", async () => {
7319
+ const forceExit = setTimeout(() => process.exit(1), 3e3);
7320
+ forceExit.unref();
7321
+ await closeBrowser();
7322
+ process.exit(0);
7323
+ });
7324
+ process.on("SIGTERM", async () => {
7325
+ const forceExit = setTimeout(() => process.exit(1), 3e3);
7326
+ forceExit.unref();
7327
+ await closeBrowser();
7328
+ process.exit(0);
7329
+ });
7054
7330
  async function main() {
7055
7331
  const pipelineGraph = loadPipelineGraph();
7056
7332
  const phasePosition = new Map(PHASE_ORDER.map((p, i) => [p, i]));