@agent360/browser-mcp 1.13.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/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@agent360/browser-mcp",
3
+ "version": "1.13.0",
4
+ "description": "Browser MCP — control your real Chrome from Claude Code. Multi-session, human-in-the-loop, 21 tools.",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "bin": {
8
+ "browser-mcp": "./bin/cli.js"
9
+ },
10
+ "files": [
11
+ "index.js",
12
+ "tools.js",
13
+ "bin/",
14
+ "extension/",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "start": "node index.js"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "browser",
23
+ "chrome",
24
+ "claude",
25
+ "claude-code",
26
+ "automation",
27
+ "ai-agent",
28
+ "browser-automation",
29
+ "model-context-protocol"
30
+ ],
31
+ "author": "Agent360 <hello@agent360.dk>",
32
+ "license": "MIT",
33
+ "homepage": "https://github.com/Agent360dk/browser-mcp",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/Agent360dk/browser-mcp.git"
37
+ },
38
+ "dependencies": {
39
+ "@modelcontextprotocol/sdk": "^1.28.0",
40
+ "ws": "^8.18.0"
41
+ }
42
+ }
package/tools.js ADDED
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Agent360 Browser MCP — Tool Definitions
3
+ *
4
+ * Defines all MCP tools exposed to Claude Code.
5
+ */
6
+
7
+ export const TOOLS = [
8
+ {
9
+ name: 'browser_navigate',
10
+ description: 'Navigate the active browser tab to a URL. Reuses the current tab by default (no tab spam). Pass new_tab=true only when you need to keep the current page open.',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ url: { type: 'string', description: 'URL to navigate to' },
15
+ new_tab: { type: 'boolean', description: 'Open in new tab instead of reusing current (default: false)' },
16
+ },
17
+ required: ['url'],
18
+ },
19
+ },
20
+ {
21
+ name: 'browser_get_page_content',
22
+ description: 'Get the content of the current page as text or HTML.',
23
+ inputSchema: {
24
+ type: 'object',
25
+ properties: {
26
+ format: { type: 'string', enum: ['text', 'html'], description: 'Output format (default: text)' },
27
+ },
28
+ },
29
+ },
30
+ {
31
+ name: 'browser_screenshot',
32
+ description: 'Take a screenshot of the visible area of the current tab. Returns base64 PNG.',
33
+ inputSchema: { type: 'object', properties: {} },
34
+ },
35
+ {
36
+ name: 'browser_execute_script',
37
+ description: 'Execute JavaScript code in the context of the current page. Returns the result.',
38
+ inputSchema: {
39
+ type: 'object',
40
+ properties: {
41
+ code: { type: 'string', description: 'JavaScript expression to evaluate (runs in page context)' },
42
+ },
43
+ required: ['code'],
44
+ },
45
+ },
46
+ {
47
+ name: 'browser_click',
48
+ description: 'Click an element on the page. Supports CSS selectors AND text-based selectors. Auto-scrolls element into view. Uses real mouse events (works on Angular/React SPAs and CSP-strict sites like Google, Stripe). Examples: "button:text(Get started)", "text=Submit", "#my-button", "a.btn-primary"',
49
+ inputSchema: {
50
+ type: 'object',
51
+ properties: {
52
+ selector: { type: 'string', description: 'CSS selector or text selector. Text formats: "text=Click me" (any element), "button:text(Submit)" (specific tag)' },
53
+ },
54
+ required: ['selector'],
55
+ },
56
+ },
57
+ {
58
+ name: 'browser_fill',
59
+ description: 'Fill a form input field with a value. Supports CSS selectors AND text-based selectors. Auto-scrolls and focuses the element. Works on CSP-strict sites via Chrome Debugger API.',
60
+ inputSchema: {
61
+ type: 'object',
62
+ properties: {
63
+ selector: { type: 'string', description: 'CSS selector or text selector for the input field' },
64
+ value: { type: 'string', description: 'Value to fill in' },
65
+ },
66
+ required: ['selector', 'value'],
67
+ },
68
+ },
69
+ {
70
+ name: 'browser_press_key',
71
+ description: 'Press a keyboard key (Enter, Tab, Escape, ArrowDown, etc.). Useful for submitting forms, navigating dropdowns, closing dialogs. Supports modifier keys (ctrl, alt, shift, meta).',
72
+ inputSchema: {
73
+ type: 'object',
74
+ properties: {
75
+ key: { type: 'string', description: 'Key to press: "Enter", "Tab", "Escape", "ArrowDown", "ArrowUp", "Backspace", "a", "1", etc.' },
76
+ code: { type: 'string', description: 'Key code (optional, defaults to key name). E.g. "KeyA" for "a"' },
77
+ ctrl: { type: 'boolean', description: 'Hold Ctrl/Cmd key' },
78
+ alt: { type: 'boolean', description: 'Hold Alt key' },
79
+ shift: { type: 'boolean', description: 'Hold Shift key' },
80
+ meta: { type: 'boolean', description: 'Hold Meta (Cmd on Mac) key' },
81
+ },
82
+ required: ['key'],
83
+ },
84
+ },
85
+ {
86
+ name: 'browser_scroll',
87
+ description: 'Scroll the page to an element or by pixel amount. Useful for reaching elements below the fold.',
88
+ inputSchema: {
89
+ type: 'object',
90
+ properties: {
91
+ selector: { type: 'string', description: 'CSS or text selector to scroll to (element scrolled into center of viewport)' },
92
+ x: { type: 'number', description: 'Pixels to scroll horizontally (positive = right)' },
93
+ y: { type: 'number', description: 'Pixels to scroll vertically (positive = down, e.g. 500)' },
94
+ },
95
+ },
96
+ },
97
+ {
98
+ name: 'browser_wait',
99
+ description: 'Wait for an element to appear on the page. Supports CSS and text-based selectors.',
100
+ inputSchema: {
101
+ type: 'object',
102
+ properties: {
103
+ selector: { type: 'string', description: 'CSS selector or text selector (e.g. "text=Success", "button:text(Next)") to wait for' },
104
+ timeout: { type: 'number', description: 'Max wait time in ms (default: 10000)' },
105
+ },
106
+ required: ['selector'],
107
+ },
108
+ },
109
+ {
110
+ name: 'browser_hover',
111
+ description: 'Hover over an element to trigger tooltips, dropdown menus, or hover states. Supports CSS and text selectors.',
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ selector: { type: 'string', description: 'CSS or text selector to hover over' },
116
+ duration: { type: 'number', description: 'How long to hold hover in ms (default: 500)' },
117
+ },
118
+ required: ['selector'],
119
+ },
120
+ },
121
+ {
122
+ name: 'browser_select_option',
123
+ description: 'Select an option from a dropdown menu. Works with native <select> elements AND custom dropdowns (Angular Material, React Select, etc.). For custom dropdowns: clicks the trigger, waits for options, then clicks the matching option by text.',
124
+ inputSchema: {
125
+ type: 'object',
126
+ properties: {
127
+ selector: { type: 'string', description: 'CSS or text selector for the dropdown trigger / <select> element' },
128
+ option: { type: 'string', description: 'Text of the option to select (partial match supported)' },
129
+ wait: { type: 'number', description: 'Ms to wait after clicking trigger for options to appear (default: 300)' },
130
+ },
131
+ required: ['selector', 'option'],
132
+ },
133
+ },
134
+ {
135
+ name: 'browser_handle_dialog',
136
+ description: 'Handle JavaScript alert(), confirm(), or prompt() dialogs. Call this BEFORE triggering the action that causes the dialog. Waits for the dialog to appear, then accepts or dismisses it.',
137
+ inputSchema: {
138
+ type: 'object',
139
+ properties: {
140
+ action: { type: 'string', enum: ['accept', 'dismiss'], description: 'Accept or dismiss the dialog (default: accept)' },
141
+ text: { type: 'string', description: 'Text to enter for prompt() dialogs' },
142
+ timeout: { type: 'number', description: 'Max wait for dialog in ms (default: 10000)' },
143
+ },
144
+ },
145
+ },
146
+ {
147
+ name: 'browser_wait_for_network',
148
+ 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.',
149
+ inputSchema: {
150
+ type: 'object',
151
+ properties: {
152
+ url_pattern: { type: 'string', description: 'Substring to match in the request URL (e.g. "/api/users", "graphql"). Empty = any request.' },
153
+ timeout: { type: 'number', description: 'Max wait in ms (default: 15000)' },
154
+ },
155
+ },
156
+ },
157
+ {
158
+ name: 'browser_fetch',
159
+ description: 'Make an HTTP request from the extension background (NOT subject to CORS). Use this when page-context fetch would be blocked by CORS or CSP. Useful for API calls to Google, Stripe, Slack APIs while on their pages.',
160
+ inputSchema: {
161
+ type: 'object',
162
+ properties: {
163
+ url: { type: 'string', description: 'URL to fetch' },
164
+ method: { type: 'string', description: 'HTTP method (default: GET)' },
165
+ headers: { type: 'object', description: 'Request headers as key-value pairs' },
166
+ body: { type: 'string', description: 'Request body (for POST/PUT)' },
167
+ },
168
+ required: ['url'],
169
+ },
170
+ },
171
+ {
172
+ name: 'browser_list_tabs',
173
+ description: 'List all open browser tabs with their URLs and titles.',
174
+ inputSchema: { type: 'object', properties: {} },
175
+ },
176
+ {
177
+ name: 'browser_get_cookies',
178
+ description: 'Get cookies for a specific domain.',
179
+ inputSchema: {
180
+ type: 'object',
181
+ properties: {
182
+ domain: { type: 'string', description: 'Domain to get cookies for (e.g. ".stripe.com")' },
183
+ },
184
+ required: ['domain'],
185
+ },
186
+ },
187
+ {
188
+ name: 'browser_get_local_storage',
189
+ description: 'Read localStorage from the current page. Pass key for a specific value, or omit for all.',
190
+ inputSchema: {
191
+ type: 'object',
192
+ properties: {
193
+ key: { type: 'string', description: 'Specific localStorage key to read (omit for all)' },
194
+ },
195
+ },
196
+ },
197
+ {
198
+ name: 'browser_ask_user',
199
+ description: 'Show an overlay dialog asking the user to perform an action or provide information (credentials, 2FA, CAPTCHA, OAuth consent). Can include input fields for the user to fill in. Returns user responses.',
200
+ inputSchema: {
201
+ type: 'object',
202
+ properties: {
203
+ message: { type: 'string', description: 'What the user needs to do or provide' },
204
+ title: { type: 'string', description: 'Dialog title (default: "Agent360 — Action Required")' },
205
+ fields: {
206
+ type: 'array',
207
+ 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.',
208
+ items: {
209
+ type: 'object',
210
+ properties: {
211
+ name: { type: 'string', description: 'Field key (returned in response)' },
212
+ label: { type: 'string', description: 'Display label' },
213
+ type: { type: 'string', enum: ['text', 'password', 'email', 'number'], description: 'Input type (default: text)' },
214
+ },
215
+ required: ['name', 'label'],
216
+ },
217
+ },
218
+ timeout: { type: 'number', description: 'Max wait time in ms (default: 120000 = 2 min)' },
219
+ },
220
+ required: ['message'],
221
+ },
222
+ },
223
+ {
224
+ name: 'browser_list_frames',
225
+ description: 'List all frames (iframes) in the current page with their URLs and indices.',
226
+ inputSchema: { type: 'object', properties: {} },
227
+ },
228
+ {
229
+ name: 'browser_select_frame',
230
+ description: 'Execute JavaScript in a specific iframe by frame index. Use browser_list_frames first to find the right index.',
231
+ inputSchema: {
232
+ type: 'object',
233
+ properties: {
234
+ frame_index: { type: 'number', description: 'Frame index from browser_list_frames (0 = main frame)' },
235
+ code: { type: 'string', description: 'JavaScript to execute in the frame (default: returns text content)' },
236
+ },
237
+ required: ['frame_index'],
238
+ },
239
+ },
240
+ {
241
+ name: 'browser_get_new_tab',
242
+ description: 'Get the most recently opened tab (useful after clicking links that open new tabs, OAuth popups, etc.).',
243
+ inputSchema: { type: 'object', properties: {} },
244
+ },
245
+ {
246
+ name: 'browser_switch_tab',
247
+ description: 'Switch to a specific browser tab by ID. Get tab IDs from browser_list_tabs or browser_get_new_tab.',
248
+ inputSchema: {
249
+ type: 'object',
250
+ properties: {
251
+ tab_id: { type: 'number', description: 'Tab ID to activate' },
252
+ },
253
+ required: ['tab_id'],
254
+ },
255
+ },
256
+ {
257
+ name: 'browser_close_tab',
258
+ description: 'Close a browser tab by ID. Only tabs owned by the current session can be closed.',
259
+ inputSchema: {
260
+ type: 'object',
261
+ properties: {
262
+ tab_id: { type: 'number', description: 'Tab ID to close (get from browser_list_tabs)' },
263
+ },
264
+ required: ['tab_id'],
265
+ },
266
+ },
267
+ {
268
+ name: 'browser_extract_token',
269
+ description: 'Navigate to a provider\'s API settings page and extract the API token. Optionally store it in Agent360 vault.',
270
+ inputSchema: {
271
+ type: 'object',
272
+ properties: {
273
+ provider: { type: 'string', description: 'Provider slug (stripe, hubspot, slack, etc.)' },
274
+ store_in_vault: { type: 'boolean', description: 'If true, POST token to Agent360 vault API' },
275
+ },
276
+ required: ['provider'],
277
+ },
278
+ },
279
+ ];
280
+
281
+ // Known provider token pages for browser_extract_token
282
+ export const PROVIDER_PAGES = {
283
+ stripe: {
284
+ url: 'https://dashboard.stripe.com/apikeys',
285
+ instructions: 'Look for the Secret key starting with sk_live_ or sk_test_',
286
+ },
287
+ hubspot: {
288
+ url: 'https://app.hubspot.com/settings/',
289
+ instructions: 'Navigate to Integrations → Private Apps → create or find existing app → Access Token',
290
+ },
291
+ slack: {
292
+ url: 'https://api.slack.com/apps',
293
+ instructions: 'Select app → OAuth & Permissions → Bot User OAuth Token (xoxb-...)',
294
+ },
295
+ shopify: {
296
+ url: 'https://admin.shopify.com/store/',
297
+ instructions: 'Settings → Apps → Develop apps → find app → Admin API access token',
298
+ },
299
+ mailchimp: {
300
+ url: 'https://us1.admin.mailchimp.com/account/api/',
301
+ instructions: 'Look for the API key or create a new one',
302
+ },
303
+ pipedrive: {
304
+ url: 'https://app.pipedrive.com/settings/api',
305
+ instructions: 'Copy the personal API token shown on the page',
306
+ },
307
+ calendly: {
308
+ url: 'https://calendly.com/integrations/api_webhooks',
309
+ instructions: 'Copy the personal access token or generate a new one',
310
+ },
311
+ google: {
312
+ url: 'https://console.cloud.google.com/apis/credentials',
313
+ instructions: 'Find or create an API key / OAuth client',
314
+ },
315
+ linkedin: {
316
+ url: 'https://www.linkedin.com/developers/apps',
317
+ instructions: 'Select app → Auth → Client credentials',
318
+ },
319
+ };