auto-feedback 0.1.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.
Files changed (90) hide show
  1. package/README.md +180 -0
  2. package/build/capture/console-collector.d.ts +16 -0
  3. package/build/capture/console-collector.js +43 -0
  4. package/build/capture/error-collector.d.ts +15 -0
  5. package/build/capture/error-collector.js +47 -0
  6. package/build/capture/network-collector.d.ts +16 -0
  7. package/build/capture/network-collector.js +76 -0
  8. package/build/capture/process-collector.d.ts +16 -0
  9. package/build/capture/process-collector.js +48 -0
  10. package/build/capture/types.d.ts +61 -0
  11. package/build/capture/types.js +5 -0
  12. package/build/index.d.ts +6 -0
  13. package/build/index.js +41 -0
  14. package/build/interaction/selectors.d.ts +26 -0
  15. package/build/interaction/selectors.js +84 -0
  16. package/build/interaction/types.d.ts +56 -0
  17. package/build/interaction/types.js +5 -0
  18. package/build/process/cleanup.d.ts +23 -0
  19. package/build/process/cleanup.js +50 -0
  20. package/build/process/launcher.d.ts +22 -0
  21. package/build/process/launcher.js +54 -0
  22. package/build/process/monitor.d.ts +14 -0
  23. package/build/process/monitor.js +67 -0
  24. package/build/process/types.d.ts +84 -0
  25. package/build/process/types.js +5 -0
  26. package/build/screenshot/auto-capture.d.ts +14 -0
  27. package/build/screenshot/auto-capture.js +38 -0
  28. package/build/screenshot/capture.d.ts +21 -0
  29. package/build/screenshot/capture.js +48 -0
  30. package/build/screenshot/optimize.d.ts +19 -0
  31. package/build/screenshot/optimize.js +28 -0
  32. package/build/screenshot/types.d.ts +43 -0
  33. package/build/screenshot/types.js +4 -0
  34. package/build/server.d.ts +10 -0
  35. package/build/server.js +18 -0
  36. package/build/session-manager.d.ts +119 -0
  37. package/build/session-manager.js +284 -0
  38. package/build/tools/check-port.d.ts +10 -0
  39. package/build/tools/check-port.js +40 -0
  40. package/build/tools/click-element.d.ts +13 -0
  41. package/build/tools/click-element.js +118 -0
  42. package/build/tools/get-console-logs.d.ts +7 -0
  43. package/build/tools/get-console-logs.js +55 -0
  44. package/build/tools/get-element-state.d.ts +14 -0
  45. package/build/tools/get-element-state.js +116 -0
  46. package/build/tools/get-errors.d.ts +7 -0
  47. package/build/tools/get-errors.js +40 -0
  48. package/build/tools/get-network-logs.d.ts +7 -0
  49. package/build/tools/get-network-logs.js +58 -0
  50. package/build/tools/get-process-output.d.ts +7 -0
  51. package/build/tools/get-process-output.js +55 -0
  52. package/build/tools/get-screenshot.d.ts +7 -0
  53. package/build/tools/get-screenshot.js +32 -0
  54. package/build/tools/index.d.ts +9 -0
  55. package/build/tools/index.js +117 -0
  56. package/build/tools/launch-electron.d.ts +13 -0
  57. package/build/tools/launch-electron.js +97 -0
  58. package/build/tools/launch-web-server.d.ts +13 -0
  59. package/build/tools/launch-web-server.js +88 -0
  60. package/build/tools/launch-windows-exe.d.ts +13 -0
  61. package/build/tools/launch-windows-exe.js +81 -0
  62. package/build/tools/navigate.d.ts +13 -0
  63. package/build/tools/navigate.js +137 -0
  64. package/build/tools/run-workflow.d.ts +14 -0
  65. package/build/tools/run-workflow.js +207 -0
  66. package/build/tools/screenshot-desktop.d.ts +13 -0
  67. package/build/tools/screenshot-desktop.js +80 -0
  68. package/build/tools/screenshot-electron.d.ts +13 -0
  69. package/build/tools/screenshot-electron.js +72 -0
  70. package/build/tools/screenshot-web.d.ts +13 -0
  71. package/build/tools/screenshot-web.js +129 -0
  72. package/build/tools/stop-process.d.ts +14 -0
  73. package/build/tools/stop-process.js +41 -0
  74. package/build/tools/type-text.d.ts +13 -0
  75. package/build/tools/type-text.js +137 -0
  76. package/build/tools/wait-for-element.d.ts +14 -0
  77. package/build/tools/wait-for-element.js +93 -0
  78. package/build/types/index.d.ts +31 -0
  79. package/build/types/index.js +4 -0
  80. package/build/utils/errors.d.ts +26 -0
  81. package/build/utils/errors.js +62 -0
  82. package/build/utils/shutdown.d.ts +16 -0
  83. package/build/utils/shutdown.js +34 -0
  84. package/build/workflow/assertions.d.ts +25 -0
  85. package/build/workflow/assertions.js +326 -0
  86. package/build/workflow/executor.d.ts +34 -0
  87. package/build/workflow/executor.js +269 -0
  88. package/build/workflow/types.d.ts +95 -0
  89. package/build/workflow/types.js +6 -0
  90. package/package.json +36 -0
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # Feedback
2
+
3
+ An MCP server that gives Claude Code eyes and hands for GUI development. When Claude builds a web app, Electron app, or Windows desktop application, Feedback launches the app, captures screenshots, interacts with the UI (click buttons, fill forms, navigate), captures errors and logs, and runs multi-step QA workflows with assertions — so Claude can iterate until the GUI actually works.
4
+
5
+ ## Why
6
+
7
+ Claude Code currently has no way to see the visual output of GUI code it writes. This leads to blind iteration cycles where the user must describe what's wrong. Feedback closes the loop: Claude writes code, launches the app, takes a screenshot, verifies the result, and fixes issues — all autonomously.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install -g auto-feedback
13
+ ```
14
+
15
+ Then install Playwright browsers (required for web/Electron automation):
16
+
17
+ ```bash
18
+ npx playwright install chromium
19
+ ```
20
+
21
+ ## Configure with Claude Code
22
+
23
+ Add to your Claude Code MCP settings (`~/.claude/settings.json` or project `.claude/settings.json`):
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "feedback": {
29
+ "command": "auto-feedback",
30
+ "args": []
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Or if installed locally in a project:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "feedback": {
42
+ "command": "npx",
43
+ "args": ["auto-feedback"]
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ Restart Claude Code after adding the configuration. You should see Feedback's 23 tools available.
50
+
51
+ ## What It Does
52
+
53
+ ### Session Management
54
+
55
+ Every interaction starts with creating a session. Sessions track all resources (processes, browsers, screenshots, logs) and clean up everything when ended.
56
+
57
+ ### Launch Apps
58
+
59
+ - **Web dev servers** — Launch `npm start`, `vite`, `webpack`, `next dev`, etc. Automatically detects when the server is ready via stdout pattern matching and TCP port polling.
60
+ - **Electron apps** — Launch and connect Playwright for full automation.
61
+ - **Windows .exe files** — Launch native desktop apps and track their process.
62
+
63
+ ### Take Screenshots
64
+
65
+ - **Web/Electron** — Playwright-based screenshots with full-page or viewport modes.
66
+ - **Desktop apps** — Native window capture by PID.
67
+ - **Auto-capture** — Automatically captures screenshots after page navigation events.
68
+ - **Optimized** — All screenshots resized and compressed to WebP for fast MCP transport.
69
+
70
+ ### Interact with UI
71
+
72
+ - **Click elements** — By CSS selector, text content, role, or test ID. Returns a post-click screenshot.
73
+ - **Type text** — Fill inputs with paste or per-keystroke typing. Auto-waits for element readiness.
74
+ - **Navigate** — Go to URLs, browser back/forward. Updates page tracking automatically.
75
+ - **Read state** — Get element text, visibility, enabled/disabled, attributes, bounding box.
76
+ - **Wait for elements** — Wait for elements to become visible, hidden, attached, or detached.
77
+
78
+ ### Capture Errors & Logs
79
+
80
+ - **Console logs** — Browser console output (log, error, warn) per session.
81
+ - **Runtime errors** — Uncaught exceptions and page crashes.
82
+ - **Network traffic** — HTTP requests/responses with status codes and timing.
83
+ - **Process output** — stdout/stderr from dev servers and executables.
84
+
85
+ ### Run QA Workflows
86
+
87
+ Execute multi-step sequences with per-step screenshots and log capture:
88
+
89
+ ```
90
+ run_workflow: [
91
+ { action: "navigate", url: "http://localhost:3000" },
92
+ { action: "click", selector: "#login-button" },
93
+ { action: "type", selector: "#email", text: "user@example.com" },
94
+ { action: "type", selector: "#password", text: "password123" },
95
+ { action: "click", selector: "role=button[name='Sign In']" },
96
+ { action: "assert", selector: ".welcome-message", assertType: "text-contains", expected: "Welcome" }
97
+ ]
98
+ ```
99
+
100
+ Each step captures a screenshot and log deltas. Failed steps stop the workflow with diagnostic context.
101
+
102
+ ### Assert UI State
103
+
104
+ 13 assertion types for verifying application behavior:
105
+
106
+ | Assertion | What it checks |
107
+ |-----------|---------------|
108
+ | `exists` | Element is in the DOM |
109
+ | `not-exists` | Element is not in the DOM |
110
+ | `visible` | Element is visible |
111
+ | `hidden` | Element is hidden or absent |
112
+ | `text-equals` | Element text matches exactly |
113
+ | `text-contains` | Element text contains substring |
114
+ | `has-attribute` | Element has the named attribute |
115
+ | `attribute-equals` | Attribute matches expected value |
116
+ | `enabled` | Element is enabled |
117
+ | `disabled` | Element is disabled |
118
+ | `checked` | Checkbox/radio is checked |
119
+ | `not-checked` | Checkbox/radio is not checked |
120
+ | `value-equals` | Input value matches expected |
121
+
122
+ ## All 23 Tools
123
+
124
+ | # | Tool | Purpose |
125
+ |---|------|---------|
126
+ | 1 | `get_version` | Server version and capabilities |
127
+ | 2 | `create_session` | Start a new testing session |
128
+ | 3 | `list_sessions` | List active sessions |
129
+ | 4 | `end_session` | End session and clean up resources |
130
+ | 5 | `check_port` | Check if a port is available |
131
+ | 6 | `launch_web_server` | Start a web dev server |
132
+ | 7 | `launch_electron` | Launch an Electron app |
133
+ | 8 | `launch_windows_exe` | Launch a Windows executable |
134
+ | 9 | `stop_process` | Stop all processes in a session |
135
+ | 10 | `screenshot_web` | Screenshot a web page by URL |
136
+ | 11 | `screenshot_electron` | Screenshot an Electron app |
137
+ | 12 | `screenshot_desktop` | Screenshot a desktop app window |
138
+ | 13 | `get_screenshot` | Get latest auto-captured screenshot |
139
+ | 14 | `click_element` | Click an element on the page |
140
+ | 15 | `type_text` | Type into an input field |
141
+ | 16 | `navigate` | Navigate to URL or back/forward |
142
+ | 17 | `get_element_state` | Read element properties |
143
+ | 18 | `wait_for_element` | Wait for element state change |
144
+ | 19 | `get_console_logs` | Get browser console output |
145
+ | 20 | `get_errors` | Get runtime errors and crashes |
146
+ | 21 | `get_network_logs` | Get HTTP request/response logs |
147
+ | 22 | `get_process_output` | Get process stdout/stderr |
148
+ | 23 | `run_workflow` | Execute multi-step QA workflow |
149
+
150
+ ## Typical Flow
151
+
152
+ ```
153
+ create_session
154
+ -> launch_web_server (npm run dev on port 3000)
155
+ -> screenshot_web (http://localhost:3000)
156
+ -> click_element (#submit-button)
157
+ -> type_text (#search-input, "hello world")
158
+ -> run_workflow (multi-step test with assertions)
159
+ -> get_console_logs (check for errors)
160
+ -> stop_process (clean up)
161
+ -> end_session
162
+ ```
163
+
164
+ ## Requirements
165
+
166
+ - **Node.js** >= 18.0.0
167
+ - **Playwright Chromium** — installed via `npx playwright install chromium`
168
+ - **Windows** — required for desktop app screenshots and .exe launching (web/Electron work on all platforms)
169
+
170
+ ## Tech Stack
171
+
172
+ - TypeScript/Node.js with ESM
173
+ - [MCP SDK](https://github.com/modelcontextprotocol/sdk) for Claude Code integration
174
+ - [Playwright](https://playwright.dev/) for web and Electron automation
175
+ - [Sharp](https://sharp.pixelplumbing.com/) for screenshot optimization (WebP)
176
+ - [node-screenshots](https://github.com/nicehash/node-screenshots) for native desktop capture
177
+
178
+ ## License
179
+
180
+ MIT
@@ -0,0 +1,16 @@
1
+ /**
2
+ * ERRX-01: Browser console log capture
3
+ * Attaches to Playwright page.on("console") events and stores entries
4
+ * in a bounded array. Uses msg.text() (never jsonValue) for reliability.
5
+ */
6
+ import type { Page } from "playwright";
7
+ import { Collector, ConsoleEntry } from "./types.js";
8
+ /**
9
+ * Attach a console log collector to a Playwright page.
10
+ * Captures all console.log/warn/error/info/debug messages.
11
+ *
12
+ * @param page - Playwright Page to monitor
13
+ * @param maxEntries - Maximum entries to buffer (oldest dropped when full)
14
+ * @returns Collector with getEntries() and detach()
15
+ */
16
+ export declare function attachConsoleCollector(page: Page, maxEntries?: number): Collector<ConsoleEntry>;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * ERRX-01: Browser console log capture
3
+ * Attaches to Playwright page.on("console") events and stores entries
4
+ * in a bounded array. Uses msg.text() (never jsonValue) for reliability.
5
+ */
6
+ /**
7
+ * Attach a console log collector to a Playwright page.
8
+ * Captures all console.log/warn/error/info/debug messages.
9
+ *
10
+ * @param page - Playwright Page to monitor
11
+ * @param maxEntries - Maximum entries to buffer (oldest dropped when full)
12
+ * @returns Collector with getEntries() and detach()
13
+ */
14
+ export function attachConsoleCollector(page, maxEntries = 1000) {
15
+ const entries = [];
16
+ const handler = (msg) => {
17
+ const location = msg.location();
18
+ const entry = {
19
+ timestamp: new Date().toISOString(),
20
+ level: msg.type(),
21
+ text: msg.text(),
22
+ };
23
+ // Only include location if it has a meaningful URL
24
+ if (location && location.url) {
25
+ entry.location = {
26
+ url: location.url,
27
+ lineNumber: location.lineNumber,
28
+ columnNumber: location.columnNumber,
29
+ };
30
+ }
31
+ if (entries.length >= maxEntries) {
32
+ entries.shift();
33
+ }
34
+ entries.push(entry);
35
+ };
36
+ page.on("console", handler);
37
+ return {
38
+ getEntries: () => [...entries],
39
+ detach: () => {
40
+ page.off("console", handler);
41
+ },
42
+ };
43
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * ERRX-02: Uncaught exception and page crash capture
3
+ * Attaches to Playwright page.on("pageerror") and page.on("crash") events.
4
+ */
5
+ import type { Page } from "playwright";
6
+ import { Collector, ErrorEntry } from "./types.js";
7
+ /**
8
+ * Attach an error/crash collector to a Playwright page.
9
+ * Captures uncaught exceptions (with stack traces) and page crashes.
10
+ *
11
+ * @param page - Playwright Page to monitor
12
+ * @param maxEntries - Maximum entries to buffer (oldest dropped when full)
13
+ * @returns Collector with getEntries() and detach()
14
+ */
15
+ export declare function attachErrorCollector(page: Page, maxEntries?: number): Collector<ErrorEntry>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * ERRX-02: Uncaught exception and page crash capture
3
+ * Attaches to Playwright page.on("pageerror") and page.on("crash") events.
4
+ */
5
+ /**
6
+ * Attach an error/crash collector to a Playwright page.
7
+ * Captures uncaught exceptions (with stack traces) and page crashes.
8
+ *
9
+ * @param page - Playwright Page to monitor
10
+ * @param maxEntries - Maximum entries to buffer (oldest dropped when full)
11
+ * @returns Collector with getEntries() and detach()
12
+ */
13
+ export function attachErrorCollector(page, maxEntries = 100) {
14
+ const entries = [];
15
+ const errorHandler = (error) => {
16
+ const entry = {
17
+ timestamp: new Date().toISOString(),
18
+ type: "uncaught-exception",
19
+ message: error.message,
20
+ stack: error.stack,
21
+ };
22
+ if (entries.length >= maxEntries) {
23
+ entries.shift();
24
+ }
25
+ entries.push(entry);
26
+ };
27
+ const crashHandler = () => {
28
+ const entry = {
29
+ timestamp: new Date().toISOString(),
30
+ type: "page-crash",
31
+ message: "Page crashed (possible out of memory)",
32
+ };
33
+ if (entries.length >= maxEntries) {
34
+ entries.shift();
35
+ }
36
+ entries.push(entry);
37
+ };
38
+ page.on("pageerror", errorHandler);
39
+ page.on("crash", crashHandler);
40
+ return {
41
+ getEntries: () => [...entries],
42
+ detach: () => {
43
+ page.off("pageerror", errorHandler);
44
+ page.off("crash", crashHandler);
45
+ },
46
+ };
47
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * ERRX-04: HTTP request/response logging
3
+ * Attaches to Playwright page request/response/requestfailed events.
4
+ * Tracks timing via Date.now() delta. Does NOT capture bodies or headers.
5
+ */
6
+ import type { Page } from "playwright";
7
+ import { Collector, NetworkEntry } from "./types.js";
8
+ /**
9
+ * Attach a network request/response collector to a Playwright page.
10
+ * Tracks request timing, status codes, and failed requests.
11
+ *
12
+ * @param page - Playwright Page to monitor
13
+ * @param maxEntries - Maximum entries to buffer (oldest dropped when full)
14
+ * @returns Collector with getEntries() and detach()
15
+ */
16
+ export declare function attachNetworkCollector(page: Page, maxEntries?: number): Collector<NetworkEntry>;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * ERRX-04: HTTP request/response logging
3
+ * Attaches to Playwright page request/response/requestfailed events.
4
+ * Tracks timing via Date.now() delta. Does NOT capture bodies or headers.
5
+ */
6
+ /**
7
+ * Attach a network request/response collector to a Playwright page.
8
+ * Tracks request timing, status codes, and failed requests.
9
+ *
10
+ * @param page - Playwright Page to monitor
11
+ * @param maxEntries - Maximum entries to buffer (oldest dropped when full)
12
+ * @returns Collector with getEntries() and detach()
13
+ */
14
+ export function attachNetworkCollector(page, maxEntries = 500) {
15
+ const entries = [];
16
+ const pendingRequests = new Map();
17
+ /**
18
+ * Composite key for matching requests to responses.
19
+ * Uses method + URL to handle concurrent requests to different endpoints.
20
+ */
21
+ const requestKey = (request) => `${request.method()} ${request.url()}`;
22
+ const requestHandler = (request) => {
23
+ pendingRequests.set(requestKey(request), Date.now());
24
+ };
25
+ const responseHandler = (response) => {
26
+ const request = response.request();
27
+ const key = requestKey(request);
28
+ const startTime = pendingRequests.get(key);
29
+ pendingRequests.delete(key);
30
+ const entry = {
31
+ timestamp: new Date().toISOString(),
32
+ method: request.method(),
33
+ url: request.url(),
34
+ resourceType: request.resourceType(),
35
+ status: response.status(),
36
+ statusText: response.statusText(),
37
+ durationMs: startTime !== undefined ? Date.now() - startTime : undefined,
38
+ fromServiceWorker: response.fromServiceWorker(),
39
+ };
40
+ if (entries.length >= maxEntries) {
41
+ entries.shift();
42
+ }
43
+ entries.push(entry);
44
+ };
45
+ const failedHandler = (request) => {
46
+ const key = requestKey(request);
47
+ const startTime = pendingRequests.get(key);
48
+ pendingRequests.delete(key);
49
+ const failure = request.failure();
50
+ const entry = {
51
+ timestamp: new Date().toISOString(),
52
+ method: request.method(),
53
+ url: request.url(),
54
+ resourceType: request.resourceType(),
55
+ status: 0,
56
+ statusText: "FAILED",
57
+ durationMs: startTime !== undefined ? Date.now() - startTime : undefined,
58
+ errorText: failure?.errorText,
59
+ };
60
+ if (entries.length >= maxEntries) {
61
+ entries.shift();
62
+ }
63
+ entries.push(entry);
64
+ };
65
+ page.on("request", requestHandler);
66
+ page.on("response", responseHandler);
67
+ page.on("requestfailed", failedHandler);
68
+ return {
69
+ getEntries: () => [...entries],
70
+ detach: () => {
71
+ page.off("request", requestHandler);
72
+ page.off("response", responseHandler);
73
+ page.off("requestfailed", failedHandler);
74
+ },
75
+ };
76
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * ERRX-03: Process stdout/stderr buffered capture
3
+ * Attaches to child process output streams, splits multi-line output,
4
+ * and tags each line with stream source (stdout/stderr).
5
+ */
6
+ import type { ChildProcess } from "child_process";
7
+ import { Collector, ProcessOutputEntry } from "./types.js";
8
+ /**
9
+ * Attach a process output collector to a child process.
10
+ * Captures stdout and stderr, splitting multi-line output into individual entries.
11
+ *
12
+ * @param child - Node.js ChildProcess to monitor
13
+ * @param maxLines - Maximum entries to buffer (oldest dropped when full)
14
+ * @returns Collector with getEntries() and detach()
15
+ */
16
+ export declare function attachProcessCollector(child: ChildProcess, maxLines?: number): Collector<ProcessOutputEntry>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * ERRX-03: Process stdout/stderr buffered capture
3
+ * Attaches to child process output streams, splits multi-line output,
4
+ * and tags each line with stream source (stdout/stderr).
5
+ */
6
+ /**
7
+ * Attach a process output collector to a child process.
8
+ * Captures stdout and stderr, splitting multi-line output into individual entries.
9
+ *
10
+ * @param child - Node.js ChildProcess to monitor
11
+ * @param maxLines - Maximum entries to buffer (oldest dropped when full)
12
+ * @returns Collector with getEntries() and detach()
13
+ */
14
+ export function attachProcessCollector(child, maxLines = 5000) {
15
+ const entries = [];
16
+ const createHandler = (stream) => {
17
+ return (data) => {
18
+ const text = data.toString();
19
+ const lines = text.split("\n");
20
+ for (const line of lines) {
21
+ const trimmed = line.trimEnd();
22
+ if (trimmed.length === 0) {
23
+ continue;
24
+ }
25
+ const entry = {
26
+ timestamp: new Date().toISOString(),
27
+ stream,
28
+ text: trimmed,
29
+ };
30
+ if (entries.length >= maxLines) {
31
+ entries.shift();
32
+ }
33
+ entries.push(entry);
34
+ }
35
+ };
36
+ };
37
+ const stdoutHandler = createHandler("stdout");
38
+ const stderrHandler = createHandler("stderr");
39
+ child.stdout?.on("data", stdoutHandler);
40
+ child.stderr?.on("data", stderrHandler);
41
+ return {
42
+ getEntries: () => [...entries],
43
+ detach: () => {
44
+ child.stdout?.off("data", stdoutHandler);
45
+ child.stderr?.off("data", stderrHandler);
46
+ },
47
+ };
48
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Shared type definitions for diagnostic capture infrastructure
3
+ * Used by all collector modules and SessionManager
4
+ */
5
+ /**
6
+ * Generic collector interface — container for captured diagnostic data.
7
+ * Each collector attaches event listeners, stores entries in a bounded array,
8
+ * and provides getEntries() to read and detach() to clean up.
9
+ */
10
+ export interface Collector<T> {
11
+ getEntries: () => T[];
12
+ detach: () => void;
13
+ }
14
+ /**
15
+ * ERRX-01: Console log entry
16
+ * Captured from Playwright page.on("console") events.
17
+ */
18
+ export interface ConsoleEntry {
19
+ timestamp: string;
20
+ level: string;
21
+ text: string;
22
+ location?: {
23
+ url: string;
24
+ lineNumber: number;
25
+ columnNumber: number;
26
+ };
27
+ }
28
+ /**
29
+ * ERRX-02: Error/crash entry
30
+ * Captured from page.on("pageerror") and page.on("crash") events.
31
+ */
32
+ export interface ErrorEntry {
33
+ timestamp: string;
34
+ type: "uncaught-exception" | "page-crash";
35
+ message: string;
36
+ stack?: string;
37
+ }
38
+ /**
39
+ * ERRX-04: Network request/response entry
40
+ * Captured from page.on("request"), page.on("response"), page.on("requestfailed").
41
+ */
42
+ export interface NetworkEntry {
43
+ timestamp: string;
44
+ method: string;
45
+ url: string;
46
+ resourceType: string;
47
+ status: number;
48
+ statusText: string;
49
+ durationMs?: number;
50
+ errorText?: string;
51
+ fromServiceWorker?: boolean;
52
+ }
53
+ /**
54
+ * ERRX-03: Process output entry
55
+ * Captured from child process stdout/stderr streams.
56
+ */
57
+ export interface ProcessOutputEntry {
58
+ timestamp: string;
59
+ stream: "stdout" | "stderr";
60
+ text: string;
61
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared type definitions for diagnostic capture infrastructure
3
+ * Used by all collector modules and SessionManager
4
+ */
5
+ export {};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry point for Feedback MCP server
4
+ * Starts server on stdio transport with graceful shutdown handling
5
+ */
6
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry point for Feedback MCP server
4
+ * Starts server on stdio transport with graceful shutdown handling
5
+ */
6
+ import { createServer } from "./server.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import { ShutdownManager } from "./utils/shutdown.js";
9
+ import { SessionManager } from "./session-manager.js";
10
+ // Create shutdown manager before any async operations
11
+ const shutdownManager = new ShutdownManager();
12
+ // Create session manager
13
+ const sessionManager = new SessionManager();
14
+ // Register signal handlers BEFORE connecting transport
15
+ process.once("SIGINT", () => {
16
+ void shutdownManager.cleanup();
17
+ });
18
+ process.once("SIGTERM", () => {
19
+ void shutdownManager.cleanup();
20
+ });
21
+ async function main() {
22
+ // Create server with session manager
23
+ const server = createServer(sessionManager);
24
+ // Create stdio transport
25
+ const transport = new StdioServerTransport();
26
+ // Connect server to transport
27
+ await server.connect(transport);
28
+ // Register cleanup handlers
29
+ shutdownManager.register(async () => {
30
+ console.error("Closing server");
31
+ });
32
+ shutdownManager.register(async () => {
33
+ await sessionManager.destroyAll();
34
+ });
35
+ console.error("Feedback MCP Server running on stdio");
36
+ }
37
+ // Start server with fatal error handler
38
+ main().catch((error) => {
39
+ console.error("Fatal error:", error);
40
+ process.exit(1);
41
+ });
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Selector resolution and page discovery
3
+ * Converts string selectors to Playwright Locators and discovers active pages
4
+ */
5
+ import type { Page, Locator } from "playwright";
6
+ import type { SessionManager } from "../session-manager.js";
7
+ import type { PageDiscoveryResult } from "./types.js";
8
+ /**
9
+ * Convert a selector string to a Playwright Locator.
10
+ *
11
+ * Supported formats:
12
+ * - CSS selectors: #id, .class, div > span (passed directly to Playwright)
13
+ * - Text: text=Click me (Playwright native)
14
+ * - Role: role=button[name='Submit'] (Playwright native)
15
+ * - XPath: xpath=//div[@id='main'] (Playwright native)
16
+ * - Test ID: testid=my-btn (resolved via getByTestId)
17
+ */
18
+ export declare function resolveSelector(page: Page, selector: string): Locator;
19
+ /**
20
+ * Find the active page for interaction in a session.
21
+ *
22
+ * - If pageIdentifier is provided, looks up that specific page
23
+ * - If omitted and session has exactly one page, auto-selects it
24
+ * - If omitted and session has 0 or >1 pages, returns actionable error
25
+ */
26
+ export declare function getActivePage(sessionManager: SessionManager, sessionId: string, pageIdentifier?: string): PageDiscoveryResult;