browser-bridge-mcp 0.1.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/LICENSE +21 -0
- package/README.md +144 -0
- package/bin/cli.mjs +153 -0
- package/middleware.mjs +22 -0
- package/next.mjs +40 -0
- package/package.json +52 -0
- package/src/client.js +725 -0
- package/src/server.mjs +691 -0
- package/vite.mjs +18 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mukesh Bishnoi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# browser-bridge-mcp
|
|
2
|
+
|
|
3
|
+
Give [Claude Code](https://docs.anthropic.com/en/docs/claude-code) direct access to your browser — console logs, network requests, JS errors, storage, DOM, and more.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Browser <──WebSocket──> MCP Server <──stdio──> Claude Code
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
A small client script runs in your browser tab, hooks into console, fetch, XHR, and error events, and streams everything to an MCP server that Claude Code can query.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -D browser-bridge-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. Register with Claude Code
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# User scope (just you)
|
|
25
|
+
npx browser-bridge-mcp setup
|
|
26
|
+
|
|
27
|
+
# Project scope (whole team via .mcp.json)
|
|
28
|
+
npx browser-bridge-mcp setup --scope project
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 3. Connect your app (pick one)
|
|
32
|
+
|
|
33
|
+
**Next.js** — add to `next.config.mjs` (or `.ts`):
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import { withBrowserBridge } from 'browser-bridge-mcp/next';
|
|
37
|
+
|
|
38
|
+
// Wrap your config — no-op in production
|
|
39
|
+
export default withBrowserBridge(nextConfig);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Vite** — add to `vite.config.js`:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import { browserBridge } from 'browser-bridge-mcp/vite';
|
|
46
|
+
|
|
47
|
+
export default defineConfig({
|
|
48
|
+
plugins: [browserBridge()],
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Any page** (bookmarklet / console paste):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx browser-bridge-mcp bookmarklet # generates clickable bookmarklet HTML
|
|
56
|
+
npx browser-bridge-mcp snippet # prints client.js to stdout
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 4. Use it
|
|
60
|
+
|
|
61
|
+
Restart Claude Code, run your dev server, done. Claude can now see everything in your browser.
|
|
62
|
+
|
|
63
|
+
## What Claude Can See
|
|
64
|
+
|
|
65
|
+
| Tool | Description |
|
|
66
|
+
|------|-------------|
|
|
67
|
+
| `browser_get_console_logs` | Console output (log, warn, error, info, debug) |
|
|
68
|
+
| `browser_get_network_requests` | Fetch/XHR with status, timing, headers, body |
|
|
69
|
+
| `browser_get_errors` | JS errors and unhandled promise rejections |
|
|
70
|
+
| `browser_get_local_storage` | Read localStorage |
|
|
71
|
+
| `browser_get_session_storage` | Read sessionStorage |
|
|
72
|
+
| `browser_get_cookies` | Read cookies |
|
|
73
|
+
| `browser_get_page_info` | URL, title, viewport, scroll position |
|
|
74
|
+
| `browser_execute_js` | Run arbitrary JS in the page |
|
|
75
|
+
| `browser_get_redux_state` | Redux store state |
|
|
76
|
+
| `browser_get_react_query_cache` | React Query cache |
|
|
77
|
+
| `browser_get_performance` | Page load timing, memory, resources |
|
|
78
|
+
| `browser_get_dom_snapshot` | DOM tree snapshot (CSS selector targeted) |
|
|
79
|
+
| `browser_list_connections` | List connected tabs |
|
|
80
|
+
| `browser_focus_tab` | Focus a specific tab for queries |
|
|
81
|
+
| `browser_clear_all` | Clear all event buffers |
|
|
82
|
+
|
|
83
|
+
## Multi-Tab Support
|
|
84
|
+
|
|
85
|
+
Connect multiple browser tabs simultaneously. Use `browser_focus_tab` to switch which tab Claude is actively querying. The focused tab gets a blue badge; other connected tabs get a gray badge.
|
|
86
|
+
|
|
87
|
+
## Configuration
|
|
88
|
+
|
|
89
|
+
Environment variables:
|
|
90
|
+
|
|
91
|
+
| Variable | Default | Description |
|
|
92
|
+
|----------|---------|-------------|
|
|
93
|
+
| `BROWSER_BRIDGE_PORT` | `8089` | WebSocket server port |
|
|
94
|
+
| `BROWSER_BRIDGE_HTTP_PORT` | `8090` | HTTP server port (serves client.js) |
|
|
95
|
+
|
|
96
|
+
Browser-side (set before client.js loads):
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
window.__BRIDGE_PORT = 8089; // WebSocket port
|
|
100
|
+
window.__BRIDGE_LABEL = "my-tab"; // Custom tab label
|
|
101
|
+
window.__BRIDGE_CAPTURE_BODIES = true; // Capture request/response bodies
|
|
102
|
+
window.__BRIDGE_MAX_BODY_SIZE = 10000; // Max body size in chars
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Framework Plugins
|
|
106
|
+
|
|
107
|
+
All plugins are **dev-only** and **no-op in production**.
|
|
108
|
+
|
|
109
|
+
### Next.js
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
import { withBrowserBridge } from 'browser-bridge-mcp/next';
|
|
113
|
+
export default withBrowserBridge(nextConfig);
|
|
114
|
+
// Composes with other wrappers:
|
|
115
|
+
// export default withSentryConfig(withBrowserBridge(nextConfig), sentryOptions);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Vite
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
import { browserBridge } from 'browser-bridge-mcp/vite';
|
|
122
|
+
export default defineConfig({ plugins: [browserBridge()] });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Express / Connect
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
import { browserBridgeMiddleware } from 'browser-bridge-mcp/middleware';
|
|
129
|
+
app.use(browserBridgeMiddleware());
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## CLI Commands
|
|
133
|
+
|
|
134
|
+
| Command | Description |
|
|
135
|
+
|---------|-------------|
|
|
136
|
+
| `npx browser-bridge-mcp setup` | Register MCP server with Claude Code |
|
|
137
|
+
| `npx browser-bridge-mcp setup --scope project` | Add to `.mcp.json` (team-wide) |
|
|
138
|
+
| `npx browser-bridge-mcp bookmarklet` | Generate bookmarklet HTML file |
|
|
139
|
+
| `npx browser-bridge-mcp snippet` | Print client.js to stdout |
|
|
140
|
+
| `npx browser-bridge-mcp serve` | Start server manually (debugging) |
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT
|
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Browser Bridge MCP — CLI
|
|
5
|
+
*
|
|
6
|
+
* Commands:
|
|
7
|
+
* setup Register MCP server with Claude Code (user scope)
|
|
8
|
+
* setup --scope project Register in .mcp.json (project scope, git-committed)
|
|
9
|
+
* bookmarklet Generate bookmarklet.html and open it
|
|
10
|
+
* snippet Print client.js to stdout for console paste
|
|
11
|
+
* serve Start the MCP server manually (for debugging)
|
|
12
|
+
* (default) Start MCP server via stdio (used by Claude Code)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { execSync } from "child_process";
|
|
16
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
import { dirname, join } from "path";
|
|
19
|
+
|
|
20
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const ROOT = join(__dirname, "..");
|
|
22
|
+
const CLIENT_PATH = join(ROOT, "src", "client.js");
|
|
23
|
+
|
|
24
|
+
const command = process.argv[2];
|
|
25
|
+
|
|
26
|
+
switch (command) {
|
|
27
|
+
case "setup":
|
|
28
|
+
setup();
|
|
29
|
+
break;
|
|
30
|
+
case "bookmarklet":
|
|
31
|
+
bookmarklet();
|
|
32
|
+
break;
|
|
33
|
+
case "snippet":
|
|
34
|
+
snippet();
|
|
35
|
+
break;
|
|
36
|
+
case "serve":
|
|
37
|
+
serve();
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
// Default: start the MCP server (this is what Claude Code invokes via stdio)
|
|
41
|
+
await import("../src/server.mjs");
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Commands
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
function setup() {
|
|
50
|
+
const scopeFlag = process.argv.includes("--scope") && process.argv[process.argv.indexOf("--scope") + 1] === "project";
|
|
51
|
+
|
|
52
|
+
if (scopeFlag) {
|
|
53
|
+
// Project-scope: write .mcp.json
|
|
54
|
+
const mcpConfig = {
|
|
55
|
+
mcpServers: {
|
|
56
|
+
"browser-bridge": {
|
|
57
|
+
command: "npx",
|
|
58
|
+
args: ["-y", "browser-bridge-mcp"],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const mcpPath = join(process.cwd(), ".mcp.json");
|
|
64
|
+
let existing = {};
|
|
65
|
+
try {
|
|
66
|
+
existing = JSON.parse(readFileSync(mcpPath, "utf-8"));
|
|
67
|
+
} catch {
|
|
68
|
+
// File doesn't exist yet
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
existing.mcpServers = existing.mcpServers || {};
|
|
72
|
+
existing.mcpServers["browser-bridge"] = mcpConfig.mcpServers["browser-bridge"];
|
|
73
|
+
|
|
74
|
+
writeFileSync(mcpPath, JSON.stringify(existing, null, 2) + "\n");
|
|
75
|
+
console.log("✓ Added browser-bridge to .mcp.json (project scope)");
|
|
76
|
+
console.log(" Commit .mcp.json so your team gets it automatically.");
|
|
77
|
+
} else {
|
|
78
|
+
// User-scope: use claude mcp add
|
|
79
|
+
try {
|
|
80
|
+
execSync(
|
|
81
|
+
'claude mcp add browser-bridge --transport stdio -- npx -y browser-bridge-mcp',
|
|
82
|
+
{ stdio: "inherit" }
|
|
83
|
+
);
|
|
84
|
+
console.log("\n✓ Browser Bridge MCP registered with Claude Code");
|
|
85
|
+
console.log(" Restart Claude Code to activate.");
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error("Failed to register MCP server. Is Claude Code CLI installed?");
|
|
88
|
+
console.error(" Try: npx browser-bridge-mcp setup --scope project");
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function bookmarklet() {
|
|
95
|
+
const clientJs = readFileSync(CLIENT_PATH, "utf-8");
|
|
96
|
+
|
|
97
|
+
// Basic minification: remove comments and extra whitespace
|
|
98
|
+
const minified = clientJs
|
|
99
|
+
.replace(/\/\*[\s\S]*?\*\//g, "") // block comments
|
|
100
|
+
.replace(/\/\/.*$/gm, "") // line comments
|
|
101
|
+
.replace(/\n\s*\n/g, "\n") // empty lines
|
|
102
|
+
.replace(/^\s+/gm, "") // leading whitespace
|
|
103
|
+
.trim();
|
|
104
|
+
|
|
105
|
+
const bookmarkletUrl = `javascript:${encodeURIComponent(minified)}`;
|
|
106
|
+
|
|
107
|
+
const html = `<!DOCTYPE html>
|
|
108
|
+
<html><head><title>Browser Bridge Bookmarklet</title></head>
|
|
109
|
+
<body style="font-family:system-ui;max-width:600px;margin:40px auto;padding:20px;">
|
|
110
|
+
<h1>Browser Bridge</h1>
|
|
111
|
+
<p>Drag this link to your bookmarks bar:</p>
|
|
112
|
+
<p style="font-size:24px;padding:20px;background:#f0f0f0;border-radius:8px;text-align:center;">
|
|
113
|
+
<a href="${bookmarkletUrl}" style="color:#059669;text-decoration:none;font-weight:bold;">
|
|
114
|
+
Connect to Claude
|
|
115
|
+
</a>
|
|
116
|
+
</p>
|
|
117
|
+
<p style="color:#666;">Click it on any page to connect that tab to Claude Code's Browser Bridge.</p>
|
|
118
|
+
<h2>Or paste in console:</h2>
|
|
119
|
+
<pre style="background:#1e1e1e;color:#d4d4d4;padding:16px;border-radius:8px;overflow-x:auto;font-size:12px;max-height:300px;overflow-y:auto;">${clientJs.replace(/</g, "<").replace(/>/g, ">")}</pre>
|
|
120
|
+
</body></html>`;
|
|
121
|
+
|
|
122
|
+
const outPath = join(process.cwd(), "bookmarklet.html");
|
|
123
|
+
writeFileSync(outPath, html);
|
|
124
|
+
console.log(`✓ Bookmarklet written to ${outPath}`);
|
|
125
|
+
console.log(` (${bookmarkletUrl.length} characters)`);
|
|
126
|
+
|
|
127
|
+
// Try to open in browser
|
|
128
|
+
try {
|
|
129
|
+
const platform = process.platform;
|
|
130
|
+
if (platform === "darwin") {
|
|
131
|
+
execSync(`open "${outPath}"`);
|
|
132
|
+
} else if (platform === "linux") {
|
|
133
|
+
execSync(`xdg-open "${outPath}"`);
|
|
134
|
+
} else if (platform === "win32") {
|
|
135
|
+
execSync(`start "${outPath}"`);
|
|
136
|
+
}
|
|
137
|
+
} catch {
|
|
138
|
+
console.log(" Open bookmarklet.html in your browser to use it.");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function snippet() {
|
|
143
|
+
const clientJs = readFileSync(CLIENT_PATH, "utf-8");
|
|
144
|
+
process.stdout.write(clientJs);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function serve() {
|
|
148
|
+
console.log("Starting Browser Bridge MCP server...");
|
|
149
|
+
console.log(" WebSocket: ws://127.0.0.1:8089");
|
|
150
|
+
console.log(" HTTP (client.js): http://127.0.0.1:8090/client.js");
|
|
151
|
+
console.log(" Press Ctrl+C to stop.\n");
|
|
152
|
+
await import("../src/server.mjs");
|
|
153
|
+
}
|
package/middleware.mjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express/Connect middleware: browserBridgeMiddleware()
|
|
3
|
+
* Injects the browser bridge client script into HTML responses.
|
|
4
|
+
* For non-Next/Vite frameworks (Express, Fastify, etc.).
|
|
5
|
+
*/
|
|
6
|
+
export function browserBridgeMiddleware(options = {}) {
|
|
7
|
+
const httpPort = options.httpPort || 8090;
|
|
8
|
+
return (req, res, next) => {
|
|
9
|
+
const originalEnd = res.end;
|
|
10
|
+
res.end = function (chunk, ...args) {
|
|
11
|
+
if (res.getHeader("content-type")?.includes("text/html") && chunk) {
|
|
12
|
+
const html = chunk.toString();
|
|
13
|
+
chunk = html.replace(
|
|
14
|
+
"</body>",
|
|
15
|
+
`<script src="http://127.0.0.1:${httpPort}/client.js" async></script></body>`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
originalEnd.call(this, chunk, ...args);
|
|
19
|
+
};
|
|
20
|
+
next();
|
|
21
|
+
};
|
|
22
|
+
}
|
package/next.mjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js plugin: withBrowserBridge(nextConfig)
|
|
3
|
+
* Auto-injects the browser bridge client script in development mode.
|
|
4
|
+
* Complete no-op in production.
|
|
5
|
+
*/
|
|
6
|
+
export function withBrowserBridge(nextConfig = {}, options = {}) {
|
|
7
|
+
if (process.env.NODE_ENV !== "development") return nextConfig;
|
|
8
|
+
|
|
9
|
+
const httpPort = options.httpPort || 8090;
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
...nextConfig,
|
|
13
|
+
webpack(config, ctx) {
|
|
14
|
+
// Only inject on client-side build
|
|
15
|
+
if (!ctx.isServer) {
|
|
16
|
+
const { BannerPlugin } = ctx.webpack;
|
|
17
|
+
config.plugins.push(
|
|
18
|
+
new BannerPlugin({
|
|
19
|
+
banner: `
|
|
20
|
+
if (typeof window !== 'undefined' && !window.__browserBridge) {
|
|
21
|
+
var s = document.createElement('script');
|
|
22
|
+
s.src = 'http://127.0.0.1:${httpPort}/client.js';
|
|
23
|
+
s.async = true;
|
|
24
|
+
s.onerror = function() { console.debug('[BrowserBridge] MCP server not running'); };
|
|
25
|
+
document.head.appendChild(s);
|
|
26
|
+
}
|
|
27
|
+
`,
|
|
28
|
+
raw: true,
|
|
29
|
+
entryOnly: true,
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
// Chain with user's webpack config if present
|
|
34
|
+
if (typeof nextConfig.webpack === "function") {
|
|
35
|
+
return nextConfig.webpack(config, ctx);
|
|
36
|
+
}
|
|
37
|
+
return config;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "browser-bridge-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Give Claude Code direct access to your browser - console, network, errors, storage, DOM and more",
|
|
6
|
+
"author": "Mukesh Bishnoi <mukeshb.work@gmail.com>",
|
|
7
|
+
"bin": {
|
|
8
|
+
"browser-bridge-mcp": "./bin/cli.mjs"
|
|
9
|
+
},
|
|
10
|
+
"main": "./src/server.mjs",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./src/server.mjs",
|
|
13
|
+
"./next": "./next.mjs",
|
|
14
|
+
"./vite": "./vite.mjs",
|
|
15
|
+
"./middleware": "./middleware.mjs",
|
|
16
|
+
"./client": "./src/client.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin/",
|
|
20
|
+
"src/",
|
|
21
|
+
"next.mjs",
|
|
22
|
+
"vite.mjs",
|
|
23
|
+
"middleware.mjs"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
27
|
+
"ws": "^8.18.0",
|
|
28
|
+
"zod": "^3.24.0"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"mcp",
|
|
32
|
+
"claude",
|
|
33
|
+
"claude-code",
|
|
34
|
+
"browser",
|
|
35
|
+
"devtools",
|
|
36
|
+
"debugging",
|
|
37
|
+
"console",
|
|
38
|
+
"network"
|
|
39
|
+
],
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/mukeshblackhat/browser-bridge-mcp.git"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/mukeshblackhat/browser-bridge-mcp#readme",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/mukeshblackhat/browser-bridge-mcp/issues"
|
|
51
|
+
}
|
|
52
|
+
}
|