browsirai 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.
- package/LICENSE +78 -0
- package/README.md +454 -0
- package/dist/bin.js +4929 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +4925 -0
- package/dist/cli.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +4172 -0
- package/dist/server.js.map +1 -0
- package/package.json +61 -0
- package/skills/browsirai/SKILL.md +722 -0
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: browsirai
|
|
3
|
+
description: Control your live Chrome browser session via MCP tools. Navigate, click, fill forms, take screenshots, read accessibility trees, inspect source code locations, and automate browser interactions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# browsirai
|
|
7
|
+
|
|
8
|
+
MCP server that connects AI coding agents to a running Chrome browser via Chrome DevTools Protocol. Interact with your live session -- logged-in state, cookies, and all open tabs.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- A Chromium-based browser (Chrome, Edge, Brave, Arc) with remote debugging enabled
|
|
13
|
+
- Node.js 22+
|
|
14
|
+
|
|
15
|
+
### Enable Remote Debugging
|
|
16
|
+
|
|
17
|
+
**Option A** -- Launch Chrome with a flag:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# macOS
|
|
21
|
+
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
|
|
22
|
+
|
|
23
|
+
# Linux
|
|
24
|
+
google-chrome --remote-debugging-port=9222
|
|
25
|
+
|
|
26
|
+
# Windows
|
|
27
|
+
chrome.exe --remote-debugging-port=9222
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Option B** -- Enable in browser: navigate to `chrome://inspect/#remote-debugging` and toggle the switch.
|
|
31
|
+
|
|
32
|
+
### Supported Browsers
|
|
33
|
+
|
|
34
|
+
Chrome, Edge, Brave, Arc, Vivaldi, Opera, Chromium. Discovery works on macOS, Linux, and Windows.
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Connect to browser on default port (9222)
|
|
40
|
+
browser_connect
|
|
41
|
+
|
|
42
|
+
# Or specify a custom port/host
|
|
43
|
+
browser_connect { "port": 9222, "host": "127.0.0.1" }
|
|
44
|
+
|
|
45
|
+
# List all open tabs
|
|
46
|
+
browser_tabs
|
|
47
|
+
|
|
48
|
+
# Navigate to a URL
|
|
49
|
+
browser_navigate { "url": "https://example.com" }
|
|
50
|
+
|
|
51
|
+
# Take a snapshot to see the page structure
|
|
52
|
+
browser_snapshot
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Core Workflow
|
|
56
|
+
|
|
57
|
+
The **snapshot-ref interaction pattern** is the primary way to work with page elements:
|
|
58
|
+
|
|
59
|
+
1. **Snapshot** -- Call `browser_snapshot` to get the accessibility tree. Each element receives an `@eN` ref (e.g., `@e1`, `@e2`, `@e15`).
|
|
60
|
+
2. **Interact** -- Use the `@eN` ref in `browser_click`, `browser_fill_form`, `browser_hover`, etc.
|
|
61
|
+
3. **Verify** -- Call `browser_screenshot` to visually confirm the result, or `browser_snapshot` again to check updated state.
|
|
62
|
+
|
|
63
|
+
Example snapshot output:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
@e1 heading "Welcome" level=1
|
|
67
|
+
@e2 link "Sign In"
|
|
68
|
+
@e3 textbox "Email" value=""
|
|
69
|
+
@e4 textbox "Password" value=""
|
|
70
|
+
@e5 button "Log In"
|
|
71
|
+
@e6 checkbox "Remember me"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
After a snapshot, refs remain valid until the page navigates or the DOM changes significantly. If a tool fails with "invalid ref", take a new snapshot.
|
|
75
|
+
|
|
76
|
+
## Tools Reference
|
|
77
|
+
|
|
78
|
+
### Navigation
|
|
79
|
+
|
|
80
|
+
#### `browser_navigate`
|
|
81
|
+
|
|
82
|
+
Navigate to a URL. Waits for the page to load.
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
browser_navigate { "url": "https://github.com" }
|
|
86
|
+
browser_navigate { "url": "https://example.com", "waitUntil": "networkidle" }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
| Param | Type | Default | Description |
|
|
90
|
+
|-------|------|---------|-------------|
|
|
91
|
+
| `url` | string | required | URL to navigate to |
|
|
92
|
+
| `waitUntil` | `"load"` \| `"domcontentloaded"` \| `"networkidle"` | `"load"` | When to consider navigation complete |
|
|
93
|
+
|
|
94
|
+
#### `browser_navigate_back`
|
|
95
|
+
|
|
96
|
+
Navigate back or forward in browser history.
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
browser_navigate_back
|
|
100
|
+
browser_navigate_back { "direction": "forward" }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
| Param | Type | Default | Description |
|
|
104
|
+
|-------|------|---------|-------------|
|
|
105
|
+
| `direction` | `"back"` \| `"forward"` | `"back"` | History navigation direction |
|
|
106
|
+
|
|
107
|
+
#### `browser_wait_for`
|
|
108
|
+
|
|
109
|
+
Wait for a condition before proceeding. Default timeout: 30 seconds.
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
browser_wait_for { "text": "Successfully saved" }
|
|
113
|
+
browser_wait_for { "textGone": "Loading..." }
|
|
114
|
+
browser_wait_for { "selector": ".results-table" }
|
|
115
|
+
browser_wait_for { "selector": ".modal", "state": "hidden" }
|
|
116
|
+
browser_wait_for { "url": "**/dashboard**" }
|
|
117
|
+
browser_wait_for { "fn": "document.querySelectorAll('.item').length > 5" }
|
|
118
|
+
browser_wait_for { "time": 2 }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| Param | Type | Description |
|
|
122
|
+
|-------|------|-------------|
|
|
123
|
+
| `text` | string | Wait until text appears in page body |
|
|
124
|
+
| `textGone` | string | Wait until text disappears from page body |
|
|
125
|
+
| `selector` | string | Wait until a CSS selector matches an element |
|
|
126
|
+
| `state` | `"hidden"` | Combined with `selector` -- wait until element is hidden |
|
|
127
|
+
| `url` | string | Wait until URL matches glob pattern (supports `*` and `**`) |
|
|
128
|
+
| `fn` | string | Wait until JS expression evaluates to truthy |
|
|
129
|
+
| `time` | number | Simple delay in seconds |
|
|
130
|
+
| `timeout` | number | Override timeout (seconds if <=60, milliseconds if >60) |
|
|
131
|
+
|
|
132
|
+
### Observation
|
|
133
|
+
|
|
134
|
+
#### `browser_snapshot`
|
|
135
|
+
|
|
136
|
+
Capture the accessibility tree with `@eN` refs. This is the primary tool for understanding page structure.
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
browser_snapshot
|
|
140
|
+
browser_snapshot { "compact": true }
|
|
141
|
+
browser_snapshot { "interactive": true }
|
|
142
|
+
browser_snapshot { "selector": "#main-content" }
|
|
143
|
+
browser_snapshot { "depth": 3 }
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Param | Type | Default | Description |
|
|
147
|
+
|-------|------|---------|-------------|
|
|
148
|
+
| `selector` | string | - | CSS selector to scope the snapshot |
|
|
149
|
+
| `compact` | boolean | false | Hide InlineTextBox nodes and empty wrappers |
|
|
150
|
+
| `interactive` | boolean | false | Only show interactive elements (buttons, links, inputs, etc.) |
|
|
151
|
+
| `cursor` | boolean | false | Include elements with `cursor:pointer` style |
|
|
152
|
+
| `depth` | number | 100 | Maximum tree depth |
|
|
153
|
+
|
|
154
|
+
Interactive roles included when `interactive: true`: button, link, textbox, checkbox, radio, combobox, listbox, menuitem, menuitemcheckbox, menuitemradio, option, searchbox, slider, spinbutton, switch, tab, treeitem.
|
|
155
|
+
|
|
156
|
+
#### `browser_screenshot`
|
|
157
|
+
|
|
158
|
+
Take a screenshot. Returns base64-encoded image data.
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
browser_screenshot
|
|
162
|
+
browser_screenshot { "fullPage": true }
|
|
163
|
+
browser_screenshot { "selector": "#hero-section" }
|
|
164
|
+
browser_screenshot { "format": "jpeg", "quality": 80 }
|
|
165
|
+
browser_screenshot { "annotate": true }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
| Param | Type | Default | Description |
|
|
169
|
+
|-------|------|---------|-------------|
|
|
170
|
+
| `selector` | string | - | CSS selector to screenshot a specific element |
|
|
171
|
+
| `fullPage` | boolean | false | Capture full scrollable page, not just viewport |
|
|
172
|
+
| `format` | `"png"` \| `"jpeg"` | `"png"` | Image format |
|
|
173
|
+
| `quality` | number | - | JPEG quality (0-100). Only for jpeg format |
|
|
174
|
+
| `annotate` | boolean | false | Overlay numbered labels on interactive elements |
|
|
175
|
+
|
|
176
|
+
#### `browser_html`
|
|
177
|
+
|
|
178
|
+
Get raw HTML content of the page or a specific element.
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
browser_html
|
|
182
|
+
browser_html { "selector": "#app" }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
| Param | Type | Description |
|
|
186
|
+
|-------|------|-------------|
|
|
187
|
+
| `selector` | string | CSS selector to scope HTML output |
|
|
188
|
+
|
|
189
|
+
#### `browser_tabs`
|
|
190
|
+
|
|
191
|
+
List open browser tabs. Only shows page-type targets (excludes service workers, extensions).
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
browser_tabs
|
|
195
|
+
browser_tabs { "filter": "*github.com*" }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
| Param | Type | Description |
|
|
199
|
+
|-------|------|-------------|
|
|
200
|
+
| `filter` | string | Glob-style URL filter pattern |
|
|
201
|
+
|
|
202
|
+
#### `browser_console_messages`
|
|
203
|
+
|
|
204
|
+
Retrieve captured console messages.
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
browser_console_messages
|
|
208
|
+
browser_console_messages { "level": "error" }
|
|
209
|
+
browser_console_messages { "limit": 20 }
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
| Param | Type | Description |
|
|
213
|
+
|-------|------|-------------|
|
|
214
|
+
| `limit` | number | Maximum messages to return (default: 1000, most recent) |
|
|
215
|
+
| `level` | `"log"` \| `"info"` \| `"warn"` \| `"error"` | Filter by minimum severity |
|
|
216
|
+
|
|
217
|
+
#### `browser_network_requests`
|
|
218
|
+
|
|
219
|
+
List captured network requests.
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
browser_network_requests
|
|
223
|
+
browser_network_requests { "filter": "*api*" }
|
|
224
|
+
browser_network_requests { "includeHeaders": true, "includeStatic": false }
|
|
225
|
+
browser_network_requests { "limit": 10 }
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Param | Type | Default | Description |
|
|
229
|
+
|-------|------|---------|-------------|
|
|
230
|
+
| `filter` | string | - | Glob-style URL filter |
|
|
231
|
+
| `limit` | number | - | Maximum requests to return (most recent) |
|
|
232
|
+
| `includeHeaders` | boolean | false | Include request/response headers |
|
|
233
|
+
| `includeStatic` | boolean | true | Include static resources (JS, CSS, images, fonts) |
|
|
234
|
+
|
|
235
|
+
### Interaction
|
|
236
|
+
|
|
237
|
+
#### `browser_click`
|
|
238
|
+
|
|
239
|
+
Click an element. Supports three targeting methods: ref, selector, or coordinates.
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
browser_click { "ref": "@e5" }
|
|
243
|
+
browser_click { "selector": "#submit-btn" }
|
|
244
|
+
browser_click { "x": 150, "y": 300 }
|
|
245
|
+
browser_click { "ref": "@e2", "newTab": true }
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
| Param | Type | Description |
|
|
249
|
+
|-------|------|-------------|
|
|
250
|
+
| `ref` | string | `@eN` ref from snapshot |
|
|
251
|
+
| `selector` | string | CSS selector |
|
|
252
|
+
| `x`, `y` | number | CSS pixel coordinates (see Coordinates section) |
|
|
253
|
+
| `newTab` | boolean | Open link in new tab (adds Meta/Ctrl modifier) |
|
|
254
|
+
|
|
255
|
+
Must provide one of: `ref`, `selector`, or both `x` and `y`.
|
|
256
|
+
|
|
257
|
+
The click sequence: scrolls element into view, computes center coordinates from the box model, then dispatches mouseMoved -> mousePressed -> 50ms delay -> mouseReleased.
|
|
258
|
+
|
|
259
|
+
#### `browser_fill_form`
|
|
260
|
+
|
|
261
|
+
Fill a form field. Clears existing value before typing. Dispatches `input` and `change` events.
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
browser_fill_form { "ref": "@e3", "value": "user@example.com" }
|
|
265
|
+
browser_fill_form { "selector": "#search-input", "value": "search query" }
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
| Param | Type | Description |
|
|
269
|
+
|-------|------|-------------|
|
|
270
|
+
| `ref` | string | `@eN` ref from snapshot |
|
|
271
|
+
| `selector` | string | CSS selector |
|
|
272
|
+
| `value` | string | Text to enter |
|
|
273
|
+
|
|
274
|
+
Must provide either `ref` or `selector`.
|
|
275
|
+
|
|
276
|
+
Handles different field types automatically:
|
|
277
|
+
- **textbox**: focus -> clear -> insert text -> dispatch events
|
|
278
|
+
- **checkbox/radio**: clicks to toggle
|
|
279
|
+
- **combobox (select)**: sets value directly
|
|
280
|
+
- **slider**: sets value and dispatches events
|
|
281
|
+
|
|
282
|
+
Note: Will not fill readonly or disabled fields (returns an error).
|
|
283
|
+
|
|
284
|
+
#### `browser_type`
|
|
285
|
+
|
|
286
|
+
Type text into the focused element or a specific ref. Unlike `browser_fill_form`, does NOT clear existing value first.
|
|
287
|
+
|
|
288
|
+
```
|
|
289
|
+
browser_type { "text": "Hello world" }
|
|
290
|
+
browser_type { "text": "search term", "ref": "@e3", "submit": true }
|
|
291
|
+
browser_type { "text": "slowly typed", "slowly": true }
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
| Param | Type | Default | Description |
|
|
295
|
+
|-------|------|---------|-------------|
|
|
296
|
+
| `text` | string | required | Text to type |
|
|
297
|
+
| `ref` | string | - | `@eN` ref to focus before typing |
|
|
298
|
+
| `slowly` | boolean | false | Type character-by-character with key events |
|
|
299
|
+
| `submit` | boolean | false | Press Enter after typing |
|
|
300
|
+
|
|
301
|
+
- **Fast mode** (default): uses `Input.insertText` -- single CDP call, instant.
|
|
302
|
+
- **Slow mode** (`slowly: true`): dispatches individual keyDown/char/keyUp per character. Use for apps that listen to individual key events.
|
|
303
|
+
- Use `browser_type` (not `browser_evaluate`) to enter text in **cross-origin iframes**.
|
|
304
|
+
|
|
305
|
+
#### `browser_press_key`
|
|
306
|
+
|
|
307
|
+
Press a keyboard key or key combination.
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
browser_press_key { "key": "Enter" }
|
|
311
|
+
browser_press_key { "key": "Tab" }
|
|
312
|
+
browser_press_key { "key": "Control+c" }
|
|
313
|
+
browser_press_key { "key": "Control+Shift+a" }
|
|
314
|
+
browser_press_key { "key": "Escape" }
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
| Param | Type | Description |
|
|
318
|
+
|-------|------|-------------|
|
|
319
|
+
| `key` | string | Key name or combination with `+` separator |
|
|
320
|
+
|
|
321
|
+
Supported keys: Enter, Tab, Escape, Backspace, Delete, ArrowLeft/Up/Right/Down, Home, End, PageUp, PageDown, Space, F1-F12, plus any single character.
|
|
322
|
+
|
|
323
|
+
Modifier keys: Control, Shift, Alt, Meta. Combine with `+`: `Control+c`, `Meta+a`, `Control+Shift+Tab`.
|
|
324
|
+
|
|
325
|
+
#### `browser_hover`
|
|
326
|
+
|
|
327
|
+
Hover over an element. Triggers mouseover/mouseenter events.
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
browser_hover { "ref": "@e7" }
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
| Param | Type | Description |
|
|
334
|
+
|-------|------|-------------|
|
|
335
|
+
| `ref` | string | `@eN` ref from snapshot (required) |
|
|
336
|
+
|
|
337
|
+
#### `browser_drag`
|
|
338
|
+
|
|
339
|
+
Drag from one element to another. Uses synthesized mouse events with intermediate move points.
|
|
340
|
+
|
|
341
|
+
```
|
|
342
|
+
browser_drag { "startRef": "@e3", "endRef": "@e8" }
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
| Param | Type | Description |
|
|
346
|
+
|-------|------|-------------|
|
|
347
|
+
| `startRef` | string | `@eN` ref for the drag source |
|
|
348
|
+
| `endRef` | string | `@eN` ref for the drop target |
|
|
349
|
+
|
|
350
|
+
Drag sequence: mouseMoved(start) -> mousePressed(start) -> intermediate mouseMoved steps -> mouseMoved(end) -> mouseReleased(end).
|
|
351
|
+
|
|
352
|
+
#### `browser_scroll`
|
|
353
|
+
|
|
354
|
+
Scroll the page or a specific element.
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
browser_scroll { "direction": "down" }
|
|
358
|
+
browser_scroll { "direction": "down", "pixels": 500 }
|
|
359
|
+
browser_scroll { "selector": ".sidebar", "direction": "down" }
|
|
360
|
+
browser_scroll { "selector": "#target-element" }
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
| Param | Type | Default | Description |
|
|
364
|
+
|-------|------|---------|-------------|
|
|
365
|
+
| `direction` | `"up"` \| `"down"` \| `"left"` \| `"right"` | - | Scroll direction |
|
|
366
|
+
| `pixels` | number | 300 | Pixels to scroll |
|
|
367
|
+
| `selector` | string | - | Scrollable container, or element to scroll into view |
|
|
368
|
+
|
|
369
|
+
Three modes:
|
|
370
|
+
- **selector only** (no direction): scrolls the element into view (centered)
|
|
371
|
+
- **selector + direction**: scrolls within that container
|
|
372
|
+
- **direction only**: scrolls the page viewport
|
|
373
|
+
|
|
374
|
+
#### `browser_select_option`
|
|
375
|
+
|
|
376
|
+
Select option(s) in a `<select>` element. Matches by value attribute or visible label text.
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
browser_select_option { "ref": "@e12", "values": ["us-east-1"] }
|
|
380
|
+
browser_select_option { "ref": "@e12", "values": ["Option A", "Option C"] }
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
| Param | Type | Description |
|
|
384
|
+
|-------|------|-------------|
|
|
385
|
+
| `ref` | string | `@eN` ref (required) |
|
|
386
|
+
| `values` | string[] | Values or label text to select |
|
|
387
|
+
|
|
388
|
+
### Dialog & File
|
|
389
|
+
|
|
390
|
+
#### `browser_handle_dialog`
|
|
391
|
+
|
|
392
|
+
Accept or dismiss JavaScript dialogs (alert, confirm, prompt, beforeunload).
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
browser_handle_dialog { "accept": true }
|
|
396
|
+
browser_handle_dialog { "accept": false }
|
|
397
|
+
browser_handle_dialog { "accept": true, "promptText": "my input" }
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
| Param | Type | Description |
|
|
401
|
+
|-------|------|-------------|
|
|
402
|
+
| `accept` | boolean | Accept (true) or dismiss (false) the dialog |
|
|
403
|
+
| `promptText` | string | Text to enter in a prompt dialog |
|
|
404
|
+
|
|
405
|
+
Waits up to 5 seconds for a dialog to appear if none is currently pending.
|
|
406
|
+
|
|
407
|
+
#### `browser_file_upload`
|
|
408
|
+
|
|
409
|
+
Upload files to a file input element.
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
browser_file_upload { "ref": "@e9", "paths": ["/Users/me/photo.jpg"] }
|
|
413
|
+
browser_file_upload { "ref": "@e9", "paths": ["/tmp/doc1.pdf", "/tmp/doc2.pdf"] }
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
| Param | Type | Description |
|
|
417
|
+
|-------|------|-------------|
|
|
418
|
+
| `ref` | string | `@eN` ref for the file input (required) |
|
|
419
|
+
| `paths` | string[] | Absolute file paths to upload |
|
|
420
|
+
|
|
421
|
+
### Lifecycle
|
|
422
|
+
|
|
423
|
+
#### `browser_connect`
|
|
424
|
+
|
|
425
|
+
Connect to a running browser instance via CDP.
|
|
426
|
+
|
|
427
|
+
```
|
|
428
|
+
browser_connect
|
|
429
|
+
browser_connect { "port": 9222 }
|
|
430
|
+
browser_connect { "host": "192.168.1.10", "port": 9222 }
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
| Param | Type | Default | Description |
|
|
434
|
+
|-------|------|---------|-------------|
|
|
435
|
+
| `port` | number | 9222 | Debug port |
|
|
436
|
+
| `host` | string | `"127.0.0.1"` | Host address |
|
|
437
|
+
|
|
438
|
+
#### `browser_list`
|
|
439
|
+
|
|
440
|
+
List all discoverable browser instances (scans default ports 9222, 9229).
|
|
441
|
+
|
|
442
|
+
```
|
|
443
|
+
browser_list
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
Returns browser name, version, and WebSocket debugger URL for each instance found.
|
|
447
|
+
|
|
448
|
+
#### `browser_close`
|
|
449
|
+
|
|
450
|
+
Close or detach from browser tabs.
|
|
451
|
+
|
|
452
|
+
```
|
|
453
|
+
browser_close
|
|
454
|
+
browser_close { "force": true }
|
|
455
|
+
browser_close { "force": true, "targetId": "ABC123..." }
|
|
456
|
+
browser_close { "force": true, "closeAll": true }
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
| Param | Type | Default | Description |
|
|
460
|
+
|-------|------|---------|-------------|
|
|
461
|
+
| `force` | boolean | false | Actually close tab(s) instead of just detaching |
|
|
462
|
+
| `targetId` | string | - | Specific tab to close |
|
|
463
|
+
| `closeAll` | boolean | false | Close all page tabs |
|
|
464
|
+
|
|
465
|
+
Without `force`, simply detaches the session (tabs remain open).
|
|
466
|
+
|
|
467
|
+
#### `browser_resize`
|
|
468
|
+
|
|
469
|
+
Resize the browser viewport.
|
|
470
|
+
|
|
471
|
+
```
|
|
472
|
+
browser_resize { "width": 1280, "height": 720 }
|
|
473
|
+
browser_resize { "width": 375, "height": 812, "deviceScaleFactor": 3 }
|
|
474
|
+
browser_resize { "preset": "mobile" }
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
| Param | Type | Description |
|
|
478
|
+
|-------|------|-------------|
|
|
479
|
+
| `width` | number | Viewport width in CSS pixels |
|
|
480
|
+
| `height` | number | Viewport height in CSS pixels |
|
|
481
|
+
| `deviceScaleFactor` | number | Device pixel ratio (DPR) override |
|
|
482
|
+
| `preset` | string | Device preset name |
|
|
483
|
+
|
|
484
|
+
Presets: `mobile` (375x667), `tablet` (768x1024), `desktop` (1280x720), `fullhd` (1920x1080), `reset` (clear override).
|
|
485
|
+
|
|
486
|
+
Must provide either `width` + `height` together, or a `preset`.
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
browser_resize { "preset": "reset" }
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Use `preset: "reset"` to clear the device metrics override and restore the browser's native viewport.
|
|
493
|
+
|
|
494
|
+
### Advanced Observation
|
|
495
|
+
|
|
496
|
+
#### `browser_annotated_screenshot`
|
|
497
|
+
|
|
498
|
+
Take a screenshot with numbered labels overlaid on interactive elements. Useful for identifying clickable elements visually.
|
|
499
|
+
|
|
500
|
+
```
|
|
501
|
+
browser_annotated_screenshot
|
|
502
|
+
browser_annotated_screenshot { "selector": "#main-content" }
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
| Param | Type | Description |
|
|
506
|
+
|-------|------|-------------|
|
|
507
|
+
| `selector` | string | CSS selector to scope the annotated area |
|
|
508
|
+
|
|
509
|
+
Returns an image with numbered labels plus a text index mapping each label to its role, name, and `@eN` ref.
|
|
510
|
+
|
|
511
|
+
#### `browser_inspect_source`
|
|
512
|
+
|
|
513
|
+
Inspect a DOM element and return its source code location. Maps UI elements back to their source files -- file path, line number, and component name.
|
|
514
|
+
|
|
515
|
+
```
|
|
516
|
+
browser_inspect_source { "selector": "h1" }
|
|
517
|
+
browser_inspect_source { "ref": "@e5" }
|
|
518
|
+
browser_inspect_source { "selector": "nav" }
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
| Param | Type | Description |
|
|
522
|
+
|-------|------|-------------|
|
|
523
|
+
| `ref` | string | `@eN` ref from snapshot |
|
|
524
|
+
| `selector` | string | CSS selector |
|
|
525
|
+
|
|
526
|
+
Must provide either `ref` or `selector`.
|
|
527
|
+
|
|
528
|
+
Returns:
|
|
529
|
+
- **Element**: tag name
|
|
530
|
+
- **Component**: nearest framework component name
|
|
531
|
+
- **Source**: file path, line number, column number
|
|
532
|
+
- **Component Stack**: full ancestor component chain with source locations
|
|
533
|
+
|
|
534
|
+
Supported frameworks:
|
|
535
|
+
- **React**: Walks the Fiber tree and parses `jsxDEV()` calls in `Function.toString()` to extract `fileName`/`lineNumber` embedded by `@babel/plugin-transform-react-jsx-source` (works with Vite, CRA, Next.js dev mode)
|
|
536
|
+
- **Vue**: Reads `__vueParentComponent.type.__file`
|
|
537
|
+
- **Svelte**: Reads `__svelte_meta.loc`
|
|
538
|
+
|
|
539
|
+
Note: Only works in **development mode** where source metadata is preserved. Production builds strip this information.
|
|
540
|
+
|
|
541
|
+
### Code Execution
|
|
542
|
+
|
|
543
|
+
#### `browser_evaluate`
|
|
544
|
+
|
|
545
|
+
Evaluate JavaScript in the page context. Supports async expressions.
|
|
546
|
+
|
|
547
|
+
```
|
|
548
|
+
browser_evaluate { "expression": "document.title" }
|
|
549
|
+
browser_evaluate { "expression": "document.querySelectorAll('a').length" }
|
|
550
|
+
browser_evaluate { "expression": "await fetch('/api/status').then(r => r.json())" }
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
| Param | Type | Description |
|
|
554
|
+
|-------|------|-------------|
|
|
555
|
+
| `expression` | string | JavaScript expression to evaluate |
|
|
556
|
+
| `frameId` | string | Target frame ID for execution |
|
|
557
|
+
|
|
558
|
+
Returns the evaluated result. Handles primitives, objects, DOM nodes (serialized to description), null, and undefined. Async expressions are awaited automatically.
|
|
559
|
+
|
|
560
|
+
## Coordinates
|
|
561
|
+
|
|
562
|
+
Screenshot image dimensions differ from CSS pixel dimensions due to device pixel ratio (DPR).
|
|
563
|
+
|
|
564
|
+
```
|
|
565
|
+
Screenshot pixels = CSS pixels x DPR
|
|
566
|
+
CSS pixels = Screenshot pixels / DPR
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
- `browser_screenshot` detects DPR using a 3-level cascade: Page.getLayoutMetrics -> Emulation.getDeviceMetricsOverride -> window.devicePixelRatio
|
|
570
|
+
- `browser_click` coordinates (`x`, `y`) use **CSS pixels**
|
|
571
|
+
- Typical Retina display: DPR = 2, so divide screenshot pixel coordinates by 2
|
|
572
|
+
|
|
573
|
+
## Security
|
|
574
|
+
|
|
575
|
+
Network requests are automatically redacted to prevent secret leakage:
|
|
576
|
+
|
|
577
|
+
- **Headers**: Authorization, Cookie, Set-Cookie, X-API-Key, X-Auth-Token, X-CSRF-Token, Proxy-Authorization, and other auth-related headers are replaced with `[REDACTED]`
|
|
578
|
+
- **Body fields**: password, secret, token, api_key, apiKey, access_token, refresh_token, client_secret, private_key are redacted in JSON bodies
|
|
579
|
+
- **Inline secrets**: JWTs (`eyJ...`) are replaced with `[REDACTED_JWT]`, Bearer tokens with `Bearer [REDACTED]`
|
|
580
|
+
|
|
581
|
+
## Tips & Best Practices
|
|
582
|
+
|
|
583
|
+
- **Prefer `browser_snapshot` over `browser_html`** for understanding page structure. The accessibility tree is semantic, compact, and provides `@eN` refs for interaction.
|
|
584
|
+
- **Use `@eN` refs for reliable targeting.** Refs are tied to accessibility tree nodes and resolve to exact DOM elements. CSS selectors can be fragile if the DOM changes.
|
|
585
|
+
- **Use `browser_type` for cross-origin iframes** -- `browser_evaluate` cannot access cross-origin content, but `Input.insertText` works regardless of origin.
|
|
586
|
+
- **`browser_fill_form` clears existing value** before typing. Use `browser_type` if you want to append to existing text.
|
|
587
|
+
- **Check `browser_console_messages` after interactions** to catch JavaScript errors or failed API calls.
|
|
588
|
+
- **Take a new snapshot after navigation or DOM changes.** Refs from old snapshots become stale.
|
|
589
|
+
- **Use `browser_snapshot { "interactive": true }`** on complex pages to filter to only actionable elements (buttons, links, inputs).
|
|
590
|
+
- **Use `browser_snapshot { "compact": true }`** to reduce noise from inline text nodes.
|
|
591
|
+
- **Scroll before screenshotting** if the target content is below the fold. Use `browser_scroll { "direction": "down" }` or `browser_scroll { "selector": "#element" }` to scroll it into view.
|
|
592
|
+
|
|
593
|
+
## Common Patterns
|
|
594
|
+
|
|
595
|
+
### Login Flow
|
|
596
|
+
|
|
597
|
+
```
|
|
598
|
+
# 1. Navigate to login page
|
|
599
|
+
browser_navigate { "url": "https://app.example.com/login" }
|
|
600
|
+
|
|
601
|
+
# 2. Snapshot to find form fields
|
|
602
|
+
browser_snapshot
|
|
603
|
+
|
|
604
|
+
# 3. Fill email and password (using refs from snapshot)
|
|
605
|
+
browser_fill_form { "ref": "@e3", "value": "user@example.com" }
|
|
606
|
+
browser_fill_form { "ref": "@e4", "value": "mypassword123" }
|
|
607
|
+
|
|
608
|
+
# 4. Click the login button
|
|
609
|
+
browser_click { "ref": "@e5" }
|
|
610
|
+
|
|
611
|
+
# 5. Wait for navigation to complete
|
|
612
|
+
browser_wait_for { "url": "**/dashboard**" }
|
|
613
|
+
|
|
614
|
+
# 6. Verify with screenshot
|
|
615
|
+
browser_screenshot
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### Form Filling
|
|
619
|
+
|
|
620
|
+
```
|
|
621
|
+
# 1. Navigate and snapshot
|
|
622
|
+
browser_navigate { "url": "https://app.example.com/settings" }
|
|
623
|
+
browser_snapshot { "interactive": true }
|
|
624
|
+
|
|
625
|
+
# 2. Fill each field using refs
|
|
626
|
+
browser_fill_form { "ref": "@e2", "value": "John Doe" }
|
|
627
|
+
browser_fill_form { "ref": "@e3", "value": "john@example.com" }
|
|
628
|
+
browser_select_option { "ref": "@e4", "values": ["UTC-5"] }
|
|
629
|
+
|
|
630
|
+
# 3. Submit the form
|
|
631
|
+
browser_click { "ref": "@e6" }
|
|
632
|
+
|
|
633
|
+
# 4. Wait for confirmation
|
|
634
|
+
browser_wait_for { "text": "Settings saved" }
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Data Extraction
|
|
638
|
+
|
|
639
|
+
```
|
|
640
|
+
# 1. Navigate to the data page
|
|
641
|
+
browser_navigate { "url": "https://example.com/products" }
|
|
642
|
+
|
|
643
|
+
# 2. Use evaluate to extract structured data
|
|
644
|
+
browser_evaluate { "expression": "JSON.stringify([...document.querySelectorAll('.product')].map(el => ({ name: el.querySelector('h2').textContent, price: el.querySelector('.price').textContent })))" }
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### Visual Testing
|
|
648
|
+
|
|
649
|
+
```
|
|
650
|
+
# 1. Navigate and set viewport
|
|
651
|
+
browser_navigate { "url": "https://example.com" }
|
|
652
|
+
browser_resize { "width": 1440, "height": 900 }
|
|
653
|
+
browser_screenshot { "fullPage": true }
|
|
654
|
+
|
|
655
|
+
# 2. Test mobile viewport
|
|
656
|
+
browser_resize { "width": 375, "height": 812, "deviceScaleFactor": 3 }
|
|
657
|
+
browser_screenshot { "fullPage": true }
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
### Debugging API Calls
|
|
661
|
+
|
|
662
|
+
```
|
|
663
|
+
# 1. Navigate and perform actions
|
|
664
|
+
browser_navigate { "url": "https://app.example.com" }
|
|
665
|
+
browser_click { "ref": "@e5" }
|
|
666
|
+
|
|
667
|
+
# 2. Check network requests for API calls
|
|
668
|
+
browser_network_requests { "filter": "*api*", "includeStatic": false }
|
|
669
|
+
|
|
670
|
+
# 3. Check for console errors
|
|
671
|
+
browser_console_messages { "level": "error" }
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
### Waiting for Dynamic Content
|
|
675
|
+
|
|
676
|
+
```
|
|
677
|
+
# Wait for text to appear after an action
|
|
678
|
+
browser_click { "ref": "@e3" }
|
|
679
|
+
browser_wait_for { "text": "Results loaded" }
|
|
680
|
+
|
|
681
|
+
# Wait for a loading spinner to disappear
|
|
682
|
+
browser_wait_for { "selector": ".spinner", "state": "hidden" }
|
|
683
|
+
|
|
684
|
+
# Wait for a custom JS condition
|
|
685
|
+
browser_wait_for { "fn": "window.__dataLoaded === true" }
|
|
686
|
+
|
|
687
|
+
# Wait for URL to change after form submission
|
|
688
|
+
browser_wait_for { "url": "**/confirmation**" }
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
### Finding Source Code for UI Elements
|
|
692
|
+
|
|
693
|
+
```
|
|
694
|
+
# 1. Snapshot the page to identify elements
|
|
695
|
+
browser_snapshot
|
|
696
|
+
|
|
697
|
+
# 2. Inspect a specific element's source
|
|
698
|
+
browser_inspect_source { "ref": "@e5" }
|
|
699
|
+
# → Component: Hero
|
|
700
|
+
# → Source: /src/routes/index.tsx:64:11
|
|
701
|
+
|
|
702
|
+
# 3. Or use a CSS selector directly
|
|
703
|
+
browser_inspect_source { "selector": "nav" }
|
|
704
|
+
# → Component: Navbar
|
|
705
|
+
# → Source: /src/components/Navbar.tsx:12:5
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
### Working with Multiple Tabs
|
|
709
|
+
|
|
710
|
+
```
|
|
711
|
+
# List all tabs
|
|
712
|
+
browser_tabs
|
|
713
|
+
|
|
714
|
+
# Open a link in a new tab
|
|
715
|
+
browser_click { "ref": "@e10", "newTab": true }
|
|
716
|
+
|
|
717
|
+
# List tabs again to see the new one
|
|
718
|
+
browser_tabs
|
|
719
|
+
|
|
720
|
+
# Close a specific tab by its target ID
|
|
721
|
+
browser_close { "force": true, "targetId": "TARGET_ID_HERE" }
|
|
722
|
+
```
|