mcp-web-inspector 0.1.3 → 0.2.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/README.md +68 -9
- package/dist/index.js +6 -1
- package/dist/toolConstants.d.ts +7 -0
- package/dist/toolConstants.js +46 -0
- package/dist/toolHandler.d.ts +6 -6
- package/dist/toolHandler.js +71 -202
- package/dist/tools/browser/ancestorInspection.d.ts +2 -0
- package/dist/tools/browser/ancestorInspection.js +159 -29
- package/dist/tools/browser/base.d.ts +65 -0
- package/dist/tools/browser/base.js +147 -0
- package/dist/tools/browser/computedStyles.d.ts +1 -0
- package/dist/tools/browser/computedStyles.js +8 -21
- package/dist/tools/browser/console/__tests__/console.test.d.ts +1 -0
- package/dist/tools/browser/console/__tests__/console.test.js +200 -0
- package/dist/tools/browser/console/__tests__/tabSwitchConsole.test.d.ts +8 -0
- package/dist/tools/browser/console/__tests__/tabSwitchConsole.test.js +83 -0
- package/dist/tools/browser/console/get_console_logs.d.ts +33 -0
- package/dist/tools/browser/console/get_console_logs.js +133 -0
- package/dist/tools/browser/console/index.d.ts +1 -0
- package/dist/tools/browser/console/index.js +1 -0
- package/dist/tools/browser/content/__tests__/output.test.d.ts +1 -0
- package/dist/tools/browser/content/__tests__/output.test.js +108 -0
- package/dist/tools/browser/content/__tests__/screenshot.test.d.ts +1 -0
- package/dist/tools/browser/content/__tests__/screenshot.test.js +167 -0
- package/dist/tools/browser/content/__tests__/visiblePage.test.d.ts +1 -0
- package/dist/tools/browser/content/__tests__/visiblePage.test.js +381 -0
- package/dist/tools/browser/content/get_html.d.ts +9 -0
- package/dist/tools/browser/content/get_html.js +121 -0
- package/dist/tools/browser/content/get_text.d.ts +9 -0
- package/dist/tools/browser/content/get_text.js +96 -0
- package/dist/tools/browser/content/index.d.ts +3 -0
- package/dist/tools/browser/content/index.js +3 -0
- package/dist/tools/browser/content/screenshot.d.ts +14 -0
- package/dist/tools/browser/content/screenshot.js +106 -0
- package/dist/tools/browser/elementVisibility.js +9 -13
- package/dist/tools/browser/evaluation/evaluate.d.ts +13 -0
- package/dist/tools/browser/evaluation/evaluate.js +97 -0
- package/dist/tools/browser/evaluation/index.d.ts +1 -0
- package/dist/tools/browser/evaluation/index.js +1 -0
- package/dist/tools/browser/inspectDom.js +34 -14
- package/dist/tools/browser/inspection/__tests__/compareElementAlignment.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/compareElementAlignment.test.js +173 -0
- package/dist/tools/browser/inspection/__tests__/computedStyles.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/computedStyles.test.js +146 -0
- package/dist/tools/browser/inspection/__tests__/elementExists.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/elementExists.test.js +149 -0
- package/dist/tools/browser/inspection/__tests__/elementVisibility.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/elementVisibility.test.js +405 -0
- package/dist/tools/browser/inspection/__tests__/findByText.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/findByText.test.js +199 -0
- package/dist/tools/browser/inspection/__tests__/getTestIds.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/getTestIds.test.js +251 -0
- package/dist/tools/browser/inspection/__tests__/inspectAncestors.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/inspectAncestors.test.js +354 -0
- package/dist/tools/browser/inspection/__tests__/inspectDom.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/inspectDom.test.js +1070 -0
- package/dist/tools/browser/inspection/__tests__/measureElement.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/measureElement.test.js +333 -0
- package/dist/tools/browser/inspection/__tests__/querySelectorAll.test.d.ts +1 -0
- package/dist/tools/browser/inspection/__tests__/querySelectorAll.test.js +480 -0
- package/dist/tools/browser/inspection/check_visibility.d.ts +13 -0
- package/dist/tools/browser/inspection/check_visibility.js +245 -0
- package/dist/tools/browser/inspection/compare_element_alignment.d.ts +12 -0
- package/dist/tools/browser/inspection/compare_element_alignment.js +200 -0
- package/dist/tools/browser/inspection/element_exists.d.ts +10 -0
- package/dist/tools/browser/inspection/element_exists.js +73 -0
- package/dist/tools/browser/inspection/find_by_text.d.ts +14 -0
- package/dist/tools/browser/inspection/find_by_text.js +240 -0
- package/dist/tools/browser/inspection/get_computed_styles.d.ts +13 -0
- package/dist/tools/browser/inspection/get_computed_styles.js +139 -0
- package/dist/tools/browser/inspection/get_test_ids.d.ts +13 -0
- package/dist/tools/browser/inspection/get_test_ids.js +168 -0
- package/dist/tools/browser/inspection/index.d.ts +10 -0
- package/dist/tools/browser/inspection/index.js +10 -0
- package/dist/tools/browser/inspection/inspect_ancestors.d.ts +19 -0
- package/dist/tools/browser/inspection/inspect_ancestors.js +396 -0
- package/dist/tools/browser/inspection/inspect_dom.d.ts +13 -0
- package/dist/tools/browser/inspection/inspect_dom.js +649 -0
- package/dist/tools/browser/inspection/measure_element.d.ts +11 -0
- package/dist/tools/browser/inspection/measure_element.js +154 -0
- package/dist/tools/browser/inspection/query_selector.d.ts +13 -0
- package/dist/tools/browser/inspection/query_selector.js +229 -0
- package/dist/tools/browser/interaction/__tests__/advancedInteraction.test.d.ts +1 -0
- package/dist/tools/browser/interaction/__tests__/advancedInteraction.test.js +204 -0
- package/dist/tools/browser/interaction/__tests__/interaction.test.d.ts +1 -0
- package/dist/tools/browser/interaction/__tests__/interaction.test.js +396 -0
- package/dist/tools/browser/interaction/click.d.ts +9 -0
- package/dist/tools/browser/interaction/click.js +34 -0
- package/dist/tools/browser/interaction/drag.d.ts +9 -0
- package/dist/tools/browser/interaction/drag.js +49 -0
- package/dist/tools/browser/interaction/fill.d.ts +9 -0
- package/dist/tools/browser/interaction/fill.js +35 -0
- package/dist/tools/browser/interaction/hover.d.ts +9 -0
- package/dist/tools/browser/interaction/hover.js +34 -0
- package/dist/tools/browser/interaction/index.d.ts +7 -0
- package/dist/tools/browser/interaction/index.js +7 -0
- package/dist/tools/browser/interaction/press_key.d.ts +9 -0
- package/dist/tools/browser/interaction/press_key.js +38 -0
- package/dist/tools/browser/interaction/select.d.ts +9 -0
- package/dist/tools/browser/interaction/select.js +35 -0
- package/dist/tools/browser/interaction/upload_file.d.ts +9 -0
- package/dist/tools/browser/interaction/upload_file.js +35 -0
- package/dist/tools/browser/interaction.js +63 -26
- package/dist/tools/browser/lifecycle/close.d.ts +9 -0
- package/dist/tools/browser/lifecycle/close.js +47 -0
- package/dist/tools/browser/lifecycle/index.d.ts +1 -0
- package/dist/tools/browser/lifecycle/index.js +1 -0
- package/dist/tools/browser/measureElement.d.ts +1 -0
- package/dist/tools/browser/measureElement.js +8 -21
- package/dist/tools/browser/navigation/__tests__/goNavigation.test.d.ts +1 -0
- package/dist/tools/browser/navigation/__tests__/goNavigation.test.js +90 -0
- package/dist/tools/browser/navigation/__tests__/navigation.test.d.ts +1 -0
- package/dist/tools/browser/navigation/__tests__/navigation.test.js +113 -0
- package/dist/tools/browser/navigation/go_back.d.ts +9 -0
- package/dist/tools/browser/navigation/go_back.js +25 -0
- package/dist/tools/browser/navigation/go_forward.d.ts +9 -0
- package/dist/tools/browser/navigation/go_forward.js +25 -0
- package/dist/tools/browser/navigation/index.d.ts +3 -0
- package/dist/tools/browser/navigation/index.js +3 -0
- package/dist/tools/browser/navigation/navigate.d.ts +9 -0
- package/dist/tools/browser/navigation/navigate.js +80 -0
- package/dist/tools/browser/network/__tests__/networkMonitoring.test.d.ts +1 -0
- package/dist/tools/browser/network/__tests__/networkMonitoring.test.js +127 -0
- package/dist/tools/browser/network/get_request_details.d.ts +10 -0
- package/dist/tools/browser/network/get_request_details.js +153 -0
- package/dist/tools/browser/network/index.d.ts +2 -0
- package/dist/tools/browser/network/index.js +2 -0
- package/dist/tools/browser/network/list_network_requests.d.ts +11 -0
- package/dist/tools/browser/network/list_network_requests.js +94 -0
- package/dist/tools/browser/register.d.ts +2 -0
- package/dist/tools/browser/register.js +79 -0
- package/dist/tools/browser/visiblePage.js +120 -85
- package/dist/tools/browser/waiting/__tests__/waitForElement.test.d.ts +1 -0
- package/dist/tools/browser/waiting/__tests__/waitForElement.test.js +139 -0
- package/dist/tools/browser/waiting/index.d.ts +2 -0
- package/dist/tools/browser/waiting/index.js +2 -0
- package/dist/tools/browser/waiting/wait_for_element.d.ts +11 -0
- package/dist/tools/browser/waiting/wait_for_element.js +63 -0
- package/dist/tools/browser/waiting/wait_for_network_idle.d.ts +9 -0
- package/dist/tools/browser/waiting/wait_for_network_idle.js +48 -0
- package/dist/tools/common/registry.d.ts +8 -0
- package/dist/tools/common/registry.js +48 -0
- package/dist/tools/common/types.d.ts +12 -1
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.js +0 -1
- package/dist/tools.d.ts +9 -551
- package/dist/tools.js +11 -575
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -39,6 +39,33 @@ npm install -g mcp-web-inspector
|
|
|
39
39
|
|
|
40
40
|
All configurations below use `npx` which automatically downloads and runs the latest version. Click to expand installation instructions for your AI tool:
|
|
41
41
|
|
|
42
|
+
<details>
|
|
43
|
+
<summary><b>🚀 Codex CLI</b></summary>
|
|
44
|
+
|
|
45
|
+
### Installation via CLI
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Add the server globally
|
|
49
|
+
codex mcp add web-inspector -- npx -y mcp-web-inspector
|
|
50
|
+
|
|
51
|
+
# Verify it was registered
|
|
52
|
+
codex mcp list
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Manual Configuration
|
|
56
|
+
|
|
57
|
+
Codex stores MCP server definitions in `~/.codex/config.toml`. Add (or create) an entry under the `[mcp.servers]` table:
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
[mcp.servers.web-inspector]
|
|
61
|
+
command = "npx"
|
|
62
|
+
args = ["-y", "mcp-web-inspector"]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Restart Codex CLI to make sure the new server is available in future sessions.
|
|
66
|
+
|
|
67
|
+
</details>
|
|
68
|
+
|
|
42
69
|
<details>
|
|
43
70
|
<summary><b>🤖 Claude Code (CLI)</b></summary>
|
|
44
71
|
|
|
@@ -109,10 +136,10 @@ Restart Claude Desktop after saving the configuration.
|
|
|
109
136
|
|
|
110
137
|
```bash
|
|
111
138
|
# VS Code Stable
|
|
112
|
-
code --add-mcp '{"name":"web-inspector","command":"npx","args":["mcp-web-inspector"]}'
|
|
139
|
+
code --add-mcp '{"name":"web-inspector","command":"npx","args":["-y","mcp-web-inspector"]}'
|
|
113
140
|
|
|
114
141
|
# VS Code Insiders
|
|
115
|
-
code-insiders --add-mcp '{"name":"web-inspector","command":"npx","args":["mcp-web-inspector"]}'
|
|
142
|
+
code-insiders --add-mcp '{"name":"web-inspector","command":"npx","args":["-y","mcp-web-inspector"]}'
|
|
116
143
|
```
|
|
117
144
|
|
|
118
145
|
### Manual Configuration
|
|
@@ -277,6 +304,8 @@ Most MCP-compatible tools use a similar configuration format. Look for:
|
|
|
277
304
|
}
|
|
278
305
|
```
|
|
279
306
|
|
|
307
|
+
CLI-first assistants such as GitHub Copilot CLI, Copylot CLI, Continue CLI, and other emerging AI coders follow the same pattern—either run their `mcp add` command with `npx -y mcp-web-inspector` or drop the snippet above into their MCP config file.
|
|
308
|
+
|
|
280
309
|
If your tool supports MCP but isn't listed here, consult its documentation for the exact configuration file location.
|
|
281
310
|
|
|
282
311
|
</details>
|
|
@@ -289,6 +318,7 @@ Customize server behavior with command line flags:
|
|
|
289
318
|
|
|
290
319
|
- **`--no-save-session`** - Disable automatic session persistence (start with fresh browser state each time)
|
|
291
320
|
- **`--user-data-dir <path>`** - Custom directory for session data (default: `./.mcp-web-inspector`)
|
|
321
|
+
- **`--headless`** - Run browser in headless mode by default (no visible window)
|
|
292
322
|
|
|
293
323
|
**Example usage:**
|
|
294
324
|
```json
|
|
@@ -302,6 +332,30 @@ Customize server behavior with command line flags:
|
|
|
302
332
|
}
|
|
303
333
|
```
|
|
304
334
|
|
|
335
|
+
**Run in headless mode for automation/CI:**
|
|
336
|
+
```json
|
|
337
|
+
{
|
|
338
|
+
"mcpServers": {
|
|
339
|
+
"web-inspector": {
|
|
340
|
+
"command": "npx",
|
|
341
|
+
"args": ["-y", "mcp-web-inspector", "--headless"]
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Combine multiple flags:**
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"mcpServers": {
|
|
351
|
+
"web-inspector": {
|
|
352
|
+
"command": "npx",
|
|
353
|
+
"args": ["-y", "mcp-web-inspector", "--headless", "--no-save-session"]
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
305
359
|
---
|
|
306
360
|
|
|
307
361
|
## Session Persistence & Data Storage
|
|
@@ -395,8 +449,8 @@ rm -rf ./.mcp-web-inspector/screenshots # Clear screenshots only
|
|
|
395
449
|
- Session files can be large and bloat your git history
|
|
396
450
|
|
|
397
451
|
**Best practices:**
|
|
398
|
-
-
|
|
399
|
-
- Use `headless:
|
|
452
|
+
- **Default is visible browser** (`headless: false`) for interactive debugging
|
|
453
|
+
- Use `headless: true` explicitly for automation and CI/CD environments
|
|
400
454
|
- Clear session data after testing sensitive applications
|
|
401
455
|
- Use `--no-save-session` flag when testing on shared/public sites
|
|
402
456
|
|
|
@@ -570,11 +624,16 @@ Ultra-lightweight existence check. Returns simple ✓ exists or ✗ not found st
|
|
|
570
624
|
Navigate to a URL with full browser configuration options.
|
|
571
625
|
|
|
572
626
|
**Parameters:**
|
|
573
|
-
- `browserType` - chromium, firefox, or webkit
|
|
574
|
-
- `width`, `height` - Viewport dimensions
|
|
575
|
-
- `headless` - Run in headless mode
|
|
576
|
-
- `timeout` - Navigation timeout
|
|
577
|
-
- `waitUntil` - Navigation wait condition
|
|
627
|
+
- `browserType` - chromium, firefox, or webkit (default: chromium)
|
|
628
|
+
- `width`, `height` - Viewport dimensions (default: auto-detected screen size)
|
|
629
|
+
- `headless` - Run in headless mode (default: **false** - browser window visible)
|
|
630
|
+
- `timeout` - Navigation timeout in ms (default: 30000)
|
|
631
|
+
- `waitUntil` - Navigation wait condition (default: "load")
|
|
632
|
+
|
|
633
|
+
**Default Behavior:**
|
|
634
|
+
- Browser window is **visible by default** for interactive debugging
|
|
635
|
+
- Use `headless: true` for automation, CI/CD, or when you don't need visual feedback
|
|
636
|
+
- Use `headless: false` (or omit) when debugging interactively
|
|
578
637
|
|
|
579
638
|
#### `go_back`
|
|
580
639
|
Navigate back in browser history. Essential for testing navigation flows and multi-step forms.
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { createToolDefinitions } from "./tools.js";
|
|
4
|
+
import { createToolDefinitions } from "./tools/common/registry.js";
|
|
5
5
|
import { setupRequestHandlers } from "./requestHandler.js";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
7
|
import { setSessionConfig } from "./toolHandler.js";
|
|
@@ -16,6 +16,10 @@ const { values } = parseArgs({
|
|
|
16
16
|
type: 'string',
|
|
17
17
|
default: './.mcp-web-inspector',
|
|
18
18
|
},
|
|
19
|
+
'headless': {
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
default: false,
|
|
22
|
+
},
|
|
19
23
|
},
|
|
20
24
|
strict: false,
|
|
21
25
|
});
|
|
@@ -25,6 +29,7 @@ const sessionConfig = {
|
|
|
25
29
|
saveSession: !Boolean(values['no-save-session']),
|
|
26
30
|
userDataDir: `${baseDir}/user-data`,
|
|
27
31
|
screenshotsDir: `${baseDir}/screenshots`,
|
|
32
|
+
headlessDefault: Boolean(values['headless']),
|
|
28
33
|
};
|
|
29
34
|
setSessionConfig(sessionConfig);
|
|
30
35
|
async function runServer() {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool constants - separate file to avoid circular dependencies
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Get list of all browser tool names
|
|
6
|
+
*/
|
|
7
|
+
export const BROWSER_TOOLS = [
|
|
8
|
+
// Navigation & Control
|
|
9
|
+
"navigate",
|
|
10
|
+
"go_back",
|
|
11
|
+
"go_forward",
|
|
12
|
+
"screenshot",
|
|
13
|
+
// DOM Inspection (PRIMARY)
|
|
14
|
+
"inspect_dom",
|
|
15
|
+
"get_test_ids",
|
|
16
|
+
"query_selector",
|
|
17
|
+
"find_by_text",
|
|
18
|
+
// Visibility & Position
|
|
19
|
+
"check_visibility",
|
|
20
|
+
"compare_element_alignment",
|
|
21
|
+
"inspect_ancestors",
|
|
22
|
+
"element_exists",
|
|
23
|
+
"wait_for_element",
|
|
24
|
+
"wait_for_network_idle",
|
|
25
|
+
// Style & Content
|
|
26
|
+
"get_computed_styles",
|
|
27
|
+
"measure_element",
|
|
28
|
+
"get_text",
|
|
29
|
+
"get_html",
|
|
30
|
+
"get_console_logs",
|
|
31
|
+
// Network Monitoring
|
|
32
|
+
"list_network_requests",
|
|
33
|
+
"get_request_details",
|
|
34
|
+
// Interactions (for debugging/testing workflows)
|
|
35
|
+
"click",
|
|
36
|
+
"fill",
|
|
37
|
+
"hover",
|
|
38
|
+
"select",
|
|
39
|
+
"upload_file",
|
|
40
|
+
"drag",
|
|
41
|
+
"press_key",
|
|
42
|
+
// JavaScript Execution
|
|
43
|
+
"evaluate",
|
|
44
|
+
// Cleanup
|
|
45
|
+
"close"
|
|
46
|
+
];
|
package/dist/toolHandler.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Page } from 'playwright';
|
|
2
2
|
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import type { SessionConfig } from './tools/common/types.js';
|
|
3
4
|
export interface NetworkRequest {
|
|
4
5
|
index: number;
|
|
5
6
|
method: string;
|
|
@@ -18,11 +19,6 @@ export interface NetworkRequest {
|
|
|
18
19
|
body: string | null;
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
|
-
interface SessionConfig {
|
|
22
|
-
saveSession: boolean;
|
|
23
|
-
userDataDir: string;
|
|
24
|
-
screenshotsDir: string;
|
|
25
|
-
}
|
|
26
22
|
/**
|
|
27
23
|
* Sets the session configuration
|
|
28
24
|
*/
|
|
@@ -31,6 +27,10 @@ export declare function setSessionConfig(config: Partial<SessionConfig>): void;
|
|
|
31
27
|
* Gets the screenshots directory
|
|
32
28
|
*/
|
|
33
29
|
export declare function getScreenshotsDir(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Gets the default headless setting
|
|
32
|
+
*/
|
|
33
|
+
export declare function getHeadlessDefault(): boolean;
|
|
34
34
|
/**
|
|
35
35
|
* Resets browser and page variables
|
|
36
36
|
* Used when browser is closed
|
|
@@ -48,7 +48,7 @@ export declare function clearNetworkLog(): void;
|
|
|
48
48
|
* Sets the provided page to the global page variable
|
|
49
49
|
* @param newPage The Page object to set as the global page
|
|
50
50
|
*/
|
|
51
|
-
export declare function setGlobalPage(newPage: Page): void
|
|
51
|
+
export declare function setGlobalPage(newPage: Page): Promise<void>;
|
|
52
52
|
interface BrowserSettings {
|
|
53
53
|
viewport?: {
|
|
54
54
|
width?: number;
|
package/dist/toolHandler.js
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
1
|
import { chromium, firefox, webkit, devices } from 'playwright';
|
|
2
|
-
import { BROWSER_TOOLS } from './tools.js';
|
|
3
2
|
import { checkBrowsersInstalled, getInstallationInstructions } from './utils/browserCheck.js';
|
|
4
|
-
import {
|
|
5
|
-
import { ClickTool, FillTool, SelectTool, HoverTool, EvaluateTool, UploadFileTool } from './tools/browser/interaction.js';
|
|
6
|
-
import { VisibleTextTool, VisibleHtmlTool } from './tools/browser/visiblePage.js';
|
|
7
|
-
import { ElementVisibilityTool } from './tools/browser/elementVisibility.js';
|
|
8
|
-
import { InspectDomTool } from './tools/browser/inspectDom.js';
|
|
9
|
-
import { GetTestIdsTool } from './tools/browser/getTestIds.js';
|
|
10
|
-
import { QuerySelectorAllTool } from './tools/browser/querySelectorAll.js';
|
|
11
|
-
import { FindByTextTool } from './tools/browser/findByText.js';
|
|
12
|
-
import { GetComputedStylesTool } from './tools/browser/computedStyles.js';
|
|
13
|
-
import { MeasureElementTool } from './tools/browser/measureElement.js';
|
|
14
|
-
import { ElementExistsTool } from './tools/browser/elementExists.js';
|
|
15
|
-
import { CompareElementAlignmentTool } from './tools/browser/compareElementAlignment.js';
|
|
16
|
-
import { InspectAncestorsTool } from './tools/browser/ancestorInspection.js';
|
|
17
|
-
import { GoBackTool, GoForwardTool } from './tools/browser/navigation.js';
|
|
18
|
-
import { DragTool, PressKeyTool } from './tools/browser/interaction.js';
|
|
19
|
-
import { WaitForElementTool } from './tools/browser/waitForElement.js';
|
|
20
|
-
import { WaitForNetworkIdleTool } from './tools/browser/waitForNetworkIdle.js';
|
|
21
|
-
import { ListNetworkRequestsTool } from './tools/browser/listNetworkRequests.js';
|
|
22
|
-
import { GetRequestDetailsTool } from './tools/browser/getRequestDetails.js';
|
|
3
|
+
import { getToolInstance, isBrowserTool, executeTool } from './tools/common/registry.js';
|
|
23
4
|
// Global state
|
|
24
5
|
let browser;
|
|
25
6
|
let page;
|
|
@@ -29,6 +10,7 @@ let sessionConfig = {
|
|
|
29
10
|
saveSession: false,
|
|
30
11
|
userDataDir: './.mcp-web-inspector/user-data',
|
|
31
12
|
screenshotsDir: './.mcp-web-inspector/screenshots',
|
|
13
|
+
headlessDefault: false,
|
|
32
14
|
};
|
|
33
15
|
/**
|
|
34
16
|
* Sets the session configuration
|
|
@@ -42,6 +24,12 @@ export function setSessionConfig(config) {
|
|
|
42
24
|
export function getScreenshotsDir() {
|
|
43
25
|
return sessionConfig.screenshotsDir;
|
|
44
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Gets the default headless setting
|
|
29
|
+
*/
|
|
30
|
+
export function getHeadlessDefault() {
|
|
31
|
+
return sessionConfig.headlessDefault;
|
|
32
|
+
}
|
|
45
33
|
/**
|
|
46
34
|
* Resets browser and page variables
|
|
47
35
|
* Used when browser is closed
|
|
@@ -68,52 +56,61 @@ export function clearNetworkLog() {
|
|
|
68
56
|
* Sets the provided page to the global page variable
|
|
69
57
|
* @param newPage The Page object to set as the global page
|
|
70
58
|
*/
|
|
71
|
-
export function setGlobalPage(newPage) {
|
|
59
|
+
export async function setGlobalPage(newPage) {
|
|
72
60
|
page = newPage;
|
|
61
|
+
// Register console message handlers and network listeners for the new page
|
|
62
|
+
await registerConsoleMessage(page);
|
|
63
|
+
await registerNetworkListeners(page);
|
|
73
64
|
page.bringToFront(); // Bring the new tab to the front
|
|
74
|
-
console.log("Global page has been updated.");
|
|
65
|
+
console.log("Global page has been updated with listeners registered.");
|
|
75
66
|
}
|
|
76
|
-
// Tool instances
|
|
77
|
-
let screenshotTool;
|
|
78
|
-
let navigationTool;
|
|
79
|
-
let closeBrowserTool;
|
|
80
|
-
let consoleLogsTool;
|
|
81
|
-
let clickTool;
|
|
82
|
-
let fillTool;
|
|
83
|
-
let selectTool;
|
|
84
|
-
let hoverTool;
|
|
85
|
-
let uploadFileTool;
|
|
86
|
-
let evaluateTool;
|
|
87
|
-
let visibleTextTool;
|
|
88
|
-
let visibleHtmlTool;
|
|
89
|
-
let goBackTool;
|
|
90
|
-
let goForwardTool;
|
|
91
|
-
let dragTool;
|
|
92
|
-
let pressKeyTool;
|
|
93
|
-
let elementVisibilityTool;
|
|
94
|
-
let inspectDomTool;
|
|
95
|
-
let getTestIdsTool;
|
|
96
|
-
let querySelectorAllTool;
|
|
97
|
-
let findByTextTool;
|
|
98
|
-
let getComputedStylesTool;
|
|
99
|
-
let measureElementTool;
|
|
100
|
-
let elementExistsTool;
|
|
101
|
-
let compareElementAlignmentTool;
|
|
102
|
-
let inspectAncestorsTool;
|
|
103
|
-
let waitForElementTool;
|
|
104
|
-
let waitForNetworkIdleTool;
|
|
105
|
-
let listNetworkRequestsTool;
|
|
106
|
-
let getRequestDetailsTool;
|
|
107
67
|
/**
|
|
108
68
|
* Device preset mapping to Playwright device descriptors
|
|
109
69
|
*/
|
|
110
70
|
const DEVICE_PRESETS = {
|
|
71
|
+
// Mobile devices
|
|
111
72
|
'iphone-se': 'iPhone SE',
|
|
112
73
|
'iphone-14': 'iPhone 14',
|
|
113
74
|
'iphone-14-pro': 'iPhone 14 Pro',
|
|
114
75
|
'pixel-5': 'Pixel 5',
|
|
115
76
|
'ipad': 'iPad (gen 7)',
|
|
116
|
-
'samsung-s21': 'Galaxy S21'
|
|
77
|
+
'samsung-s21': 'Galaxy S21',
|
|
78
|
+
// Desktop devices (custom configs)
|
|
79
|
+
'desktop-1080p': 'Desktop 1080p',
|
|
80
|
+
'desktop-2k': 'Desktop 2K',
|
|
81
|
+
'laptop-hd': 'Laptop HD'
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Custom device configurations for presets not in Playwright's built-in devices
|
|
85
|
+
*/
|
|
86
|
+
const CUSTOM_DEVICE_CONFIGS = {
|
|
87
|
+
'Desktop 1080p': {
|
|
88
|
+
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.7204.23 Safari/537.36',
|
|
89
|
+
viewport: { width: 1920, height: 1080 },
|
|
90
|
+
screen: { width: 1920, height: 1080 },
|
|
91
|
+
deviceScaleFactor: 1,
|
|
92
|
+
isMobile: false,
|
|
93
|
+
hasTouch: false,
|
|
94
|
+
defaultBrowserType: 'chromium'
|
|
95
|
+
},
|
|
96
|
+
'Desktop 2K': {
|
|
97
|
+
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.7204.23 Safari/537.36',
|
|
98
|
+
viewport: { width: 2560, height: 1440 },
|
|
99
|
+
screen: { width: 2560, height: 1440 },
|
|
100
|
+
deviceScaleFactor: 1,
|
|
101
|
+
isMobile: false,
|
|
102
|
+
hasTouch: false,
|
|
103
|
+
defaultBrowserType: 'chromium'
|
|
104
|
+
},
|
|
105
|
+
'Laptop HD': {
|
|
106
|
+
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.7204.23 Safari/537.36',
|
|
107
|
+
viewport: { width: 1366, height: 768 },
|
|
108
|
+
screen: { width: 1366, height: 768 },
|
|
109
|
+
deviceScaleFactor: 1,
|
|
110
|
+
isMobile: false,
|
|
111
|
+
hasTouch: false,
|
|
112
|
+
defaultBrowserType: 'chromium'
|
|
113
|
+
}
|
|
117
114
|
};
|
|
118
115
|
/**
|
|
119
116
|
* Register network event listeners
|
|
@@ -163,6 +160,7 @@ async function registerNetworkListeners(page) {
|
|
|
163
160
|
}
|
|
164
161
|
async function registerConsoleMessage(page) {
|
|
165
162
|
page.on("console", (msg) => {
|
|
163
|
+
const consoleLogsTool = getToolInstance("get_console_logs", null);
|
|
166
164
|
if (consoleLogsTool) {
|
|
167
165
|
const type = msg.type();
|
|
168
166
|
let text = msg.text();
|
|
@@ -186,6 +184,7 @@ async function registerConsoleMessage(page) {
|
|
|
186
184
|
});
|
|
187
185
|
// Uncaught exception
|
|
188
186
|
page.on("pageerror", (error) => {
|
|
187
|
+
const consoleLogsTool = getToolInstance("get_console_logs", null);
|
|
189
188
|
if (consoleLogsTool) {
|
|
190
189
|
const message = error.message;
|
|
191
190
|
const stack = error.stack || "";
|
|
@@ -300,7 +299,7 @@ export async function ensureBrowser(browserSettings) {
|
|
|
300
299
|
}
|
|
301
300
|
// Launch new browser if needed
|
|
302
301
|
if (!browser) {
|
|
303
|
-
const { viewport, userAgent, headless =
|
|
302
|
+
const { viewport, userAgent, headless = sessionConfig.headlessDefault, browserType = 'chromium', device } = browserSettings ?? {};
|
|
304
303
|
// If browser type is changing, force a new browser instance
|
|
305
304
|
if (browser && currentBrowserType !== browserType) {
|
|
306
305
|
try {
|
|
@@ -315,12 +314,13 @@ export async function ensureBrowser(browserSettings) {
|
|
|
315
314
|
let deviceConfig = null;
|
|
316
315
|
if (device && DEVICE_PRESETS[device]) {
|
|
317
316
|
const playwrightDeviceName = DEVICE_PRESETS[device];
|
|
318
|
-
|
|
317
|
+
// Check custom configs first, then Playwright's built-in devices
|
|
318
|
+
deviceConfig = CUSTOM_DEVICE_CONFIGS[playwrightDeviceName] || devices[playwrightDeviceName];
|
|
319
319
|
if (deviceConfig) {
|
|
320
320
|
console.error(`Using device preset: ${device} (${playwrightDeviceName})`);
|
|
321
321
|
}
|
|
322
322
|
else {
|
|
323
|
-
console.error(`Warning: Device preset ${playwrightDeviceName} not found
|
|
323
|
+
console.error(`Warning: Device preset ${playwrightDeviceName} not found`);
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
console.error(`Launching new ${browserType} browser instance...`);
|
|
@@ -451,12 +451,13 @@ export async function ensureBrowser(browserSettings) {
|
|
|
451
451
|
}
|
|
452
452
|
resetBrowserState();
|
|
453
453
|
// Try one more time from scratch
|
|
454
|
-
const { viewport, userAgent, headless =
|
|
454
|
+
const { viewport, userAgent, headless = sessionConfig.headlessDefault, browserType = 'chromium', device } = browserSettings ?? {};
|
|
455
455
|
// Get device configuration if device preset is specified
|
|
456
456
|
let deviceConfig = null;
|
|
457
457
|
if (device && DEVICE_PRESETS[device]) {
|
|
458
458
|
const playwrightDeviceName = DEVICE_PRESETS[device];
|
|
459
|
-
|
|
459
|
+
// Check custom configs first, then Playwright's built-in devices
|
|
460
|
+
deviceConfig = CUSTOM_DEVICE_CONFIGS[playwrightDeviceName] || devices[playwrightDeviceName];
|
|
460
461
|
}
|
|
461
462
|
// Use the appropriate browser engine
|
|
462
463
|
let browserInstance;
|
|
@@ -554,78 +555,10 @@ export async function ensureBrowser(browserSettings) {
|
|
|
554
555
|
return page;
|
|
555
556
|
}
|
|
556
557
|
}
|
|
557
|
-
/**
|
|
558
|
-
* Initialize all tool instances
|
|
559
|
-
*/
|
|
560
|
-
function initializeTools(server) {
|
|
561
|
-
// Browser tools
|
|
562
|
-
if (!screenshotTool)
|
|
563
|
-
screenshotTool = new ScreenshotTool(server);
|
|
564
|
-
if (!navigationTool)
|
|
565
|
-
navigationTool = new NavigationTool(server);
|
|
566
|
-
if (!closeBrowserTool)
|
|
567
|
-
closeBrowserTool = new CloseBrowserTool(server);
|
|
568
|
-
if (!consoleLogsTool)
|
|
569
|
-
consoleLogsTool = new ConsoleLogsTool(server);
|
|
570
|
-
if (!clickTool)
|
|
571
|
-
clickTool = new ClickTool(server);
|
|
572
|
-
if (!fillTool)
|
|
573
|
-
fillTool = new FillTool(server);
|
|
574
|
-
if (!selectTool)
|
|
575
|
-
selectTool = new SelectTool(server);
|
|
576
|
-
if (!hoverTool)
|
|
577
|
-
hoverTool = new HoverTool(server);
|
|
578
|
-
if (!uploadFileTool)
|
|
579
|
-
uploadFileTool = new UploadFileTool(server);
|
|
580
|
-
if (!evaluateTool)
|
|
581
|
-
evaluateTool = new EvaluateTool(server);
|
|
582
|
-
if (!visibleTextTool)
|
|
583
|
-
visibleTextTool = new VisibleTextTool(server);
|
|
584
|
-
if (!visibleHtmlTool)
|
|
585
|
-
visibleHtmlTool = new VisibleHtmlTool(server);
|
|
586
|
-
if (!goBackTool)
|
|
587
|
-
goBackTool = new GoBackTool(server);
|
|
588
|
-
if (!goForwardTool)
|
|
589
|
-
goForwardTool = new GoForwardTool(server);
|
|
590
|
-
if (!dragTool)
|
|
591
|
-
dragTool = new DragTool(server);
|
|
592
|
-
if (!pressKeyTool)
|
|
593
|
-
pressKeyTool = new PressKeyTool(server);
|
|
594
|
-
if (!elementVisibilityTool)
|
|
595
|
-
elementVisibilityTool = new ElementVisibilityTool(server);
|
|
596
|
-
if (!inspectDomTool)
|
|
597
|
-
inspectDomTool = new InspectDomTool(server);
|
|
598
|
-
if (!getTestIdsTool)
|
|
599
|
-
getTestIdsTool = new GetTestIdsTool(server);
|
|
600
|
-
if (!querySelectorAllTool)
|
|
601
|
-
querySelectorAllTool = new QuerySelectorAllTool(server);
|
|
602
|
-
if (!findByTextTool)
|
|
603
|
-
findByTextTool = new FindByTextTool(server);
|
|
604
|
-
if (!getComputedStylesTool)
|
|
605
|
-
getComputedStylesTool = new GetComputedStylesTool(server);
|
|
606
|
-
if (!measureElementTool)
|
|
607
|
-
measureElementTool = new MeasureElementTool(server);
|
|
608
|
-
if (!elementExistsTool)
|
|
609
|
-
elementExistsTool = new ElementExistsTool(server);
|
|
610
|
-
if (!compareElementAlignmentTool)
|
|
611
|
-
compareElementAlignmentTool = new CompareElementAlignmentTool(server);
|
|
612
|
-
if (!inspectAncestorsTool)
|
|
613
|
-
inspectAncestorsTool = new InspectAncestorsTool(server);
|
|
614
|
-
if (!waitForElementTool)
|
|
615
|
-
waitForElementTool = new WaitForElementTool(server);
|
|
616
|
-
if (!waitForNetworkIdleTool)
|
|
617
|
-
waitForNetworkIdleTool = new WaitForNetworkIdleTool(server);
|
|
618
|
-
if (!listNetworkRequestsTool)
|
|
619
|
-
listNetworkRequestsTool = new ListNetworkRequestsTool(server);
|
|
620
|
-
if (!getRequestDetailsTool)
|
|
621
|
-
getRequestDetailsTool = new GetRequestDetailsTool(server);
|
|
622
|
-
}
|
|
623
558
|
/**
|
|
624
559
|
* Main handler for tool calls
|
|
625
560
|
*/
|
|
626
561
|
export async function handleToolCall(name, args, server) {
|
|
627
|
-
// Initialize tools
|
|
628
|
-
initializeTools(server);
|
|
629
562
|
try {
|
|
630
563
|
// Special case for browser close to ensure it always works
|
|
631
564
|
if (name === "close") {
|
|
@@ -657,8 +590,9 @@ export async function handleToolCall(name, args, server) {
|
|
|
657
590
|
isError: false,
|
|
658
591
|
};
|
|
659
592
|
}
|
|
593
|
+
const requiresBrowser = isBrowserTool(name);
|
|
660
594
|
// Check if we have a disconnected browser that needs cleanup
|
|
661
|
-
if (browser && !browser.isConnected() &&
|
|
595
|
+
if (browser && !browser.isConnected() && requiresBrowser) {
|
|
662
596
|
console.error("Detected disconnected browser before tool execution, cleaning up...");
|
|
663
597
|
try {
|
|
664
598
|
await browser.close().catch(() => { }); // Ignore errors
|
|
@@ -673,7 +607,7 @@ export async function handleToolCall(name, args, server) {
|
|
|
673
607
|
server
|
|
674
608
|
};
|
|
675
609
|
// Set up browser if needed
|
|
676
|
-
if (
|
|
610
|
+
if (requiresBrowser) {
|
|
677
611
|
const browserSettings = {
|
|
678
612
|
viewport: {
|
|
679
613
|
width: args.width,
|
|
@@ -699,83 +633,13 @@ export async function handleToolCall(name, args, server) {
|
|
|
699
633
|
};
|
|
700
634
|
}
|
|
701
635
|
}
|
|
702
|
-
// Route to appropriate tool
|
|
703
|
-
|
|
704
|
-
// Browser tools
|
|
705
|
-
case "navigate":
|
|
706
|
-
return await navigationTool.execute(args, context);
|
|
707
|
-
case "screenshot":
|
|
708
|
-
return await screenshotTool.execute(args, context);
|
|
709
|
-
case "close":
|
|
710
|
-
return await closeBrowserTool.execute(args, context);
|
|
711
|
-
case "get_console_logs":
|
|
712
|
-
return await consoleLogsTool.execute(args, context);
|
|
713
|
-
case "click":
|
|
714
|
-
return await clickTool.execute(args, context);
|
|
715
|
-
case "fill":
|
|
716
|
-
return await fillTool.execute(args, context);
|
|
717
|
-
case "select":
|
|
718
|
-
return await selectTool.execute(args, context);
|
|
719
|
-
case "hover":
|
|
720
|
-
return await hoverTool.execute(args, context);
|
|
721
|
-
case "upload_file":
|
|
722
|
-
return await uploadFileTool.execute(args, context);
|
|
723
|
-
case "evaluate":
|
|
724
|
-
return await evaluateTool.execute(args, context);
|
|
725
|
-
case "get_text":
|
|
726
|
-
return await visibleTextTool.execute(args, context);
|
|
727
|
-
case "get_html":
|
|
728
|
-
return await visibleHtmlTool.execute(args, context);
|
|
729
|
-
case "go_back":
|
|
730
|
-
return await goBackTool.execute(args, context);
|
|
731
|
-
case "go_forward":
|
|
732
|
-
return await goForwardTool.execute(args, context);
|
|
733
|
-
case "drag":
|
|
734
|
-
return await dragTool.execute(args, context);
|
|
735
|
-
case "press_key":
|
|
736
|
-
return await pressKeyTool.execute(args, context);
|
|
737
|
-
case "check_visibility":
|
|
738
|
-
return await elementVisibilityTool.execute(args, context);
|
|
739
|
-
case "inspect_dom":
|
|
740
|
-
return await inspectDomTool.execute(args, context);
|
|
741
|
-
case "get_test_ids":
|
|
742
|
-
return await getTestIdsTool.execute(args, context);
|
|
743
|
-
case "query_selector":
|
|
744
|
-
return await querySelectorAllTool.execute(args, context);
|
|
745
|
-
case "find_by_text":
|
|
746
|
-
return await findByTextTool.execute(args, context);
|
|
747
|
-
case "get_computed_styles":
|
|
748
|
-
return await getComputedStylesTool.execute(args, context);
|
|
749
|
-
case "measure_element":
|
|
750
|
-
return await measureElementTool.execute(args, context);
|
|
751
|
-
case "element_exists":
|
|
752
|
-
return await elementExistsTool.execute(args, context);
|
|
753
|
-
case "compare_element_alignment":
|
|
754
|
-
return await compareElementAlignmentTool.execute(args, context);
|
|
755
|
-
case "inspect_ancestors":
|
|
756
|
-
return await inspectAncestorsTool.execute(args, context);
|
|
757
|
-
case "wait_for_element":
|
|
758
|
-
return await waitForElementTool.execute(args, context);
|
|
759
|
-
case "wait_for_network_idle":
|
|
760
|
-
return await waitForNetworkIdleTool.execute(args, context);
|
|
761
|
-
case "list_network_requests":
|
|
762
|
-
return await listNetworkRequestsTool.execute(args, context);
|
|
763
|
-
case "get_request_details":
|
|
764
|
-
return await getRequestDetailsTool.execute(args, context);
|
|
765
|
-
default:
|
|
766
|
-
return {
|
|
767
|
-
content: [{
|
|
768
|
-
type: "text",
|
|
769
|
-
text: `Unknown tool: ${name}`,
|
|
770
|
-
}],
|
|
771
|
-
isError: true,
|
|
772
|
-
};
|
|
773
|
-
}
|
|
636
|
+
// Route to appropriate tool using registry
|
|
637
|
+
return await executeTool(name, args, context, server);
|
|
774
638
|
}
|
|
775
639
|
catch (error) {
|
|
776
640
|
console.error(`Error handling tool ${name}:`, error);
|
|
777
641
|
// Handle browser-specific errors at the top level
|
|
778
|
-
if (
|
|
642
|
+
if (isBrowserTool(name)) {
|
|
779
643
|
const errorMessage = error.message;
|
|
780
644
|
if (errorMessage.includes("Target page, context or browser has been closed") ||
|
|
781
645
|
errorMessage.includes("Browser has been disconnected") ||
|
|
@@ -806,30 +670,35 @@ export async function handleToolCall(name, args, server) {
|
|
|
806
670
|
* Get console logs
|
|
807
671
|
*/
|
|
808
672
|
export function getConsoleLogs() {
|
|
673
|
+
const consoleLogsTool = getToolInstance("get_console_logs", null);
|
|
809
674
|
return consoleLogsTool?.getConsoleLogs() ?? [];
|
|
810
675
|
}
|
|
811
676
|
/**
|
|
812
677
|
* Get screenshots
|
|
813
678
|
*/
|
|
814
679
|
export function getScreenshots() {
|
|
680
|
+
const screenshotTool = getToolInstance("screenshot", null);
|
|
815
681
|
return screenshotTool?.getScreenshots() ?? new Map();
|
|
816
682
|
}
|
|
817
683
|
/**
|
|
818
684
|
* Update last interaction timestamp
|
|
819
685
|
*/
|
|
820
686
|
export function updateLastInteractionTimestamp() {
|
|
687
|
+
const consoleLogsTool = getToolInstance("get_console_logs", null);
|
|
821
688
|
consoleLogsTool?.updateLastInteractionTimestamp();
|
|
822
689
|
}
|
|
823
690
|
/**
|
|
824
691
|
* Update last navigation timestamp
|
|
825
692
|
*/
|
|
826
693
|
export function updateLastNavigationTimestamp() {
|
|
694
|
+
const consoleLogsTool = getToolInstance("get_console_logs", null);
|
|
827
695
|
consoleLogsTool?.updateLastNavigationTimestamp();
|
|
828
696
|
}
|
|
829
697
|
/**
|
|
830
698
|
* Clear console logs
|
|
831
699
|
*/
|
|
832
700
|
export function clearConsoleLogs() {
|
|
701
|
+
const consoleLogsTool = getToolInstance("get_console_logs", null);
|
|
833
702
|
consoleLogsTool?.clearConsoleLogs();
|
|
834
703
|
}
|
|
835
704
|
export { registerConsoleMessage };
|