Browserctl MCP vs Ghostlight

A side-by-side look at the Browserctl MCP and Ghostlight MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.

Browserctl MCP logoBrowserctl MCPBrowser Automation · Local subprocess (stdio)Universal Browser Control Protocol & MCP Server for AI Agents and Developers63GoodAuth: no auth requiredGhostlight logoGhostlightBrowser Automation · Local subprocess (stdio)Drive your real logged-in browser from any MCP client. Governed or wide open, one portable binary.63GoodAuth: not declared

Verdict: choose Browserctl MCP for browser automation work as a local process; choose Ghostlight for browser automation as a local process. You can also run both side by side in one mcpServers block.

Which MCP server should you choose?

Browserctl MCP logoChoose Browserctl MCP when

  • You need dedicated capabilities in the Browser Automation domain.
  • You prefer a local stdio subprocess transport.
  • Its auth model fits you: No auth required.
  • You want tools like browser_load_tools, browser_list_available_tools, browser_action.
Explore Browserctl MCP

Ghostlight logoChoose Ghostlight when

  • You need dedicated capabilities in the Browser Automation domain.
  • You prefer a local stdio subprocess transport.
  • You want tools like browser_tabs, browser_navigate, browser_history.
Explore Ghostlight

Feature & specification comparison

Rows where the two servers differ are marked.

SpecBrowserctl MCP logoBrowserctl MCPGhostlight logoGhostlight
CategoryBrowser AutomationBrowser Automation
Quality signal63/100 · Good63/100 · Good
Install commandConfirmedConfirmed
TransportLocal subprocess (stdio)Local subprocess (stdio)
AuthNo auth requiredNot declared
PricingFreeNot declared
Required env varsNone listedNone listed
Verified ownerCommunity listingCommunity listing
GitHub stars01
Directory activity 1 views 0 installs 0 upvotes 1 views 0 installs 0 upvotes
Tools2523

Tools & capabilities

Browserctl MCP tools 25

  • browser_load_tools[EXTEND] Load a profile of tools that are not currently visible: network (capture every request, read response bodies, export a HAR, wait for network idle), cookies (read, set, delete), storage (localStorage, sessionStorage), console (console messages and page errors), cdp (raw CDP, coordinate input, audit), record (record and replay), tabs (windows, groups, visibility), advanced (a11y tree, PDF, history, element screenshots), system (a shell command on the bridge host, not the page), or all. browser_action reaches any single action without loading its profile; this is for when you want the tools themselves.
  • browser_list_available_tools[EXTEND] Every capability this server has, loaded or not, with its parameters. Use it before assuming something is missing; browser_load_tools turns any of it on.
  • browser_action[EXTEND] Dispatch any protocol action by name, including ones whose tool is not loaded: browser_action({action, params}). Called with no arguments it prints the catalogue — every action the bridge will dispatch. Check it before concluding something is impossible.
  • browser_status[SESSION] Whether the bridge is reachable, the daemon's state, and whether the Chrome extension is connected. Call it when a command failed for a reason that sounds like infrastructure rather than the page; browser_start brings the daemon back.
  • browser_snapshot[READ] A text census of the page's controls: one line per element with a stable 'ref' to act on, in reading order. Start here to see what is on a page. scope: 'viewport' (default) or 'all' — every element currently in the DOM, worth it whenever a COUNT or a COMPLETE list is the answer. 'all' is not everything the page can show: feeds and virtualised lists keep most rows out of the DOM until something is clicked, and 'hiddenContent' names the control that loads them. The census hoists key inputs and search fields to the top, and dense repetitive runs are folded; each folded control comes back in 'folded' as a line '@ref "text" -> href'. What it withheld comes back as data: window/next (paging), offscreenCount, foldedCount, duplicateCount, structure (a ref per region), pageState.openDialogs, hiddenContent. It does NOT carry pixel geometry, class names or attributes: browser_extract({selector, fields}) returns those for every match, and is cheaper for a list's data.
  • browser_read_page[READ] The accessibility tree as indented text — which control sits inside which group, form or region — with a ref on each interactive element. Structure, not prose. Reach for browser_snapshot first unless nesting is the question, and for browser_get_property when what you want is a region's text. Narrow with target (one subtree) and mode: 'all' (include non-interactive nodes); depth defaults to 60 because a React SPA nests 25-45 levels deep, and a clipped walk reports 'depthClipped' rather than looking like an empty page.
  • browser_find[READ] Find things on the page and get a ref back for each. in: 'controls' (default) matches interactive elements by accessible name, text, placeholder, aria-label or title, and 'matchedBy' says which of those hit; in: 'text' searches the page's prose instead and each match carries 'nearestInteractive'. SCOPE differs by index and every result names it in 'searchedScope'. Controls reads the WHOLE page — top frame, open Shadow DOM, iframes — on screen or not, so its count can differ from browser_snapshot's (viewport by default); a sub-frame match carries a ref like 'f3:ref_5', passed back verbatim. Text reads the top frame and Shadow DOM, NOT iframes. Takes a CSS 'selector' instead of 'query' when that is what you have — the cheap way to get a ref for something that just appeared, without another browser_snapshot. A zero-match answers with 'nearest': labels that differ only by case or diacritics, with their refs, plus the page's own vocabulary — so a one-character transcription error costs one call, not four. A label cut short carries 'truncatedBy' and the read that returns the rest.
  • browser_click[ACT] Click an element by 'target' (ref '@ref_1', CSS selector, visible text, or snapshot index). Waits for the DOM to settle and reports what changed in 'effect' and 'resolved'. If the click navigates, the response reports urlChanged instead of failing on a stale ref.
  • browser_type[ACT] Put text into any editable target — input, textarea, contenteditable, or rich-text editor. method: 'set' (default, native setters so React and Vue see it) | 'type' | 'paste' (for large payloads and AST editors). On an autocomplete field, effect.suggestions lists the options the text opened, each with a ref to click: picking one is what commits the value. For a <select> dropdown, use browser_select_option.
  • browser_fill_form[ACT] Set several form controls in one round-trip: text fields, checkboxes, radios and <select>s. On failure, stops and reports the failed index and which fields were already written. Optionally clicks submitTarget afterwards.
  • browser_select_option[ACT] Select one or more options in a <select> element. Values are matched by value first, then by visible label.
  • browser_scroll[ACT] Scroll the page, or a specific container when the window itself does not move — a drawer, a table, an overflow:auto div. A container that cannot scroll is refused with the reason, rather than reported as a scroll that did nothing. To see what is below without moving, browser_snapshot({scope: 'all'}).
  • +13 more on the listing page

