machine-bridge-mcp 0.13.0 → 0.15.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/CHANGELOG.md +38 -0
- package/README.md +41 -12
- package/SECURITY.md +5 -5
- package/browser-extension/browser-operations.js +515 -0
- package/browser-extension/devtools-input.js +151 -0
- package/browser-extension/manifest.json +3 -2
- package/browser-extension/page-automation.js +540 -75
- package/browser-extension/pairing.js +1 -1
- package/browser-extension/service-worker.js +158 -258
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/AUDIT.md +13 -1
- package/docs/LOCAL_AUTOMATION.md +18 -14
- package/docs/OPERATIONS.md +17 -9
- package/docs/TESTING.md +4 -4
- package/package.json +10 -4
- package/src/local/agent-context.mjs +1 -1
- package/src/local/browser-bridge.mjs +245 -91
- package/src/local/browser-command.mjs +126 -0
- package/src/local/cli.mjs +37 -5
- package/src/local/runtime.mjs +2 -0
- package/src/local/service.mjs +7 -3
- package/src/shared/tool-catalog.json +214 -8
- package/src/worker/index.ts +14 -8
package/docs/OPERATIONS.md
CHANGED
|
@@ -44,14 +44,15 @@ machine-mcp browser setup
|
|
|
44
44
|
machine-mcp browser status
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
`browser setup` prints the unpacked-extension path and opens the local pairing page. Load that directory
|
|
47
|
+
`browser setup` prints the unpacked-extension path and opens the local pairing page. Load that directory into the Chromium profile you actually use; it is not installed into Playwright or a separate automation profile. `browser status` prints the authenticated extension build/protocol and the existing-profile backend. The pairing page contains the token only in non-cacheable loopback HTML; the CLI and MCP result do not print it. A first pairing is automatic. When local pairing state was reset or moved, click the extension icon on the active pairing page to authorize replacing the extension's previous broker configuration.
|
|
48
48
|
|
|
49
49
|
Diagnosis:
|
|
50
50
|
|
|
51
51
|
| Result | Interpretation |
|
|
52
52
|
|---|---|
|
|
53
53
|
| broker not reachable | no full-profile runtime owns the machine broker, state is stale, or a local security product blocked loopback listening |
|
|
54
|
-
| broker running, extension disconnected | extension not loaded/enabled, pairing not completed, browser profile not running, or MV3 worker reconnect failed |
|
|
54
|
+
| broker running, extension disconnected | extension not loaded/enabled in the intended Chromium profile, pairing not completed, browser profile not running, or MV3 worker reconnect failed |
|
|
55
|
+
| extension reload required | unpacked files, permissions, protocol, or capability set differ from the running extension; reload it from the extensions page and revisit the pairing page |
|
|
55
56
|
| tab list works but page action fails | restricted browser-internal page, inaccessible frame, stale selector, page navigation, enterprise policy, or page script interference |
|
|
56
57
|
| `frame_id` action fails | frame was replaced or is not accessible; inspect frames again |
|
|
57
58
|
| resource-backed upload fails | resource unavailable/too large, input is not `type=file`, page replaced the input, or the site rejects the file |
|
|
@@ -76,14 +77,21 @@ machine-mcp service status
|
|
|
76
77
|
machine-mcp --verbose
|
|
77
78
|
```
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
|
|
80
|
+
For installation or upgrade, launch a pinned npm 12 CLI from an empty temporary directory. This avoids depending on the old npm version currently on `PATH` and prevents its `npx` bootstrap from validating unrelated nearby project metadata first. On Windows Command Prompt:
|
|
81
|
+
|
|
82
|
+
```bat
|
|
83
|
+
set "MBM_INSTALL_DIR=%TEMP%\machine-bridge-mcp-install-%RANDOM%-%RANDOM%"
|
|
84
|
+
mkdir "%MBM_INSTALL_DIR%"
|
|
85
|
+
pushd "%MBM_INSTALL_DIR%"
|
|
86
|
+
npx --yes npm@12.0.1 install --global npm@12.0.1
|
|
87
|
+
npx --yes npm@12.0.1 install --global --omit=optional --allow-scripts=esbuild,workerd,sharp,fsevents machine-bridge-mcp@latest
|
|
88
|
+
popd
|
|
89
|
+
rmdir /s /q "%MBM_INSTALL_DIR%"
|
|
90
|
+
npm --version
|
|
83
91
|
machine-mcp --verbose
|
|
84
92
|
```
|
|
85
93
|
|
|
86
|
-
Keep `--omit=optional` in the install command. Without it npm may resolve optional `fsevents` and warn that its install script was not included in `allowScripts`; Machine Bridge does not require that development-time watcher at runtime.
|
|
94
|
+
`Unknown cli config "--allow-scripts"` proves the package installation ran under npm 11 or older. `Invalid property "node"` or `Invalid property "devEngines.node"` means npm parsed a legacy `devEngines` object; inspect the npm debug log to identify its source rather than assuming it belongs to Machine Bridge. The published package declares both Node.js 26 and npm 12 in `engines`, and `machine-mcp doctor` checks both active versions. Keep `--omit=optional` in the install command. Without it npm may resolve optional `fsevents` and warn that its install script was not included in `allowScripts`; Machine Bridge does not require that development-time watcher at runtime.
|
|
87
95
|
|
|
88
96
|
## State-root safety and removal
|
|
89
97
|
|
|
@@ -93,7 +101,7 @@ Uninstall acquires a state-root `maintenance.lock` that blocks new profile/state
|
|
|
93
101
|
|
|
94
102
|
## Logs
|
|
95
103
|
|
|
96
|
-
Remote autostart definitions prefer a stable PATH alias that resolves to the currently running Node executable and persist a sanitized absolute-only service `PATH` containing the Node/CLI directories, the installer's absolute PATH entries, and platform defaults. This avoids versioned Homebrew-style paths becoming invalid after upgrades and prevents launchd/systemd from falling back to a minimal system-only PATH. Re-run `machine-mcp service install` after changing Node installation families or PATH layout. A service-style `--daemon-only` start that finds the same workspace daemon already running is an idempotent no-op: it exits successfully without repeating warnings or readiness output; explicit policy/secret/change requests still report that changes were not applied. Autostart logs are stored under the state root in `logs/daemon.out.log` and `logs/daemon.err.log`. Files are owner-only where supported and tail-trimmed before daemon startup. On a logging-schema upgrade, bounded prior content is moved into `daemon.out.legacy.log` and `daemon.err.legacy.log`; use the active filenames when diagnosing current behavior.
|
|
104
|
+
Windows Scheduled Task command lines use CRT-compatible quoting, including trailing backslashes and drive-root paths. Remote autostart definitions prefer a stable PATH alias that resolves to the currently running Node executable and persist a sanitized absolute-only service `PATH` containing the Node/CLI directories, the installer's absolute PATH entries, and platform defaults. This avoids versioned Homebrew-style paths becoming invalid after upgrades and prevents launchd/systemd from falling back to a minimal system-only PATH. Re-run `machine-mcp service install` after changing Node installation families or PATH layout. A service-style `--daemon-only` start that finds the same workspace daemon already running is an idempotent no-op: it exits successfully without repeating warnings or readiness output; explicit policy/secret/change requests still report that changes were not applied. Autostart logs are stored under the state root in `logs/daemon.out.log` and `logs/daemon.err.log`. Files are owner-only where supported and tail-trimmed before daemon startup. On a logging-schema upgrade, bounded prior content is moved into `daemon.out.legacy.log` and `daemon.err.legacy.log`; use the active filenames when diagnosing current behavior.
|
|
97
105
|
|
|
98
106
|
Logging is level-based:
|
|
99
107
|
|
|
@@ -192,7 +200,7 @@ Defense-in-depth limits include:
|
|
|
192
200
|
- managed-job timeout: 1–3,600 seconds per step;
|
|
193
201
|
- managed-job output: 64 KiB per stream and 256 KiB total captured across one job;
|
|
194
202
|
- registered resources: 64, 1 MiB each, 8 MiB referenced per job;
|
|
195
|
-
- browser source: 4 MiB; browser WebSocket messages: 8 MiB; pending browser requests: 32 per runtime;
|
|
203
|
+
- browser source: 4 MiB aggregate across at most 64 accessible frames; semantic inspection: 1,000 elements aggregate, 100,000 scanned nodes, 10,000 reusable refs, and 2 MiB bounded page-text search per frame; browser WebSocket messages: 8 MiB; pending browser requests: 32 per runtime;
|
|
196
204
|
- browser forms: 200 fields, 128 KiB per text value, and 4 MiB aggregate text; upload: eight resources and 5 MiB total;
|
|
197
205
|
- application Accessibility inspection: 500 elements and depth 12; action text: 4,000 characters;
|
|
198
206
|
- job-scoped temporary files: 16 files, 512 KiB total content.
|
package/docs/TESTING.md
CHANGED
|
@@ -48,11 +48,11 @@ The suite includes:
|
|
|
48
48
|
- shared no-follow bounded-file reads for normal files, over-limit data, directories, and symbolic links;
|
|
49
49
|
- CLI parsing, policy profiles, and client configuration boundaries;
|
|
50
50
|
- live stdio MCP initialization with session instructions, capability resolution, discovery, calls, rich content, sessions, cancellation, managed-job acceptance, and a detached job/finally phase that survives stdio shutdown;
|
|
51
|
-
- live local Worker OAuth registration, consent, PKCE, token replay rejection, throttling, CORS, protocol negotiation, daemon-backed session bootstrap, dynamic tool advertisement, rich content, daemon replacement, cancellation, malformed daemon JSON/non-object rejection, duplicate hello rejection, and unknown-message closure.
|
|
51
|
+
- live local Worker OAuth registration, consent, URL-constructed `303` callbacks including the ChatGPT redirect URI and encoded state, PKCE, token replay rejection, throttling, CORS, protocol negotiation, daemon-backed session bootstrap, dynamic tool advertisement, rich content, daemon replacement, cancellation, malformed daemon JSON/non-object rejection, duplicate hello rejection, and unknown-message closure.
|
|
52
52
|
|
|
53
53
|
## Opt-in live desktop and browser validation
|
|
54
54
|
|
|
55
|
-
The normal suite uses deterministic mocks for macOS Accessibility and an authenticated in-process extension peer for browser routing. Before a release that changes local UI automation, run the macOS live smoke test on a machine where the invoking Node/terminal process has Accessibility permission:
|
|
55
|
+
The normal suite uses deterministic mocks for macOS Accessibility and an authenticated in-process extension peer for browser routing. Browser contract tests cover acknowledged protocol readiness, provisional pairing commit/rollback boundaries, strict extension IDs and matching loopback ports, stale-extension rejection, compatible replacement without premature displacement, clean rejection of in-flight direct and proxied requests, keepalive handling, trusted-input replay prevention after partial dispatch, focus-safe screenshots, aggregate 64-frame/source/element budgets, bounded hostile DOM/text processing, contenteditable-secret suppression, partial-form failure reporting, stable refs, combined waits, and actionability failures. Before a release that changes local UI automation, run the macOS live smoke test on a machine where the invoking Node/terminal process has Accessibility permission:
|
|
56
56
|
|
|
57
57
|
```sh
|
|
58
58
|
npm run app-automation:live-test
|
|
@@ -60,7 +60,7 @@ npm run app-automation:live-test
|
|
|
60
60
|
|
|
61
61
|
It opens Calculator, activates it through the fixed JXA helper, verifies structured JSON output, inspects main-window Accessibility controls with menu recursion disabled, clicks the `One` control, and quits the application. It is intentionally excluded from CI because macOS TCC permission and a graphical login session are host state.
|
|
62
62
|
|
|
63
|
-
For
|
|
63
|
+
For deterministic release validation, perform an isolated-profile smoke test with the packaged unpacked extension; a Playwright persistent Chromium context is acceptable only as that isolated harness. When the requirement is specifically to prove control of the user's ordinary browser, the user must load the same unpacked directory into that known daily Chromium profile; status can verify the extension version/protocol and that Machine Bridge did not launch a browser, but cannot infer profile identity. Then use a localhost no-store fixture in a newly created tab. Do not enumerate, read, or mutate unrelated existing tabs. In both modes, inspect and reuse refs, exercise waits/forms/trusted input/open Shadow DOM/screenshots, verify final live DOM, and close the fixture tab.
|
|
64
64
|
|
|
65
65
|
## Additional release checks
|
|
66
66
|
|
|
@@ -97,7 +97,7 @@ Run `npm run privacy:check` before committing and before packaging. Run and revi
|
|
|
97
97
|
|
|
98
98
|
## Package manifest
|
|
99
99
|
|
|
100
|
-
`npm run package:test` executes a real silent `npm pack --dry-run --json`, requires clean parseable JSON, rejects sensitive local artifacts and credential-like file classes, validates every packaged mode as `0644` or `0755`, and verifies that privacy/engineering guidance, runtime/relay/secure-file/lock/service/browser/app modules, all package-script helpers, the packaged browser extension, contribution discipline, and privacy/release-impact checkers are present. `npm run install:test`
|
|
100
|
+
`npm run package:test` executes a real silent `npm pack --dry-run --json`, requires clean parseable JSON, rejects sensitive local artifacts and credential-like file classes, validates every packaged mode as `0644` or `0755`, and verifies that privacy/engineering guidance, runtime/relay/secure-file/lock/service/browser/app modules, all package-script helpers, the packaged browser extension, contribution discipline, and privacy/release-impact checkers are present. `npm run install:test` requires npm 12, installs the real tarball from a package-free directory into an isolated global prefix with the documented options, verifies the packaged npm engine requirement, rejects blocked-script warnings, confirms optional `fsevents` is absent, and runs the installed CLI. The test runs on Linux, macOS, and Windows CI.
|
|
101
101
|
|
|
102
102
|
The stdio integration test also sends an oversized line, verifies bounded rejection, and confirms that the next valid request is still processed.
|
|
103
103
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "machine-bridge-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Cross-client MCP bridge for local agent context, structured browser and application automation, files, Git, processes, resources, and durable jobs over stdio or OAuth relay.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": ">=26.0.0"
|
|
8
|
+
"node": ">=26.0.0",
|
|
9
|
+
"npm": ">=12.0.0"
|
|
9
10
|
},
|
|
10
11
|
"bin": {
|
|
11
12
|
"machine-bridge-mcp": "bin/machine-mcp.mjs",
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"worker:types": "wrangler types src/worker/worker-configuration.d.ts",
|
|
43
44
|
"typecheck": "npm run worker:types && tsc -p tsconfig.json --noEmit",
|
|
44
45
|
"syntax": "node scripts/syntax-check.mjs",
|
|
45
|
-
"check": "npm run privacy:check && npm run privacy:test && npm run release-impact:check && npm run release-impact:test && npm run release-state:test && npm run release-ci:test && npm run network-retry:test && npm run relay:test && npm run secure-file:test && npm run architecture:test && npm run typecheck && npm run syntax && npm run process-lock:test && npm run service-lifecycle:test && npm run catalog:test && npm run agent-context:test && npm run browser-bridge:test && npm run app-automation:test && npm run self-test && npm run atomic-fs:test && npm run package:test && npm run ssh-key:test && npm run full-access:test && npm run managed-jobs:test && npm run stdio:integration-test && npm run worker:integration-test",
|
|
46
|
+
"check": "npm run privacy:check && npm run privacy:test && npm run release-impact:check && npm run release-impact:test && npm run release-state:test && npm run release-ci:test && npm run network-retry:test && npm run relay:test && npm run secure-file:test && npm run architecture:test && npm run typecheck && npm run syntax && npm run process-lock:test && npm run service-lifecycle:test && npm run service-platform:test && npm run catalog:test && npm run agent-context:test && npm run browser-command:test && npm run browser-devtools-input:test && npm run browser-service-worker:test && npm run browser-page-automation:test && npm run browser-bridge:test && npm run app-automation:test && npm run self-test && npm run atomic-fs:test && npm run package:test && npm run ssh-key:test && npm run full-access:test && npm run managed-jobs:test && npm run stdio:integration-test && npm run worker:integration-test",
|
|
46
47
|
"worker:dry-run": "wrangler deploy --dry-run",
|
|
47
48
|
"worker:integration-test": "node tests/worker-integration-test.mjs",
|
|
48
49
|
"release:check": "node scripts/github-release.mjs --check",
|
|
@@ -72,7 +73,12 @@
|
|
|
72
73
|
"app-automation:test": "node tests/app-automation-test.mjs",
|
|
73
74
|
"process-lock:test": "node tests/process-lock-test.mjs",
|
|
74
75
|
"service-lifecycle:test": "node tests/service-lifecycle-test.mjs",
|
|
75
|
-
"app-automation:live-test": "node tests/app-automation-test.mjs --live-macos"
|
|
76
|
+
"app-automation:live-test": "node tests/app-automation-test.mjs --live-macos",
|
|
77
|
+
"browser-command:test": "node tests/browser-command-test.mjs",
|
|
78
|
+
"browser-devtools-input:test": "node tests/browser-devtools-input-test.mjs",
|
|
79
|
+
"browser-page-automation:test": "node tests/browser-page-automation-test.mjs",
|
|
80
|
+
"browser-service-worker:test": "node tests/browser-service-worker-test.mjs",
|
|
81
|
+
"service-platform:test": "node tests/service-platform-test.mjs"
|
|
76
82
|
},
|
|
77
83
|
"dependencies": {
|
|
78
84
|
"https-proxy-agent": "9.1.0",
|
|
@@ -825,7 +825,7 @@ function recommendTools(task, { commandsAvailable, commandRelevant, skillRelevan
|
|
|
825
825
|
const tools = ["agent_context"];
|
|
826
826
|
if (skillRelevant) tools.push("load_local_skill");
|
|
827
827
|
if (commandRelevant) tools.push("run_local_command");
|
|
828
|
-
if (/browser|chrome|edge|brave|网页|浏览器|表单|网站/.test(lower)) tools.push("browser_status", "browser_list_tabs", "browser_inspect_page", "browser_action", "browser_fill_form");
|
|
828
|
+
if (/browser|chrome|edge|brave|网页|浏览器|表单|网站/.test(lower)) tools.push("browser_status", "browser_list_tabs", "browser_manage_tabs", "browser_inspect_page", "browser_wait", "browser_action", "browser_fill_form");
|
|
829
829
|
if (/app|application|gui|window|应用|软件|窗口|界面/.test(lower)) tools.push("list_local_applications", "inspect_local_application", "operate_local_application");
|
|
830
830
|
if (/git|commit|branch|diff|仓库|提交|分支/.test(lower)) tools.push("git_status", "git_diff");
|
|
831
831
|
if (/test|build|lint|command|terminal|测试|构建|命令|终端/.test(lower)) tools.push(commandsAvailable ? "run_local_command" : "run_process");
|