chrometools-mcp 2.4.2 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +540 -0
- package/COMPONENT_MAPPING_SPEC.md +1217 -0
- package/README.md +494 -38
- package/bridge/bridge-client.js +472 -0
- package/bridge/bridge-service.js +399 -0
- package/bridge/install.js +241 -0
- package/browser/browser-manager.js +107 -2
- package/browser/page-manager.js +226 -69
- package/docs/CHROME_EXTENSION.md +219 -0
- package/docs/PAGE_OBJECT_MODEL_CONCEPT.md +1756 -0
- package/element-finder-utils.js +138 -28
- package/extension/background.js +643 -0
- package/extension/content.js +715 -0
- package/extension/icons/create-icons.js +164 -0
- package/extension/icons/icon128.png +0 -0
- package/extension/icons/icon16.png +0 -0
- package/extension/icons/icon48.png +0 -0
- package/extension/manifest.json +58 -0
- package/extension/popup/popup.css +437 -0
- package/extension/popup/popup.html +102 -0
- package/extension/popup/popup.js +415 -0
- package/extension/recorder-overlay.css +93 -0
- package/figma-tools.js +120 -0
- package/index.js +3347 -2518
- package/models/BaseInputModel.js +93 -0
- package/models/CheckboxGroupModel.js +199 -0
- package/models/CheckboxModel.js +103 -0
- package/models/ColorInputModel.js +53 -0
- package/models/DateInputModel.js +67 -0
- package/models/RadioGroupModel.js +126 -0
- package/models/RangeInputModel.js +60 -0
- package/models/SelectModel.js +97 -0
- package/models/TextInputModel.js +34 -0
- package/models/TextareaModel.js +59 -0
- package/models/TimeInputModel.js +49 -0
- package/models/index.js +122 -0
- package/package.json +3 -2
- package/pom/apom-converter.js +267 -0
- package/pom/apom-tree-converter.js +515 -0
- package/pom/element-id-generator.js +175 -0
- package/recorder/page-object-generator.js +16 -0
- package/recorder/scenario-executor.js +80 -2
- package/server/tool-definitions.js +839 -656
- package/server/tool-groups.js +3 -2
- package/server/tool-schemas.js +367 -296
- package/server/websocket-bridge.js +447 -0
- package/utils/selector-resolver.js +186 -0
- package/utils/ui-framework-detector.js +392 -0
package/server/tool-schemas.js
CHANGED
|
@@ -1,296 +1,367 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* server/tool-schemas.js
|
|
3
|
-
*
|
|
4
|
-
* Zod schemas for all MCP tools
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { z } from 'zod';
|
|
8
|
-
|
|
9
|
-
// Basic tools
|
|
10
|
-
export const PingSchema = z.object({
|
|
11
|
-
message: z.string().optional().describe("Optional message to send"),
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export const OpenBrowserSchema = z.object({
|
|
15
|
-
url: z.string().describe("URL to open in the browser"),
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export const ClickSchema = z.object({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
export const
|
|
87
|
-
selector: z.string().describe("CSS selector to
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.optional()
|
|
130
|
-
.describe("
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
//
|
|
150
|
-
export const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
export const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
1
|
+
/**
|
|
2
|
+
* server/tool-schemas.js
|
|
3
|
+
*
|
|
4
|
+
* Zod schemas for all MCP tools
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
// Basic tools
|
|
10
|
+
export const PingSchema = z.object({
|
|
11
|
+
message: z.string().optional().describe("Optional message to send"),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const OpenBrowserSchema = z.object({
|
|
15
|
+
url: z.string().describe("URL to open in the browser"),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const ClickSchema = z.object({
|
|
19
|
+
id: z.string().optional().describe("APOM element ID from analyzePage (e.g., 'button_45', 'link_7'). Mutually exclusive with selector."),
|
|
20
|
+
selector: z.string().optional().describe("CSS selector for element to click. Mutually exclusive with id."),
|
|
21
|
+
waitAfter: z.number().optional().describe("Milliseconds to wait after click (default: 1500)"),
|
|
22
|
+
screenshot: z.boolean().optional().describe("Capture screenshot after click (default: false for performance)"),
|
|
23
|
+
timeout: z.number().optional().describe("Maximum time to wait for operation in ms (default: 30000)"),
|
|
24
|
+
}).refine(data => (data.id && !data.selector) || (!data.id && data.selector), {
|
|
25
|
+
message: "Either 'id' or 'selector' must be provided, but not both"
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const TypeSchema = z.object({
|
|
29
|
+
id: z.string().optional().describe("APOM element ID from analyzePage (e.g., 'input_20', 'input_33'). Mutually exclusive with selector."),
|
|
30
|
+
selector: z.string().optional().describe("CSS selector for input element. Mutually exclusive with id."),
|
|
31
|
+
text: z.string().describe("Text to type"),
|
|
32
|
+
delay: z.number().optional().describe("Delay between keystrokes in ms (default: 0)"),
|
|
33
|
+
clearFirst: z.boolean().optional().describe("Clear field before typing (default: true)"),
|
|
34
|
+
}).refine(data => (data.id && !data.selector) || (!data.id && data.selector), {
|
|
35
|
+
message: "Either 'id' or 'selector' must be provided, but not both"
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const GetElementSchema = z.object({
|
|
39
|
+
selector: z.string().optional().describe("CSS selector (optional, defaults to body)"),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const HoverSchema = z.object({
|
|
43
|
+
id: z.string().optional().describe("APOM element ID from analyzePage. Mutually exclusive with selector."),
|
|
44
|
+
selector: z.string().optional().describe("CSS selector for element to hover. Mutually exclusive with id."),
|
|
45
|
+
}).refine(data => (data.id && !data.selector) || (!data.id && data.selector), {
|
|
46
|
+
message: "Either 'id' or 'selector' must be provided, but not both"
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export const SelectOptionSchema = z.object({
|
|
50
|
+
id: z.string().optional().describe("APOM element ID from analyzePage for select element. Mutually exclusive with selector."),
|
|
51
|
+
selector: z.string().optional().describe("CSS selector for select element. Mutually exclusive with id."),
|
|
52
|
+
value: z.string().optional().describe("Value of option to select (option's value attribute)"),
|
|
53
|
+
text: z.string().optional().describe("Text content of option to select"),
|
|
54
|
+
index: z.number().min(0).optional().describe("Index of option to select (0-based)"),
|
|
55
|
+
}).refine(data => (data.id && !data.selector) || (!data.id && data.selector), {
|
|
56
|
+
message: "Either 'id' or 'selector' must be provided, but not both"
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export const DragSchema = z.object({
|
|
60
|
+
selector: z.string().describe("CSS selector for element to drag"),
|
|
61
|
+
direction: z.enum(['up', 'down', 'left', 'right', 'up-left', 'up-right', 'down-left', 'down-right'])
|
|
62
|
+
.describe("Direction to drag: vertical (up, down), horizontal (left, right), or diagonal (up-left, up-right, down-left, down-right)"),
|
|
63
|
+
distance: z.number().min(1).optional().describe("Distance to drag in pixels (default: 100)"),
|
|
64
|
+
duration: z.number().min(100).optional().describe("Duration of drag operation in milliseconds (default: 500)"),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export const ScrollHorizontalSchema = z.object({
|
|
68
|
+
selector: z.string().describe("CSS selector for element to scroll"),
|
|
69
|
+
direction: z.enum(['left', 'right']).describe("Direction to scroll horizontally"),
|
|
70
|
+
amount: z.union([z.number().min(1), z.literal('full')]).describe("Amount to scroll in pixels, or 'full' to scroll to the end"),
|
|
71
|
+
behavior: z.enum(['auto', 'smooth']).optional().describe("Scroll behavior (default: auto)"),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// CSS tools
|
|
75
|
+
export const GetComputedCssSchema = z.object({
|
|
76
|
+
selector: z.string().optional().describe("CSS selector (optional, defaults to body)"),
|
|
77
|
+
category: z.enum(['all', 'layout', 'typography', 'colors', 'visual']).optional().describe("Filter by CSS category: 'layout' (sizing, positioning), 'typography' (fonts, text), 'colors' (color schemes), 'visual' (effects, transforms), 'all' (default)"),
|
|
78
|
+
properties: z.array(z.string()).optional().describe("Specific CSS properties to return (e.g., ['color', 'font-size']). Overrides category filter."),
|
|
79
|
+
includeDefaults: z.boolean().optional().describe("Include properties with default values (default: false)"),
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
export const GetBoxModelSchema = z.object({
|
|
83
|
+
selector: z.string().describe("CSS selector for element"),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export const SetStylesSchema = z.object({
|
|
87
|
+
selector: z.string().describe("CSS selector for element to modify"),
|
|
88
|
+
styles: z.array(z.object({
|
|
89
|
+
name: z.string().describe("CSS property name (e.g., 'color')"),
|
|
90
|
+
value: z.string().describe("CSS property value (e.g., 'red')")
|
|
91
|
+
})).describe("Array of CSS property name-value pairs"),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Screenshot tools
|
|
95
|
+
export const ScreenshotSchema = z.object({
|
|
96
|
+
selector: z.string().describe("CSS selector for element to screenshot"),
|
|
97
|
+
padding: z.number().optional().describe("Padding around element in pixels (default: 0)"),
|
|
98
|
+
maxWidth: z.number().nullable().optional().describe("Maximum width in pixels, auto-scales if larger (default: 1024, set to null for original size)"),
|
|
99
|
+
maxHeight: z.number().nullable().optional().describe("Maximum height in pixels, auto-scales if larger (default: 8000 for API limit, set to null for original size)"),
|
|
100
|
+
quality: z.number().min(1).max(100).optional().describe("JPEG quality 1-100 (default: 80, only applies to JPEG format)"),
|
|
101
|
+
format: z.enum(['png', 'jpeg', 'auto']).optional().describe("Image format: 'png', 'jpeg', or 'auto' (default: 'auto' - chooses based on size)"),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export const SaveScreenshotSchema = z.object({
|
|
105
|
+
selector: z.string().describe("CSS selector for element to screenshot"),
|
|
106
|
+
filePath: z.string().describe("Absolute path where to save file"),
|
|
107
|
+
padding: z.number().optional().describe("Padding around element in pixels (default: 0)"),
|
|
108
|
+
maxWidth: z.number().nullable().optional().describe("Maximum width in pixels, auto-scales if larger (default: 1024, set to null for original size)"),
|
|
109
|
+
maxHeight: z.number().nullable().optional().describe("Maximum height in pixels, auto-scales if larger (default: 8000 for API limit, set to null for original size)"),
|
|
110
|
+
quality: z.number().min(1).max(100).optional().describe("JPEG quality 1-100 (default: 80, only applies to JPEG format)"),
|
|
111
|
+
format: z.enum(['png', 'jpeg', 'auto']).optional().describe("Image format: 'png', 'jpeg', or 'auto' (default: 'auto' - chooses based on size)"),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Navigation tools
|
|
115
|
+
export const ScrollToSchema = z.object({
|
|
116
|
+
selector: z.string().describe("CSS selector for element to scroll to"),
|
|
117
|
+
behavior: z.enum(['auto', 'smooth']).optional().describe("Scroll behavior (default: auto)"),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export const WaitForElementSchema = z.object({
|
|
121
|
+
selector: z.string().describe("CSS selector to wait for"),
|
|
122
|
+
timeout: z.number().optional().describe("Maximum time to wait in milliseconds (default: 5000)"),
|
|
123
|
+
visible: z.boolean().optional().describe("Wait for element to be visible (default: true)"),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export const NavigateToSchema = z.object({
|
|
127
|
+
url: z.string().describe("URL to navigate to"),
|
|
128
|
+
waitUntil: z.enum(['load', 'domcontentloaded', 'networkidle0', 'networkidle2'])
|
|
129
|
+
.optional()
|
|
130
|
+
.describe("Wait until event (default: networkidle2)"),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
export const SetViewportSchema = z.object({
|
|
134
|
+
width: z.number().min(320).max(4000).describe("Viewport width in pixels (320-4000)"),
|
|
135
|
+
height: z.number().min(200).max(3000).describe("Viewport height in pixels (200-3000)"),
|
|
136
|
+
deviceScaleFactor: z.number().min(0.5).max(3).optional().describe("Device pixel ratio (0.5-3, default: 1)"),
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
export const GetViewportSchema = z.object({});
|
|
140
|
+
|
|
141
|
+
// Script execution
|
|
142
|
+
export const ExecuteScriptSchema = z.object({
|
|
143
|
+
script: z.string().describe("JavaScript code to execute in page context"),
|
|
144
|
+
waitAfter: z.number().optional().describe("Milliseconds to wait after execution (default: 500)"),
|
|
145
|
+
screenshot: z.boolean().optional().describe("Capture screenshot after execution (default: false for performance)"),
|
|
146
|
+
timeout: z.number().optional().describe("Maximum time to wait for operation in ms (default: 30000)"),
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Network monitoring tools
|
|
150
|
+
export const GetConsoleLogsSchema = z.object({
|
|
151
|
+
types: z.array(z.enum(['log', 'warn', 'error', 'info', 'debug', 'verbose', 'warning']))
|
|
152
|
+
.optional()
|
|
153
|
+
.describe("Filter by log types (default: all)"),
|
|
154
|
+
clear: z.boolean().optional().describe("Clear logs after reading (default: false)"),
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
export const ListNetworkRequestsSchema = z.object({
|
|
158
|
+
types: z.array(z.enum(['Document', 'Stylesheet', 'Image', 'Media', 'Font', 'Script', 'XHR', 'Fetch', 'WebSocket', 'Other']))
|
|
159
|
+
.optional()
|
|
160
|
+
.default(['Fetch', 'XHR'])
|
|
161
|
+
.describe("Filter by request types (default: Fetch, XHR)"),
|
|
162
|
+
status: z.enum(['pending', 'completed', 'failed', 'all'])
|
|
163
|
+
.optional()
|
|
164
|
+
.describe("Filter by status (default: all)"),
|
|
165
|
+
limit: z.number().min(1).max(500).optional().default(50).describe("Maximum number of requests to return (default: 50)"),
|
|
166
|
+
offset: z.number().min(0).optional().default(0).describe("Number of requests to skip before returning results (default: 0)"),
|
|
167
|
+
clear: z.boolean().optional().describe("Clear requests after reading (default: false)"),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
export const GetNetworkRequestSchema = z.object({
|
|
171
|
+
requestId: z.string().describe("Request ID to get details for"),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export const FilterNetworkRequestsSchema = z.object({
|
|
175
|
+
urlPattern: z.string().describe("URL pattern to filter by (regex or partial match)"),
|
|
176
|
+
types: z.array(z.enum(['Document', 'Stylesheet', 'Image', 'Media', 'Font', 'Script', 'XHR', 'Fetch', 'WebSocket', 'Other']))
|
|
177
|
+
.optional()
|
|
178
|
+
.default(['Fetch', 'XHR'])
|
|
179
|
+
.describe("Filter by request types (default: Fetch, XHR)"),
|
|
180
|
+
clear: z.boolean().optional().describe("Clear requests after reading (default: false)"),
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Figma tools
|
|
184
|
+
export const GetFigmaFrameSchema = z.object({
|
|
185
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
186
|
+
fileKey: z.string().describe("Figma file key (from URL: figma.com/file/FILE_KEY/...)"),
|
|
187
|
+
nodeId: z.string().describe("Figma node ID (frame/component ID)"),
|
|
188
|
+
scale: z.number().min(0.1).max(4).optional().describe("Export scale (0.1-4, default: 2)"),
|
|
189
|
+
format: z.enum(['png', 'jpg', 'svg']).optional().describe("Export format (default: png)")
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
export const CompareFigmaToElementSchema = z.object({
|
|
193
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
194
|
+
fileKey: z.string().describe("Figma file key"),
|
|
195
|
+
nodeId: z.string().describe("Figma frame/component ID"),
|
|
196
|
+
selector: z.string().describe("CSS selector for page element"),
|
|
197
|
+
threshold: z.number().min(0).max(1).optional().describe("Difference threshold (0-1, default: 0.05)"),
|
|
198
|
+
figmaScale: z.number().min(0.1).max(4).optional().describe("Figma export scale (default: 2)")
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
export const GetFigmaSpecsSchema = z.object({
|
|
202
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
203
|
+
fileKey: z.string().describe("Figma file key"),
|
|
204
|
+
nodeId: z.string().describe("Figma frame/component ID")
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
export const ParseFigmaUrlSchema = z.object({
|
|
208
|
+
url: z.string().describe("Full Figma URL or fileKey")
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
export const ListFigmaPagesSchema = z.object({
|
|
212
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
213
|
+
fileKey: z.string().describe("Figma file key or full Figma URL")
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
export const SearchFigmaFramesSchema = z.object({
|
|
217
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
218
|
+
fileKey: z.string().describe("Figma file key or full Figma URL"),
|
|
219
|
+
searchQuery: z.string().describe("Search query")
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
export const GetFigmaComponentsSchema = z.object({
|
|
223
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
224
|
+
fileKey: z.string().describe("Figma file key or full Figma URL")
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
export const GetFigmaStylesSchema = z.object({
|
|
228
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
229
|
+
fileKey: z.string().describe("Figma file key or full Figma URL")
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
export const GetFigmaColorPaletteSchema = z.object({
|
|
233
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
234
|
+
fileKey: z.string().describe("Figma file key or full Figma URL")
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
export const ConvertFigmaToCodeSchema = z.object({
|
|
238
|
+
figmaToken: z.string().optional().describe("Figma API token (optional if FIGMA_TOKEN env var is set)"),
|
|
239
|
+
fileKey: z.string().describe("Figma file key (from URL: figma.com/file/FILE_KEY/...)"),
|
|
240
|
+
nodeId: z.string().describe("Figma node ID (frame/component ID, formats: '123:456' or '123-456')"),
|
|
241
|
+
framework: z.enum(['react', 'react-typescript', 'html']).optional().describe("Target framework (default: react)"),
|
|
242
|
+
includeComments: z.boolean().optional().describe("Include descriptive comments in generated code (default: true)")
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Page analysis tools
|
|
246
|
+
export const SmartFindElementSchema = z.object({
|
|
247
|
+
description: z.string().describe("Natural language description of element to find (e.g., 'login button', 'email field')"),
|
|
248
|
+
maxResults: z.number().min(1).max(20).optional().describe("Maximum number of candidates to return (default: 5)"),
|
|
249
|
+
action: z.object({
|
|
250
|
+
type: z.enum(['click', 'type', 'scrollTo', 'screenshot', 'hover', 'setStyles']).describe("Action to perform on the best match"),
|
|
251
|
+
text: z.string().optional().describe("Text to type (required for 'type' action)"),
|
|
252
|
+
styles: z.array(z.object({
|
|
253
|
+
name: z.string(),
|
|
254
|
+
value: z.string()
|
|
255
|
+
})).optional().describe("Styles to apply (required for 'setStyles' action)"),
|
|
256
|
+
screenshot: z.boolean().optional().describe("Capture screenshot after action (default: false)"),
|
|
257
|
+
waitAfter: z.number().optional().describe("Wait time in ms after action"),
|
|
258
|
+
}).optional().describe("Optional action to perform on the best matching element"),
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
export const AnalyzePageSchema = z.object({
|
|
262
|
+
refresh: z.boolean().optional().describe("Force refresh of cached analysis (default: false)"),
|
|
263
|
+
includeAll: z.boolean().optional().describe("Include all elements on page, not just interactive ones (default: false). Useful for layout work and finding non-interactive elements to style."),
|
|
264
|
+
useLegacyFormat: z.boolean().optional().describe("Return legacy format instead of APOM (default: false - APOM is now the default format)"),
|
|
265
|
+
registerElements: z.boolean().optional().describe("Automatically register elements in selector resolver (default: true)"),
|
|
266
|
+
groupBy: z.enum(['type', 'flat']).optional().describe("Group elements by type or return flat structure (default: 'type')"),
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
export const GetElementByApomIdSchema = z.object({
|
|
270
|
+
id: z.string().describe("APOM element ID (e.g., 'input_20', 'button_45') from analyzePage result"),
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
export const GetAllInteractiveElementsSchema = z.object({
|
|
274
|
+
includeHidden: z.boolean().optional().describe("Include hidden elements (default: false)"),
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
export const FindElementsByTextSchema = z.object({
|
|
278
|
+
text: z.string().describe("Text to search for in elements"),
|
|
279
|
+
exact: z.boolean().optional().describe("Exact match only (default: false)"),
|
|
280
|
+
caseSensitive: z.boolean().optional().describe("Case sensitive search (default: false)"),
|
|
281
|
+
action: z.object({
|
|
282
|
+
type: z.enum(['click', 'type', 'scrollTo', 'screenshot', 'hover', 'setStyles']).describe("Action to perform on the first match"),
|
|
283
|
+
text: z.string().optional().describe("Text to type (required for 'type' action)"),
|
|
284
|
+
styles: z.array(z.object({
|
|
285
|
+
name: z.string(),
|
|
286
|
+
value: z.string()
|
|
287
|
+
})).optional().describe("Styles to apply (required for 'setStyles' action)"),
|
|
288
|
+
screenshot: z.boolean().optional().describe("Capture screenshot after action (default: false)"),
|
|
289
|
+
waitAfter: z.number().optional().describe("Wait time in ms after action"),
|
|
290
|
+
}).optional().describe("Optional action to perform on the first matching element"),
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Group selection tools
|
|
294
|
+
export const SelectFromGroupSchema = z.object({
|
|
295
|
+
name: z.string().describe("Name attribute of the radio/checkbox group"),
|
|
296
|
+
value: z.string().optional().describe("Single value to select (for radio or single checkbox)"),
|
|
297
|
+
values: z.array(z.string()).optional().describe("Multiple values to select (for checkbox group)"),
|
|
298
|
+
text: z.string().optional().describe("Label text to match (alternative to value)"),
|
|
299
|
+
texts: z.array(z.string()).optional().describe("Multiple label texts to match (for checkbox group)"),
|
|
300
|
+
mode: z.enum(['set', 'add', 'remove', 'toggle']).optional().describe("For checkboxes: 'set' (replace), 'add', 'remove', 'toggle' (default: 'set')"),
|
|
301
|
+
by: z.enum(['value', 'text', 'auto']).optional().describe("Match by value, text, or auto-detect (default: 'auto')"),
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Recorder tools (schemas created from inline definitions)
|
|
305
|
+
export const EnableRecorderSchema = z.object({
|
|
306
|
+
directory: z.string().optional().describe("Directory to save scenarios (optional, defaults to auto-detected project root)")
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
export const ExecuteScenarioSchema = z.object({
|
|
310
|
+
name: z.string().describe("Scenario name"),
|
|
311
|
+
projectId: z.string().optional().describe("Optional: Project ID (domain) to disambiguate scenarios with same name"),
|
|
312
|
+
parameters: z.record(z.any()).optional().describe("Execution parameters"),
|
|
313
|
+
executeDependencies: z.boolean().optional().describe("Execute dependencies (default: true)")
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
export const ListScenariosSchema = z.object({
|
|
317
|
+
directory: z.string().optional().describe("Directory where scenarios are stored (optional)")
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
export const SearchScenariosSchema = z.object({
|
|
321
|
+
text: z.string().optional().describe("Search text"),
|
|
322
|
+
tags: z.array(z.string()).optional().describe("Filter tags"),
|
|
323
|
+
directory: z.string().optional().describe("Directory where scenarios are stored (optional)")
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
export const GetScenarioInfoSchema = z.object({
|
|
327
|
+
name: z.string().describe("Scenario name"),
|
|
328
|
+
includeSecrets: z.boolean().optional().describe("Include secrets (default: false)"),
|
|
329
|
+
directory: z.string().optional().describe("Directory where scenarios are stored (optional)")
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
export const DeleteScenarioSchema = z.object({
|
|
333
|
+
name: z.string().describe("Scenario name"),
|
|
334
|
+
directory: z.string().optional().describe("Directory where scenarios are stored (optional)")
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
export const ExportScenarioAsCodeSchema = z.object({
|
|
338
|
+
scenarioName: z.string().describe("Name of scenario to export"),
|
|
339
|
+
language: z.enum(['playwright-typescript', 'playwright-python', 'selenium-python', 'selenium-java']).describe("Target test framework and language"),
|
|
340
|
+
cleanSelectors: z.boolean().optional().describe("Remove unstable CSS classes (default: true)"),
|
|
341
|
+
includeComments: z.boolean().optional().describe("Include descriptive comments (default: true)"),
|
|
342
|
+
generatePageObject: z.boolean().optional().describe("Also generate Page Object class for the page (default: false)"),
|
|
343
|
+
pageObjectClassName: z.string().optional().describe("Page Object class name (optional, auto-generated if not provided)"),
|
|
344
|
+
directory: z.string().optional().describe("Directory where scenarios are stored (optional)"),
|
|
345
|
+
appendToFile: z.string().optional().describe("Path to existing test file to append to (enables append mode)"),
|
|
346
|
+
testName: z.string().optional().describe("Override test name (default: from scenario name)"),
|
|
347
|
+
insertPosition: z.enum(['end', 'before', 'after']).optional().describe("Where to insert test: 'end' (default), 'before', or 'after' a reference test"),
|
|
348
|
+
referenceTestName: z.string().optional().describe("Reference test name for 'before'/'after' insertion")
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
export const GeneratePageObjectSchema = z.object({
|
|
352
|
+
className: z.string().optional().describe("Page Object class name (optional, auto-generated from page title/URL if not provided)"),
|
|
353
|
+
framework: z.enum(['playwright-typescript', 'playwright-python', 'selenium-python', 'selenium-java']).optional().describe("Target test framework (default: playwright-typescript)"),
|
|
354
|
+
includeComments: z.boolean().optional().describe("Include descriptive comments in generated code (default: true)"),
|
|
355
|
+
groupElements: z.boolean().optional().describe("Group elements by page sections (default: true)")
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Tab management tools
|
|
359
|
+
export const ListTabsSchema = z.object({});
|
|
360
|
+
|
|
361
|
+
export const SwitchTabSchema = z.object({
|
|
362
|
+
tab: z.union([
|
|
363
|
+
z.number().min(0).describe("Tab index (0-based)"),
|
|
364
|
+
z.string().describe("URL pattern to match (partial match)")
|
|
365
|
+
]).describe("Tab identifier: index number or URL pattern to match"),
|
|
366
|
+
});
|
|
367
|
+
|