junso-browser 0.2.12 → 0.3.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/README.md +59 -2
- package/bin/junso-browser.js +11 -1
- package/dist/mcp.js +50 -41
- package/dist/server.js +90 -9
- package/package.json +2 -1
- package/scripts/install.sh +216 -0
package/README.md
CHANGED
|
@@ -66,7 +66,60 @@ Open `http://<host>:8790/view/<profile>?token=<token>` in any browser to **watch
|
|
|
66
66
|
|
|
67
67
|
## Optional browser MCP
|
|
68
68
|
|
|
69
|
-
junso-browser
|
|
69
|
+
junso-browser ships the **same browser MCP** over two transports — the way to give any MCP client (Jun, Codex, Claude Desktop) browser tools without a local browser. It drives profiles through the host's CDP gateway, so it works whether junso-browser is local or remote.
|
|
70
|
+
|
|
71
|
+
### HTTP transport — no local install (recommended)
|
|
72
|
+
|
|
73
|
+
Since 0.3.0 the host exposes the MCP at **`POST /mcp`** (Streamable HTTP), so a client adds junso-browser as a plain URL with nothing installed locally. Token-authed via `Authorization: Bearer <token>` (also accepts `x-junso-token: <token>` or `?token=<token>` in the URL).
|
|
74
|
+
|
|
75
|
+
**The auth header config differs per client** — this is the #1 setup gotcha:
|
|
76
|
+
|
|
77
|
+
**Claude Code** (`.mcp.json` at the repo root, or `~/.claude.json` for user scope) — uses a `headers` object:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"mcpServers": {
|
|
82
|
+
"junso-browser": {
|
|
83
|
+
"type": "http",
|
|
84
|
+
"url": "http://<host>:8790/mcp",
|
|
85
|
+
"headers": { "Authorization": "Bearer <token>" }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Codex / Jun** (`config.toml`) — uses **`http_headers`** (NOT `headers` — Codex silently ignores a `headers` block, connects with no auth, gets a 401, and hangs at `startupState:"starting"`):
|
|
92
|
+
|
|
93
|
+
```toml
|
|
94
|
+
# may also require this at the top level on some builds:
|
|
95
|
+
experimental_use_rmcp_client = true
|
|
96
|
+
|
|
97
|
+
[mcp_servers.junso-browser]
|
|
98
|
+
url = "http://<host>:8790/mcp"
|
|
99
|
+
|
|
100
|
+
[mcp_servers.junso-browser.http_headers]
|
|
101
|
+
Authorization = "Bearer <token>"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Codex also supports `bearer_token_env_var = "MY_TOKEN_ENV"` and `env_http_headers` to source the token/headers from env vars instead of hardcoding.
|
|
105
|
+
|
|
106
|
+
Common to all clients:
|
|
107
|
+
- Append `?profile=<id>` to the URL to set the session's initial profile (else `default`, auto-created).
|
|
108
|
+
- Behind the Caddy TLS front, use `https://<host>:8443/mcp` (or whatever subdomain reverse-proxies to `127.0.0.1:8790`).
|
|
109
|
+
- The MCP runs in-process on the host, one isolated server per session (`Mcp-Session-Id` header), idle-reaped after 10 min. A plain `GET /mcp` → **405** (the bridge is request/response only, no server→client SSE) — that's expected, not an error.
|
|
110
|
+
- `browser_solve_captcha`'s 2captcha key is supplied **by the connector**: `x-twocaptcha-key` header or `?twocaptcha=` (keeps the secret with the client).
|
|
111
|
+
|
|
112
|
+
**Troubleshooting:** if the client hangs on "loading" / shows a "Connect"/OAuth button / sits at `authStatus:"unsupported"`, the token isn't reaching the host (wrong header key — see Codex `http_headers` above) → it 401s and never completes the handshake. Verify the host independently with a raw POST:
|
|
113
|
+
```bash
|
|
114
|
+
curl -i -X POST http://<host>:8790/mcp \
|
|
115
|
+
-H "Authorization: Bearer <token>" \
|
|
116
|
+
-H "Content-Type: application/json" \
|
|
117
|
+
-H "Accept: application/json, text/event-stream" \
|
|
118
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
|
|
119
|
+
```
|
|
120
|
+
A working host returns **200** with an `mcp-session-id` header and `serverInfo: junso-browser`. If curl works but the client doesn't, the problem is the client's auth-key syntax, not the host. Also confirm you're hitting an actual junso-browser host: `GET /health` returns JSON `{"name":"junso-browser",…}` — if it returns HTML, that hostname is serving a different app (e.g. the Jun web UI) and junso-browser isn't routed there.
|
|
121
|
+
|
|
122
|
+
### stdio transport — `junso-browser-mcp` bin
|
|
70
123
|
|
|
71
124
|
Add it to a client's MCP config (once `junso-browser` is installed globally):
|
|
72
125
|
|
|
@@ -79,7 +132,11 @@ Add it to a client's MCP config (once `junso-browser` is installed globally):
|
|
|
79
132
|
|
|
80
133
|
(or `"command": "bunx", "args": ["-y", "junso-browser-mcp"]` without a global install).
|
|
81
134
|
|
|
82
|
-
Tools
|
|
135
|
+
### Tools
|
|
136
|
+
|
|
137
|
+
Drive: `browser_status`, `browser_navigate`, `browser_snapshot`, `browser_click`, `browser_fill`, `browser_type`, `browser_press`, `browser_select`, `browser_scroll`, `browser_wait`, `browser_read`, `browser_eval`, `browser_screenshot`, `browser_exec`. Identity: `browser_list_profiles`, `browser_switch_profile`, `browser_create_profile`. Proxy/IP: `browser_get_proxy`, `browser_set_proxy`, `browser_exit_ip`, `browser_rotate_proxy`, `browser_probe_ip`. CAPTCHA: `browser_solve_captcha`.
|
|
138
|
+
|
|
139
|
+
The active profile (env `JUNSO_BROWSER_PROFILE` for stdio / `?profile=` for HTTP, default `default`) is auto-created on the host if missing; `browser_switch_profile` changes identity at runtime. `browser_exit_ip` returns the live exit IP + geo health (`kind`, `tzMismatch`); `browser_rotate_proxy` draws a fresh sticky IP and re-syncs the fingerprint — the host carries standing login `instructions` so clients follow the residential-IP → health-check → one-attempt-per-IP recipe automatically.
|
|
83
140
|
|
|
84
141
|
## Status
|
|
85
142
|
|
package/bin/junso-browser.js
CHANGED
|
@@ -18,9 +18,19 @@ if (cmd === "version" || cmd === "--version" || cmd === "-v") {
|
|
|
18
18
|
console.log(require(path.join(root, "package.json")).version);
|
|
19
19
|
} else if (cmd === "mcp") {
|
|
20
20
|
await import(path.join(root, "dist", "mcp.js")); // also available as `junso-browser-mcp`
|
|
21
|
+
} else if (cmd === "setup" || cmd === "install") {
|
|
22
|
+
// Run the installer (Chromium libs, cloak prefetch, token, optional systemd) against
|
|
23
|
+
// THIS already-installed package. Forwards flags, e.g. `junso-browser setup --systemd
|
|
24
|
+
// --host 0.0.0.0 --public-url ws://IP:8790`. See scripts/install.sh for flags.
|
|
25
|
+
const script = path.join(root, "scripts", "install.sh");
|
|
26
|
+
const proc = Bun.spawn(["bash", script, "--no-install", ...process.argv.slice(3)], {
|
|
27
|
+
cwd: root,
|
|
28
|
+
stdio: ["inherit", "inherit", "inherit"],
|
|
29
|
+
});
|
|
30
|
+
process.exit(await proc.exited);
|
|
21
31
|
} else if (cmd === "start" || cmd === undefined) {
|
|
22
32
|
await import(path.join(root, "dist", "server.js"));
|
|
23
33
|
} else {
|
|
24
|
-
console.error(`Unknown command: ${cmd}\nUsage: junso-browser [start|mcp|version]`);
|
|
34
|
+
console.error(`Unknown command: ${cmd}\nUsage: junso-browser [start|mcp|setup|version]`);
|
|
25
35
|
process.exit(1);
|
|
26
36
|
}
|