browser-mcp-lite 1.0.1 → 1.0.3
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/index.js +19 -16
- package/package.json +1 -1
- package/tools.js +23 -1
package/index.js
CHANGED
|
@@ -173,22 +173,25 @@ const sep = '\u2501'.repeat(53);
|
|
|
173
173
|
|
|
174
174
|
console.log(`[browser-mcp-lite] MCP server: ${mcpUrl}`);
|
|
175
175
|
console.log(`[browser-mcp-lite] WebSocket: ${wsUrl}`);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
console.log(
|
|
179
|
-
console.log(
|
|
180
|
-
console.log(
|
|
181
|
-
|
|
182
|
-
console.log(`\n\u2501\u2501\u2501 MCP Client Config (save as .mcp.json) \u2501\u2501\u2501`);
|
|
183
|
-
console.log(JSON.stringify({
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
176
|
+
|
|
177
|
+
if (isNew) {
|
|
178
|
+
console.log('\n\u26A0 First run \u2014 new token generated');
|
|
179
|
+
console.log(`\n\u2501\u2501\u2501 Auth Token (paste into Chrome Extension popup) \u2501\u2501\u2501`);
|
|
180
|
+
console.log(TOKEN);
|
|
181
|
+
console.log(sep);
|
|
182
|
+
console.log(`\n\u2501\u2501\u2501 MCP Client Config (save as .mcp.json) \u2501\u2501\u2501`);
|
|
183
|
+
console.log(JSON.stringify({
|
|
184
|
+
mcpServers: {
|
|
185
|
+
browser: {
|
|
186
|
+
type: 'http',
|
|
187
|
+
url: mcpUrl,
|
|
188
|
+
headers: { Authorization: `Bearer ${TOKEN}` },
|
|
189
|
+
},
|
|
189
190
|
},
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
}, null, 2));
|
|
192
|
+
console.log(sep);
|
|
193
|
+
} else {
|
|
194
|
+
console.log(`[browser-mcp-lite] Token: ${TOKEN.slice(0, 8)}...`);
|
|
195
|
+
}
|
|
193
196
|
|
|
194
197
|
console.log('\n[browser-mcp-lite] Waiting for Chrome Extension...');
|
package/package.json
CHANGED
package/tools.js
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { sendToExtension } from './index.js';
|
|
3
3
|
|
|
4
|
+
// --- inject_script risk detection ---
|
|
5
|
+
const RISK_PATTERNS = [
|
|
6
|
+
{ pattern: /\b(fetch|XMLHttpRequest|sendBeacon|navigator\.sendBeacon)\s*\(/i, label: 'network request' },
|
|
7
|
+
{ pattern: /document\.cookie/i, label: 'cookie access' },
|
|
8
|
+
{ pattern: /localStorage|sessionStorage/i, label: 'storage access' },
|
|
9
|
+
{ pattern: /indexedDB/i, label: 'IndexedDB access' },
|
|
10
|
+
{ pattern: /new\s+WebSocket\s*\(/i, label: 'WebSocket connection' },
|
|
11
|
+
{ pattern: /new\s+EventSource\s*\(/i, label: 'EventSource connection' },
|
|
12
|
+
{ pattern: /window\.open\s*\(/i, label: 'window.open' },
|
|
13
|
+
{ pattern: /document\.write/i, label: 'document.write' },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
function detectRisks(code) {
|
|
17
|
+
return RISK_PATTERNS.filter(r => r.pattern.test(code)).map(r => r.label);
|
|
18
|
+
}
|
|
19
|
+
|
|
4
20
|
export function registerTools(server) {
|
|
5
21
|
|
|
6
22
|
// --- list_tabs ---
|
|
@@ -53,8 +69,14 @@ export function registerTools(server) {
|
|
|
53
69
|
tabId: z.number().optional().describe('Tab ID to inject into. Defaults to the active tab.'),
|
|
54
70
|
},
|
|
55
71
|
async ({ code, tabId }) => {
|
|
72
|
+
const risks = detectRisks(code);
|
|
56
73
|
const result = await sendToExtension('inject_script', { code, tabId });
|
|
57
|
-
|
|
74
|
+
const output = JSON.stringify(result, null, 2);
|
|
75
|
+
if (risks.length > 0) {
|
|
76
|
+
const warning = `\u26A0 RISK: This script uses ${risks.join(', ')}. Verify this was intentional.`;
|
|
77
|
+
return { content: [{ type: 'text', text: `${warning}\n\n${output}` }] };
|
|
78
|
+
}
|
|
79
|
+
return { content: [{ type: 'text', text: output }] };
|
|
58
80
|
}
|
|
59
81
|
);
|
|
60
82
|
}
|