@stackwright-pro/mcp 0.2.0-alpha.0 → 0.2.0-alpha.1

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.
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/server.js CHANGED
@@ -111,8 +111,8 @@ function registerDataExplorerTools(server2) {
111
111
  lines.push(" endpoints:");
112
112
  if (result.filter.include && result.filter.include.length > 0) {
113
113
  lines.push(" include:");
114
- for (const path4 of result.filter.include) {
115
- lines.push(` - ${path4}`);
114
+ for (const path3 of result.filter.include) {
115
+ lines.push(` - ${path3}`);
116
116
  }
117
117
  }
118
118
  if (result.filter.exclude && result.filter.exclude.length > 0) {
@@ -142,6 +142,7 @@ function registerDataExplorerTools(server2) {
142
142
 
143
143
  // src/tools/security.ts
144
144
  var import_zod2 = require("zod");
145
+ var import_crypto = require("crypto");
145
146
  var import_fs = __toESM(require("fs"));
146
147
  var import_path = __toESM(require("path"));
147
148
  function registerSecurityTools(server2) {
@@ -219,8 +220,7 @@ This spec is not on the approved-specs allowlist. Add it using stackwright_pro_a
219
220
  if (!specPath.startsWith("http://") && !specPath.startsWith("https://")) {
220
221
  if (import_fs.default.existsSync(specPath)) {
221
222
  const specContent = import_fs.default.readFileSync(specPath, "utf8");
222
- const crypto = require("crypto");
223
- const sha256 = crypto.createHash("sha256").update(specContent).digest("hex");
223
+ const sha256 = (0, import_crypto.createHash)("sha256").update(specContent).digest("hex");
224
224
  if (sha256 !== matchingSpec.sha256) {
225
225
  return {
226
226
  content: [
@@ -271,8 +271,7 @@ Status: Valid (${allowlist.length} specs on allowlist)`
271
271
  sha256 = "<computed-at-build>";
272
272
  } else if (import_fs.default.existsSync(url)) {
273
273
  const specContent = import_fs.default.readFileSync(url, "utf8");
274
- const crypto = require("crypto");
275
- sha256 = crypto.createHash("sha256").update(specContent).digest("hex");
274
+ sha256 = (0, import_crypto.createHash)("sha256").update(specContent).digest("hex");
276
275
  } else {
277
276
  return {
278
277
  content: [
@@ -650,11 +649,11 @@ var import_zod5 = require("zod");
650
649
  var import_child_process = require("child_process");
651
650
  var import_os = require("os");
652
651
  var import_path2 = require("path");
653
- var import_crypto = require("crypto");
652
+ var import_crypto2 = require("crypto");
654
653
  var import_fs2 = require("fs");
655
654
  var activeServers = /* @__PURE__ */ new Map();
656
655
  async function startPythonServer(sessionId) {
657
- const socketPath = (0, import_path2.join)((0, import_os.tmpdir)(), `otter-raft-${(0, import_crypto.randomUUID)()}.sock`);
656
+ const socketPath = (0, import_path2.join)((0, import_os.tmpdir)(), `otter-raft-${(0, import_crypto2.randomUUID)()}.sock`);
658
657
  const port = 8765 + Math.floor(Math.random() * 100);
659
658
  return new Promise((resolve, reject) => {
660
659
  const pythonPath = process.platform === "win32" ? "python" : "python3";
@@ -716,10 +715,10 @@ async function stopPythonServer(sessionId) {
716
715
  activeServers.delete(sessionId);
717
716
  }
718
717
  }
719
- async function httpRequest(host, port, path4, body) {
718
+ async function httpRequest(host, port, path3, body) {
720
719
  const http = await import("http");
721
720
  return new Promise((resolve, reject) => {
722
- const url = new URL(path4, `http://${host}:${port}`);
721
+ const url = new URL(path3, `http://${host}:${port}`);
723
722
  const reqOptions = {
724
723
  hostname: host,
725
724
  port,
@@ -780,7 +779,7 @@ function registerClarificationTools(server2) {
780
779
  target_field: import_zod5.z.string().optional().describe("What field/config does this clarify?")
781
780
  },
782
781
  async ({ context, question_type, question, choices, priority = "preferred", target_field }) => {
783
- const sessionId = `mcp_${(0, import_crypto.randomUUID)().slice(0, 8)}`;
782
+ const sessionId = `mcp_${(0, import_crypto2.randomUUID)().slice(0, 8)}`;
784
783
  try {
785
784
  const { port } = await startPythonServer(sessionId);
786
785
  await httpRequest(port === 8765 ? "127.0.0.1" : "127.0.0.1", port, "/sessions", {});
@@ -862,7 +861,7 @@ Cannot proceed without user input. Consider:
862
861
  selected_values: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.string()).describe("What the user actually selected")
863
862
  },
864
863
  async ({ stated_preference, selected_values }) => {
865
- const sessionId = `mcp_${(0, import_crypto.randomUUID)().slice(0, 8)}`;
864
+ const sessionId = `mcp_${(0, import_crypto2.randomUUID)().slice(0, 8)}`;
866
865
  try {
867
866
  const { port } = await startPythonServer(sessionId);
868
867
  const response = await httpRequest(
@@ -959,26 +958,20 @@ function registerPackageTools(server2) {
959
958
  packages: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).describe(
960
959
  'Dependencies to add. Record<packageName, version>. e.g. { "@stackwright-pro/auth": "latest" }'
961
960
  ),
962
- devPackages: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).optional().describe(
963
- "devDependencies to add. Same format as packages."
964
- ),
965
- scripts: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).optional().describe(
966
- "npm scripts to add. Only adds if key does not already exist."
967
- ),
961
+ devPackages: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).optional().describe("devDependencies to add. Same format as packages."),
962
+ scripts: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).optional().describe("npm scripts to add. Only adds if key does not already exist."),
968
963
  targetDir: import_zod6.z.string().optional().describe(
969
964
  "Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory."
970
965
  ),
971
- runInstall: import_zod6.z.boolean().optional().default(true).describe(
972
- "Run pnpm install after writing package.json. Defaults to true."
973
- )
966
+ runInstall: import_zod6.z.boolean().optional().default(true).describe("Run pnpm install after writing package.json. Defaults to true.")
974
967
  },
975
968
  async ({ packages, devPackages, scripts, targetDir, runInstall }) => {
976
969
  const result = setupPackages({
977
970
  packages,
978
- devPackages,
979
- scripts,
980
- targetDir,
981
- runInstall
971
+ runInstall,
972
+ ...devPackages !== void 0 ? { devPackages } : {},
973
+ ...scripts !== void 0 ? { scripts } : {},
974
+ ...targetDir !== void 0 ? { targetDir } : {}
982
975
  });
983
976
  const statusLine = result.success ? `\u2705 package.json updated: ${result.packageJsonPath}` : `\u274C Failed: ${result.error}`;
984
977
  const lines = [
@@ -1201,17 +1194,57 @@ function setupPackages(opts) {
1201
1194
  ...installError !== void 0 ? { installError } : {}
1202
1195
  };
1203
1196
  } catch (err) {
1204
- return { ...emptyResult, success: false, error: err instanceof Error ? err.message : String(err) };
1197
+ return {
1198
+ ...emptyResult,
1199
+ success: false,
1200
+ error: err instanceof Error ? err.message : String(err)
1201
+ };
1205
1202
  }
1206
1203
  }
1207
1204
 
1205
+ // package.json
1206
+ var package_default = {
1207
+ dependencies: {
1208
+ "@modelcontextprotocol/sdk": "^1.10.0",
1209
+ "@stackwright-pro/cli-data-explorer": "workspace:*",
1210
+ zod: "^4.3.6"
1211
+ },
1212
+ devDependencies: {
1213
+ "@types/node": "^24.1.0",
1214
+ tsup: "^8.5.0",
1215
+ typescript: "^5.8.3",
1216
+ vitest: "^4.0.18"
1217
+ },
1218
+ scripts: {
1219
+ build: "tsup src/server.ts --format cjs,esm --dts --clean",
1220
+ dev: "tsup src/server.ts --format cjs,esm --dts --watch",
1221
+ start: "node dist/server.js",
1222
+ test: "vitest run",
1223
+ "test:coverage": "vitest run --coverage"
1224
+ },
1225
+ name: "@stackwright-pro/mcp",
1226
+ version: "0.2.0-alpha.0",
1227
+ description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
1228
+ license: "PROPRIETARY",
1229
+ main: "./dist/server.js",
1230
+ module: "./dist/server.mjs",
1231
+ types: "./dist/server.d.ts",
1232
+ exports: {
1233
+ ".": {
1234
+ types: "./dist/server.d.ts",
1235
+ import: "./dist/server.mjs",
1236
+ require: "./dist/server.js"
1237
+ }
1238
+ },
1239
+ files: [
1240
+ "dist"
1241
+ ]
1242
+ };
1243
+
1208
1244
  // src/server.ts
1209
- var import_fs4 = require("fs");
1210
- var import_path4 = __toESM(require("path"));
1211
- var packageJson = JSON.parse((0, import_fs4.readFileSync)(import_path4.default.join(__dirname, "package.json"), "utf8"));
1212
1245
  var server = new import_mcp.McpServer({
1213
1246
  name: "stackwright-pro",
1214
- version: packageJson.version
1247
+ version: package_default.version
1215
1248
  });
1216
1249
  registerDataExplorerTools(server);
1217
1250
  registerSecurityTools(server);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts","../src/tools/clarification.ts","../src/tools/packages.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\nimport { registerClarificationTools } from './tools/clarification.js';\nimport { registerPackageTools } from './tools/packages.js';\nimport { readFileSync } from 'fs';\nimport path from 'path';\n\n// Dynamic version from package.json\nconst packageJson = JSON.parse(readFileSync(path.join(__dirname, 'package.json'), 'utf8'));\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: packageJson.version,\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\nregisterClarificationTools(server); // stackwright_pro_clarify, stackwright_pro_detect_conflict, stackwright_pro_get_defaults\nregisterPackageTools(server); // stackwright_pro_setup_packages\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n ...(specPath !== undefined && { specPath }),\n ...(projectRoot !== undefined && { projectRoot }),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`📦 Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`📦 ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\n💡 Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: z\n .array(z.string())\n .describe('Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'),\n excludePatterns: z\n .array(z.string())\n .optional()\n .describe('Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'),\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n ...(excludePatterns !== undefined && { excludePatterns }),\n projectRoot: projectRoot ?? process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['🔐 Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\n⚠️ Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n const allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const crypto = require('crypto');\n const sha256 = crypto.createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time\n sha256 = '<computed-at-build>';\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n const crypto = require('crypto');\n sha256 = crypto.createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📝 Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: '❌ stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`🔐 Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`📦 ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: z\n .number()\n .optional()\n .describe('Revalidation interval in seconds (default: 60)'),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description = '';\n if (revalidate < 60) {\n description = '⚡ Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = '📊 Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = '💾 Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n '🗄️ Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `⚙️ ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? '⏳ Show loading until cached' : fallback === 'true' ? '📄 Generate on demand' : '❌ 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: z\n .array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: z.number().optional().describe('Revalidation interval'),\n })\n )\n .describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`⚙️ Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = '💾';\n if (rev < 60) freshness = '⚡';\n else if (rev < 300) freshness = '📊';\n else if (rev >= 3600) freshness = '🗄️';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with grid, metric_card, data_table, and collection_list content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: z.array(z.string()).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add metric cards in a grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - type: grid`);\n yamlLines.push(` columns: 4`);\n yamlLines.push(` items:`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Total\"`);\n yamlLines.push(` value: {{ ${slug}.count }}`);\n yamlLines.push(` icon: Database`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Active\"`);\n yamlLines.push(` value: 0`);\n yamlLines.push(` icon: CheckCircle`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - type: collection_list`);\n yamlLines.push(` label: ${entities[0]}-listing`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['id', 'name', 'status', 'created_at'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => f.name)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - type: data_table`);\n yamlLines.push(` label: ${entities[0]}-table`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` columns:`);\n yamlLines.push(` - field: id`);\n yamlLines.push(` header: ID`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: name`);\n yamlLines.push(` header: Name`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: status`);\n yamlLines.push(` header: Status`);\n yamlLines.push(` type: badge`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📊 Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - main:',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n ' background: \"primary\"',\n ' color: \"text\"',\n '',\n ' - grid:',\n ' label: \"detail-fields\"',\n ' columns: 2',\n ' items:',\n ];\n\n // Add field cards\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n for (const field of displayFields) {\n const label = field.name.replace(/_/g, ' ').replace(/\\b\\w/g, (l: string) => l.toUpperCase());\n yamlLines.push(` - card:`);\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(` textSize: \"h4\"`);\n yamlLines.push(` content:`);\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(` textSize: \"body1\"`);\n }\n\n yamlLines.push(' background: \"background\"');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📄 Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n","/**\n * Clarification MCP Tools\n *\n * Provides human-in-the-loop clarification for otters that encounter\n * ambiguity during execution.\n *\n * This bridges to the Python Clarification Protocol server which\n * handles:\n * - Channel routing (TUI, CLI args, config, defaults)\n * - Conflict detection\n * - Stubborn user escalation\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { spawn, ChildProcess } from 'child_process';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { randomUUID } from 'crypto';\nimport { existsSync, unlinkSync } from 'fs';\n\n// Types matching Python server\nexport interface ClarificationRequest {\n context?: string;\n question_type: 'closed_choice' | 'open_text' | 'conditional' | 'multi_step' | 'reconciliation';\n question: string;\n choices?: string[];\n priority?: 'blocking' | 'preferred' | 'optional';\n target_field?: string;\n}\n\nexport interface ClarificationResponse {\n request_id: string;\n decision: {\n value: unknown;\n explicit: boolean;\n source: string;\n };\n fallback_used: boolean;\n fallback_reason?: string;\n}\n\n// Track active Python server processes\nconst activeServers: Map<string, ChildProcess> = new Map();\n\n/**\n * Start the Python Clarification Protocol server\n */\nasync function startPythonServer(sessionId: string): Promise<{ port: number; socketPath: string }> {\n const socketPath = join(tmpdir(), `otter-raft-${randomUUID()}.sock`);\n const port = 8765 + Math.floor(Math.random() * 100); // Random port to avoid conflicts\n\n return new Promise((resolve, reject) => {\n const pythonPath = process.platform === 'win32' ? 'python' : 'python3';\n\n // Find Python package\n const packageRoot = findPythonPackageRoot();\n\n const proc = spawn(\n pythonPath,\n ['-m', 'stackwright_pro.raft.server', '--socket', socketPath, '--port', String(port)],\n {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PYTHONPATH: packageRoot,\n },\n }\n );\n\n // Register process for cleanup\n activeServers.set(sessionId, proc);\n\n let startupOutput = '';\n let started = false;\n\n proc.stdout?.on('data', (data: Buffer) => {\n startupOutput += data.toString();\n if (startupOutput.includes('Server ready') || startupOutput.includes('HTTP server')) {\n started = true;\n resolve({ port, socketPath });\n }\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n // Only log errors, not startup messages\n if (!startupOutput.includes('Starting')) {\n console.error('[Python Clarification]', data.toString().trim());\n }\n });\n\n proc.on('error', (err) => {\n if (!started) {\n activeServers.delete(sessionId);\n reject(new Error(`Failed to start Python server: ${err.message}`));\n }\n });\n\n proc.on('exit', (code) => {\n activeServers.delete(sessionId);\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath);\n } catch {\n // Ignore cleanup errors\n }\n }\n });\n\n // Timeout after 10 seconds\n setTimeout(() => {\n if (!started) {\n proc.kill();\n activeServers.delete(sessionId);\n reject(new Error('Python server startup timeout'));\n }\n }, 10000);\n });\n}\n\n/**\n * Stop the Python server for a session\n */\nasync function stopPythonServer(sessionId: string): Promise<void> {\n const proc = activeServers.get(sessionId);\n if (proc) {\n proc.kill('SIGTERM');\n activeServers.delete(sessionId);\n }\n}\n\n/**\n * Make HTTP request to Python server\n */\nasync function httpRequest<T>(\n host: string,\n port: number,\n path: string,\n body?: unknown\n): Promise<T> {\n const http = await import('http');\n\n return new Promise((resolve, reject) => {\n const url = new URL(path, `http://${host}:${port}`);\n\n const reqOptions = {\n hostname: host,\n port: port,\n path: url.pathname,\n method: body ? 'POST' : 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n\n const req = http.request(reqOptions, (res) => {\n let data = '';\n\n res.on('data', (chunk: Buffer) => {\n data += chunk.toString();\n });\n\n res.on('end', () => {\n try {\n const parsed = JSON.parse(data);\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(parsed.detail || parsed.error || `HTTP ${res.statusCode}`));\n } else {\n resolve(parsed);\n }\n } catch (e) {\n reject(new Error(`Failed to parse response: ${data}`));\n }\n });\n });\n\n req.on('error', reject);\n\n if (body) {\n req.write(JSON.stringify(body));\n }\n\n req.end();\n });\n}\n\n/**\n * Find Python package root\n */\nfunction findPythonPackageRoot(): string {\n const candidates = [\n join(__dirname, '../../python/src'),\n join(__dirname, '../../../python/src'),\n join(process.cwd(), 'python/src'),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return process.cwd();\n}\n\n/**\n * Register clarification MCP tools\n */\nexport function registerClarificationTools(server: McpServer): void {\n // Tool: Ask for clarification (creates session)\n server.tool(\n 'stackwright_pro_clarify',\n 'Ask the user for clarification when an otter encounters ambiguity. ' +\n 'This is for MID-EXECUTION questions, not upfront question collection. ' +\n 'Use this when the otter needs user input to proceed. ' +\n \"Returns the user's decision which should be used to continue execution.\",\n {\n context: z.string().optional().describe('Context about what the otter is trying to do'),\n question_type: z\n .enum(['closed_choice', 'open_text', 'conditional', 'multi_step', 'reconciliation'])\n .describe('Type of question being asked'),\n question: z.string().describe('The clarification question to ask the user'),\n choices: z\n .array(z.string())\n .optional()\n .describe('Options for closed_choice or multi_step questions'),\n priority: z\n .enum(['blocking', 'preferred', 'optional'])\n .optional()\n .describe('How critical is this clarification? Default: preferred'),\n target_field: z.string().optional().describe('What field/config does this clarify?'),\n },\n async ({ context, question_type, question, choices, priority = 'preferred', target_field }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Create session\n await httpRequest(port === 8765 ? '127.0.0.1' : '127.0.0.1', port, '/sessions', {});\n\n // Set context if provided\n if (context) {\n await httpRequest(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n `/sessions/${sessionId}/context`,\n { context: { purpose: context } }\n );\n }\n\n // Ask for clarification\n const request: ClarificationRequest = {\n ...(context !== undefined && { context }),\n question_type,\n question,\n ...(choices !== undefined && { choices }),\n priority,\n ...(target_field !== undefined && { target_field }),\n };\n\n const response = await httpRequest<ClarificationResponse>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/clarify',\n { request }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n // Format response for LLM\n const decision = response.decision;\n const value = decision.value;\n const source = decision.source;\n const explicit = decision.explicit ? 'explicitly' : 'via fallback';\n\n if (response.fallback_used) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ Clarification fallback used: ${response.fallback_reason || 'No user input available'}\\n\\n` +\n `Default value used: ${JSON.stringify(value)}\\n\\n` +\n `💡 Consider following up with the user later if this default isn't appropriate.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `✅ User clarified (${source}): ${JSON.stringify(value)}\\n\\n` +\n `Use this value to continue execution.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n // If server not available, try stdio mode as fallback\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Clarification failed: ${error instanceof Error ? error.message : 'Unknown error'}\\n\\n` +\n `Cannot proceed without user input. Consider:\\n` +\n `1. Using a reasonable default\\n` +\n `2. Asking the user directly in your response\\n` +\n `3. Skipping this step if optional`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Detect preference conflict\n server.tool(\n 'stackwright_pro_detect_conflict',\n \"Detect when a user's stated preference conflicts with their selected choices. \" +\n 'Use this to identify when users might be indecisive or misunderstood a question. ' +\n 'Returns conflict details and resolution options.',\n {\n stated_preference: z.string().describe('What the user said they wanted'),\n selected_values: z.record(z.string(), z.string()).describe('What the user actually selected'),\n },\n async ({ stated_preference, selected_values }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Check for conflict\n const response = await httpRequest<{ conflict: boolean; data?: any }>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/conflict',\n { stated_preference, selected_values }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n if (response.conflict) {\n const data = response.data;\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ CONFLICT DETECTED\\n\\n` +\n `User stated: \"${stated_preference}\"\\n` +\n `But selected: ${JSON.stringify(selected_values)}\\n\\n` +\n `Conflict: ${data.description}\\n\\n` +\n `Resolution options: ${data.options?.join(', ') || 'Ask user to clarify'}\\n\\n` +\n `💡 Consider asking the user to reconcile this conflict.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ No conflict detected between stated preference and selections.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Conflict detection failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Get clarification defaults\n server.tool(\n 'stackwright_pro_get_defaults',\n 'Get the current clarification defaults from config. ' +\n \"Use this to understand what fallback values will be used if user doesn't provide input.\",\n {\n config_path: z\n .string()\n .optional()\n .describe('Path to config file. Default: .stackwright/clarification.yaml'),\n },\n async ({ config_path }) => {\n // This reads from the Python config module directly\n // For now, return a message pointing to where config is stored\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `📋 Clarification defaults\\n\\n` +\n `Configuration is loaded from:\\n` +\n `- Environment: CLARIFICATION_* variables\\n` +\n `- Config file: ${config_path || '.stackwright/clarification.yaml'}\\n` +\n `- CLI args: --clarify-* flags\\n\\n` +\n `Default behaviors:\\n` +\n `- allow_dont_know: true (users can skip)\\n` +\n `- default_timeout: 120 seconds\\n` +\n `- channel_priority: [tui, cli_args, config, defaults]\\n\\n` +\n `💡 Set CLARIFICATION_DEFAULT_<FIELD>=value to change defaults.`,\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, realpathSync, lstatSync } from 'fs';\nimport { execSync } from 'child_process';\nimport path from 'path';\n\n/**\n * stackwright_pro_setup_packages MCP tool\n *\n * Ensures pro packages are present in a project's package.json.\n * Used by the Pro Foreman Otter to bootstrap dependencies before\n * specialist otters run — enabling the otter raft's IoC dependency\n * declaration pattern.\n *\n * Merge semantics: NEVER overwrites an existing version pin.\n * If a package is already declared at any version, it is skipped.\n * This preserves intentional version pinning by developers.\n */\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n [key: string]: unknown;\n}\n\ninterface SetupPackagesResult {\n success: boolean;\n added: string[];\n skipped: string[];\n scriptsAdded: string[];\n installed: boolean;\n packageJsonPath: string;\n error?: string;\n installError?: string;\n}\n\nexport function registerPackageTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_setup_packages',\n 'Ensures pro packages are present in a project\\'s package.json. ' +\n 'Safe to call multiple times — never overwrites existing version pins. ' +\n 'Use this to bootstrap dependencies before specialist otters run.',\n {\n // FIX 3 (B-new-1): Zod v4 requires two-arg z.record(keySchema, valueSchema)\n packages: z.record(z.string(), z.string()).describe(\n 'Dependencies to add. Record<packageName, version>. e.g. { \"@stackwright-pro/auth\": \"latest\" }'\n ),\n devPackages: z.record(z.string(), z.string()).optional().describe(\n 'devDependencies to add. Same format as packages.'\n ),\n scripts: z.record(z.string(), z.string()).optional().describe(\n 'npm scripts to add. Only adds if key does not already exist.'\n ),\n targetDir: z.string().optional().describe(\n 'Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory.'\n ),\n runInstall: z.boolean().optional().default(true).describe(\n 'Run pnpm install after writing package.json. Defaults to true.'\n ),\n },\n async ({ packages, devPackages, scripts, targetDir, runInstall }) => {\n const result = setupPackages({\n packages,\n devPackages,\n scripts,\n targetDir,\n runInstall,\n });\n\n const statusLine = result.success\n ? `✅ package.json updated: ${result.packageJsonPath}`\n : `❌ Failed: ${result.error}`;\n\n const lines = [\n statusLine,\n '',\n result.added.length > 0\n ? `Added (${result.added.length}): ${result.added.join(', ')}`\n : 'Added: none',\n result.skipped.length > 0\n ? `Skipped/already present (${result.skipped.length}): ${result.skipped.join(', ')}`\n : 'Skipped: none',\n result.scriptsAdded.length > 0\n ? `Scripts added (${result.scriptsAdded.length}): ${result.scriptsAdded.join(', ')}`\n : 'Scripts added: none',\n `pnpm install: ${result.installed ? 'ran successfully' : result.success && runInstall ? 'failed (non-fatal)' : 'skipped'}`,\n ];\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n\n/**\n * Core implementation — extracted so it can be tested directly without\n * going through the MCP server machinery. Keeping I/O at the edges.\n */\nexport function setupPackages(opts: {\n packages: Record<string, string>;\n devPackages?: Record<string, string>;\n scripts?: Record<string, string>;\n targetDir?: string;\n runInstall: boolean;\n}): SetupPackagesResult {\n const emptyResult: Omit<SetupPackagesResult, 'success' | 'error'> = {\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n };\n\n try {\n // -------------------------------------------------------------------------\n // Security: path traversal guard\n // -------------------------------------------------------------------------\n const cwd = process.cwd();\n const resolvedTarget = opts.targetDir\n ? path.resolve(opts.targetDir)\n : cwd;\n\n // Ensure resolved path stays within cwd — no sneaky ../../etc tricks\n const cwdWithSep = cwd.endsWith(path.sep) ? cwd : cwd + path.sep;\n if (resolvedTarget !== cwd && !resolvedTarget.startsWith(cwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory is outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Find package.json (existence check before symlink resolution)\n // -------------------------------------------------------------------------\n const preResolvePackageJsonPath = path.join(resolvedTarget, 'package.json');\n\n if (!existsSync(preResolvePackageJsonPath)) {\n return {\n success: false,\n ...emptyResult,\n error: `No package.json found in ${resolvedTarget}`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: directory-level symlink bypass guard (B2)\n // -------------------------------------------------------------------------\n let realTarget: string;\n try {\n realTarget = realpathSync(resolvedTarget);\n } catch {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n error: `Could not resolve real path of target directory`,\n };\n }\n\n const realCwd = realpathSync(cwd);\n const realCwdWithSep = realCwd.endsWith(path.sep) ? realCwd : realCwd + path.sep;\n if (realTarget !== realCwd && !realTarget.startsWith(realCwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory resolved to a location outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: file-level symlink guard at package.json (C-1 / FIX 1)\n // -------------------------------------------------------------------------\n // Reconstruct package.json path from the symlink-resolved target directory.\n // This prevents readFileSync / writeFileSync from following a file-level\n // symlink planted at <targetDir>/package.json.\n const realPackageJsonPath = path.join(realTarget, 'package.json');\n\n const pkgStat = lstatSync(realPackageJsonPath);\n if (pkgStat.isSymbolicLink()) {\n return {\n ...emptyResult,\n success: false,\n error: `package.json is a symlink — refusing to read or write`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: package name validation (C-2C / L-1)\n // -------------------------------------------------------------------------\n // npm package name spec: optional @scope/, then lowercase alphanumeric + hyphens/dots/underscores\n const VALID_PKG_NAME_RE = /^(@[a-z0-9][a-z0-9\\-._~]*\\/)?[a-z0-9][a-z0-9\\-._~]*$/;\n const allPkgNames = [\n ...Object.keys(opts.packages ?? {}),\n ...Object.keys(opts.devPackages ?? {}),\n ];\n for (const pkg of allPkgNames) {\n if (!VALID_PKG_NAME_RE.test(pkg)) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package name: '${pkg}' — must match npm package name specification`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: version string allowlist (C-2B / FIX 2B)\n // -------------------------------------------------------------------------\n // Allows: semver ranges (^1.0.0, ~2.1, >=3, 1.x, *), workspace:*, latest/next/beta/alpha/canary/rc\n // Blocks: git+https://, file:, npm:evil@, http://, ssh://, etc.\n const SAFE_VERSION_RE =\n /^(workspace:[*^~]?|\\*|latest|next|beta|alpha|canary|rc|[~^><=*|, ]*[\\d.x*][\\d.x*\\-+a-zA-Z.~^><=*|, ]*)$/;\n const allVersionEntries = [\n ...Object.entries(opts.packages ?? {}),\n ...Object.entries(opts.devPackages ?? {}),\n ];\n for (const [pkg, version] of allVersionEntries) {\n if (!SAFE_VERSION_RE.test(version.trim())) {\n return {\n ...emptyResult,\n success: false,\n error: `Unsafe version specifier for '${pkg}': '${version}' — only semver ranges, workspace:*, and dist-tags (latest/next/beta) are permitted`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: lifecycle script key blocklist (C-2A / FIX 2A)\n // -------------------------------------------------------------------------\n const BLOCKED_LIFECYCLE_KEYS = new Set([\n 'preinstall', 'install', 'postinstall', 'prepare',\n 'prepublish', 'prepublishOnly', 'prepack', 'postpack',\n 'dependencies', // pnpm hook key\n ]);\n if (opts.scripts) {\n for (const key of Object.keys(opts.scripts)) {\n if (BLOCKED_LIFECYCLE_KEYS.has(key)) {\n return {\n ...emptyResult,\n success: false,\n error: `Blocked lifecycle script key: '${key}' — writing npm lifecycle hooks is not permitted`,\n };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Read & parse\n // -------------------------------------------------------------------------\n const raw = readFileSync(realPackageJsonPath, 'utf8');\n\n // W2: Validate package.json structure with Zod before touching anything\n const PackageJsonSchema = z.object({\n // Zod v4: z.record(keySchema, valueSchema) — two-arg form required\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n }).passthrough();\n\n const schemaResult = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!schemaResult.success) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package.json structure: ${schemaResult.error.message}`,\n };\n }\n // FIX 4 (B-new-2): The schema has already validated the shape — the cast is earned.\n // passthrough() + noUncheckedIndexedAccess would otherwise broaden field types to unknown.\n const parsed = schemaResult.data as PackageJson;\n\n // -------------------------------------------------------------------------\n // Merge dependencies — NEVER overwrite existing version pins\n // -------------------------------------------------------------------------\n const added: string[] = [];\n const skipped: string[] = [];\n const scriptsAdded: string[] = [];\n\n // Live Set grows as packages are written — prevents same pkg landing in both buckets (B4).\n // Uses `in` semantics (not falsy) so empty-string versions are treated as existing (B3).\n const claimedPkgs = new Set<string>([\n ...Object.keys(parsed.dependencies ?? {}),\n ...Object.keys(parsed.devDependencies ?? {}),\n ]);\n\n // Regular dependencies\n parsed.dependencies = parsed.dependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.packages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.dependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n\n // Dev dependencies\n if (opts.devPackages && Object.keys(opts.devPackages).length > 0) {\n parsed.devDependencies = parsed.devDependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.devPackages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.devDependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n }\n\n // Scripts — same never-overwrite semantics\n if (opts.scripts && Object.keys(opts.scripts).length > 0) {\n parsed.scripts = parsed.scripts ?? {};\n for (const [key, value] of Object.entries(opts.scripts)) {\n if (parsed.scripts[key] === undefined) {\n parsed.scripts[key] = value;\n scriptsAdded.push(key);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Write back — use realPackageJsonPath (symlink-resolved) for all I/O\n // -------------------------------------------------------------------------\n writeFileSync(realPackageJsonPath, JSON.stringify(parsed, null, 2) + '\\n');\n\n // -------------------------------------------------------------------------\n // Run pnpm install (optional, non-fatal on failure)\n // -------------------------------------------------------------------------\n let installed = false;\n let installError: string | undefined;\n\n if (opts.runInstall) {\n try {\n execSync('pnpm install', { cwd: realTarget, stdio: 'pipe', timeout: 60_000 });\n installed = true;\n } catch (err) {\n // Don't blow up the whole tool — install failure is recoverable.\n // The caller can re-run or handle manually.\n installed = false;\n const spawnErr = err as { stderr?: Buffer; message?: string };\n installError = spawnErr.stderr?.toString().trim() || (err instanceof Error ? err.message : 'unknown error');\n }\n }\n\n return {\n success: true,\n added,\n skipped,\n scriptsAdded,\n installed,\n packageJsonPath: realPackageJsonPath,\n ...(installError !== undefined ? { installError } : {}),\n };\n } catch (err) {\n return { ...emptyResult, success: false, error: err instanceof Error ? err.message : String(err) };\n }\n}\n"],"mappings":"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","names":["server","path","import_zod","server","path","fs","import_zod","server","import_zod","import_cli_data_explorer","server","import_zod","import_path","import_fs","path","server","import_zod","import_fs","import_child_process","import_path","server","path","import_fs","import_path","path"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts","../src/tools/clarification.ts","../src/tools/packages.ts","../package.json"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\nimport { registerClarificationTools } from './tools/clarification.js';\nimport { registerPackageTools } from './tools/packages.js';\nimport packageJson from '../package.json';\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: packageJson.version,\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\nregisterClarificationTools(server); // stackwright_pro_clarify, stackwright_pro_detect_conflict, stackwright_pro_get_defaults\nregisterPackageTools(server); // stackwright_pro_setup_packages\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n ...(specPath !== undefined && { specPath }),\n ...(projectRoot !== undefined && { projectRoot }),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`📦 Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`📦 ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\n💡 Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: z\n .array(z.string())\n .describe('Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'),\n excludePatterns: z\n .array(z.string())\n .optional()\n .describe('Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'),\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n ...(excludePatterns !== undefined && { excludePatterns }),\n projectRoot: projectRoot ?? process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['🔐 Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\n⚠️ Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { createHash } from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n const allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const sha256 = createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time\n sha256 = '<computed-at-build>';\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n sha256 = createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📝 Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: '❌ stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`🔐 Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`📦 ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: z\n .number()\n .optional()\n .describe('Revalidation interval in seconds (default: 60)'),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description = '';\n if (revalidate < 60) {\n description = '⚡ Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = '📊 Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = '💾 Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n '🗄️ Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `⚙️ ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? '⏳ Show loading until cached' : fallback === 'true' ? '📄 Generate on demand' : '❌ 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: z\n .array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: z.number().optional().describe('Revalidation interval'),\n })\n )\n .describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`⚙️ Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = '💾';\n if (rev < 60) freshness = '⚡';\n else if (rev < 300) freshness = '📊';\n else if (rev >= 3600) freshness = '🗄️';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with grid, metric_card, data_table, and collection_list content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: z.array(z.string()).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add metric cards in a grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - type: grid`);\n yamlLines.push(` columns: 4`);\n yamlLines.push(` items:`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Total\"`);\n yamlLines.push(` value: {{ ${slug}.count }}`);\n yamlLines.push(` icon: Database`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Active\"`);\n yamlLines.push(` value: 0`);\n yamlLines.push(` icon: CheckCircle`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - type: collection_list`);\n yamlLines.push(` label: ${entities[0]}-listing`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['id', 'name', 'status', 'created_at'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => f.name)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - type: data_table`);\n yamlLines.push(` label: ${entities[0]}-table`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` columns:`);\n yamlLines.push(` - field: id`);\n yamlLines.push(` header: ID`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: name`);\n yamlLines.push(` header: Name`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: status`);\n yamlLines.push(` header: Status`);\n yamlLines.push(` type: badge`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📊 Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - main:',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n ' background: \"primary\"',\n ' color: \"text\"',\n '',\n ' - grid:',\n ' label: \"detail-fields\"',\n ' columns: 2',\n ' items:',\n ];\n\n // Add field cards\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n for (const field of displayFields) {\n const label = field.name\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (l: string) => l.toUpperCase());\n yamlLines.push(` - card:`);\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(` textSize: \"h4\"`);\n yamlLines.push(` content:`);\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(` textSize: \"body1\"`);\n }\n\n yamlLines.push(' background: \"background\"');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📄 Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n","/**\n * Clarification MCP Tools\n *\n * Provides human-in-the-loop clarification for otters that encounter\n * ambiguity during execution.\n *\n * This bridges to the Python Clarification Protocol server which\n * handles:\n * - Channel routing (TUI, CLI args, config, defaults)\n * - Conflict detection\n * - Stubborn user escalation\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { spawn, ChildProcess } from 'child_process';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { randomUUID } from 'crypto';\nimport { existsSync, unlinkSync } from 'fs';\n\n// Types matching Python server\nexport interface ClarificationRequest {\n context?: string;\n question_type: 'closed_choice' | 'open_text' | 'conditional' | 'multi_step' | 'reconciliation';\n question: string;\n choices?: string[];\n priority?: 'blocking' | 'preferred' | 'optional';\n target_field?: string;\n}\n\nexport interface ClarificationResponse {\n request_id: string;\n decision: {\n value: unknown;\n explicit: boolean;\n source: string;\n };\n fallback_used: boolean;\n fallback_reason?: string;\n}\n\n// Track active Python server processes\nconst activeServers: Map<string, ChildProcess> = new Map();\n\n/**\n * Start the Python Clarification Protocol server\n */\nasync function startPythonServer(sessionId: string): Promise<{ port: number; socketPath: string }> {\n const socketPath = join(tmpdir(), `otter-raft-${randomUUID()}.sock`);\n const port = 8765 + Math.floor(Math.random() * 100); // Random port to avoid conflicts\n\n return new Promise((resolve, reject) => {\n const pythonPath = process.platform === 'win32' ? 'python' : 'python3';\n\n // Find Python package\n const packageRoot = findPythonPackageRoot();\n\n const proc = spawn(\n pythonPath,\n ['-m', 'stackwright_pro.raft.server', '--socket', socketPath, '--port', String(port)],\n {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PYTHONPATH: packageRoot,\n },\n }\n );\n\n // Register process for cleanup\n activeServers.set(sessionId, proc);\n\n let startupOutput = '';\n let started = false;\n\n proc.stdout?.on('data', (data: Buffer) => {\n startupOutput += data.toString();\n if (startupOutput.includes('Server ready') || startupOutput.includes('HTTP server')) {\n started = true;\n resolve({ port, socketPath });\n }\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n // Only log errors, not startup messages\n if (!startupOutput.includes('Starting')) {\n console.error('[Python Clarification]', data.toString().trim());\n }\n });\n\n proc.on('error', (err) => {\n if (!started) {\n activeServers.delete(sessionId);\n reject(new Error(`Failed to start Python server: ${err.message}`));\n }\n });\n\n proc.on('exit', (code) => {\n activeServers.delete(sessionId);\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath);\n } catch {\n // Ignore cleanup errors\n }\n }\n });\n\n // Timeout after 10 seconds\n setTimeout(() => {\n if (!started) {\n proc.kill();\n activeServers.delete(sessionId);\n reject(new Error('Python server startup timeout'));\n }\n }, 10000);\n });\n}\n\n/**\n * Stop the Python server for a session\n */\nasync function stopPythonServer(sessionId: string): Promise<void> {\n const proc = activeServers.get(sessionId);\n if (proc) {\n proc.kill('SIGTERM');\n activeServers.delete(sessionId);\n }\n}\n\n/**\n * Make HTTP request to Python server\n */\nasync function httpRequest<T>(\n host: string,\n port: number,\n path: string,\n body?: unknown\n): Promise<T> {\n const http = await import('http');\n\n return new Promise((resolve, reject) => {\n const url = new URL(path, `http://${host}:${port}`);\n\n const reqOptions = {\n hostname: host,\n port: port,\n path: url.pathname,\n method: body ? 'POST' : 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n\n const req = http.request(reqOptions, (res) => {\n let data = '';\n\n res.on('data', (chunk: Buffer) => {\n data += chunk.toString();\n });\n\n res.on('end', () => {\n try {\n const parsed = JSON.parse(data);\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(parsed.detail || parsed.error || `HTTP ${res.statusCode}`));\n } else {\n resolve(parsed);\n }\n } catch (e) {\n reject(new Error(`Failed to parse response: ${data}`));\n }\n });\n });\n\n req.on('error', reject);\n\n if (body) {\n req.write(JSON.stringify(body));\n }\n\n req.end();\n });\n}\n\n/**\n * Find Python package root\n */\nfunction findPythonPackageRoot(): string {\n const candidates = [\n join(__dirname, '../../python/src'),\n join(__dirname, '../../../python/src'),\n join(process.cwd(), 'python/src'),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return process.cwd();\n}\n\n/**\n * Register clarification MCP tools\n */\nexport function registerClarificationTools(server: McpServer): void {\n // Tool: Ask for clarification (creates session)\n server.tool(\n 'stackwright_pro_clarify',\n 'Ask the user for clarification when an otter encounters ambiguity. ' +\n 'This is for MID-EXECUTION questions, not upfront question collection. ' +\n 'Use this when the otter needs user input to proceed. ' +\n \"Returns the user's decision which should be used to continue execution.\",\n {\n context: z.string().optional().describe('Context about what the otter is trying to do'),\n question_type: z\n .enum(['closed_choice', 'open_text', 'conditional', 'multi_step', 'reconciliation'])\n .describe('Type of question being asked'),\n question: z.string().describe('The clarification question to ask the user'),\n choices: z\n .array(z.string())\n .optional()\n .describe('Options for closed_choice or multi_step questions'),\n priority: z\n .enum(['blocking', 'preferred', 'optional'])\n .optional()\n .describe('How critical is this clarification? Default: preferred'),\n target_field: z.string().optional().describe('What field/config does this clarify?'),\n },\n async ({ context, question_type, question, choices, priority = 'preferred', target_field }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Create session\n await httpRequest(port === 8765 ? '127.0.0.1' : '127.0.0.1', port, '/sessions', {});\n\n // Set context if provided\n if (context) {\n await httpRequest(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n `/sessions/${sessionId}/context`,\n { context: { purpose: context } }\n );\n }\n\n // Ask for clarification\n const request: ClarificationRequest = {\n ...(context !== undefined && { context }),\n question_type,\n question,\n ...(choices !== undefined && { choices }),\n priority,\n ...(target_field !== undefined && { target_field }),\n };\n\n const response = await httpRequest<ClarificationResponse>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/clarify',\n { request }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n // Format response for LLM\n const decision = response.decision;\n const value = decision.value;\n const source = decision.source;\n const explicit = decision.explicit ? 'explicitly' : 'via fallback';\n\n if (response.fallback_used) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ Clarification fallback used: ${response.fallback_reason || 'No user input available'}\\n\\n` +\n `Default value used: ${JSON.stringify(value)}\\n\\n` +\n `💡 Consider following up with the user later if this default isn't appropriate.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `✅ User clarified (${source}): ${JSON.stringify(value)}\\n\\n` +\n `Use this value to continue execution.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n // If server not available, try stdio mode as fallback\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Clarification failed: ${error instanceof Error ? error.message : 'Unknown error'}\\n\\n` +\n `Cannot proceed without user input. Consider:\\n` +\n `1. Using a reasonable default\\n` +\n `2. Asking the user directly in your response\\n` +\n `3. Skipping this step if optional`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Detect preference conflict\n server.tool(\n 'stackwright_pro_detect_conflict',\n \"Detect when a user's stated preference conflicts with their selected choices. \" +\n 'Use this to identify when users might be indecisive or misunderstood a question. ' +\n 'Returns conflict details and resolution options.',\n {\n stated_preference: z.string().describe('What the user said they wanted'),\n selected_values: z.record(z.string(), z.string()).describe('What the user actually selected'),\n },\n async ({ stated_preference, selected_values }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Check for conflict\n const response = await httpRequest<{ conflict: boolean; data?: any }>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/conflict',\n { stated_preference, selected_values }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n if (response.conflict) {\n const data = response.data;\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ CONFLICT DETECTED\\n\\n` +\n `User stated: \"${stated_preference}\"\\n` +\n `But selected: ${JSON.stringify(selected_values)}\\n\\n` +\n `Conflict: ${data.description}\\n\\n` +\n `Resolution options: ${data.options?.join(', ') || 'Ask user to clarify'}\\n\\n` +\n `💡 Consider asking the user to reconcile this conflict.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ No conflict detected between stated preference and selections.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Conflict detection failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Get clarification defaults\n server.tool(\n 'stackwright_pro_get_defaults',\n 'Get the current clarification defaults from config. ' +\n \"Use this to understand what fallback values will be used if user doesn't provide input.\",\n {\n config_path: z\n .string()\n .optional()\n .describe('Path to config file. Default: .stackwright/clarification.yaml'),\n },\n async ({ config_path }) => {\n // This reads from the Python config module directly\n // For now, return a message pointing to where config is stored\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `📋 Clarification defaults\\n\\n` +\n `Configuration is loaded from:\\n` +\n `- Environment: CLARIFICATION_* variables\\n` +\n `- Config file: ${config_path || '.stackwright/clarification.yaml'}\\n` +\n `- CLI args: --clarify-* flags\\n\\n` +\n `Default behaviors:\\n` +\n `- allow_dont_know: true (users can skip)\\n` +\n `- default_timeout: 120 seconds\\n` +\n `- channel_priority: [tui, cli_args, config, defaults]\\n\\n` +\n `💡 Set CLARIFICATION_DEFAULT_<FIELD>=value to change defaults.`,\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, realpathSync, lstatSync } from 'fs';\nimport { execSync } from 'child_process';\nimport path from 'path';\n\n/**\n * stackwright_pro_setup_packages MCP tool\n *\n * Ensures pro packages are present in a project's package.json.\n * Used by the Pro Foreman Otter to bootstrap dependencies before\n * specialist otters run — enabling the otter raft's IoC dependency\n * declaration pattern.\n *\n * Merge semantics: NEVER overwrites an existing version pin.\n * If a package is already declared at any version, it is skipped.\n * This preserves intentional version pinning by developers.\n */\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n [key: string]: unknown;\n}\n\ninterface SetupPackagesResult {\n success: boolean;\n added: string[];\n skipped: string[];\n scriptsAdded: string[];\n installed: boolean;\n packageJsonPath: string;\n error?: string;\n installError?: string;\n}\n\nexport function registerPackageTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_setup_packages',\n \"Ensures pro packages are present in a project's package.json. \" +\n 'Safe to call multiple times — never overwrites existing version pins. ' +\n 'Use this to bootstrap dependencies before specialist otters run.',\n {\n // FIX 3 (B-new-1): Zod v4 requires two-arg z.record(keySchema, valueSchema)\n packages: z\n .record(z.string(), z.string())\n .describe(\n 'Dependencies to add. Record<packageName, version>. e.g. { \"@stackwright-pro/auth\": \"latest\" }'\n ),\n devPackages: z\n .record(z.string(), z.string())\n .optional()\n .describe('devDependencies to add. Same format as packages.'),\n scripts: z\n .record(z.string(), z.string())\n .optional()\n .describe('npm scripts to add. Only adds if key does not already exist.'),\n targetDir: z\n .string()\n .optional()\n .describe(\n 'Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory.'\n ),\n runInstall: z\n .boolean()\n .optional()\n .default(true)\n .describe('Run pnpm install after writing package.json. Defaults to true.'),\n },\n async ({ packages, devPackages, scripts, targetDir, runInstall }) => {\n // exactOptionalPropertyTypes: true means we cannot pass `undefined` explicitly\n // for optional fields — conditionally spread them instead.\n const result = setupPackages({\n packages,\n runInstall,\n ...(devPackages !== undefined ? { devPackages } : {}),\n ...(scripts !== undefined ? { scripts } : {}),\n ...(targetDir !== undefined ? { targetDir } : {}),\n });\n\n const statusLine = result.success\n ? `✅ package.json updated: ${result.packageJsonPath}`\n : `❌ Failed: ${result.error}`;\n\n const lines = [\n statusLine,\n '',\n result.added.length > 0\n ? `Added (${result.added.length}): ${result.added.join(', ')}`\n : 'Added: none',\n result.skipped.length > 0\n ? `Skipped/already present (${result.skipped.length}): ${result.skipped.join(', ')}`\n : 'Skipped: none',\n result.scriptsAdded.length > 0\n ? `Scripts added (${result.scriptsAdded.length}): ${result.scriptsAdded.join(', ')}`\n : 'Scripts added: none',\n `pnpm install: ${result.installed ? 'ran successfully' : result.success && runInstall ? 'failed (non-fatal)' : 'skipped'}`,\n ];\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n\n/**\n * Core implementation — extracted so it can be tested directly without\n * going through the MCP server machinery. Keeping I/O at the edges.\n */\nexport function setupPackages(opts: {\n packages: Record<string, string>;\n devPackages?: Record<string, string>;\n scripts?: Record<string, string>;\n targetDir?: string;\n runInstall: boolean;\n}): SetupPackagesResult {\n const emptyResult: Omit<SetupPackagesResult, 'success' | 'error'> = {\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n };\n\n try {\n // -------------------------------------------------------------------------\n // Security: path traversal guard\n // -------------------------------------------------------------------------\n const cwd = process.cwd();\n const resolvedTarget = opts.targetDir ? path.resolve(opts.targetDir) : cwd;\n\n // Ensure resolved path stays within cwd — no sneaky ../../etc tricks\n const cwdWithSep = cwd.endsWith(path.sep) ? cwd : cwd + path.sep;\n if (resolvedTarget !== cwd && !resolvedTarget.startsWith(cwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory is outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Find package.json (existence check before symlink resolution)\n // -------------------------------------------------------------------------\n const preResolvePackageJsonPath = path.join(resolvedTarget, 'package.json');\n\n if (!existsSync(preResolvePackageJsonPath)) {\n return {\n success: false,\n ...emptyResult,\n error: `No package.json found in ${resolvedTarget}`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: directory-level symlink bypass guard (B2)\n // -------------------------------------------------------------------------\n let realTarget: string;\n try {\n realTarget = realpathSync(resolvedTarget);\n } catch {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n error: `Could not resolve real path of target directory`,\n };\n }\n\n const realCwd = realpathSync(cwd);\n const realCwdWithSep = realCwd.endsWith(path.sep) ? realCwd : realCwd + path.sep;\n if (realTarget !== realCwd && !realTarget.startsWith(realCwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory resolved to a location outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: file-level symlink guard at package.json (C-1 / FIX 1)\n // -------------------------------------------------------------------------\n // Reconstruct package.json path from the symlink-resolved target directory.\n // This prevents readFileSync / writeFileSync from following a file-level\n // symlink planted at <targetDir>/package.json.\n const realPackageJsonPath = path.join(realTarget, 'package.json');\n\n const pkgStat = lstatSync(realPackageJsonPath);\n if (pkgStat.isSymbolicLink()) {\n return {\n ...emptyResult,\n success: false,\n error: `package.json is a symlink — refusing to read or write`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: package name validation (C-2C / L-1)\n // -------------------------------------------------------------------------\n // npm package name spec: optional @scope/, then lowercase alphanumeric + hyphens/dots/underscores\n const VALID_PKG_NAME_RE = /^(@[a-z0-9][a-z0-9\\-._~]*\\/)?[a-z0-9][a-z0-9\\-._~]*$/;\n const allPkgNames = [\n ...Object.keys(opts.packages ?? {}),\n ...Object.keys(opts.devPackages ?? {}),\n ];\n for (const pkg of allPkgNames) {\n if (!VALID_PKG_NAME_RE.test(pkg)) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package name: '${pkg}' — must match npm package name specification`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: version string allowlist (C-2B / FIX 2B)\n // -------------------------------------------------------------------------\n // Allows: semver ranges (^1.0.0, ~2.1, >=3, 1.x, *), workspace:*, latest/next/beta/alpha/canary/rc\n // Blocks: git+https://, file:, npm:evil@, http://, ssh://, etc.\n const SAFE_VERSION_RE =\n /^(workspace:[*^~]?|\\*|latest|next|beta|alpha|canary|rc|[~^><=*|, ]*[\\d.x*][\\d.x*\\-+a-zA-Z.~^><=*|, ]*)$/;\n const allVersionEntries = [\n ...Object.entries(opts.packages ?? {}),\n ...Object.entries(opts.devPackages ?? {}),\n ];\n for (const [pkg, version] of allVersionEntries) {\n if (!SAFE_VERSION_RE.test(version.trim())) {\n return {\n ...emptyResult,\n success: false,\n error: `Unsafe version specifier for '${pkg}': '${version}' — only semver ranges, workspace:*, and dist-tags (latest/next/beta) are permitted`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: lifecycle script key blocklist (C-2A / FIX 2A)\n // -------------------------------------------------------------------------\n const BLOCKED_LIFECYCLE_KEYS = new Set([\n 'preinstall',\n 'install',\n 'postinstall',\n 'prepare',\n 'prepublish',\n 'prepublishOnly',\n 'prepack',\n 'postpack',\n 'dependencies', // pnpm hook key\n ]);\n if (opts.scripts) {\n for (const key of Object.keys(opts.scripts)) {\n if (BLOCKED_LIFECYCLE_KEYS.has(key)) {\n return {\n ...emptyResult,\n success: false,\n error: `Blocked lifecycle script key: '${key}' — writing npm lifecycle hooks is not permitted`,\n };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Read & parse\n // -------------------------------------------------------------------------\n const raw = readFileSync(realPackageJsonPath, 'utf8');\n\n // W2: Validate package.json structure with Zod before touching anything\n const PackageJsonSchema = z\n .object({\n // Zod v4: z.record(keySchema, valueSchema) — two-arg form required\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n })\n .passthrough();\n\n const schemaResult = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!schemaResult.success) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package.json structure: ${schemaResult.error.message}`,\n };\n }\n // FIX 4 (B-new-2): The schema has already validated the shape — the cast is earned.\n // passthrough() + noUncheckedIndexedAccess would otherwise broaden field types to unknown.\n const parsed = schemaResult.data as PackageJson;\n\n // -------------------------------------------------------------------------\n // Merge dependencies — NEVER overwrite existing version pins\n // -------------------------------------------------------------------------\n const added: string[] = [];\n const skipped: string[] = [];\n const scriptsAdded: string[] = [];\n\n // Live Set grows as packages are written — prevents same pkg landing in both buckets (B4).\n // Uses `in` semantics (not falsy) so empty-string versions are treated as existing (B3).\n const claimedPkgs = new Set<string>([\n ...Object.keys(parsed.dependencies ?? {}),\n ...Object.keys(parsed.devDependencies ?? {}),\n ]);\n\n // Regular dependencies\n parsed.dependencies = parsed.dependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.packages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.dependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n\n // Dev dependencies\n if (opts.devPackages && Object.keys(opts.devPackages).length > 0) {\n parsed.devDependencies = parsed.devDependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.devPackages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.devDependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n }\n\n // Scripts — same never-overwrite semantics\n if (opts.scripts && Object.keys(opts.scripts).length > 0) {\n parsed.scripts = parsed.scripts ?? {};\n for (const [key, value] of Object.entries(opts.scripts)) {\n if (parsed.scripts[key] === undefined) {\n parsed.scripts[key] = value;\n scriptsAdded.push(key);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Write back — use realPackageJsonPath (symlink-resolved) for all I/O\n // -------------------------------------------------------------------------\n writeFileSync(realPackageJsonPath, JSON.stringify(parsed, null, 2) + '\\n');\n\n // -------------------------------------------------------------------------\n // Run pnpm install (optional, non-fatal on failure)\n // -------------------------------------------------------------------------\n let installed = false;\n let installError: string | undefined;\n\n if (opts.runInstall) {\n try {\n execSync('pnpm install', { cwd: realTarget, stdio: 'pipe', timeout: 60_000 });\n installed = true;\n } catch (err) {\n // Don't blow up the whole tool — install failure is recoverable.\n // The caller can re-run or handle manually.\n installed = false;\n const spawnErr = err as { stderr?: Buffer; message?: string };\n installError =\n spawnErr.stderr?.toString().trim() ||\n (err instanceof Error ? err.message : 'unknown error');\n }\n }\n\n return {\n success: true,\n added,\n skipped,\n scriptsAdded,\n installed,\n packageJsonPath: realPackageJsonPath,\n ...(installError !== undefined ? { installError } : {}),\n };\n } catch (err) {\n return {\n ...emptyResult,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","{\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.10.0\",\n \"@stackwright-pro/cli-data-explorer\": \"workspace:*\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.1.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.3\",\n \"vitest\": \"^4.0.18\"\n },\n \"scripts\": {\n \"build\": \"tsup src/server.ts --format cjs,esm --dts --clean\",\n \"dev\": \"tsup src/server.ts --format cjs,esm --dts --watch\",\n \"start\": \"node dist/server.js\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"name\": \"@stackwright-pro/mcp\",\n \"version\": \"0.2.0-alpha.0\",\n \"description\": \"MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation\",\n \"license\": \"PROPRIETARY\",\n \"main\": \"./dist/server.js\",\n \"module\": \"./dist/server.mjs\",\n \"types\": \"./dist/server.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.mjs\",\n \"require\": \"./dist/server.js\"\n }\n },\n \"files\": [\n \"dist\"\n ]\n}\n"],"mappings":"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","names":["server","path","import_zod","server","path","fs","import_zod","server","import_zod","import_cli_data_explorer","server","import_zod","import_path","import_crypto","import_fs","path","server","import_zod","import_fs","import_child_process","import_path","server","path"]}
package/dist/server.mjs CHANGED
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/server.ts
9
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -94,8 +87,8 @@ function registerDataExplorerTools(server2) {
94
87
  lines.push(" endpoints:");
95
88
  if (result.filter.include && result.filter.include.length > 0) {
96
89
  lines.push(" include:");
97
- for (const path4 of result.filter.include) {
98
- lines.push(` - ${path4}`);
90
+ for (const path3 of result.filter.include) {
91
+ lines.push(` - ${path3}`);
99
92
  }
100
93
  }
101
94
  if (result.filter.exclude && result.filter.exclude.length > 0) {
@@ -125,6 +118,7 @@ function registerDataExplorerTools(server2) {
125
118
 
126
119
  // src/tools/security.ts
127
120
  import { z as z2 } from "zod";
121
+ import { createHash } from "crypto";
128
122
  import fs from "fs";
129
123
  import path from "path";
130
124
  function registerSecurityTools(server2) {
@@ -202,8 +196,7 @@ This spec is not on the approved-specs allowlist. Add it using stackwright_pro_a
202
196
  if (!specPath.startsWith("http://") && !specPath.startsWith("https://")) {
203
197
  if (fs.existsSync(specPath)) {
204
198
  const specContent = fs.readFileSync(specPath, "utf8");
205
- const crypto = __require("crypto");
206
- const sha256 = crypto.createHash("sha256").update(specContent).digest("hex");
199
+ const sha256 = createHash("sha256").update(specContent).digest("hex");
207
200
  if (sha256 !== matchingSpec.sha256) {
208
201
  return {
209
202
  content: [
@@ -254,8 +247,7 @@ Status: Valid (${allowlist.length} specs on allowlist)`
254
247
  sha256 = "<computed-at-build>";
255
248
  } else if (fs.existsSync(url)) {
256
249
  const specContent = fs.readFileSync(url, "utf8");
257
- const crypto = __require("crypto");
258
- sha256 = crypto.createHash("sha256").update(specContent).digest("hex");
250
+ sha256 = createHash("sha256").update(specContent).digest("hex");
259
251
  } else {
260
252
  return {
261
253
  content: [
@@ -699,10 +691,10 @@ async function stopPythonServer(sessionId) {
699
691
  activeServers.delete(sessionId);
700
692
  }
701
693
  }
702
- async function httpRequest(host, port, path4, body) {
694
+ async function httpRequest(host, port, path3, body) {
703
695
  const http = await import("http");
704
696
  return new Promise((resolve, reject) => {
705
- const url = new URL(path4, `http://${host}:${port}`);
697
+ const url = new URL(path3, `http://${host}:${port}`);
706
698
  const reqOptions = {
707
699
  hostname: host,
708
700
  port,
@@ -942,26 +934,20 @@ function registerPackageTools(server2) {
942
934
  packages: z6.record(z6.string(), z6.string()).describe(
943
935
  'Dependencies to add. Record<packageName, version>. e.g. { "@stackwright-pro/auth": "latest" }'
944
936
  ),
945
- devPackages: z6.record(z6.string(), z6.string()).optional().describe(
946
- "devDependencies to add. Same format as packages."
947
- ),
948
- scripts: z6.record(z6.string(), z6.string()).optional().describe(
949
- "npm scripts to add. Only adds if key does not already exist."
950
- ),
937
+ devPackages: z6.record(z6.string(), z6.string()).optional().describe("devDependencies to add. Same format as packages."),
938
+ scripts: z6.record(z6.string(), z6.string()).optional().describe("npm scripts to add. Only adds if key does not already exist."),
951
939
  targetDir: z6.string().optional().describe(
952
940
  "Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory."
953
941
  ),
954
- runInstall: z6.boolean().optional().default(true).describe(
955
- "Run pnpm install after writing package.json. Defaults to true."
956
- )
942
+ runInstall: z6.boolean().optional().default(true).describe("Run pnpm install after writing package.json. Defaults to true.")
957
943
  },
958
944
  async ({ packages, devPackages, scripts, targetDir, runInstall }) => {
959
945
  const result = setupPackages({
960
946
  packages,
961
- devPackages,
962
- scripts,
963
- targetDir,
964
- runInstall
947
+ runInstall,
948
+ ...devPackages !== void 0 ? { devPackages } : {},
949
+ ...scripts !== void 0 ? { scripts } : {},
950
+ ...targetDir !== void 0 ? { targetDir } : {}
965
951
  });
966
952
  const statusLine = result.success ? `\u2705 package.json updated: ${result.packageJsonPath}` : `\u274C Failed: ${result.error}`;
967
953
  const lines = [
@@ -1184,17 +1170,57 @@ function setupPackages(opts) {
1184
1170
  ...installError !== void 0 ? { installError } : {}
1185
1171
  };
1186
1172
  } catch (err) {
1187
- return { ...emptyResult, success: false, error: err instanceof Error ? err.message : String(err) };
1173
+ return {
1174
+ ...emptyResult,
1175
+ success: false,
1176
+ error: err instanceof Error ? err.message : String(err)
1177
+ };
1188
1178
  }
1189
1179
  }
1190
1180
 
1181
+ // package.json
1182
+ var package_default = {
1183
+ dependencies: {
1184
+ "@modelcontextprotocol/sdk": "^1.10.0",
1185
+ "@stackwright-pro/cli-data-explorer": "workspace:*",
1186
+ zod: "^4.3.6"
1187
+ },
1188
+ devDependencies: {
1189
+ "@types/node": "^24.1.0",
1190
+ tsup: "^8.5.0",
1191
+ typescript: "^5.8.3",
1192
+ vitest: "^4.0.18"
1193
+ },
1194
+ scripts: {
1195
+ build: "tsup src/server.ts --format cjs,esm --dts --clean",
1196
+ dev: "tsup src/server.ts --format cjs,esm --dts --watch",
1197
+ start: "node dist/server.js",
1198
+ test: "vitest run",
1199
+ "test:coverage": "vitest run --coverage"
1200
+ },
1201
+ name: "@stackwright-pro/mcp",
1202
+ version: "0.2.0-alpha.0",
1203
+ description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
1204
+ license: "PROPRIETARY",
1205
+ main: "./dist/server.js",
1206
+ module: "./dist/server.mjs",
1207
+ types: "./dist/server.d.ts",
1208
+ exports: {
1209
+ ".": {
1210
+ types: "./dist/server.d.ts",
1211
+ import: "./dist/server.mjs",
1212
+ require: "./dist/server.js"
1213
+ }
1214
+ },
1215
+ files: [
1216
+ "dist"
1217
+ ]
1218
+ };
1219
+
1191
1220
  // src/server.ts
1192
- import { readFileSync as readFileSync2 } from "fs";
1193
- import path3 from "path";
1194
- var packageJson = JSON.parse(readFileSync2(path3.join(__dirname, "package.json"), "utf8"));
1195
1221
  var server = new McpServer({
1196
1222
  name: "stackwright-pro",
1197
- version: packageJson.version
1223
+ version: package_default.version
1198
1224
  });
1199
1225
  registerDataExplorerTools(server);
1200
1226
  registerSecurityTools(server);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts","../src/tools/clarification.ts","../src/tools/packages.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\nimport { registerClarificationTools } from './tools/clarification.js';\nimport { registerPackageTools } from './tools/packages.js';\nimport { readFileSync } from 'fs';\nimport path from 'path';\n\n// Dynamic version from package.json\nconst packageJson = JSON.parse(readFileSync(path.join(__dirname, 'package.json'), 'utf8'));\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: packageJson.version,\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\nregisterClarificationTools(server); // stackwright_pro_clarify, stackwright_pro_detect_conflict, stackwright_pro_get_defaults\nregisterPackageTools(server); // stackwright_pro_setup_packages\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n ...(specPath !== undefined && { specPath }),\n ...(projectRoot !== undefined && { projectRoot }),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`📦 Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`📦 ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\n💡 Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: z\n .array(z.string())\n .describe('Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'),\n excludePatterns: z\n .array(z.string())\n .optional()\n .describe('Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'),\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n ...(excludePatterns !== undefined && { excludePatterns }),\n projectRoot: projectRoot ?? process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['🔐 Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\n⚠️ Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n const allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const crypto = require('crypto');\n const sha256 = crypto.createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time\n sha256 = '<computed-at-build>';\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n const crypto = require('crypto');\n sha256 = crypto.createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📝 Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: '❌ stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`🔐 Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`📦 ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: z\n .number()\n .optional()\n .describe('Revalidation interval in seconds (default: 60)'),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description = '';\n if (revalidate < 60) {\n description = '⚡ Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = '📊 Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = '💾 Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n '🗄️ Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `⚙️ ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? '⏳ Show loading until cached' : fallback === 'true' ? '📄 Generate on demand' : '❌ 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: z\n .array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: z.number().optional().describe('Revalidation interval'),\n })\n )\n .describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`⚙️ Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = '💾';\n if (rev < 60) freshness = '⚡';\n else if (rev < 300) freshness = '📊';\n else if (rev >= 3600) freshness = '🗄️';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with grid, metric_card, data_table, and collection_list content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: z.array(z.string()).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add metric cards in a grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - type: grid`);\n yamlLines.push(` columns: 4`);\n yamlLines.push(` items:`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Total\"`);\n yamlLines.push(` value: {{ ${slug}.count }}`);\n yamlLines.push(` icon: Database`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Active\"`);\n yamlLines.push(` value: 0`);\n yamlLines.push(` icon: CheckCircle`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - type: collection_list`);\n yamlLines.push(` label: ${entities[0]}-listing`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['id', 'name', 'status', 'created_at'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => f.name)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - type: data_table`);\n yamlLines.push(` label: ${entities[0]}-table`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` columns:`);\n yamlLines.push(` - field: id`);\n yamlLines.push(` header: ID`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: name`);\n yamlLines.push(` header: Name`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: status`);\n yamlLines.push(` header: Status`);\n yamlLines.push(` type: badge`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📊 Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - main:',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n ' background: \"primary\"',\n ' color: \"text\"',\n '',\n ' - grid:',\n ' label: \"detail-fields\"',\n ' columns: 2',\n ' items:',\n ];\n\n // Add field cards\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n for (const field of displayFields) {\n const label = field.name.replace(/_/g, ' ').replace(/\\b\\w/g, (l: string) => l.toUpperCase());\n yamlLines.push(` - card:`);\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(` textSize: \"h4\"`);\n yamlLines.push(` content:`);\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(` textSize: \"body1\"`);\n }\n\n yamlLines.push(' background: \"background\"');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📄 Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n","/**\n * Clarification MCP Tools\n *\n * Provides human-in-the-loop clarification for otters that encounter\n * ambiguity during execution.\n *\n * This bridges to the Python Clarification Protocol server which\n * handles:\n * - Channel routing (TUI, CLI args, config, defaults)\n * - Conflict detection\n * - Stubborn user escalation\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { spawn, ChildProcess } from 'child_process';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { randomUUID } from 'crypto';\nimport { existsSync, unlinkSync } from 'fs';\n\n// Types matching Python server\nexport interface ClarificationRequest {\n context?: string;\n question_type: 'closed_choice' | 'open_text' | 'conditional' | 'multi_step' | 'reconciliation';\n question: string;\n choices?: string[];\n priority?: 'blocking' | 'preferred' | 'optional';\n target_field?: string;\n}\n\nexport interface ClarificationResponse {\n request_id: string;\n decision: {\n value: unknown;\n explicit: boolean;\n source: string;\n };\n fallback_used: boolean;\n fallback_reason?: string;\n}\n\n// Track active Python server processes\nconst activeServers: Map<string, ChildProcess> = new Map();\n\n/**\n * Start the Python Clarification Protocol server\n */\nasync function startPythonServer(sessionId: string): Promise<{ port: number; socketPath: string }> {\n const socketPath = join(tmpdir(), `otter-raft-${randomUUID()}.sock`);\n const port = 8765 + Math.floor(Math.random() * 100); // Random port to avoid conflicts\n\n return new Promise((resolve, reject) => {\n const pythonPath = process.platform === 'win32' ? 'python' : 'python3';\n\n // Find Python package\n const packageRoot = findPythonPackageRoot();\n\n const proc = spawn(\n pythonPath,\n ['-m', 'stackwright_pro.raft.server', '--socket', socketPath, '--port', String(port)],\n {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PYTHONPATH: packageRoot,\n },\n }\n );\n\n // Register process for cleanup\n activeServers.set(sessionId, proc);\n\n let startupOutput = '';\n let started = false;\n\n proc.stdout?.on('data', (data: Buffer) => {\n startupOutput += data.toString();\n if (startupOutput.includes('Server ready') || startupOutput.includes('HTTP server')) {\n started = true;\n resolve({ port, socketPath });\n }\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n // Only log errors, not startup messages\n if (!startupOutput.includes('Starting')) {\n console.error('[Python Clarification]', data.toString().trim());\n }\n });\n\n proc.on('error', (err) => {\n if (!started) {\n activeServers.delete(sessionId);\n reject(new Error(`Failed to start Python server: ${err.message}`));\n }\n });\n\n proc.on('exit', (code) => {\n activeServers.delete(sessionId);\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath);\n } catch {\n // Ignore cleanup errors\n }\n }\n });\n\n // Timeout after 10 seconds\n setTimeout(() => {\n if (!started) {\n proc.kill();\n activeServers.delete(sessionId);\n reject(new Error('Python server startup timeout'));\n }\n }, 10000);\n });\n}\n\n/**\n * Stop the Python server for a session\n */\nasync function stopPythonServer(sessionId: string): Promise<void> {\n const proc = activeServers.get(sessionId);\n if (proc) {\n proc.kill('SIGTERM');\n activeServers.delete(sessionId);\n }\n}\n\n/**\n * Make HTTP request to Python server\n */\nasync function httpRequest<T>(\n host: string,\n port: number,\n path: string,\n body?: unknown\n): Promise<T> {\n const http = await import('http');\n\n return new Promise((resolve, reject) => {\n const url = new URL(path, `http://${host}:${port}`);\n\n const reqOptions = {\n hostname: host,\n port: port,\n path: url.pathname,\n method: body ? 'POST' : 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n\n const req = http.request(reqOptions, (res) => {\n let data = '';\n\n res.on('data', (chunk: Buffer) => {\n data += chunk.toString();\n });\n\n res.on('end', () => {\n try {\n const parsed = JSON.parse(data);\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(parsed.detail || parsed.error || `HTTP ${res.statusCode}`));\n } else {\n resolve(parsed);\n }\n } catch (e) {\n reject(new Error(`Failed to parse response: ${data}`));\n }\n });\n });\n\n req.on('error', reject);\n\n if (body) {\n req.write(JSON.stringify(body));\n }\n\n req.end();\n });\n}\n\n/**\n * Find Python package root\n */\nfunction findPythonPackageRoot(): string {\n const candidates = [\n join(__dirname, '../../python/src'),\n join(__dirname, '../../../python/src'),\n join(process.cwd(), 'python/src'),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return process.cwd();\n}\n\n/**\n * Register clarification MCP tools\n */\nexport function registerClarificationTools(server: McpServer): void {\n // Tool: Ask for clarification (creates session)\n server.tool(\n 'stackwright_pro_clarify',\n 'Ask the user for clarification when an otter encounters ambiguity. ' +\n 'This is for MID-EXECUTION questions, not upfront question collection. ' +\n 'Use this when the otter needs user input to proceed. ' +\n \"Returns the user's decision which should be used to continue execution.\",\n {\n context: z.string().optional().describe('Context about what the otter is trying to do'),\n question_type: z\n .enum(['closed_choice', 'open_text', 'conditional', 'multi_step', 'reconciliation'])\n .describe('Type of question being asked'),\n question: z.string().describe('The clarification question to ask the user'),\n choices: z\n .array(z.string())\n .optional()\n .describe('Options for closed_choice or multi_step questions'),\n priority: z\n .enum(['blocking', 'preferred', 'optional'])\n .optional()\n .describe('How critical is this clarification? Default: preferred'),\n target_field: z.string().optional().describe('What field/config does this clarify?'),\n },\n async ({ context, question_type, question, choices, priority = 'preferred', target_field }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Create session\n await httpRequest(port === 8765 ? '127.0.0.1' : '127.0.0.1', port, '/sessions', {});\n\n // Set context if provided\n if (context) {\n await httpRequest(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n `/sessions/${sessionId}/context`,\n { context: { purpose: context } }\n );\n }\n\n // Ask for clarification\n const request: ClarificationRequest = {\n ...(context !== undefined && { context }),\n question_type,\n question,\n ...(choices !== undefined && { choices }),\n priority,\n ...(target_field !== undefined && { target_field }),\n };\n\n const response = await httpRequest<ClarificationResponse>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/clarify',\n { request }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n // Format response for LLM\n const decision = response.decision;\n const value = decision.value;\n const source = decision.source;\n const explicit = decision.explicit ? 'explicitly' : 'via fallback';\n\n if (response.fallback_used) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ Clarification fallback used: ${response.fallback_reason || 'No user input available'}\\n\\n` +\n `Default value used: ${JSON.stringify(value)}\\n\\n` +\n `💡 Consider following up with the user later if this default isn't appropriate.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `✅ User clarified (${source}): ${JSON.stringify(value)}\\n\\n` +\n `Use this value to continue execution.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n // If server not available, try stdio mode as fallback\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Clarification failed: ${error instanceof Error ? error.message : 'Unknown error'}\\n\\n` +\n `Cannot proceed without user input. Consider:\\n` +\n `1. Using a reasonable default\\n` +\n `2. Asking the user directly in your response\\n` +\n `3. Skipping this step if optional`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Detect preference conflict\n server.tool(\n 'stackwright_pro_detect_conflict',\n \"Detect when a user's stated preference conflicts with their selected choices. \" +\n 'Use this to identify when users might be indecisive or misunderstood a question. ' +\n 'Returns conflict details and resolution options.',\n {\n stated_preference: z.string().describe('What the user said they wanted'),\n selected_values: z.record(z.string(), z.string()).describe('What the user actually selected'),\n },\n async ({ stated_preference, selected_values }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Check for conflict\n const response = await httpRequest<{ conflict: boolean; data?: any }>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/conflict',\n { stated_preference, selected_values }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n if (response.conflict) {\n const data = response.data;\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ CONFLICT DETECTED\\n\\n` +\n `User stated: \"${stated_preference}\"\\n` +\n `But selected: ${JSON.stringify(selected_values)}\\n\\n` +\n `Conflict: ${data.description}\\n\\n` +\n `Resolution options: ${data.options?.join(', ') || 'Ask user to clarify'}\\n\\n` +\n `💡 Consider asking the user to reconcile this conflict.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ No conflict detected between stated preference and selections.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Conflict detection failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Get clarification defaults\n server.tool(\n 'stackwright_pro_get_defaults',\n 'Get the current clarification defaults from config. ' +\n \"Use this to understand what fallback values will be used if user doesn't provide input.\",\n {\n config_path: z\n .string()\n .optional()\n .describe('Path to config file. Default: .stackwright/clarification.yaml'),\n },\n async ({ config_path }) => {\n // This reads from the Python config module directly\n // For now, return a message pointing to where config is stored\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `📋 Clarification defaults\\n\\n` +\n `Configuration is loaded from:\\n` +\n `- Environment: CLARIFICATION_* variables\\n` +\n `- Config file: ${config_path || '.stackwright/clarification.yaml'}\\n` +\n `- CLI args: --clarify-* flags\\n\\n` +\n `Default behaviors:\\n` +\n `- allow_dont_know: true (users can skip)\\n` +\n `- default_timeout: 120 seconds\\n` +\n `- channel_priority: [tui, cli_args, config, defaults]\\n\\n` +\n `💡 Set CLARIFICATION_DEFAULT_<FIELD>=value to change defaults.`,\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, realpathSync, lstatSync } from 'fs';\nimport { execSync } from 'child_process';\nimport path from 'path';\n\n/**\n * stackwright_pro_setup_packages MCP tool\n *\n * Ensures pro packages are present in a project's package.json.\n * Used by the Pro Foreman Otter to bootstrap dependencies before\n * specialist otters run — enabling the otter raft's IoC dependency\n * declaration pattern.\n *\n * Merge semantics: NEVER overwrites an existing version pin.\n * If a package is already declared at any version, it is skipped.\n * This preserves intentional version pinning by developers.\n */\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n [key: string]: unknown;\n}\n\ninterface SetupPackagesResult {\n success: boolean;\n added: string[];\n skipped: string[];\n scriptsAdded: string[];\n installed: boolean;\n packageJsonPath: string;\n error?: string;\n installError?: string;\n}\n\nexport function registerPackageTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_setup_packages',\n 'Ensures pro packages are present in a project\\'s package.json. ' +\n 'Safe to call multiple times — never overwrites existing version pins. ' +\n 'Use this to bootstrap dependencies before specialist otters run.',\n {\n // FIX 3 (B-new-1): Zod v4 requires two-arg z.record(keySchema, valueSchema)\n packages: z.record(z.string(), z.string()).describe(\n 'Dependencies to add. Record<packageName, version>. e.g. { \"@stackwright-pro/auth\": \"latest\" }'\n ),\n devPackages: z.record(z.string(), z.string()).optional().describe(\n 'devDependencies to add. Same format as packages.'\n ),\n scripts: z.record(z.string(), z.string()).optional().describe(\n 'npm scripts to add. Only adds if key does not already exist.'\n ),\n targetDir: z.string().optional().describe(\n 'Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory.'\n ),\n runInstall: z.boolean().optional().default(true).describe(\n 'Run pnpm install after writing package.json. Defaults to true.'\n ),\n },\n async ({ packages, devPackages, scripts, targetDir, runInstall }) => {\n const result = setupPackages({\n packages,\n devPackages,\n scripts,\n targetDir,\n runInstall,\n });\n\n const statusLine = result.success\n ? `✅ package.json updated: ${result.packageJsonPath}`\n : `❌ Failed: ${result.error}`;\n\n const lines = [\n statusLine,\n '',\n result.added.length > 0\n ? `Added (${result.added.length}): ${result.added.join(', ')}`\n : 'Added: none',\n result.skipped.length > 0\n ? `Skipped/already present (${result.skipped.length}): ${result.skipped.join(', ')}`\n : 'Skipped: none',\n result.scriptsAdded.length > 0\n ? `Scripts added (${result.scriptsAdded.length}): ${result.scriptsAdded.join(', ')}`\n : 'Scripts added: none',\n `pnpm install: ${result.installed ? 'ran successfully' : result.success && runInstall ? 'failed (non-fatal)' : 'skipped'}`,\n ];\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n\n/**\n * Core implementation — extracted so it can be tested directly without\n * going through the MCP server machinery. Keeping I/O at the edges.\n */\nexport function setupPackages(opts: {\n packages: Record<string, string>;\n devPackages?: Record<string, string>;\n scripts?: Record<string, string>;\n targetDir?: string;\n runInstall: boolean;\n}): SetupPackagesResult {\n const emptyResult: Omit<SetupPackagesResult, 'success' | 'error'> = {\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n };\n\n try {\n // -------------------------------------------------------------------------\n // Security: path traversal guard\n // -------------------------------------------------------------------------\n const cwd = process.cwd();\n const resolvedTarget = opts.targetDir\n ? path.resolve(opts.targetDir)\n : cwd;\n\n // Ensure resolved path stays within cwd — no sneaky ../../etc tricks\n const cwdWithSep = cwd.endsWith(path.sep) ? cwd : cwd + path.sep;\n if (resolvedTarget !== cwd && !resolvedTarget.startsWith(cwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory is outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Find package.json (existence check before symlink resolution)\n // -------------------------------------------------------------------------\n const preResolvePackageJsonPath = path.join(resolvedTarget, 'package.json');\n\n if (!existsSync(preResolvePackageJsonPath)) {\n return {\n success: false,\n ...emptyResult,\n error: `No package.json found in ${resolvedTarget}`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: directory-level symlink bypass guard (B2)\n // -------------------------------------------------------------------------\n let realTarget: string;\n try {\n realTarget = realpathSync(resolvedTarget);\n } catch {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n error: `Could not resolve real path of target directory`,\n };\n }\n\n const realCwd = realpathSync(cwd);\n const realCwdWithSep = realCwd.endsWith(path.sep) ? realCwd : realCwd + path.sep;\n if (realTarget !== realCwd && !realTarget.startsWith(realCwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory resolved to a location outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: file-level symlink guard at package.json (C-1 / FIX 1)\n // -------------------------------------------------------------------------\n // Reconstruct package.json path from the symlink-resolved target directory.\n // This prevents readFileSync / writeFileSync from following a file-level\n // symlink planted at <targetDir>/package.json.\n const realPackageJsonPath = path.join(realTarget, 'package.json');\n\n const pkgStat = lstatSync(realPackageJsonPath);\n if (pkgStat.isSymbolicLink()) {\n return {\n ...emptyResult,\n success: false,\n error: `package.json is a symlink — refusing to read or write`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: package name validation (C-2C / L-1)\n // -------------------------------------------------------------------------\n // npm package name spec: optional @scope/, then lowercase alphanumeric + hyphens/dots/underscores\n const VALID_PKG_NAME_RE = /^(@[a-z0-9][a-z0-9\\-._~]*\\/)?[a-z0-9][a-z0-9\\-._~]*$/;\n const allPkgNames = [\n ...Object.keys(opts.packages ?? {}),\n ...Object.keys(opts.devPackages ?? {}),\n ];\n for (const pkg of allPkgNames) {\n if (!VALID_PKG_NAME_RE.test(pkg)) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package name: '${pkg}' — must match npm package name specification`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: version string allowlist (C-2B / FIX 2B)\n // -------------------------------------------------------------------------\n // Allows: semver ranges (^1.0.0, ~2.1, >=3, 1.x, *), workspace:*, latest/next/beta/alpha/canary/rc\n // Blocks: git+https://, file:, npm:evil@, http://, ssh://, etc.\n const SAFE_VERSION_RE =\n /^(workspace:[*^~]?|\\*|latest|next|beta|alpha|canary|rc|[~^><=*|, ]*[\\d.x*][\\d.x*\\-+a-zA-Z.~^><=*|, ]*)$/;\n const allVersionEntries = [\n ...Object.entries(opts.packages ?? {}),\n ...Object.entries(opts.devPackages ?? {}),\n ];\n for (const [pkg, version] of allVersionEntries) {\n if (!SAFE_VERSION_RE.test(version.trim())) {\n return {\n ...emptyResult,\n success: false,\n error: `Unsafe version specifier for '${pkg}': '${version}' — only semver ranges, workspace:*, and dist-tags (latest/next/beta) are permitted`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: lifecycle script key blocklist (C-2A / FIX 2A)\n // -------------------------------------------------------------------------\n const BLOCKED_LIFECYCLE_KEYS = new Set([\n 'preinstall', 'install', 'postinstall', 'prepare',\n 'prepublish', 'prepublishOnly', 'prepack', 'postpack',\n 'dependencies', // pnpm hook key\n ]);\n if (opts.scripts) {\n for (const key of Object.keys(opts.scripts)) {\n if (BLOCKED_LIFECYCLE_KEYS.has(key)) {\n return {\n ...emptyResult,\n success: false,\n error: `Blocked lifecycle script key: '${key}' — writing npm lifecycle hooks is not permitted`,\n };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Read & parse\n // -------------------------------------------------------------------------\n const raw = readFileSync(realPackageJsonPath, 'utf8');\n\n // W2: Validate package.json structure with Zod before touching anything\n const PackageJsonSchema = z.object({\n // Zod v4: z.record(keySchema, valueSchema) — two-arg form required\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n }).passthrough();\n\n const schemaResult = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!schemaResult.success) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package.json structure: ${schemaResult.error.message}`,\n };\n }\n // FIX 4 (B-new-2): The schema has already validated the shape — the cast is earned.\n // passthrough() + noUncheckedIndexedAccess would otherwise broaden field types to unknown.\n const parsed = schemaResult.data as PackageJson;\n\n // -------------------------------------------------------------------------\n // Merge dependencies — NEVER overwrite existing version pins\n // -------------------------------------------------------------------------\n const added: string[] = [];\n const skipped: string[] = [];\n const scriptsAdded: string[] = [];\n\n // Live Set grows as packages are written — prevents same pkg landing in both buckets (B4).\n // Uses `in` semantics (not falsy) so empty-string versions are treated as existing (B3).\n const claimedPkgs = new Set<string>([\n ...Object.keys(parsed.dependencies ?? {}),\n ...Object.keys(parsed.devDependencies ?? {}),\n ]);\n\n // Regular dependencies\n parsed.dependencies = parsed.dependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.packages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.dependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n\n // Dev dependencies\n if (opts.devPackages && Object.keys(opts.devPackages).length > 0) {\n parsed.devDependencies = parsed.devDependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.devPackages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.devDependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n }\n\n // Scripts — same never-overwrite semantics\n if (opts.scripts && Object.keys(opts.scripts).length > 0) {\n parsed.scripts = parsed.scripts ?? {};\n for (const [key, value] of Object.entries(opts.scripts)) {\n if (parsed.scripts[key] === undefined) {\n parsed.scripts[key] = value;\n scriptsAdded.push(key);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Write back — use realPackageJsonPath (symlink-resolved) for all I/O\n // -------------------------------------------------------------------------\n writeFileSync(realPackageJsonPath, JSON.stringify(parsed, null, 2) + '\\n');\n\n // -------------------------------------------------------------------------\n // Run pnpm install (optional, non-fatal on failure)\n // -------------------------------------------------------------------------\n let installed = false;\n let installError: string | undefined;\n\n if (opts.runInstall) {\n try {\n execSync('pnpm install', { cwd: realTarget, stdio: 'pipe', timeout: 60_000 });\n installed = true;\n } catch (err) {\n // Don't blow up the whole tool — install failure is recoverable.\n // The caller can re-run or handle manually.\n installed = false;\n const spawnErr = err as { stderr?: Buffer; message?: string };\n installError = spawnErr.stderr?.toString().trim() || (err instanceof Error ? err.message : 'unknown error');\n }\n }\n\n return {\n success: true,\n added,\n skipped,\n scriptsAdded,\n installed,\n packageJsonPath: realPackageJsonPath,\n ...(installError !== undefined ? { installError } : {}),\n };\n } catch (err) {\n return { ...emptyResult, success: false, error: err instanceof Error ? err.message : String(err) };\n }\n}\n"],"mappings":"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","names":["server","path","z","server","z","server","z","listEntities","server","z","path","server","z","existsSync","path","server","readFileSync","path"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/tools/data-explorer.ts","../src/tools/security.ts","../src/tools/isr.ts","../src/tools/dashboard.ts","../src/tools/clarification.ts","../src/tools/packages.ts","../package.json"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { registerDataExplorerTools } from './tools/data-explorer.js';\nimport { registerSecurityTools } from './tools/security.js';\nimport { registerIsrTools } from './tools/isr.js';\nimport { registerDashboardTools } from './tools/dashboard.js';\nimport { registerClarificationTools } from './tools/clarification.js';\nimport { registerPackageTools } from './tools/packages.js';\nimport packageJson from '../package.json';\n\nconst server = new McpServer({\n name: 'stackwright-pro',\n version: packageJson.version,\n});\n\n// Register all Pro tools\nregisterDataExplorerTools(server); // stackwright_pro_list_entities, stackwright_pro_generate_filter\nregisterSecurityTools(server); // stackwright_pro_validate_spec, stackwright_pro_add_approved_spec, stackwright_pro_list_approved_specs\nregisterIsrTools(server); // stackwright_pro_configure_isr, stackwright_pro_configure_isr_batch\nregisterDashboardTools(server); // stackwright_pro_generate_dashboard, stackwright_pro_generate_detail_page\nregisterClarificationTools(server); // stackwright_pro_clarify, stackwright_pro_detect_conflict, stackwright_pro_get_defaults\nregisterPackageTools(server); // stackwright_pro_setup_packages\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Stackwright Pro MCP server running on stdio');\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities, generateFilter } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register data-explorer MCP tools.\n * Tools for discovering API entities and generating endpoint filters.\n */\nexport function registerDataExplorerTools(server: McpServer): void {\n // Tool: List available entities\n server.tool(\n 'stackwright_pro_list_entities',\n 'List all available API entities from OpenAPI specs or generated Zod schemas. ' +\n 'Use this to discover what entities are available before generating endpoint filters. ' +\n 'Returns entity names, endpoints, and field counts. ' +\n 'Part of the Pro Otter Raft for building API-integrated Stackwright applications.',\n {\n specPath: z.string().optional().describe('Path to OpenAPI spec file (YAML or JSON)'),\n projectRoot: z\n .string()\n .optional()\n .describe('Project root directory (auto-detected if omitted)'),\n },\n async ({ specPath, projectRoot }) => {\n const result = listEntities({\n ...(specPath !== undefined && { specPath }),\n ...(projectRoot !== undefined && { projectRoot }),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error discovering entities: ${(result.errors ?? []).join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = [`📦 Found ${result.entities.length} API Entities:\\n`];\n\n for (const entity of result.entities) {\n lines.push(`📦 ${entity.name} (${entity.slug})`);\n lines.push(` Endpoint: ${entity.endpoint}`);\n lines.push(` Fields: ${entity.fieldCount}`);\n if (entity.fields.length > 0) {\n const fieldTypes = entity.fields\n .slice(0, 3)\n .map((f) => `${f.name}:${f.type}`)\n .join(', ');\n lines.push(` Types: ${fieldTypes}${entity.fields.length > 3 ? '...' : ''}`);\n }\n lines.push('');\n }\n\n lines.push(\n `\\n💡 Use stackwright_pro_generate_filter with selected entity slugs to create endpoint filters.`\n );\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n\n // Tool: Generate endpoint filter\n server.tool(\n 'stackwright_pro_generate_filter',\n 'Generate endpoint filter configuration from selected entities. ' +\n 'Creates include/exclude patterns for stackwright.yml OpenAPI integration. ' +\n 'Use this after stackwright_pro_list_entities to select which API endpoints the application needs. ' +\n 'Only selected endpoints will generate client code, reducing bundle size and improving security.',\n {\n selectedEntities: z\n .array(z.string())\n .describe('Entity slugs to include (e.g., [\"equipment\", \"supplies\"])'),\n excludePatterns: z\n .array(z.string())\n .optional()\n .describe('Glob patterns to exclude (e.g., [\"/admin/**\", \"/reports/**\"])'),\n projectRoot: z.string().optional().describe('Project root directory'),\n },\n async ({ selectedEntities, excludePatterns, projectRoot }) => {\n const result = generateFilter({\n selectedEntities,\n ...(excludePatterns !== undefined && { excludePatterns }),\n projectRoot: projectRoot ?? process.cwd(),\n });\n\n if (!result.success) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error generating filter: ${result.warnings?.join(', ')}`,\n },\n ],\n isError: true,\n };\n }\n\n const lines: string[] = ['🔐 Generated Endpoint Filter:\\n'];\n lines.push('```yaml');\n lines.push('integrations:');\n lines.push(' - type: openapi');\n lines.push(' endpoints:');\n\n if (result.filter.include && result.filter.include.length > 0) {\n lines.push(' include:');\n for (const path of result.filter.include) {\n lines.push(` - ${path}`);\n }\n }\n\n if (result.filter.exclude && result.filter.exclude.length > 0) {\n lines.push(' exclude:');\n for (const pattern of result.filter.exclude) {\n lines.push(` - ${pattern}`);\n }\n }\n\n lines.push('```');\n\n if (result.warnings && result.warnings.length > 0) {\n lines.push('\\n⚠️ Warnings:');\n for (const warning of result.warnings) {\n lines.push(` ${warning}`);\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { createHash } from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register security-focused MCP tools.\n * Tools for validating specs against approved-specs and managing the allowlist.\n */\nexport function registerSecurityTools(server: McpServer): void {\n // Tool: Validate a spec against approved-specs\n server.tool(\n 'stackwright_pro_validate_spec',\n 'Validate an OpenAPI spec against the enterprise approved-specs configuration. ' +\n 'Checks if the spec URL is on the allowlist and verifies SHA-256 hash integrity. ' +\n 'Use this in enterprise environments where only pre-approved API specs are allowed. ' +\n 'Fails build if spec is not approved or has been modified.',\n {\n specPath: z.string().describe('URL or file path to the OpenAPI spec to validate'),\n configPath: z\n .string()\n .optional()\n .describe('Path to stackwright.yml with prebuild.security config'),\n },\n async ({ specPath, configPath }) => {\n // Try to load config from stackwright.yml\n let securityEnabled = false;\n const allowlist: Array<{ name: string; url: string; sha256: string }> = [];\n\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (fs.existsSync(configFile)) {\n try {\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Simple regex extraction for security config\n const securityMatch = content.match(\n /prebuild:\\s*\\n\\s*security:\\s*\\n\\s*enabled:\\s*(true|false)/\n );\n if (securityMatch && securityMatch[1] === 'true') {\n securityEnabled = true;\n // Extract allowlist entries\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n for (const match of specMatches) {\n allowlist.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim(),\n });\n }\n }\n } catch {\n // Config exists but couldn't parse - continue without it\n }\n }\n\n // If no security config, just return success (security not enabled)\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec validation skipped (security not enabled)\\n\\nTo enable approved-specs validation, add to stackwright.yml:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist:\\n - name: My API\\n url: ${specPath}\\n sha256: <sha256-of-spec>`,\n },\n ],\n };\n }\n\n // Check if spec is in allowlist\n const matchingSpec = allowlist.find((s) => s.url === specPath);\n\n if (!matchingSpec) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Spec rejected!\\n\\nError Code: SPEC_NOT_IN_ALLOWLIST\\n\\nURL: ${specPath}\\n\\nThis spec is not on the approved-specs allowlist. ` +\n `Add it using stackwright_pro_add_approved_spec before proceeding.`,\n },\n ],\n isError: true,\n };\n }\n\n // For file-based specs, compute hash and validate\n if (!specPath.startsWith('http://') && !specPath.startsWith('https://')) {\n if (fs.existsSync(specPath)) {\n const specContent = fs.readFileSync(specPath, 'utf8');\n const sha256 = createHash('sha256').update(specContent).digest('hex');\n\n if (sha256 !== matchingSpec.sha256) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec hash mismatch!\\n\\nError Code: SPEC_HASH_MISMATCH\\n\\nExpected: ${matchingSpec.sha256.substring(0, 16)}...\\nActual: ${sha256.substring(0, 16)}...\\n\\nThe spec has been modified since it was approved. Re-approve the spec to continue.`,\n },\n ],\n isError: true,\n };\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ Spec approved!\\n\\nName: ${matchingSpec.name}\\nURL: ${specPath}\\nStatus: Valid (${allowlist.length} specs on allowlist)`,\n },\n ],\n };\n }\n );\n\n // Tool: Add approved spec to allowlist\n server.tool(\n 'stackwright_pro_add_approved_spec',\n 'Add an OpenAPI spec to the approved-specs allowlist in stackwright.yml. ' +\n 'Computes the SHA-256 hash of the spec and adds it to the security configuration. ' +\n 'Use this when onboarding a new API in enterprise environments.',\n {\n name: z.string().describe('Human-readable name for the spec'),\n url: z.string().describe('URL or file path to the OpenAPI spec'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ name, url, configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n // Compute SHA-256 of spec\n let sha256 = '<computed-at-build>';\n\n try {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n // URL spec - hash computed at build time\n sha256 = '<computed-at-build>';\n } else if (fs.existsSync(url)) {\n const specContent = fs.readFileSync(url, 'utf8');\n sha256 = createHash('sha256').update(specContent).digest('hex');\n } else {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Spec file not found: ${url}`,\n },\n ],\n isError: true,\n };\n }\n } catch (e) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Failed to read spec: ${e}`,\n },\n ],\n isError: true,\n };\n }\n\n const yamlSnippet = ` - name: ${name}\n url: ${url}\n sha256: ${sha256}`;\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📝 Add this to stackwright.yml under prebuild.security.allowlist:\\n\\n${yamlSnippet}\\n\\nSHA-256 computed: ${sha256}`,\n },\n ],\n };\n }\n );\n\n // Tool: List approved specs\n server.tool(\n 'stackwright_pro_list_approved_specs',\n 'List all specs currently on the approved-specs allowlist. ' +\n 'Shows spec names, URLs, and hash prefixes. ' +\n 'Use this to audit what APIs are approved in the project.',\n {\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ configPath }) => {\n const configFile = configPath || path.join(process.cwd(), 'stackwright.yml');\n\n if (!fs.existsSync(configFile)) {\n return {\n content: [\n {\n type: 'text' as const,\n text: '❌ stackwright.yml not found in project root.',\n },\n ],\n isError: true,\n };\n }\n\n const content = fs.readFileSync(configFile, 'utf8');\n\n // Check if security is enabled\n const securityEnabled =\n content.includes('prebuild:') &&\n content.includes('security:') &&\n content.includes('enabled: true');\n\n if (!securityEnabled) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Approved-specs validation is not enabled.\\n\\nAdd to stackwright.yml to enable:\\n\\nprebuild:\\n security:\\n enabled: true\\n allowlist: []',\n },\n ],\n };\n }\n\n // Extract specs\n const specs: Array<{ name: string; url: string; sha256: string }> = [];\n const specMatches = content.matchAll(\n /- name:\\s*(.+?)\\n\\s+url:\\s*(.+?)\\n\\s+sha256:\\s*(.+?)(?:\\n|$)/g\n );\n\n for (const match of specMatches) {\n specs.push({\n name: match[1]!.trim(),\n url: match[2]!.trim(),\n sha256: match[3]!.trim().substring(0, 16) + '...',\n });\n }\n\n if (specs.length === 0) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'ℹ️ Security enabled but no specs on allowlist.\\n\\nAdd specs using stackwright_pro_add_approved_spec.',\n },\n ],\n };\n }\n\n const lines = [`🔐 Approved Specs (${specs.length}):\\n`];\n for (const spec of specs) {\n lines.push(`📦 ${spec.name}`);\n lines.push(` URL: ${spec.url}`);\n lines.push(` Hash: ${spec.sha256}`);\n lines.push('');\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Register ISR configuration MCP tools.\n * Tools for configuring Incremental Static Regeneration for API-backed collections.\n */\nexport function registerIsrTools(server: McpServer): void {\n // Tool: Configure ISR for a collection\n server.tool(\n 'stackwright_pro_configure_isr',\n 'Configure Incremental Static Regeneration (ISR) for an API-backed collection. ' +\n 'ISR allows API data to be cached and refreshed on a schedule, providing real-time data ' +\n 'with the performance of static generation. ' +\n 'Use this after stackwright_pro_generate_filter to set revalidation intervals.',\n {\n collection: z.string().describe('Collection name (e.g., \"equipment\", \"supplies\")'),\n revalidateSeconds: z\n .number()\n .optional()\n .describe('Revalidation interval in seconds (default: 60)'),\n fallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Fallback behavior for new pages'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collection, revalidateSeconds = 60, fallback = 'blocking', configPath }) => {\n const revalidate = revalidateSeconds;\n\n const yamlSnippet = `# Add to stackwright.yml under integrations:\n - type: openapi\n name: ${collection}\n # ... other config\n isr:\n revalidate: ${revalidate}\n fallback: ${fallback}`;\n\n let description = '';\n if (revalidate < 60) {\n description = '⚡ Very fresh data (revalidate every ' + revalidate + 's)';\n } else if (revalidate < 300) {\n description = '📊 Fresh data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else if (revalidate < 3600) {\n description = '💾 Cached data (revalidate every ' + (revalidate / 60).toFixed(0) + ' min)';\n } else {\n description =\n '🗄️ Static data (revalidate every ' + (revalidate / 3600).toFixed(0) + ' hour)';\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `⚙️ ISR Configuration for \"${collection}\":\\n\\n${description}\\n\\nFallback: ${fallback === 'blocking' ? '⏳ Show loading until cached' : fallback === 'true' ? '📄 Generate on demand' : '❌ 404 for new pages'}\\n\\n\\`\\`\\`yaml\\n${yamlSnippet}\\n\\`\\`\\``,\n },\n ],\n };\n }\n );\n\n // Tool: Configure ISR for multiple collections\n server.tool(\n 'stackwright_pro_configure_isr_batch',\n 'Configure ISR for multiple collections at once. ' +\n 'More efficient than calling stackwright_pro_configure_isr multiple times. ' +\n 'Provide different revalidation intervals based on data freshness requirements.',\n {\n collections: z\n .array(\n z.object({\n name: z.string().describe('Collection name'),\n revalidateSeconds: z.number().optional().describe('Revalidation interval'),\n })\n )\n .describe('Array of collection configurations'),\n defaultFallback: z\n .enum(['blocking', 'true', 'false'])\n .optional()\n .describe('Default fallback behavior'),\n configPath: z.string().optional().describe('Path to stackwright.yml'),\n },\n async ({ collections, defaultFallback = 'blocking', configPath }) => {\n const lines = [`⚙️ Batch ISR Configuration:\\n`];\n\n for (const col of collections) {\n const rev = col.revalidateSeconds || 60;\n let freshness = '💾';\n if (rev < 60) freshness = '⚡';\n else if (rev < 300) freshness = '📊';\n else if (rev >= 3600) freshness = '🗄️';\n\n lines.push(`${freshness} ${col.name}: revalidate=${rev}s`);\n }\n\n lines.push(`\\nFallback: ${defaultFallback}`);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { listEntities } from '@stackwright-pro/cli-data-explorer';\n\n/**\n * Register dashboard generation MCP tools.\n * Tools for building pages that display live API data.\n */\nexport function registerDashboardTools(server: McpServer): void {\n // Tool: Generate dashboard page configuration\n server.tool(\n 'stackwright_pro_generate_dashboard',\n 'Generate a dashboard page configuration for displaying API data. ' +\n 'Creates YAML content for a Stackwright page with grid, metric_card, data_table, and collection_list content types. ' +\n 'Use this after stackwright_pro_generate_filter to create pages for your API collections.',\n {\n entities: z.array(z.string()).describe('Entity slugs to include in dashboard'),\n layout: z.enum(['grid', 'table', 'mixed']).optional().describe('Dashboard layout style'),\n pageTitle: z.string().optional().describe('Page title'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for entity details'),\n },\n async ({ entities, layout = 'mixed', pageTitle, specPath }) => {\n // Get entity details if spec provided\n let entityDetails: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n entityDetails = result.entities.filter((e) => entities.includes(e.slug));\n }\n }\n\n const title =\n pageTitle || entities.map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(' & ');\n\n const yamlLines = [\n '# Dashboard page configuration',\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${title} | Dashboard\"`,\n ` description: \"Live data from API\"`,\n '',\n ' content_items:',\n ];\n\n // Add metric cards in a grid for each entity\n if (layout === 'grid' || layout === 'mixed') {\n for (const slug of entities) {\n yamlLines.push(` - type: grid`);\n yamlLines.push(` columns: 4`);\n yamlLines.push(` items:`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Total\"`);\n yamlLines.push(` value: {{ ${slug}.count }}`);\n yamlLines.push(` icon: Database`);\n yamlLines.push(` - type: metric_card`);\n yamlLines.push(` label: \"Active\"`);\n yamlLines.push(` value: 0`);\n yamlLines.push(` icon: CheckCircle`);\n yamlLines.push('');\n }\n }\n\n // Add collection listing for each entity\n yamlLines.push(` - type: collection_list`);\n yamlLines.push(` label: ${entities[0]}-listing`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` showFilters: true`);\n yamlLines.push(` showSearch: true`);\n const defaultCols = ['id', 'name', 'status', 'created_at'];\n yamlLines.push(\n ` columns: ${\n entityDetails[0]?.fields\n ?.slice(0, 4)\n .map((f: any) => f.name)\n .join(', ') || defaultCols.join(', ')\n }`\n );\n yamlLines.push('');\n\n if (layout === 'table') {\n yamlLines.push(` - type: data_table`);\n yamlLines.push(` label: ${entities[0]}-table`);\n yamlLines.push(` collection: ${entities[0]}`);\n yamlLines.push(` columns:`);\n yamlLines.push(` - field: id`);\n yamlLines.push(` header: ID`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: name`);\n yamlLines.push(` header: Name`);\n yamlLines.push(` sortable: true`);\n yamlLines.push(` - field: status`);\n yamlLines.push(` header: Status`);\n yamlLines.push(` type: badge`);\n }\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📊 Generated Dashboard for: ${entities.join(', ')}\\n\\nLayout: ${layout}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/dashboard/content.yml and validate with stackwright_validate_pages.`,\n },\n ],\n };\n }\n );\n\n // Tool: Generate detail page\n server.tool(\n 'stackwright_pro_generate_detail_page',\n 'Generate a detail view page for a single API entity. ' +\n 'Creates YAML content for displaying all fields of an individual record. ' +\n 'Use this to create detail pages that complement collection listing pages.',\n {\n entity: z.string().describe('Entity slug (e.g., \"equipment\")'),\n slugField: z.string().optional().describe('Field to use as URL slug (default: \"id\")'),\n specPath: z.string().optional().describe('Path to OpenAPI spec for field details'),\n },\n async ({ entity, slugField = 'id', specPath }) => {\n // Get field details if spec provided\n let fields: any[] = [];\n if (specPath) {\n const result = listEntities({ specPath });\n if (result.success) {\n const ent = result.entities.find((e) => e.slug === entity);\n if (ent) {\n fields = ent.fields;\n }\n }\n }\n\n const entityName = entity.charAt(0).toUpperCase() + entity.slice(1);\n\n const yamlLines = [\n `# Detail page for ${entityName}`,\n '# Generated by Stackwright Pro MCP',\n '',\n 'content:',\n ' meta:',\n ` title: \"${entityName} Details | {{ ${entity}.${slugField} }}\"`,\n '',\n ' content_items:',\n ' - main:',\n ' label: \"detail-header\"',\n ' heading:',\n ` text: \"{{ ${entity}.${slugField} }}\"`,\n ' textSize: \"h1\"',\n ' textBlocks:',\n ` - text: \"Details for this ${entity}\"`,\n ' textSize: \"body1\"',\n ' background: \"primary\"',\n ' color: \"text\"',\n '',\n ' - grid:',\n ' label: \"detail-fields\"',\n ' columns: 2',\n ' items:',\n ];\n\n // Add field cards\n const displayFields =\n fields.length > 0\n ? fields.slice(0, 8)\n : [\n { name: slugField, type: 'string' },\n { name: 'created_at', type: 'datetime' },\n { name: 'updated_at', type: 'datetime' },\n ];\n\n for (const field of displayFields) {\n const label = field.name\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (l: string) => l.toUpperCase());\n yamlLines.push(` - card:`);\n yamlLines.push(` label: \"${field.name}-field\"`);\n yamlLines.push(` heading:`);\n yamlLines.push(` text: \"${label}\"`);\n yamlLines.push(` textSize: \"h4\"`);\n yamlLines.push(` content:`);\n yamlLines.push(` - text: \"{{ ${entity}.${field.name} }}\"`);\n yamlLines.push(` textSize: \"body1\"`);\n }\n\n yamlLines.push(' background: \"background\"');\n\n const yaml = yamlLines.join('\\n');\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `📄 Generated Detail Page for: ${entity}\\n\\n\\`\\`\\`yaml\\n${yaml}\\n\\`\\`\\`\\n\\n💡 Add this to pages/${entity}/[${slugField}]/content.yml and validate.`,\n },\n ],\n };\n }\n );\n}\n","/**\n * Clarification MCP Tools\n *\n * Provides human-in-the-loop clarification for otters that encounter\n * ambiguity during execution.\n *\n * This bridges to the Python Clarification Protocol server which\n * handles:\n * - Channel routing (TUI, CLI args, config, defaults)\n * - Conflict detection\n * - Stubborn user escalation\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { spawn, ChildProcess } from 'child_process';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { randomUUID } from 'crypto';\nimport { existsSync, unlinkSync } from 'fs';\n\n// Types matching Python server\nexport interface ClarificationRequest {\n context?: string;\n question_type: 'closed_choice' | 'open_text' | 'conditional' | 'multi_step' | 'reconciliation';\n question: string;\n choices?: string[];\n priority?: 'blocking' | 'preferred' | 'optional';\n target_field?: string;\n}\n\nexport interface ClarificationResponse {\n request_id: string;\n decision: {\n value: unknown;\n explicit: boolean;\n source: string;\n };\n fallback_used: boolean;\n fallback_reason?: string;\n}\n\n// Track active Python server processes\nconst activeServers: Map<string, ChildProcess> = new Map();\n\n/**\n * Start the Python Clarification Protocol server\n */\nasync function startPythonServer(sessionId: string): Promise<{ port: number; socketPath: string }> {\n const socketPath = join(tmpdir(), `otter-raft-${randomUUID()}.sock`);\n const port = 8765 + Math.floor(Math.random() * 100); // Random port to avoid conflicts\n\n return new Promise((resolve, reject) => {\n const pythonPath = process.platform === 'win32' ? 'python' : 'python3';\n\n // Find Python package\n const packageRoot = findPythonPackageRoot();\n\n const proc = spawn(\n pythonPath,\n ['-m', 'stackwright_pro.raft.server', '--socket', socketPath, '--port', String(port)],\n {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PYTHONPATH: packageRoot,\n },\n }\n );\n\n // Register process for cleanup\n activeServers.set(sessionId, proc);\n\n let startupOutput = '';\n let started = false;\n\n proc.stdout?.on('data', (data: Buffer) => {\n startupOutput += data.toString();\n if (startupOutput.includes('Server ready') || startupOutput.includes('HTTP server')) {\n started = true;\n resolve({ port, socketPath });\n }\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n // Only log errors, not startup messages\n if (!startupOutput.includes('Starting')) {\n console.error('[Python Clarification]', data.toString().trim());\n }\n });\n\n proc.on('error', (err) => {\n if (!started) {\n activeServers.delete(sessionId);\n reject(new Error(`Failed to start Python server: ${err.message}`));\n }\n });\n\n proc.on('exit', (code) => {\n activeServers.delete(sessionId);\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath);\n } catch {\n // Ignore cleanup errors\n }\n }\n });\n\n // Timeout after 10 seconds\n setTimeout(() => {\n if (!started) {\n proc.kill();\n activeServers.delete(sessionId);\n reject(new Error('Python server startup timeout'));\n }\n }, 10000);\n });\n}\n\n/**\n * Stop the Python server for a session\n */\nasync function stopPythonServer(sessionId: string): Promise<void> {\n const proc = activeServers.get(sessionId);\n if (proc) {\n proc.kill('SIGTERM');\n activeServers.delete(sessionId);\n }\n}\n\n/**\n * Make HTTP request to Python server\n */\nasync function httpRequest<T>(\n host: string,\n port: number,\n path: string,\n body?: unknown\n): Promise<T> {\n const http = await import('http');\n\n return new Promise((resolve, reject) => {\n const url = new URL(path, `http://${host}:${port}`);\n\n const reqOptions = {\n hostname: host,\n port: port,\n path: url.pathname,\n method: body ? 'POST' : 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n\n const req = http.request(reqOptions, (res) => {\n let data = '';\n\n res.on('data', (chunk: Buffer) => {\n data += chunk.toString();\n });\n\n res.on('end', () => {\n try {\n const parsed = JSON.parse(data);\n if (res.statusCode && res.statusCode >= 400) {\n reject(new Error(parsed.detail || parsed.error || `HTTP ${res.statusCode}`));\n } else {\n resolve(parsed);\n }\n } catch (e) {\n reject(new Error(`Failed to parse response: ${data}`));\n }\n });\n });\n\n req.on('error', reject);\n\n if (body) {\n req.write(JSON.stringify(body));\n }\n\n req.end();\n });\n}\n\n/**\n * Find Python package root\n */\nfunction findPythonPackageRoot(): string {\n const candidates = [\n join(__dirname, '../../python/src'),\n join(__dirname, '../../../python/src'),\n join(process.cwd(), 'python/src'),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return process.cwd();\n}\n\n/**\n * Register clarification MCP tools\n */\nexport function registerClarificationTools(server: McpServer): void {\n // Tool: Ask for clarification (creates session)\n server.tool(\n 'stackwright_pro_clarify',\n 'Ask the user for clarification when an otter encounters ambiguity. ' +\n 'This is for MID-EXECUTION questions, not upfront question collection. ' +\n 'Use this when the otter needs user input to proceed. ' +\n \"Returns the user's decision which should be used to continue execution.\",\n {\n context: z.string().optional().describe('Context about what the otter is trying to do'),\n question_type: z\n .enum(['closed_choice', 'open_text', 'conditional', 'multi_step', 'reconciliation'])\n .describe('Type of question being asked'),\n question: z.string().describe('The clarification question to ask the user'),\n choices: z\n .array(z.string())\n .optional()\n .describe('Options for closed_choice or multi_step questions'),\n priority: z\n .enum(['blocking', 'preferred', 'optional'])\n .optional()\n .describe('How critical is this clarification? Default: preferred'),\n target_field: z.string().optional().describe('What field/config does this clarify?'),\n },\n async ({ context, question_type, question, choices, priority = 'preferred', target_field }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Create session\n await httpRequest(port === 8765 ? '127.0.0.1' : '127.0.0.1', port, '/sessions', {});\n\n // Set context if provided\n if (context) {\n await httpRequest(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n `/sessions/${sessionId}/context`,\n { context: { purpose: context } }\n );\n }\n\n // Ask for clarification\n const request: ClarificationRequest = {\n ...(context !== undefined && { context }),\n question_type,\n question,\n ...(choices !== undefined && { choices }),\n priority,\n ...(target_field !== undefined && { target_field }),\n };\n\n const response = await httpRequest<ClarificationResponse>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/clarify',\n { request }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n // Format response for LLM\n const decision = response.decision;\n const value = decision.value;\n const source = decision.source;\n const explicit = decision.explicit ? 'explicitly' : 'via fallback';\n\n if (response.fallback_used) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ Clarification fallback used: ${response.fallback_reason || 'No user input available'}\\n\\n` +\n `Default value used: ${JSON.stringify(value)}\\n\\n` +\n `💡 Consider following up with the user later if this default isn't appropriate.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `✅ User clarified (${source}): ${JSON.stringify(value)}\\n\\n` +\n `Use this value to continue execution.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n // If server not available, try stdio mode as fallback\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `❌ Clarification failed: ${error instanceof Error ? error.message : 'Unknown error'}\\n\\n` +\n `Cannot proceed without user input. Consider:\\n` +\n `1. Using a reasonable default\\n` +\n `2. Asking the user directly in your response\\n` +\n `3. Skipping this step if optional`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Detect preference conflict\n server.tool(\n 'stackwright_pro_detect_conflict',\n \"Detect when a user's stated preference conflicts with their selected choices. \" +\n 'Use this to identify when users might be indecisive or misunderstood a question. ' +\n 'Returns conflict details and resolution options.',\n {\n stated_preference: z.string().describe('What the user said they wanted'),\n selected_values: z.record(z.string(), z.string()).describe('What the user actually selected'),\n },\n async ({ stated_preference, selected_values }) => {\n const sessionId = `mcp_${randomUUID().slice(0, 8)}`;\n\n try {\n // Start Python server\n const { port } = await startPythonServer(sessionId);\n\n // Check for conflict\n const response = await httpRequest<{ conflict: boolean; data?: any }>(\n port === 8765 ? '127.0.0.1' : '127.0.0.1',\n port,\n '/conflict',\n { stated_preference, selected_values }\n );\n\n // Cleanup\n await stopPythonServer(sessionId);\n\n if (response.conflict) {\n const data = response.data;\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `⚠️ CONFLICT DETECTED\\n\\n` +\n `User stated: \"${stated_preference}\"\\n` +\n `But selected: ${JSON.stringify(selected_values)}\\n\\n` +\n `Conflict: ${data.description}\\n\\n` +\n `Resolution options: ${data.options?.join(', ') || 'Ask user to clarify'}\\n\\n` +\n `💡 Consider asking the user to reconcile this conflict.`,\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `✅ No conflict detected between stated preference and selections.`,\n },\n ],\n };\n } catch (error) {\n await stopPythonServer(sessionId);\n\n return {\n content: [\n {\n type: 'text' as const,\n text: `❌ Conflict detection failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n }\n );\n\n // Tool: Get clarification defaults\n server.tool(\n 'stackwright_pro_get_defaults',\n 'Get the current clarification defaults from config. ' +\n \"Use this to understand what fallback values will be used if user doesn't provide input.\",\n {\n config_path: z\n .string()\n .optional()\n .describe('Path to config file. Default: .stackwright/clarification.yaml'),\n },\n async ({ config_path }) => {\n // This reads from the Python config module directly\n // For now, return a message pointing to where config is stored\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `📋 Clarification defaults\\n\\n` +\n `Configuration is loaded from:\\n` +\n `- Environment: CLARIFICATION_* variables\\n` +\n `- Config file: ${config_path || '.stackwright/clarification.yaml'}\\n` +\n `- CLI args: --clarify-* flags\\n\\n` +\n `Default behaviors:\\n` +\n `- allow_dont_know: true (users can skip)\\n` +\n `- default_timeout: 120 seconds\\n` +\n `- channel_priority: [tui, cli_args, config, defaults]\\n\\n` +\n `💡 Set CLARIFICATION_DEFAULT_<FIELD>=value to change defaults.`,\n },\n ],\n };\n }\n );\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { readFileSync, writeFileSync, existsSync, realpathSync, lstatSync } from 'fs';\nimport { execSync } from 'child_process';\nimport path from 'path';\n\n/**\n * stackwright_pro_setup_packages MCP tool\n *\n * Ensures pro packages are present in a project's package.json.\n * Used by the Pro Foreman Otter to bootstrap dependencies before\n * specialist otters run — enabling the otter raft's IoC dependency\n * declaration pattern.\n *\n * Merge semantics: NEVER overwrites an existing version pin.\n * If a package is already declared at any version, it is skipped.\n * This preserves intentional version pinning by developers.\n */\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n [key: string]: unknown;\n}\n\ninterface SetupPackagesResult {\n success: boolean;\n added: string[];\n skipped: string[];\n scriptsAdded: string[];\n installed: boolean;\n packageJsonPath: string;\n error?: string;\n installError?: string;\n}\n\nexport function registerPackageTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_setup_packages',\n \"Ensures pro packages are present in a project's package.json. \" +\n 'Safe to call multiple times — never overwrites existing version pins. ' +\n 'Use this to bootstrap dependencies before specialist otters run.',\n {\n // FIX 3 (B-new-1): Zod v4 requires two-arg z.record(keySchema, valueSchema)\n packages: z\n .record(z.string(), z.string())\n .describe(\n 'Dependencies to add. Record<packageName, version>. e.g. { \"@stackwright-pro/auth\": \"latest\" }'\n ),\n devPackages: z\n .record(z.string(), z.string())\n .optional()\n .describe('devDependencies to add. Same format as packages.'),\n scripts: z\n .record(z.string(), z.string())\n .optional()\n .describe('npm scripts to add. Only adds if key does not already exist.'),\n targetDir: z\n .string()\n .optional()\n .describe(\n 'Project directory containing package.json. Defaults to process.cwd(). Must be an absolute path within the current working directory.'\n ),\n runInstall: z\n .boolean()\n .optional()\n .default(true)\n .describe('Run pnpm install after writing package.json. Defaults to true.'),\n },\n async ({ packages, devPackages, scripts, targetDir, runInstall }) => {\n // exactOptionalPropertyTypes: true means we cannot pass `undefined` explicitly\n // for optional fields — conditionally spread them instead.\n const result = setupPackages({\n packages,\n runInstall,\n ...(devPackages !== undefined ? { devPackages } : {}),\n ...(scripts !== undefined ? { scripts } : {}),\n ...(targetDir !== undefined ? { targetDir } : {}),\n });\n\n const statusLine = result.success\n ? `✅ package.json updated: ${result.packageJsonPath}`\n : `❌ Failed: ${result.error}`;\n\n const lines = [\n statusLine,\n '',\n result.added.length > 0\n ? `Added (${result.added.length}): ${result.added.join(', ')}`\n : 'Added: none',\n result.skipped.length > 0\n ? `Skipped/already present (${result.skipped.length}): ${result.skipped.join(', ')}`\n : 'Skipped: none',\n result.scriptsAdded.length > 0\n ? `Scripts added (${result.scriptsAdded.length}): ${result.scriptsAdded.join(', ')}`\n : 'Scripts added: none',\n `pnpm install: ${result.installed ? 'ran successfully' : result.success && runInstall ? 'failed (non-fatal)' : 'skipped'}`,\n ];\n\n return {\n content: [\n {\n type: 'text' as const,\n text: lines.join('\\n'),\n },\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n };\n }\n );\n}\n\n/**\n * Core implementation — extracted so it can be tested directly without\n * going through the MCP server machinery. Keeping I/O at the edges.\n */\nexport function setupPackages(opts: {\n packages: Record<string, string>;\n devPackages?: Record<string, string>;\n scripts?: Record<string, string>;\n targetDir?: string;\n runInstall: boolean;\n}): SetupPackagesResult {\n const emptyResult: Omit<SetupPackagesResult, 'success' | 'error'> = {\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n };\n\n try {\n // -------------------------------------------------------------------------\n // Security: path traversal guard\n // -------------------------------------------------------------------------\n const cwd = process.cwd();\n const resolvedTarget = opts.targetDir ? path.resolve(opts.targetDir) : cwd;\n\n // Ensure resolved path stays within cwd — no sneaky ../../etc tricks\n const cwdWithSep = cwd.endsWith(path.sep) ? cwd : cwd + path.sep;\n if (resolvedTarget !== cwd && !resolvedTarget.startsWith(cwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory is outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Find package.json (existence check before symlink resolution)\n // -------------------------------------------------------------------------\n const preResolvePackageJsonPath = path.join(resolvedTarget, 'package.json');\n\n if (!existsSync(preResolvePackageJsonPath)) {\n return {\n success: false,\n ...emptyResult,\n error: `No package.json found in ${resolvedTarget}`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: directory-level symlink bypass guard (B2)\n // -------------------------------------------------------------------------\n let realTarget: string;\n try {\n realTarget = realpathSync(resolvedTarget);\n } catch {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n error: `Could not resolve real path of target directory`,\n };\n }\n\n const realCwd = realpathSync(cwd);\n const realCwdWithSep = realCwd.endsWith(path.sep) ? realCwd : realCwd + path.sep;\n if (realTarget !== realCwd && !realTarget.startsWith(realCwdWithSep)) {\n return {\n success: false,\n added: [],\n skipped: [],\n scriptsAdded: [],\n installed: false,\n packageJsonPath: '',\n // FIX 5 (M-4): do not leak absolute paths in error messages\n error: `Path traversal rejected: target directory resolved to a location outside the allowed working directory`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: file-level symlink guard at package.json (C-1 / FIX 1)\n // -------------------------------------------------------------------------\n // Reconstruct package.json path from the symlink-resolved target directory.\n // This prevents readFileSync / writeFileSync from following a file-level\n // symlink planted at <targetDir>/package.json.\n const realPackageJsonPath = path.join(realTarget, 'package.json');\n\n const pkgStat = lstatSync(realPackageJsonPath);\n if (pkgStat.isSymbolicLink()) {\n return {\n ...emptyResult,\n success: false,\n error: `package.json is a symlink — refusing to read or write`,\n };\n }\n\n // -------------------------------------------------------------------------\n // Security: package name validation (C-2C / L-1)\n // -------------------------------------------------------------------------\n // npm package name spec: optional @scope/, then lowercase alphanumeric + hyphens/dots/underscores\n const VALID_PKG_NAME_RE = /^(@[a-z0-9][a-z0-9\\-._~]*\\/)?[a-z0-9][a-z0-9\\-._~]*$/;\n const allPkgNames = [\n ...Object.keys(opts.packages ?? {}),\n ...Object.keys(opts.devPackages ?? {}),\n ];\n for (const pkg of allPkgNames) {\n if (!VALID_PKG_NAME_RE.test(pkg)) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package name: '${pkg}' — must match npm package name specification`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: version string allowlist (C-2B / FIX 2B)\n // -------------------------------------------------------------------------\n // Allows: semver ranges (^1.0.0, ~2.1, >=3, 1.x, *), workspace:*, latest/next/beta/alpha/canary/rc\n // Blocks: git+https://, file:, npm:evil@, http://, ssh://, etc.\n const SAFE_VERSION_RE =\n /^(workspace:[*^~]?|\\*|latest|next|beta|alpha|canary|rc|[~^><=*|, ]*[\\d.x*][\\d.x*\\-+a-zA-Z.~^><=*|, ]*)$/;\n const allVersionEntries = [\n ...Object.entries(opts.packages ?? {}),\n ...Object.entries(opts.devPackages ?? {}),\n ];\n for (const [pkg, version] of allVersionEntries) {\n if (!SAFE_VERSION_RE.test(version.trim())) {\n return {\n ...emptyResult,\n success: false,\n error: `Unsafe version specifier for '${pkg}': '${version}' — only semver ranges, workspace:*, and dist-tags (latest/next/beta) are permitted`,\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Security: lifecycle script key blocklist (C-2A / FIX 2A)\n // -------------------------------------------------------------------------\n const BLOCKED_LIFECYCLE_KEYS = new Set([\n 'preinstall',\n 'install',\n 'postinstall',\n 'prepare',\n 'prepublish',\n 'prepublishOnly',\n 'prepack',\n 'postpack',\n 'dependencies', // pnpm hook key\n ]);\n if (opts.scripts) {\n for (const key of Object.keys(opts.scripts)) {\n if (BLOCKED_LIFECYCLE_KEYS.has(key)) {\n return {\n ...emptyResult,\n success: false,\n error: `Blocked lifecycle script key: '${key}' — writing npm lifecycle hooks is not permitted`,\n };\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Read & parse\n // -------------------------------------------------------------------------\n const raw = readFileSync(realPackageJsonPath, 'utf8');\n\n // W2: Validate package.json structure with Zod before touching anything\n const PackageJsonSchema = z\n .object({\n // Zod v4: z.record(keySchema, valueSchema) — two-arg form required\n dependencies: z.record(z.string(), z.string()).optional(),\n devDependencies: z.record(z.string(), z.string()).optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n })\n .passthrough();\n\n const schemaResult = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!schemaResult.success) {\n return {\n ...emptyResult,\n success: false,\n error: `Invalid package.json structure: ${schemaResult.error.message}`,\n };\n }\n // FIX 4 (B-new-2): The schema has already validated the shape — the cast is earned.\n // passthrough() + noUncheckedIndexedAccess would otherwise broaden field types to unknown.\n const parsed = schemaResult.data as PackageJson;\n\n // -------------------------------------------------------------------------\n // Merge dependencies — NEVER overwrite existing version pins\n // -------------------------------------------------------------------------\n const added: string[] = [];\n const skipped: string[] = [];\n const scriptsAdded: string[] = [];\n\n // Live Set grows as packages are written — prevents same pkg landing in both buckets (B4).\n // Uses `in` semantics (not falsy) so empty-string versions are treated as existing (B3).\n const claimedPkgs = new Set<string>([\n ...Object.keys(parsed.dependencies ?? {}),\n ...Object.keys(parsed.devDependencies ?? {}),\n ]);\n\n // Regular dependencies\n parsed.dependencies = parsed.dependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.packages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.dependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n\n // Dev dependencies\n if (opts.devPackages && Object.keys(opts.devPackages).length > 0) {\n parsed.devDependencies = parsed.devDependencies ?? {};\n for (const [pkg, version] of Object.entries(opts.devPackages)) {\n if (claimedPkgs.has(pkg)) {\n skipped.push(pkg);\n } else {\n parsed.devDependencies[pkg] = version;\n claimedPkgs.add(pkg);\n added.push(pkg);\n }\n }\n }\n\n // Scripts — same never-overwrite semantics\n if (opts.scripts && Object.keys(opts.scripts).length > 0) {\n parsed.scripts = parsed.scripts ?? {};\n for (const [key, value] of Object.entries(opts.scripts)) {\n if (parsed.scripts[key] === undefined) {\n parsed.scripts[key] = value;\n scriptsAdded.push(key);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Write back — use realPackageJsonPath (symlink-resolved) for all I/O\n // -------------------------------------------------------------------------\n writeFileSync(realPackageJsonPath, JSON.stringify(parsed, null, 2) + '\\n');\n\n // -------------------------------------------------------------------------\n // Run pnpm install (optional, non-fatal on failure)\n // -------------------------------------------------------------------------\n let installed = false;\n let installError: string | undefined;\n\n if (opts.runInstall) {\n try {\n execSync('pnpm install', { cwd: realTarget, stdio: 'pipe', timeout: 60_000 });\n installed = true;\n } catch (err) {\n // Don't blow up the whole tool — install failure is recoverable.\n // The caller can re-run or handle manually.\n installed = false;\n const spawnErr = err as { stderr?: Buffer; message?: string };\n installError =\n spawnErr.stderr?.toString().trim() ||\n (err instanceof Error ? err.message : 'unknown error');\n }\n }\n\n return {\n success: true,\n added,\n skipped,\n scriptsAdded,\n installed,\n packageJsonPath: realPackageJsonPath,\n ...(installError !== undefined ? { installError } : {}),\n };\n } catch (err) {\n return {\n ...emptyResult,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","{\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.10.0\",\n \"@stackwright-pro/cli-data-explorer\": \"workspace:*\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.1.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.3\",\n \"vitest\": \"^4.0.18\"\n },\n \"scripts\": {\n \"build\": \"tsup src/server.ts --format cjs,esm --dts --clean\",\n \"dev\": \"tsup src/server.ts --format cjs,esm --dts --watch\",\n \"start\": \"node dist/server.js\",\n \"test\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"name\": \"@stackwright-pro/mcp\",\n \"version\": \"0.2.0-alpha.0\",\n \"description\": \"MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation\",\n \"license\": \"PROPRIETARY\",\n \"main\": \"./dist/server.js\",\n \"module\": \"./dist/server.mjs\",\n \"types\": \"./dist/server.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/server.d.ts\",\n \"import\": \"./dist/server.mjs\",\n \"require\": \"./dist/server.js\"\n }\n },\n \"files\": [\n \"dist\"\n ]\n}\n"],"mappings":"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","names":["server","path","z","server","z","server","z","listEntities","server","z","path","server","z","existsSync","path","server"]}
package/package.json CHANGED
@@ -2,8 +2,7 @@
2
2
  "dependencies": {
3
3
  "@modelcontextprotocol/sdk": "^1.10.0",
4
4
  "zod": "^4.3.6",
5
- "@stackwright-pro/cli-data-explorer": "1.0.1",
6
- "@stackwright-pro/openapi": "0.2.1"
5
+ "@stackwright-pro/cli-data-explorer": "1.0.2-alpha.0"
7
6
  },
8
7
  "devDependencies": {
9
8
  "@types/node": "^24.1.0",
@@ -12,7 +11,7 @@
12
11
  "vitest": "^4.0.18"
13
12
  },
14
13
  "name": "@stackwright-pro/mcp",
15
- "version": "0.2.0-alpha.0",
14
+ "version": "0.2.0-alpha.1",
16
15
  "description": "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
17
16
  "license": "PROPRIETARY",
18
17
  "main": "./dist/server.js",
@@ -28,6 +27,9 @@
28
27
  "files": [
29
28
  "dist"
30
29
  ],
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
31
33
  "scripts": {
32
34
  "build": "tsup src/server.ts --format cjs,esm --dts --clean",
33
35
  "dev": "tsup src/server.ts --format cjs,esm --dts --watch",