๐ฆ Undetectable browser automation an LLM can drive โ Camoufox stealth + a 17-tool MCP server. Human-like behavior, session persistence, CLI & Python API.
This MCP server provides undetectable browser automation for LLMs, using Camoufox stealth and 17 tools to let AI agents navigate, click, type, and scr...
91@mcp.tool()
92@_mcp_tool
93async def browser_open(url: str) -> dict:
94 """Navigate to a URL and return a snapshot of the page with all interactive elements."""
95 _, page, _ = await _ensure_browser()
96 await page.goto(url)
97 return await _auto_snapshot(page)// Local-with-credentials MCP; requires compromised LLM to exploit, but allows reading arbitrary local files.
1def _get_aes_key() -> bytes:
2 import win32crypt
3 state = json.loads(LOCAL_STATE.read_text(encoding="utf-8"))
4 encrypted_key = base64.b64decode(state["os_crypt"]["encrypted_key"])
5 encrypted_key = encrypted_key[5:]
6 return win32crypt.CryptUnprotectData(encrypted_key, None, None, None, 0)[1]
7
8def _decrypt_value(encrypted: bytes, key: bytes) -> str:
9 ...
10 return AESGCM(key).decrypt(nonce, ciphertext, None).decode("utf-8", errors="replace")
11
12def extract(output: Path | None = None) -> list[dict]:
13 key = _get_aes_key()
14 ...
15 cookies.append({
16 "name": r["name"],
17 "value": value,
18 ...
19 })
20 dest.write_text(json.dumps(cookies, indent=2, ensure_ascii=False), encoding="utf-8")// Local-with-credentials MCP; requires compromised LLM to exploit, but the script is present in the codebase and can be invoked.
218@mcp.tool()
219@_mcp_tool
220async def browser_evaluate(js: str) -> dict:
221 """Execute arbitrary JavaScript in the page context and return the result."""
222 _, page, _ = await _ensure_browser()
223 result = await evaluate(page, js)
224 return {"result": result}// Local-with-credentials MCP; requires compromised LLM to exploit, but the tool provides direct arbitrary code execution capability.
227@mcp.tool()
228@_mcp_tool
229async def browser_save_session(name: str = "default") -> dict:
230 """Save current browser cookies to a named session file for later restoration."""
231 _, page, _ = await _ensure_browser()
232 cfg = BrowserConfig.from_env()
233 path = cfg.profile_dir.parent / name / "cookies.json"
234 path.parent.mkdir(parents=True, exist_ok=True)
235 await save_cookies(page, path)
236 return {"path": str(path)}// Local-with-credentials MCP; requires compromised LLM to exploit, but allows writing files outside intended directory.
239@mcp.tool()
240@_mcp_tool
241async def browser_load_session(name: str = "default") -> dict:
242 """Load cookies from a previously saved named session into the current browser context."""
243 _, page, _ = await _ensure_browser()
244 cfg = BrowserConfig.from_env()
245 path = cfg.profile_dir.parent / name / "cookies.json"
246 await load_cookies(page, path)
247 return {"ok": True}// Local-with-credentials MCP; requires compromised LLM to exploit, but allows reading arbitrary files.
91@mcp.tool()
92@_mcp_tool
93async def browser_open(url: str) -> dict:
94 """Navigate to a URL and return a snapshot..."""
95 _, page, _ = await _ensure_browser()
96 await page.goto(url)
97 return await _auto_snapshot(page)// Local-with-credentials MCP; requires compromised LLM to exploit, but allows SSRF to internal services.
89@mcp.tool()
90@_mcp_tool
91async def browser_open(url: str) -> dict:
92 """Navigate to a URL and return a snapshot..."""
93 _, page, _ = await _ensure_browser()
94 await page.goto(url)
95 return await _auto_snapshot(page)
96
97@mcp.tool()
98@_mcp_tool
99async def browser_evaluate(js: str) -> dict:
100 """Execute arbitrary JavaScript..."""
101 _, page, _ = await _ensure_browser()
102 result = await evaluate(page, js)
103 return {"result": result}// Local-with-credentials MCP; requires compromised LLM to exploit, but the broad scope increases attack surface.