@agent360/browser-mcp 1.28.1 → 1.29.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 +161 -46
- package/bin/cli.js +99 -21
- package/extension/background.js +1309 -194
- package/extension/manifest.json +1 -1
- package/extension/offscreen.js +62 -5
- package/extension/popup.html +9 -4
- package/extension/popup.js +5 -5
- package/index.js +380 -109
- package/package.json +5 -5
- package/tools.js +16 -16
- package/vagt.js +3 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent360/browser-mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Browser MCP
|
|
3
|
+
"version": "1.29.1",
|
|
4
|
+
"description": "Browser MCP - give your AI agent a real, logged-in Chrome: test authenticated apps, read 2FA codes from Gmail, scrape behind logins, solve CAPTCHAs. 40 tools, multi-session, human-in-the-loop.",
|
|
5
5
|
"mcpName": "io.github.Agent360dk/browser-mcp",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "index.js",
|
|
@@ -64,11 +64,11 @@
|
|
|
64
64
|
"ws": "^8.18.0"
|
|
65
65
|
},
|
|
66
66
|
"overrides": {
|
|
67
|
-
"fast-uri": "^3.1.
|
|
68
|
-
"hono": "^4.
|
|
67
|
+
"fast-uri": "^3.1.7",
|
|
68
|
+
"hono": "^4.13.7",
|
|
69
69
|
"ip-address": "^10.3.1",
|
|
70
70
|
"@hono/node-server": "^1.19.15",
|
|
71
71
|
"body-parser": "^2.2.3",
|
|
72
|
-
"qs": "^6.
|
|
72
|
+
"qs": "^6.16.0"
|
|
73
73
|
}
|
|
74
74
|
}
|
package/tools.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent360 Browser MCP
|
|
2
|
+
* Agent360 Browser MCP - Tool Definitions
|
|
3
3
|
*
|
|
4
4
|
* Defines all MCP tools exposed to Claude Code.
|
|
5
5
|
*/
|
|
@@ -29,7 +29,7 @@ export const TOOLS = [
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
name: 'browser_extract_list',
|
|
32
|
-
description: 'Read EVERY row of a long or virtualised list by scrolling its container until no new rows appear. Use this instead of browser_get_page_content whenever a page shows a repeating list longer than the viewport
|
|
32
|
+
description: 'Read EVERY row of a long or virtualised list by scrolling its container until no new rows appear. Use this instead of browser_get_page_content whenever a page shows a repeating list longer than the viewport - mail lists (Outlook, Gmail), invoice/billing tables, search results, transaction histories. Those UIs keep only ~7 rows in the DOM at a time, so a single page read returns a sliver and looks complete. Pass the CSS selector of one repeating row (e.g. \'[role="option"]\', \'tr\', \'[role="listitem"]\'); the scrollable ancestor is found automatically. Returns deduplicated row text plus reached_end so you know whether you saw the whole list.',
|
|
33
33
|
inputSchema: {
|
|
34
34
|
type: 'object',
|
|
35
35
|
properties: {
|
|
@@ -55,7 +55,7 @@ export const TOOLS = [
|
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
name: 'browser_execute_script',
|
|
58
|
-
description: 'Execute JavaScript in the current page. IMPORTANT: the parameter is `code` (NOT `script`
|
|
58
|
+
description: 'Execute JavaScript in the current page. IMPORTANT: the parameter is `code` (NOT `script` - though that alias is accepted), and it must be an EXPRESSION, not statements: use an IIFE `(() => { ...; return x; })()`. Top-level `return` is a syntax error (the handler wraps code in parentheses).',
|
|
59
59
|
inputSchema: {
|
|
60
60
|
type: 'object',
|
|
61
61
|
properties: {
|
|
@@ -77,7 +77,7 @@ export const TOOLS = [
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
name: 'browser_right_click',
|
|
80
|
-
description: 'Right-click an element (trusted CDP mouse events) to open page-level context menus (web apps like OWA/Google Docs render their own). Note: Chrome\'s NATIVE context menu does not open via CDP
|
|
80
|
+
description: 'Right-click an element (trusted CDP mouse events) to open page-level context menus (web apps like OWA/Google Docs render their own). Note: Chrome\'s NATIVE context menu does not open via CDP - only in-page menus.',
|
|
81
81
|
inputSchema: {
|
|
82
82
|
type: 'object',
|
|
83
83
|
properties: {
|
|
@@ -100,7 +100,7 @@ export const TOOLS = [
|
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
102
|
name: 'browser_reattach_debugger',
|
|
103
|
-
description: 'RECOVERY: Force-detach and re-attach the Chrome debugger on the current tab. Use when interactive tools (click/fill/press_key) start timing out or reporting ghost-attach ("Debugger attach failed ... ghost") while list_tabs still works
|
|
103
|
+
description: 'RECOVERY: Force-detach and re-attach the Chrome debugger on the current tab. Use when interactive tools (click/fill/press_key) start timing out or reporting ghost-attach ("Debugger attach failed ... ghost") while list_tabs still works - faster than reloading the extension.',
|
|
104
104
|
inputSchema: { type: 'object', properties: {} },
|
|
105
105
|
},
|
|
106
106
|
{
|
|
@@ -185,7 +185,7 @@ export const TOOLS = [
|
|
|
185
185
|
type: 'object',
|
|
186
186
|
properties: {
|
|
187
187
|
selector: { type: 'string', description: 'CSS or text selector for the dropdown trigger / <select> element' },
|
|
188
|
-
option: { type: 'string', description: 'Text OR value of the option to select. Exact value match wins, then exact text, then partial text. Aliases: `value`, `label`. Fails loudly with the available options if nothing matches
|
|
188
|
+
option: { type: 'string', description: 'Text OR value of the option to select. Exact value match wins, then exact text, then partial text. Aliases: `value`, `label`. Fails loudly with the available options if nothing matches - it never reports success without the field actually changing.' },
|
|
189
189
|
wait: { type: 'number', description: 'Ms to wait after clicking trigger for options to appear (default: 300)' },
|
|
190
190
|
},
|
|
191
191
|
required: ['selector', 'option'],
|
|
@@ -220,7 +220,7 @@ export const TOOLS = [
|
|
|
220
220
|
},
|
|
221
221
|
{
|
|
222
222
|
name: 'browser_drop_file',
|
|
223
|
-
description: 'Upload a file when browser_upload_file fails. Two strategies: (1) finds a hidden <input type="file"> in the target\'s subtree or up to 2 ancestor levels; (2) if there is no input at all, intercepts the NATIVE OS file-chooser
|
|
223
|
+
description: 'Upload a file when browser_upload_file fails. Two strategies: (1) finds a hidden <input type="file"> in the target\'s subtree or up to 2 ancestor levels; (2) if there is no input at all, intercepts the NATIVE OS file-chooser - pass the selector of the button that opens the dialog, and the file is supplied programmatically without the dialog ever appearing. Strategy 2 handles sites like Google Ads that never put a file input in the DOM. Files must be regular files inside the working directory the MCP server runs in - folders, symlinks and hardlinks that point outside it are refused.',
|
|
224
224
|
inputSchema: {
|
|
225
225
|
type: 'object',
|
|
226
226
|
properties: {
|
|
@@ -233,7 +233,7 @@ export const TOOLS = [
|
|
|
233
233
|
},
|
|
234
234
|
{
|
|
235
235
|
name: 'browser_set_date',
|
|
236
|
-
description: 'Robustly set a date input
|
|
236
|
+
description: 'Robustly set a date input - handles native <input type="date">, masked text inputs (e.g. MM/DD/YYYY), and calendar pickers (MUI, react-datepicker, AntD, Lexical/Meta). Tries native value-set, format-aware typing via Input.insertText, and ARIA-based picker navigation in sequence with read-back verification. Use instead of browser_fill when fill fails or for any input that opens a calendar widget.',
|
|
237
237
|
inputSchema: {
|
|
238
238
|
type: 'object',
|
|
239
239
|
properties: {
|
|
@@ -246,7 +246,7 @@ export const TOOLS = [
|
|
|
246
246
|
},
|
|
247
247
|
{
|
|
248
248
|
name: 'browser_handle_dialog',
|
|
249
|
-
description: 'Arm automatic handling of the next JavaScript alert/confirm/prompt on the active tab, then return immediately. Call this BEFORE the click that opens the dialog
|
|
249
|
+
description: 'Arm automatic handling of the next JavaScript alert/confirm/prompt on the active tab, then return immediately. Call this BEFORE the click that opens the dialog - a dialog freezes the tab, so nothing can be clicked once it is on screen. Pass wait=true only when the dialog is already opening.',
|
|
250
250
|
inputSchema: {
|
|
251
251
|
type: 'object',
|
|
252
252
|
properties: {
|
|
@@ -259,7 +259,7 @@ export const TOOLS = [
|
|
|
259
259
|
},
|
|
260
260
|
{
|
|
261
261
|
name: 'browser_wait_for_network',
|
|
262
|
-
description: 'Wait for a network request to complete. Useful after clicking buttons that trigger API calls
|
|
262
|
+
description: 'Wait for a network request to complete. Useful after clicking buttons that trigger API calls - ensures data is loaded before reading the page. Monitors real network traffic via Chrome DevTools Protocol.',
|
|
263
263
|
inputSchema: {
|
|
264
264
|
type: 'object',
|
|
265
265
|
properties: {
|
|
@@ -289,11 +289,11 @@ export const TOOLS = [
|
|
|
289
289
|
},
|
|
290
290
|
{
|
|
291
291
|
name: 'browser_get_cookies',
|
|
292
|
-
description: 'Get cookies for a
|
|
292
|
+
description: 'Get cookies for a site this session has open in one of its tabs (the site itself, a parent domain or a subdomain). Navigate to the site first - cookies for sites the session is not working on are refused.',
|
|
293
293
|
inputSchema: {
|
|
294
294
|
type: 'object',
|
|
295
295
|
properties: {
|
|
296
|
-
domain: { type: 'string', description: 'Domain to get cookies for (e.g. ".stripe.com")' },
|
|
296
|
+
domain: { type: 'string', description: 'Domain to get cookies for (e.g. ".stripe.com"). Must match a tab this session has open.' },
|
|
297
297
|
},
|
|
298
298
|
required: ['domain'],
|
|
299
299
|
},
|
|
@@ -356,7 +356,7 @@ export const TOOLS = [
|
|
|
356
356
|
type: 'object',
|
|
357
357
|
properties: {
|
|
358
358
|
message: { type: 'string', description: 'What the user needs to do or provide' },
|
|
359
|
-
title: { type: 'string', description: 'Dialog title (default: "Agent360
|
|
359
|
+
title: { type: 'string', description: 'Dialog title (default: "Agent360 - Action Required")' },
|
|
360
360
|
fields: {
|
|
361
361
|
type: 'array',
|
|
362
362
|
description: 'Input fields for user to fill in. Each field has: name (key), label (display text), type (text/password/email). Omit for simple "Done/Skip" confirmation.',
|
|
@@ -421,7 +421,7 @@ export const TOOLS = [
|
|
|
421
421
|
},
|
|
422
422
|
{
|
|
423
423
|
name: 'browser_upload_file',
|
|
424
|
-
description: 'Upload a file to a <input type="file"> element on the page. Uses Chrome Debugger API to set files programmatically
|
|
424
|
+
description: 'Upload a file to a <input type="file"> element on the page. Uses Chrome Debugger API to set files programmatically - no dialog needed. For drag-drop zones without visible file input use browser_drop_file. Files must be regular files inside the working directory the MCP server runs in - folders, symlinks and hardlinks that point outside it are refused.',
|
|
425
425
|
inputSchema: {
|
|
426
426
|
type: 'object',
|
|
427
427
|
properties: {
|
|
@@ -460,7 +460,7 @@ export const TOOLS = [
|
|
|
460
460
|
},
|
|
461
461
|
{
|
|
462
462
|
name: 'browser_about',
|
|
463
|
-
description: 'Returns Browser MCP info and pre-filled URLs the user can click to submit feature wishes, share use-cases, or report bugs. Call this PROACTIVELY whenever the user (a) mentions a feature they wish existed ("I wish browser-mcp could...", "it would be nice if..."), (b) says something is missing, broken, or unexpected, (c) asks how Browser MCP works or who maintains it, or (d) describes something cool they built with browser-mcp. Pass intent="wish" | "use_case" | "bug" | "info" plus an optional title and body, and offer the returned submit_url to the user. Browser MCP is community-shaped
|
|
463
|
+
description: 'Returns Browser MCP info and pre-filled URLs the user can click to submit feature wishes, share use-cases, or report bugs. Call this PROACTIVELY whenever the user (a) mentions a feature they wish existed ("I wish browser-mcp could...", "it would be nice if..."), (b) says something is missing, broken, or unexpected, (c) asks how Browser MCP works or who maintains it, or (d) describes something cool they built with browser-mcp. Pass intent="wish" | "use_case" | "bug" | "info" plus an optional title and body, and offer the returned submit_url to the user. Browser MCP is community-shaped - this tool is how the user contributes back.',
|
|
464
464
|
inputSchema: {
|
|
465
465
|
type: 'object',
|
|
466
466
|
properties: {
|
|
@@ -482,7 +482,7 @@ export const TOOLS = [
|
|
|
482
482
|
},
|
|
483
483
|
{
|
|
484
484
|
name: 'browser_provide_feedback',
|
|
485
|
-
description: 'Self-diagnosis + feedback in one call. Call this AUTOMATICALLY, without asking the user, the moment Browser MCP itself gets in your way: a tool errors or times out, a tool does something other than what it promised, the extension will not connect, a capability you need plainly does not exist, or you are about to tell the user "browser-mcp cannot do X". It first CHECKS THE INSTALL
|
|
485
|
+
description: 'Self-diagnosis + feedback in one call. Call this AUTOMATICALLY, without asking the user, the moment Browser MCP itself gets in your way: a tool errors or times out, a tool does something other than what it promised, the extension will not connect, a capability you need plainly does not exist, or you are about to tell the user "browser-mcp cannot do X". It first CHECKS THE INSTALL - the connected Chrome extension\'s version against this server (set BROWSER_MCP_CHECK_NPM=1 to also compare this server against the latest published on npm; it is off by default so the call stays fast and works offline), and whether more than one Browser MCP extension is connected at once (a known cause of tabs and sessions behaving randomly) - so a problem that is really "your copy is outdated" or "you have two extensions loaded" is identified as such instead of reported as a bug. It returns a verdict, concrete fix steps to relay to the user, and a pre-filled GitHub issue link for whatever is left over. Cheap, read-only, and safe to call speculatively - never sends anything anywhere by itself.',
|
|
486
486
|
inputSchema: {
|
|
487
487
|
type: 'object',
|
|
488
488
|
properties: {
|
package/vagt.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Foraeldre-vagten
|
|
2
|
+
* Foraeldre-vagten - hvornaar er en proces i kaeden faktisk doed?
|
|
3
3
|
*
|
|
4
4
|
* Ligger i sit eget modul UDEN sideeffekter, saa den kan importeres og koeres i en
|
|
5
5
|
* test. `index.js` starter en WebSocket-server, forbinder MCP-transporten og saetter
|
|
6
|
-
* timere op ved import
|
|
6
|
+
* timere op ved import - den kan ikke importeres af en test uden at haenge. Derfor
|
|
7
7
|
* blev vagt-logikken tidligere kun grepped efter som tekst, og en regex kan ikke se
|
|
8
8
|
* om FORTOLKNINGEN af en fejl er rigtig.
|
|
9
9
|
*
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* [MCP] vagt-kaede: 1
|
|
13
13
|
* [MCP] Chrome extension connected on port 9882
|
|
14
|
-
* [MCP] Proces 1 i kaeden doede
|
|
14
|
+
* [MCP] Proces 1 i kaeden doede - chatten bag denne server er vaek
|
|
15
15
|
*
|
|
16
16
|
* Pid 1 er launchd. Den doede ikke. `process.kill(1, 0)` kaster EPERM for en
|
|
17
17
|
* almindelig bruger, og koden tolkede ENHVER exception som doed. Vagten der skulle
|