@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 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.3](./CHANGELOG.md) · [npm](https://www.npmjs.com/package/@mindstone/mcp-server-browser-automation)
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
- - The `agent-browser` CLI on `PATH`, or `npx` available so the server can install it automatically.
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 requires the `agent-browser` CLI binary to control the browser.
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. **npx fallback**: If the binary is not found, the server automatically falls back to `npx -y agent-browser@0.33.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
- ```bash
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
 
@@ -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
- * Falls back to `npx -y agent-browser@<NPX_FALLBACK_VERSION>` if the binary is
25
- * not on PATH. Uses execFile (no shell) to prevent command injection.
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
@@ -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
- let resolvedBinary = null;
7
- function resolveAgentBrowser() {
8
- if (resolvedBinary)
9
- return resolvedBinary;
10
- // Default to the binary name — execFile will search PATH.
11
- // If not found (ENOENT), the caller falls back to npx.
12
- resolvedBinary = 'agent-browser';
13
- return resolvedBinary;
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
- * Falls back to `npx -y agent-browser@<NPX_FALLBACK_VERSION>` if the binary is
103
- * not on PATH. Uses execFile (no shell) to prevent command injection.
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 binary = resolveAgentBrowser();
115
- try {
110
+ const run = async (file, fileArgs) => {
116
111
  // execFile is safe against command injection (no shell interpretation)
117
- const result = await execFileAsync(binary, args, {
112
+ const result = await execFileAsync(file, fileArgs, {
118
113
  env,
119
114
  timeout: timeoutMs,
120
- maxBuffer: 10 * 1024 * 1024, // 10MB for large snapshots
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
- const err = error;
126
- // Binary not found on PATH — try npx fallback (pulls a pinned version
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
- // Timeout — name only the subcommand: the full argument vector may carry
153
- // sensitive values (URLs with userinfo, selectors, filenames, typed
154
- // values, evaluation scripts) and must not be echoed to the model.
155
- if (err.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER' || err.killed) {
156
- throw new ConnectorError(`Command timed out after ${timeoutMs}ms: agent-browser ${args[0]}`, 'TIMEOUT', 'The browser operation took too long. Try a simpler action or increase the timeout.');
157
- }
158
- // Other errors — include the (enveloped) stderr for diagnostics
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
- * Reset the resolved binary cache.
164
- * Primarily used for testing to reset state between test runs.
165
- */
166
- export function resetBinaryCache() {
167
- resolvedBinary = null;
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 CLI binary on PATH, or npx available for fallback
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 CLI binary on PATH, or npx available for fallback
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",
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
  },