@runtimescope/mcp-server 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/tools/network.ts","../src/tools/console.ts","../src/tools/session.ts","../src/tools/issues.ts","../src/tools/timeline.ts","../src/tools/state.ts","../src/tools/renders.ts","../src/tools/performance.ts","../src/tools/dom-snapshot.ts","../src/tools/har.ts","../src/tools/errors.ts","../src/tools/api-discovery.ts","../src/tools/database.ts","../src/tools/process-monitor.ts","../src/tools/infra-connector.ts","../src/tools/session-diff.ts","../src/tools/recon-metadata.ts","../src/tools/recon-design-tokens.ts","../src/tools/recon-fonts.ts","../src/tools/recon-layout.ts","../src/tools/recon-accessibility.ts","../src/tools/recon-computed-styles.ts","../src/tools/recon-element-snapshot.ts","../src/tools/recon-assets.ts","../src/tools/recon-style-diff.ts","../src/scanner/index.ts","../src/scanner/signal-collector.ts","../src/scanner/recon-collectors.ts","../src/scanner/event-builder.ts","../src/tools/scanner.ts","../src/tools/history.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CollectorServer,\n ProjectManager,\n ApiDiscoveryEngine,\n ProcessMonitor,\n InfraConnector,\n ConnectionManager,\n SchemaIntrospector,\n DataBrowser,\n SessionManager,\n HttpServer,\n SqliteStore,\n AuthManager,\n Redactor,\n resolveTlsConfig,\n} from '@runtimescope/collector';\n\n// --- Existing M1/M2 tool registrations ---\nimport { registerNetworkTools } from './tools/network.js';\nimport { registerConsoleTools } from './tools/console.js';\nimport { registerSessionTools } from './tools/session.js';\nimport { registerIssueTools } from './tools/issues.js';\nimport { registerTimelineTools } from './tools/timeline.js';\nimport { registerStateTools } from './tools/state.js';\nimport { registerRenderTools } from './tools/renders.js';\nimport { registerPerformanceTools } from './tools/performance.js';\nimport { registerDomSnapshotTools } from './tools/dom-snapshot.js';\nimport { registerHarTools } from './tools/har.js';\nimport { registerErrorTools } from './tools/errors.js';\n\n// --- New M3 tool registrations ---\nimport { registerApiDiscoveryTools } from './tools/api-discovery.js';\nimport { registerDatabaseTools } from './tools/database.js';\nimport { registerProcessMonitorTools } from './tools/process-monitor.js';\nimport { registerInfraTools } from './tools/infra-connector.js';\nimport { registerSessionDiffTools } from './tools/session-diff.js';\n\n// --- Recon tools (extension-powered UI analysis) ---\nimport { registerReconMetadataTools } from './tools/recon-metadata.js';\nimport { registerReconDesignTokenTools } from './tools/recon-design-tokens.js';\nimport { registerReconFontTools } from './tools/recon-fonts.js';\nimport { registerReconLayoutTools } from './tools/recon-layout.js';\nimport { registerReconAccessibilityTools } from './tools/recon-accessibility.js';\nimport { registerReconComputedStyleTools } from './tools/recon-computed-styles.js';\nimport { registerReconElementSnapshotTools } from './tools/recon-element-snapshot.js';\nimport { registerReconAssetTools } from './tools/recon-assets.js';\nimport { registerReconStyleDiffTools } from './tools/recon-style-diff.js';\n\n// --- Playwright scanner ---\nimport { PlaywrightScanner } from './scanner/index.js';\nimport { registerScannerTools } from './tools/scanner.js';\n\n// --- Historical event persistence ---\nimport { registerHistoryTools } from './tools/history.js';\n\nconst COLLECTOR_PORT = parseInt(process.env.RUNTIMESCOPE_PORT ?? '9090', 10);\nconst HTTP_PORT = parseInt(process.env.RUNTIMESCOPE_HTTP_PORT ?? '9091', 10);\nconst BUFFER_SIZE = parseInt(process.env.RUNTIMESCOPE_BUFFER_SIZE ?? '10000', 10);\n\n/**\n * Attempt to kill any stale process holding the collector port.\n * This handles the case where a previous MCP server process didn't\n * clean up (e.g. Claude Code session crashed).\n */\nfunction killStaleProcess(port: number): void {\n try {\n const pids = execSync(`lsof -ti :${port} 2>/dev/null`, { encoding: 'utf-8' }).trim();\n if (pids) {\n const myPid = process.pid.toString();\n for (const pid of pids.split('\\n')) {\n if (pid && pid !== myPid) {\n console.error(`[RuntimeScope] Killing stale process ${pid} on port ${port}`);\n try {\n process.kill(parseInt(pid, 10), 'SIGTERM');\n } catch {\n // Process may have already exited\n }\n }\n }\n }\n } catch {\n // lsof not available or no process found — that's fine\n }\n}\n\nasync function main() {\n // 1. Initialize project management\n const projectManager = new ProjectManager();\n projectManager.ensureGlobalDir();\n\n // 1b. Load security config from ~/.runtimescope/config.json\n const globalConfig = projectManager.getGlobalConfig();\n\n const authManager = new AuthManager({\n enabled: globalConfig.auth?.enabled ?? false,\n apiKeys: globalConfig.auth?.apiKeys ?? [],\n });\n\n const tlsConfig = resolveTlsConfig() ?? globalConfig.tls ?? undefined;\n\n const redactor = new Redactor({\n enabled: globalConfig.redaction?.enabled ?? false,\n useBuiltIn: true,\n rules: globalConfig.redaction?.rules?.map(r => ({\n name: r.name,\n pattern: new RegExp(r.pattern, 'gi'),\n replacement: r.replacement,\n })),\n });\n\n const corsOrigins = process.env.RUNTIMESCOPE_CORS_ORIGINS?.split(',').map(s => s.trim())\n ?? globalConfig.corsOrigins;\n\n if (authManager.isEnabled()) {\n console.error(`[RuntimeScope] Auth enabled (${globalConfig.auth?.apiKeys?.length ?? 0} API keys)`);\n }\n if (tlsConfig) {\n console.error(`[RuntimeScope] TLS enabled (cert: ${tlsConfig.certPath})`);\n }\n if (redactor.isEnabled()) {\n console.error('[RuntimeScope] Payload redaction enabled');\n }\n\n // 2. Clear any stale collector from a previous session\n killStaleProcess(COLLECTOR_PORT);\n killStaleProcess(HTTP_PORT);\n\n // 3. Start the collector WebSocket server with project scoping\n const collector = new CollectorServer({\n bufferSize: BUFFER_SIZE,\n projectManager,\n authManager,\n rateLimits: globalConfig.rateLimits,\n tls: tlsConfig,\n });\n await collector.start({ port: COLLECTOR_PORT, maxRetries: 5, retryDelayMs: 1000 });\n\n const store = collector.getStore();\n\n // Wire in redactor for defense-in-depth event sanitization\n if (redactor.isEnabled()) {\n store.setRedactor(redactor);\n }\n\n // 4. Initialize engines\n const apiDiscovery = new ApiDiscoveryEngine(store);\n const connectionManager = new ConnectionManager();\n const schemaIntrospector = new SchemaIntrospector();\n const dataBrowser = new DataBrowser();\n const processMonitor = new ProcessMonitor(store);\n processMonitor.start();\n\n const infraConnector = new InfraConnector(store);\n\n // Session manager shares the collector's SQLite stores (by reference)\n const sqliteStores = collector.getSqliteStores();\n const sessionManager = new SessionManager(projectManager, sqliteStores, store);\n\n // Auto-snapshot session metrics on SDK disconnect\n collector.onDisconnect((sessionId, projectName) => {\n try {\n sessionManager.createSnapshot(sessionId, projectName);\n console.error(`[RuntimeScope] Session ${sessionId} metrics saved to SQLite`);\n } catch {\n // Non-fatal: snapshot failure shouldn't break anything\n }\n });\n\n // Retention policy: prune events older than N days on startup\n const RETENTION_DAYS = parseInt(process.env.RUNTIMESCOPE_RETENTION_DAYS ?? '30', 10);\n const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1000;\n for (const projectName of projectManager.listProjects()) {\n const dbPath = projectManager.getProjectDbPath(projectName);\n if (existsSync(dbPath)) {\n try {\n const tempStore = new SqliteStore({ dbPath });\n const deleted = tempStore.deleteOldEvents(cutoffMs);\n if (deleted > 0) {\n console.error(`[RuntimeScope] Pruned ${deleted} events older than ${RETENTION_DAYS}d from \"${projectName}\"`);\n }\n tempStore.close();\n } catch {\n // Non-fatal: retention cleanup failure shouldn't prevent startup\n }\n }\n }\n\n // 5. Start HTTP API for dashboard\n const httpServer = new HttpServer(store, processMonitor, {\n authManager,\n allowedOrigins: corsOrigins,\n });\n try {\n await httpServer.start({ port: HTTP_PORT, tls: tlsConfig });\n } catch (err) {\n console.error('[RuntimeScope] HTTP API failed to start:', (err as Error).message);\n // Non-fatal: MCP tools still work without HTTP API\n }\n\n // 6. Create Playwright scanner (lazy — browser launches on first scan)\n const scanner = new PlaywrightScanner();\n\n // 7. Create MCP server\n const mcp = new McpServer({\n name: 'runtimescope',\n version: '0.6.0',\n });\n\n // 8. Register all 46 tools\n\n // --- Core Runtime (12 existing) ---\n registerNetworkTools(mcp, store);\n registerConsoleTools(mcp, store);\n registerSessionTools(mcp, store);\n registerIssueTools(mcp, store, apiDiscovery, processMonitor);\n registerTimelineTools(mcp, store);\n registerStateTools(mcp, store);\n registerRenderTools(mcp, store);\n registerPerformanceTools(mcp, store);\n registerDomSnapshotTools(mcp, store, collector);\n registerHarTools(mcp, store);\n registerErrorTools(mcp, store);\n\n // --- API Discovery (5 new) ---\n registerApiDiscoveryTools(mcp, store, apiDiscovery);\n\n // --- Database (7 new) ---\n registerDatabaseTools(mcp, store, connectionManager, schemaIntrospector, dataBrowser);\n\n // --- Process Monitor (3 new) ---\n registerProcessMonitorTools(mcp, processMonitor);\n\n // --- Infrastructure (4 new) ---\n registerInfraTools(mcp, infraConnector);\n\n // --- Session Diffing (2 new) ---\n registerSessionDiffTools(mcp, sessionManager);\n\n // --- Recon / UI Analysis (9 new — extension-powered) ---\n registerReconMetadataTools(mcp, store, collector);\n registerReconDesignTokenTools(mcp, store, collector);\n registerReconFontTools(mcp, store);\n registerReconLayoutTools(mcp, store, collector);\n registerReconAccessibilityTools(mcp, store);\n registerReconComputedStyleTools(mcp, store, collector, scanner);\n registerReconElementSnapshotTools(mcp, store, collector, scanner);\n registerReconAssetTools(mcp, store);\n registerReconStyleDiffTools(mcp, store);\n\n // --- Playwright Scanner + SDK Snippet (2 new) ---\n registerScannerTools(mcp, store, scanner);\n\n // --- Historical Persistence (2 new) ---\n registerHistoryTools(mcp, collector, projectManager);\n\n // 9. Connect MCP to stdio transport\n const transport = new StdioServerTransport();\n await mcp.connect(transport);\n\n console.error('[RuntimeScope] MCP server running on stdio (v0.6.0 — 46 tools)');\n console.error(`[RuntimeScope] SDK snippet at http://127.0.0.1:${HTTP_PORT}/snippet`);\n console.error(`[RuntimeScope] SDK should connect to ws://127.0.0.1:${COLLECTOR_PORT}`);\n console.error(`[RuntimeScope] HTTP API at http://127.0.0.1:${HTTP_PORT}`);\n\n // 10. Robust shutdown\n let shuttingDown = false;\n const shutdown = async () => {\n if (shuttingDown) return;\n shuttingDown = true;\n\n processMonitor.stop();\n await scanner.shutdown();\n await connectionManager.closeAll();\n await httpServer.stop();\n collector.stop();\n\n process.exit(0);\n };\n\n process.on('SIGINT', () => { shutdown(); });\n process.on('SIGTERM', () => { shutdown(); });\n process.on('beforeExit', () => { shutdown(); });\n\n // If stdin closes (Claude Code disconnected), shut down cleanly\n process.stdin.on('end', () => { shutdown(); });\n process.stdin.on('close', () => { shutdown(); });\n}\n\nmain().catch((err) => {\n console.error('[RuntimeScope] Fatal error:', err);\n process.exit(1);\n});\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nexport function registerNetworkTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_network_requests',\n 'Get captured network (fetch) requests from the running web app. Returns URL, method, status, timing, and optional GraphQL operation info.',\n {\n since_seconds: z.number().optional().describe('Only return requests from the last N seconds'),\n url_pattern: z.string().optional().describe('Filter by URL substring match'),\n status: z.number().optional().describe('Filter by HTTP status code'),\n method: z.string().optional().describe('Filter by HTTP method (GET, POST, etc.)'),\n },\n async ({ since_seconds, url_pattern, status, method }) => {\n const events = store.getNetworkRequests({\n sinceSeconds: since_seconds,\n urlPattern: url_pattern,\n status,\n method,\n });\n\n const timeRange =\n events.length > 0\n ? { from: events[events.length - 1].timestamp, to: events[0].timestamp }\n : { from: 0, to: 0 };\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const failedCount = events.filter((e) => e.status >= 400).length;\n const avgDuration =\n events.length > 0\n ? (events.reduce((s, e) => s + e.duration, 0) / events.length).toFixed(0)\n : '0';\n\n const issues: string[] = [];\n if (failedCount > 0) issues.push(`${failedCount} failed request(s) (4xx/5xx)`);\n const slowRequests = events.filter((e) => e.duration > 3000);\n if (slowRequests.length > 0) issues.push(`${slowRequests.length} slow request(s) (>3s)`);\n\n // Detect N+1 pattern: same endpoint called >5 times within 2 seconds\n const urlCounts = new Map<string, { count: number; first: number; last: number }>();\n for (const e of events) {\n const key = `${e.method} ${e.url}`;\n const existing = urlCounts.get(key);\n if (existing) {\n existing.count++;\n existing.last = Math.max(existing.last, e.timestamp);\n existing.first = Math.min(existing.first, e.timestamp);\n } else {\n urlCounts.set(key, { count: 1, first: e.timestamp, last: e.timestamp });\n }\n }\n for (const [key, info] of urlCounts) {\n if (info.count > 5 && info.last - info.first < 2000) {\n issues.push(`Possible N+1: ${key} called ${info.count} times in ${((info.last - info.first) / 1000).toFixed(1)}s`);\n }\n }\n\n const response = {\n summary: `Found ${events.length} network request(s)${since_seconds ? ` in the last ${since_seconds}s` : ''}. Average duration: ${avgDuration}ms.`,\n data: events.map((e) => ({\n url: e.url,\n method: e.method,\n status: e.status,\n duration: `${e.duration.toFixed(0)}ms`,\n ttfb: `${e.ttfb.toFixed(0)}ms`,\n requestBodySize: e.requestBodySize,\n responseBodySize: e.responseBodySize,\n graphqlOperation: e.graphqlOperation ?? null,\n timestamp: new Date(e.timestamp).toISOString(),\n })),\n issues,\n metadata: { timeRange, eventCount: events.length, sessionId },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nexport function registerConsoleTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_console_messages',\n 'Get captured console messages (log, warn, error, info, debug, trace) from the running web app. Includes message text, args, and stack traces for errors.',\n {\n level: z\n .enum(['log', 'warn', 'error', 'info', 'debug', 'trace'])\n .optional()\n .describe('Filter by console level'),\n since_seconds: z.number().optional().describe('Only return messages from the last N seconds'),\n search: z\n .string()\n .optional()\n .describe('Search message text (case-insensitive substring match)'),\n },\n async ({ level, since_seconds, search }) => {\n const events = store.getConsoleMessages({\n level,\n sinceSeconds: since_seconds,\n search,\n });\n\n const timeRange =\n events.length > 0\n ? { from: events[events.length - 1].timestamp, to: events[0].timestamp }\n : { from: 0, to: 0 };\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n // Group by level for summary\n const levelCounts: Record<string, number> = {};\n for (const e of events) {\n levelCounts[e.level] = (levelCounts[e.level] || 0) + 1;\n }\n const levelSummary = Object.entries(levelCounts)\n .map(([l, c]) => `${c} ${l}`)\n .join(', ');\n\n // Detect error spam: same error message repeated >5 times in 10 seconds\n const issues: string[] = [];\n const errorMessages = new Map<string, { count: number; first: number; last: number }>();\n for (const e of events) {\n if (e.level === 'error') {\n const existing = errorMessages.get(e.message);\n if (existing) {\n existing.count++;\n existing.last = Math.max(existing.last, e.timestamp);\n existing.first = Math.min(existing.first, e.timestamp);\n } else {\n errorMessages.set(e.message, { count: 1, first: e.timestamp, last: e.timestamp });\n }\n }\n }\n for (const [msg, info] of errorMessages) {\n if (info.count > 5 && info.last - info.first < 10_000) {\n const truncated = msg.length > 80 ? msg.slice(0, 80) + '...' : msg;\n issues.push(`Error spam: \"${truncated}\" repeated ${info.count} times in ${((info.last - info.first) / 1000).toFixed(1)}s`);\n }\n }\n\n const response = {\n summary: `Found ${events.length} console message(s)${since_seconds ? ` in the last ${since_seconds}s` : ''}${levelSummary ? `. Breakdown: ${levelSummary}` : ''}.`,\n data: events.map((e) => ({\n level: e.level,\n message: e.message,\n args: e.args,\n stackTrace: e.stackTrace ?? null,\n sourceFile: e.sourceFile ?? null,\n timestamp: new Date(e.timestamp).toISOString(),\n })),\n issues,\n metadata: { timeRange, eventCount: events.length, sessionId },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nexport function registerSessionTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_session_info',\n 'Get information about connected browser sessions and overall event statistics. Use this to check if the SDK is connected.',\n {},\n async () => {\n const sessions = store.getSessionInfo();\n\n const response = {\n summary:\n sessions.length > 0\n ? `${sessions.length} session(s) connected. Total events captured: ${store.eventCount}.`\n : 'No active sessions. Make sure the RuntimeScope SDK is injected in your app and connected to ws://localhost:9090.',\n data: sessions.map((s) => ({\n sessionId: s.sessionId,\n appName: s.appName,\n sdkVersion: s.sdkVersion,\n connectedAt: new Date(s.connectedAt).toISOString(),\n eventCount: s.eventCount,\n isConnected: s.isConnected,\n })),\n issues: sessions.length === 0 ? ['No SDK connections detected'] : [],\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: store.eventCount,\n sessionId: sessions[0]?.sessionId ?? null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n server.tool(\n 'clear_events',\n 'Clear all captured events from the buffer. Use this to start a fresh capture session.',\n {},\n async () => {\n const { clearedCount } = store.clear();\n\n const response = {\n summary: `Cleared ${clearedCount} events. Buffer is now empty.`,\n data: null,\n issues: [],\n metadata: {\n timeRange: { from: 0, to: 0 },\n eventCount: 0,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore, DetectedIssue } from '@runtimescope/collector';\nimport { detectIssues } from '@runtimescope/collector';\nimport type { ApiDiscoveryEngine } from '@runtimescope/collector';\nimport type { ProcessMonitor } from '@runtimescope/collector';\n\nexport function registerIssueTools(\n server: McpServer,\n store: EventStore,\n apiDiscovery?: ApiDiscoveryEngine,\n processMonitor?: ProcessMonitor\n): void {\n server.tool(\n 'detect_issues',\n 'Run all pattern detectors against captured runtime data and return prioritized issues. Detects: failed requests, slow requests (>3s), N+1 request patterns, console error spam, high error rates, slow DB queries (>500ms), N+1 DB queries, API degradation, high latency endpoints, orphaned processes, and more. Use this as the first tool when investigating performance problems.',\n {\n since_seconds: z\n .number()\n .optional()\n .describe('Analyze events from the last N seconds (default: all events)'),\n severity_filter: z\n .enum(['high', 'medium', 'low'])\n .optional()\n .describe('Only return issues at this severity or above'),\n },\n async ({ since_seconds, severity_filter }) => {\n const events = store.getAllEvents(since_seconds);\n const allIssues: DetectedIssue[] = [...detectIssues(events)];\n\n // Merge engine-contributed issues\n if (apiDiscovery) {\n try {\n allIssues.push(...apiDiscovery.detectIssues(events));\n } catch { /* engine may not have data yet */ }\n }\n if (processMonitor) {\n try {\n allIssues.push(...processMonitor.detectIssues());\n } catch { /* engine may not have scanned yet */ }\n }\n\n // Re-sort merged issues by severity\n const severityOrder = { high: 0, medium: 1, low: 2 };\n allIssues.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);\n\n const filterThreshold = severity_filter ? severityOrder[severity_filter] : 2;\n const issues = allIssues.filter(\n (i) => severityOrder[i.severity] <= filterThreshold\n );\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const highCount = issues.filter((i) => i.severity === 'high').length;\n const mediumCount = issues.filter((i) => i.severity === 'medium').length;\n const lowCount = issues.filter((i) => i.severity === 'low').length;\n\n const summaryParts: string[] = [];\n if (issues.length === 0) {\n summaryParts.push('No issues detected.');\n } else {\n summaryParts.push(`Found ${issues.length} issue(s):`);\n if (highCount > 0) summaryParts.push(`${highCount} HIGH`);\n if (mediumCount > 0) summaryParts.push(`${mediumCount} MEDIUM`);\n if (lowCount > 0) summaryParts.push(`${lowCount} LOW`);\n }\n summaryParts.push(`Analyzed ${events.length} events${since_seconds ? ` from last ${since_seconds}s` : ''}.`);\n\n const response = {\n summary: summaryParts.join(' '),\n data: issues.map((i) => ({\n severity: i.severity.toUpperCase(),\n pattern: i.pattern,\n title: i.title,\n description: i.description,\n evidence: i.evidence,\n suggestion: i.suggestion ?? null,\n })),\n issues: issues.map((i) => `[${i.severity.toUpperCase()}] ${i.title}`),\n metadata: {\n timeRange: {\n from: events.length > 0 ? events[0].timestamp : 0,\n to: events.length > 0 ? events[events.length - 1].timestamp : 0,\n },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type {\n RuntimeEvent,\n NetworkEvent,\n ConsoleEvent,\n StateEvent,\n RenderEvent,\n PerformanceEvent,\n DomSnapshotEvent,\n DatabaseEvent,\n} from '@runtimescope/collector';\n\nexport function registerTimelineTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_event_timeline',\n 'Get a chronological view of ALL events (network requests, console messages) interleaved by timestamp. Essential for understanding causal chains — e.g. seeing that an API call failed, then an error was logged, then another retry fired. Events are in chronological order (oldest first).',\n {\n since_seconds: z\n .number()\n .optional()\n .describe('Only return events from the last N seconds (default: 60)'),\n event_types: z\n .array(z.enum(['network', 'console', 'session', 'state', 'render', 'performance', 'dom_snapshot', 'database']))\n .optional()\n .describe('Filter by event types (default: all)'),\n limit: z\n .number()\n .optional()\n .describe('Max events to return (default: 200, max: 1000)'),\n },\n async ({ since_seconds, event_types, limit }) => {\n const sinceSeconds = since_seconds ?? 60;\n const maxEvents = Math.min(limit ?? 200, 1000);\n\n const events = store.getEventTimeline({\n sinceSeconds,\n eventTypes: event_types as any,\n });\n\n // Take the most recent N events if over limit\n const trimmed = events.length > maxEvents\n ? events.slice(events.length - maxEvents)\n : events;\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n // Build summary stats\n const typeCounts: Record<string, number> = {};\n for (const e of trimmed) {\n typeCounts[e.eventType] = (typeCounts[e.eventType] || 0) + 1;\n }\n const typeBreakdown = Object.entries(typeCounts)\n .map(([t, c]) => `${c} ${t}`)\n .join(', ');\n\n const response = {\n summary: `Timeline: ${trimmed.length} event(s) in the last ${sinceSeconds}s${events.length > maxEvents ? ` (showing last ${maxEvents} of ${events.length})` : ''}. Breakdown: ${typeBreakdown || 'none'}.`,\n data: trimmed.map((e) => formatTimelineEvent(e)),\n issues: [],\n metadata: {\n timeRange: {\n from: trimmed.length > 0 ? trimmed[0].timestamp : 0,\n to: trimmed.length > 0 ? trimmed[trimmed.length - 1].timestamp : 0,\n },\n eventCount: trimmed.length,\n totalInWindow: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n\nfunction formatTimelineEvent(event: RuntimeEvent): Record<string, unknown> {\n const base = {\n type: event.eventType,\n timestamp: new Date(event.timestamp).toISOString(),\n relativeMs: 0, // will be set by caller if needed\n };\n\n switch (event.eventType) {\n case 'network': {\n const ne = event as NetworkEvent;\n return {\n ...base,\n method: ne.method,\n url: ne.url,\n status: ne.status,\n duration: `${ne.duration.toFixed(0)}ms`,\n graphql: ne.graphqlOperation\n ? `${ne.graphqlOperation.type} ${ne.graphqlOperation.name}`\n : null,\n };\n }\n case 'console': {\n const ce = event as ConsoleEvent;\n return {\n ...base,\n level: ce.level,\n message: ce.message.length > 200 ? ce.message.slice(0, 200) + '...' : ce.message,\n hasStack: !!ce.stackTrace,\n };\n }\n case 'session':\n return {\n ...base,\n note: 'SDK session connected',\n };\n case 'state': {\n const se = event as StateEvent;\n return {\n ...base,\n storeId: se.storeId,\n library: se.library,\n phase: se.phase,\n action: se.action?.type ?? null,\n changedKeys: se.diff ? Object.keys(se.diff).join(', ') : null,\n };\n }\n case 'render': {\n const re = event as RenderEvent;\n return {\n ...base,\n totalRenders: re.totalRenders,\n componentCount: re.profiles.length,\n suspicious: re.suspiciousComponents.length > 0\n ? re.suspiciousComponents.join(', ')\n : null,\n };\n }\n case 'performance': {\n const pe = event as PerformanceEvent;\n return {\n ...base,\n metric: pe.metricName,\n value: pe.value,\n rating: pe.rating,\n element: pe.element ?? null,\n };\n }\n case 'dom_snapshot': {\n const ds = event as DomSnapshotEvent;\n return {\n ...base,\n url: ds.url,\n elementCount: ds.elementCount,\n htmlSize: `${Math.round(ds.html.length / 1024)}KB`,\n truncated: ds.truncated,\n };\n }\n case 'database': {\n const de = event as DatabaseEvent;\n return {\n ...base,\n operation: de.operation,\n query: de.query.length > 150 ? de.query.slice(0, 150) + '...' : de.query,\n duration: `${de.duration.toFixed(0)}ms`,\n tables: de.tablesAccessed,\n source: de.source,\n error: de.error ?? null,\n };\n }\n default:\n return base;\n }\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nexport function registerStateTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_state_snapshots',\n 'Get state store snapshots and diffs from Zustand or Redux stores. Shows state changes over time with action history, mutation frequency, and shallow diffs showing which keys changed.',\n {\n store_name: z\n .string()\n .optional()\n .describe('Filter by store name/ID'),\n since_seconds: z\n .number()\n .optional()\n .describe('Only return events from the last N seconds'),\n },\n async ({ store_name, since_seconds }) => {\n const events = store.getStateEvents({\n storeId: store_name,\n sinceSeconds: since_seconds,\n });\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n const issues: string[] = [];\n\n // Detect store thrashing (>10 updates/sec in any 1-second window)\n const storeUpdates = new Map<string, number[]>();\n for (const e of events) {\n if (e.phase !== 'update') continue;\n const timestamps = storeUpdates.get(e.storeId) ?? [];\n timestamps.push(e.timestamp);\n storeUpdates.set(e.storeId, timestamps);\n }\n\n for (const [storeId, timestamps] of storeUpdates) {\n if (timestamps.length < 10) continue;\n // Check 1-second sliding windows\n for (let i = 0; i <= timestamps.length - 10; i++) {\n if (timestamps[i + 9] - timestamps[i] < 1000) {\n issues.push(`Store thrashing: \"${storeId}\" had ${timestamps.length} updates, 10+ in a 1-second window`);\n break;\n }\n }\n }\n\n const response = {\n summary: `Found ${events.length} state event(s)${since_seconds ? ` in the last ${since_seconds}s` : ''}${store_name ? ` for store \"${store_name}\"` : ''}.`,\n data: events.map((e) => ({\n storeId: e.storeId,\n library: e.library,\n phase: e.phase,\n state: e.state,\n previousState: e.previousState ?? null,\n diff: e.diff ?? null,\n action: e.action ?? null,\n timestamp: new Date(e.timestamp).toISOString(),\n })),\n issues,\n metadata: {\n timeRange: {\n from: events.length > 0 ? events[0].timestamp : 0,\n to: events.length > 0 ? events[events.length - 1].timestamp : 0,\n },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type { RenderComponentProfile } from '@runtimescope/collector';\n\nexport function registerRenderTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_render_profile',\n 'Get React component render profiles showing render counts, velocity, average duration, and render causes. Flags suspicious components that are re-rendering excessively. Requires captureRenders: true in the SDK config and React dev mode for accurate timing data.',\n {\n component_name: z\n .string()\n .optional()\n .describe('Filter by component name (substring match)'),\n since_seconds: z\n .number()\n .optional()\n .describe('Only return events from the last N seconds'),\n },\n async ({ component_name, since_seconds }) => {\n const events = store.getRenderEvents({\n componentName: component_name,\n sinceSeconds: since_seconds,\n });\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n const issues: string[] = [];\n\n // Merge profiles across snapshots\n const merged = new Map<string, RenderComponentProfile>();\n const allSuspicious = new Set<string>();\n\n for (const event of events) {\n for (const profile of event.profiles) {\n const existing = merged.get(profile.componentName);\n if (existing) {\n existing.renderCount += profile.renderCount;\n existing.totalDuration += profile.totalDuration;\n existing.avgDuration =\n existing.renderCount > 0\n ? existing.totalDuration / existing.renderCount\n : 0;\n existing.renderVelocity = Math.max(existing.renderVelocity, profile.renderVelocity);\n existing.lastRenderPhase = profile.lastRenderPhase;\n existing.lastRenderCause = profile.lastRenderCause;\n if (profile.suspicious) existing.suspicious = true;\n } else {\n merged.set(profile.componentName, { ...profile });\n }\n\n if (profile.suspicious) {\n allSuspicious.add(profile.componentName);\n }\n }\n }\n\n if (allSuspicious.size > 0) {\n issues.push(`${allSuspicious.size} suspicious component(s): ${Array.from(allSuspicious).join(', ')}`);\n }\n\n // Sort by render count descending\n const profiles = Array.from(merged.values()).sort(\n (a, b) => b.renderCount - a.renderCount\n );\n\n const totalRenders = profiles.reduce((s, p) => s + p.renderCount, 0);\n\n const response = {\n summary: `${profiles.length} component(s) tracked, ${totalRenders} total renders${since_seconds ? ` in the last ${since_seconds}s` : ''}. ${allSuspicious.size} suspicious.`,\n data: profiles.map((p) => ({\n componentName: p.componentName,\n renderCount: p.renderCount,\n totalDuration: `${p.totalDuration.toFixed(1)}ms`,\n avgDuration: `${p.avgDuration.toFixed(1)}ms`,\n renderVelocity: `${p.renderVelocity.toFixed(1)}/sec`,\n lastRenderPhase: p.lastRenderPhase,\n lastRenderCause: p.lastRenderCause,\n suspicious: p.suspicious,\n })),\n issues,\n metadata: {\n timeRange: {\n from: events.length > 0 ? events[0].timestamp : 0,\n to: events.length > 0 ? events[events.length - 1].timestamp : 0,\n },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nconst WEB_VITAL_METRICS = ['LCP', 'FCP', 'CLS', 'TTFB', 'FID', 'INP'] as const;\nconst SERVER_METRICS = [\n 'memory.rss', 'memory.heapUsed', 'memory.heapTotal', 'memory.external',\n 'eventloop.lag.mean', 'eventloop.lag.p99', 'eventloop.lag.max',\n 'gc.pause.major', 'gc.pause.minor',\n 'cpu.user', 'cpu.system',\n 'handles.active', 'requests.active',\n] as const;\n\nconst ALL_METRICS = [...WEB_VITAL_METRICS, ...SERVER_METRICS] as const;\n\nfunction isWebVital(name: string): boolean {\n return (WEB_VITAL_METRICS as readonly string[]).includes(name);\n}\n\nexport function registerPerformanceTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_performance_metrics',\n 'Get performance metrics from browser (Web Vitals: LCP, FCP, CLS, TTFB, FID, INP) and/or server (memory, event loop lag, GC pauses, CPU usage). Browser metrics include quality ratings. Server metrics require capturePerformance: true in the server-SDK config.',\n {\n metric_name: z\n .enum(ALL_METRICS)\n .optional()\n .describe('Filter by specific metric name'),\n source: z\n .enum(['browser', 'server', 'all'])\n .optional()\n .default('all')\n .describe('Filter by metric source: browser (Web Vitals), server (Node.js runtime), or all'),\n since_seconds: z\n .number()\n .optional()\n .describe('Only return metrics from the last N seconds'),\n },\n async ({ metric_name, source, since_seconds }) => {\n let events = store.getPerformanceMetrics({\n metricName: metric_name,\n sinceSeconds: since_seconds,\n });\n\n // Filter by source\n if (source === 'browser') {\n events = events.filter((e) => isWebVital(e.metricName));\n } else if (source === 'server') {\n events = events.filter((e) => !isWebVital(e.metricName));\n }\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n const issues: string[] = [];\n\n // Flag poor Web Vitals\n const poor = events.filter((e) => e.rating === 'poor');\n const needsImprovement = events.filter((e) => e.rating === 'needs-improvement');\n if (poor.length > 0) {\n issues.push(`${poor.length} metric(s) rated \"poor\": ${poor.map((e) => e.metricName).join(', ')}`);\n }\n if (needsImprovement.length > 0) {\n issues.push(`${needsImprovement.length} metric(s) need improvement: ${needsImprovement.map((e) => e.metricName).join(', ')}`);\n }\n\n // Flag server-side concerns\n const highMemory = events.filter((e) => e.metricName === 'memory.heapUsed' && e.value > 500 * 1024 * 1024);\n if (highMemory.length > 0) {\n issues.push(`Heap usage exceeded 500MB in ${highMemory.length} sample(s)`);\n }\n const highEventLoop = events.filter((e) => e.metricName === 'eventloop.lag.p99' && e.value > 100);\n if (highEventLoop.length > 0) {\n issues.push(`Event loop p99 lag exceeded 100ms in ${highEventLoop.length} sample(s)`);\n }\n\n // Show latest value per metric\n const latest = new Map<string, typeof events[0]>();\n for (const e of events) {\n latest.set(e.metricName, e);\n }\n\n // Group by source for structured output\n const browserMetrics = Array.from(latest.values()).filter((e) => isWebVital(e.metricName));\n const serverMetrics = Array.from(latest.values()).filter((e) => !isWebVital(e.metricName));\n\n const formatMetric = (e: typeof events[0]) => ({\n metricName: e.metricName,\n value: e.value,\n unit: e.unit ?? (e.metricName === 'CLS' ? 'score' : 'ms'),\n rating: e.rating ?? null,\n element: e.element ?? null,\n timestamp: new Date(e.timestamp).toISOString(),\n });\n\n const response = {\n summary: `${latest.size} unique metric(s) captured (${browserMetrics.length} browser, ${serverMetrics.length} server). ${poor.length} poor, ${needsImprovement.length} needs improvement.`,\n data: {\n browser: browserMetrics.map(formatMetric),\n server: serverMetrics.map(formatMetric),\n },\n allEvents: events.map((e) => ({\n metricName: e.metricName,\n value: e.value,\n unit: e.unit ?? (e.metricName === 'CLS' ? 'score' : 'ms'),\n rating: e.rating ?? null,\n timestamp: new Date(e.timestamp).toISOString(),\n })),\n issues,\n metadata: {\n timeRange: {\n from: events.length > 0 ? events[0].timestamp : 0,\n to: events.length > 0 ? events[events.length - 1].timestamp : 0,\n },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type { CollectorServer } from '@runtimescope/collector';\n\nfunction generateRequestId(): string {\n return Math.random().toString(36).slice(2, 10) + Date.now().toString(36);\n}\n\nexport function registerDomSnapshotTools(\n server: McpServer,\n store: EventStore,\n collector: CollectorServer\n): void {\n server.tool(\n 'get_dom_snapshot',\n 'Capture a live DOM snapshot from the running web app. Sends a command to the SDK which serializes document.documentElement.outerHTML and returns it along with the current URL, viewport dimensions, scroll position, and element count. Useful for understanding what the user sees.',\n {\n max_size: z\n .number()\n .optional()\n .describe('Maximum HTML size in bytes (default: 500000). Larger pages will be truncated.'),\n },\n async ({ max_size }) => {\n const sessions = store.getSessionInfo();\n const sessionId = collector.getFirstSessionId();\n const activeSession = sessions[0] ?? null;\n\n if (!sessionId || !activeSession?.isConnected) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: 'No active SDK session connected. Ensure the SDK is running in the browser.',\n data: null,\n issues: ['No active session'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2),\n }],\n };\n }\n\n try {\n const requestId = generateRequestId();\n const result = await collector.sendCommand(sessionId, {\n command: 'capture_dom_snapshot',\n requestId,\n params: { maxSize: max_size ?? 500_000 },\n }, 10_000) as {\n html: string;\n url: string;\n viewport: { width: number; height: number };\n scrollPosition: { x: number; y: number };\n elementCount: number;\n truncated: boolean;\n };\n\n const response = {\n summary: `DOM snapshot captured from ${result.url}. ${result.elementCount} elements, ${Math.round(result.html.length / 1024)}KB HTML${result.truncated ? ' (truncated)' : ''}.`,\n data: {\n html: result.html,\n url: result.url,\n viewport: result.viewport,\n scrollPosition: result.scrollPosition,\n elementCount: result.elementCount,\n truncated: result.truncated,\n },\n issues: result.truncated ? ['HTML was truncated due to size limit'] : [],\n metadata: {\n timeRange: { from: Date.now(), to: Date.now() },\n eventCount: 1,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: `Failed to capture DOM snapshot: ${errorMsg}`,\n data: null,\n issues: [errorMsg],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type { NetworkEvent } from '@runtimescope/collector';\n\nexport function registerHarTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'capture_har',\n 'Export captured network requests as a HAR (HTTP Archive) 1.2 JSON file. This is the standard format used by browser DevTools, Charles Proxy, and other tools. Includes request/response headers, body content (if captureBody was enabled in the SDK), and timing data.',\n {\n since_seconds: z\n .number()\n .optional()\n .describe('Only include requests from the last N seconds'),\n },\n async ({ since_seconds }) => {\n const events = store.getNetworkRequests({\n sinceSeconds: since_seconds,\n });\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const har = buildHar(events);\n\n const response = {\n summary: `HAR export: ${events.length} request(s)${since_seconds ? ` from the last ${since_seconds}s` : ''}. Import into Chrome DevTools or any HAR viewer.`,\n data: har,\n issues: [],\n metadata: {\n timeRange: {\n from: events.length > 0 ? events[0].timestamp : 0,\n to: events.length > 0 ? events[events.length - 1].timestamp : 0,\n },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n\ninterface HarEntry {\n startedDateTime: string;\n time: number;\n request: {\n method: string;\n url: string;\n httpVersion: string;\n headers: { name: string; value: string }[];\n queryString: { name: string; value: string }[];\n postData?: { mimeType: string; text: string };\n headersSize: number;\n bodySize: number;\n };\n response: {\n status: number;\n statusText: string;\n httpVersion: string;\n headers: { name: string; value: string }[];\n content: {\n size: number;\n mimeType: string;\n text?: string;\n };\n headersSize: number;\n bodySize: number;\n };\n timings: {\n send: number;\n wait: number;\n receive: number;\n };\n}\n\nfunction buildHar(events: NetworkEvent[]): Record<string, unknown> {\n const entries: HarEntry[] = events.map((e) => {\n const queryString = parseQueryString(e.url);\n const requestHeaders = Object.entries(e.requestHeaders).map(([name, value]) => ({\n name,\n value,\n }));\n const responseHeaders = Object.entries(e.responseHeaders).map(([name, value]) => ({\n name,\n value,\n }));\n\n const contentType =\n e.responseHeaders['content-type'] ?? 'application/octet-stream';\n\n const entry: HarEntry = {\n startedDateTime: new Date(e.timestamp).toISOString(),\n time: Math.round(e.duration),\n request: {\n method: e.method,\n url: e.url,\n httpVersion: 'HTTP/1.1',\n headers: requestHeaders,\n queryString,\n headersSize: -1,\n bodySize: e.requestBodySize,\n },\n response: {\n status: e.status,\n statusText: statusText(e.status),\n httpVersion: 'HTTP/1.1',\n headers: responseHeaders,\n content: {\n size: e.responseBodySize,\n mimeType: contentType,\n ...(e.responseBody ? { text: e.responseBody } : {}),\n },\n headersSize: -1,\n bodySize: e.responseBodySize,\n },\n timings: {\n send: 0,\n wait: Math.round(e.ttfb),\n receive: Math.max(0, Math.round(e.duration - e.ttfb)),\n },\n };\n\n if (e.requestBody) {\n const reqContentType =\n e.requestHeaders['content-type'] ?? 'application/octet-stream';\n entry.request.postData = {\n mimeType: reqContentType,\n text: e.requestBody,\n };\n }\n\n return entry;\n });\n\n return {\n log: {\n version: '1.2',\n creator: {\n name: 'RuntimeScope',\n version: '0.2.0',\n },\n entries,\n },\n };\n}\n\nfunction parseQueryString(url: string): { name: string; value: string }[] {\n try {\n const parsed = new URL(url);\n return Array.from(parsed.searchParams.entries()).map(([name, value]) => ({\n name,\n value,\n }));\n } catch {\n return [];\n }\n}\n\nfunction statusText(status: number): string {\n const texts: Record<number, string> = {\n 200: 'OK',\n 201: 'Created',\n 204: 'No Content',\n 301: 'Moved Permanently',\n 302: 'Found',\n 304: 'Not Modified',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 409: 'Conflict',\n 422: 'Unprocessable Entity',\n 429: 'Too Many Requests',\n 500: 'Internal Server Error',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n };\n return texts[status] ?? '';\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\ninterface StackFrame {\n functionName: string;\n file: string;\n line: number;\n column: number;\n}\n\ninterface ErrorWithContext {\n message: string;\n timestamp: string;\n frames: (StackFrame & { sourceContext?: string[] })[];\n}\n\nexport function registerErrorTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_errors_with_source_context',\n 'Get console errors with parsed stack traces and surrounding source code lines. Fetches the actual source files from the dev server (e.g. http://localhost:3000/src/...) and shows the lines around the error. This gives you the same context as clicking a stack frame in DevTools.',\n {\n since_seconds: z\n .number()\n .optional()\n .describe('Only return errors from the last N seconds'),\n fetch_source: z\n .boolean()\n .optional()\n .describe('Whether to fetch source files for context (default: true). Set false for faster results.'),\n context_lines: z\n .number()\n .optional()\n .describe('Number of source lines to show above and below the error line (default: 5)'),\n },\n async ({ since_seconds, fetch_source, context_lines }) => {\n const shouldFetch = fetch_source !== false;\n const contextSize = context_lines ?? 5;\n\n const events = store.getConsoleMessages({\n level: 'error',\n sinceSeconds: since_seconds,\n });\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n // Limit to 50 errors\n const limited = events.slice(0, 50);\n const sourceCache = new Map<string, string | null>();\n\n const errors: ErrorWithContext[] = [];\n\n for (const event of limited) {\n const frames = event.stackTrace ? parseStackTrace(event.stackTrace) : [];\n\n if (shouldFetch) {\n for (const frame of frames) {\n // Skip node_modules and non-http files\n if (frame.file.includes('node_modules')) continue;\n if (!frame.file.startsWith('http')) continue;\n\n if (!sourceCache.has(frame.file)) {\n sourceCache.set(frame.file, await fetchSource(frame.file));\n }\n\n const source = sourceCache.get(frame.file);\n if (source) {\n (frame as StackFrame & { sourceContext?: string[] }).sourceContext =\n extractContext(source, frame.line, contextSize);\n }\n }\n }\n\n errors.push({\n message: event.message,\n timestamp: new Date(event.timestamp).toISOString(),\n frames: frames as (StackFrame & { sourceContext?: string[] })[],\n });\n }\n\n const issues: string[] = [];\n if (events.length > 50) {\n issues.push(`Showing 50 of ${events.length} errors`);\n }\n\n // Group by unique message\n const uniqueMessages = new Set(limited.map((e) => e.message.slice(0, 100)));\n\n const response = {\n summary: `${limited.length} error(s)${since_seconds ? ` in the last ${since_seconds}s` : ''}, ${uniqueMessages.size} unique. ${shouldFetch ? 'Source context included.' : 'Source context disabled.'}`,\n data: errors,\n issues,\n metadata: {\n timeRange: {\n from: limited.length > 0 ? limited[0].timestamp : 0,\n to: limited.length > 0 ? limited[limited.length - 1].timestamp : 0,\n },\n eventCount: limited.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n\n/**\n * Parse stack traces from Chrome/V8 and Firefox formats.\n * Chrome: \" at functionName (file:line:col)\"\n * Firefox: \"functionName@file:line:col\"\n */\nfunction parseStackTrace(stack: string): StackFrame[] {\n const frames: StackFrame[] = [];\n\n for (const line of stack.split('\\n')) {\n const trimmed = line.trim();\n\n // Chrome/V8 format: \"at functionName (file:line:col)\"\n const chromeMatch = trimmed.match(\n /^at\\s+(?:(.+?)\\s+\\()?(https?:\\/\\/[^)]+):(\\d+):(\\d+)\\)?$/\n );\n if (chromeMatch) {\n frames.push({\n functionName: chromeMatch[1] ?? '<anonymous>',\n file: chromeMatch[2],\n line: parseInt(chromeMatch[3], 10),\n column: parseInt(chromeMatch[4], 10),\n });\n continue;\n }\n\n // Firefox format: \"functionName@file:line:col\"\n const firefoxMatch = trimmed.match(\n /^(.+?)@(https?:\\/\\/.+):(\\d+):(\\d+)$/\n );\n if (firefoxMatch) {\n frames.push({\n functionName: firefoxMatch[1] ?? '<anonymous>',\n file: firefoxMatch[2],\n line: parseInt(firefoxMatch[3], 10),\n column: parseInt(firefoxMatch[4], 10),\n });\n }\n }\n\n return frames;\n}\n\n/** Fetch source file with timeout */\nasync function fetchSource(url: string): Promise<string | null> {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 2000);\n\n const response = await fetch(url, { signal: controller.signal });\n clearTimeout(timeout);\n\n if (!response.ok) return null;\n return await response.text();\n } catch {\n return null;\n }\n}\n\n/** Extract lines around a target line */\nfunction extractContext(\n source: string,\n targetLine: number,\n contextSize: number\n): string[] {\n const lines = source.split('\\n');\n const start = Math.max(0, targetLine - contextSize - 1);\n const end = Math.min(lines.length, targetLine + contextSize);\n\n return lines.slice(start, end).map((line, i) => {\n const lineNum = start + i + 1;\n const marker = lineNum === targetLine ? '>>>' : ' ';\n return `${marker} ${lineNum.toString().padStart(4)} | ${line}`;\n });\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore, ApiDiscoveryEngine } from '@runtimescope/collector';\n\nexport function registerApiDiscoveryTools(\n server: McpServer,\n store: EventStore,\n engine: ApiDiscoveryEngine\n): void {\n // --- get_api_catalog ---\n server.tool(\n 'get_api_catalog',\n 'Discover all API endpoints the app is communicating with, auto-grouped by service. Shows normalized paths, call counts, auth patterns, and inferred response shapes.',\n {\n service: z.string().optional().describe('Filter by service name (e.g. \"Supabase\", \"Your API\")'),\n min_calls: z.number().optional().describe('Only show endpoints with at least N calls'),\n },\n async ({ service, min_calls }) => {\n const catalog = engine.getCatalog({ service, minCalls: min_calls });\n const services = engine.getServiceMap();\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const response = {\n summary: `Discovered ${catalog.length} API endpoint(s) across ${services.length} service(s).`,\n data: {\n services: services.map((s) => ({\n name: s.name,\n baseUrl: s.baseUrl,\n endpointCount: s.endpointCount,\n totalCalls: s.totalCalls,\n avgLatency: `${s.avgLatency.toFixed(0)}ms`,\n errorRate: `${(s.errorRate * 100).toFixed(1)}%`,\n auth: s.auth.type,\n platform: s.detectedPlatform ?? null,\n })),\n endpoints: catalog.map((ep) => ({\n method: ep.method,\n path: ep.normalizedPath,\n service: ep.service,\n callCount: ep.callCount,\n auth: ep.auth.type,\n firstSeen: new Date(ep.firstSeen).toISOString(),\n lastSeen: new Date(ep.lastSeen).toISOString(),\n graphql: ep.graphqlOperation ?? null,\n responseFields: ep.contract?.responseFields.length ?? 0,\n })),\n },\n issues: [] as string[],\n metadata: {\n timeRange: catalog.length > 0\n ? { from: Math.min(...catalog.map((e) => e.firstSeen)), to: Math.max(...catalog.map((e) => e.lastSeen)) }\n : { from: 0, to: 0 },\n eventCount: catalog.reduce((s, e) => s + e.callCount, 0),\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_api_health ---\n server.tool(\n 'get_api_health',\n 'Get health metrics for discovered API endpoints: success rate, latency percentiles (p50/p95), error rates and error codes.',\n {\n endpoint: z.string().optional().describe('Filter by endpoint path substring'),\n since_seconds: z.number().optional().describe('Only consider requests from the last N seconds'),\n },\n async ({ endpoint, since_seconds }) => {\n const health = engine.getHealth({ endpoint, sinceSeconds: since_seconds });\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const issues: string[] = [];\n for (const ep of health) {\n if (ep.errorRate > 0.5) issues.push(`${ep.method} ${ep.normalizedPath}: ${(ep.errorRate * 100).toFixed(0)}% error rate`);\n if (ep.p95Latency > 5000) issues.push(`${ep.method} ${ep.normalizedPath}: p95 latency ${(ep.p95Latency / 1000).toFixed(1)}s`);\n }\n\n const response = {\n summary: `Health report for ${health.length} endpoint(s).${issues.length > 0 ? ` ${issues.length} issue(s) found.` : ''}`,\n data: health.map((ep) => ({\n method: ep.method,\n path: ep.normalizedPath,\n service: ep.service,\n callCount: ep.callCount,\n successRate: `${(ep.successRate * 100).toFixed(1)}%`,\n avgLatency: `${ep.avgLatency.toFixed(0)}ms`,\n p50Latency: `${ep.p50Latency.toFixed(0)}ms`,\n p95Latency: `${ep.p95Latency.toFixed(0)}ms`,\n errorRate: `${(ep.errorRate * 100).toFixed(1)}%`,\n errorCodes: ep.errorCodes,\n })),\n issues,\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: health.reduce((s, e) => s + e.callCount, 0),\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_api_documentation ---\n server.tool(\n 'get_api_documentation',\n 'Generate API documentation from observed network traffic. Shows endpoints, auth, latency, and inferred response shapes in markdown format.',\n {\n service: z.string().optional().describe('Generate docs for a specific service only'),\n },\n async ({ service }) => {\n const docs = engine.getDocumentation({ service });\n\n return {\n content: [{ type: 'text' as const, text: docs }],\n };\n }\n );\n\n // --- get_service_map ---\n server.tool(\n 'get_service_map',\n 'Get a topology map of all external services the app communicates with, including detected platforms (Supabase, Vercel, Stripe, etc.), call counts, and latency.',\n {},\n async () => {\n const services = engine.getServiceMap();\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const response = {\n summary: `${services.length} service(s) detected from network traffic.`,\n data: services.map((s) => ({\n name: s.name,\n baseUrl: s.baseUrl,\n endpointCount: s.endpointCount,\n totalCalls: s.totalCalls,\n avgLatency: `${s.avgLatency.toFixed(0)}ms`,\n errorRate: `${(s.errorRate * 100).toFixed(1)}%`,\n auth: s.auth,\n detectedPlatform: s.detectedPlatform ?? null,\n })),\n issues: [] as string[],\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: services.reduce((s, e) => s + e.totalCalls, 0),\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_api_changes ---\n server.tool(\n 'get_api_changes',\n 'Compare API endpoints between two sessions. Detects added/removed endpoints and response shape changes.',\n {\n session_a: z.string().describe('First session ID'),\n session_b: z.string().describe('Second session ID'),\n },\n async ({ session_a, session_b }) => {\n const changes = engine.getApiChanges(session_a, session_b);\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const added = changes.filter((c) => c.changeType === 'added').length;\n const removed = changes.filter((c) => c.changeType === 'removed').length;\n const modified = changes.filter((c) => c.changeType === 'modified').length;\n\n const response = {\n summary: `${changes.length} API change(s) between sessions: ${added} added, ${removed} removed, ${modified} modified.`,\n data: changes,\n issues: removed > 0 ? [`${removed} endpoint(s) no longer called — may indicate removed features or routing changes`] : [],\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: changes.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type {\n EventStore,\n ConnectionManager,\n SchemaIntrospector,\n DataBrowser,\n} from '@runtimescope/collector';\nimport {\n aggregateQueryStats,\n detectN1Queries,\n detectSlowQueries,\n suggestIndexes,\n} from '@runtimescope/collector';\n\nexport function registerDatabaseTools(\n server: McpServer,\n store: EventStore,\n connectionManager: ConnectionManager,\n schemaIntrospector: SchemaIntrospector,\n dataBrowser: DataBrowser\n): void {\n // --- get_query_log ---\n server.tool(\n 'get_query_log',\n 'Get captured database queries with SQL, timing, rows returned, and source ORM. Requires server-side SDK instrumentation.',\n {\n since_seconds: z.number().optional().describe('Only return queries from the last N seconds'),\n table: z.string().optional().describe('Filter by table name'),\n min_duration_ms: z.number().optional().describe('Only return queries slower than N ms'),\n search: z.string().optional().describe('Search query text'),\n },\n async ({ since_seconds, table, min_duration_ms, search }) => {\n const events = store.getDatabaseEvents({\n sinceSeconds: since_seconds,\n table,\n minDurationMs: min_duration_ms,\n search,\n });\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const totalDuration = events.reduce((s, e) => s + e.duration, 0);\n const avgDuration = events.length > 0 ? totalDuration / events.length : 0;\n const errorCount = events.filter((e) => e.error).length;\n\n const issues: string[] = [];\n if (errorCount > 0) issues.push(`${errorCount} query error(s)`);\n const slowCount = events.filter((e) => e.duration > 500).length;\n if (slowCount > 0) issues.push(`${slowCount} slow query/queries (>500ms)`);\n\n const response = {\n summary: `Found ${events.length} database query/queries${since_seconds ? ` in the last ${since_seconds}s` : ''}. Avg duration: ${avgDuration.toFixed(0)}ms.`,\n data: events.map((e) => ({\n query: e.query.slice(0, 200),\n normalizedQuery: e.normalizedQuery.slice(0, 150),\n duration: `${e.duration.toFixed(0)}ms`,\n operation: e.operation,\n tables: e.tablesAccessed,\n source: e.source,\n rowsReturned: e.rowsReturned ?? null,\n rowsAffected: e.rowsAffected ?? null,\n error: e.error ?? null,\n label: e.label ?? null,\n timestamp: new Date(e.timestamp).toISOString(),\n })),\n issues,\n metadata: {\n timeRange: events.length > 0\n ? { from: events[0].timestamp, to: events[events.length - 1].timestamp }\n : { from: 0, to: 0 },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_query_performance ---\n server.tool(\n 'get_query_performance',\n 'Get aggregated database query performance stats: avg/max/p95 duration, call counts, N+1 detection, and slow query analysis.',\n {\n since_seconds: z.number().optional().describe('Analyze queries from the last N seconds'),\n },\n async ({ since_seconds }) => {\n const events = store.getDatabaseEvents({ sinceSeconds: since_seconds });\n const stats = aggregateQueryStats(events);\n const n1Issues = detectN1Queries(events);\n const slowIssues = detectSlowQueries(events);\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const issues: string[] = [\n ...n1Issues.map((i) => i.title),\n ...slowIssues.map((i) => i.title),\n ];\n\n const response = {\n summary: `Analyzed ${events.length} queries across ${stats.length} unique patterns. ${issues.length} issue(s) found.`,\n data: {\n queryStats: stats.slice(0, 20).map((s) => ({\n pattern: s.normalizedQuery.slice(0, 150),\n tables: s.tables,\n operation: s.operation,\n callCount: s.callCount,\n avgDuration: `${s.avgDuration.toFixed(0)}ms`,\n maxDuration: `${s.maxDuration.toFixed(0)}ms`,\n p95Duration: `${s.p95Duration.toFixed(0)}ms`,\n totalDuration: `${s.totalDuration.toFixed(0)}ms`,\n avgRows: s.avgRowsReturned.toFixed(0),\n })),\n detectedIssues: [...n1Issues, ...slowIssues],\n },\n issues,\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_schema_map ---\n server.tool(\n 'get_schema_map',\n 'Get the full database schema: tables, columns, types, foreign keys, and indexes. Requires a configured database connection.',\n {\n connection_id: z.string().optional().describe('Connection ID (defaults to first available)'),\n table: z.string().optional().describe('Introspect a specific table only'),\n },\n async ({ connection_id, table }) => {\n const connections = connectionManager.listConnections();\n if (connections.length === 0) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: 'No database connections configured.',\n data: null,\n issues: ['Configure a database connection in your project\\'s infrastructure config.'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const connId = connection_id ?? connections[0].id;\n const conn = connectionManager.getConnection(connId);\n if (!conn) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `Connection \"${connId}\" not found.`,\n data: null,\n issues: [`Available connections: ${connections.map((c) => c.id).join(', ')}`],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n let schema;\n try {\n schema = await schemaIntrospector.introspect(conn, table);\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `Schema introspection failed: ${(err as Error).message}`,\n data: null,\n issues: [(err as Error).message],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const response = {\n summary: `Schema for ${schema.connectionId}: ${schema.tables.length} table(s).`,\n data: schema.tables.map((t) => ({\n name: t.name,\n rowCount: t.rowCount ?? null,\n columns: t.columns.map((c) => ({\n name: c.name,\n type: c.type,\n nullable: c.nullable,\n isPrimaryKey: c.isPrimaryKey,\n default: c.defaultValue ?? null,\n })),\n foreignKeys: t.foreignKeys,\n indexes: t.indexes,\n })),\n issues: [] as string[],\n metadata: {\n timeRange: { from: schema.fetchedAt, to: schema.fetchedAt },\n eventCount: schema.tables.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_table_data ---\n server.tool(\n 'get_table_data',\n 'Read rows from a database table with pagination. Requires a configured database connection.',\n {\n table: z.string().describe('Table name to read'),\n connection_id: z.string().optional().describe('Connection ID'),\n limit: z.number().optional().describe('Max rows (default 50, max 1000)'),\n offset: z.number().optional().describe('Pagination offset'),\n where: z.string().optional().describe('SQL WHERE clause (without WHERE keyword)'),\n order_by: z.string().optional().describe('SQL ORDER BY clause (without ORDER BY keyword)'),\n },\n async ({ table, connection_id, limit, offset, where, order_by }) => {\n const connections = connectionManager.listConnections();\n const connId = connection_id ?? connections[0]?.id;\n if (!connId) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: 'No database connections configured.',\n data: null,\n issues: ['Configure a database connection.'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const conn = connectionManager.getConnection(connId);\n if (!conn) {\n return {\n content: [{ type: 'text' as const, text: `Connection \"${connId}\" not found.` }],\n };\n }\n\n let result;\n try {\n result = await dataBrowser.read(conn, { table, limit, offset, where, orderBy: order_by });\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `Read failed: ${(err as Error).message}`,\n data: null,\n issues: [(err as Error).message],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const response = {\n summary: `${result.rows.length} row(s) from \"${table}\" (${result.total} total).`,\n data: { rows: result.rows, total: result.total, limit: result.limit, offset: result.offset },\n issues: [] as string[],\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: result.rows.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- modify_table_data ---\n server.tool(\n 'modify_table_data',\n 'Insert, update, or delete rows in a LOCAL DEV database. Safety guarded: localhost only, WHERE required for update/delete, max 100 affected rows, wrapped in transaction.',\n {\n table: z.string().describe('Table name'),\n operation: z.enum(['insert', 'update', 'delete']).describe('Operation type'),\n connection_id: z.string().optional().describe('Connection ID'),\n data: z.record(z.unknown()).optional().describe('Row data (for insert/update)'),\n where: z.string().optional().describe('WHERE clause (required for update/delete)'),\n },\n async ({ table, operation, connection_id, data, where }) => {\n const connections = connectionManager.listConnections();\n const connId = connection_id ?? connections[0]?.id;\n if (!connId) {\n return {\n content: [{ type: 'text' as const, text: 'No database connections configured.' }],\n };\n }\n\n const conn = connectionManager.getConnection(connId);\n if (!conn) {\n return {\n content: [{ type: 'text' as const, text: `Connection \"${connId}\" not found.` }],\n };\n }\n\n // Safety: require WHERE for update/delete to prevent accidental mass operations\n if ((operation === 'update' || operation === 'delete') && !where) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `WHERE clause required for ${operation} operations.`,\n data: null,\n issues: [`${operation} without WHERE clause is not allowed`],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n let result;\n try {\n result = await dataBrowser.write(conn, { table, operation, data, where });\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `Write failed: ${(err as Error).message}`,\n data: null,\n issues: [(err as Error).message],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const response = {\n summary: result.success\n ? `${operation} on \"${table}\": ${result.affectedRows} row(s) affected.`\n : `${operation} on \"${table}\" failed: ${result.error}`,\n data: result,\n issues: result.error ? [result.error] : [],\n metadata: {\n timeRange: { from: Date.now(), to: Date.now() },\n eventCount: result.affectedRows,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_database_connections ---\n server.tool(\n 'get_database_connections',\n 'List all configured database connections with their health status.',\n {},\n async () => {\n const connections = connectionManager.listConnections();\n\n const response = {\n summary: `${connections.length} database connection(s) configured.`,\n data: connections,\n issues: connections.filter((c) => !c.isHealthy).map((c) => `Connection \"${c.id}\" is unhealthy`),\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: connections.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- suggest_indexes ---\n server.tool(\n 'suggest_indexes',\n 'Analyze captured database queries and suggest missing indexes based on WHERE/ORDER BY columns and query performance.',\n {\n since_seconds: z.number().optional().describe('Analyze queries from the last N seconds'),\n },\n async ({ since_seconds }) => {\n const events = store.getDatabaseEvents({ sinceSeconds: since_seconds });\n const suggestions = suggestIndexes(events);\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n const response = {\n summary: `${suggestions.length} index suggestion(s) based on ${events.length} captured queries.`,\n data: suggestions.map((s) => ({\n table: s.table,\n columns: s.columns,\n reason: s.reason,\n estimatedImpact: s.estimatedImpact,\n queryPattern: s.queryPattern,\n suggestedSQL: `CREATE INDEX idx_${s.table}_${s.columns.join('_')} ON ${s.table}(${s.columns.join(', ')});`,\n })),\n issues: suggestions.filter((s) => s.estimatedImpact === 'high').map((s) => `High-impact index missing on ${s.table}(${s.columns.join(', ')})`),\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: events.length,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport { execSync, spawn } from 'node:child_process';\nimport { existsSync, statSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ProcessMonitor } from '@runtimescope/collector';\n\nexport function registerProcessMonitorTools(\n server: McpServer,\n processMonitor: ProcessMonitor\n): void {\n // --- get_dev_processes ---\n server.tool(\n 'get_dev_processes',\n 'List all running dev processes (Next.js, Vite, Prisma, Docker, databases, etc.) with PID, port, memory, and CPU usage.',\n {\n type: z.string().optional().describe('Filter by process type (next, vite, docker, postgres, etc.)'),\n project: z.string().optional().describe('Filter by project name'),\n },\n async ({ type, project }) => {\n processMonitor.scan();\n const processes = processMonitor.getProcesses({\n type: type as Parameters<typeof processMonitor.getProcesses>[0] extends undefined ? never : NonNullable<Parameters<typeof processMonitor.getProcesses>[0]>['type'],\n project,\n });\n\n const issues = processMonitor.detectIssues();\n\n const response = {\n summary: `${processes.length} dev process(es) running.${issues.length > 0 ? ` ${issues.length} issue(s) detected.` : ''}`,\n data: processes.map((p) => ({\n pid: p.pid,\n type: p.type,\n command: p.command,\n cpuPercent: `${p.cpuPercent}%`,\n memoryMB: `${p.memoryMB.toFixed(0)}MB`,\n ports: p.ports,\n cwd: p.cwd ?? null,\n project: p.project ?? null,\n isOrphaned: p.isOrphaned,\n })),\n issues: issues.map((i) => i.title),\n metadata: {\n timeRange: { from: Date.now(), to: Date.now() },\n eventCount: processes.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- kill_process ---\n server.tool(\n 'kill_process',\n 'Terminate a dev process by PID. Default signal is SIGTERM; use SIGKILL for force kill.',\n {\n pid: z.number().describe('Process ID to kill'),\n signal: z.enum(['SIGTERM', 'SIGKILL']).optional().describe('Signal to send (default: SIGTERM)'),\n },\n async ({ pid, signal }) => {\n // Safety: refuse to kill PID 0/1 (init) or the current process\n if (pid < 2 || pid === process.pid) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `Refusing to kill PID ${pid}: ${pid < 2 ? 'system process' : 'current process'}.`,\n data: { success: false, pid },\n issues: [`Cannot kill PID ${pid}`],\n metadata: { timeRange: { from: Date.now(), to: Date.now() }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const result = processMonitor.killProcess(pid, signal ?? 'SIGTERM');\n\n const response = {\n summary: result.success\n ? `Process ${pid} terminated with ${signal ?? 'SIGTERM'}.`\n : `Failed to kill process ${pid}: ${result.error}`,\n data: result,\n issues: result.error ? [result.error] : [],\n metadata: {\n timeRange: { from: Date.now(), to: Date.now() },\n eventCount: 1,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_port_usage ---\n server.tool(\n 'get_port_usage',\n 'Show which dev processes are bound to which ports. Useful for debugging port conflicts.',\n {\n port: z.number().optional().describe('Filter by specific port number'),\n },\n async ({ port }) => {\n processMonitor.scan();\n const ports = processMonitor.getPortUsage(port);\n\n const response = {\n summary: `${ports.length} port binding(s) found.`,\n data: ports.map((p) => ({\n port: p.port,\n pid: p.pid,\n process: p.process,\n type: p.type,\n project: p.project ?? null,\n })),\n issues: [] as string[],\n metadata: {\n timeRange: { from: Date.now(), to: Date.now() },\n eventCount: ports.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- purge_caches ---\n server.tool(\n 'purge_caches',\n 'Delete common build/dev cache directories (.next/cache, node_modules/.cache, .vite, .turbo, .swc, .parcel-cache, etc.) for a project directory. Reports size freed per cache.',\n {\n directory: z.string().describe('Absolute path to the project directory'),\n dryRun: z.boolean().optional().describe('If true, report what would be deleted without actually deleting (default: false)'),\n },\n async ({ directory, dryRun }) => {\n const CACHE_TARGETS = [\n '.next/cache',\n 'node_modules/.cache',\n 'node_modules/.vite',\n '.turbo',\n '.cache',\n '.swc',\n '.parcel-cache',\n '.nuxt',\n 'tsconfig.tsbuildinfo',\n ];\n\n const purged: { path: string; sizeMB: number; deleted: boolean }[] = [];\n let totalFreed = 0;\n\n for (const target of CACHE_TARGETS) {\n const fullPath = join(directory, target);\n if (!existsSync(fullPath)) continue;\n\n const sizeMB = getDirSizeMB(fullPath);\n const deleted = !dryRun;\n\n if (!dryRun) {\n try {\n rmSync(fullPath, { recursive: true, force: true });\n } catch {\n purged.push({ path: target, sizeMB, deleted: false });\n continue;\n }\n }\n\n totalFreed += sizeMB;\n purged.push({ path: target, sizeMB, deleted });\n }\n\n const mode = dryRun ? 'Dry run' : 'Purged';\n const response = {\n summary: purged.length > 0\n ? `${mode}: ${purged.length} cache(s), ${totalFreed.toFixed(1)}MB ${dryRun ? 'would be freed' : 'freed'}.`\n : 'No caches found to purge.',\n data: {\n directory,\n dryRun: dryRun ?? false,\n totalFreedMB: parseFloat(totalFreed.toFixed(1)),\n caches: purged,\n },\n issues: purged.filter((p) => !p.deleted && !dryRun).map((p) => `Failed to delete ${p.path}`),\n metadata: {\n timeRange: { from: Date.now(), to: Date.now() },\n eventCount: purged.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- restart_dev_server ---\n server.tool(\n 'restart_dev_server',\n 'Kill a dev server process, purge build caches in its working directory, and restart it with the same or a custom command. Combines kill_process + purge_caches + spawn into one operation.',\n {\n pid: z.number().describe('PID of the dev server process to restart'),\n command: z.string().optional().describe('Custom start command (e.g. \"npm run dev\"). If omitted, infers from process type.'),\n skipCachePurge: z.boolean().optional().describe('If true, skip cache purging (default: false)'),\n signal: z.enum(['SIGTERM', 'SIGKILL']).optional().describe('Kill signal (default: SIGTERM)'),\n },\n async ({ pid, command, skipCachePurge, signal }) => {\n // Safety: refuse to kill PID 0/1 (init) or the current process\n if (pid < 2 || pid === process.pid) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `Refusing to restart PID ${pid}: ${pid < 2 ? 'system process' : 'current process'}.`,\n data: { success: false, pid },\n issues: [`Cannot kill PID ${pid}`],\n metadata: { timeRange: { from: Date.now(), to: Date.now() }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n // 1. Get process info before killing\n processMonitor.scan();\n const processes = processMonitor.getProcesses();\n const proc = processes.find((p) => p.pid === pid);\n\n if (!proc) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: `Process ${pid} not found. It may have already exited.`,\n data: { pid, found: false },\n issues: [`Process ${pid} not found`],\n metadata: { timeRange: { from: Date.now(), to: Date.now() }, eventCount: 0, sessionId: null },\n }, null, 2),\n }],\n };\n }\n\n const cwd = proc.cwd;\n const startCommand = command ?? inferStartCommand(proc.type, proc.command);\n\n // 2. Kill the process\n const killResult = processMonitor.killProcess(pid, signal ?? 'SIGTERM');\n if (!killResult.success) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: `Failed to kill process ${pid}: ${killResult.error}`,\n data: { pid, killed: false, error: killResult.error },\n issues: [killResult.error ?? 'Unknown error'],\n metadata: { timeRange: { from: Date.now(), to: Date.now() }, eventCount: 0, sessionId: null },\n }, null, 2),\n }],\n };\n }\n\n // Wait briefly for process to exit\n await new Promise((r) => setTimeout(r, 500));\n\n // 3. Purge caches\n let cachesFreedMB = 0;\n let cachesPurged = 0;\n if (!skipCachePurge && cwd) {\n const CACHE_TARGETS = [\n '.next/cache', 'node_modules/.cache', 'node_modules/.vite',\n '.turbo', '.cache', '.swc', '.parcel-cache', '.nuxt', 'tsconfig.tsbuildinfo',\n ];\n for (const target of CACHE_TARGETS) {\n const fullPath = join(cwd, target);\n if (!existsSync(fullPath)) continue;\n const sizeMB = getDirSizeMB(fullPath);\n try {\n rmSync(fullPath, { recursive: true, force: true });\n cachesFreedMB += sizeMB;\n cachesPurged++;\n } catch {\n // skip failures\n }\n }\n }\n\n // 4. Restart with new command\n let restarted = false;\n let newPid: number | null = null;\n let restartError: string | undefined;\n\n if (startCommand && cwd) {\n try {\n const child = spawn(startCommand, {\n cwd,\n shell: true,\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n newPid = child.pid ?? null;\n restarted = true;\n } catch (err) {\n restartError = (err as Error).message;\n }\n } else if (!startCommand) {\n restartError = 'Could not infer start command. Provide one via the \"command\" parameter.';\n } else if (!cwd) {\n restartError = 'Could not determine working directory for the process. Provide a command and working directory manually.';\n }\n\n const response = {\n summary: [\n `Killed ${proc.type} process ${pid}.`,\n cachesPurged > 0 ? `Purged ${cachesPurged} cache(s) (${cachesFreedMB.toFixed(1)}MB).` : null,\n restarted ? `Restarted with PID ${newPid} using: ${startCommand}` : null,\n restartError ? `Restart failed: ${restartError}` : null,\n ].filter(Boolean).join(' '),\n data: {\n killed: { pid, type: proc.type, signal: signal ?? 'SIGTERM' },\n cachesPurged: { count: cachesPurged, freedMB: parseFloat(cachesFreedMB.toFixed(1)) },\n restarted: { success: restarted, newPid, command: startCommand, cwd },\n },\n issues: restartError ? [restartError] : [],\n metadata: {\n timeRange: { from: Date.now(), to: Date.now() },\n eventCount: 1,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n\n// --- Helpers ---\n\nfunction getDirSizeMB(path: string): number {\n try {\n const stat = statSync(path);\n if (stat.isFile()) return stat.size / (1024 * 1024);\n\n // Use du for directories (fast, handles nested files)\n const output = execSync(`du -sk \"${path}\" 2>/dev/null`, { encoding: 'utf-8', timeout: 5000 });\n const kb = parseInt(output.trim().split('\\t')[0], 10);\n return isNaN(kb) ? 0 : kb / 1024;\n } catch {\n return 0;\n }\n}\n\nfunction inferStartCommand(type: string, rawCommand: string): string | null {\n // Common dev server start commands by type\n const defaults: Record<string, string> = {\n next: 'npx next dev',\n vite: 'npx vite',\n webpack: 'npx webpack serve',\n wrangler: 'npx wrangler dev',\n prisma: 'npx prisma studio',\n bun: 'bun run dev',\n deno: 'deno task dev',\n };\n\n if (defaults[type]) return defaults[type];\n\n // For node processes, check if the original command gives us clues\n if (rawCommand.includes('ts-node') || rawCommand.includes('tsx')) {\n // Extract the script path\n const match = rawCommand.match(/(ts-node|tsx)\\s+(.+)/);\n if (match) return `npx ${match[1]} ${match[2]}`;\n }\n\n // Fallback: try npm run dev (most common)\n if (type === 'node') return 'npm run dev';\n\n return null;\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { InfraConnector } from '@runtimescope/collector';\n\nexport function registerInfraTools(\n server: McpServer,\n infraConnector: InfraConnector\n): void {\n // --- get_deploy_logs ---\n server.tool(\n 'get_deploy_logs',\n 'Get deployment history from connected platforms (Vercel, Cloudflare, Railway). Shows build status, branch, commit, and timing.',\n {\n project: z.string().optional().describe('Project name'),\n platform: z.string().optional().describe('Filter by platform (vercel, cloudflare, railway)'),\n deploy_id: z.string().optional().describe('Get details for a specific deployment'),\n },\n async ({ project, platform, deploy_id }) => {\n const logs = await infraConnector.getDeployLogs(project ?? 'default', platform, deploy_id);\n\n const response = {\n summary: `${logs.length} deployment(s) found.`,\n data: logs.map((l) => ({\n id: l.id,\n platform: l.platform,\n status: l.status,\n url: l.url ?? null,\n branch: l.branch ?? null,\n commit: l.commit?.slice(0, 8) ?? null,\n createdAt: new Date(l.createdAt).toISOString(),\n readyAt: l.readyAt ? new Date(l.readyAt).toISOString() : null,\n error: l.errorMessage ?? null,\n })),\n issues: logs.filter((l) => l.status === 'error').map((l) => `Deploy ${l.id.slice(0, 8)} failed on ${l.platform}`),\n metadata: {\n timeRange: logs.length > 0\n ? { from: Math.min(...logs.map((l) => l.createdAt)), to: Math.max(...logs.map((l) => l.createdAt)) }\n : { from: 0, to: 0 },\n eventCount: logs.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_runtime_logs ---\n server.tool(\n 'get_runtime_logs',\n 'Get runtime error/info logs from connected deployment platforms.',\n {\n project: z.string().optional().describe('Project name'),\n platform: z.string().optional().describe('Filter by platform'),\n level: z.string().optional().describe('Filter by log level (info, warn, error)'),\n since_seconds: z.number().optional().describe('Only return logs from the last N seconds'),\n },\n async ({ project, platform, level, since_seconds }) => {\n const since = since_seconds ? Date.now() - since_seconds * 1000 : undefined;\n const logs = await infraConnector.getRuntimeLogs(project ?? 'default', { platform, since, level });\n\n const response = {\n summary: `${logs.length} runtime log(s) found.`,\n data: logs.map((l) => ({\n timestamp: new Date(l.timestamp).toISOString(),\n level: l.level,\n message: l.message,\n source: l.source ?? null,\n platform: l.platform,\n })),\n issues: logs.filter((l) => l.level === 'error').length > 0\n ? [`${logs.filter((l) => l.level === 'error').length} error(s) in runtime logs`]\n : [],\n metadata: {\n timeRange: logs.length > 0\n ? { from: logs[logs.length - 1].timestamp, to: logs[0].timestamp }\n : { from: 0, to: 0 },\n eventCount: logs.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_build_status ---\n server.tool(\n 'get_build_status',\n 'Get the current deployment status for each connected platform.',\n {\n project: z.string().optional().describe('Project name'),\n },\n async ({ project }) => {\n const statuses = await infraConnector.getBuildStatus(project ?? 'default');\n\n const response = {\n summary: `${statuses.length} platform(s) reporting build status.`,\n data: statuses.map((s) => ({\n platform: s.platform,\n project: s.project,\n status: s.status,\n url: s.url ?? null,\n lastDeployed: new Date(s.lastDeployed).toISOString(),\n deployId: s.latestDeployId,\n })),\n issues: statuses.filter((s) => s.status === 'error').map((s) => `${s.platform}: latest deploy failed`),\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: statuses.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_infra_overview ---\n server.tool(\n 'get_infra_overview',\n 'Overview of which platforms a project uses, combining explicit configuration with auto-detection from network traffic.',\n {\n project: z.string().optional().describe('Project name'),\n },\n async ({ project }) => {\n const overview = infraConnector.getInfraOverview(project);\n\n const response = {\n summary: overview.length > 0\n ? `Infrastructure overview: ${overview[0].platforms.length} configured platform(s), ${overview[0].detectedFromTraffic.length} detected from traffic.`\n : 'No infrastructure information available.',\n data: overview,\n issues: [] as string[],\n metadata: {\n timeRange: { from: 0, to: Date.now() },\n eventCount: overview.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { SessionManager, SessionMetrics } from '@runtimescope/collector';\nimport { compareSessions } from '@runtimescope/collector';\n\nexport function registerSessionDiffTools(\n server: McpServer,\n sessionManager: SessionManager\n): void {\n // --- compare_sessions ---\n server.tool(\n 'compare_sessions',\n 'Compare two sessions: render counts, API latency, errors, Web Vitals, and query performance. Shows regressions and improvements.',\n {\n session_a: z.string().describe('First session ID (baseline)'),\n session_b: z.string().describe('Second session ID (comparison)'),\n project: z.string().optional().describe('Project name'),\n },\n async ({ session_a, session_b, project }) => {\n const projectName = project ?? 'default';\n const history = sessionManager.getSessionHistory(projectName, 100);\n\n const snapshotA = history.find((s) => s.sessionId === session_a);\n const snapshotB = history.find((s) => s.sessionId === session_b);\n\n if (!snapshotA || !snapshotB) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: 'Could not find one or both sessions in history.',\n data: null,\n issues: [\n !snapshotA ? `Session ${session_a} not found` : null,\n !snapshotB ? `Session ${session_b} not found` : null,\n ].filter(Boolean),\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const diff = compareSessions(snapshotA.metrics, snapshotB.metrics);\n\n const regressions = [\n ...diff.endpointDeltas.filter((d) => d.classification === 'regression'),\n ...diff.componentDeltas.filter((d) => d.classification === 'regression'),\n ...diff.webVitalDeltas.filter((d) => d.classification === 'regression'),\n ...diff.queryDeltas.filter((d) => d.classification === 'regression'),\n ];\n\n const improvements = [\n ...diff.endpointDeltas.filter((d) => d.classification === 'improvement'),\n ...diff.componentDeltas.filter((d) => d.classification === 'improvement'),\n ...diff.webVitalDeltas.filter((d) => d.classification === 'improvement'),\n ...diff.queryDeltas.filter((d) => d.classification === 'improvement'),\n ];\n\n const response = {\n summary: `Session comparison: ${regressions.length} regression(s), ${improvements.length} improvement(s). Error delta: ${diff.overallDelta.errorCountDelta >= 0 ? '+' : ''}${diff.overallDelta.errorCountDelta}.`,\n data: {\n endpointDeltas: diff.endpointDeltas.map((d) => ({\n ...d,\n before: `${d.before.toFixed(0)}ms`,\n after: `${d.after.toFixed(0)}ms`,\n percentChange: `${(d.percentChange * 100).toFixed(1)}%`,\n })),\n componentDeltas: diff.componentDeltas.map((d) => ({\n ...d,\n percentChange: `${(d.percentChange * 100).toFixed(1)}%`,\n })),\n webVitalDeltas: diff.webVitalDeltas.map((d) => ({\n ...d,\n percentChange: `${(d.percentChange * 100).toFixed(1)}%`,\n })),\n queryDeltas: diff.queryDeltas.map((d) => ({\n ...d,\n before: `${d.before.toFixed(0)}ms`,\n after: `${d.after.toFixed(0)}ms`,\n percentChange: `${(d.percentChange * 100).toFixed(1)}%`,\n })),\n overallDelta: diff.overallDelta,\n },\n issues: regressions.map((r) => `Regression: ${r.key} (${(r.percentChange * 100).toFixed(1)}% worse)`),\n metadata: {\n timeRange: { from: snapshotA.createdAt, to: snapshotB.createdAt },\n eventCount: 2,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n\n // --- get_session_history ---\n server.tool(\n 'get_session_history',\n 'List past sessions with build metadata, event counts, and timestamps. Requires SQLite persistence.',\n {\n project: z.string().optional().describe('Project name'),\n limit: z.number().optional().describe('Max sessions to return (default 20)'),\n },\n async ({ project, limit }) => {\n const projectName = project ?? 'default';\n const history = sessionManager.getSessionHistory(projectName, limit ?? 20);\n\n const response = {\n summary: `${history.length} session(s) in history for project \"${projectName}\".`,\n data: history.map((s) => ({\n sessionId: s.sessionId,\n project: s.project,\n createdAt: new Date(s.createdAt).toISOString(),\n totalEvents: s.metrics.totalEvents,\n errorCount: s.metrics.errorCount,\n endpointCount: Object.keys(s.metrics.endpoints).length,\n componentCount: Object.keys(s.metrics.components).length,\n buildMeta: s.buildMeta ?? null,\n })),\n issues: [] as string[],\n metadata: {\n timeRange: history.length > 0\n ? { from: history[history.length - 1].createdAt, to: history[0].createdAt }\n : { from: 0, to: 0 },\n eventCount: history.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n }\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type { CollectorServer } from '@runtimescope/collector';\n\nexport function registerReconMetadataTools(\n server: McpServer,\n store: EventStore,\n collector: CollectorServer,\n): void {\n server.tool(\n 'get_page_metadata',\n 'Get page metadata and tech stack detection for the current page. Returns URL, viewport, meta tags, detected framework/UI library/build tool/hosting, external stylesheets and scripts. Requires the RuntimeScope extension to be connected.',\n {\n url: z\n .string()\n .optional()\n .describe('Filter by URL substring'),\n force_refresh: z\n .boolean()\n .optional()\n .default(false)\n .describe('Send a recon_scan command to the extension to capture fresh data'),\n },\n async ({ url, force_refresh }) => {\n if (force_refresh) {\n const sessions = store.getSessionInfo();\n const activeSession = sessions.find((s) => s.isConnected);\n if (activeSession) {\n try {\n await collector.sendCommand(activeSession.sessionId, {\n command: 'recon_scan',\n requestId: crypto.randomUUID(),\n params: { categories: ['recon_metadata'] },\n });\n } catch {\n // Extension may not support commands yet; fall through to stored data\n }\n }\n }\n\n const event = store.getReconMetadata({ url });\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: 'No page metadata captured yet. Ensure the RuntimeScope extension is connected and has scanned a page.',\n data: null,\n issues: ['No recon_metadata events found in the event store'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const ts = event.techStack;\n const stackParts: string[] = [];\n if (ts.framework.name !== 'unknown') stackParts.push(`${ts.framework.name}${ts.framework.version ? ' ' + ts.framework.version : ''}`);\n if (ts.metaFramework?.name && ts.metaFramework.name !== 'unknown') stackParts.push(ts.metaFramework.name);\n if (ts.uiLibrary?.name && ts.uiLibrary.name !== 'unknown') stackParts.push(ts.uiLibrary.name);\n if (ts.hosting?.name && ts.hosting.name !== 'unknown') stackParts.push(`on ${ts.hosting.name}`);\n\n const issues: string[] = [];\n if (!event.metaTags['viewport']) {\n issues.push('No viewport meta tag detected');\n }\n if (ts.framework.confidence === 'low') {\n issues.push(`Framework detection confidence is low: ${ts.framework.name}`);\n }\n\n const response = {\n summary: `Page: ${event.title || event.url}. Tech stack: ${stackParts.join(' + ') || 'unknown'}. ${event.externalStylesheets.length} stylesheets, ${event.externalScripts.length} scripts.`,\n data: {\n url: event.url,\n title: event.title,\n viewport: event.viewport,\n documentLang: event.documentLang,\n metaTags: event.metaTags,\n techStack: {\n framework: ts.framework,\n metaFramework: ts.metaFramework ?? null,\n uiLibrary: ts.uiLibrary ?? null,\n buildTool: ts.buildTool ?? null,\n hosting: ts.hosting ?? null,\n stateManagement: ts.stateManagement ?? null,\n additional: ts.additional,\n },\n externalStylesheets: event.externalStylesheets,\n externalScripts: event.externalScripts,\n preloads: event.preloads,\n },\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type { CollectorServer } from '@runtimescope/collector';\n\nexport function registerReconDesignTokenTools(\n server: McpServer,\n store: EventStore,\n collector: CollectorServer,\n): void {\n server.tool(\n 'get_design_tokens',\n 'Extract the design system from the current page: CSS custom properties (--variables), color palette, typography scale, spacing scale, border radii, box shadows, and CSS architecture detection. Essential for matching a site\\'s visual style when recreating UI.',\n {\n url: z\n .string()\n .optional()\n .describe('Filter by URL substring'),\n category: z\n .enum(['all', 'colors', 'typography', 'spacing', 'custom_properties', 'shadows'])\n .optional()\n .default('all')\n .describe('Return only a specific token category'),\n force_refresh: z\n .boolean()\n .optional()\n .default(false)\n .describe('Send a recon_scan command to capture fresh data'),\n },\n async ({ url, category, force_refresh }) => {\n if (force_refresh) {\n const sessions = store.getSessionInfo();\n const activeSession = sessions.find((s) => s.isConnected);\n if (activeSession) {\n try {\n await collector.sendCommand(activeSession.sessionId, {\n command: 'recon_scan',\n requestId: crypto.randomUUID(),\n params: { categories: ['recon_design_tokens'] },\n });\n } catch {\n // Fall through to stored data\n }\n }\n }\n\n const event = store.getReconDesignTokens({ url });\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: 'No design tokens captured yet. Ensure the RuntimeScope extension is connected and has scanned a page.',\n data: null,\n issues: ['No recon_design_tokens events found in the event store'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const issues: string[] = [];\n\n // Analyze token quality\n if (event.customProperties.length === 0) {\n issues.push('No CSS custom properties (--variables) found. The site may use hardcoded values instead of design tokens.');\n }\n if (event.colors.length > 30) {\n issues.push(`${event.colors.length} unique colors found — this may indicate an inconsistent color system.`);\n }\n if (event.typography.length > 15) {\n issues.push(`${event.typography.length} unique typography combos found — may indicate inconsistent type scale.`);\n }\n\n // Build category-filtered response\n const data: Record<string, unknown> = {};\n\n if (category === 'all' || category === 'custom_properties') {\n data.customProperties = event.customProperties;\n }\n if (category === 'all' || category === 'colors') {\n data.colors = event.colors;\n }\n if (category === 'all' || category === 'typography') {\n data.typography = event.typography;\n }\n if (category === 'all' || category === 'spacing') {\n data.spacing = event.spacing;\n }\n if (category === 'all' || category === 'shadows') {\n data.borderRadii = event.borderRadii;\n data.boxShadows = event.boxShadows;\n }\n\n if (category === 'all') {\n data.cssArchitecture = event.cssArchitecture;\n data.classNamingPatterns = event.classNamingPatterns;\n data.sampleClassNames = event.sampleClassNames;\n }\n\n const summaryParts = [\n `${event.customProperties.length} CSS variables`,\n `${event.colors.length} colors`,\n `${event.typography.length} type combos`,\n `${event.spacing.length} spacing values`,\n `CSS architecture: ${event.cssArchitecture}`,\n ];\n\n const response = {\n summary: summaryParts.join(', ') + '.',\n data,\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nexport function registerReconFontTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_font_info',\n 'Get typography details for the current page: @font-face declarations, font families actually used in computed styles, icon fonts with glyph usage, and font loading strategy. Critical for matching typography when recreating UI.',\n {\n url: z\n .string()\n .optional()\n .describe('Filter by URL substring'),\n },\n async ({ url }) => {\n const event = store.getReconFonts({ url });\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: 'No font data captured yet. Ensure the RuntimeScope extension is connected and has scanned a page.',\n data: null,\n issues: ['No recon_fonts events found in the event store'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const issues: string[] = [];\n\n // Identify potential problems\n const uniqueFamilies = new Set(event.fontsUsed.map((f) => f.family));\n if (uniqueFamilies.size > 5) {\n issues.push(`${uniqueFamilies.size} different font families in use — may impact page load performance.`);\n }\n\n // Check for font-display usage\n const missingDisplay = event.fontFaces.filter((f) => !f.display);\n if (missingDisplay.length > 0) {\n issues.push(`${missingDisplay.length} @font-face rule(s) without font-display — may cause FOIT (flash of invisible text).`);\n }\n\n const families = Array.from(uniqueFamilies).join(', ');\n\n const response = {\n summary: `${event.fontFaces.length} @font-face declarations, ${uniqueFamilies.size} font families in use (${families}), ${event.iconFonts.length} icon font(s). Loading: ${event.loadingStrategy}.`,\n data: {\n fontFaces: event.fontFaces,\n fontsUsed: event.fontsUsed,\n iconFonts: event.iconFonts,\n loadingStrategy: event.loadingStrategy,\n },\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore, CollectorServer } from '@runtimescope/collector';\nimport type { LayoutNode } from '@runtimescope/collector';\n\nexport function registerReconLayoutTools(\n server: McpServer,\n store: EventStore,\n collector: CollectorServer,\n): void {\n server.tool(\n 'get_layout_tree',\n 'Get the DOM structure with layout information: element tags, classes, bounding rects, display mode (flex/grid/block), flex/grid properties (direction, justify, align, gap, template columns/rows), position, and z-index. Optionally scoped to a CSS selector. Essential for understanding page structure when recreating UI.',\n {\n selector: z\n .string()\n .optional()\n .describe('CSS selector to scope the tree (e.g., \"nav\", \".hero\", \"main\"). Omit for full page.'),\n max_depth: z\n .number()\n .optional()\n .default(10)\n .describe('Maximum depth of the tree to return (default 10)'),\n url: z\n .string()\n .optional()\n .describe('Filter by URL substring'),\n force_refresh: z\n .boolean()\n .optional()\n .default(false)\n .describe('Request fresh capture from extension'),\n },\n async ({ selector, max_depth, url, force_refresh }) => {\n if (force_refresh) {\n const sessions = store.getSessionInfo();\n const activeSession = sessions.find((s) => s.isConnected);\n if (activeSession) {\n try {\n await collector.sendCommand(activeSession.sessionId, {\n command: 'recon_layout_tree',\n requestId: crypto.randomUUID(),\n params: { selector, maxDepth: max_depth },\n });\n } catch {\n // Fall through to stored data\n }\n }\n }\n\n const event = store.getReconLayoutTree({ url });\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: 'No layout tree captured yet. Ensure the RuntimeScope extension is connected and has scanned a page.',\n data: null,\n issues: ['No recon_layout_tree events found in the event store'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n // If a selector was requested, find the matching subtree\n let tree = event.tree;\n let totalElements = event.totalElements;\n if (selector && !event.rootSelector) {\n const found = findNode(tree, selector);\n if (found) {\n tree = found;\n totalElements = countNodes(found);\n }\n }\n\n // Prune to max_depth\n const pruned = pruneTree(tree, max_depth ?? 10);\n\n // Analyze layout patterns\n const issues: string[] = [];\n const flexCount = countByDisplay(tree, 'flex');\n const gridCount = countByDisplay(tree, 'grid');\n\n const response = {\n summary: `Layout tree: ${totalElements} elements, max depth ${event.maxDepth}. ${flexCount} flex containers, ${gridCount} grid containers. Viewport: ${event.viewport.width}x${event.viewport.height}.${selector ? ` Scoped to: ${selector}.` : ''}`,\n data: {\n viewport: event.viewport,\n scrollHeight: event.scrollHeight,\n rootSelector: selector ?? event.rootSelector ?? null,\n tree: pruned,\n totalElements,\n maxDepth: event.maxDepth,\n },\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n\nfunction findNode(node: LayoutNode, selector: string): LayoutNode | null {\n // Simple matching: check tag, id, class\n if (matchesSelector(node, selector)) return node;\n for (const child of node.children) {\n const found = findNode(child, selector);\n if (found) return found;\n }\n return null;\n}\n\nfunction matchesSelector(node: LayoutNode, selector: string): boolean {\n // Basic selector matching for common patterns\n if (selector.startsWith('#') && node.id === selector.slice(1)) return true;\n if (selector.startsWith('.') && node.classList.includes(selector.slice(1))) return true;\n if (node.tag === selector.toLowerCase()) return true;\n // Check role\n if (selector.startsWith('[role=') && node.role === selector.slice(6, -1).replace(/\"/g, '')) return true;\n return false;\n}\n\nfunction countNodes(node: LayoutNode): number {\n let count = 1;\n for (const child of node.children) {\n count += countNodes(child);\n }\n return count;\n}\n\nfunction countByDisplay(node: LayoutNode, displayType: string): number {\n let count = node.display?.includes(displayType) ? 1 : 0;\n for (const child of node.children) {\n count += countByDisplay(child, displayType);\n }\n return count;\n}\n\nfunction pruneTree(node: LayoutNode, maxDepth: number, currentDepth = 0): LayoutNode {\n if (currentDepth >= maxDepth) {\n return {\n ...node,\n children: [],\n childCount: node.childCount,\n };\n }\n return {\n ...node,\n children: node.children.map((c) => pruneTree(c, maxDepth, currentDepth + 1)),\n };\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nexport function registerReconAccessibilityTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_accessibility_tree',\n 'Get the accessibility structure of the current page: heading hierarchy (h1-h6), ARIA landmarks (nav, main, aside), form fields with labels, buttons, links, and images with alt text status. Useful for ensuring UI recreations maintain proper semantic HTML and accessibility.',\n {\n url: z\n .string()\n .optional()\n .describe('Filter by URL substring'),\n },\n async ({ url }) => {\n const event = store.getReconAccessibility({ url });\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: 'No accessibility data captured yet. Ensure the RuntimeScope extension is connected and has scanned a page.',\n data: null,\n issues: ['No recon_accessibility events found in the event store'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const issues = [...event.issues];\n\n // Analyze heading structure\n const headingLevels = event.headings.map((h) => h.level);\n if (headingLevels.length > 0 && headingLevels[0] !== 1) {\n issues.push(`First heading is h${headingLevels[0]}, not h1.`);\n }\n for (let i = 1; i < headingLevels.length; i++) {\n if (headingLevels[i] > headingLevels[i - 1] + 1) {\n issues.push(`Heading level skip: h${headingLevels[i - 1]} → h${headingLevels[i]} (missing h${headingLevels[i - 1] + 1}).`);\n break;\n }\n }\n\n // Check images without alt\n const missingAlt = event.images.filter((img) => !img.hasAlt);\n if (missingAlt.length > 0) {\n issues.push(`${missingAlt.length} image(s) missing alt text.`);\n }\n\n // Check form labels\n const unlabeled = event.formFields.filter((f) => !f.label && !f.ariaDescribedBy);\n if (unlabeled.length > 0) {\n issues.push(`${unlabeled.length} form field(s) without labels.`);\n }\n\n // Check landmarks\n const hasMain = event.landmarks.some((l) => l.role === 'main');\n const hasNav = event.landmarks.some((l) => l.role === 'navigation');\n if (!hasMain) issues.push('No <main> landmark found.');\n if (!hasNav) issues.push('No <nav> landmark found.');\n\n const response = {\n summary: `${event.headings.length} headings, ${event.landmarks.length} landmarks, ${event.formFields.length} form fields, ${event.buttons.length} buttons, ${event.links.length} links, ${event.images.length} images. ${issues.length} accessibility issue(s).`,\n data: {\n headings: event.headings,\n landmarks: event.landmarks,\n formFields: event.formFields,\n buttons: event.buttons,\n links: event.links,\n images: event.images,\n },\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore, CollectorServer } from '@runtimescope/collector';\nimport type { PlaywrightScanner } from '../scanner/index.js';\n\n// Common CSS property groups for the `properties` filter\nconst PROPERTY_GROUPS: Record<string, string[]> = {\n colors: [\n 'color', 'background-color', 'border-color', 'border-top-color', 'border-right-color',\n 'border-bottom-color', 'border-left-color', 'outline-color', 'text-decoration-color',\n 'box-shadow', 'text-shadow',\n ],\n typography: [\n 'font-family', 'font-size', 'font-weight', 'font-style', 'line-height',\n 'letter-spacing', 'text-align', 'text-transform', 'text-decoration',\n 'word-spacing', 'white-space', 'text-overflow',\n ],\n spacing: [\n 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'gap',\n ],\n layout: [\n 'display', 'position', 'top', 'right', 'bottom', 'left',\n 'width', 'height', 'min-width', 'max-width', 'min-height', 'max-height',\n 'flex-direction', 'justify-content', 'align-items', 'flex-wrap', 'flex-grow', 'flex-shrink',\n 'grid-template-columns', 'grid-template-rows', 'grid-column', 'grid-row',\n 'overflow', 'z-index',\n ],\n borders: [\n 'border-width', 'border-style', 'border-color', 'border-radius',\n 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width',\n 'border-top-left-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius',\n 'outline-width', 'outline-style', 'outline-color', 'outline-offset',\n ],\n visual: [\n 'opacity', 'background-color', 'background-image', 'background-size', 'background-position',\n 'box-shadow', 'text-shadow', 'filter', 'backdrop-filter',\n 'transform', 'transition', 'animation',\n ],\n};\n\nexport function registerReconComputedStyleTools(\n server: McpServer,\n store: EventStore,\n collector: CollectorServer,\n scanner: PlaywrightScanner,\n): void {\n server.tool(\n 'get_computed_styles',\n 'Get computed CSS styles for elements matching a selector. Returns the actual resolved values the browser uses to render each element. Can filter by property group (colors, typography, spacing, layout, borders, visual) or specific property names. When multiple elements match, highlights variations between them.',\n {\n selector: z\n .string()\n .describe('CSS selector to query (e.g., \".btn-primary\", \"nav > ul > li\", \"[data-testid=hero]\")'),\n properties: z\n .enum(['all', 'colors', 'typography', 'spacing', 'layout', 'borders', 'visual'])\n .optional()\n .default('all')\n .describe('Property group to return, or \"all\" for everything'),\n specific_properties: z\n .array(z.string())\n .optional()\n .describe('Specific CSS property names to return (overrides the properties group)'),\n force_refresh: z\n .boolean()\n .optional()\n .default(false)\n .describe('Request fresh capture from extension or scanner for this selector'),\n },\n async ({ selector, properties, specific_properties, force_refresh }) => {\n // Determine property filter for on-demand collection\n const propFilter = specific_properties ??\n (properties !== 'all' ? PROPERTY_GROUPS[properties] : undefined);\n\n // If force_refresh, try to get fresh data from extension\n if (force_refresh) {\n const sessions = store.getSessionInfo();\n const activeSession = sessions.find((s) => s.isConnected);\n if (activeSession) {\n try {\n await collector.sendCommand(activeSession.sessionId, {\n command: 'recon_computed_styles',\n requestId: crypto.randomUUID(),\n params: { selector, properties: propFilter },\n });\n } catch {\n // Fall through to stored data or scanner fallback\n }\n }\n }\n\n // Check for pre-captured events first\n const events = store.getReconComputedStyles();\n let event = events.find((e) => e.selector === selector) ?? events[0];\n\n // Fallback: if no pre-captured data, use the scanner to query live\n if ((!event || event.entries.length === 0) && scanner.getLastScannedUrl()) {\n const url = scanner.getLastScannedUrl()!;\n try {\n const raw = await scanner.queryComputedStyles(url, selector, propFilter);\n if (raw.entries.length > 0) {\n // Build a synthetic event and store it for caching\n const syntheticEvent = {\n eventId: `evt-scan-cs-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n sessionId: `scan-${Date.now()}`,\n timestamp: Date.now(),\n eventType: 'recon_computed_styles' as const,\n url,\n selector: raw.selector,\n propertyFilter: raw.propertyFilter,\n entries: raw.entries,\n };\n store.addEvent(syntheticEvent);\n event = syntheticEvent;\n }\n } catch {\n // Scanner query failed, fall through to error message\n }\n }\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event || event.entries.length === 0) {\n const hint = scanner.getLastScannedUrl()\n ? `No elements matched \"${selector}\" on the scanned page. Check the selector and try again.`\n : `No computed styles captured for \"${selector}\". Run scan_website first to scan a page, then query selectors on it.`;\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: hint,\n data: null,\n issues: ['No computed style data available for this selector'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const issues: string[] = [];\n\n // Filter properties if a group or specific list is requested\n const entries = event.entries.map((entry) => {\n let styles = entry.styles;\n\n if (specific_properties && specific_properties.length > 0) {\n const filtered: Record<string, string> = {};\n for (const prop of specific_properties) {\n if (styles[prop] !== undefined) filtered[prop] = styles[prop];\n }\n styles = filtered;\n } else if (properties !== 'all' && PROPERTY_GROUPS[properties]) {\n const group = PROPERTY_GROUPS[properties];\n const filtered: Record<string, string> = {};\n for (const prop of group) {\n if (styles[prop] !== undefined) filtered[prop] = styles[prop];\n }\n styles = filtered;\n }\n\n return {\n selector: entry.selector,\n matchCount: entry.matchCount,\n styles,\n variations: entry.variations ?? [],\n };\n });\n\n // Flag variations\n for (const entry of entries) {\n if (entry.variations.length > 0) {\n issues.push(\n `${entry.variations.length} property variation(s) across ${entry.matchCount} matching elements for \"${entry.selector}\".`,\n );\n }\n }\n\n const totalProps = entries.reduce((sum, e) => sum + Object.keys(e.styles).length, 0);\n\n const response = {\n summary: `${entries.length} element(s) matched \"${selector}\". ${totalProps} CSS properties returned${properties !== 'all' ? ` (${properties} group)` : ''}.`,\n data: {\n selector,\n propertyFilter: specific_properties ?? properties,\n entries,\n },\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore, CollectorServer } from '@runtimescope/collector';\nimport type { PlaywrightScanner } from '../scanner/index.js';\n\nexport function registerReconElementSnapshotTools(\n server: McpServer,\n store: EventStore,\n collector: CollectorServer,\n scanner: PlaywrightScanner,\n): void {\n server.tool(\n 'get_element_snapshot',\n 'Deep snapshot of a specific element and its children: structure, attributes, text content, bounding rects, and key computed styles for every node. This is the \"zoom in\" tool — use it when you need the full picture of a component (a card, a nav bar, a form) for recreation. More detailed than get_layout_tree, more targeted than get_computed_styles.',\n {\n selector: z\n .string()\n .describe('CSS selector for the root element (e.g., \".card\", \"#hero\", \"[data-testid=checkout-form]\")'),\n depth: z\n .number()\n .optional()\n .default(5)\n .describe('How many levels deep to capture children (default 5)'),\n force_refresh: z\n .boolean()\n .optional()\n .default(false)\n .describe('Request fresh capture from extension or scanner for this element'),\n },\n async ({ selector, depth, force_refresh }) => {\n // If force_refresh, try to get fresh data from extension\n if (force_refresh) {\n const sessions = store.getSessionInfo();\n const activeSession = sessions.find((s) => s.isConnected);\n if (activeSession) {\n try {\n await collector.sendCommand(activeSession.sessionId, {\n command: 'recon_element_snapshot',\n requestId: crypto.randomUUID(),\n params: { selector, depth },\n });\n } catch {\n // Fall through to stored data or scanner fallback\n }\n }\n }\n\n // Check for pre-captured events first\n const events = store.getReconElementSnapshots();\n let event = events.find((e) => e.selector === selector) ?? events[0];\n\n // Fallback: if no pre-captured data, use the scanner to query live\n if (!event && scanner.getLastScannedUrl()) {\n const url = scanner.getLastScannedUrl()!;\n try {\n const raw = await scanner.queryElementSnapshot(url, selector, depth);\n if (raw) {\n // Build a synthetic event and store it for caching\n const syntheticEvent = {\n eventId: `evt-scan-es-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n sessionId: `scan-${Date.now()}`,\n timestamp: Date.now(),\n eventType: 'recon_element_snapshot' as const,\n url,\n selector: raw.selector,\n depth: raw.depth,\n totalNodes: raw.totalNodes,\n root: raw.root,\n };\n store.addEvent(syntheticEvent);\n event = syntheticEvent;\n }\n } catch {\n // Scanner query failed, fall through to error message\n }\n }\n\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event) {\n const hint = scanner.getLastScannedUrl()\n ? `No element found matching \"${selector}\" on the scanned page. Check the selector and try again.`\n : `No element snapshot captured for \"${selector}\". Run scan_website first to scan a page, then query selectors on it.`;\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: hint,\n data: null,\n issues: ['No element snapshot data available for this selector'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const issues: string[] = [];\n\n // Analyze the snapshot\n const root = event.root;\n if (root.boundingRect.width === 0 || root.boundingRect.height === 0) {\n issues.push(`Root element \"${selector}\" has zero dimensions (${root.boundingRect.width}x${root.boundingRect.height}). It may be hidden.`);\n }\n\n const response = {\n summary: `Element snapshot for \"${selector}\": ${event.totalNodes} nodes captured to depth ${event.depth}. Root is <${root.tag}> at ${root.boundingRect.width}x${root.boundingRect.height}px.`,\n data: {\n selector: event.selector,\n depth: event.depth,\n totalNodes: event.totalNodes,\n root: event.root,\n },\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\n\nexport function registerReconAssetTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_asset_inventory',\n 'Sprite-aware asset inventory for the current page. Detects and extracts: standard images, inline SVGs, SVG sprite sheets (<symbol>/<use> references), CSS background sprites (with crop coordinates and extracted frames), CSS mask sprites, and icon fonts (with glyph codepoints). For CSS sprites, calculates the exact crop rectangle from background-position/size and can provide extracted individual frames as data URLs.',\n {\n category: z\n .enum(['all', 'images', 'svg', 'sprites', 'icon_fonts'])\n .optional()\n .default('all')\n .describe('Filter by asset category'),\n url: z\n .string()\n .optional()\n .describe('Filter by page URL substring'),\n },\n async ({ category, url }) => {\n const event = store.getReconAssetInventory({ url });\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n if (!event) {\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: 'No asset inventory captured yet. Ensure the RuntimeScope extension is connected and has scanned a page.',\n data: null,\n issues: ['No recon_asset_inventory events found in the event store'],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const issues: string[] = [];\n\n // Build category-filtered response\n const data: Record<string, unknown> = {};\n\n if (category === 'all' || category === 'images') {\n data.images = event.images;\n // Flag missing alt text\n const missingAlt = event.images.filter((img) => !img.alt);\n if (missingAlt.length > 0) {\n issues.push(`${missingAlt.length} image(s) missing alt text.`);\n }\n // Flag oversized images\n const oversized = event.images.filter(\n (img) => img.naturalWidth && img.width && img.naturalWidth > img.width * 2,\n );\n if (oversized.length > 0) {\n issues.push(`${oversized.length} image(s) are significantly larger than their display size — consider resizing.`);\n }\n }\n\n if (category === 'all' || category === 'svg') {\n data.inlineSVGs = event.inlineSVGs;\n data.svgSprites = event.svgSprites;\n }\n\n if (category === 'all' || category === 'sprites') {\n data.backgroundSprites = event.backgroundSprites;\n data.maskSprites = event.maskSprites;\n data.svgSprites = event.svgSprites;\n\n // Summarize sprite sheets\n const totalBgFrames = event.backgroundSprites.reduce((sum, s) => sum + s.frames.length, 0);\n const totalMaskFrames = event.maskSprites.reduce((sum, s) => sum + s.frames.length, 0);\n const totalSvgSymbols = event.svgSprites.length;\n\n if (totalBgFrames > 0 || totalMaskFrames > 0 || totalSvgSymbols > 0) {\n const spriteParts: string[] = [];\n if (totalBgFrames > 0) spriteParts.push(`${totalBgFrames} background sprite frame(s) from ${event.backgroundSprites.length} sheet(s)`);\n if (totalMaskFrames > 0) spriteParts.push(`${totalMaskFrames} mask sprite frame(s) from ${event.maskSprites.length} sheet(s)`);\n if (totalSvgSymbols > 0) spriteParts.push(`${totalSvgSymbols} SVG symbol(s)`);\n issues.push(`Sprite detection: ${spriteParts.join(', ')}.`);\n }\n }\n\n if (category === 'all' || category === 'icon_fonts') {\n data.iconFonts = event.iconFonts;\n const totalGlyphs = event.iconFonts.reduce((sum, f) => sum + f.glyphs.length, 0);\n if (totalGlyphs > 0) {\n issues.push(`${totalGlyphs} icon font glyph(s) from ${event.iconFonts.length} font(s) detected.`);\n }\n }\n\n // Build summary\n const summaryParts: string[] = [];\n summaryParts.push(`${event.images.length} images`);\n summaryParts.push(`${event.inlineSVGs.length} inline SVGs`);\n const bgFrames = event.backgroundSprites.reduce((sum, s) => sum + s.frames.length, 0);\n if (bgFrames > 0) summaryParts.push(`${bgFrames} CSS sprite frames`);\n if (event.svgSprites.length > 0) summaryParts.push(`${event.svgSprites.length} SVG symbols`);\n if (event.maskSprites.length > 0) {\n const maskFrames = event.maskSprites.reduce((sum, s) => sum + s.frames.length, 0);\n summaryParts.push(`${maskFrames} mask sprite frames`);\n }\n const totalGlyphs = event.iconFonts.reduce((sum, f) => sum + f.glyphs.length, 0);\n if (totalGlyphs > 0) summaryParts.push(`${totalGlyphs} icon font glyphs`);\n summaryParts.push(`${event.totalAssets} total assets`);\n\n const response = {\n summary: summaryParts.join(', ') + '.',\n data,\n issues,\n metadata: {\n timeRange: { from: event.timestamp, to: event.timestamp },\n eventCount: 1,\n sessionId: event.sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type { ComputedStyleEntry } from '@runtimescope/collector';\n\n// Properties that matter most for visual fidelity\nconst VISUAL_PROPERTIES = [\n 'color', 'background-color', 'border-color', 'border-radius',\n 'font-family', 'font-size', 'font-weight', 'line-height', 'letter-spacing',\n 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'width', 'height', 'display', 'position', 'gap',\n 'flex-direction', 'justify-content', 'align-items',\n 'box-shadow', 'text-shadow', 'opacity', 'border-width', 'border-style',\n 'text-align', 'text-transform', 'text-decoration', 'overflow',\n 'grid-template-columns', 'grid-template-rows',\n];\n\ninterface StyleDiffEntry {\n property: string;\n sourceValue: string;\n targetValue: string;\n match: boolean;\n delta?: string; // for numeric values, the difference\n}\n\nexport function registerReconStyleDiffTools(server: McpServer, store: EventStore): void {\n server.tool(\n 'get_style_diff',\n 'Compare computed styles between two captured element snapshots to check how closely a recreation matches the original. Compares two selectors from stored computed style events and reports property-by-property differences with a match percentage. Use this to verify UI recreation fidelity.',\n {\n source_selector: z\n .string()\n .describe('CSS selector for the source/original element'),\n target_selector: z\n .string()\n .describe('CSS selector for the target/recreation element'),\n properties: z\n .enum(['visual', 'all'])\n .optional()\n .default('visual')\n .describe('\"visual\" compares only visually-significant properties (colors, typography, spacing, layout). \"all\" compares everything.'),\n specific_properties: z\n .array(z.string())\n .optional()\n .describe('Specific CSS property names to compare (overrides properties group)'),\n },\n async ({ source_selector, target_selector, properties, specific_properties }) => {\n const events = store.getReconComputedStyles();\n const sessions = store.getSessionInfo();\n const sessionId = sessions[0]?.sessionId ?? null;\n\n // Find the styles for each selector\n const sourceEvent = events.find((e) =>\n e.entries.some((entry) => entry.selector === source_selector),\n );\n const targetEvent = events.find((e) =>\n e.entries.some((entry) => entry.selector === target_selector),\n );\n\n if (!sourceEvent || !targetEvent) {\n const missing: string[] = [];\n if (!sourceEvent) missing.push(`source \"${source_selector}\"`);\n if (!targetEvent) missing.push(`target \"${target_selector}\"`);\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: `Missing computed styles for ${missing.join(' and ')}. Capture computed styles for both selectors first using get_computed_styles with force_refresh=true.`,\n data: null,\n issues: [`No captured styles for: ${missing.join(', ')}`],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId },\n }, null, 2),\n }],\n };\n }\n\n const sourceEntry = sourceEvent.entries.find((e) => e.selector === source_selector)!;\n const targetEntry = targetEvent.entries.find((e) => e.selector === target_selector)!;\n\n // Determine which properties to compare\n let propsToCompare: string[];\n if (specific_properties && specific_properties.length > 0) {\n propsToCompare = specific_properties;\n } else if (properties === 'visual') {\n propsToCompare = VISUAL_PROPERTIES;\n } else {\n // All properties present in either source or target\n propsToCompare = Array.from(\n new Set([...Object.keys(sourceEntry.styles), ...Object.keys(targetEntry.styles)]),\n );\n }\n\n // Compare\n const diffs: StyleDiffEntry[] = [];\n let matchCount = 0;\n let diffCount = 0;\n\n for (const prop of propsToCompare) {\n const sourceVal = sourceEntry.styles[prop] ?? '(not set)';\n const targetVal = targetEntry.styles[prop] ?? '(not set)';\n const match = normalizeValue(sourceVal) === normalizeValue(targetVal);\n\n if (match) matchCount++;\n else diffCount++;\n\n const entry: StyleDiffEntry = { property: prop, sourceValue: sourceVal, targetValue: targetVal, match };\n\n // Calculate numeric delta for px/rem/em values\n if (!match) {\n const sourceNum = parseNumericValue(sourceVal);\n const targetNum = parseNumericValue(targetVal);\n if (sourceNum !== null && targetNum !== null) {\n const diff = targetNum - sourceNum;\n entry.delta = `${diff > 0 ? '+' : ''}${diff.toFixed(1)}px`;\n }\n }\n\n diffs.push(entry);\n }\n\n const matchPercentage = propsToCompare.length > 0\n ? Math.round((matchCount / propsToCompare.length) * 100)\n : 100;\n\n const issues: string[] = [];\n // Highlight the most significant differences\n const significantDiffs = diffs.filter((d) => !d.match);\n if (significantDiffs.length > 0) {\n const topDiffs = significantDiffs.slice(0, 10);\n for (const d of topDiffs) {\n issues.push(`${d.property}: \"${d.sourceValue}\" → \"${d.targetValue}\"${d.delta ? ` (${d.delta})` : ''}`);\n }\n if (significantDiffs.length > 10) {\n issues.push(`...and ${significantDiffs.length - 10} more differences.`);\n }\n }\n\n const response = {\n summary: `Style comparison: ${matchPercentage}% match (${matchCount}/${propsToCompare.length} properties). ${diffCount} difference(s) between \"${source_selector}\" and \"${target_selector}\".`,\n data: {\n sourceSelector: source_selector,\n targetSelector: target_selector,\n matchPercentage,\n totalProperties: propsToCompare.length,\n matches: matchCount,\n differences: diffCount,\n diffs: diffs.filter((d) => !d.match), // Only return differences\n matchingProperties: diffs.filter((d) => d.match).map((d) => d.property),\n },\n issues,\n metadata: {\n timeRange: {\n from: Math.min(sourceEvent.timestamp, targetEvent.timestamp),\n to: Math.max(sourceEvent.timestamp, targetEvent.timestamp),\n },\n eventCount: 2,\n sessionId,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n\nfunction normalizeValue(value: string): string {\n // Normalize whitespace and case for comparison\n return value.trim().toLowerCase().replace(/\\s+/g, ' ');\n}\n\nfunction parseNumericValue(value: string): number | null {\n const match = value.match(/^(-?[\\d.]+)\\s*(px|rem|em|%)$/);\n if (!match) return null;\n const num = parseFloat(match[1]);\n // Convert rem/em to px approximation (assume 16px base)\n const unit = match[2];\n if (unit === 'rem' || unit === 'em') return num * 16;\n return num;\n}\n","import { readFileSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { TechnologyDatabase, detect } from '@runtimescope/extension';\nimport type { TechDetectionResult, DetectionSignals } from '@runtimescope/extension';\nimport type { RuntimeEvent } from '@runtimescope/collector';\nimport {\n collectDetectionSignals,\n extractJsGlobalPaths,\n extractDomSelectors,\n} from './signal-collector.js';\nimport {\n collectDesignTokens,\n collectLayoutTree,\n collectAccessibility,\n collectFonts,\n collectAssets,\n collectComputedStyles,\n collectElementSnapshot,\n} from './recon-collectors.js';\nimport type { RawComputedStyles, RawElementSnapshot } from './recon-collectors.js';\nimport { buildReconEvents } from './event-builder.js';\n\nexport interface ScanOptions {\n viewportWidth?: number;\n viewportHeight?: number;\n waitFor?: 'load' | 'networkidle' | 'domcontentloaded';\n timeout?: number;\n}\n\nexport interface ScanResult {\n url: string;\n title: string;\n techStack: TechDetectionResult[];\n events: RuntimeEvent[];\n summary: string;\n scanDurationMs: number;\n}\n\n/**\n * PlaywrightScanner — orchestrates headless browser scans.\n * Lazily loads Playwright and the technology database.\n * Reuses the browser instance across scans for performance.\n */\nexport class PlaywrightScanner {\n private db: TechnologyDatabase | null = null;\n private jsGlobalPaths: string[] = [];\n private domSelectors: string[] = [];\n private browser: unknown = null;\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private static IDLE_TIMEOUT = 60_000; // Close browser after 60s idle\n private lastScannedUrl: string | null = null;\n\n /**\n * Lazily load the technology database.\n */\n private ensureDb(): TechnologyDatabase {\n if (this.db) return this.db;\n\n // Resolve path to the data files in @runtimescope/extension\n const __dirname = dirname(fileURLToPath(import.meta.url));\n // Try multiple possible paths for the data files\n const possiblePaths = [\n resolve(__dirname, '../../../node_modules/@runtimescope/extension/src/data'),\n resolve(__dirname, '../../extension/src/data'),\n ];\n\n let techData: Record<string, unknown> | null = null;\n let catData: Record<string, unknown> | null = null;\n\n for (const basePath of possiblePaths) {\n try {\n techData = JSON.parse(readFileSync(resolve(basePath, 'technologies.json'), 'utf-8'));\n catData = JSON.parse(readFileSync(resolve(basePath, 'categories.json'), 'utf-8'));\n break;\n } catch {\n continue;\n }\n }\n\n if (!techData || !catData) {\n throw new Error('Could not load technology database. Ensure @runtimescope/extension is built.');\n }\n\n this.db = new TechnologyDatabase(techData as Record<string, never>, catData as Record<string, never>);\n\n // Pre-extract signals for the detection engine\n const allTechs = this.db.getAll();\n this.jsGlobalPaths = extractJsGlobalPaths(allTechs);\n this.domSelectors = extractDomSelectors(allTechs);\n\n console.error(`[RuntimeScope] Scanner loaded: ${this.db.size} technologies, ${this.jsGlobalPaths.length} JS paths, ${this.domSelectors.length} DOM selectors`);\n\n return this.db;\n }\n\n /**\n * Lazily launch or reuse a Chromium browser.\n */\n private async ensureBrowser(): Promise<{ chromium: unknown; browser: unknown }> {\n // Reset idle timer\n if (this.idleTimer) {\n clearTimeout(this.idleTimer);\n this.idleTimer = null;\n }\n\n // Dynamic import — Playwright is only loaded when scan_website is actually called\n const pw = await import('playwright');\n\n if (!this.browser || !(this.browser as { isConnected(): boolean }).isConnected()) {\n this.browser = await pw.chromium.launch({ headless: true });\n console.error('[RuntimeScope] Scanner: Chromium launched');\n }\n\n // Set idle auto-close\n this.idleTimer = setTimeout(() => {\n this.shutdown().catch(() => {});\n }, PlaywrightScanner.IDLE_TIMEOUT);\n\n return { chromium: pw.chromium, browser: this.browser };\n }\n\n /**\n * Scan a website: collect all signals, detect tech stack, build recon events.\n */\n async scan(url: string, options: ScanOptions = {}): Promise<ScanResult> {\n const startTime = Date.now();\n const {\n viewportWidth = 1280,\n viewportHeight = 720,\n waitFor = 'networkidle',\n timeout = 60_000,\n } = options;\n\n const db = this.ensureDb();\n const { browser } = await this.ensureBrowser();\n const br = browser as import('playwright').Browser;\n\n // Create a fresh context and page\n const context = await br.newContext({\n viewport: { width: viewportWidth, height: viewportHeight },\n userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',\n });\n\n const page = await context.newPage();\n\n try {\n // Capture main document response headers\n let mainResponse: import('playwright').Response | null = null;\n page.on('response', (response) => {\n if (!mainResponse && response.request().resourceType() === 'document') {\n mainResponse = response;\n }\n });\n\n // Navigate\n await page.goto(url, {\n waitUntil: waitFor,\n timeout,\n });\n\n const title = await page.title();\n const sessionId = `scan-${Date.now()}`;\n\n // Collect stylesheet hrefs (needed for event builder)\n const stylesheetHrefs = await page.evaluate(() =>\n Array.from(document.querySelectorAll('link[rel=\"stylesheet\"]')).map((el) => el.getAttribute('href') || ''),\n );\n\n // Run collections in parallel\n const [signals, tokens, layout, a11y, fonts, assets] = await Promise.all([\n collectDetectionSignals(page, mainResponse, this.jsGlobalPaths, this.domSelectors),\n collectDesignTokens(page),\n collectLayoutTree(page),\n collectAccessibility(page),\n collectFonts(page),\n collectAssets(page),\n ]);\n\n // Run tech stack detection\n const techStack = detect(signals, db);\n\n // Build recon events\n const events = buildReconEvents(\n url,\n title,\n sessionId,\n techStack,\n tokens,\n layout,\n a11y,\n fonts,\n assets,\n { width: viewportWidth, height: viewportHeight },\n signals.meta || {},\n signals.scriptSrc || [],\n stylesheetHrefs,\n );\n\n // Build summary\n const topTechs = techStack.slice(0, 10).map((t) => `${t.name}${t.version ? ' ' + t.version : ''} (${t.confidence}%)`);\n const summaryParts = [\n `Scanned: ${title || url}`,\n `Tech stack: ${topTechs.join(', ') || 'none detected'}`,\n `Design: ${tokens.customProperties.length} CSS vars, ${tokens.colors.length} colors, ${tokens.typography.length} type combos`,\n `Layout: ${layout.totalElements} elements, depth ${layout.maxDepth}`,\n `Fonts: ${fonts.fontFaces.length} faces, ${fonts.fontsUsed.length} used`,\n `Assets: ${assets.images.length} images, ${assets.inlineSVGs.length} SVGs, ${assets.totalAssets} total`,\n `Accessibility: ${a11y.headings.length} headings, ${a11y.landmarks.length} landmarks, ${a11y.issues.length} issues`,\n ];\n\n const scanDurationMs = Date.now() - startTime;\n\n this.lastScannedUrl = page.url();\n\n return {\n url: page.url(),\n title,\n techStack,\n events,\n summary: summaryParts.join('. ') + `. Scan took ${scanDurationMs}ms.`,\n scanDurationMs,\n };\n } finally {\n await context.close();\n }\n }\n\n /**\n * Get the last scanned URL (so tools know a scan was performed).\n */\n getLastScannedUrl(): string | null {\n return this.lastScannedUrl;\n }\n\n /**\n * On-demand: query computed styles for a selector on a previously scanned URL.\n * Opens a fresh page, navigates, collects, closes.\n */\n async queryComputedStyles(\n url: string,\n selector: string,\n propertyFilter?: string[],\n ): Promise<RawComputedStyles> {\n const { browser } = await this.ensureBrowser();\n const br = browser as import('playwright').Browser;\n const context = await br.newContext({\n viewport: { width: 1280, height: 720 },\n });\n const page = await context.newPage();\n try {\n await page.goto(url, { waitUntil: 'networkidle', timeout: 60_000 });\n return await collectComputedStyles(page, selector, propertyFilter);\n } finally {\n await context.close();\n }\n }\n\n /**\n * On-demand: query element snapshot for a selector on a previously scanned URL.\n * Opens a fresh page, navigates, collects, closes.\n */\n async queryElementSnapshot(\n url: string,\n selector: string,\n depth = 5,\n ): Promise<RawElementSnapshot | null> {\n const { browser } = await this.ensureBrowser();\n const br = browser as import('playwright').Browser;\n const context = await br.newContext({\n viewport: { width: 1280, height: 720 },\n });\n const page = await context.newPage();\n try {\n await page.goto(url, { waitUntil: 'networkidle', timeout: 60_000 });\n return await collectElementSnapshot(page, selector, depth);\n } finally {\n await context.close();\n }\n }\n\n /**\n * Shutdown: close browser if open.\n */\n async shutdown(): Promise<void> {\n if (this.idleTimer) {\n clearTimeout(this.idleTimer);\n this.idleTimer = null;\n }\n if (this.browser) {\n try {\n await (this.browser as import('playwright').Browser).close();\n } catch {\n // Already closed\n }\n this.browser = null;\n console.error('[RuntimeScope] Scanner: Chromium closed');\n }\n }\n}\n","import type { Page, Response } from 'playwright';\nimport type { DetectionSignals, DomSignals, DomElementResult } from '@runtimescope/extension';\n\n/**\n * Collect DetectionSignals from a Playwright page for the tech stack detection engine.\n * This runs multiple page.evaluate calls to extract all signal types.\n */\nexport async function collectDetectionSignals(\n page: Page,\n mainResponse: Response | null,\n jsGlobalPaths: string[],\n domSelectors: string[],\n): Promise<DetectionSignals> {\n const url = page.url();\n\n // 1. Headers from the main document response\n const headers: Record<string, string> = {};\n if (mainResponse) {\n const allHeaders = await mainResponse.allHeaders();\n for (const [key, value] of Object.entries(allHeaders)) {\n headers[key.toLowerCase()] = value;\n }\n }\n\n // 2. Cookies\n const cookies: Record<string, string> = {};\n const rawCookies = await page.context().cookies();\n for (const c of rawCookies) {\n cookies[c.name] = c.value;\n }\n\n // 3-6: Meta tags, script srcs, inline scripts, CSS — batch in one evaluate\n const pageSignals = await page.evaluate(() => {\n // Meta tags\n const meta: Record<string, string> = {};\n document.querySelectorAll('meta[name],meta[property],meta[http-equiv]').forEach((el) => {\n const name = el.getAttribute('name') || el.getAttribute('property') || el.getAttribute('http-equiv');\n const content = el.getAttribute('content');\n if (name && content) meta[name.toLowerCase()] = content;\n });\n\n // Script src URLs\n const scriptSrc: string[] = [];\n document.querySelectorAll('script[src]').forEach((el) => {\n const src = el.getAttribute('src');\n if (src) scriptSrc.push(src);\n });\n\n // Inline script content (limited to first 500 chars each, max 50 scripts)\n const scripts: string[] = [];\n document.querySelectorAll('script:not([src])').forEach((el) => {\n const text = el.textContent?.trim();\n if (text && scripts.length < 50) {\n scripts.push(text.slice(0, 500));\n }\n });\n\n // CSS: custom properties from :root + <style> tag contents\n const css: string[] = [];\n const rootStyles = getComputedStyle(document.documentElement);\n const cssVarNames: string[] = [];\n for (let i = 0; i < rootStyles.length; i++) {\n const prop = rootStyles[i];\n if (prop.startsWith('--')) cssVarNames.push(prop);\n }\n if (cssVarNames.length > 0) {\n css.push(cssVarNames.map((v) => `${v}: ${rootStyles.getPropertyValue(v)}`).join('; '));\n }\n document.querySelectorAll('style').forEach((el) => {\n const text = el.textContent?.trim();\n if (text && css.length < 20) css.push(text.slice(0, 2000));\n });\n\n return { meta, scriptSrc, scripts, css };\n });\n\n // 7. HTML source (full page, limited to 50KB for pattern matching)\n const fullHtml = await page.content();\n const html = fullHtml.slice(0, 50_000);\n\n // 8. JS globals — evaluate a batch of known paths\n const js = await page.evaluate((paths: string[]) => {\n const results: Record<string, string> = {};\n for (const path of paths) {\n try {\n const parts = path.split('.');\n let current: unknown = window;\n for (const part of parts) {\n if (current == null) break;\n current = (current as Record<string, unknown>)[part];\n }\n if (current !== undefined) {\n results[path] = typeof current === 'string' ? current\n : typeof current === 'number' ? String(current)\n : '';\n }\n } catch {\n // Skip inaccessible properties\n }\n }\n return results;\n }, jsGlobalPaths);\n\n // 9. DOM selectors — batch query\n const dom = await page.evaluate((selectors: string[]) => {\n const results: Record<string, Array<{\n exists: boolean;\n attributes: Record<string, string>;\n properties: Record<string, string>;\n text: string;\n }>> = {};\n\n for (const selector of selectors) {\n try {\n const elements = document.querySelectorAll(selector);\n if (elements.length === 0) continue;\n\n const elResults: Array<{\n exists: boolean;\n attributes: Record<string, string>;\n properties: Record<string, string>;\n text: string;\n }> = [];\n\n // Only process first 3 matches per selector\n const limit = Math.min(elements.length, 3);\n for (let i = 0; i < limit; i++) {\n const el = elements[i];\n const attributes: Record<string, string> = {};\n for (const attr of el.attributes) {\n attributes[attr.name] = attr.value;\n }\n\n // Check common DOM properties used by detection\n const properties: Record<string, string> = {};\n const propsToCheck = ['_reactRootContainer', '__vue__', '__svelte', 'ng-version'];\n for (const prop of propsToCheck) {\n if (prop in el) {\n properties[prop] = String((el as unknown as Record<string, unknown>)[prop] ?? '');\n }\n }\n\n elResults.push({\n exists: true,\n attributes,\n properties,\n text: (el.textContent || '').trim().slice(0, 200),\n });\n }\n\n results[selector] = elResults;\n } catch {\n // Invalid selector or access error — skip\n }\n }\n\n return results;\n }, domSelectors) as DomSignals;\n\n return {\n url,\n headers,\n cookies,\n meta: pageSignals.meta,\n scriptSrc: pageSignals.scriptSrc,\n scripts: pageSignals.scripts,\n html,\n css: pageSignals.css,\n js,\n dom,\n // xhr: not collected in one-shot scan (would need request interception over time)\n };\n}\n\n/**\n * Extract all unique JS global paths from the technology database entries.\n */\nexport function extractJsGlobalPaths(\n technologies: Array<{ js?: Record<string, unknown> }>,\n): string[] {\n const paths = new Set<string>();\n for (const tech of technologies) {\n if (tech.js) {\n for (const path of Object.keys(tech.js)) {\n paths.add(path);\n }\n }\n }\n return Array.from(paths);\n}\n\n/**\n * Extract all unique DOM selectors from the technology database entries.\n */\nexport function extractDomSelectors(\n technologies: Array<{ dom?: Record<string, unknown> }>,\n): string[] {\n const selectors = new Set<string>();\n for (const tech of technologies) {\n if (tech.dom) {\n for (const selector of Object.keys(tech.dom)) {\n selectors.add(selector);\n }\n }\n }\n return Array.from(selectors);\n}\n","import type { Page } from 'playwright';\n\n// ============================================================\n// Raw data types returned from page.evaluate\n// ============================================================\n\nexport interface RawDesignTokens {\n customProperties: Array<{ name: string; value: string; source: string }>;\n colors: Array<{ value: string; hex: string; usageCount: number; properties: string[]; sampleSelectors: string[] }>;\n typography: Array<{ fontFamily: string; fontSize: string; fontWeight: string; lineHeight: string; letterSpacing: string; usageCount: number; sampleSelectors: string[] }>;\n spacing: Array<{ value: string; pixels: number; usageCount: number; properties: string[] }>;\n borderRadii: Array<{ value: string; usageCount: number }>;\n boxShadows: Array<{ value: string; usageCount: number }>;\n cssArchitecture: string;\n classNamingPatterns: string[];\n sampleClassNames: string[];\n}\n\nexport interface RawLayoutNode {\n tag: string;\n id?: string;\n classList: string[];\n dataAttributes: Record<string, string>;\n role?: string;\n ariaLabel?: string;\n boundingRect: { x: number; y: number; width: number; height: number };\n display: string;\n position: string;\n flexDirection?: string;\n justifyContent?: string;\n alignItems?: string;\n gridTemplateColumns?: string;\n gridTemplateRows?: string;\n gap?: string;\n children: RawLayoutNode[];\n childCount: number;\n textContent?: string;\n}\n\nexport interface RawLayoutTree {\n viewport: { width: number; height: number };\n scrollHeight: number;\n tree: RawLayoutNode;\n totalElements: number;\n maxDepth: number;\n}\n\nexport interface RawAccessibility {\n headings: Array<{ level: number; text: string; selector: string }>;\n landmarks: Array<{ role: string; label?: string; selector: string }>;\n formFields: Array<{ tag: string; type?: string; name?: string; label?: string; required: boolean; selector: string }>;\n links: Array<{ tag: string; text: string; href: string; selector: string }>;\n buttons: Array<{ tag: string; text: string; role?: string; selector: string }>;\n images: Array<{ src: string; alt: string; hasAlt: boolean; selector: string }>;\n issues: string[];\n}\n\nexport interface RawFonts {\n fontFaces: Array<{ family: string; weight: string; style: string; src: string; display?: string }>;\n fontsUsed: Array<{ family: string; weight: string; style: string; usageCount: number; sampleSelectors: string[] }>;\n iconFonts: Array<{ fontFamily: string; fontFaceUrl?: string; glyphs: Array<{ codepoint: string; pseudoElement: string; selector: string; renderedSize: number }> }>;\n loadingStrategy: string;\n}\n\nexport interface RawAssets {\n images: Array<{ src: string; alt: string; width: number; height: number; naturalWidth: number; naturalHeight: number; format: string; selector: string }>;\n inlineSVGs: Array<{ selector: string; viewBox: string; width: number; height: number; source: string }>;\n svgSprites: Array<{ id: string; viewBox: string; paths: string; referencedBy: string[] }>;\n backgroundSprites: Array<{ sheetUrl: string; sheetWidth: number; sheetHeight: number; frames: Array<{ selector: string; cropX: number; cropY: number; cropWidth: number; cropHeight: number }> }>;\n maskSprites: never[];\n iconFonts: Array<{ fontFamily: string; fontFaceUrl?: string; glyphs: Array<{ codepoint: string; pseudoElement: string; selector: string; renderedSize: number }> }>;\n totalAssets: number;\n}\n\n// ============================================================\n// Collectors\n// ============================================================\n\nexport async function collectDesignTokens(page: Page): Promise<RawDesignTokens> {\n return page.evaluate(() => {\n const rootStyle = getComputedStyle(document.documentElement);\n\n // CSS custom properties from :root\n const customProperties: Array<{ name: string; value: string; source: string }> = [];\n for (let i = 0; i < rootStyle.length; i++) {\n const prop = rootStyle[i];\n if (prop.startsWith('--')) {\n customProperties.push({ name: prop, value: rootStyle.getPropertyValue(prop).trim(), source: ':root' });\n }\n }\n\n // Sample elements for colors, typography, spacing\n const colorMap = new Map<string, { count: number; properties: Set<string>; selectors: Set<string> }>();\n const typoMap = new Map<string, { count: number; selectors: Set<string>; parsed: { fontFamily: string; fontSize: string; fontWeight: string; lineHeight: string; letterSpacing: string } }>();\n const spacingMap = new Map<string, { count: number; properties: Set<string> }>();\n const radiusMap = new Map<string, number>();\n const shadowMap = new Map<string, number>();\n\n // Sample up to 200 visible elements\n const allElements = document.querySelectorAll('body *');\n const sampleLimit = Math.min(allElements.length, 200);\n for (let i = 0; i < sampleLimit; i++) {\n const el = allElements[i];\n const elRect = el.getBoundingClientRect();\n if (elRect.width === 0 && elRect.height === 0) continue;\n\n const cs = getComputedStyle(el);\n const cls = el.getAttribute('class') || '';\n const selector = el.tagName.toLowerCase() + (cls ? '.' + cls.split(' ')[0] : '');\n\n // Colors\n for (const prop of ['color', 'background-color', 'border-color'] as const) {\n const val = cs.getPropertyValue(prop);\n if (val && val !== 'rgba(0, 0, 0, 0)' && val !== 'transparent') {\n const entry = colorMap.get(val) || { count: 0, properties: new Set(), selectors: new Set() };\n entry.count++;\n entry.properties.add(prop);\n if (entry.selectors.size < 3) entry.selectors.add(selector);\n colorMap.set(val, entry);\n }\n }\n\n // Typography\n const typoKey = `${cs.fontFamily}|${cs.fontSize}|${cs.fontWeight}|${cs.lineHeight}|${cs.letterSpacing}`;\n const typoEntry = typoMap.get(typoKey) || {\n count: 0, selectors: new Set(),\n parsed: { fontFamily: cs.fontFamily, fontSize: cs.fontSize, fontWeight: cs.fontWeight, lineHeight: cs.lineHeight, letterSpacing: cs.letterSpacing },\n };\n typoEntry.count++;\n if (typoEntry.selectors.size < 3) typoEntry.selectors.add(selector);\n typoMap.set(typoKey, typoEntry);\n\n // Spacing (padding, margin, gap)\n for (const prop of ['padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'gap'] as const) {\n const val = cs.getPropertyValue(prop);\n if (val && val !== '0px' && val !== 'normal' && val !== 'auto') {\n const entry = spacingMap.get(val) || { count: 0, properties: new Set() };\n entry.count++;\n entry.properties.add(prop.replace(/-(?:top|right|bottom|left)/, ''));\n spacingMap.set(val, entry);\n }\n }\n\n // Border radii\n const radius = cs.borderRadius;\n if (radius && radius !== '0px') {\n radiusMap.set(radius, (radiusMap.get(radius) || 0) + 1);\n }\n\n // Box shadows\n const shadow = cs.boxShadow;\n if (shadow && shadow !== 'none') {\n shadowMap.set(shadow, (shadowMap.get(shadow) || 0) + 1);\n }\n }\n\n // Convert to hex helper\n function rgbToHex(rgb: string): string {\n const match = rgb.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n if (!match) return rgb;\n return '#' + [match[1], match[2], match[3]]\n .map((n) => parseInt(n).toString(16).padStart(2, '0'))\n .join('');\n }\n\n const colors = Array.from(colorMap.entries())\n .map(([value, data]) => ({\n value, hex: rgbToHex(value), usageCount: data.count,\n properties: Array.from(data.properties), sampleSelectors: Array.from(data.selectors),\n }))\n .sort((a, b) => b.usageCount - a.usageCount)\n .slice(0, 50);\n\n const typography = Array.from(typoMap.values())\n .map((data) => ({\n ...data.parsed, usageCount: data.count, sampleSelectors: Array.from(data.selectors),\n }))\n .sort((a, b) => b.usageCount - a.usageCount)\n .slice(0, 30);\n\n const spacing = Array.from(spacingMap.entries())\n .map(([value, data]) => ({\n value, pixels: parseFloat(value) || 0, usageCount: data.count,\n properties: Array.from(data.properties),\n }))\n .sort((a, b) => b.usageCount - a.usageCount)\n .slice(0, 30);\n\n const borderRadii = Array.from(radiusMap.entries())\n .map(([value, count]) => ({ value, usageCount: count }))\n .sort((a, b) => b.usageCount - a.usageCount);\n\n const boxShadows = Array.from(shadowMap.entries())\n .map(([value, count]) => ({ value, usageCount: count }))\n .sort((a, b) => b.usageCount - a.usageCount);\n\n // CSS architecture detection\n const sampleClassNames: string[] = [];\n const classCounts = { tailwind: 0, bem: 0, modules: 0, atomic: 0, vanilla: 0 };\n document.querySelectorAll('[class]').forEach((el) => {\n if (sampleClassNames.length < 20) {\n for (const c of el.classList) sampleClassNames.push(c);\n }\n for (const c of el.classList) {\n if (/^(flex|grid|text-|bg-|p-|m-|w-|h-|gap-|items-|justify-)/.test(c)) classCounts.tailwind++;\n else if (/^[a-z]+--.+/.test(c) || /__/.test(c)) classCounts.bem++;\n else if (/^[a-zA-Z]+_[a-zA-Z0-9_]{5,}$/.test(c)) classCounts.modules++;\n }\n });\n\n let cssArchitecture = 'vanilla';\n const classNamingPatterns: string[] = [];\n if (classCounts.tailwind > 10) { cssArchitecture = 'tailwind'; classNamingPatterns.push('tailwind utilities'); }\n else if (classCounts.bem > 5) { cssArchitecture = 'bem'; classNamingPatterns.push('BEM naming'); }\n else if (classCounts.modules > 5) { cssArchitecture = 'css-modules'; classNamingPatterns.push('CSS Modules'); }\n\n return {\n customProperties, colors, typography, spacing, borderRadii, boxShadows,\n cssArchitecture, classNamingPatterns, sampleClassNames: sampleClassNames.slice(0, 20),\n };\n });\n}\n\nexport async function collectLayoutTree(page: Page, maxDepth = 6): Promise<RawLayoutTree> {\n return page.evaluate((maxD: number) => {\n function walkNode(el: Element, depth: number): RawLayoutNode | null {\n if (depth > maxD) return null;\n const cs = getComputedStyle(el);\n if (cs.display === 'none') return null;\n\n const rect = el.getBoundingClientRect();\n const tag = el.tagName.toLowerCase();\n\n const dataAttributes: Record<string, string> = {};\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-')) dataAttributes[attr.name] = attr.value;\n }\n\n const children: RawLayoutNode[] = [];\n let childCount = 0;\n for (const child of el.children) {\n childCount++;\n if (children.length < 20) { // Limit children per level\n const childNode = walkNode(child, depth + 1);\n if (childNode) children.push(childNode);\n }\n }\n\n const node: RawLayoutNode = {\n tag,\n classList: Array.from(el.classList),\n dataAttributes,\n boundingRect: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) },\n display: cs.display,\n position: cs.position,\n children,\n childCount,\n };\n\n if (el.id) node.id = el.id;\n if (el.getAttribute('role')) node.role = el.getAttribute('role')!;\n if (el.getAttribute('aria-label')) node.ariaLabel = el.getAttribute('aria-label')!;\n\n // Flex props\n if (cs.display.includes('flex')) {\n node.flexDirection = cs.flexDirection;\n node.justifyContent = cs.justifyContent;\n node.alignItems = cs.alignItems;\n }\n // Grid props\n if (cs.display.includes('grid')) {\n node.gridTemplateColumns = cs.gridTemplateColumns;\n node.gridTemplateRows = cs.gridTemplateRows;\n node.gap = cs.gap;\n }\n // Text content for leaf-ish nodes\n if (el.children.length === 0 && el.textContent) {\n node.textContent = el.textContent.trim().slice(0, 100);\n }\n\n return node;\n }\n\n const body = document.body;\n const tree = walkNode(body, 0) || {\n tag: 'body', classList: [], dataAttributes: {},\n boundingRect: { x: 0, y: 0, width: 0, height: 0 },\n display: 'block', position: 'static', children: [], childCount: 0,\n };\n\n let totalElements = 0;\n function countDepth(node: RawLayoutNode, d: number): number {\n totalElements++;\n let max = d;\n for (const child of node.children) {\n max = Math.max(max, countDepth(child, d + 1));\n }\n return max;\n }\n const maxDepth = countDepth(tree, 0);\n\n return {\n viewport: { width: window.innerWidth, height: window.innerHeight },\n scrollHeight: document.documentElement.scrollHeight,\n tree,\n totalElements,\n maxDepth,\n };\n\n // Type assertion for the recursive type used inside evaluate\n type RawLayoutNode = {\n tag: string; id?: string; classList: string[]; dataAttributes: Record<string, string>;\n role?: string; ariaLabel?: string;\n boundingRect: { x: number; y: number; width: number; height: number };\n display: string; position: string;\n flexDirection?: string; justifyContent?: string; alignItems?: string;\n gridTemplateColumns?: string; gridTemplateRows?: string; gap?: string;\n children: RawLayoutNode[]; childCount: number; textContent?: string;\n };\n }, maxDepth);\n}\n\nexport async function collectAccessibility(page: Page): Promise<RawAccessibility> {\n return page.evaluate(() => {\n function getSelector(el: Element): string {\n if (el.id) return `#${el.id}`;\n const tag = el.tagName.toLowerCase();\n const cls = el.classList[0];\n return cls ? `${tag}.${cls}` : tag;\n }\n\n // Headings\n const headings: Array<{ level: number; text: string; selector: string }> = [];\n document.querySelectorAll('h1,h2,h3,h4,h5,h6').forEach((el) => {\n headings.push({\n level: parseInt(el.tagName[1]),\n text: (el.textContent || '').trim().slice(0, 100),\n selector: getSelector(el),\n });\n });\n\n // Landmarks\n const landmarks: Array<{ role: string; label?: string; selector: string }> = [];\n const landmarkEls = document.querySelectorAll('nav,main,aside,header,footer,section[aria-label],form[aria-label],[role=\"navigation\"],[role=\"main\"],[role=\"complementary\"],[role=\"banner\"],[role=\"contentinfo\"],[role=\"search\"]');\n landmarkEls.forEach((el) => {\n const role = el.getAttribute('role') || el.tagName.toLowerCase();\n const label = el.getAttribute('aria-label') || el.getAttribute('aria-labelledby') || undefined;\n landmarks.push({ role, label, selector: getSelector(el) });\n });\n\n // Form fields\n const formFields: Array<{ tag: string; type?: string; name?: string; label?: string; required: boolean; selector: string }> = [];\n document.querySelectorAll('input,select,textarea').forEach((el) => {\n const input = el as HTMLInputElement;\n const id = input.id;\n const label = id ? document.querySelector(`label[for=\"${id}\"]`)?.textContent?.trim() : undefined;\n formFields.push({\n tag: el.tagName.toLowerCase(),\n type: input.type || undefined,\n name: input.name || undefined,\n label: label || input.getAttribute('aria-label') || input.placeholder || undefined,\n required: input.required,\n selector: getSelector(el),\n });\n });\n\n // Links (sample first 50)\n const links: Array<{ tag: string; text: string; href: string; selector: string }> = [];\n document.querySelectorAll('a[href]').forEach((el) => {\n if (links.length >= 50) return;\n const a = el as HTMLAnchorElement;\n links.push({\n tag: 'a',\n text: (a.textContent || '').trim().slice(0, 80),\n href: a.getAttribute('href') || '',\n selector: getSelector(el),\n });\n });\n\n // Buttons\n const buttons: Array<{ tag: string; text: string; role?: string; selector: string }> = [];\n document.querySelectorAll('button,[role=\"button\"],input[type=\"submit\"],input[type=\"button\"]').forEach((el) => {\n buttons.push({\n tag: el.tagName.toLowerCase(),\n text: (el.textContent || (el as HTMLInputElement).value || '').trim().slice(0, 80),\n role: el.getAttribute('role') || undefined,\n selector: getSelector(el),\n });\n });\n\n // Images\n const images: Array<{ src: string; alt: string; hasAlt: boolean; selector: string }> = [];\n document.querySelectorAll('img').forEach((el) => {\n const img = el as HTMLImageElement;\n images.push({\n src: img.src,\n alt: img.alt,\n hasAlt: img.hasAttribute('alt') && img.alt.length > 0,\n selector: getSelector(el),\n });\n });\n\n // Issue detection\n const issues: string[] = [];\n // Check heading hierarchy\n let prevLevel = 0;\n for (const h of headings) {\n if (h.level > prevLevel + 1 && prevLevel > 0) {\n issues.push(`Heading level skip: h${prevLevel} → h${h.level}`);\n }\n prevLevel = h.level;\n }\n if (!landmarks.some((l) => l.role === 'main')) {\n issues.push('No <main> landmark found');\n }\n const missingAlt = images.filter((i) => !i.hasAlt);\n if (missingAlt.length > 0) {\n issues.push(`${missingAlt.length} image(s) missing alt text`);\n }\n\n return { headings, landmarks, formFields, links, buttons, images, issues };\n });\n}\n\nexport async function collectFonts(page: Page): Promise<RawFonts> {\n return page.evaluate(() => {\n // Font faces from document.fonts API\n const fontFaces: Array<{ family: string; weight: string; style: string; src: string; display?: string }> = [];\n try {\n for (const face of document.fonts) {\n fontFaces.push({\n family: face.family.replace(/\"/g, ''),\n weight: face.weight,\n style: face.style,\n src: '', // Not accessible from API\n display: face.display || undefined,\n });\n }\n } catch {\n // document.fonts may not be available\n }\n\n // Also check @font-face rules in stylesheets\n try {\n for (const sheet of document.styleSheets) {\n try {\n for (const rule of sheet.cssRules) {\n if (rule instanceof CSSFontFaceRule) {\n const style = rule.style;\n const family = style.getPropertyValue('font-family').replace(/[\"']/g, '');\n if (family && !fontFaces.some((f) => f.family === family && f.weight === style.getPropertyValue('font-weight'))) {\n fontFaces.push({\n family,\n weight: style.getPropertyValue('font-weight') || '400',\n style: style.getPropertyValue('font-style') || 'normal',\n src: style.getPropertyValue('src') || '',\n display: style.getPropertyValue('font-display') || undefined,\n });\n }\n }\n }\n } catch {\n // Cross-origin stylesheets block cssRules access\n }\n }\n } catch {\n // stylesheet access error\n }\n\n // Font usage across elements\n const fontUsageMap = new Map<string, { count: number; selectors: Set<string> }>();\n const elements = document.querySelectorAll('body *');\n const limit = Math.min(elements.length, 200);\n for (let i = 0; i < limit; i++) {\n const el = elements[i];\n const elRect = el.getBoundingClientRect();\n if (elRect.width === 0 && elRect.height === 0) continue;\n const cs = getComputedStyle(el);\n const key = `${cs.fontFamily}|${cs.fontWeight}|${cs.fontStyle}`;\n const entry = fontUsageMap.get(key) || { count: 0, selectors: new Set() };\n entry.count++;\n const cls = el.getAttribute('class') || '';\n const selector = el.tagName.toLowerCase() + (cls ? '.' + cls.split(' ')[0] : '');\n if (entry.selectors.size < 3) entry.selectors.add(selector);\n fontUsageMap.set(key, entry);\n }\n\n const fontsUsed = Array.from(fontUsageMap.entries())\n .map(([key, data]) => {\n const [family, weight, style] = key.split('|');\n return {\n family: family.split(',')[0].trim().replace(/[\"']/g, ''),\n weight, style,\n usageCount: data.count,\n sampleSelectors: Array.from(data.selectors),\n };\n })\n .sort((a, b) => b.usageCount - a.usageCount);\n\n // Loading strategy\n const strategies: string[] = [];\n const hasPreload = document.querySelector('link[rel=\"preload\"][as=\"font\"]');\n if (hasPreload) strategies.push('preloaded');\n if (fontFaces.some((f) => f.display === 'swap')) strategies.push('font-display: swap');\n if (fontFaces.some((f) => f.src.includes('woff2'))) strategies.push('woff2');\n const loadingStrategy = strategies.length > 0 ? strategies.join(' + ') : 'default';\n\n return { fontFaces, fontsUsed, iconFonts: [], loadingStrategy };\n });\n}\n\nexport async function collectAssets(page: Page): Promise<RawAssets> {\n return page.evaluate(() => {\n function getSelector(el: Element): string {\n if (el.id) return `#${el.id}`;\n const tag = el.tagName.toLowerCase();\n const cls = el.classList[0];\n return cls ? `${tag}.${cls}` : tag;\n }\n\n // Images\n const images: Array<{\n src: string; alt: string; width: number; height: number;\n naturalWidth: number; naturalHeight: number; format: string; selector: string;\n }> = [];\n document.querySelectorAll('img').forEach((el) => {\n const img = el as HTMLImageElement;\n const src = img.src;\n const ext = src.split('.').pop()?.split('?')[0]?.toLowerCase() || '';\n const format = { webp: 'webp', png: 'png', jpg: 'jpeg', jpeg: 'jpeg', gif: 'gif', svg: 'svg', avif: 'avif' }[ext] || ext;\n images.push({\n src, alt: img.alt,\n width: img.width, height: img.height,\n naturalWidth: img.naturalWidth, naturalHeight: img.naturalHeight,\n format, selector: getSelector(el),\n });\n });\n\n // Inline SVGs\n const inlineSVGs: Array<{ selector: string; viewBox: string; width: number; height: number; source: string }> = [];\n document.querySelectorAll('svg').forEach((el) => {\n const svg = el as SVGSVGElement;\n // Skip SVGs inside sprite sheets\n if (svg.closest('symbol') || svg.closest('[style*=\"display: none\"]')) return;\n const rect = svg.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return;\n inlineSVGs.push({\n selector: getSelector(el),\n viewBox: svg.getAttribute('viewBox') || '',\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n source: svg.outerHTML.slice(0, 500),\n });\n });\n\n // SVG sprites (symbol/use pattern)\n const svgSprites: Array<{ id: string; viewBox: string; paths: string; referencedBy: string[] }> = [];\n document.querySelectorAll('svg symbol[id]').forEach((el) => {\n const symbol = el as SVGSymbolElement;\n const id = symbol.id;\n const refs: string[] = [];\n document.querySelectorAll(`use[href=\"#${id}\"],use[xlink\\\\:href=\"#${id}\"]`).forEach((use) => {\n refs.push(getSelector(use.closest('svg') || use));\n });\n svgSprites.push({\n id,\n viewBox: symbol.getAttribute('viewBox') || '',\n paths: symbol.innerHTML.slice(0, 200),\n referencedBy: refs,\n });\n });\n\n // Background sprites\n const backgroundSprites: Array<{\n sheetUrl: string; sheetWidth: number; sheetHeight: number;\n frames: Array<{ selector: string; cropX: number; cropY: number; cropWidth: number; cropHeight: number }>;\n }> = [];\n const bgSpriteMap = new Map<string, Array<{ selector: string; cropX: number; cropY: number; cropWidth: number; cropHeight: number }>>();\n\n document.querySelectorAll('*').forEach((el) => {\n const cs = getComputedStyle(el);\n const bgImage = cs.backgroundImage;\n if (!bgImage || bgImage === 'none' || !bgImage.startsWith('url(')) return;\n const bgPos = cs.backgroundPosition;\n const bgSize = cs.backgroundSize;\n if (bgSize === 'cover' || bgSize === 'contain' || bgSize === 'auto') return;\n\n const urlMatch = bgImage.match(/url\\([\"']?(.+?)[\"']?\\)/);\n if (!urlMatch) return;\n const url = urlMatch[1];\n\n const rect = el.getBoundingClientRect();\n const posMatch = bgPos.match(/([-\\d.]+)px\\s+([-\\d.]+)px/);\n if (!posMatch) return;\n\n const frames = bgSpriteMap.get(url) || [];\n frames.push({\n selector: getSelector(el),\n cropX: Math.abs(parseFloat(posMatch[1])),\n cropY: Math.abs(parseFloat(posMatch[2])),\n cropWidth: Math.round(rect.width),\n cropHeight: Math.round(rect.height),\n });\n bgSpriteMap.set(url, frames);\n });\n\n for (const [url, frames] of bgSpriteMap.entries()) {\n if (frames.length >= 2) { // Only count as sprite if multiple frames\n backgroundSprites.push({ sheetUrl: url, sheetWidth: 0, sheetHeight: 0, frames });\n }\n }\n\n const totalAssets = images.length + inlineSVGs.length + svgSprites.length +\n backgroundSprites.reduce((s, b) => s + b.frames.length, 0);\n\n return {\n images, inlineSVGs, svgSprites, backgroundSprites,\n maskSprites: [] as never[], iconFonts: [], totalAssets,\n };\n });\n}\n\n// ============================================================\n// On-demand Collectors (used by tools, not the main scan pipeline)\n// ============================================================\n\nexport interface RawComputedStyles {\n selector: string;\n propertyFilter?: string[];\n entries: Array<{\n selector: string;\n matchCount: number;\n styles: Record<string, string>;\n variations: Array<{\n property: string;\n values: Array<{ value: string; count: number }>;\n }>;\n }>;\n}\n\nexport interface RawElementSnapshot {\n selector: string;\n depth: number;\n totalNodes: number;\n root: RawSnapshotNode;\n}\n\nexport interface RawSnapshotNode {\n tag: string;\n id?: string;\n classList: string[];\n attributes: Record<string, string>;\n textContent?: string;\n boundingRect: { x: number; y: number; width: number; height: number };\n computedStyles: Record<string, string>;\n children: RawSnapshotNode[];\n}\n\n/**\n * Collect computed styles for elements matching a CSS selector.\n * Runs inside Playwright's page context.\n */\nexport async function collectComputedStyles(\n page: Page,\n selector: string,\n propertyFilter?: string[],\n): Promise<RawComputedStyles> {\n return page.evaluate(\n ({ sel, propFilter }) => {\n const elements = document.querySelectorAll(sel);\n if (elements.length === 0) {\n return { selector: sel, propertyFilter: propFilter, entries: [] };\n }\n\n // Key visual/layout properties when no filter specified\n const DEFAULT_PROPS = [\n 'color', 'background-color', 'border-color',\n 'font-family', 'font-size', 'font-weight', 'font-style', 'line-height',\n 'letter-spacing', 'text-align', 'text-transform', 'text-decoration',\n 'display', 'position', 'top', 'right', 'bottom', 'left',\n 'width', 'height', 'min-width', 'max-width', 'min-height', 'max-height',\n 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'gap', 'flex-direction', 'justify-content', 'align-items', 'flex-wrap',\n 'grid-template-columns', 'grid-template-rows',\n 'border-width', 'border-style', 'border-radius',\n 'box-shadow', 'text-shadow', 'opacity', 'overflow', 'z-index',\n 'transform', 'transition', 'background-image', 'background-size',\n 'cursor', 'pointer-events',\n ];\n\n const propsToCapture = propFilter && propFilter.length > 0 ? propFilter : DEFAULT_PROPS;\n\n // Collect styles from all matching elements\n const allStyles: Record<string, string>[] = [];\n const limit = Math.min(elements.length, 50);\n for (let i = 0; i < limit; i++) {\n const cs = getComputedStyle(elements[i]);\n const styles: Record<string, string> = {};\n for (const prop of propsToCapture) {\n const val = cs.getPropertyValue(prop);\n if (val) styles[prop] = val;\n }\n allStyles.push(styles);\n }\n\n // Compute the \"first element\" styles and detect variations\n const baseStyles = allStyles[0] || {};\n const variations: Array<{\n property: string;\n values: Array<{ value: string; count: number }>;\n }> = [];\n\n if (allStyles.length > 1) {\n for (const prop of propsToCapture) {\n const valueCounts = new Map<string, number>();\n for (const s of allStyles) {\n const val = s[prop] || '';\n valueCounts.set(val, (valueCounts.get(val) || 0) + 1);\n }\n if (valueCounts.size > 1) {\n variations.push({\n property: prop,\n values: Array.from(valueCounts.entries())\n .map(([value, count]) => ({ value, count }))\n .sort((a, b) => b.count - a.count),\n });\n }\n }\n }\n\n return {\n selector: sel,\n propertyFilter: propFilter,\n entries: [{\n selector: sel,\n matchCount: elements.length,\n styles: baseStyles,\n variations,\n }],\n };\n },\n { sel: selector, propFilter: propertyFilter },\n );\n}\n\n/**\n * Collect a deep element snapshot for a CSS selector.\n * Captures structure, attributes, bounding rects, and key computed styles.\n */\nexport async function collectElementSnapshot(\n page: Page,\n selector: string,\n maxDepth = 5,\n): Promise<RawElementSnapshot | null> {\n return page.evaluate(\n ({ sel, maxD }) => {\n const rootEl = document.querySelector(sel);\n if (!rootEl) return null;\n\n const KEY_STYLES = [\n 'display', 'position', 'color', 'background-color',\n 'font-family', 'font-size', 'font-weight', 'line-height',\n 'width', 'height', 'margin', 'padding', 'border',\n 'flex-direction', 'justify-content', 'align-items', 'gap',\n 'grid-template-columns', 'grid-template-rows',\n 'border-radius', 'box-shadow', 'opacity', 'overflow', 'z-index',\n ];\n\n type SnapNode = {\n tag: string; id?: string; classList: string[];\n attributes: Record<string, string>; textContent?: string;\n boundingRect: { x: number; y: number; width: number; height: number };\n computedStyles: Record<string, string>;\n children: SnapNode[];\n };\n\n let totalNodes = 0;\n\n function walk(el: Element, depth: number): SnapNode {\n totalNodes++;\n const rect = el.getBoundingClientRect();\n const cs = getComputedStyle(el);\n\n const attributes: Record<string, string> = {};\n for (const attr of el.attributes) {\n if (!['class', 'id', 'style'].includes(attr.name)) {\n attributes[attr.name] = attr.value.slice(0, 200);\n }\n }\n\n const computedStyles: Record<string, string> = {};\n for (const prop of KEY_STYLES) {\n const val = cs.getPropertyValue(prop);\n if (val) computedStyles[prop] = val;\n }\n\n const children: SnapNode[] = [];\n if (depth < maxD) {\n const childLimit = Math.min(el.children.length, 30);\n for (let i = 0; i < childLimit; i++) {\n children.push(walk(el.children[i], depth + 1));\n }\n }\n\n const node: SnapNode = {\n tag: el.tagName.toLowerCase(),\n classList: Array.from(el.classList),\n attributes,\n boundingRect: {\n x: Math.round(rect.x), y: Math.round(rect.y),\n width: Math.round(rect.width), height: Math.round(rect.height),\n },\n computedStyles,\n children,\n };\n\n if (el.id) node.id = el.id;\n if (el.children.length === 0 && el.textContent) {\n node.textContent = el.textContent.trim().slice(0, 200);\n }\n\n return node;\n }\n\n const root = walk(rootEl, 0);\n\n return {\n selector: sel,\n depth: maxD,\n totalNodes,\n root,\n };\n },\n { sel: selector, maxD: maxDepth },\n );\n}\n","import type { TechDetectionResult } from '@runtimescope/extension';\nimport type {\n RuntimeEvent,\n ReconMetadataEvent,\n ReconDesignTokensEvent,\n ReconLayoutTreeEvent,\n ReconAccessibilityEvent,\n ReconFontsEvent,\n ReconAssetInventoryEvent,\n} from '@runtimescope/collector';\nimport type {\n RawDesignTokens,\n RawLayoutTree,\n RawAccessibility,\n RawFonts,\n RawAssets,\n} from './recon-collectors.js';\n\nfunction makeEventId(): string {\n return `evt-scan-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * Build all 6 recon events from collected scanner data.\n */\nexport function buildReconEvents(\n url: string,\n title: string,\n sessionId: string,\n techResults: TechDetectionResult[],\n tokens: RawDesignTokens,\n layout: RawLayoutTree,\n a11y: RawAccessibility,\n fonts: RawFonts,\n assets: RawAssets,\n viewport: { width: number; height: number },\n meta: Record<string, string>,\n scriptSrcs: string[],\n stylesheetHrefs: string[],\n): RuntimeEvent[] {\n const timestamp = Date.now();\n const events: RuntimeEvent[] = [];\n\n // 1. ReconMetadataEvent — tech stack + page info\n const framework = techResults.find((t) => t.categories.some((c) => c.id === 12));\n const metaFramework = techResults.find((t) =>\n t.categories.some((c) => c.id === 18 || c.id === 57) && t.name !== framework?.name,\n );\n const uiLib = techResults.find((t) => t.categories.some((c) => c.id === 66));\n const buildTool = techResults.find((t) =>\n t.categories.some((c) => c.id === 19) || t.name.match(/webpack|vite|parcel|turbopack|esbuild|rollup/i),\n );\n const hosting = techResults.find((t) =>\n t.categories.some((c) => c.id === 62 || c.id === 31) || t.name.match(/vercel|netlify|cloudflare|aws|heroku/i),\n );\n\n function toDetection(result: TechDetectionResult | undefined): { name: string; confidence: 'high' | 'medium' | 'low'; version?: string; evidence: string[] } {\n if (!result) return { name: 'unknown', confidence: 'low', evidence: [] };\n return {\n name: result.name.toLowerCase(),\n confidence: result.confidence >= 75 ? 'high' : result.confidence >= 40 ? 'medium' : 'low',\n version: result.version || undefined,\n evidence: [`Detected by scanner (confidence: ${result.confidence}%)`],\n };\n }\n\n const metadataEvent: ReconMetadataEvent = {\n eventId: makeEventId(),\n sessionId,\n timestamp,\n eventType: 'recon_metadata',\n url,\n title,\n viewport,\n documentLang: '', // Not critical for this use case\n metaTags: meta,\n techStack: {\n framework: toDetection(framework),\n metaFramework: metaFramework ? toDetection(metaFramework) : undefined,\n uiLibrary: uiLib ? toDetection(uiLib) : undefined,\n buildTool: buildTool ? toDetection(buildTool) : undefined,\n hosting: hosting ? toDetection(hosting) : undefined,\n additional: techResults\n .filter((t) => t !== framework && t !== metaFramework && t !== uiLib && t !== buildTool && t !== hosting)\n .slice(0, 20)\n .map((t) => ({\n name: t.name,\n confidence: t.confidence >= 75 ? 'high' as const : t.confidence >= 40 ? 'medium' as const : 'low' as const,\n version: t.version || undefined,\n evidence: [`${t.categories.map((c) => c.name).join(', ')}`],\n })),\n },\n externalStylesheets: stylesheetHrefs.map((href) => ({ href, crossOrigin: !href.startsWith(url) })),\n externalScripts: scriptSrcs.map((src) => ({ src, async: false, defer: false, type: 'text/javascript' })),\n preloads: [],\n };\n events.push(metadataEvent);\n\n // 2. ReconDesignTokensEvent\n const designTokensEvent: ReconDesignTokensEvent = {\n eventId: makeEventId(),\n sessionId,\n timestamp,\n eventType: 'recon_design_tokens',\n url,\n ...tokens,\n };\n events.push(designTokensEvent);\n\n // 3. ReconLayoutTreeEvent\n const layoutEvent: ReconLayoutTreeEvent = {\n eventId: makeEventId(),\n sessionId,\n timestamp,\n eventType: 'recon_layout_tree',\n url,\n viewport: layout.viewport,\n scrollHeight: layout.scrollHeight,\n tree: layout.tree,\n totalElements: layout.totalElements,\n maxDepth: layout.maxDepth,\n };\n events.push(layoutEvent);\n\n // 4. ReconAccessibilityEvent\n const a11yEvent: ReconAccessibilityEvent = {\n eventId: makeEventId(),\n sessionId,\n timestamp,\n eventType: 'recon_accessibility',\n url,\n ...a11y,\n };\n events.push(a11yEvent);\n\n // 5. ReconFontsEvent\n const fontsEvent: ReconFontsEvent = {\n eventId: makeEventId(),\n sessionId,\n timestamp,\n eventType: 'recon_fonts',\n url,\n ...fonts,\n };\n events.push(fontsEvent);\n\n // 6. ReconAssetInventoryEvent\n const assetsEvent: ReconAssetInventoryEvent = {\n eventId: makeEventId(),\n sessionId,\n timestamp,\n eventType: 'recon_asset_inventory',\n url,\n ...assets,\n };\n events.push(assetsEvent);\n\n return events;\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { EventStore } from '@runtimescope/collector';\nimport type { PlaywrightScanner } from '../scanner/index.js';\n\nconst COLLECTOR_PORT = process.env.RUNTIMESCOPE_PORT ?? '9090';\nconst HTTP_PORT = process.env.RUNTIMESCOPE_HTTP_PORT ?? '9091';\n\nexport function registerScannerTools(\n server: McpServer,\n store: EventStore,\n scanner: PlaywrightScanner,\n): void {\n // ---------- get_sdk_snippet ----------\n server.tool(\n 'get_sdk_snippet',\n 'Generate a ready-to-paste code snippet to connect any web application to RuntimeScope for live runtime monitoring. Works with ANY tech stack — React, Vue, Angular, Svelte, plain HTML, Flask/Django templates, Rails ERB, PHP, WordPress, etc. Returns the appropriate installation method based on the project type.',\n {\n app_name: z\n .string()\n .optional()\n .default('my-app')\n .describe('Name for the app in RuntimeScope (e.g., \"echo-frontend\", \"dashboard\")'),\n framework: z\n .enum(['html', 'react', 'vue', 'angular', 'svelte', 'nextjs', 'nuxt', 'flask', 'django', 'rails', 'php', 'wordpress', 'other'])\n .optional()\n .default('html')\n .describe('The framework/tech stack of the project. Use \"html\" for any plain HTML or server-rendered pages.'),\n },\n async ({ app_name, framework }) => {\n const scriptTagSnippet = `<!-- RuntimeScope — paste before </body> -->\n<script src=\"http://localhost:${HTTP_PORT}/runtimescope.js\"></script>\n<script>\n RuntimeScope.init({\n appName: '${app_name}',\n endpoint: 'ws://localhost:${COLLECTOR_PORT}',\n });\n</script>`;\n\n const npmSnippet = `// npm install @runtimescope/sdk\nimport { RuntimeScope } from '@runtimescope/sdk';\n\nRuntimeScope.init({\n appName: '${app_name}',\n endpoint: 'ws://localhost:${COLLECTOR_PORT}',\n});`;\n\n // Determine which snippet to use\n const usesNpm = ['react', 'vue', 'angular', 'svelte', 'nextjs', 'nuxt'].includes(framework);\n const primarySnippet = usesNpm ? npmSnippet : scriptTagSnippet;\n\n // Framework-specific placement hints\n const placementHints: Record<string, string> = {\n html: 'Paste the <script> tags before </body> in your HTML file(s).',\n react: 'Add the import to your entry file (src/index.tsx or src/main.tsx), before ReactDOM.render/createRoot.',\n vue: 'Add the import to your entry file (src/main.ts), before createApp().',\n angular: 'Add the import to your main.ts, before bootstrapApplication().',\n svelte: 'Add the import to your entry file (src/main.ts), before new App().',\n nextjs: 'Add the import to your app/layout.tsx or pages/_app.tsx. For App Router, use a client component wrapper.',\n nuxt: 'Create a plugin file (plugins/runtimescope.client.ts) with the init call.',\n flask: 'Add the <script> tags to your base template (templates/base.html) before </body>.',\n django: 'Add the <script> tags to your base template (templates/base.html) before </body>.',\n rails: 'Add the <script> tags to your application layout (app/views/layouts/application.html.erb) before </body>.',\n php: 'Add the <script> tags to your layout/footer file before </body>.',\n wordpress: 'Add the <script> tags to your theme\\'s footer.php before </body>, or use a custom HTML plugin.',\n other: 'Add the <script> tags to your HTML template before </body>. Works in any HTML page.',\n };\n\n const response = {\n summary: `SDK snippet for ${framework} project \"${app_name}\". ${usesNpm ? 'Uses npm import.' : 'Uses <script> tag — no build system required.'}`,\n data: {\n snippet: primarySnippet,\n placement: placementHints[framework] || placementHints.other,\n alternativeSnippet: usesNpm ? scriptTagSnippet : npmSnippet,\n alternativeNote: usesNpm\n ? 'If you prefer, you can also use a <script> tag instead of npm:'\n : 'If the project uses npm/Node.js, you can also install via:',\n requirements: [\n 'RuntimeScope MCP server must be running (it starts automatically with Claude Code)',\n `SDK bundle served at http://localhost:${HTTP_PORT}/runtimescope.js`,\n `WebSocket collector at ws://localhost:${COLLECTOR_PORT}`,\n ],\n whatItCaptures: [\n 'Network requests (fetch/XHR) with timing and headers',\n 'Console logs, warnings, and errors with stack traces',\n 'React/Vue/Svelte component renders (if applicable)',\n 'State store changes (Redux, Zustand, Pinia)',\n 'Web Vitals (LCP, FCP, CLS, TTFB, INP)',\n 'Unhandled errors and promise rejections',\n ],\n },\n issues: [],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n\n // ---------- scan_website ----------\n server.tool(\n 'scan_website',\n 'Visit a website with a headless browser and extract comprehensive data: tech stack (7,221 technologies), design tokens (colors, typography, spacing, CSS variables), layout tree (DOM with bounding rects, flex/grid), accessibility structure, fonts, and asset inventory (images, SVGs, sprites). After scanning, all recon tools (get_design_tokens, get_layout_tree, get_font_info, etc.) will return data from the scanned page. This is the primary way to analyze any website.',\n {\n url: z\n .string()\n .describe('The full URL to scan (e.g., \"https://stripe.com\")'),\n viewport_width: z\n .number()\n .optional()\n .default(1280)\n .describe('Viewport width in pixels (default: 1280)'),\n viewport_height: z\n .number()\n .optional()\n .default(720)\n .describe('Viewport height in pixels (default: 720)'),\n wait_for: z\n .enum(['load', 'networkidle', 'domcontentloaded'])\n .optional()\n .default('networkidle')\n .describe('Wait condition before scanning (default: networkidle)'),\n },\n async ({ url, viewport_width, viewport_height, wait_for }) => {\n try {\n const result = await scanner.scan(url, {\n viewportWidth: viewport_width,\n viewportHeight: viewport_height,\n waitFor: wait_for,\n });\n\n // Write all recon events to the store\n for (const event of result.events) {\n store.addEvent(event);\n }\n\n const topTech = result.techStack.slice(0, 15).map((t) => ({\n name: t.name,\n version: t.version || undefined,\n confidence: t.confidence,\n categories: t.categories.map((c) => c.name),\n }));\n\n const issues: string[] = [];\n if (result.techStack.length === 0) {\n issues.push('No technologies detected — the page may use server-rendered HTML with no identifiable framework.');\n }\n\n const response = {\n summary: result.summary,\n data: {\n url: result.url,\n title: result.title,\n techStack: topTech,\n totalTechnologiesDetected: result.techStack.length,\n eventsStored: result.events.length,\n availableTools: [\n 'get_page_metadata — tech stack details',\n 'get_design_tokens — colors, typography, spacing, CSS variables',\n 'get_layout_tree — DOM structure with layout info',\n 'get_font_info — font faces and usage',\n 'get_accessibility_tree — headings, landmarks, forms',\n 'get_asset_inventory — images, SVGs, sprites',\n 'get_computed_styles — CSS values for specific selectors',\n 'get_element_snapshot — deep snapshot of an element',\n 'get_style_diff — compare styles between selectors',\n ],\n },\n issues,\n metadata: {\n timeRange: { from: Date.now() - result.scanDurationMs, to: Date.now() },\n eventCount: result.events.length,\n sessionId: result.events[0]?.sessionId ?? null,\n scanDurationMs: result.scanDurationMs,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n // Provide helpful error messages\n let hint = '';\n if (message.includes('browserType.launch')) {\n hint = ' Ensure Chromium is installed: npx playwright install chromium';\n } else if (message.includes('net::ERR_')) {\n hint = ' The URL may be unreachable or blocked.';\n } else if (message.includes('Timeout')) {\n hint = ' The page took too long to load. Try with wait_for: \"load\" instead of \"networkidle\".';\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({\n summary: `Scan failed: ${message}${hint}`,\n data: null,\n issues: [`Scan error: ${message}${hint}`],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2),\n }],\n };\n }\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CollectorServer, ProjectManager } from '@runtimescope/collector';\n\nconst EVENT_TYPES = [\n 'network', 'console', 'session', 'state', 'render',\n 'dom_snapshot', 'performance', 'database',\n 'recon_metadata', 'recon_design_tokens', 'recon_fonts',\n 'recon_layout_tree', 'recon_accessibility', 'recon_computed_styles',\n 'recon_element_snapshot', 'recon_asset_inventory',\n] as const;\n\n/**\n * Parse a date parameter: supports ISO strings, relative strings (\"2h\", \"7d\", \"30m\"), or epoch ms.\n */\nfunction parseDateParam(value: string | undefined): number | undefined {\n if (!value) return undefined;\n\n // Relative time: \"2h\", \"7d\", \"30m\", \"1w\"\n const relMatch = value.match(/^(\\d+)(m|h|d|w)$/);\n if (relMatch) {\n const amount = parseInt(relMatch[1], 10);\n const unit = relMatch[2];\n const ms = { m: 60_000, h: 3_600_000, d: 86_400_000, w: 604_800_000 }[unit]!;\n return Date.now() - amount * ms;\n }\n\n // Epoch milliseconds\n const num = Number(value);\n if (!isNaN(num) && num > 1_000_000_000_000) return num;\n\n // ISO date string\n const date = new Date(value);\n if (!isNaN(date.getTime())) return date.getTime();\n\n return undefined;\n}\n\nexport function registerHistoryTools(\n server: McpServer,\n collector: CollectorServer,\n projectManager: ProjectManager,\n): void {\n // ---------- get_historical_events ----------\n server.tool(\n 'get_historical_events',\n 'Query past events from persistent SQLite storage. Use this to access events beyond the in-memory buffer (last 10K events). Events persist across Claude Code restarts. Filter by project, event type, time range, and session.',\n {\n project: z\n .string()\n .describe('Project/app name (the appName used in SDK init)'),\n event_types: z\n .array(z.enum(EVENT_TYPES))\n .optional()\n .describe('Filter by event types (e.g., [\"network\", \"console\"])'),\n since: z\n .string()\n .optional()\n .describe('Start time — relative (\"2h\", \"7d\", \"30m\") or ISO date string'),\n until: z\n .string()\n .optional()\n .describe('End time — relative or ISO date string'),\n session_id: z\n .string()\n .optional()\n .describe('Filter by specific session ID'),\n limit: z\n .number()\n .optional()\n .default(200)\n .describe('Max events to return (default 200, max 1000)'),\n offset: z\n .number()\n .optional()\n .default(0)\n .describe('Pagination offset'),\n },\n async ({ project, event_types, since, until, session_id, limit, offset }) => {\n const sqliteStore = collector.getSqliteStore(project);\n if (!sqliteStore) {\n // Check if the project directory exists at all\n const projects = projectManager.listProjects();\n const hint = projects.length > 0\n ? ` Available projects: ${projects.join(', ')}`\n : ' No projects have connected yet.';\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({\n summary: `No historical data for project \"${project}\".${hint}`,\n data: null,\n issues: [`Project \"${project}\" has no SQLite store. Connect an SDK with appName: \"${project}\" first.`],\n metadata: { timeRange: { from: 0, to: 0 }, eventCount: 0, sessionId: null },\n }, null, 2) }],\n };\n }\n\n const sinceMs = parseDateParam(since);\n const untilMs = parseDateParam(until);\n const cappedLimit = Math.min(limit, 1000);\n\n const events = sqliteStore.getEvents({\n project,\n sessionId: session_id,\n eventTypes: event_types as string[] | undefined,\n since: sinceMs,\n until: untilMs,\n limit: cappedLimit,\n offset,\n });\n\n const totalCount = sqliteStore.getEventCount({\n project,\n sessionId: session_id,\n eventTypes: event_types as string[] | undefined,\n since: sinceMs,\n until: untilMs,\n });\n\n const timeRange = events.length > 0\n ? { from: events[0].timestamp, to: events[events.length - 1].timestamp }\n : { from: 0, to: 0 };\n\n // Group by event type for summary\n const typeCounts: Record<string, number> = {};\n for (const e of events) {\n typeCounts[e.eventType] = (typeCounts[e.eventType] || 0) + 1;\n }\n\n const typeBreakdown = Object.entries(typeCounts)\n .map(([type, count]) => `${type}: ${count}`)\n .join(', ');\n\n const response = {\n summary: `${events.length} events returned (${totalCount} total matching). ${typeBreakdown || 'No events.'}${totalCount > cappedLimit + offset ? ` Use offset=${offset + cappedLimit} for next page.` : ''}`,\n data: {\n events,\n pagination: {\n returned: events.length,\n total: totalCount,\n limit: cappedLimit,\n offset,\n hasMore: offset + cappedLimit < totalCount,\n },\n },\n issues: [] as string[],\n metadata: {\n timeRange,\n eventCount: events.length,\n sessionId: session_id ?? null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n\n // ---------- list_projects ----------\n server.tool(\n 'list_projects',\n 'List all projects with stored historical data. Shows project names, event counts, session counts, and date ranges from SQLite persistence.',\n {},\n async () => {\n const projectNames = projectManager.listProjects();\n\n const projects = projectNames.map((name) => {\n const sqliteStore = collector.getSqliteStore(name);\n if (!sqliteStore) {\n return {\n name,\n eventCount: 0,\n sessionCount: 0,\n isConnected: false,\n note: 'Project directory exists but no active SQLite store (SDK has not connected this session)',\n };\n }\n\n const eventCount = sqliteStore.getEventCount({ project: name });\n const sessions = sqliteStore.getSessions(name, 100);\n const connectedSessions = sessions.filter((s) => s.isConnected);\n\n return {\n name,\n eventCount,\n sessionCount: sessions.length,\n activeSessions: connectedSessions.length,\n isConnected: connectedSessions.length > 0,\n oldestSession: sessions.length > 0\n ? new Date(sessions[sessions.length - 1].connectedAt).toISOString()\n : null,\n newestSession: sessions.length > 0\n ? new Date(sessions[0].connectedAt).toISOString()\n : null,\n };\n });\n\n const totalEvents = projects.reduce((s, p) => s + p.eventCount, 0);\n const connectedCount = projects.filter((p) => p.isConnected).length;\n\n const response = {\n summary: `${projects.length} project(s), ${totalEvents} total events, ${connectedCount} currently connected.`,\n data: projects,\n issues: [] as string[],\n metadata: {\n timeRange: { from: 0, to: 0 },\n eventCount: projects.length,\n sessionId: null,\n },\n };\n\n return {\n content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],\n };\n },\n );\n}\n"],"mappings":"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","names":["execSync","existsSync","z","z","z","z","z","z","z","z","z","z","z","z","z","z","z","sessions","z","sessions","z","z","sessions","z","z","sessions","z","sessions","z","totalGlyphs","z","maxDepth","z","z","COLLECTOR_PORT","HTTP_PORT","execSync","existsSync"]}