Tethernet MCP Server
Claude browser co-pilot — guides you step by step through complex web workflows in your real logged-in browser.
This is the MCP server (1 of 2). It connects Claude Code or Claude Desktop to your browser via the Model Context Protocol (stdio transport).
The browser extension is also required. Install it from the Tethernet extension repository.
Supports Chrome and Firefox.
Quick Start
Claude Code
claude mcp add tethernet --scope user -- npx -y @drbenedictporkins/tethernet-mcp
Claude Desktop
Edit your config file and add to mcpServers:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"tethernet": {
"command": "npx",
"args": ["-y", "@drbenedictporkins/tethernet-mcp"]
}
}
}
Restart Claude Desktop after editing.
After installing
Install the browser extension, open the Tethernet popup, and enter the port shown by get_connection_info.
Development
npm run dev # Hot reload (tsx watch)
npm run build # Compile TypeScript
npm test # Run tests (vitest)
MCP Tools
Getting Started
get_started— Call first. Returns behavioral instructions and browser-specific notes (SPA detection, click escalation, batching).
Connection
get_connection_info— WebSocket URL/port to enter in the extension popupget_connection_status— Extension connected status, tab count, port
Tab Management
list_tabs— List all open tabs with URLs and titlesget_active_tab— Get the currently active tabswitch_tab— Switch to a tab by IDcreate_tab— Open a new tab with optional URLclose_tab— Close a tablist_frames— List iframes in a page
Navigation
navigate— Navigate to a URLreload_page— Reload the page (with optional cache bypass)go_back/go_forward— Browser history navigationwait_for_navigation— Wait for a page load to completewait_for_element— Wait for a CSS selector to appear in the DOMwait_for_text— Wait for specific text to appear on the pagewait_for_url— Wait for the tab URL to contain a substring (SPA-safe)wait_for_download— Wait for a file download to complete. Returns filename, URL, MIME type, size. Call immediately after triggering the download.
DOM Inspection
dom_stats— Element count, depth, HTML size — call before fetching full HTMLget_dom_structure— Progressive DOM tree at controlled depthget_page_content— Full page HTML (use dom_stats first to check size)get_page_text— Readable text extraction. Modes:full,article,readable,readabilityget_clean_content— Navigate to a URL in the user's authenticated browser and return clean extracted markdown via Mozilla Readability. Strips nav, ads, and boilerplate. Use for auth-walled pages (court records, license lookups, people-search sites).
Element Interaction
click_element— Click a DOM element by CSS selector or tref_N handlenative_click— OS-level mouse click (isTrusted: true). Use when synthetic events are ignored by SPAs. macOS only.type_text— Type into an input (with optional clear)fill_form— Fill multiple form fields at oncepress_key— Fire keyboard events (Enter, Tab, Escape, arrow keys, modifier combos)select_option— Set a<select>dropdown by value or indexset_checkbox— Check or uncheck a checkbox/radiohover_element— Dispatch mouseover/mouseenter to reveal dropdowns or tooltipsfocus_element— Move focus to an element before key inputscroll_to— Scroll to a position or elementhandle_dialog— Install an auto-responder foralert/confirm/promptdialogs. Call before the action that triggers the dialog. Call withdrain:trueto read and clear the log.upload_file— Set a file on an<input type="file">via DataTransfer. Provide content as a string (text) or base64 (base64). Does not open the native file chooser.
Element Discovery
find— Natural language element search. Returns tref_N handles. Use when you don't know the CSS selector.get_ref— Register a specific element by selector and get a stable tref_N handleget_element— Inspect a single element: tag, text, value, bounds, visibility, attributesget_accessibility_tree— Compact semantic tree with tref_N handles. Usefilter: "interactive"first.
Batch Execution
browser_batch— Execute 2+ browser actions in a single round-trip. Default for any predictable multi-step sequence.
Screenshots
take_screenshot— Capture page or element. Saves to/tmp, returns file path (useReadin Claude Code). SetreturnBase64: truefor inline image in Claude Desktop. Supports crop, scale, format.
Script Execution
execute_script— Run JavaScript in page context with full DOM access. Large payloads blocked by default; usepreview: trueorforce: true.fetch_with_session— Send an HTTP request from within the active tab, automatically including that tab's cookies and auth. Use for probing authenticated APIs without sharing credentials.
Audit
run_lighthouse— Run a Lighthouse-style audit (performance, accessibility, SEO, best-practices) on the current tab. No headless browser required. Returns 0–100 scores with per-check details.
Cookies & Storage
get_cookies/set_cookie— Read/write cookies (including HttpOnly on Firefox)browser_storage_get/browser_storage_set/browser_storage_list/browser_storage_delete— Persistent extension storage. Survives browser restarts. Use for site maps, selectors, automation workarounds.
Network Capture
capture_network— Capture HTTP traffic for a duration. Chrome: auto-captures response bodies. Firefox: requires DevTools (F12) open.start_network_capture/stop_network_capture— Non-blocking capture for long-running monitoringget_capture— Retrieve capture data. Modes:summary,slim,fullfind_in_capture— Search capture for a substring or regex. Cheaper than pulling full data.clear_capture— Clear the in-memory capture buffer
Capture (On-demand)
capture_console— Intercept console output for a durationcapture_errors— Listen for JS errors and unhandled promise rejectionscapture_websocket— Intercept WebSocket messages for new connections during capture window
Configuration
Optional environment variables:
| Variable | Default | Description |
|---|---|---|
TETHERWEB_HOST |
127.0.0.1 |
WebSocket bind address |
TETHERWEB_VISION_URL |
(disabled) | Ollama-compatible vision endpoint — if set, take_screenshot returns extracted text instead of image |
TETHERWEB_VISION_MODEL |
qwen2.5vl:7b |
Vision model name |
Architecture
Claude Code/Desktop ──stdio──► MCP Server (Node.js) ──WebSocket──► Browser Extension
(dynamic port, OS-assigned)
Each session spawns its own server process with its own WebSocket port — explicit 1:1 binding.
Extension Protocol
Commands (server → extension):
{ "action": "click_element", "params": { "tabId": 1, "selector": "#btn" }, "requestId": "uuid" }
Responses (extension → server):
{ "requestId": "uuid", "result": { "clicked": true }, "error": null }
Session logs: $TMPDIR/tethernet-mcp-logs/session-<timestamp>.jsonl