@stackwright-pro/mcp 0.2.0-alpha.101 → 0.2.0-alpha.102

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
@@ -556,7 +556,7 @@ function registerDashboardTools(server2) {
556
556
  yamlLines.push(` header: Status`);
557
557
  yamlLines.push(` type: badge`);
558
558
  }
559
- const yaml = yamlLines.join("\n");
559
+ const yaml2 = yamlLines.join("\n");
560
560
  return {
561
561
  content: [
562
562
  {
@@ -566,7 +566,7 @@ function registerDashboardTools(server2) {
566
566
  Layout: ${layout}
567
567
 
568
568
  \`\`\`yaml
569
- ${yaml}
569
+ ${yaml2}
570
570
  \`\`\`
571
571
 
572
572
  \u{1F4A1} Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`
@@ -647,7 +647,7 @@ ${yaml}
647
647
  yamlLines.push(" action: navigate");
648
648
  yamlLines.push(` href: "/${entity}"`);
649
649
  yamlLines.push(" style: secondary");
650
- const yaml = yamlLines.join("\n");
650
+ const yaml2 = yamlLines.join("\n");
651
651
  return {
652
652
  content: [
653
653
  {
@@ -655,7 +655,7 @@ ${yaml}
655
655
  text: `\u{1F4C4} Generated Detail Page for: ${entity}
656
656
 
657
657
  \`\`\`yaml
658
- ${yaml}
658
+ ${yaml2}
659
659
  \`\`\`
660
660
 
661
661
  \u{1F4A1} Add this to pages/${entity}/[${slugField}]/content.yml and validate.`
@@ -2455,7 +2455,7 @@ function enrichErrors(issues, synonyms) {
2455
2455
  });
2456
2456
  }
2457
2457
  function handleValidateYamlFragment(input) {
2458
- const { schemaName, yaml } = input;
2458
+ const { schemaName, yaml: yaml2 } = input;
2459
2459
  if (!SUPPORTED_SCHEMA_NAMES.includes(schemaName)) {
2460
2460
  return {
2461
2461
  valid: false,
@@ -2465,7 +2465,7 @@ function handleValidateYamlFragment(input) {
2465
2465
  const name = schemaName;
2466
2466
  let parsed;
2467
2467
  try {
2468
- parsed = yamlLoad(yaml);
2468
+ parsed = yamlLoad(yaml2);
2469
2469
  } catch (err) {
2470
2470
  return {
2471
2471
  valid: false,
@@ -2491,8 +2491,8 @@ function registerValidateYamlFragmentTool(server2) {
2491
2491
  ),
2492
2492
  yaml: z11.string().describe("YAML string to validate (can also be JSON \u2014 js-yaml parses both)")
2493
2493
  },
2494
- async ({ schemaName, yaml }) => {
2495
- const result = handleValidateYamlFragment({ schemaName, yaml });
2494
+ async ({ schemaName, yaml: yaml2 }) => {
2495
+ const result = handleValidateYamlFragment({ schemaName, yaml: yaml2 });
2496
2496
  return {
2497
2497
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
2498
2498
  };
@@ -2967,7 +2967,8 @@ function defaultPhaseStatus() {
2967
2967
  answered: false,
2968
2968
  executed: false,
2969
2969
  artifactWritten: false,
2970
- retryCount: 0
2970
+ retryCount: 0,
2971
+ inFlight: false
2971
2972
  };
2972
2973
  }
2973
2974
  function createDefaultState() {
@@ -3084,7 +3085,13 @@ function handleSetPipelineState(input) {
3084
3085
  isError: true
3085
3086
  };
3086
3087
  }
3087
- const VALID_FIELDS = ["questionsCollected", "answered", "executed", "artifactWritten"];
3088
+ const VALID_FIELDS = [
3089
+ "questionsCollected",
3090
+ "answered",
3091
+ "executed",
3092
+ "artifactWritten",
3093
+ "inFlight"
3094
+ ];
3088
3095
  if (input.field && !VALID_FIELDS.includes(input.field)) {
3089
3096
  return {
3090
3097
  text: JSON.stringify({
@@ -4143,6 +4150,14 @@ function handleEmitEvent(input) {
4143
4150
  };
4144
4151
  }
4145
4152
  emitted = emitFn({ type: "phase_start", phase: input.phase, otter: caller });
4153
+ } else if (input.type === "phase_ready") {
4154
+ if (!input.phase) {
4155
+ return {
4156
+ text: JSON.stringify({ emitted: false, reason: "phase required for phase_ready" }),
4157
+ isError: false
4158
+ };
4159
+ }
4160
+ emitted = emitFn({ type: "phase_ready", phase: input.phase, otter: caller });
4146
4161
  } else if (input.type === "phase_complete") {
4147
4162
  if (!input.phase) {
4148
4163
  return {
@@ -4183,23 +4198,24 @@ function handleEmitEvent(input) {
4183
4198
  }
4184
4199
  }
4185
4200
  function registerPipelineTools(server2) {
4186
- const DESC = "Writes state to .stackwright/ \u2014 the filesystem is the state machine.";
4201
+ const DESC2 = "Writes state to .stackwright/ \u2014 the filesystem is the state machine.";
4187
4202
  const res = (r) => ({
4188
4203
  content: [{ type: "text", text: r.text }],
4189
4204
  isError: r.isError
4190
4205
  });
4191
4206
  server2.tool(
4192
4207
  "stackwright_pro_get_pipeline_state",
4193
- `Read pipeline state from .stackwright/pipeline-state.json. ${DESC}`,
4208
+ `Read pipeline state from .stackwright/pipeline-state.json. ${DESC2}`,
4194
4209
  {},
4195
4210
  async () => res(handleGetPipelineState())
4196
4211
  );
4197
4212
  server2.tool(
4198
4213
  "stackwright_pro_set_pipeline_state",
4199
- `Atomic read\u2192modify\u2192write pipeline state. ${DESC}`,
4214
+ `Atomic read\u2192modify\u2192write pipeline state. ${DESC2}`,
4200
4215
  {
4201
4216
  phase: z13.string().optional().describe('Phase to update, e.g. "designer"'),
4202
- field: z13.enum(["questionsCollected", "answered", "executed", "artifactWritten"]).optional().describe("Boolean field to set"),
4217
+ field: z13.enum(["questionsCollected", "answered", "executed", "artifactWritten", "inFlight"]).optional().describe("Boolean field to set"),
4218
+ // inFlight: set true BEFORE specialist invoke (dataflow mode, swp-ioc7); false after.
4203
4219
  value: boolCoerce(z13.boolean().optional()).describe(
4204
4220
  'Value for the field \u2014 must be a JSON boolean (true/false), NOT the string "true"/"false"'
4205
4221
  ),
@@ -4211,7 +4227,13 @@ function registerPipelineTools(server2) {
4211
4227
  z13.array(
4212
4228
  z13.object({
4213
4229
  phase: z13.string(),
4214
- field: z13.enum(["questionsCollected", "answered", "executed", "artifactWritten"]),
4230
+ field: z13.enum([
4231
+ "questionsCollected",
4232
+ "answered",
4233
+ "executed",
4234
+ "artifactWritten",
4235
+ "inFlight"
4236
+ ]),
4215
4237
  value: z13.boolean()
4216
4238
  })
4217
4239
  ).optional()
@@ -4230,7 +4252,7 @@ function registerPipelineTools(server2) {
4230
4252
  );
4231
4253
  server2.tool(
4232
4254
  "stackwright_pro_check_execution_ready",
4233
- `Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC}`,
4255
+ `Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC2}`,
4234
4256
  {
4235
4257
  phase: z13.string().optional().describe("If provided, check only this phase's readiness. Omit to check all phases.")
4236
4258
  },
@@ -4238,19 +4260,19 @@ function registerPipelineTools(server2) {
4238
4260
  );
4239
4261
  server2.tool(
4240
4262
  "stackwright_pro_get_ready_phases",
4241
- `Return phases whose dependencies are all satisfied (executed=true). Use to determine which phases can run next \u2014 enables wave-based execution. ${DESC}`,
4263
+ `Return phases whose dependencies are all satisfied (executed=true). Use to determine which phases can run next \u2014 enables wave-based execution. ${DESC2}`,
4242
4264
  {},
4243
4265
  async () => res(handleGetReadyPhases())
4244
4266
  );
4245
4267
  server2.tool(
4246
4268
  "stackwright_pro_list_artifacts",
4247
- `List phase artifacts in .stackwright/artifacts/ with completedCount/totalCount. ${DESC}`,
4269
+ `List phase artifacts in .stackwright/artifacts/ with completedCount/totalCount. ${DESC2}`,
4248
4270
  {},
4249
4271
  async () => res(handleListArtifacts())
4250
4272
  );
4251
4273
  server2.tool(
4252
4274
  "stackwright_pro_write_phase_questions",
4253
- `Parse otter question-collection response \u2192 .stackwright/questions/{phase}.json. Specialists may also call this directly with a parsed questions array. ${DESC}`,
4275
+ `Parse otter question-collection response \u2192 .stackwright/questions/{phase}.json. Specialists may also call this directly with a parsed questions array. ${DESC2}`,
4254
4276
  {
4255
4277
  phase: z13.string().optional().describe('Phase name, e.g. "designer" (required for direct write)'),
4256
4278
  responseText: z13.string().optional().describe("Raw LLM response from QUESTION_COLLECTION_MODE"),
@@ -4295,13 +4317,13 @@ function registerPipelineTools(server2) {
4295
4317
  );
4296
4318
  server2.tool(
4297
4319
  "stackwright_pro_build_specialist_prompt",
4298
- `Assemble execution prompt from answers + upstream artifacts. Foreman passes verbatim. ${DESC}`,
4320
+ `Assemble execution prompt from answers + upstream artifacts. Foreman passes verbatim. ${DESC2}`,
4299
4321
  { phase: z13.string().describe('Phase to build prompt for, e.g. "pages"') },
4300
4322
  async ({ phase }) => res(handleBuildSpecialistPrompt({ phase }))
4301
4323
  );
4302
4324
  server2.tool(
4303
4325
  "stackwright_pro_validate_artifact",
4304
- `Validate and write artifact to .stackwright/artifacts/. Returns retryPrompt on failure. ${DESC}`,
4326
+ `Validate and write artifact to .stackwright/artifacts/. Returns retryPrompt on failure. ${DESC2}`,
4305
4327
  {
4306
4328
  phase: z13.string().describe('Phase that produced this artifact, e.g. "designer"'),
4307
4329
  responseText: z13.string().optional().describe("Raw response text from the specialist otter (Foreman-mediated path, legacy)"),
@@ -4333,9 +4355,17 @@ function registerPipelineTools(server2) {
4333
4355
  );
4334
4356
  server2.tool(
4335
4357
  "stackwright_pro_emit_event",
4336
- `FOREMAN ONLY \u2014 specialist otters that call this will receive an authorization rejection (no-op, not an error). 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}`,
4358
+ `FOREMAN ONLY \u2014 specialist otters that call this will receive an authorization rejection (no-op, not an error). 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. ${DESC2}`,
4337
4359
  {
4338
- type: z13.enum(["phase_start", "phase_complete", "agent_invoke_start", "agent_invoke_complete"]).describe("Event type to emit"),
4360
+ type: z13.enum([
4361
+ "phase_start",
4362
+ "phase_complete",
4363
+ "phase_ready",
4364
+ "agent_invoke_start",
4365
+ "agent_invoke_complete"
4366
+ ]).describe("Event type to emit"),
4367
+ // phase_ready: emitted in dataflow mode (swp-ioc7) when a phase enters the ready set
4368
+ // (deps satisfied, not inFlight, not yet complete) — BEFORE invoking the specialist.
4339
4369
  phase: z13.string().optional().describe("Current phase name"),
4340
4370
  targetOtter: z13.string().optional().describe("For agent_invoke_* events: which otter is being invoked"),
4341
4371
  success: boolCoerce(z13.boolean().optional()).describe(
@@ -4446,7 +4476,17 @@ var OTTER_WRITE_ALLOWLISTS = {
4446
4476
  { prefix: "pages/", suffix: "/content.yml", description: "Landing page content" },
4447
4477
  { prefix: "pages/", suffix: "/content.yaml", description: "Landing page content" },
4448
4478
  { prefix: ".stackwright/artifacts/", suffix: ".json", description: "Polish artifact" },
4449
- { prefix: "README.md", suffix: "", description: "Project README rewrite" }
4479
+ { prefix: "README.md", suffix: "", description: "Project README rewrite" },
4480
+ {
4481
+ prefix: ".env.local",
4482
+ suffix: "",
4483
+ description: ".env.local runtime config \u2014 emitter output from stackwright_pro_emit_env_local (swp-8qdd)"
4484
+ },
4485
+ {
4486
+ prefix: ".env.local.example",
4487
+ suffix: "",
4488
+ description: ".env.local.example template \u2014 emitter output from stackwright_pro_emit_env_local (swp-8qdd)"
4489
+ }
4450
4490
  ],
4451
4491
  // QA otter writes ONLY to the qa/ directory and the qa-findings artifact.
4452
4492
  // It never writes .tsx, .ts, .yml, or .json outside these paths.
@@ -4814,10 +4854,10 @@ function handleSafeWrite(input) {
4814
4854
  return result;
4815
4855
  }
4816
4856
  function registerSafeWriteTools(server2) {
4817
- 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.";
4857
+ const DESC2 = "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.";
4818
4858
  server2.tool(
4819
4859
  "stackwright_pro_safe_write",
4820
- DESC,
4860
+ DESC2,
4821
4861
  {
4822
4862
  callerOtter: z14.string().describe('The otter agent name requesting the write, e.g. "stackwright-pro-page-otter"'),
4823
4863
  filePath: z14.string().describe('Relative path from project root, e.g. "pages/dashboard/content.yml"'),
@@ -5785,7 +5825,7 @@ var _checksums = /* @__PURE__ */ new Map([
5785
5825
  ],
5786
5826
  [
5787
5827
  "stackwright-pro-foreman-otter.json",
5788
- "9191e176241c15f3d77180e1b843cc3a517b708737b5bd3cda7db62f2d6675d1"
5828
+ "c23436769a9db06fa6f9d312b4fdd8b2cef6646461020eeaf227303350073593"
5789
5829
  ],
5790
5830
  [
5791
5831
  "stackwright-pro-form-wizard-otter.json",
@@ -5801,7 +5841,7 @@ var _checksums = /* @__PURE__ */ new Map([
5801
5841
  ],
5802
5842
  [
5803
5843
  "stackwright-pro-polish-otter.json",
5804
- "9d0c53651b60507607efc0d9a0f9d166bf5ae8571f1645682e0b151d42c276ab"
5844
+ "fd8f8963266c6179eebf8eac4f656e8274aa3a721e5296abdbde5b00ad8a2297"
5805
5845
  ],
5806
5846
  [
5807
5847
  "stackwright-pro-qa-otter.json",
@@ -5809,7 +5849,7 @@ var _checksums = /* @__PURE__ */ new Map([
5809
5849
  ],
5810
5850
  [
5811
5851
  "stackwright-pro-scaffold-otter.json",
5812
- "5756ea77178334684b4df1d9d3395bca62cedb4991ab07dc4cf61aa7e540ea14"
5852
+ "c2ae10733d8bd66bd965b29a77193b0abf0ea6765cd02886df1413bf598e0588"
5813
5853
  ],
5814
5854
  [
5815
5855
  "stackwright-pro-theme-otter.json",
@@ -6890,10 +6930,10 @@ function handleCleanupScaffold(_cwd) {
6890
6930
  };
6891
6931
  }
6892
6932
  function registerScaffoldCleanupTools(server2) {
6893
- const DESC = "Deterministic scaffold remnant cleanup \u2014 removes stale OSS scaffold files after raft run.";
6933
+ const DESC2 = "Deterministic scaffold remnant cleanup \u2014 removes stale OSS scaffold files after raft run.";
6894
6934
  server2.tool(
6895
6935
  "stackwright_pro_cleanup_scaffold",
6896
- `Remove/rewrite stale scaffold files (blog posts, hardcoded not-found page) after the raft pipeline completes. ${DESC}`,
6936
+ `Remove/rewrite stale scaffold files (blog posts, hardcoded not-found page) after the raft pipeline completes. ${DESC2}`,
6897
6937
  {},
6898
6938
  async () => {
6899
6939
  const r = handleCleanupScaffold();
@@ -7461,10 +7501,100 @@ function registerStripLegacyIntegrationsTool(server2) {
7461
7501
  );
7462
7502
  }
7463
7503
 
7464
- // src/tools/list-specs.ts
7504
+ // src/tools/emitters.ts
7465
7505
  import { z as z22 } from "zod";
7466
- import { readdirSync as readdirSync5, readFileSync as readFileSync12, statSync, existsSync as existsSync12 } from "fs";
7467
- import { join as join13, extname, basename as basename2 } from "path";
7506
+ import { readFileSync as readFileSync12, existsSync as existsSync12, readdirSync as readdirSync5 } from "fs";
7507
+ import { join as join13 } from "path";
7508
+ import yaml from "js-yaml";
7509
+ import { emitEnvLocal } from "@stackwright-pro/emitters";
7510
+ function readIntegrations(cwd) {
7511
+ const filePath = join13(cwd, "stackwright.integrations.yml");
7512
+ if (!existsSync12(filePath)) return [];
7513
+ try {
7514
+ const raw = yaml.load(readFileSync12(filePath, "utf-8"));
7515
+ if (!raw?.integrations || !Array.isArray(raw.integrations)) return [];
7516
+ return raw.integrations.filter((i) => typeof i.name === "string").map((i) => ({
7517
+ name: i.name,
7518
+ auth: i.auth ? { type: i.auth.type, header: i.auth.header, envVar: i.auth.envVar } : void 0
7519
+ }));
7520
+ } catch {
7521
+ return [];
7522
+ }
7523
+ }
7524
+ function readServiceTokenRefs(cwd) {
7525
+ const servicesDir = join13(cwd, "services");
7526
+ if (!existsSync12(servicesDir)) return [];
7527
+ try {
7528
+ const files = readdirSync5(servicesDir).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
7529
+ const refs = [];
7530
+ for (const file of files) {
7531
+ try {
7532
+ const raw = yaml.load(
7533
+ readFileSync12(join13(servicesDir, file), "utf-8")
7534
+ );
7535
+ if (raw?.tokenEnv && typeof raw.tokenEnv === "string") {
7536
+ refs.push({
7537
+ name: raw.name ?? file.replace(/\.ya?ml$/, ""),
7538
+ tokenEnv: raw.tokenEnv
7539
+ });
7540
+ }
7541
+ } catch {
7542
+ }
7543
+ }
7544
+ return refs;
7545
+ } catch {
7546
+ return [];
7547
+ }
7548
+ }
7549
+ var DESC = "Returns { envLocal, envLocalExample } as JSON. The otter writes both files via stackwright_pro_safe_write.";
7550
+ function registerEmitterTools(server2) {
7551
+ server2.tool(
7552
+ "stackwright_pro_emit_env_local",
7553
+ `Emit .env.local + .env.local.example contents from stackwright.integrations.yml and services/*.yml. Deterministic emitter \u2014 same project config produces byte-identical output.
7554
+
7555
+ Call this tool, then write both files with stackwright_pro_safe_write:
7556
+ 1. stackwright_pro_emit_env_local({ cwd }) \u2192 { envLocal, envLocalExample }
7557
+ 2. stackwright_pro_safe_write({ filePath: '.env.local', content: envLocal, ... })
7558
+ 3. stackwright_pro_safe_write({ filePath: '.env.local.example', content: envLocalExample, ... })
7559
+
7560
+ Do NOT compose the contents by hand. This emitter is the source of truth. If an env var is missing, update integrations.yml or the emitter \u2014 not the file. This is the first concrete instance of the swp-zf9y deterministic emitter pattern. ${DESC}`,
7561
+ {
7562
+ cwd: z22.string().describe(
7563
+ "Absolute path to the project root containing stackwright.integrations.yml and optionally services/*.yml"
7564
+ )
7565
+ },
7566
+ async ({ cwd }) => {
7567
+ const integrations = readIntegrations(cwd);
7568
+ const services = readServiceTokenRefs(cwd);
7569
+ const output = emitEnvLocal({ integrations, services });
7570
+ return {
7571
+ content: [
7572
+ {
7573
+ type: "text",
7574
+ text: JSON.stringify(
7575
+ {
7576
+ envLocal: output.envLocal,
7577
+ envLocalExample: output.envLocalExample,
7578
+ meta: {
7579
+ integrationsRead: integrations.length,
7580
+ serviceTokenRefsRead: services.length,
7581
+ envVarsEmitted: (output.envLocal.match(/^NEXT_PUBLIC_[A-Z0-9_]+=.+$/m) ? output.envLocal.match(/^NEXT_PUBLIC_[A-Z0-9_]+=.+$/gm) ?? [] : []).length
7582
+ }
7583
+ },
7584
+ null,
7585
+ 2
7586
+ )
7587
+ }
7588
+ ]
7589
+ };
7590
+ }
7591
+ );
7592
+ }
7593
+
7594
+ // src/tools/list-specs.ts
7595
+ import { z as z23 } from "zod";
7596
+ import { readdirSync as readdirSync6, readFileSync as readFileSync13, statSync, existsSync as existsSync13 } from "fs";
7597
+ import { join as join14, extname, basename as basename2 } from "path";
7468
7598
  var STRIP_SUFFIXES = ["-openapi", "-asyncapi", "-api", "-spec"];
7469
7599
  var ALLOWED_EXTS = /* @__PURE__ */ new Set([".yaml", ".yml", ".json"]);
7470
7600
  function deriveIntegrationName(fileName) {
@@ -7486,18 +7616,18 @@ function detectFormat(snippet) {
7486
7616
  }
7487
7617
  function handleListSpecs(input) {
7488
7618
  const { projectRoot } = input;
7489
- const specsDir = join13(projectRoot, "specs");
7619
+ const specsDir = join14(projectRoot, "specs");
7490
7620
  const empty = { projectRoot, specs: [], totalCount: 0 };
7491
- if (!existsSync12(specsDir)) return empty;
7621
+ if (!existsSync13(specsDir)) return empty;
7492
7622
  let entries;
7493
7623
  try {
7494
- entries = readdirSync5(specsDir);
7624
+ entries = readdirSync6(specsDir);
7495
7625
  } catch {
7496
7626
  return empty;
7497
7627
  }
7498
7628
  const specs = [];
7499
7629
  for (const entry of entries) {
7500
- const fullPath = join13(specsDir, entry);
7630
+ const fullPath = join14(specsDir, entry);
7501
7631
  let stat;
7502
7632
  try {
7503
7633
  stat = statSync(fullPath);
@@ -7508,7 +7638,7 @@ function handleListSpecs(input) {
7508
7638
  if (!ALLOWED_EXTS.has(extname(entry).toLowerCase())) continue;
7509
7639
  let snippet = "";
7510
7640
  try {
7511
- snippet = readFileSync12(fullPath, "utf-8").slice(0, 2048);
7641
+ snippet = readFileSync13(fullPath, "utf-8").slice(0, 2048);
7512
7642
  } catch {
7513
7643
  }
7514
7644
  specs.push({
@@ -7527,7 +7657,7 @@ function registerListSpecsTool(server2) {
7527
7657
  "stackwright_pro_list_specs",
7528
7658
  "Enumerate OpenAPI/AsyncAPI specs in the project's specs/ directory. Returns one entry per spec with integration name (derived from filename), detected format, and size. Used by the foreman to fan out the api phase with one api-otter invocation per spec.",
7529
7659
  {
7530
- projectRoot: z22.string().describe("Absolute path to the project root directory")
7660
+ projectRoot: z23.string().describe("Absolute path to the project root directory")
7531
7661
  },
7532
7662
  async ({ projectRoot }) => {
7533
7663
  const result = handleListSpecs({ projectRoot });
@@ -7544,6 +7674,7 @@ var package_default = {
7544
7674
  "@modelcontextprotocol/sdk": "^1.10.0",
7545
7675
  "@stackwright/cli": "^0.9.0",
7546
7676
  "@stackwright-pro/auth-nextjs": "workspace:*",
7677
+ "@stackwright-pro/emitters": "workspace:*",
7547
7678
  "@stackwright-pro/cli-data-explorer": "workspace:*",
7548
7679
  "@stackwright-pro/openapi": "workspace:*",
7549
7680
  "@stackwright-pro/pulse": "workspace:*",
@@ -7571,7 +7702,7 @@ var package_default = {
7571
7702
  "test:coverage": "vitest run --coverage"
7572
7703
  },
7573
7704
  name: "@stackwright-pro/mcp",
7574
- version: "0.2.0-alpha.101",
7705
+ version: "0.2.0-alpha.102",
7575
7706
  description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
7576
7707
  license: "SEE LICENSE IN LICENSE",
7577
7708
  main: "./dist/server.js",
@@ -7651,6 +7782,7 @@ registerScaffoldCleanupTools(server);
7651
7782
  registerContrastTools(server);
7652
7783
  registerCompileTools(server);
7653
7784
  registerStripLegacyIntegrationsTool(server);
7785
+ registerEmitterTools(server);
7654
7786
  registerListSpecsTool(server);
7655
7787
  registerContentTypeTools(server);
7656
7788
  registerPageTools(server);