browser-console-mcp 1.0.2 → 1.0.5
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/bin/copy-browser-inject.js +55 -0
- package/bin/copy-html2canvas.js +45 -2
- package/dist/browser/browser-inject.js +9 -9
- package/dist/browser/index.js +1 -1
- package/dist/client/browser-console-mcp.js +1 -1
- package/dist/client/index.js +13 -13
- package/dist/server/index.js +9 -9
- package/dist/server/static-server.js +4 -4
- package/package.json +12 -3
- package/dist/browser/browser-mcp-server.js +0 -718
- package/dist/browser/index.js.map +0 -1
- package/dist/client/browser-console-mcp.js.map +0 -1
- package/dist/static/html2canvas/dist/html2canvas.min.js +0 -20
- package/rollup.browser.config.js +0 -23
- package/rollup.config.js +0 -22
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var BrowserConsoleMCP=function(){"use strict";const e=new class{constructor(e="ws://localhost:7898/browser"){this.ws=null,this.connected=!1,this.commandHistory=[],this.historyIndex=-1,this.serverUrl=e}connect(){try{this.loadHtml2Canvas().then((()=>{this.ws=new WebSocket(this.serverUrl),this.ws.onopen=()=>{this.connected=!0,console.
|
|
1
|
+
var BrowserConsoleMCP=function(){"use strict";const e=new class{constructor(e="ws://localhost:7898/browser"){this.ws=null,this.connected=!1,this.commandHistory=[],this.historyIndex=-1,this.serverUrl=e}connect(){try{this.loadHtml2Canvas().then((()=>{this.ws=new WebSocket(this.serverUrl),this.ws.onopen=()=>{this.connected=!0,console.log("%c[MCP Client] Connected to server","color: green"),this.registerConsoleCommands()},this.ws.onmessage=e=>{try{const t=JSON.parse(e.data);this.handleServerMessage(t)}catch(e){console.error("[MCP Client] Message parsing error:",e)}},this.ws.onclose=()=>{this.connected=!1,console.log("%c[MCP Client] Disconnected from server","color: orange")},this.ws.onerror=e=>{console.error("[MCP Client] WebSocket error:",e)}})).catch((e=>{console.error("[MCP Client] Failed to load html2canvas:",e)}))}catch(e){console.error("[MCP Client] Connection error:",e)}}loadHtml2Canvas(){return new Promise(((e,t)=>{if(void 0!==window.html2canvas)return console.log("[MCP Client] html2canvas already loaded"),void e(!0);console.log("[MCP Client] Loading html2canvas...");const n=document.createElement("script");n.src="https://html2canvas.hertzen.com/dist/html2canvas.min.js",n.onload=()=>{console.log("[MCP Client] html2canvas loaded from CDN"),e(!0)},n.onerror=()=>{console.log("[MCP Client] Trying local path for html2canvas...");const n=document.createElement("script");n.src="/html2canvas.min.js",n.onload=()=>{console.log("[MCP Client] html2canvas loaded from local path"),e(!0)},n.onerror=n=>{console.log("[MCP Client] Trying unpkg CDN for html2canvas...");const o=document.createElement("script");o.src="https://unpkg.com/html2canvas/dist/html2canvas.min.js",o.onload=()=>{console.log("[MCP Client] html2canvas loaded from unpkg CDN"),e(!0)},o.onerror=e=>{console.error("[MCP Client] Failed to load html2canvas:",e),t(new Error("Unable to load html2canvas library, please ensure your network connection is working"))},document.head.appendChild(o)},document.head.appendChild(n)},document.head.appendChild(n)}))}handleServerMessage(e){if("get_page_html"!==e.type)if("execute_js"!==e.type)if("get_page_title"!==e.type)if("get_elements"!==e.type)if("capture_screenshot"!==e.type)if("get_page_url"!==e.type)if("click_element"!==e.type)if("input_text"!==e.type)switch(e.type){case"command_result":console.log(`%c[MCP Server] ${e.payload?.result}`,"color: blue");break;case"error":console.error(`[MCP Server] Error: ${e.payload?.error}`);break;case"connection_status":console.log(`%c[MCP Server] ${e.message}`,"color: green");break;default:console.log(`[MCP Server] Received message type: ${e.type}`)}else{const t=e.requestId,n=e.selector,o=e.text;try{const e=document.querySelector(n);if(!e)return void this.sendError(t,`Input field not found: ${n}`);if("INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName)return void this.sendError(t,`Selected element is not an input field: ${e.tagName}`);e.value=o,e.dispatchEvent(new Event("input",{bubbles:!0})),this.sendResponse(t,{success:!0,message:`Successfully input text to: ${n}`})}catch(e){this.sendError(t,`Error inputting text: ${e.message}`)}}else{const t=e.requestId,n=e.selector;try{const e=document.querySelector(n);if(!e)return void this.sendError(t,`Element not found: ${n}`);e.click(),this.sendResponse(t,{success:!0,message:`Successfully clicked element: ${n}`})}catch(e){this.sendError(t,`Error clicking element: ${e.message}`)}}else{const t=e.requestId;try{const e=window.location.href;this.sendResponse(t,{url:e})}catch(e){this.sendError(t,`Error getting URL: ${e.message}`)}}else{const t=e.requestId,n=e.selector||"body";(async()=>{try{await this.loadHtml2Canvas();const e=document.querySelector(n);if(!e)return void this.sendError(t,`Element not found: ${n}`);const o={allowTaint:!0,useCORS:!0,logging:!1,scale:window.devicePixelRatio||1,backgroundColor:null,removeContainer:!0,x:0,y:0,scrollX:0,scrollY:0,width:e.offsetWidth,height:e.offsetHeight},s=window.html2canvas;if(!s)return void this.sendError(t,"html2canvas library not properly loaded");let r=await s(e,o);if(!r)return void this.sendError(t,"Screenshot failed: unable to create canvas");const c=r.getContext("2d");if(c){const e=c.getImageData(0,0,r.width,r.height),t=this.getContentBounds(e);if(t){const e=document.createElement("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n&&(n.drawImage(r,t.left,t.top,t.width,t.height,0,0,t.width,t.height),r=e)}}const i=r.toDataURL("image/png");this.sendResponse(t,{imageDataUrl:i})}catch(e){console.error("[MCP Client] Screenshot error:",e),this.sendError(t,`Screenshot error: ${e.message}`)}})()}else{const t=e.requestId,n=e.selector;try{const e=[...document.querySelectorAll(n)].map((e=>({tagName:e.tagName,id:e.id,className:e.className,textContent:e.textContent?.trim().substring(0,500)||"",attributes:[...e.attributes].reduce(((e,t)=>(e[t.name]=t.value,e)),{})})));this.sendResponse(t,{elements:e})}catch(e){this.sendError(t,`Error getting elements: ${e.message}`)}}else{const t=e.requestId;try{const e=document.title;this.sendResponse(t,{title:e})}catch(e){this.sendError(t,`Error getting title: ${e.message}`)}}else{const t=e.requestId,n=e.code;try{const e=new Function(n)();let o;try{o=JSON.stringify(e)}catch(t){o=String(e)}const s={requestId:t,result:o};this.ws?.send(JSON.stringify(s))}catch(e){console.error("[MCP Client] Error executing JavaScript:",e),this.sendError(t,`Error executing JavaScript: ${e.message}`)}}else{const t=e.requestId;try{const e=document.documentElement.outerHTML;this.sendResponse(t,{html:e})}catch(e){this.sendError(t,`Error getting HTML: ${e.message}`)}}}sendResponse(e,t){if(!this.connected||!this.ws)return void console.error("[MCP Client] Not connected to server, cannot send response");const n={requestId:e,...t};this.ws.send(JSON.stringify(n))}sendError(e,t){if(!this.connected||!this.ws)return void console.error("[MCP Client] Not connected to server, cannot send error response");const n={requestId:e,error:t};this.ws.send(JSON.stringify(n))}sendCommand(e){if(!this.connected||!this.ws)return void console.error("[MCP Client] Not connected to server");const t={type:"command",payload:{command:e}};this.ws.send(JSON.stringify(t)),this.commandHistory.push(e),this.historyIndex=this.commandHistory.length}registerConsoleCommands(){window.mcp={exec:e=>(this.sendCommand(e),"Command sent"),disconnect:()=>(this.ws&&(this.ws.close(),this.ws=null),"Disconnected"),reconnect:()=>(this.connect(),"Reconnecting..."),help:()=>"\nMCP Client Commands:\n mcp.exec(command) - Execute a command\n mcp.disconnect() - Disconnect from server\n mcp.reconnect() - Reconnect to server\n mcp.help() - Show help information\n "},console.log("%c[MCP Client] Console commands registered, use mcp.help() to see available commands","color: green")}getContentBounds(e){const{width:t,height:n,data:o}=e;let s=t,r=n,c=0,i=0,a=!1;for(let e=0;e<n;e++)for(let n=0;n<t;n++){o[4*(e*t+n)+3]>10&&(a=!0,s=Math.min(s,n),r=Math.min(r,e),c=Math.max(c,n),i=Math.max(i,e))}if(!a)return null;return s=Math.max(0,s-10),r=Math.max(0,r-10),c=Math.min(t-1,c+10),i=Math.min(n-1,i+10),{left:s,top:r,width:c-s+1,height:i-r+1}}};return e.connect(),e}();
|
|
2
2
|
//# sourceMappingURL=browser-console-mcp.js.map
|
package/dist/client/index.js
CHANGED
|
@@ -22,7 +22,7 @@ class BrowserConsoleMCP {
|
|
|
22
22
|
this.ws = new WebSocket(this.serverUrl);
|
|
23
23
|
this.ws.onopen = () => {
|
|
24
24
|
this.connected = true;
|
|
25
|
-
console.
|
|
25
|
+
console.log("%c[MCP Client] Connected to server", "color: green");
|
|
26
26
|
this.registerConsoleCommands();
|
|
27
27
|
};
|
|
28
28
|
this.ws.onmessage = (event) => {
|
|
@@ -36,7 +36,7 @@ class BrowserConsoleMCP {
|
|
|
36
36
|
};
|
|
37
37
|
this.ws.onclose = () => {
|
|
38
38
|
this.connected = false;
|
|
39
|
-
console.
|
|
39
|
+
console.log("%c[MCP Client] Disconnected from server", "color: orange");
|
|
40
40
|
};
|
|
41
41
|
this.ws.onerror = (error) => {
|
|
42
42
|
console.error("[MCP Client] WebSocket error:", error);
|
|
@@ -56,35 +56,35 @@ class BrowserConsoleMCP {
|
|
|
56
56
|
loadHtml2Canvas() {
|
|
57
57
|
return new Promise((resolve, reject) => {
|
|
58
58
|
if (typeof window.html2canvas !== "undefined") {
|
|
59
|
-
console.
|
|
59
|
+
console.log("[MCP Client] html2canvas already loaded");
|
|
60
60
|
resolve(true);
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
|
-
console.
|
|
63
|
+
console.log("[MCP Client] Loading html2canvas...");
|
|
64
64
|
// Prioritize loading html2canvas from CDN
|
|
65
65
|
const script = document.createElement("script");
|
|
66
66
|
script.src = "https://html2canvas.hertzen.com/dist/html2canvas.min.js";
|
|
67
67
|
script.onload = () => {
|
|
68
|
-
console.
|
|
68
|
+
console.log("[MCP Client] html2canvas loaded from CDN");
|
|
69
69
|
resolve(true);
|
|
70
70
|
};
|
|
71
71
|
script.onerror = () => {
|
|
72
72
|
// If CDN fails, try local path
|
|
73
|
-
console.
|
|
73
|
+
console.log("[MCP Client] Trying local path for html2canvas...");
|
|
74
74
|
const localScript = document.createElement("script");
|
|
75
75
|
localScript.src = "/html2canvas.min.js";
|
|
76
76
|
localScript.onload = () => {
|
|
77
|
-
console.
|
|
77
|
+
console.log("[MCP Client] html2canvas loaded from local path");
|
|
78
78
|
resolve(true);
|
|
79
79
|
};
|
|
80
80
|
localScript.onerror = (err) => {
|
|
81
81
|
// Try using unpkg CDN
|
|
82
|
-
console.
|
|
82
|
+
console.log("[MCP Client] Trying unpkg CDN for html2canvas...");
|
|
83
83
|
const unpkgScript = document.createElement("script");
|
|
84
84
|
unpkgScript.src =
|
|
85
85
|
"https://unpkg.com/html2canvas/dist/html2canvas.min.js";
|
|
86
86
|
unpkgScript.onload = () => {
|
|
87
|
-
console.
|
|
87
|
+
console.log("[MCP Client] html2canvas loaded from unpkg CDN");
|
|
88
88
|
resolve(true);
|
|
89
89
|
};
|
|
90
90
|
unpkgScript.onerror = (err) => {
|
|
@@ -313,17 +313,17 @@ class BrowserConsoleMCP {
|
|
|
313
313
|
// Handle other message types
|
|
314
314
|
switch (message.type) {
|
|
315
315
|
case "command_result":
|
|
316
|
-
console.
|
|
316
|
+
console.log(`%c[MCP Server] ${message.payload?.result}`, "color: blue");
|
|
317
317
|
break;
|
|
318
318
|
case "error":
|
|
319
319
|
console.error(`[MCP Server] Error: ${message.payload?.error}`);
|
|
320
320
|
break;
|
|
321
321
|
case "connection_status":
|
|
322
|
-
console.
|
|
322
|
+
console.log(`%c[MCP Server] ${message.message}`, "color: green");
|
|
323
323
|
break;
|
|
324
324
|
default:
|
|
325
325
|
// Only log message type, not full message content
|
|
326
|
-
console.
|
|
326
|
+
console.log(`[MCP Server] Received message type: ${message.type}`);
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
/**
|
|
@@ -401,7 +401,7 @@ MCP Client Commands:
|
|
|
401
401
|
`;
|
|
402
402
|
},
|
|
403
403
|
};
|
|
404
|
-
console.
|
|
404
|
+
console.log("%c[MCP Client] Console commands registered, use mcp.help() to see available commands", "color: green");
|
|
405
405
|
}
|
|
406
406
|
/**
|
|
407
407
|
* Get image content boundaries, remove excess whitespace
|
package/dist/server/index.js
CHANGED
|
@@ -35,9 +35,9 @@ class BrowserConsoleMCPServer {
|
|
|
35
35
|
this.staticServer.start();
|
|
36
36
|
// Start HTTP server
|
|
37
37
|
this.httpServer.listen(this.port, () => {
|
|
38
|
-
console.
|
|
39
|
-
console.
|
|
40
|
-
console.
|
|
38
|
+
console.log(`[MCP Server] HTTP server started on port ${this.port}`);
|
|
39
|
+
console.log(`[MCP Server] WebSocket server path: ws://localhost:${this.port}/ws`);
|
|
40
|
+
console.log(`[MCP Server] Static files will be redirected to port ${this.staticServer.getPort()}`);
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
@@ -47,7 +47,7 @@ class BrowserConsoleMCPServer {
|
|
|
47
47
|
this.wss.on("connection", (ws) => {
|
|
48
48
|
const clientId = this.generateClientId();
|
|
49
49
|
this.clients.set(clientId, { id: clientId, ws });
|
|
50
|
-
console.
|
|
50
|
+
console.log(`[MCP Server] Client ${clientId} connected`);
|
|
51
51
|
ws.on("message", (data) => {
|
|
52
52
|
try {
|
|
53
53
|
const message = JSON.parse(data.toString());
|
|
@@ -59,7 +59,7 @@ class BrowserConsoleMCPServer {
|
|
|
59
59
|
});
|
|
60
60
|
ws.on("close", () => {
|
|
61
61
|
this.clients.delete(clientId);
|
|
62
|
-
console.
|
|
62
|
+
console.log(`[MCP Server] Client ${clientId} disconnected`);
|
|
63
63
|
});
|
|
64
64
|
ws.on("error", (error) => {
|
|
65
65
|
console.error(`[MCP Server] WebSocket error (client ${clientId}):`, error);
|
|
@@ -79,7 +79,7 @@ class BrowserConsoleMCPServer {
|
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
// Only log message type, not the full message content
|
|
82
|
-
console.
|
|
82
|
+
console.log(`[MCP Server] Received message type ${message.type} from client ${clientId}`);
|
|
83
83
|
switch (message.type) {
|
|
84
84
|
case "command":
|
|
85
85
|
this.executeCommand(client, message.payload?.command);
|
|
@@ -96,7 +96,7 @@ class BrowserConsoleMCPServer {
|
|
|
96
96
|
this.sendErrorToClient(client, "Command is empty");
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
|
-
console.
|
|
99
|
+
console.log(`[MCP Server] Executing command: ${command}`);
|
|
100
100
|
exec(command, (error, stdout, stderr) => {
|
|
101
101
|
if (error) {
|
|
102
102
|
this.sendErrorToClient(client, `Command execution error: ${error.message}`);
|
|
@@ -139,7 +139,7 @@ class BrowserConsoleMCPServer {
|
|
|
139
139
|
this.httpServer.close();
|
|
140
140
|
this.wss.close();
|
|
141
141
|
this.staticServer.stop();
|
|
142
|
-
console.
|
|
142
|
+
console.log("[MCP Server] Server closed");
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
// Create and start server instance
|
|
@@ -147,7 +147,7 @@ const server = new BrowserConsoleMCPServer();
|
|
|
147
147
|
server.start();
|
|
148
148
|
// Handle process exit
|
|
149
149
|
process.on("SIGINT", () => {
|
|
150
|
-
console.
|
|
150
|
+
console.log("[MCP Server] Shutting down server...");
|
|
151
151
|
server.stop();
|
|
152
152
|
process.exit(0);
|
|
153
153
|
});
|
|
@@ -141,7 +141,7 @@ mcp.reconnect();</code></pre>
|
|
|
141
141
|
Expires: "0",
|
|
142
142
|
});
|
|
143
143
|
res.end(fileContent);
|
|
144
|
-
console.
|
|
144
|
+
console.log(`[Static Server] Successfully served static file: ${filePath}`);
|
|
145
145
|
}
|
|
146
146
|
else {
|
|
147
147
|
console.error(`[Static Server] Static file not found: ${filePath}`);
|
|
@@ -160,8 +160,8 @@ mcp.reconnect();</code></pre>
|
|
|
160
160
|
*/
|
|
161
161
|
start() {
|
|
162
162
|
this.server.listen(this.port, () => {
|
|
163
|
-
console.
|
|
164
|
-
console.
|
|
163
|
+
console.log(`[Static Server] Server started, listening on port ${this.port}`);
|
|
164
|
+
console.log(`[Static Server] Client JS file URL: http://localhost:${this.port}/browser-console-mcp.js`);
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
167
|
/**
|
|
@@ -169,7 +169,7 @@ mcp.reconnect();</code></pre>
|
|
|
169
169
|
*/
|
|
170
170
|
stop() {
|
|
171
171
|
this.server.close(() => {
|
|
172
|
-
console.
|
|
172
|
+
console.log("[Static Server] Server closed");
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
175
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-console-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "MCP client for browser console and server for Cursor",
|
|
5
5
|
"main": "dist/server/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
37
37
|
"@types/node": "^20.17.46",
|
|
38
38
|
"@types/ws": "^8.18.1",
|
|
39
|
+
"html2canvas": "^1.4.1",
|
|
39
40
|
"rollup": "^4.12.1",
|
|
40
41
|
"rollup-plugin-terser": "^7.0.2",
|
|
41
42
|
"tslib": "^2.8.1",
|
|
@@ -43,16 +44,24 @@
|
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
45
46
|
"@modelcontextprotocol/sdk": "^1.5.0",
|
|
46
|
-
"html2canvas": "^1.4.1",
|
|
47
47
|
"ws": "^8.16.0",
|
|
48
48
|
"zod": "^3.24.4"
|
|
49
49
|
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"html2canvas": "^1.4.1"
|
|
52
|
+
},
|
|
53
|
+
"peerDependenciesMeta": {
|
|
54
|
+
"html2canvas": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
50
58
|
"scripts": {
|
|
51
59
|
"build": "tsc",
|
|
52
60
|
"build:client": "rollup -c",
|
|
53
61
|
"build:browser": "rollup -c rollup.browser.config.js",
|
|
54
62
|
"copy:html2canvas": "node bin/copy-html2canvas.js",
|
|
55
|
-
"
|
|
63
|
+
"copy:browser-inject": "node bin/copy-browser-inject.js",
|
|
64
|
+
"build:all": "pnpm build && pnpm build:client && pnpm build:browser && pnpm copy:html2canvas && pnpm copy:browser-inject",
|
|
56
65
|
"dev": "tsc --watch",
|
|
57
66
|
"start": "node dist/server/index.js",
|
|
58
67
|
"start:browser": "node dist/browser/index.js"
|