@mindstone/mcp-server-browser-automation 0.2.3 → 0.2.4
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 +6 -10
- package/dist/browser-client.d.ts +3 -7
- package/dist/browser-client.js +49 -66
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Browser control you can watch: open pages, sign in, click around, fill forms, ta
|
|
|
9
9
|
|
|
10
10
|
## Status
|
|
11
11
|
|
|
12
|
-
- **Version:** [0.2.
|
|
12
|
+
- **Version:** [0.2.4](./CHANGELOG.md) · [npm](https://www.npmjs.com/package/@mindstone/mcp-server-browser-automation)
|
|
13
13
|
- **Auth:** None ([`server.json`](./server.json))
|
|
14
14
|
- **Tools:** [21](./src/tools/) (navigation, observation, interaction, sessions, files)
|
|
15
15
|
- **Surface:** browser-automation
|
|
@@ -44,7 +44,7 @@ Response (trimmed):
|
|
|
44
44
|
|
|
45
45
|
- Node.js 20+
|
|
46
46
|
- npm
|
|
47
|
-
-
|
|
47
|
+
- Nothing else to install for the CLI: the server ships `agent-browser` as a dependency.
|
|
48
48
|
|
|
49
49
|
<!-- BEGIN INSTALL_LINKS: do not edit by hand; regenerated by scripts/gen-install-links.mjs -->
|
|
50
50
|
## One-click install
|
|
@@ -94,20 +94,16 @@ npm install -g @mindstone/mcp-server-browser-automation
|
|
|
94
94
|
mcp-server-browser-automation
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
This server
|
|
97
|
+
This server uses the `agent-browser` CLI to control the browser.
|
|
98
98
|
|
|
99
99
|
### Binary Resolution
|
|
100
100
|
|
|
101
|
-
1. **PATH lookup** (preferred): If `agent-browser` is on your PATH, it is used directly.
|
|
102
|
-
2. **
|
|
101
|
+
1. **PATH lookup** (preferred): If an `agent-browser` executable is on your PATH, it is used directly.
|
|
102
|
+
2. **Bundled copy**: Otherwise the server runs the `agent-browser` package it ships as a dependency (pinned to 0.33.2), with the same Node that runs the server. No shell and no `npx` are involved, so this works the same on Windows, macOS and Linux.
|
|
103
103
|
|
|
104
104
|
### Installing agent-browser
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
npm install -g agent-browser
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Or let the npx fallback handle it automatically (slower on first use due to download).
|
|
106
|
+
Nothing to do: installing this server installs `agent-browser` with it. A separate executable on PATH takes precedence. On Windows, npm's `.cmd` shims cannot be used, so the bundled copy runs instead.
|
|
111
107
|
|
|
112
108
|
## Configuration
|
|
113
109
|
|
package/dist/browser-client.d.ts
CHANGED
|
@@ -21,13 +21,9 @@ export interface ExecOptions {
|
|
|
21
21
|
* on the CLI — passing one would be a CLI error — so headless is the absence
|
|
22
22
|
* of `--headed`.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Runs an `agent-browser` executable from PATH when there is one; otherwise
|
|
25
|
+
* runs the connector's own agent-browser dependency with this Node. Both use
|
|
26
|
+
* execFile with no shell, so no argument is ever interpreted by a shell.
|
|
26
27
|
*/
|
|
27
28
|
export declare function execAgentBrowser(args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
28
|
-
/**
|
|
29
|
-
* Reset the resolved binary cache.
|
|
30
|
-
* Primarily used for testing to reset state between test runs.
|
|
31
|
-
*/
|
|
32
|
-
export declare function resetBinaryCache(): void;
|
|
33
29
|
//# sourceMappingURL=browser-client.d.ts.map
|
package/dist/browser-client.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import { promisify } from 'node:util';
|
|
3
4
|
import { ConnectorError, DEFAULT_TIMEOUT_MS, SESSION_NAME } from './types.js';
|
|
4
5
|
import { wrapUntrusted } from './untrusted-content.js';
|
|
5
6
|
const execFileAsync = promisify(execFile);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
const MAX_BUFFER = 10 * 1024 * 1024; // 10MB for large snapshots
|
|
8
|
+
let bundledEntry = null;
|
|
9
|
+
/**
|
|
10
|
+
* Path to the JS entry of the agent-browser package this connector depends
|
|
11
|
+
* on. Run with `process.execPath` rather than through an npm `.cmd` shim or
|
|
12
|
+
* npx: on Windows, execFile cannot start a shim without a shell, and npx
|
|
13
|
+
* reaches the CLI through cmd.exe, which cuts arguments at the first newline.
|
|
14
|
+
* Throws MODULE_NOT_FOUND when the dependency is missing.
|
|
15
|
+
*/
|
|
16
|
+
function resolveBundledEntry() {
|
|
17
|
+
if (!bundledEntry) {
|
|
18
|
+
bundledEntry = createRequire(import.meta.url).resolve('agent-browser/bin/agent-browser.js');
|
|
19
|
+
}
|
|
20
|
+
return bundledEntry;
|
|
14
21
|
}
|
|
15
22
|
function buildEnv() {
|
|
16
23
|
const env = { ...process.env };
|
|
@@ -54,18 +61,6 @@ function resolveHeaded(optionHeaded, env) {
|
|
|
54
61
|
return false;
|
|
55
62
|
return true;
|
|
56
63
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Pinned version of agent-browser used by the npx fallback.
|
|
59
|
-
*
|
|
60
|
-
* Why pinned: keeps fallback behavior reproducible. Bump when verified against
|
|
61
|
-
* a newer release. Do not use `latest` — npx caches by spec, and an unpinned
|
|
62
|
-
* spec produces flaky behavior across machines.
|
|
63
|
-
*
|
|
64
|
-
* 0.33.2 verified 2026-08-05 against the connector's full command surface
|
|
65
|
-
* (open, snapshot -i, screenshot, pdf, get url/title/text, tab, click/fill/
|
|
66
|
-
* type/press/scroll/select/hover, eval, back/forward, wait, close).
|
|
67
|
-
*/
|
|
68
|
-
const NPX_FALLBACK_VERSION = '0.33.2';
|
|
69
64
|
/**
|
|
70
65
|
* Build the ConnectorError message for a failed CLI invocation.
|
|
71
66
|
*
|
|
@@ -99,8 +94,9 @@ function cliFailureMessage(command, stderr, stdout) {
|
|
|
99
94
|
* on the CLI — passing one would be a CLI error — so headless is the absence
|
|
100
95
|
* of `--headed`.
|
|
101
96
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
97
|
+
* Runs an `agent-browser` executable from PATH when there is one; otherwise
|
|
98
|
+
* runs the connector's own agent-browser dependency with this Node. Both use
|
|
99
|
+
* execFile with no shell, so no argument is ever interpreted by a shell.
|
|
104
100
|
*/
|
|
105
101
|
export async function execAgentBrowser(args, options) {
|
|
106
102
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
@@ -111,59 +107,46 @@ export async function execAgentBrowser(args, options) {
|
|
|
111
107
|
if (resolveHeaded(options?.headed, env) && args.length > 0) {
|
|
112
108
|
args = [args[0], '--headed', ...args.slice(1)];
|
|
113
109
|
}
|
|
114
|
-
const
|
|
115
|
-
try {
|
|
110
|
+
const run = async (file, fileArgs) => {
|
|
116
111
|
// execFile is safe against command injection (no shell interpretation)
|
|
117
|
-
const result = await execFileAsync(
|
|
112
|
+
const result = await execFileAsync(file, fileArgs, {
|
|
118
113
|
env,
|
|
119
114
|
timeout: timeoutMs,
|
|
120
|
-
maxBuffer:
|
|
115
|
+
maxBuffer: MAX_BUFFER,
|
|
116
|
+
// GUI hosts should not open a console window for each CLI call on Windows.
|
|
117
|
+
windowsHide: true,
|
|
121
118
|
});
|
|
122
119
|
return { stdout: result.stdout, stderr: result.stderr ?? '' };
|
|
120
|
+
};
|
|
121
|
+
try {
|
|
122
|
+
return await run('agent-browser', args);
|
|
123
123
|
}
|
|
124
124
|
catch (error) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
// from the npm cache / registry).
|
|
128
|
-
if (err.code === 'ENOENT') {
|
|
129
|
-
try {
|
|
130
|
-
const npxResult = await execFileAsync('npx', ['-y', `agent-browser@${NPX_FALLBACK_VERSION}`, ...args], {
|
|
131
|
-
env,
|
|
132
|
-
timeout: timeoutMs + 15_000, // extra time for npx install
|
|
133
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
134
|
-
});
|
|
135
|
-
return { stdout: npxResult.stdout, stderr: npxResult.stderr ?? '' };
|
|
136
|
-
}
|
|
137
|
-
catch (npxError) {
|
|
138
|
-
const npxErr = npxError;
|
|
139
|
-
// Distinguish: npx itself missing (true binary-not-found) vs
|
|
140
|
-
// agent-browser ran but returned non-zero (CLI error surfaced via npx).
|
|
141
|
-
if (npxErr.code === 'ENOENT') {
|
|
142
|
-
throw new ConnectorError(`agent-browser binary not found on PATH and npx is also unavailable: ${npxErr.message ?? String(npxErr)}`, 'BINARY_NOT_FOUND', 'Install agent-browser: npm install -g agent-browser\n' +
|
|
143
|
-
'Or ensure npx is available on PATH.');
|
|
144
|
-
}
|
|
145
|
-
// npx ran but the underlying CLI exited non-zero — propagate as CLI_ERROR
|
|
146
|
-
// with the (enveloped) stderr for diagnosis.
|
|
147
|
-
throw new ConnectorError(cliFailureMessage(args[0], npxErr.stderr, npxErr.stdout), 'CLI_ERROR', 'The agent-browser CLI command failed (via npx fallback). ' +
|
|
148
|
-
'Check the error details above. ' +
|
|
149
|
-
'For best performance, install agent-browser globally: npm install -g agent-browser');
|
|
150
|
-
}
|
|
125
|
+
if (error.code !== 'ENOENT') {
|
|
126
|
+
throw classifyFailure(error, args[0], timeoutMs);
|
|
151
127
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
throw new ConnectorError(cliFailureMessage(args[0], err.stderr, err.stdout), 'CLI_ERROR', 'The agent-browser CLI command failed. Check that agent-browser is installed and the browser session is active.');
|
|
128
|
+
}
|
|
129
|
+
// Not on PATH: run the bundled copy.
|
|
130
|
+
try {
|
|
131
|
+
return await run(process.execPath, [resolveBundledEntry(), ...args]);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
throw classifyFailure(error, args[0], timeoutMs);
|
|
160
135
|
}
|
|
161
136
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
137
|
+
function classifyFailure(error, command, timeoutMs) {
|
|
138
|
+
const err = error;
|
|
139
|
+
// Timeout — name only the subcommand: the full argument vector may carry
|
|
140
|
+
// sensitive values (URLs with userinfo, selectors, filenames, typed
|
|
141
|
+
// values, evaluation scripts) and must not be echoed to the model.
|
|
142
|
+
if (err.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER' || err.killed) {
|
|
143
|
+
return new ConnectorError(`Command timed out after ${timeoutMs}ms: agent-browser ${command}`, 'TIMEOUT', 'The browser operation took too long. Try a simpler action or increase the timeout.');
|
|
144
|
+
}
|
|
145
|
+
// Neither a PATH executable nor the bundled dependency could be started.
|
|
146
|
+
if (err.code === 'MODULE_NOT_FOUND' || err.code === 'ENOENT') {
|
|
147
|
+
return new ConnectorError('agent-browser is not on PATH and the copy bundled with this connector could not be found', 'BINARY_NOT_FOUND', "This connector's installation is incomplete. Reinstall the connector.");
|
|
148
|
+
}
|
|
149
|
+
// Other errors — include the (enveloped) stderr for diagnostics
|
|
150
|
+
return new ConnectorError(cliFailureMessage(command, err.stderr, err.stdout), 'CLI_ERROR', 'The agent-browser CLI command failed. Check that agent-browser is installed and the browser session is active.');
|
|
168
151
|
}
|
|
169
152
|
//# sourceMappingURL=browser-client.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Sessions persist automatically between invocations.
|
|
8
8
|
*
|
|
9
9
|
* Requirements:
|
|
10
|
-
* - agent-browser
|
|
10
|
+
* - agent-browser executable on PATH, or the bundled dependency run with this Node
|
|
11
11
|
*
|
|
12
12
|
* Environment variables:
|
|
13
13
|
* - AGENT_BROWSER_SESSION_NAME: Session name for persistence (default: "mcp")
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Sessions persist automatically between invocations.
|
|
8
8
|
*
|
|
9
9
|
* Requirements:
|
|
10
|
-
* - agent-browser
|
|
10
|
+
* - agent-browser executable on PATH, or the bundled dependency run with this Node
|
|
11
11
|
*
|
|
12
12
|
* Environment variables:
|
|
13
13
|
* - AGENT_BROWSER_SESSION_NAME: Session name for persistence (default: "mcp")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindstone/mcp-server-browser-automation",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"mcpName": "io.github.mindstone/mcp-server-browser-automation",
|
|
5
5
|
"description": "Browser automation MCP server — visible-by-default browser control via accessibility snapshots, navigation, form filling, screenshots, and tab management. Set AGENT_BROWSER_SHOW_WINDOW=false to run quietly.",
|
|
6
6
|
"license": "FSL-1.1-MIT",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
35
|
+
"agent-browser": "0.33.2",
|
|
35
36
|
"graceful-fs": "^4.2.11",
|
|
36
37
|
"zod": "^3.23.0"
|
|
37
38
|
},
|