@ebowwa/mcp-browser 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/README.md +147 -0
- package/dist/client.d.ts +104 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +275 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +634 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# @ebowwa/mcp-browser
|
|
2
|
+
|
|
3
|
+
MCP server for browser automation via [dev-browser](https://github.com/sawyerhood/dev-browser).
|
|
4
|
+
|
|
5
|
+
**This is an optional extension** - Coder works without it. Install only if you need browser automation.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Optional dependency** - dev-browser is a peer dependency, not required
|
|
10
|
+
- **Graceful degradation** - Coder continues if dev-browser isn't installed
|
|
11
|
+
- **Full Playwright API** - Navigate, click, fill, screenshot, evaluate
|
|
12
|
+
- **AI-friendly snapshots** - `page.snapshotForAI()` for structured page state
|
|
13
|
+
- **Persistent pages** - Browser tabs persist across tool calls
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### 1. Install dev-browser (required for browser automation)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g dev-browser
|
|
21
|
+
dev-browser install # Installs Playwright + Chromium
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Add to Coder's MCP config
|
|
25
|
+
|
|
26
|
+
Add to `~/.claude.json`:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"browser": {
|
|
32
|
+
"command": "mcp-browser",
|
|
33
|
+
"type": "stdio"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Tools
|
|
40
|
+
|
|
41
|
+
| Tool | Description |
|
|
42
|
+
|------|-------------|
|
|
43
|
+
| `browser_status` | Check if dev-browser is available |
|
|
44
|
+
| `browser_help` | Get dev-browser CLI help |
|
|
45
|
+
| `browser_navigate` | Navigate to URL |
|
|
46
|
+
| `browser_get_url` | Get current URL |
|
|
47
|
+
| `browser_get_title` | Get page title |
|
|
48
|
+
| `browser_list_pages` | List all browser tabs |
|
|
49
|
+
| `browser_close_page` | Close a named page |
|
|
50
|
+
| `browser_click` | Click element by selector |
|
|
51
|
+
| `browser_fill` | Fill form field |
|
|
52
|
+
| `browser_type` | Type text (appends) |
|
|
53
|
+
| `browser_press` | Press keyboard key |
|
|
54
|
+
| `browser_wait_for_selector` | Wait for element |
|
|
55
|
+
| `browser_snapshot` | Get AI-friendly page state |
|
|
56
|
+
| `browser_screenshot` | Take screenshot |
|
|
57
|
+
| `browser_evaluate` | Run JavaScript in page |
|
|
58
|
+
| `browser_execute_script` | Run raw dev-browser script |
|
|
59
|
+
|
|
60
|
+
## Usage Examples
|
|
61
|
+
|
|
62
|
+
### Navigate and interact
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
User: "Go to github.com and search for 'mcp'"
|
|
66
|
+
|
|
67
|
+
→ browser_navigate({ url: "https://github.com" })
|
|
68
|
+
→ browser_fill({ selector: "[name='q']", value: "mcp" })
|
|
69
|
+
→ browser_press({ key: "Enter" })
|
|
70
|
+
→ browser_snapshot({})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Get AI-friendly page state
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
→ browser_snapshot({ pageName: "main", depth: 10 })
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
{
|
|
80
|
+
"full": "# GitHub\n\n## Search Results\n\n- mcp (Model Context Protocol)\n- ...",
|
|
81
|
+
"incremental": "..."
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Take screenshot
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
→ browser_screenshot({ filename: "search-results.png" })
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
{
|
|
92
|
+
"success": true,
|
|
93
|
+
"data": { "path": "~/.dev-browser/tmp/search-results.png" }
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Execute custom script
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
→ browser_execute_script({
|
|
101
|
+
script: `
|
|
102
|
+
const page = await browser.getPage("main");
|
|
103
|
+
await page.goto("https://example.com");
|
|
104
|
+
const links = await page.$$eval('a', els => els.map(e => e.href));
|
|
105
|
+
console.log(JSON.stringify(links));
|
|
106
|
+
`
|
|
107
|
+
})
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## When dev-browser is NOT installed
|
|
111
|
+
|
|
112
|
+
Coder gracefully handles the missing dependency:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
→ browser_navigate({ url: "https://example.com" })
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
{
|
|
119
|
+
"success": false,
|
|
120
|
+
"error": "dev-browser is not installed",
|
|
121
|
+
"hint": "Install with: npm install -g dev-browser && dev-browser install"
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Coder continues to work with all other tools - browser automation is simply unavailable.
|
|
126
|
+
|
|
127
|
+
## Architecture
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Coder
|
|
131
|
+
├── MCP Client
|
|
132
|
+
│ └── connects to → mcp-browser (optional)
|
|
133
|
+
│ └── wraps → dev-browser CLI
|
|
134
|
+
│ └── QuickJS WASM sandbox
|
|
135
|
+
│ └── Playwright API
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Why Optional?
|
|
139
|
+
|
|
140
|
+
- **Not all tasks need browsers** - Most coding tasks are file/code operations
|
|
141
|
+
- **Smaller footprint** - No browser dependencies in core Coder
|
|
142
|
+
- **User choice** - Install only what you need
|
|
143
|
+
- **CI/CD friendly** - Headless environments may not want browser overhead
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dev-browser CLI client wrapper
|
|
3
|
+
*
|
|
4
|
+
* Provides a TypeScript interface to the dev-browser CLI.
|
|
5
|
+
* Falls back gracefully if dev-browser is not installed.
|
|
6
|
+
*/
|
|
7
|
+
export interface BrowserPage {
|
|
8
|
+
id: string;
|
|
9
|
+
url: string;
|
|
10
|
+
title: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface BrowserResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
output?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
data?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface SnapshotResult {
|
|
20
|
+
full: string;
|
|
21
|
+
incremental?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ScreenshotResult {
|
|
24
|
+
path: string;
|
|
25
|
+
base64?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if dev-browser CLI is available
|
|
29
|
+
*/
|
|
30
|
+
export declare function isDevBrowserAvailable(): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Get dev-browser CLI help text (useful for LLM context)
|
|
33
|
+
*/
|
|
34
|
+
export declare function getDevBrowserHelp(): Promise<string>;
|
|
35
|
+
interface CommandOptions {
|
|
36
|
+
timeout?: number;
|
|
37
|
+
headless?: boolean;
|
|
38
|
+
connect?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Execute a dev-browser script
|
|
42
|
+
*/
|
|
43
|
+
export declare function executeScript(script: string, options?: CommandOptions): Promise<BrowserResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Navigate to a URL
|
|
46
|
+
*/
|
|
47
|
+
export declare function navigate(url: string, pageName?: string): Promise<BrowserResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Click an element
|
|
50
|
+
*/
|
|
51
|
+
export declare function click(selector: string, pageName?: string): Promise<BrowserResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Fill a form field
|
|
54
|
+
*/
|
|
55
|
+
export declare function fill(selector: string, value: string, pageName?: string): Promise<BrowserResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Get page snapshot for AI analysis
|
|
58
|
+
*/
|
|
59
|
+
export declare function snapshot(options?: {
|
|
60
|
+
pageName?: string;
|
|
61
|
+
depth?: number;
|
|
62
|
+
track?: string[];
|
|
63
|
+
}): Promise<BrowserResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Take a screenshot
|
|
66
|
+
*/
|
|
67
|
+
export declare function screenshot(filename: string, pageName?: string): Promise<BrowserResult>;
|
|
68
|
+
/**
|
|
69
|
+
* List all browser pages/tabs
|
|
70
|
+
*/
|
|
71
|
+
export declare function listPages(): Promise<BrowserResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Evaluate JavaScript in the page context
|
|
74
|
+
*/
|
|
75
|
+
export declare function evaluate(jsCode: string, pageName?: string): Promise<BrowserResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Wait for a selector to appear
|
|
78
|
+
*/
|
|
79
|
+
export declare function waitForSelector(selector: string, options?: {
|
|
80
|
+
pageName?: string;
|
|
81
|
+
timeout?: number;
|
|
82
|
+
}): Promise<BrowserResult>;
|
|
83
|
+
/**
|
|
84
|
+
* Get page title
|
|
85
|
+
*/
|
|
86
|
+
export declare function getTitle(pageName?: string): Promise<BrowserResult>;
|
|
87
|
+
/**
|
|
88
|
+
* Get current URL
|
|
89
|
+
*/
|
|
90
|
+
export declare function getUrl(pageName?: string): Promise<BrowserResult>;
|
|
91
|
+
/**
|
|
92
|
+
* Close a named page
|
|
93
|
+
*/
|
|
94
|
+
export declare function closePage(pageName: string): Promise<BrowserResult>;
|
|
95
|
+
/**
|
|
96
|
+
* Type text (for inputs that don't respond to fill)
|
|
97
|
+
*/
|
|
98
|
+
export declare function type(selector: string, text: string, pageName?: string): Promise<BrowserResult>;
|
|
99
|
+
/**
|
|
100
|
+
* Press a key
|
|
101
|
+
*/
|
|
102
|
+
export declare function press(key: string, pageName?: string): Promise<BrowserResult>;
|
|
103
|
+
export {};
|
|
104
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dev-browser CLI client wrapper
|
|
3
|
+
*
|
|
4
|
+
* Provides a TypeScript interface to the dev-browser CLI.
|
|
5
|
+
* Falls back gracefully if dev-browser is not installed.
|
|
6
|
+
*/
|
|
7
|
+
import { spawn } from "child_process";
|
|
8
|
+
/**
|
|
9
|
+
* Check if dev-browser CLI is available
|
|
10
|
+
*/
|
|
11
|
+
export async function isDevBrowserAvailable() {
|
|
12
|
+
try {
|
|
13
|
+
const result = await runDevBrowserCommand(["--version"], { timeout: 5000 });
|
|
14
|
+
return result.success;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get dev-browser CLI help text (useful for LLM context)
|
|
22
|
+
*/
|
|
23
|
+
export async function getDevBrowserHelp() {
|
|
24
|
+
const result = await runDevBrowserCommand(["--help"], { timeout: 10000 });
|
|
25
|
+
return result.output || "";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Execute a dev-browser script
|
|
29
|
+
*/
|
|
30
|
+
export async function executeScript(script, options = {}) {
|
|
31
|
+
const args = [];
|
|
32
|
+
if (options.headless !== false) {
|
|
33
|
+
args.push("--headless");
|
|
34
|
+
}
|
|
35
|
+
if (options.connect) {
|
|
36
|
+
args.push("--connect");
|
|
37
|
+
}
|
|
38
|
+
return runDevBrowserCommand(args, {
|
|
39
|
+
...options,
|
|
40
|
+
stdin: script,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Run a raw dev-browser command
|
|
45
|
+
*/
|
|
46
|
+
async function runDevBrowserCommand(args, options = {}) {
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
const proc = spawn("dev-browser", args, {
|
|
49
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
50
|
+
});
|
|
51
|
+
let stdout = "";
|
|
52
|
+
let stderr = "";
|
|
53
|
+
proc.stdout.on("data", (data) => {
|
|
54
|
+
stdout += data.toString();
|
|
55
|
+
});
|
|
56
|
+
proc.stderr.on("data", (data) => {
|
|
57
|
+
stderr += data.toString();
|
|
58
|
+
});
|
|
59
|
+
// Send stdin if provided
|
|
60
|
+
if (options.stdin) {
|
|
61
|
+
proc.stdin.write(options.stdin);
|
|
62
|
+
proc.stdin.end();
|
|
63
|
+
}
|
|
64
|
+
// Timeout handling
|
|
65
|
+
const timeout = options.timeout || 60000;
|
|
66
|
+
const timer = setTimeout(() => {
|
|
67
|
+
proc.kill();
|
|
68
|
+
resolve({
|
|
69
|
+
success: false,
|
|
70
|
+
error: `Command timed out after ${timeout}ms`,
|
|
71
|
+
});
|
|
72
|
+
}, timeout);
|
|
73
|
+
proc.on("close", (code) => {
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
if (code === 0) {
|
|
76
|
+
resolve({
|
|
77
|
+
success: true,
|
|
78
|
+
output: stdout,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
resolve({
|
|
83
|
+
success: false,
|
|
84
|
+
output: stdout,
|
|
85
|
+
error: stderr || `Exit code: ${code}`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
proc.on("error", (err) => {
|
|
90
|
+
clearTimeout(timer);
|
|
91
|
+
resolve({
|
|
92
|
+
success: false,
|
|
93
|
+
error: err.message,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// High-level Browser Operations
|
|
100
|
+
// ============================================================================
|
|
101
|
+
/**
|
|
102
|
+
* Navigate to a URL
|
|
103
|
+
*/
|
|
104
|
+
export async function navigate(url, pageName = "main") {
|
|
105
|
+
const script = `
|
|
106
|
+
const page = await browser.getPage("${pageName}");
|
|
107
|
+
await page.goto("${url}");
|
|
108
|
+
console.log(JSON.stringify({ url: page.url(), title: await page.title() }));
|
|
109
|
+
`;
|
|
110
|
+
return executeScript(script);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Click an element
|
|
114
|
+
*/
|
|
115
|
+
export async function click(selector, pageName = "main") {
|
|
116
|
+
const script = `
|
|
117
|
+
const page = await browser.getPage("${pageName}");
|
|
118
|
+
await page.click("${selector}");
|
|
119
|
+
console.log("Clicked: ${selector}");
|
|
120
|
+
`;
|
|
121
|
+
return executeScript(script);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Fill a form field
|
|
125
|
+
*/
|
|
126
|
+
export async function fill(selector, value, pageName = "main") {
|
|
127
|
+
const script = `
|
|
128
|
+
const page = await browser.getPage("${pageName}");
|
|
129
|
+
await page.fill("${selector}", "${value.replace(/"/g, '\\"')}");
|
|
130
|
+
console.log("Filled: ${selector}");
|
|
131
|
+
`;
|
|
132
|
+
return executeScript(script);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get page snapshot for AI analysis
|
|
136
|
+
*/
|
|
137
|
+
export async function snapshot(options = {}) {
|
|
138
|
+
const pageName = options.pageName || "main";
|
|
139
|
+
const depth = options.depth || 10;
|
|
140
|
+
const track = options.track?.join(",") || "";
|
|
141
|
+
const script = `
|
|
142
|
+
const page = await browser.getPage("${pageName}");
|
|
143
|
+
const result = await page.snapshotForAI({ depth: ${depth}, track: "${track}" });
|
|
144
|
+
console.log(JSON.stringify(result));
|
|
145
|
+
`;
|
|
146
|
+
const result = await executeScript(script);
|
|
147
|
+
if (result.success && result.output) {
|
|
148
|
+
try {
|
|
149
|
+
result.data = JSON.parse(result.output);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Output might not be JSON
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Take a screenshot
|
|
159
|
+
*/
|
|
160
|
+
export async function screenshot(filename, pageName = "main") {
|
|
161
|
+
const script = `
|
|
162
|
+
const page = await browser.getPage("${pageName}");
|
|
163
|
+
const buf = await page.screenshot();
|
|
164
|
+
const path = await saveScreenshot(buf, "${filename}");
|
|
165
|
+
console.log(JSON.stringify({ path }));
|
|
166
|
+
`;
|
|
167
|
+
const result = await executeScript(script);
|
|
168
|
+
if (result.success && result.output) {
|
|
169
|
+
try {
|
|
170
|
+
result.data = JSON.parse(result.output);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// Output might not be JSON
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* List all browser pages/tabs
|
|
180
|
+
*/
|
|
181
|
+
export async function listPages() {
|
|
182
|
+
const script = `
|
|
183
|
+
const tabs = await browser.listPages();
|
|
184
|
+
console.log(JSON.stringify(tabs, null, 2));
|
|
185
|
+
`;
|
|
186
|
+
const result = await executeScript(script);
|
|
187
|
+
if (result.success && result.output) {
|
|
188
|
+
try {
|
|
189
|
+
result.data = JSON.parse(result.output);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Output might not be JSON
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Evaluate JavaScript in the page context
|
|
199
|
+
*/
|
|
200
|
+
export async function evaluate(jsCode, pageName = "main") {
|
|
201
|
+
const script = `
|
|
202
|
+
const page = await browser.getPage("${pageName}");
|
|
203
|
+
const result = await page.evaluate(() => {
|
|
204
|
+
${jsCode}
|
|
205
|
+
});
|
|
206
|
+
console.log(JSON.stringify(result));
|
|
207
|
+
`;
|
|
208
|
+
return executeScript(script);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Wait for a selector to appear
|
|
212
|
+
*/
|
|
213
|
+
export async function waitForSelector(selector, options = {}) {
|
|
214
|
+
const pageName = options.pageName || "main";
|
|
215
|
+
const timeout = options.timeout || 30000;
|
|
216
|
+
const script = `
|
|
217
|
+
const page = await browser.getPage("${pageName}");
|
|
218
|
+
await page.waitForSelector("${selector}", { timeout: ${timeout} });
|
|
219
|
+
console.log("Found: ${selector}");
|
|
220
|
+
`;
|
|
221
|
+
return executeScript(script, { timeout: timeout + 10000 });
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Get page title
|
|
225
|
+
*/
|
|
226
|
+
export async function getTitle(pageName = "main") {
|
|
227
|
+
const script = `
|
|
228
|
+
const page = await browser.getPage("${pageName}");
|
|
229
|
+
console.log(await page.title());
|
|
230
|
+
`;
|
|
231
|
+
return executeScript(script);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get current URL
|
|
235
|
+
*/
|
|
236
|
+
export async function getUrl(pageName = "main") {
|
|
237
|
+
const script = `
|
|
238
|
+
const page = await browser.getPage("${pageName}");
|
|
239
|
+
console.log(page.url());
|
|
240
|
+
`;
|
|
241
|
+
return executeScript(script);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Close a named page
|
|
245
|
+
*/
|
|
246
|
+
export async function closePage(pageName) {
|
|
247
|
+
const script = `
|
|
248
|
+
await browser.closePage("${pageName}");
|
|
249
|
+
console.log("Closed: ${pageName}");
|
|
250
|
+
`;
|
|
251
|
+
return executeScript(script);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Type text (for inputs that don't respond to fill)
|
|
255
|
+
*/
|
|
256
|
+
export async function type(selector, text, pageName = "main") {
|
|
257
|
+
const script = `
|
|
258
|
+
const page = await browser.getPage("${pageName}");
|
|
259
|
+
await page.type("${selector}", "${text.replace(/"/g, '\\"')}");
|
|
260
|
+
console.log("Typed into: ${selector}");
|
|
261
|
+
`;
|
|
262
|
+
return executeScript(script);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Press a key
|
|
266
|
+
*/
|
|
267
|
+
export async function press(key, pageName = "main") {
|
|
268
|
+
const script = `
|
|
269
|
+
const page = await browser.getPage("${pageName}");
|
|
270
|
+
await page.keyboard.press("${key}");
|
|
271
|
+
console.log("Pressed: ${key}");
|
|
272
|
+
`;
|
|
273
|
+
return executeScript(script);
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @ebowwa/mcp-browser
|
|
4
|
+
*
|
|
5
|
+
* MCP server for browser automation via dev-browser.
|
|
6
|
+
* Optional extension - gracefully handles when dev-browser is not installed.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* Add to ~/.claude.json:
|
|
10
|
+
* {
|
|
11
|
+
* "mcpServers": {
|
|
12
|
+
* "browser": {
|
|
13
|
+
* "command": "mcp-browser",
|
|
14
|
+
* "type": "stdio"
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @ebowwa/mcp-browser
|
|
4
|
+
*
|
|
5
|
+
* MCP server for browser automation via dev-browser.
|
|
6
|
+
* Optional extension - gracefully handles when dev-browser is not installed.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* Add to ~/.claude.json:
|
|
10
|
+
* {
|
|
11
|
+
* "mcpServers": {
|
|
12
|
+
* "browser": {
|
|
13
|
+
* "command": "mcp-browser",
|
|
14
|
+
* "type": "stdio"
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
20
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
21
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
22
|
+
import { isDevBrowserAvailable, getDevBrowserHelp, navigate, click, fill, snapshot, screenshot, listPages, evaluate, waitForSelector, getTitle, getUrl, closePage, type, press, executeScript, } from "./client.js";
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Server State
|
|
25
|
+
// ============================================================================
|
|
26
|
+
let browserStatus = {
|
|
27
|
+
available: false,
|
|
28
|
+
lastChecked: new Date(),
|
|
29
|
+
};
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Tool Definitions
|
|
32
|
+
// ============================================================================
|
|
33
|
+
const TOOLS = [
|
|
34
|
+
// Status & Info
|
|
35
|
+
{
|
|
36
|
+
name: "browser_status",
|
|
37
|
+
description: "Check if dev-browser is available and get status info",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "browser_help",
|
|
45
|
+
description: "Get dev-browser CLI help text with examples (useful for understanding capabilities)",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
// Navigation
|
|
52
|
+
{
|
|
53
|
+
name: "browser_navigate",
|
|
54
|
+
description: "Navigate to a URL in a named page (creates page if doesn't exist)",
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: "object",
|
|
57
|
+
properties: {
|
|
58
|
+
url: {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: "URL to navigate to",
|
|
61
|
+
},
|
|
62
|
+
pageName: {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "Page name (default: 'main')",
|
|
65
|
+
default: "main",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
required: ["url"],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "browser_get_url",
|
|
73
|
+
description: "Get the current URL of a page",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: "object",
|
|
76
|
+
properties: {
|
|
77
|
+
pageName: {
|
|
78
|
+
type: "string",
|
|
79
|
+
description: "Page name (default: 'main')",
|
|
80
|
+
default: "main",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "browser_get_title",
|
|
87
|
+
description: "Get the page title",
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: "object",
|
|
90
|
+
properties: {
|
|
91
|
+
pageName: {
|
|
92
|
+
type: "string",
|
|
93
|
+
description: "Page name (default: 'main')",
|
|
94
|
+
default: "main",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
// Page Management
|
|
100
|
+
{
|
|
101
|
+
name: "browser_list_pages",
|
|
102
|
+
description: "List all browser pages/tabs",
|
|
103
|
+
inputSchema: {
|
|
104
|
+
type: "object",
|
|
105
|
+
properties: {},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "browser_close_page",
|
|
110
|
+
description: "Close a named page",
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: "object",
|
|
113
|
+
properties: {
|
|
114
|
+
pageName: {
|
|
115
|
+
type: "string",
|
|
116
|
+
description: "Page name to close",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
required: ["pageName"],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
// Interactions
|
|
123
|
+
{
|
|
124
|
+
name: "browser_click",
|
|
125
|
+
description: "Click an element by selector",
|
|
126
|
+
inputSchema: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
selector: {
|
|
130
|
+
type: "string",
|
|
131
|
+
description: "CSS selector for element to click",
|
|
132
|
+
},
|
|
133
|
+
pageName: {
|
|
134
|
+
type: "string",
|
|
135
|
+
description: "Page name (default: 'main')",
|
|
136
|
+
default: "main",
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
required: ["selector"],
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "browser_fill",
|
|
144
|
+
description: "Fill a form field with text (clears existing content first)",
|
|
145
|
+
inputSchema: {
|
|
146
|
+
type: "object",
|
|
147
|
+
properties: {
|
|
148
|
+
selector: {
|
|
149
|
+
type: "string",
|
|
150
|
+
description: "CSS selector for input field",
|
|
151
|
+
},
|
|
152
|
+
value: {
|
|
153
|
+
type: "string",
|
|
154
|
+
description: "Value to fill",
|
|
155
|
+
},
|
|
156
|
+
pageName: {
|
|
157
|
+
type: "string",
|
|
158
|
+
description: "Page name (default: 'main')",
|
|
159
|
+
default: "main",
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
required: ["selector", "value"],
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "browser_type",
|
|
167
|
+
description: "Type text into an element (appends, doesn't clear)",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: {
|
|
171
|
+
selector: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "CSS selector for element",
|
|
174
|
+
},
|
|
175
|
+
text: {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "Text to type",
|
|
178
|
+
},
|
|
179
|
+
pageName: {
|
|
180
|
+
type: "string",
|
|
181
|
+
description: "Page name (default: 'main')",
|
|
182
|
+
default: "main",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
required: ["selector", "text"],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: "browser_press",
|
|
190
|
+
description: "Press a keyboard key (e.g., 'Enter', 'Tab', 'Escape')",
|
|
191
|
+
inputSchema: {
|
|
192
|
+
type: "object",
|
|
193
|
+
properties: {
|
|
194
|
+
key: {
|
|
195
|
+
type: "string",
|
|
196
|
+
description: "Key to press (e.g., 'Enter', 'Tab', 'Escape', 'ArrowDown')",
|
|
197
|
+
},
|
|
198
|
+
pageName: {
|
|
199
|
+
type: "string",
|
|
200
|
+
description: "Page name (default: 'main')",
|
|
201
|
+
default: "main",
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
required: ["key"],
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
// Waiting
|
|
208
|
+
{
|
|
209
|
+
name: "browser_wait_for_selector",
|
|
210
|
+
description: "Wait for an element to appear on the page",
|
|
211
|
+
inputSchema: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
selector: {
|
|
215
|
+
type: "string",
|
|
216
|
+
description: "CSS selector to wait for",
|
|
217
|
+
},
|
|
218
|
+
timeout: {
|
|
219
|
+
type: "number",
|
|
220
|
+
description: "Timeout in ms (default: 30000)",
|
|
221
|
+
default: 30000,
|
|
222
|
+
},
|
|
223
|
+
pageName: {
|
|
224
|
+
type: "string",
|
|
225
|
+
description: "Page name (default: 'main')",
|
|
226
|
+
default: "main",
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
required: ["selector"],
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
// Inspection
|
|
233
|
+
{
|
|
234
|
+
name: "browser_snapshot",
|
|
235
|
+
description: "Get AI-friendly page snapshot (DOM structure, text content, interactive elements)",
|
|
236
|
+
inputSchema: {
|
|
237
|
+
type: "object",
|
|
238
|
+
properties: {
|
|
239
|
+
pageName: {
|
|
240
|
+
type: "string",
|
|
241
|
+
description: "Page name (default: 'main')",
|
|
242
|
+
default: "main",
|
|
243
|
+
},
|
|
244
|
+
depth: {
|
|
245
|
+
type: "number",
|
|
246
|
+
description: "DOM traversal depth (default: 10)",
|
|
247
|
+
default: 10,
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "browser_screenshot",
|
|
254
|
+
description: "Take a screenshot of the page",
|
|
255
|
+
inputSchema: {
|
|
256
|
+
type: "object",
|
|
257
|
+
properties: {
|
|
258
|
+
filename: {
|
|
259
|
+
type: "string",
|
|
260
|
+
description: "Filename for screenshot (saved to ~/.dev-browser/tmp/)",
|
|
261
|
+
},
|
|
262
|
+
pageName: {
|
|
263
|
+
type: "string",
|
|
264
|
+
description: "Page name (default: 'main')",
|
|
265
|
+
default: "main",
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
required: ["filename"],
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
// Advanced
|
|
272
|
+
{
|
|
273
|
+
name: "browser_evaluate",
|
|
274
|
+
description: "Evaluate JavaScript in the page context",
|
|
275
|
+
inputSchema: {
|
|
276
|
+
type: "object",
|
|
277
|
+
properties: {
|
|
278
|
+
code: {
|
|
279
|
+
type: "string",
|
|
280
|
+
description: "JavaScript code to execute",
|
|
281
|
+
},
|
|
282
|
+
pageName: {
|
|
283
|
+
type: "string",
|
|
284
|
+
description: "Page name (default: 'main')",
|
|
285
|
+
default: "main",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
required: ["code"],
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: "browser_execute_script",
|
|
293
|
+
description: "Execute a raw dev-browser script (full Playwright API access)",
|
|
294
|
+
inputSchema: {
|
|
295
|
+
type: "object",
|
|
296
|
+
properties: {
|
|
297
|
+
script: {
|
|
298
|
+
type: "string",
|
|
299
|
+
description: "JavaScript code using browser, page, and Playwright API",
|
|
300
|
+
},
|
|
301
|
+
headless: {
|
|
302
|
+
type: "boolean",
|
|
303
|
+
description: "Run in headless mode (default: true)",
|
|
304
|
+
default: true,
|
|
305
|
+
},
|
|
306
|
+
connect: {
|
|
307
|
+
type: "boolean",
|
|
308
|
+
description: "Connect to existing Chrome (requires remote debugging enabled)",
|
|
309
|
+
default: false,
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
required: ["script"],
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
];
|
|
316
|
+
// ============================================================================
|
|
317
|
+
// Tool Handlers
|
|
318
|
+
// ============================================================================
|
|
319
|
+
async function handleToolCall(name, args) {
|
|
320
|
+
try {
|
|
321
|
+
// Check availability first (except for status/help tools)
|
|
322
|
+
if (name !== "browser_status" && name !== "browser_help") {
|
|
323
|
+
if (!browserStatus.available) {
|
|
324
|
+
// Re-check in case it was installed
|
|
325
|
+
browserStatus.available = await isDevBrowserAvailable();
|
|
326
|
+
browserStatus.lastChecked = new Date();
|
|
327
|
+
if (!browserStatus.available) {
|
|
328
|
+
return {
|
|
329
|
+
content: [{
|
|
330
|
+
type: "text",
|
|
331
|
+
text: JSON.stringify({
|
|
332
|
+
success: false,
|
|
333
|
+
error: "dev-browser is not installed",
|
|
334
|
+
hint: "Install with: npm install -g dev-browser && dev-browser install",
|
|
335
|
+
tool: name,
|
|
336
|
+
}, null, 2),
|
|
337
|
+
}],
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
switch (name) {
|
|
343
|
+
case "browser_status": {
|
|
344
|
+
browserStatus.available = await isDevBrowserAvailable();
|
|
345
|
+
browserStatus.lastChecked = new Date();
|
|
346
|
+
return {
|
|
347
|
+
content: [{
|
|
348
|
+
type: "text",
|
|
349
|
+
text: JSON.stringify({
|
|
350
|
+
available: browserStatus.available,
|
|
351
|
+
lastChecked: browserStatus.lastChecked.toISOString(),
|
|
352
|
+
message: browserStatus.available
|
|
353
|
+
? "dev-browser is available"
|
|
354
|
+
: "dev-browser is NOT installed. Install with: npm install -g dev-browser",
|
|
355
|
+
}, null, 2),
|
|
356
|
+
}],
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
case "browser_help": {
|
|
360
|
+
const helpText = await getDevBrowserHelp();
|
|
361
|
+
return {
|
|
362
|
+
content: [{
|
|
363
|
+
type: "text",
|
|
364
|
+
text: helpText || "Could not retrieve help text",
|
|
365
|
+
}],
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
case "browser_navigate": {
|
|
369
|
+
const url = args.url;
|
|
370
|
+
const pageName = args.pageName || "main";
|
|
371
|
+
const result = await navigate(url, pageName);
|
|
372
|
+
return {
|
|
373
|
+
content: [{
|
|
374
|
+
type: "text",
|
|
375
|
+
text: JSON.stringify(result, null, 2),
|
|
376
|
+
}],
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
case "browser_get_url": {
|
|
380
|
+
const pageName = args.pageName || "main";
|
|
381
|
+
const result = await getUrl(pageName);
|
|
382
|
+
return {
|
|
383
|
+
content: [{
|
|
384
|
+
type: "text",
|
|
385
|
+
text: JSON.stringify(result, null, 2),
|
|
386
|
+
}],
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
case "browser_get_title": {
|
|
390
|
+
const pageName = args.pageName || "main";
|
|
391
|
+
const result = await getTitle(pageName);
|
|
392
|
+
return {
|
|
393
|
+
content: [{
|
|
394
|
+
type: "text",
|
|
395
|
+
text: JSON.stringify(result, null, 2),
|
|
396
|
+
}],
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
case "browser_list_pages": {
|
|
400
|
+
const result = await listPages();
|
|
401
|
+
return {
|
|
402
|
+
content: [{
|
|
403
|
+
type: "text",
|
|
404
|
+
text: JSON.stringify(result, null, 2),
|
|
405
|
+
}],
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
case "browser_close_page": {
|
|
409
|
+
const pageName = args.pageName;
|
|
410
|
+
const result = await closePage(pageName);
|
|
411
|
+
return {
|
|
412
|
+
content: [{
|
|
413
|
+
type: "text",
|
|
414
|
+
text: JSON.stringify(result, null, 2),
|
|
415
|
+
}],
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
case "browser_click": {
|
|
419
|
+
const selector = args.selector;
|
|
420
|
+
const pageName = args.pageName || "main";
|
|
421
|
+
const result = await click(selector, pageName);
|
|
422
|
+
return {
|
|
423
|
+
content: [{
|
|
424
|
+
type: "text",
|
|
425
|
+
text: JSON.stringify(result, null, 2),
|
|
426
|
+
}],
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
case "browser_fill": {
|
|
430
|
+
const selector = args.selector;
|
|
431
|
+
const value = args.value;
|
|
432
|
+
const pageName = args.pageName || "main";
|
|
433
|
+
const result = await fill(selector, value, pageName);
|
|
434
|
+
return {
|
|
435
|
+
content: [{
|
|
436
|
+
type: "text",
|
|
437
|
+
text: JSON.stringify(result, null, 2),
|
|
438
|
+
}],
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
case "browser_type": {
|
|
442
|
+
const selector = args.selector;
|
|
443
|
+
const text = args.text;
|
|
444
|
+
const pageName = args.pageName || "main";
|
|
445
|
+
const result = await type(selector, text, pageName);
|
|
446
|
+
return {
|
|
447
|
+
content: [{
|
|
448
|
+
type: "text",
|
|
449
|
+
text: JSON.stringify(result, null, 2),
|
|
450
|
+
}],
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
case "browser_press": {
|
|
454
|
+
const key = args.key;
|
|
455
|
+
const pageName = args.pageName || "main";
|
|
456
|
+
const result = await press(key, pageName);
|
|
457
|
+
return {
|
|
458
|
+
content: [{
|
|
459
|
+
type: "text",
|
|
460
|
+
text: JSON.stringify(result, null, 2),
|
|
461
|
+
}],
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
case "browser_wait_for_selector": {
|
|
465
|
+
const selector = args.selector;
|
|
466
|
+
const timeout = args.timeout || 30000;
|
|
467
|
+
const pageName = args.pageName || "main";
|
|
468
|
+
const result = await waitForSelector(selector, { pageName, timeout });
|
|
469
|
+
return {
|
|
470
|
+
content: [{
|
|
471
|
+
type: "text",
|
|
472
|
+
text: JSON.stringify(result, null, 2),
|
|
473
|
+
}],
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
case "browser_snapshot": {
|
|
477
|
+
const pageName = args.pageName || "main";
|
|
478
|
+
const depth = args.depth || 10;
|
|
479
|
+
const result = await snapshot({ pageName, depth });
|
|
480
|
+
return {
|
|
481
|
+
content: [{
|
|
482
|
+
type: "text",
|
|
483
|
+
text: JSON.stringify(result, null, 2),
|
|
484
|
+
}],
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
case "browser_screenshot": {
|
|
488
|
+
const filename = args.filename;
|
|
489
|
+
const pageName = args.pageName || "main";
|
|
490
|
+
const result = await screenshot(filename, pageName);
|
|
491
|
+
return {
|
|
492
|
+
content: [{
|
|
493
|
+
type: "text",
|
|
494
|
+
text: JSON.stringify(result, null, 2),
|
|
495
|
+
}],
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
case "browser_evaluate": {
|
|
499
|
+
const code = args.code;
|
|
500
|
+
const pageName = args.pageName || "main";
|
|
501
|
+
const result = await evaluate(code, pageName);
|
|
502
|
+
return {
|
|
503
|
+
content: [{
|
|
504
|
+
type: "text",
|
|
505
|
+
text: JSON.stringify(result, null, 2),
|
|
506
|
+
}],
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
case "browser_execute_script": {
|
|
510
|
+
const script = args.script;
|
|
511
|
+
const headless = args.headless !== false;
|
|
512
|
+
const connect = args.connect === true;
|
|
513
|
+
const result = await executeScript(script, { headless, connect });
|
|
514
|
+
return {
|
|
515
|
+
content: [{
|
|
516
|
+
type: "text",
|
|
517
|
+
text: JSON.stringify(result, null, 2),
|
|
518
|
+
}],
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
default:
|
|
522
|
+
return {
|
|
523
|
+
content: [{
|
|
524
|
+
type: "text",
|
|
525
|
+
text: JSON.stringify({ error: `Unknown tool: ${name}` }),
|
|
526
|
+
}],
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
catch (error) {
|
|
531
|
+
return {
|
|
532
|
+
content: [{
|
|
533
|
+
type: "text",
|
|
534
|
+
text: JSON.stringify({
|
|
535
|
+
success: false,
|
|
536
|
+
error: error instanceof Error ? error.message : String(error),
|
|
537
|
+
}, null, 2),
|
|
538
|
+
}],
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
// ============================================================================
|
|
543
|
+
// Server Setup
|
|
544
|
+
// ============================================================================
|
|
545
|
+
const server = new Server({
|
|
546
|
+
name: "@ebowwa/mcp-browser",
|
|
547
|
+
version: "0.1.0",
|
|
548
|
+
}, {
|
|
549
|
+
capabilities: {
|
|
550
|
+
tools: {},
|
|
551
|
+
resources: {},
|
|
552
|
+
},
|
|
553
|
+
});
|
|
554
|
+
// List tools
|
|
555
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
556
|
+
tools: TOOLS,
|
|
557
|
+
}));
|
|
558
|
+
// Handle tool calls
|
|
559
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
560
|
+
const { name, arguments: args } = request.params;
|
|
561
|
+
return handleToolCall(name, args || {});
|
|
562
|
+
});
|
|
563
|
+
// List resources
|
|
564
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
565
|
+
resources: [
|
|
566
|
+
{
|
|
567
|
+
uri: "browser://status",
|
|
568
|
+
name: "Browser Status",
|
|
569
|
+
description: "Current status of dev-browser integration",
|
|
570
|
+
mimeType: "application/json",
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
uri: "browser://help",
|
|
574
|
+
name: "Browser Help",
|
|
575
|
+
description: "dev-browser CLI help and examples",
|
|
576
|
+
mimeType: "text/plain",
|
|
577
|
+
},
|
|
578
|
+
],
|
|
579
|
+
}));
|
|
580
|
+
// Read resources
|
|
581
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
582
|
+
const { uri } = request.params;
|
|
583
|
+
switch (uri) {
|
|
584
|
+
case "browser://status": {
|
|
585
|
+
const available = await isDevBrowserAvailable();
|
|
586
|
+
return {
|
|
587
|
+
contents: [{
|
|
588
|
+
uri,
|
|
589
|
+
mimeType: "application/json",
|
|
590
|
+
text: JSON.stringify({
|
|
591
|
+
available,
|
|
592
|
+
package: "@ebowwa/mcp-browser",
|
|
593
|
+
version: "0.1.0",
|
|
594
|
+
dependency: "dev-browser (optional)",
|
|
595
|
+
installHint: available
|
|
596
|
+
? null
|
|
597
|
+
: "npm install -g dev-browser && dev-browser install",
|
|
598
|
+
}, null, 2),
|
|
599
|
+
}],
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
case "browser://help": {
|
|
603
|
+
const help = await getDevBrowserHelp();
|
|
604
|
+
return {
|
|
605
|
+
contents: [{
|
|
606
|
+
uri,
|
|
607
|
+
mimeType: "text/plain",
|
|
608
|
+
text: help || "Help not available - dev-browser may not be installed",
|
|
609
|
+
}],
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
default:
|
|
613
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
// Start server
|
|
617
|
+
async function main() {
|
|
618
|
+
// Check availability at startup (non-blocking)
|
|
619
|
+
isDevBrowserAvailable().then((available) => {
|
|
620
|
+
browserStatus.available = available;
|
|
621
|
+
browserStatus.lastChecked = new Date();
|
|
622
|
+
if (!available) {
|
|
623
|
+
console.error("[mcp-browser] dev-browser not found. Install with: npm install -g dev-browser");
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
const transport = new StdioServerTransport();
|
|
627
|
+
await server.connect(transport);
|
|
628
|
+
console.error("@ebowwa/mcp-browser started (optional extension)");
|
|
629
|
+
}
|
|
630
|
+
main().catch((error) => {
|
|
631
|
+
console.error("Server error:", error);
|
|
632
|
+
process.exit(1);
|
|
633
|
+
});
|
|
634
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ebowwa/mcp-browser",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for browser automation via dev-browser (optional extension)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"mcp-browser": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "bun run --watch src/index.ts",
|
|
24
|
+
"start": "node dist/index.js",
|
|
25
|
+
"test": "bun test",
|
|
26
|
+
"typecheck": "tsc --noEmit"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"mcp",
|
|
30
|
+
"browser",
|
|
31
|
+
"automation",
|
|
32
|
+
"playwright",
|
|
33
|
+
"dev-browser",
|
|
34
|
+
"coder"
|
|
35
|
+
],
|
|
36
|
+
"author": "ebowwa",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.10.2"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"dev-browser": ">=1.0.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependenciesMeta": {
|
|
45
|
+
"dev-browser": {
|
|
46
|
+
"optional": true
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/bun": "^1.2.5",
|
|
51
|
+
"@types/node": "^22.13.10",
|
|
52
|
+
"typescript": "^5.8.2"
|
|
53
|
+
}
|
|
54
|
+
}
|