@stackwright-pro/mcp 0.2.0-alpha.3 → 0.2.0-alpha.4

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.
@@ -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","../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.3\",\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 \"publishConfig\": {\n \"access\": \"public\"\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"]}
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","../src/tools/questions.ts","../src/question-adapter.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 { registerQuestionTools } from './tools/questions.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\nregisterQuestionTools(server); // stackwright_pro_present_phase_questions\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 * Question Presentation MCP Tool\n *\n * Wraps ask_user_question with safe question adaptation so the foreman otter\n * never has to construct the nested questions array itself — which causes\n * consistent serialization failures where the LLM passes the array as a\n * JSON string instead of a native array.\n *\n * The tool accepts manifest-format questions (what specialist otters produce),\n * adapts them via the shared question-adapter, and calls ask_user_question\n * with a guaranteed-correct native array.\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { adaptQuestions, type QuestionManifestQuestion } from '../question-adapter.js';\n\nconst ManifestQuestionSchema = z.object({\n id: z.string(),\n question: z.string(),\n type: z.enum(['text', 'select', 'multi-select', 'confirm']),\n required: z.boolean().optional(),\n options: z\n .array(\n z.object({\n label: z.string(),\n value: z.string(),\n })\n )\n .optional(),\n default: z.union([z.string(), z.boolean(), z.array(z.string())]).optional(),\n help: z.string().optional(),\n dependsOn: z\n .object({\n questionId: z.string(),\n value: z.union([z.string(), z.array(z.string())]),\n })\n .optional(),\n});\n\nexport function registerQuestionTools(server: McpServer): void {\n server.tool(\n 'stackwright_pro_present_phase_questions',\n 'Adapt manifest-format questions from a specialist otter and present them to the user via ask_user_question. ' +\n 'Use this instead of calling ask_user_question directly — it handles label truncation, header generation, ' +\n 'confirm/text defaults, and correct array formatting automatically.',\n {\n phase: z.string().describe('Phase name for display context, e.g. \"designer\", \"api\", \"auth\"'),\n questions: z\n .array(ManifestQuestionSchema)\n .describe('Questions in Question Manifest format as produced by specialist otters'),\n answers: z\n .record(z.union([z.string(), z.array(z.string()), z.boolean()]))\n .optional()\n .describe('Previously collected answers used to resolve dependsOn conditions'),\n },\n async ({ phase, questions, answers }) => {\n // Adapt from manifest format to ask_user_question format\n const adapted = adaptQuestions(questions as QuestionManifestQuestion[], answers ?? {});\n\n if (adapted.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n phase,\n skipped: true,\n reason: 'No questions to present (all filtered by dependsOn conditions)',\n answers: [],\n }),\n },\n ],\n };\n }\n\n // Return the adapted questions for the foreman to pass to ask_user_question.\n // We return them as a structured object rather than calling ask_user_question\n // ourselves — ask_user_question is a code-puppy native tool (not an MCP peer),\n // so the foreman must call it. But now the foreman receives a pre-validated,\n // pre-truncated native array and passes it verbatim, eliminating the\n // serialization bug.\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n phase,\n adapted_questions: adapted,\n instruction:\n 'Call ask_user_question with the adapted_questions array below. ' +\n 'Pass the array value directly as the questions parameter — do not stringify it.',\n }),\n },\n ],\n };\n }\n );\n}\n","/**\n * Question Adapter - Converts between Question Manifest format and ask_user_question format\n *\n * The ask_user_question MCP tool requires:\n * - question: string (full text)\n * - header: string (max 12 chars, short label)\n * - multi_select: boolean\n * - options: {label, description}[] (REQUIRED, min 2)\n *\n * Our Question Manifest format has:\n * - id: string (e.g., \"api-1\")\n * - question: string\n * - type: 'text' | 'select' | 'multi-select' | 'confirm'\n * - options?: {label, value}[] (optional for text/confirm)\n * - required?: boolean\n * - default?: string | boolean | string[]\n * - dependsOn?: {questionId, value}\n */\n\nexport interface QuestionManifestQuestion {\n id: string;\n question: string;\n type: 'text' | 'select' | 'multi-select' | 'confirm';\n required?: boolean;\n options?: { label: string; value: string }[];\n default?: string | boolean | string[];\n help?: string;\n dependsOn?: {\n questionId: string;\n value: string | string[];\n };\n}\n\nexport interface AskUserQuestionOption {\n label: string;\n description?: string;\n}\n\nexport interface AskUserQuestion {\n question: string;\n header: string;\n multi_select: boolean;\n options: AskUserQuestionOption[];\n}\n\n/**\n * Truncate string to max length, adding ellipsis if needed\n */\nfunction truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.substring(0, maxLength - 1) + '…';\n}\n\n/**\n * Generate a valid header from a question ID\n * Headers must be max 12 chars, alphanumeric with hyphens\n */\nfunction generateHeader(id: string): string {\n // Remove numbers and prefix, keep meaningful part\n // e.g., \"api-1\" -> \"API-1\", \"auth-3\" -> \"AUTH-3\"\n const parts = id.split('-');\n if (parts.length >= 2) {\n const prefix = parts[0].toUpperCase().substring(0, 4);\n const num = parts[1];\n return truncate(`${prefix}-${num}`, 12);\n }\n return truncate(\n id\n .toUpperCase()\n .replace(/[^A-Z0-9]/g, '')\n .substring(0, 12),\n 12\n );\n}\n\n/**\n * Generate default options for question types that don't have options\n */\nfunction generateDefaultOptions(type: string): AskUserQuestionOption[] {\n switch (type) {\n case 'confirm':\n return [\n { label: 'Yes', description: 'Enable or confirm this option' },\n { label: 'No', description: 'Disable or decline this option' },\n ];\n case 'text':\n return [\n { label: 'Specify', description: 'I will provide a specific value' },\n { label: 'Skip', description: 'Use default or skip this question' },\n ];\n default:\n return [\n { label: 'Option 1', description: 'First option' },\n { label: 'Option 2', description: 'Second option' },\n ];\n }\n}\n\n/**\n * Convert a single QuestionManifest question to ask_user_question format\n */\nexport function adaptQuestion(q: QuestionManifestQuestion): AskUserQuestion {\n // Generate header from ID\n const header = generateHeader(q.id);\n\n // Determine multi_select\n const multiSelect = q.type === 'multi-select';\n\n // Handle options - use provided or generate defaults\n let options: AskUserQuestionOption[];\n\n if (q.options && q.options.length >= 2) {\n // Use provided options, adapt format\n options = q.options.map((opt) => ({\n label: truncate(opt.label, 50),\n description: opt.value !== opt.label ? opt.value : undefined,\n }));\n } else if (q.options && q.options.length === 1) {\n // Single option - add a default\n options = [\n ...q.options.map((opt) => ({ label: truncate(opt.label, 50), description: opt.value })),\n { label: 'Other', description: 'Specify a different value' },\n ];\n } else {\n // No options - generate defaults based on type\n options = generateDefaultOptions(q.type);\n }\n\n // Ensure minimum 2 options (MCP tool requirement)\n if (options.length < 2) {\n options.push({ label: 'Other', description: 'Alternative option' });\n }\n\n // Limit to 6 options (MCP tool max)\n options = options.slice(0, 6);\n\n return {\n question: q.question + (q.help ? `\\n\\n${q.help}` : ''),\n header,\n multi_select: multiSelect,\n options,\n };\n}\n\n/**\n * Adapt multiple questions, filtering by dependsOn\n *\n * @param questions - All questions from manifest\n * @param answers - Previously answered questions (for filtering conditionals)\n * @returns Questions adapted for ask_user_question, with conditionals resolved\n */\nexport function adaptQuestions(\n questions: QuestionManifestQuestion[],\n answers: Record<string, string | string[] | boolean> = {}\n): AskUserQuestion[] {\n const adapted: AskUserQuestion[] = [];\n\n for (const q of questions) {\n // Check dependsOn condition\n if (q.dependsOn) {\n const dependsAnswer = answers[q.dependsOn.questionId];\n if (dependsAnswer === undefined) {\n // Parent question not answered yet - skip this conditional question\n continue;\n }\n\n // Check if the answer matches the condition\n const expectedValues = Array.isArray(q.dependsOn.value)\n ? q.dependsOn.value\n : [q.dependsOn.value];\n\n const answerValue = Array.isArray(dependsAnswer) ? dependsAnswer[0] : dependsAnswer;\n\n if (!expectedValues.includes(answerValue as string)) {\n // Condition not met - skip this question\n continue;\n }\n }\n\n adapted.push(adaptQuestion(q));\n }\n\n return adapted;\n}\n\n/**\n * Parse JSON response from LLM (handles various formats)\n */\nexport function parseLLMQuestionsResponse(text: string): QuestionManifestQuestion[] {\n // Try to extract JSON from the response\n let jsonStr = text;\n\n // Remove markdown code blocks\n jsonStr = jsonStr.replace(/```(?:json|javascript)?\\s*/gi, '');\n jsonStr = jsonStr.replace(/```\\s*$/gm, '');\n\n // Find JSON object or array\n const firstBrace = jsonStr.indexOf('{');\n const firstBracket = jsonStr.indexOf('[');\n\n let start = -1;\n if (firstBrace !== -1 && firstBracket !== -1) {\n start = Math.min(firstBrace, firstBracket);\n } else if (firstBrace !== -1) {\n start = firstBrace;\n } else if (firstBracket !== -1) {\n start = firstBracket;\n }\n\n if (start === -1) {\n throw new Error('No JSON found in response');\n }\n\n jsonStr = jsonStr.substring(start);\n\n // Handle trailing text after JSON\n const lastBrace = jsonStr.lastIndexOf('}');\n const lastBracket = jsonStr.lastIndexOf(']');\n const end = Math.max(lastBrace, lastBracket);\n\n if (end === -1) {\n throw new Error('Invalid JSON structure');\n }\n\n jsonStr = jsonStr.substring(0, end + 1);\n\n // Fix common issues\n jsonStr = jsonStr.replace(/,(\\s*[}\\]])/g, '$1'); // Remove trailing commas\n jsonStr = jsonStr.replace(/'/g, '\"'); // Single quotes to double\n\n const parsed = JSON.parse(jsonStr);\n\n // Handle various JSON structures\n let questions: unknown[];\n\n if (Array.isArray(parsed)) {\n questions = parsed;\n } else if (parsed.questions && Array.isArray(parsed.questions)) {\n questions = parsed.questions;\n } else if (parsed.data && Array.isArray((parsed.data as Record<string, unknown>).questions)) {\n questions = (parsed.data as Record<string, unknown>).questions as unknown[];\n } else {\n throw new Error('No questions array found in response');\n }\n\n return questions as QuestionManifestQuestion[];\n}\n\n/**\n * Convert ask_user_question answers back to manifest format\n */\nexport function answersToManifestFormat(\n answers: { question_header: string; selected_options: string[]; other_text?: string | null }[],\n questions: QuestionManifestQuestion[]\n): Record<string, string | string[] | boolean> {\n const result: Record<string, string | string[] | boolean> = {};\n\n for (const answer of answers) {\n // Find matching question by header\n const headerLower = answer.question_header.toLowerCase();\n const question = questions.find((q) => {\n const qHeader = generateHeader(q.id).toLowerCase();\n return qHeader === headerLower || q.id.toLowerCase().includes(headerLower);\n });\n\n if (!question) {\n // Try to match by header prefix\n const matched = questions.find((q) => {\n const qHeader = generateHeader(q.id).toLowerCase();\n return qHeader.startsWith(headerLower.split('-')[0]);\n });\n if (matched) {\n result[matched.id] = answer.selected_options[0] || '';\n }\n continue;\n }\n\n // Handle multi-select vs single select\n if (question.type === 'multi-select' || answer.selected_options.length > 1) {\n result[question.id] = answer.selected_options;\n } else if (question.type === 'confirm') {\n result[question.id] = answer.selected_options[0] === 'Yes';\n } else {\n // For text or single select, use first option or other_text\n if (answer.other_text) {\n result[question.id] = answer.other_text;\n } else if (answer.selected_options.length > 0) {\n // Map label back to value if possible\n const option = question.options?.find((o) => o.label === answer.selected_options[0]);\n result[question.id] = option?.value ?? answer.selected_options[0];\n }\n }\n }\n\n return result;\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.4\",\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 \"publishConfig\": {\n \"access\": \"public\"\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","import_zod","server"]}