@thehappyboy/opencli-mcp-http
v0.2.0
Published
HTTP MCP server wrapping opencli — managed MCP for Claude Desktop 3p with persistent tool authorization
Maintainers
Readme
opencli-mcp-http
HTTP MCP server wrapping opencli — designed for Claude Desktop 3p managed MCP with persistent tool authorization.
22 browser automation tools that automatically use your existing Chrome login state (cookies, including HttpOnly).
Why HTTP / managed MCP?
Claude Desktop 3p runs in a VM sandbox. Only MCP connections can cross the VM boundary, but standard stdio MCP requires clicking "Allow Once" for every tool call. Managed MCP (HTTP transport) lets you authorize tools once and they stay authorized.
This server exposes the same opencli browser tools over HTTP, so Claude Desktop 3p can connect via URL with persistent authorization.
Architecture
Claude Desktop 3p (VM) ──HTTP──> Express + MCP Streamable HTTP (port 31337)
│
│ POST /command X-OpenCLI: 1
▼
opencli daemon (127.0.0.1:19825)
│
▼
Chrome Extension → BrowserPrerequisites
Install opencli + Chrome extension:
npm install -g @jackwener/opencli # Install the Chrome extension from: # https://chromewebstore.google.com/detail/opencli/ildkmabpimmkaediidaifkhjpohdnifk opencli doctor # verify all greenNode >= 18
Install
npm install -g @thehappyboy/opencli-mcp-http
opencli-mcp-http --install-daemon # installs launchd daemon, auto-starts on loginAfter this, the server is always running at http://127.0.0.1:31337/. You never need to start it manually.
Manual start (for testing)
npx -y @thehappyboy/opencli-mcp-httpDaemon management
# Check status
curl http://127.0.0.1:31337/health
# Stop daemon
launchctl unload ~/Library/LaunchAgents/com.opencli.mcp-http.plist
# Start daemon
launchctl load ~/Library/LaunchAgents/com.opencli.mcp-http.plist
# View logs
tail -f ~/Library/Logs/opencli-mcp-http.logRunning
The server listens on http://127.0.0.1:31337 (all paths route to MCP).
Health check
curl http://127.0.0.1:31337/health
# {"status":"ok","name":"opencli-mcp-http","version":"0.2.0","tools":22}Claude Desktop 3p — Managed MCP Configuration
Add to ~/Library/Application Support/Claude-3p/configLibrary/<YOUR_UUID>.json:
{
"managedMcpServers": [
{
"name": "opencli",
"url": "http://127.0.0.1:31337/",
"toolPolicy": {
"browser_open": "allow",
"browser_navigate": "allow",
"list_tabs": "allow",
"select_tab": "allow",
"close_tab": "allow",
"browser_state": "allow",
"browser_get": "allow",
"browser_find": "allow",
"browser_frames": "allow",
"browser_screenshot": "allow",
"browser_extract": "allow",
"browser_network": "allow",
"browser_wait": "allow",
"browser_click": "allow",
"browser_type": "allow",
"browser_fill": "allow",
"browser_select": "allow",
"browser_hover": "allow",
"browser_keys": "allow",
"browser_scroll": "allow",
"browser_back": "allow",
"exec_in_tab": "allow"
}
}
]
}After configuring, restart Claude Desktop 3p. All 22 opencli tools appear with persistent authorization.
Claude Code — Plugin (optional)
This package also works as a Claude Code plugin via stdio:
claude --plugin-dir /path/to/opencli-mcp-httpOr register directly:
claude mcp add --scope user opencli-http -- node /path/to/opencli-mcp-http/bin/server.jsTools (22)
Tab management
| Tool | Description |
|---|---|
| browser_open(url) | Open URL in a NEW tab. Chrome auto-attaches login cookies. |
| browser_navigate(url, tab_id) | Navigate existing tab to a new URL. |
| list_tabs() | List all tabs in the automation window. |
| select_tab(tab_id) | Make a tab active. |
| close_tab(tab_id) | Close a tab. |
Inspection
| Tool | Description |
|---|---|
| browser_state(tab_id) | Get URL/title/viewport/scroll + 200 interactive elements with refs, compounds for selects/date inputs. |
| browser_get(what, target?, tab_id) | Get title / url / html / text-of-selector. |
| browser_find(css, limit?, text_max?, tab_id) | CSS-selector search with visibility info. |
| browser_frames(tab_id) | List cross-origin iframes. |
| browser_screenshot(tab_id?) | PNG of tab (optionally select by tab_id first). |
Content & Network (NEW in v0.2.0)
| Tool | Description |
|---|---|
| browser_extract(tab_id, selector?, chunk_size?, start?) | Extract page content as structured text with chunked reading. Auto-detects Zhihu/Xiaohongshu/article containers. |
| browser_network(tab_id, inject?, filter?, clear?) | Inject fetch/XHR interceptors, retrieve captured API responses. |
| browser_wait(tab_id, type, value, timeout?) | Wait for selector/text/time with configurable timeout. |
Interaction
| Tool | Description |
|---|---|
| browser_click(target, tab_id) | Click element by CSS selector. |
| browser_type(target, text, tab_id) | Set input/textarea value with proper events. |
| browser_fill(target, text, tab_id) | Set input value exactly + verify (more reliable than type). NEW in v0.2.0. |
| browser_select(target, option, tab_id) | Pick <select> option with available-options fallback. |
| browser_hover(target, tab_id) | Mouse hover (trigger menus, tooltips). NEW in v0.2.0. |
| browser_keys(key, tab_id) | Send keyboard key. NEW in v0.2.0. |
| browser_scroll(direction, amount?, tab_id) | Scroll up/down, returns new scrollY. |
| browser_back(tab_id) | Browser history back. |
Core
| Tool | Description |
|---|---|
| exec_in_tab(tab_id, code) | Execute arbitrary JS. Use fetch(..., {credentials:'include'}) to call same-origin APIs with full login state. |
Changelog
v0.2.0
- NEW:
browser_extract— structured content extraction with chunked reading, auto-detects content containers - NEW:
browser_network— fetch/XHR interception for API capture - NEW:
browser_wait— wait for selector/text/time conditions - NEW:
browser_fill— reliable input with value verification (contenteditable support) - NEW:
browser_hover— mouse hover for menus and tooltips - NEW:
browser_keys— keyboard key dispatch - IMPROVED:
browser_state— 200 element limit, deduplication by position, compounds for selects/dates, scroll info - IMPROVED:
browser_screenshot— accepts optional tab_id - IMPROVED:
browser_click— instant scrollIntoView, returns tag name - IMPROVED:
browser_select— returns available options on mismatch
Typical workflow
User: "Read this Zhihu article: https://zhuanlan.zhihu.com/p/..."
LLM:
1. page = browser_open("https://zhuanlan.zhihu.com/p/...")
2. browser_wait(tab_id=page, type="selector", value=".Post-RichTextContainer")
3. browser_extract(tab_id=page)
→ structured text with next_start_char for chunked reading
4. close_tab(tab_id=page)Environment variables
| Variable | Default | Description |
|---|---|---|
| PORT | 31337 | HTTP server port |
Limitations
- Automation window only —
list_tabsreturns tabs in opencli's automation window, not your daily Chrome tabs. - Single Chrome profile — uses the profile where the opencli extension is installed.
- localhost only — server binds to
127.0.0.1for security. For VM access, configure port forwarding or use a reverse proxy. - Network capture is JS-level —
browser_networkintercepts fetch/XHR after injection; it won't capture initial page-load requests.
License
MIT
