barebrowse 0.4.7 → 0.5.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/CHANGELOG.md +42 -0
- package/README.md +4 -3
- package/barebrowse.context.md +34 -6
- package/mcp-server.js +38 -1
- package/package.json +4 -1
- package/src/bareagent.js +80 -0
- package/src/index.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
bareagent tool parity + test fix.
|
|
6
|
+
|
|
7
|
+
### bareagent adapter
|
|
8
|
+
- Added `hover`, `tabs`, `switchTab`, `pdf` tools (was 13 + assess, now 17 + assess)
|
|
9
|
+
- bareagent now exposes the full connect() API surface
|
|
10
|
+
|
|
11
|
+
### Tests
|
|
12
|
+
- Fixed 2 snapshot URL prefix assertions (`# url` → `url: url`) to match 0.4.7 format change
|
|
13
|
+
- 69/69 passing
|
|
14
|
+
|
|
15
|
+
### Version
|
|
16
|
+
- Package version: 0.5.1
|
|
17
|
+
- MCP server version string updated
|
|
18
|
+
|
|
19
|
+
## 0.5.0
|
|
20
|
+
|
|
21
|
+
Privacy assessment via wearehere integration.
|
|
22
|
+
|
|
23
|
+
### New: `assess` tool
|
|
24
|
+
- Scans any URL for privacy risks: cookies, trackers, fingerprinting, dark patterns, data brokers, form surveillance, link tracking, and toxic terms of service
|
|
25
|
+
- Returns compact JSON: score (0-100), risk level (low/moderate/high/critical), per-category breakdown (10 categories with score/max/summary), concerns list, and recommendation
|
|
26
|
+
- Available in MCP server (13th tool) and bareagent adapter (14th tool)
|
|
27
|
+
- Conditionally loaded: only available when `wearehere` npm package is installed
|
|
28
|
+
- Uses a dedicated `connect()` page per scan (isolated from the session page)
|
|
29
|
+
|
|
30
|
+
### Integration
|
|
31
|
+
- `wearehere` added as optional dependency in package.json
|
|
32
|
+
- MCP server: dynamic `import('wearehere')` with try/catch fallback
|
|
33
|
+
- bareagent adapter: same dynamic import pattern
|
|
34
|
+
- Zero impact when wearehere is not installed — all existing tools work unchanged
|
|
35
|
+
|
|
36
|
+
### Version
|
|
37
|
+
- Package version: 0.5.0
|
|
38
|
+
- MCP server version string updated
|
|
39
|
+
|
|
40
|
+
## 0.4.8
|
|
41
|
+
|
|
42
|
+
- Fix: `browse()` one-shot also had `#` prefix (missed in 0.4.7)
|
|
43
|
+
- MCP server version string updated
|
|
44
|
+
|
|
3
45
|
## 0.4.7
|
|
4
46
|
|
|
5
47
|
Snapshot URL prefix format changed from `# <url>` to `url: <url>`.
|
package/README.md
CHANGED
|
@@ -87,11 +87,11 @@ Or manually add to your config (`claude_desktop_config.json`, `.cursor/mcp.json`
|
|
|
87
87
|
}
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
12 tools: `browse`, `goto`, `snapshot`, `click`, `type`, `press`, `scroll`, `back`, `forward`, `drag`, `upload`, `pdf`. Session runs in hybrid mode with automatic cookie injection.
|
|
90
|
+
12 tools: `browse`, `goto`, `snapshot`, `click`, `type`, `press`, `scroll`, `back`, `forward`, `drag`, `upload`, `pdf`. Plus `assess` (privacy scan) if [wearehere](https://github.com/hamr0/wearehere) is installed. Session runs in hybrid mode with automatic cookie injection.
|
|
91
91
|
|
|
92
92
|
### 3. Library -- for agentic automation
|
|
93
93
|
|
|
94
|
-
Import barebrowse in your agent code. One-shot reads, interactive sessions, full observe-think-act loops. Works with any LLM orchestration library. Ships with a ready-made adapter for [bareagent](https://www.npmjs.com/package/bare-agent) (
|
|
94
|
+
Import barebrowse in your agent code. One-shot reads, interactive sessions, full observe-think-act loops. Works with any LLM orchestration library. Ships with a ready-made adapter for [bareagent](https://www.npmjs.com/package/bare-agent) (17 tools, auto-snapshot after every action).
|
|
95
95
|
|
|
96
96
|
For code examples, API reference, and wiring instructions, see **[barebrowse.context.md](barebrowse.context.md)** -- the full integration guide.
|
|
97
97
|
|
|
@@ -139,6 +139,7 @@ Everything the agent can do through barebrowse:
|
|
|
139
139
|
| **Upload** | Set files on a file input element |
|
|
140
140
|
| **Screenshot** | Page capture as base64 PNG/JPEG/WebP |
|
|
141
141
|
| **PDF** | Export page as PDF |
|
|
142
|
+
| **Assess** | Privacy scan: score (0-100), risk level, 10-category breakdown. Requires `npm install wearehere`. |
|
|
142
143
|
| **Tabs** | List open tabs, switch between them |
|
|
143
144
|
| **Wait for content** | Poll for text or CSS selector to appear on page |
|
|
144
145
|
| **Wait for navigation** | SPA-aware: works for full page loads and pushState |
|
|
@@ -174,7 +175,7 @@ URL -> find/launch browser (chromium.js)
|
|
|
174
175
|
-> agent-ready snapshot with [ref=N] markers
|
|
175
176
|
```
|
|
176
177
|
|
|
177
|
-
11 modules, 2,400 lines, zero dependencies.
|
|
178
|
+
11 modules, 2,400 lines, zero required dependencies.
|
|
178
179
|
|
|
179
180
|
## Requirements
|
|
180
181
|
|
package/barebrowse.context.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# barebrowse -- Integration Guide
|
|
2
2
|
|
|
3
3
|
> For AI assistants and developers wiring barebrowse into a project.
|
|
4
|
-
> v0.
|
|
4
|
+
> v0.5.1 | Node.js >= 22 | 0 required deps | MIT
|
|
5
5
|
|
|
6
6
|
## What this is
|
|
7
7
|
|
|
@@ -90,7 +90,7 @@ const snapshot = await browse('https://example.com', {
|
|
|
90
90
|
The snapshot is a YAML-like ARIA tree. First line is the page URL, second is pruning stats, then the tree:
|
|
91
91
|
|
|
92
92
|
```
|
|
93
|
-
|
|
93
|
+
url: https://example.com/
|
|
94
94
|
# 379 chars → 45 chars (88% pruned)
|
|
95
95
|
- heading "Example Domain" [level=1] [ref=3]
|
|
96
96
|
- link "More information..." [ref=8]
|
|
@@ -184,10 +184,10 @@ try {
|
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
`createBrowseTools(opts)` returns:
|
|
187
|
-
- `tools` -- array of bareagent-compatible tool objects (browse, goto, snapshot, click, type, press, scroll, select, back, forward, drag, upload, screenshot)
|
|
187
|
+
- `tools` -- array of bareagent-compatible tool objects (browse, goto, snapshot, click, type, press, scroll, select, hover, back, forward, drag, upload, tabs, switchTab, pdf, screenshot, plus assess if wearehere installed)
|
|
188
188
|
- `close()` -- cleanup function, call when done
|
|
189
189
|
|
|
190
|
-
Action tools (click, type, press, scroll, goto) auto-return a fresh snapshot so the LLM always sees the result. 300ms settle delay after actions for DOM updates.
|
|
190
|
+
Action tools (click, type, press, scroll, hover, goto, back, forward, drag, upload, select, switchTab) auto-return a fresh snapshot so the LLM always sees the result. 300ms settle delay after actions for DOM updates.
|
|
191
191
|
|
|
192
192
|
## CLI session mode
|
|
193
193
|
|
|
@@ -233,7 +233,7 @@ barebrowse ships an MCP server for direct use with Claude Desktop, Cursor, or an
|
|
|
233
233
|
}
|
|
234
234
|
```
|
|
235
235
|
|
|
236
|
-
12 tools
|
|
236
|
+
12 core tools: `browse` (one-shot), `goto`, `snapshot`, `click`, `type`, `press`, `scroll`, `back`, `forward`, `drag`, `upload`, `pdf`. Plus `assess` (privacy scan) if `wearehere` is installed (`npm install wearehere`).
|
|
237
237
|
|
|
238
238
|
Action tools return `'ok'` -- the agent calls `snapshot` explicitly to observe. This avoids double-token output since MCP tool calls are cheap to chain.
|
|
239
239
|
|
|
@@ -270,9 +270,37 @@ URL -> chromium.js (find/launch browser, permission flags)
|
|
|
270
270
|
| `src/interact.js` | ~170 | Click, type, press, scroll, hover, select |
|
|
271
271
|
| `src/consent.js` | 200 | Auto-dismiss cookie consent dialogs across languages |
|
|
272
272
|
| `src/stealth.js` | ~40 | Navigator patches for headless anti-detection |
|
|
273
|
-
| `src/bareagent.js` | ~
|
|
273
|
+
| `src/bareagent.js` | ~250 | Tool adapter for bareagent Loop |
|
|
274
274
|
| `mcp-server.js` | ~170 | MCP server (JSON-RPC over stdio) |
|
|
275
275
|
|
|
276
|
+
## Privacy assessment (optional)
|
|
277
|
+
|
|
278
|
+
Install `wearehere` to add an `assess` tool to both the MCP server and bareagent adapter:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
npm install wearehere
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
The `assess` tool navigates to a URL in an isolated browser page, scans for 10 privacy categories (cookies, trackers, fingerprinting, dark patterns, data brokers, form surveillance, link tracking, toxic terms, stored data, network traffic), and returns a compact JSON assessment:
|
|
285
|
+
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"site": "example.com",
|
|
289
|
+
"score": 62,
|
|
290
|
+
"risk": "high",
|
|
291
|
+
"recommendation": "Significant privacy risks. Avoid sharing personal info here.",
|
|
292
|
+
"concerns": ["Heavy hidden tracking", "Aggressive device fingerprinting"],
|
|
293
|
+
"categories": {
|
|
294
|
+
"cookies": { "score": 10, "max": 15, "summary": "7 third-party cookies" },
|
|
295
|
+
"trackers": { "score": 20, "max": 20, "summary": "14 hidden elements" },
|
|
296
|
+
"profiling": { "score": 10, "max": 20, "summary": "Canvas + WebGL" },
|
|
297
|
+
"terms": { "score": 15, "max": 15, "summary": "Binding arbitration" }
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Useful for agent threshold decisions: "skip sites above score 40", "warn if terms score >= 10", etc. When wearehere is not installed, the tool simply doesn't appear — no errors, no impact.
|
|
303
|
+
|
|
276
304
|
## Gotchas
|
|
277
305
|
|
|
278
306
|
1. **Refs are ephemeral.** Every `snapshot()` call generates new refs. Always snapshot before interacting. Never cache refs across snapshots.
|
package/mcp-server.js
CHANGED
|
@@ -13,6 +13,13 @@ import { browse, connect } from './src/index.js';
|
|
|
13
13
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
14
14
|
import { join } from 'node:path';
|
|
15
15
|
|
|
16
|
+
// Optional: privacy assessment via wearehere
|
|
17
|
+
let assessFn = null;
|
|
18
|
+
try {
|
|
19
|
+
({ assess: assessFn } = await import('wearehere'));
|
|
20
|
+
} catch {}
|
|
21
|
+
|
|
22
|
+
|
|
16
23
|
const MAX_CHARS_DEFAULT = 30000;
|
|
17
24
|
const OUTPUT_DIR = join(process.cwd(), '.barebrowse');
|
|
18
25
|
|
|
@@ -158,6 +165,23 @@ const TOOLS = [
|
|
|
158
165
|
},
|
|
159
166
|
];
|
|
160
167
|
|
|
168
|
+
// Add assess tool if wearehere is installed
|
|
169
|
+
if (assessFn) {
|
|
170
|
+
TOOLS.push({
|
|
171
|
+
name: 'assess',
|
|
172
|
+
description: 'Privacy assessment of any website. Navigates to the URL, scans for cookies, trackers, fingerprinting, dark patterns, data brokers, form surveillance, link tracking, and toxic terms. Returns a compact JSON with risk score (0-100), per-category breakdown, and recommendation. Powered by wearehere.',
|
|
173
|
+
inputSchema: {
|
|
174
|
+
type: 'object',
|
|
175
|
+
properties: {
|
|
176
|
+
url: { type: 'string', description: 'URL to assess (e.g. "https://example.com")' },
|
|
177
|
+
timeout: { type: 'number', description: 'Navigation timeout in ms (default: 30000)' },
|
|
178
|
+
settle: { type: 'number', description: 'Time to wait for trackers to load after page load, in ms (default: 3000)' },
|
|
179
|
+
},
|
|
180
|
+
required: ['url'],
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
161
185
|
async function handleToolCall(name, args) {
|
|
162
186
|
switch (name) {
|
|
163
187
|
case 'browse': {
|
|
@@ -229,6 +253,19 @@ async function handleToolCall(name, args) {
|
|
|
229
253
|
const page = await getPage();
|
|
230
254
|
return await page.pdf({ landscape: args.landscape });
|
|
231
255
|
}
|
|
256
|
+
case 'assess': {
|
|
257
|
+
if (!assessFn) throw new Error('wearehere is not installed. Run: npm install wearehere');
|
|
258
|
+
const page = await connect({ mode: 'hybrid' });
|
|
259
|
+
try {
|
|
260
|
+
const result = await assessFn(page, args.url, {
|
|
261
|
+
timeout: args.timeout,
|
|
262
|
+
settle: args.settle,
|
|
263
|
+
});
|
|
264
|
+
return JSON.stringify(result, null, 2);
|
|
265
|
+
} finally {
|
|
266
|
+
await page.close().catch(() => {});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
232
269
|
default:
|
|
233
270
|
throw new Error(`Unknown tool: ${name}`);
|
|
234
271
|
}
|
|
@@ -249,7 +286,7 @@ async function handleMessage(msg) {
|
|
|
249
286
|
return jsonrpcResponse(id, {
|
|
250
287
|
protocolVersion: '2024-11-05',
|
|
251
288
|
capabilities: { tools: {} },
|
|
252
|
-
serverInfo: { name: 'barebrowse', version: '0.
|
|
289
|
+
serverInfo: { name: 'barebrowse', version: '0.5.1' },
|
|
253
290
|
});
|
|
254
291
|
}
|
|
255
292
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "barebrowse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Authenticated web browsing for autonomous agents via CDP. URL in, pruned ARIA snapshot out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -28,5 +28,8 @@
|
|
|
28
28
|
"mcp",
|
|
29
29
|
"headless"
|
|
30
30
|
],
|
|
31
|
+
"optionalDependencies": {
|
|
32
|
+
"wearehere": "^1.0.0"
|
|
33
|
+
},
|
|
31
34
|
"license": "MIT"
|
|
32
35
|
}
|
package/src/bareagent.js
CHANGED
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
|
|
14
14
|
import { browse, connect } from './index.js';
|
|
15
15
|
|
|
16
|
+
// Optional: privacy assessment via wearehere
|
|
17
|
+
let assessFn = null;
|
|
18
|
+
try {
|
|
19
|
+
({ assess: assessFn } = await import('wearehere'));
|
|
20
|
+
} catch {}
|
|
21
|
+
|
|
16
22
|
const SETTLE_MS = 300;
|
|
17
23
|
const settle = () => new Promise((r) => setTimeout(r, SETTLE_MS));
|
|
18
24
|
|
|
@@ -133,6 +139,18 @@ export function createBrowseTools(opts = {}) {
|
|
|
133
139
|
},
|
|
134
140
|
execute: async ({ ref, value }) => actionAndSnapshot((page) => page.select(ref, value)),
|
|
135
141
|
},
|
|
142
|
+
{
|
|
143
|
+
name: 'hover',
|
|
144
|
+
description: 'Hover over an element by its ref. Returns the updated snapshot.',
|
|
145
|
+
parameters: {
|
|
146
|
+
type: 'object',
|
|
147
|
+
properties: {
|
|
148
|
+
ref: { type: 'string', description: 'Element ref from snapshot' },
|
|
149
|
+
},
|
|
150
|
+
required: ['ref'],
|
|
151
|
+
},
|
|
152
|
+
execute: async ({ ref }) => actionAndSnapshot((page) => page.hover(ref)),
|
|
153
|
+
},
|
|
136
154
|
{
|
|
137
155
|
name: 'back',
|
|
138
156
|
description: 'Go back in browser history. Returns the updated snapshot.',
|
|
@@ -171,6 +189,42 @@ export function createBrowseTools(opts = {}) {
|
|
|
171
189
|
},
|
|
172
190
|
execute: async ({ ref, files }) => actionAndSnapshot((page) => page.upload(ref, files)),
|
|
173
191
|
},
|
|
192
|
+
{
|
|
193
|
+
name: 'tabs',
|
|
194
|
+
description: 'List all open tabs. Returns JSON array of { index, url, title }.',
|
|
195
|
+
parameters: { type: 'object', properties: {} },
|
|
196
|
+
execute: async () => {
|
|
197
|
+
const page = await getPage();
|
|
198
|
+
const tabList = await page.tabs();
|
|
199
|
+
return JSON.stringify(tabList, null, 2);
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'switchTab',
|
|
204
|
+
description: 'Switch to a tab by index. Returns the updated snapshot.',
|
|
205
|
+
parameters: {
|
|
206
|
+
type: 'object',
|
|
207
|
+
properties: {
|
|
208
|
+
index: { type: 'number', description: 'Tab index (from tabs tool output)' },
|
|
209
|
+
},
|
|
210
|
+
required: ['index'],
|
|
211
|
+
},
|
|
212
|
+
execute: async ({ index }) => actionAndSnapshot((page) => page.switchTab(index)),
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: 'pdf',
|
|
216
|
+
description: 'Export current page as PDF. Returns base64-encoded PDF data.',
|
|
217
|
+
parameters: {
|
|
218
|
+
type: 'object',
|
|
219
|
+
properties: {
|
|
220
|
+
landscape: { type: 'boolean', description: 'Landscape orientation (default: false)' },
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
execute: async ({ landscape } = {}) => {
|
|
224
|
+
const page = await getPage();
|
|
225
|
+
return await page.pdf({ landscape });
|
|
226
|
+
},
|
|
227
|
+
},
|
|
174
228
|
{
|
|
175
229
|
name: 'screenshot',
|
|
176
230
|
description: 'Take a screenshot of the current page. Returns base64-encoded image.',
|
|
@@ -187,6 +241,32 @@ export function createBrowseTools(opts = {}) {
|
|
|
187
241
|
},
|
|
188
242
|
];
|
|
189
243
|
|
|
244
|
+
// Add assess tool if wearehere is installed
|
|
245
|
+
if (assessFn) {
|
|
246
|
+
tools.push({
|
|
247
|
+
name: 'assess',
|
|
248
|
+
description: 'Privacy assessment of a website. Returns risk score (0-100), per-category breakdown, concerns, and recommendation.',
|
|
249
|
+
parameters: {
|
|
250
|
+
type: 'object',
|
|
251
|
+
properties: {
|
|
252
|
+
url: { type: 'string', description: 'URL to assess' },
|
|
253
|
+
timeout: { type: 'number', description: 'Navigation timeout in ms (default: 30000)' },
|
|
254
|
+
settle: { type: 'number', description: 'Time to wait for trackers to load, in ms (default: 3000)' },
|
|
255
|
+
},
|
|
256
|
+
required: ['url'],
|
|
257
|
+
},
|
|
258
|
+
execute: async ({ url, timeout, settle }) => {
|
|
259
|
+
const page = await connect(opts);
|
|
260
|
+
try {
|
|
261
|
+
const result = await assessFn(page, url, { timeout, settle });
|
|
262
|
+
return JSON.stringify(result, null, 2);
|
|
263
|
+
} finally {
|
|
264
|
+
await page.close().catch(() => {});
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
190
270
|
return {
|
|
191
271
|
tools,
|
|
192
272
|
async close() {
|
package/src/index.js
CHANGED
|
@@ -103,7 +103,7 @@ export async function browse(url, opts = {}) {
|
|
|
103
103
|
} else {
|
|
104
104
|
snapshot = raw;
|
|
105
105
|
}
|
|
106
|
-
const stats =
|
|
106
|
+
const stats = `url: ${url}\n${raw.length.toLocaleString()} chars → ${snapshot.length.toLocaleString()} chars (${Math.round((1 - snapshot.length / raw.length) * 100)}% pruned)`;
|
|
107
107
|
snapshot = stats + '\n' + snapshot;
|
|
108
108
|
|
|
109
109
|
// Step 7: Clean up
|