Ghostlight tools 23

  • browser_tabsList, focus, or close this session's tabs. List gives fresh handles from the live browser; with no tab yet it needs none and names those connected.
  • browser_navigateGo to an HTTP(S) URL. Reuses the obvious tab; new_tab true opens a new one.
  • browser_historyGo back or forward, or reload. A new document invalidates target_ and view_ handles, so collect fresh ones.
  • browser_windowSet a tab's zoom or resize its browser window. Either invalidates view_ handles, so take a fresh screenshot before coordinate work.
  • browser_readRead visible page text, including open shadow roots and frames, or one target. To act, get handles from browser_inspect or browser_find.
  • browser_inspectInspect controls or page structure for fresh target_ handles. Scope document returns the outline as a bounded tree, without handles. Form controls also carry their value and what they accept: options, type, limits, hint and group.
  • browser_findFind targets by visible or accessible text and get fresh target_ handles. Fastest when you know the label. Option text finds its dropdown.
  • browser_screenshotCapture the viewport, full page, one target, or a magnified region; returns a view_ handle for coordinate calls.
  • browser_clickClick a target_ handle, a control found by selector, or a point in a view_ screenshot. Needs action; a selector lookup or expect check also needs read. Prefer a target.
  • browser_scrollScroll the page (default down, medium), reveal a target_, or wheel-scroll at a point in a view_ screenshot.
  • browser_hoverHover a target_ handle or a point in a view_ screenshot.
  • browser_fill_formFill 1 to 30 fields in one call; needs write even for unsent drafts. Nothing submits unless submit_target names the control. A value a control cannot take is refused before any field changes, with what it accepts. For credentials, set user_authorized_credentials only on the user's explicit instruction.
  • +11 more on the listing page

Ready-to-paste client configs

Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.

Browserctl MCP

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "browserctl-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "-p",
        "browserctl-mcp",
        "browserctl-mcp"
      ]
    }
  }
}

Ghostlight

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "ghostlight": {
      "command": "npx",
      "args": [
        "-y",
        "ghostlight"
      ]
    }
  }
}

Frequently asked questions

Browserctl MCP is categorized under Browser Automation and uses a local stdio subprocess. Ghostlight belongs to Browser Automation and uses a local stdio subprocess. Pick Browserctl MCP for browser automation work and Ghostlight for browser automation.

Copy the mcpServers block from the config section on this page into your client's config (for example claude_desktop_config.json or ~/.cursor/mcp.json), then fully restart the client.

Browserctl MCP is listed as free. Auth: no auth required. Ghostlight has no declared pricing — check the project's own site. If a server needs environment variables such as API keys, define them under the env key in your client's MCP config.

Yes. MCP clients support multiple servers: add browserctl-mcp and ghostlight as separate keys in the same mcpServers object, and your assistant will call tools from either one.

On AllMCPs, Browserctl MCP has a quality signal of 63/100 (Good) with 1 views, 0 installs and 0 GitHub stars. Ghostlight has 63/100 (Good) with 1 views, 0 installs and 1 GitHub stars.