chrome-bridge-mcp 1.10.0 → 1.10.1
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 +2 -2
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/server/protocol.js +1 -1
- package/server/tools.js +24 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Chrome Bridge
|
|
2
2
|
|
|
3
|
-
       [](https://chromewebstore.google.com/detail/chrome-bridge-for-claude/bioknpaeahidbelaljjohjofiloeodmb)
|
|
4
4
|
|
|
5
5
|
**Chrome Bridge is an MCP server that connects Claude Code to your real, logged-in Chrome browser — measured 2.75× fewer turns and 2.28× lower cost than the official "Claude in Chrome" extension on a form-filling task, with ~3× the toolset and no paid plan.**
|
|
6
6
|
|
|
@@ -63,7 +63,7 @@ Claude Code calls `navigate` (returning clickable element refs), `accessibility_
|
|
|
63
63
|
|
|
64
64
|
## Token-Efficient Design
|
|
65
65
|
|
|
66
|
-
- **Opt-in Surface**: 31 core tools cost ≈7.
|
|
66
|
+
- **Opt-in Surface**: 31 core tools cost ≈7.6k tokens of `tools/list`, all 60 cost ≈14.6k; specialized groups (audits, visual, network, storage, dom, files) are opt-in via `--caps`. That core figure was ≈3.8k in 1.8.0 and roughly doubled in 1.10.0: MCP annotations on every tool, rewritten descriptions, and a documented `.describe()` on all 254 parameters (coverage went from 35% to 100%). The trade is deliberate and it is not free — on the form benchmark it adds ≈8% to the cache-read tokens per turn — but the measured advantage was never prefix size, it was round trips: 2.75× fewer turns. Playwright MCP's 23 core tools measured ≈4.6k in July 2026, so on prefix size alone it is the leaner one. Measure ours with `npm run measure`.
|
|
67
67
|
- **Act-from-Result**: Tools attach a capped preview of interactive elements with short refs. Actions only report a `page_changed` delta when the URL or title actually changes.
|
|
68
68
|
- **Optimized Media**: Screenshots are downscaled to ≤1568px. Full-page captures are sliced into readable segments.
|
|
69
69
|
- **Zero-Token Escape Hatches**: The [CLI](#cli) skips MCP schemas entirely, and recorded flows [replay](#launch-mode-headless--ci) without any model in the loop.
|
package/extension/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Chrome Bridge for Claude Code",
|
|
4
|
-
"version": "1.10.
|
|
4
|
+
"version": "1.10.1",
|
|
5
5
|
"description": "Bridge your browser to Claude Code: 60 token-efficient web-dev automation tools over a local WebSocket. ChromeOS included.",
|
|
6
6
|
"homepage_url": "https://github.com/frsorrentino/chrome-bridge",
|
|
7
7
|
"minimum_chrome_version": "135",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-bridge-mcp",
|
|
3
3
|
"mcpName": "io.github.frsorrentino/chrome-bridge",
|
|
4
|
-
"version": "1.10.
|
|
4
|
+
"version": "1.10.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "MCP server with 60 tools for browser automation via Chrome extension. Works on ChromeOS/Crostini.",
|
|
7
7
|
"main": "server/index.js",
|
package/server/protocol.js
CHANGED
package/server/tools.js
CHANGED
|
@@ -586,7 +586,11 @@ export function registerTools(server, wsManager, caps = 'all') {
|
|
|
586
586
|
// --- type_text ---
|
|
587
587
|
server.tool(
|
|
588
588
|
'type_text',
|
|
589
|
-
'
|
|
589
|
+
'Put text into an input, textarea or contenteditable, by CSS selector or by a ref from get_interactives. '
|
|
590
|
+
+ 'Replaces the whole value rather than appending, and assigns through the native setter so React and '
|
|
591
|
+
+ 'Vue controlled inputs register the change, then fires input and change. mode=keys instead emits '
|
|
592
|
+
+ 'keydown/input/keyup per character, which is what autocomplete and masked fields need — slower, so '
|
|
593
|
+
+ 'reach for it only when mode=set leaves the field empty or the dropdown never opens.',
|
|
590
594
|
{
|
|
591
595
|
selector: z.string().optional().describe('CSS selector; ">>>" pierces shadow DOM. Ignored when ref is given'),
|
|
592
596
|
ref: z.string().optional().describe('From get_interactives, e.g. "n3"'),
|
|
@@ -859,7 +863,11 @@ export function registerTools(server, wsManager, caps = 'all') {
|
|
|
859
863
|
// --- wait_for ---
|
|
860
864
|
server.tool(
|
|
861
865
|
'wait_for',
|
|
862
|
-
'
|
|
866
|
+
'Block until a condition holds: element (selector in the DOM), function (JS expression turns truthy; needs '
|
|
867
|
+
+ 'the "Allow user scripts" toggle), navigation (mode=spa for client-side route changes), network_idle. '
|
|
868
|
+
+ 'Polls until timeout — 10s for element and function, 15s for navigation and network_idle — then '
|
|
869
|
+
+ '**returns `found: false` with a reason instead of raising**, so a caller that ignores the result '
|
|
870
|
+
+ 'silently proceeds as if the wait had succeeded. Read-only: waiting changes nothing on the page.',
|
|
863
871
|
{
|
|
864
872
|
condition: z.enum(['element', 'function', 'navigation', 'network_idle']).describe('function needs expression; element needs selector'),
|
|
865
873
|
selector: z.string().optional().describe('condition=element'),
|
|
@@ -983,7 +991,11 @@ export function registerTools(server, wsManager, caps = 'all') {
|
|
|
983
991
|
// --- viewport_resize ---
|
|
984
992
|
server.tool(
|
|
985
993
|
'viewport_resize',
|
|
986
|
-
'Resize Chrome window to preset (mobile
|
|
994
|
+
'Resize the Chrome **window** to a preset (mobile 375x812, tablet 768x1024, desktop 1440x900) or to explicit '
|
|
995
|
+
+ 'dimensions. The rendered viewport ends up smaller than what you ask for, by the height of the browser '
|
|
996
|
+
+ 'chrome — measure it with execute_js if the exact number matters. width and height each override the '
|
|
997
|
+
+ 'corresponding half of the preset, so preset plus width gives a custom width at the preset height. '
|
|
998
|
+
+ 'A maximized window on ChromeOS ignores the request.',
|
|
987
999
|
{
|
|
988
1000
|
preset: z.enum(['mobile', 'tablet', 'desktop']).optional().describe('375x812, 768x1024, 1440x900'),
|
|
989
1001
|
width: z.number().optional().describe('Overrides preset'),
|
|
@@ -1072,7 +1084,10 @@ export function registerTools(server, wsManager, caps = 'all') {
|
|
|
1072
1084
|
// --- highlight_elements ---
|
|
1073
1085
|
server.tool(
|
|
1074
1086
|
'highlight_elements',
|
|
1075
|
-
'
|
|
1087
|
+
'Outline every element matching a selector with a coloured overlay, to see on a screenshot what a selector '
|
|
1088
|
+
+ 'actually caught. Each call clears the overlays left by the previous one instead of stacking them, and '
|
|
1089
|
+
+ 'remove=true clears without adding. The overlays are injected DOM nodes: a reload or a navigation drops '
|
|
1090
|
+
+ 'them, and they sit above the page without altering its layout or its own styles.',
|
|
1076
1091
|
{
|
|
1077
1092
|
selector: z.string().optional().describe('CSS selector; ">>>" pierces shadow DOM. Every match is outlined'),
|
|
1078
1093
|
color: z.string().optional().default('rgba(255,0,0,0.3)').describe('Any CSS color for the overlay label'),
|
|
@@ -1740,7 +1755,11 @@ export function registerTools(server, wsManager, caps = 'all') {
|
|
|
1740
1755
|
// --- session_fixture ---
|
|
1741
1756
|
server.tool(
|
|
1742
1757
|
'session_fixture',
|
|
1743
|
-
'
|
|
1758
|
+
'Snapshot localStorage, sessionStorage and cookies of the current origin into a named fixture on the server, '
|
|
1759
|
+
+ 'restore one, or list what has been saved. A logged-in state is the usual reason. save overwrites a '
|
|
1760
|
+
+ 'fixture of the same name without asking; restore writes entries on top of what is already there '
|
|
1761
|
+
+ 'rather than clearing first, and refuses outright when the tab sits on a different origin than the '
|
|
1762
|
+
+ 'one recorded — cookies would otherwise attach to the wrong site. name is required except for list.',
|
|
1744
1763
|
{
|
|
1745
1764
|
action: z.enum(['save', 'restore', 'list']).describe('save snapshots the current origin; restore writes it back'),
|
|
1746
1765
|
name: z.string().optional().describe('Required for save/restore'),
|