1. Conduid
  2. Browser
  3. Mare Browser
MCP server · Browser

Mare Browser

Lean, LLM-first browser automation MCP server. Gives Claude, OpenCode, or any MCP client a real browser to navigate, interact with, and debug web apps.

37Low

Scored 6 months ago · breakdown

About Mare Browser

Mare Browser is an MCP server in the Browser category: lean, LLM-first browser automation MCP server. Gives Claude, OpenCode, or any MCP client a real browser to navigate, interact with, and debug web apps.

Install

Claude Code
claude mcp add mare-browser -- npx -y mare-browser-mcp
npx
npx -y mare-browser-mcp

This server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.

Ask AI

✦

Ask AI about Mare Browser

Powered by Claude · Grounded in docs

I know everything about Mare Browser. Ask me about installation, configuration, usage, or troubleshooting.

Security checks

  • ✓README presentThe repository ships documentation.

5 checks have not been run yet.

README

mare-browser-mcp

A lean, LLM-first browser automation MCP server. Gives Claude (or any MCP client) a real Chromium browser to navigate, interact with, and debug web apps — without the overhead of raw Playwright APIs.

Built with Playwright + MCP SDK. One server = one browser session = one LLM.

Free to use. If it saves you time, buy me a coffee ☕


Install (recommended)

Prerequisites: Node.js 18+, pnpm

git clone https://github.com/emadklenka/mare_browser_mcp
cd mare_browser_mcp
pnpm install
npx playwright install chromium

This is the fastest way to run the server — starts instantly with no registry lookups.


Alternative installs

Global install — no cloning, still fast:

pnpm add -g mare-browser-mcp
npx playwright install chromium

Register with Claude Code

If you cloned the repo, the setup script does it for you:

pnpm run setup

That's it. The script detects the correct path automatically and registers the MCP with Claude Code. Restart Claude Code and the browser tools are ready.

Manual config — add to ~/.claude.json under mcpServers:

{
  "mcpServers": {
    "mare-browser": {
      "command": "node",
      "args": ["/absolute/path/to/mare_browser_mcp/src/index.js"],
      "env": { "HEADLESS": "false" }
    }
  }
}

If installed globally:

{
  "mcpServers": {
    "mare-browser": {
      "command": "mare-browser-mcp",
      "env": { "HEADLESS": "false" }
    }
  }
}

Register with OpenCode

Add this to ~/.config/opencode/opencode.json (global) or opencode.json (project root):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mare_browser_mcp": {
      "type": "local",
      "command": [
        "node",
        "/absolute/path/to/mare_browser_mcp/src/index.js"
      ]
    }
  }
}

If installed globally:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mare_browser_mcp": {
      "type": "local",
      "command": ["mare-browser-mcp"]
    }
  }
}

Tools

browser_navigate(url, clear_logs?)

Navigate to a URL. Pass clear_logs: true when starting a new task to wipe stale console/network/dialog history.

browser_act(commands[])

Run a sequence of actions in one call. Supported actions:

action required params optional params what it does
click selector button (left/right/middle) Click an element. Use button: "right" for context menus
hover selector Hover over an element — triggers tooltips, dropdown menus, hover states
drag selector target or offsetX/offsetY Drag an element to another element (target) or by pixel offset (for resizing, sliders)
clicklink text Click a link/button by its visible text
fill selector, value Type into an input (clears first)
select selector, value Select a dropdown option
keypress key Press a key (e.g. Enter, Tab, Escape)
waitfor selector timeout Wait until element appears
scrollto selector Scroll element into view
wait ms Pause for N milliseconds
clearconsole — Clear console log buffer

browser_debug()

Start here when something goes wrong. Returns in one call:

  • Current URL and page title
  • Console logs (filterable by type: error, warning, log, pageerror)
  • Network requests with: method, URL, query params, request body, request headers (auth masked), status code, response body (JSON), and duration_ms timing
  • Dialog history (alert/confirm/prompt — auto-accepted, text captured)

Filter with url_filter, method_filter, console_types, or last_n.

browser_query(selector, all?, fields?, visible_only?, limit?, count_only?)

Read the DOM without a screenshot. Query any element by CSS selector.

param what it does
all Return all matching elements (default: first only)
fields Pick fields: text, value, visible, disabled, className, href, innerHTML
visible_only Filter to visible elements only — recommended for broad selectors
limit Cap the number of results (e.g. 10) to prevent huge payloads
count_only Just return the count — fast way to check "how many rows?" without fetching data

browser_eval(code)

Escape hatch for anything the other tools don't cover:

  • Read computed styles: getComputedStyle(el).backgroundColor
  • Append text to inputs without clearing
  • Type character-by-character for autocomplete
  • Drag-and-drop via manual DOM events
  • Call fetch() to hit APIs directly
  • Read JS app state (window.__store__, etc.)
  • Check CSS visibility (display, opacity, visibility)

