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

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 {
@@ -4199,7 +4214,8 @@ function registerPipelineTools(server2) {
4199
4214
  `Atomic read\u2192modify\u2192write pipeline state. ${DESC}`,
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()
@@ -4335,7 +4357,15 @@ function registerPipelineTools(server2) {
4335
4357
  "stackwright_pro_emit_event",
4336
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. ${DESC}`,
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.
@@ -5761,7 +5801,7 @@ import { join as join8, basename } from "path";
5761
5801
  var _checksums = /* @__PURE__ */ new Map([
5762
5802
  [
5763
5803
  "stackwright-pro-api-otter.json",
5764
- "175cca39127beea84ed8f1b264b8cd5cf58733db050d32328c039cca0cf0b981"
5804
+ "a5ff25531c330289af89e433e696ba1ffef8f7ea09985a559cf915592c9734ad"
5765
5805
  ],
5766
5806
  [
5767
5807
  "stackwright-pro-auth-otter.json",
@@ -5769,7 +5809,7 @@ var _checksums = /* @__PURE__ */ new Map([
5769
5809
  ],
5770
5810
  [
5771
5811
  "stackwright-pro-dashboard-otter.json",
5772
- "6918b51d1007c69e635f252b20b82774fa7c942fa1d2399769c14f8d1df4df70"
5812
+ "f8d594b14e05efea30cf253052d7c7df3e8c4174d739be4cd33f9c96cecdc451"
5773
5813
  ],
5774
5814
  [
5775
5815
  "stackwright-pro-data-otter.json",
@@ -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
+ "92930c732547c90a19e89ee0e25b5f037b7366f770941f0a01e148ff240a1b6d"
5813
5853
  ],
5814
5854
  [
5815
5855
  "stackwright-pro-theme-otter.json",
@@ -7461,10 +7501,187 @@ 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, emitProvidersFile, emitMockPorts } 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 ENV_LOCAL_DESC = "Returns { envLocal, envLocalExample } as JSON. The otter writes both files via stackwright_pro_safe_write.";
7550
+ var PROVIDERS_DESC = "Returns { providersFile } as JSON. The otter writes the file via stackwright_pro_safe_write.";
7551
+ var PORTS_DESC = "Returns { ports } as JSON \u2014 map of integration name \u2192 port number.";
7552
+ function registerEmitterTools(server2) {
7553
+ server2.tool(
7554
+ "stackwright_pro_emit_env_local",
7555
+ `Emit .env.local + .env.local.example contents from stackwright.integrations.yml and services/*.yml. Deterministic emitter \u2014 same project config produces byte-identical output.
7556
+
7557
+ Call this tool, then write both files with stackwright_pro_safe_write:
7558
+ 1. stackwright_pro_emit_env_local({ cwd }) \u2192 { envLocal, envLocalExample }
7559
+ 2. stackwright_pro_safe_write({ filePath: '.env.local', content: envLocal, ... })
7560
+ 3. stackwright_pro_safe_write({ filePath: '.env.local.example', content: envLocalExample, ... })
7561
+
7562
+ 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. ${ENV_LOCAL_DESC}`,
7563
+ {
7564
+ cwd: z22.string().describe(
7565
+ "Absolute path to the project root containing stackwright.integrations.yml and optionally services/*.yml"
7566
+ )
7567
+ },
7568
+ async ({ cwd }) => {
7569
+ const integrations = readIntegrations(cwd);
7570
+ const services = readServiceTokenRefs(cwd);
7571
+ const output = emitEnvLocal({ integrations, services });
7572
+ return {
7573
+ content: [
7574
+ {
7575
+ type: "text",
7576
+ text: JSON.stringify(
7577
+ {
7578
+ envLocal: output.envLocal,
7579
+ envLocalExample: output.envLocalExample,
7580
+ meta: {
7581
+ integrationsRead: integrations.length,
7582
+ serviceTokenRefsRead: services.length,
7583
+ envVarsEmitted: (output.envLocal.match(/^NEXT_PUBLIC_[A-Z0-9_]+=.+$/m) ? output.envLocal.match(/^NEXT_PUBLIC_[A-Z0-9_]+=.+$/gm) ?? [] : []).length
7584
+ }
7585
+ },
7586
+ null,
7587
+ 2
7588
+ )
7589
+ }
7590
+ ]
7591
+ };
7592
+ }
7593
+ );
7594
+ server2.tool(
7595
+ "stackwright_pro_emit_providers_file",
7596
+ `Emit app/_components/providers.tsx from stackwright.integrations.yml. Deterministic emitter \u2014 uses LITERAL env access per integration so Next.js can inline NEXT_PUBLIC_* vars at build time. Also registers the map provider (default: Cesium for Pro).
7597
+
7598
+ \u26A0\uFE0F CRITICAL: DO NOT compose providers.tsx by hand. Computed env access (process.env[varName]) returns undefined in browser bundles for NEXT_PUBLIC_* vars \u2014 this silently drops all auth headers and causes 401s on every integration.
7599
+
7600
+ Workflow:
7601
+ 1. stackwright_pro_emit_providers_file({ cwd, mapProvider: 'cesium' }) \u2192 { providersFile }
7602
+ 2. stackwright_pro_safe_write({ filePath: 'app/_components/providers.tsx', content: providersFile, ... })
7603
+
7604
+ mapProvider options:
7605
+ - 'cesium' (default for Pro): 3D globe + terrain, @stackwright-pro/cesium + cesium peer dep
7606
+ - 'maplibre': free-tier 2D maps, no API key \u2014 OSS-style 2D dashboards only (opt-out)
7607
+ - 'none': skip map registration (ONLY if no pages use map content_items)
7608
+
7609
+ This is the second concrete instance of the swp-zf9y deterministic emitter pattern. Refs: swp-57ku, swp-2m89, swp-zf9y, drawer 957. ${PROVIDERS_DESC}`,
7610
+ {
7611
+ cwd: z22.string().describe("Absolute path to the project root containing stackwright.integrations.yml"),
7612
+ mapProvider: z22.enum(["maplibre", "cesium", "none"]).optional().describe(
7613
+ "Map provider to register (default: cesium for Pro \u2014 3D globe + terrain). Use maplibre for OSS-style 2D dashboards (explicit opt-out). Use none if pages have no map content_items."
7614
+ )
7615
+ },
7616
+ async ({ cwd, mapProvider }) => {
7617
+ const integrations = readIntegrations(cwd);
7618
+ const providersFile = emitProvidersFile({ integrations, mapProvider });
7619
+ return {
7620
+ content: [
7621
+ {
7622
+ type: "text",
7623
+ text: JSON.stringify(
7624
+ {
7625
+ providersFile,
7626
+ meta: {
7627
+ integrationsRead: integrations.length,
7628
+ integrationsWithAuth: integrations.filter((i) => i.auth?.envVar).length,
7629
+ mapProvider: mapProvider ?? "cesium"
7630
+ }
7631
+ },
7632
+ null,
7633
+ 2
7634
+ )
7635
+ }
7636
+ ]
7637
+ };
7638
+ }
7639
+ );
7640
+ server2.tool(
7641
+ "stackwright_pro_emit_mock_ports",
7642
+ `Emit mock backend port assignments from stackwright.integrations.yml. Deterministic emitter \u2014 assigns consecutive ports starting at 4011 to each integration in declaration order. Skipped integrations (skipMockPort=true) are omitted and do not consume a port number.
7643
+
7644
+ \u26A0\uFE0F DO NOT pick mockUrl port numbers yourself. Port collisions occur when different models pick different defaults (Opus always picked 4010 for all integrations in run-4).
7645
+
7646
+ Workflow:
7647
+ 1. stackwright_pro_emit_mock_ports({ cwd }) \u2192 { ports }
7648
+ 2. For each integration, set mockUrl to http://localhost:<ports[name]>
7649
+ 3. Write stackwright.integrations.yml via stackwright_pro_safe_write
7650
+
7651
+ This is the third concrete instance of the swp-zf9y deterministic emitter pattern. Refs: swp-phkh, swp-zf9y. ${PORTS_DESC}`,
7652
+ {
7653
+ cwd: z22.string().describe("Absolute path to the project root containing stackwright.integrations.yml")
7654
+ },
7655
+ async ({ cwd }) => {
7656
+ const integrations = readIntegrations(cwd);
7657
+ const { ports } = emitMockPorts({ integrations });
7658
+ return {
7659
+ content: [
7660
+ {
7661
+ type: "text",
7662
+ text: JSON.stringify(
7663
+ {
7664
+ ports,
7665
+ meta: {
7666
+ integrationsRead: integrations.length,
7667
+ portsAssigned: Object.keys(ports).length,
7668
+ portRange: Object.keys(ports).length > 0 ? `${Math.min(...Object.values(ports))}\u2013${Math.max(...Object.values(ports))}` : "none"
7669
+ }
7670
+ },
7671
+ null,
7672
+ 2
7673
+ )
7674
+ }
7675
+ ]
7676
+ };
7677
+ }
7678
+ );
7679
+ }
7680
+
7681
+ // src/tools/list-specs.ts
7682
+ import { z as z23 } from "zod";
7683
+ import { readdirSync as readdirSync6, readFileSync as readFileSync13, statSync, existsSync as existsSync13 } from "fs";
7684
+ import { join as join14, extname, basename as basename2 } from "path";
7468
7685
  var STRIP_SUFFIXES = ["-openapi", "-asyncapi", "-api", "-spec"];
7469
7686
  var ALLOWED_EXTS = /* @__PURE__ */ new Set([".yaml", ".yml", ".json"]);
7470
7687
  function deriveIntegrationName(fileName) {
@@ -7486,18 +7703,18 @@ function detectFormat(snippet) {
7486
7703
  }
7487
7704
  function handleListSpecs(input) {
7488
7705
  const { projectRoot } = input;
7489
- const specsDir = join13(projectRoot, "specs");
7706
+ const specsDir = join14(projectRoot, "specs");
7490
7707
  const empty = { projectRoot, specs: [], totalCount: 0 };
7491
- if (!existsSync12(specsDir)) return empty;
7708
+ if (!existsSync13(specsDir)) return empty;
7492
7709
  let entries;
7493
7710
  try {
7494
- entries = readdirSync5(specsDir);
7711
+ entries = readdirSync6(specsDir);
7495
7712
  } catch {
7496
7713
  return empty;
7497
7714
  }
7498
7715
  const specs = [];
7499
7716
  for (const entry of entries) {
7500
- const fullPath = join13(specsDir, entry);
7717
+ const fullPath = join14(specsDir, entry);
7501
7718
  let stat;
7502
7719
  try {
7503
7720
  stat = statSync(fullPath);
@@ -7508,7 +7725,7 @@ function handleListSpecs(input) {
7508
7725
  if (!ALLOWED_EXTS.has(extname(entry).toLowerCase())) continue;
7509
7726
  let snippet = "";
7510
7727
  try {
7511
- snippet = readFileSync12(fullPath, "utf-8").slice(0, 2048);
7728
+ snippet = readFileSync13(fullPath, "utf-8").slice(0, 2048);
7512
7729
  } catch {
7513
7730
  }
7514
7731
  specs.push({
@@ -7527,7 +7744,7 @@ function registerListSpecsTool(server2) {
7527
7744
  "stackwright_pro_list_specs",
7528
7745
  "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
7746
  {
7530
- projectRoot: z22.string().describe("Absolute path to the project root directory")
7747
+ projectRoot: z23.string().describe("Absolute path to the project root directory")
7531
7748
  },
7532
7749
  async ({ projectRoot }) => {
7533
7750
  const result = handleListSpecs({ projectRoot });
@@ -7544,6 +7761,7 @@ var package_default = {
7544
7761
  "@modelcontextprotocol/sdk": "^1.10.0",
7545
7762
  "@stackwright/cli": "^0.9.0",
7546
7763
  "@stackwright-pro/auth-nextjs": "workspace:*",
7764
+ "@stackwright-pro/emitters": "workspace:*",
7547
7765
  "@stackwright-pro/cli-data-explorer": "workspace:*",
7548
7766
  "@stackwright-pro/openapi": "workspace:*",
7549
7767
  "@stackwright-pro/pulse": "workspace:*",
@@ -7571,7 +7789,7 @@ var package_default = {
7571
7789
  "test:coverage": "vitest run --coverage"
7572
7790
  },
7573
7791
  name: "@stackwright-pro/mcp",
7574
- version: "0.2.0-alpha.101",
7792
+ version: "0.2.0-alpha.103",
7575
7793
  description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
7576
7794
  license: "SEE LICENSE IN LICENSE",
7577
7795
  main: "./dist/server.js",
@@ -7651,6 +7869,7 @@ registerScaffoldCleanupTools(server);
7651
7869
  registerContrastTools(server);
7652
7870
  registerCompileTools(server);
7653
7871
  registerStripLegacyIntegrationsTool(server);
7872
+ registerEmitterTools(server);
7654
7873
  registerListSpecsTool(server);
7655
7874
  registerContentTypeTools(server);
7656
7875
  registerPageTools(server);