browser_scroll(direction?, pixels?, selector?, container?)

Three modes:

  • Page scroll: direction: "down", pixels: 500
  • Scroll into view: selector: ".my-element"
  • Scroll within a container: container: ".ag-body-viewport", direction: "down", pixels: 300 — for scrollable divs, grid viewports, chat panels

browser_wait_for_network(url_pattern?, method?, timeout?)

Wait for a specific network response after triggering an action — smarter than guessing with wait.

browser_screenshot()

Returns a PNG screenshot. Use as a last resort — prefer browser_debug and browser_query first.

browser_upload(selector, files[])

Upload files to a file input element.

browser_restart(url?)

Kill the browser and start fresh. Clears all logs. Optionally navigate to a URL after restart.

browser_emulate_device(device, orientation?, custom?)

Switch the browser into a device profile for responsive QA. Emulation persists across navigations until you swap devices or call browser_restart.

Presets (natural portrait viewport):

  • iphone-15-pro-max (430×932), iphone-15-pro (393×852), iphone-15 (393×852), iphone-se (375×667)
  • galaxy-s24 (360×800)
  • ipad-pro-13 (1024×1366), ipad-pro-11 (834×1194), ipad-mini (768×1024)
  • galaxy-tab-s9 (800×1280)
  • desktop-chrome (1280×800) — resets to desktop
  • custom — requires custom.userAgent + custom.viewport.{width, height}

Swapping devices recreates the browser context, so cookies and localStorage are lost and auth'd pages may land on login. innerWidth: 980 on a mobile emulation viewing a page without <meta name="viewport"> is Chrome's legacy fallback, not a bug — pointer_coarse, hasTouch, and userAgent are the authoritative signals. browser_debug surfaces the active emulation under an emulation field.


Example workflow

1. browser_navigate("https://myapp.com", clear_logs: true)
2. browser_act([
     { action: "fill", selector: "#email", value: "user@example.com" },
     { action: "fill", selector: "#password", value: "secret" },
     { action: "click", selector: "button[type=submit]" }
   ])
3. browser_wait_for_network({ url_pattern: "/api/session", method: "POST" })
4. browser_debug({ console_types: ["error"] })   <- check for login errors
5. browser_query(".dashboard-title")              <- confirm we're logged in

Hover + tooltip example

1. browser_act([{ action: "hover", selector: ".info-icon" }])
2. browser_query(".tooltip", { fields: ["text", "visible"] })

Drag-and-drop example

// Reorder columns
browser_act([{ action: "drag", selector: ".col-name", target: ".col-age" }])

// Resize a column by 100px
browser_act([{ action: "drag", selector: ".resize-handle", offsetX: 100, offsetY: 0 }])

Right-click context menu

1. browser_act([{ action: "click", selector: ".grid-row", button: "right" }])
2. browser_query(".context-menu-item", { all: true, fields: ["text"] })

Scroll inside a container

browser_scroll({ container: ".ag-body-viewport", direction: "down", pixels: 500 })

Count elements quickly

browser_query({ selector: ".ag-row", count_only: true })
// -> { selector: ".ag-row", count: 47 }

Emulate a mobile device

1. browser_emulate_device({ device: "iphone-15-pro-max" })
2. browser_navigate({ url: "https://www.youtube.com" })
   // redirects to m.youtube.com because of the iPhone UA
3. browser_screenshot()                     // mobile layout
4. browser_emulate_device({ device: "ipad-pro-13", orientation: "landscape" })
5. browser_emulate_device({ device: "desktop-chrome" })  // reset

Environment

Variable Default Description
HEADLESS false Run browser headless (true) or visible (false)
REAL_CHROME false Use your installed Chrome instead of Playwright's Chromium
CHROME_PROFILE Default Chrome profile name (when REAL_CHROME=true)

The browser launches lazily — it won't open until the first tool call.


License

MIT — free to use, modify, and distribute.

If this project helps you, buy me a coffee ☕

README copy captured when this server was indexed; it may lag the repository. The original is authoritative.

Questions

About Mare Browser

How do I install Mare Browser?

Run claude mcp add mare-browser -- npx -y mare-browser-mcp, then add the server to your MCP client's configuration.

Is Mare Browser safe to use with an AI agent?

Its trust score is 37 out of 100 (low). It passes 1 of the 1 static security checks run so far. It has no ConduID identity yet, so agent calls to it are not receipted.

Is Mare Browser still maintained?

Conduid hasn't recorded a commit date for this repository yet. Check the repository directly for recent activity.