Sallyport MCP Server

MCP server bridging Claude Code to a browser extension over WS+HMAC

Local serverstdioPython

What is the Sallyport MCP Server?

MCP server bridging Claude Code to a browser extension over WS+HMAC

What the server does

A secure browser-automation bridge between Claude Code (or any MCP client) and your Chrome. An alternative to Kimi WebBridge with explicit security boundaries instead of implicit ones.

More MCP options

Compare MCP servers by category, or browse hosted MCP servers if you prefer an endpoint over a local process.

Maintainer setup documentation.

Recorded tools

Check the linked publisher documentation and your connected client's tool list. Names and availability can vary with the server version and account permissions.

ToolWhat it does
list_tabsNo allowlist check — listing is free.
navigateChecks the destination URL against allowlist. waitFor={selector?,text?,absent?,timeoutMs?} polls after the load until the page is actually usable (SPAs render l
reloadHard reload via bypassCache=true. Allowlist-gated; refs invalidate.
history_goBack/forward through the tab's session history — return to the previous page without knowing its URL. direction='back'\
close_tabtabId required — no implicit fallback (closing the wrong tab loses work).
snapshotAccessibility tree with stable @eN refs (per-tab), pruned of layout noise. Cross-checks against a DOM walk (same refs) when the a11y tree looks suspiciously spa
read_textWhole-page or by ref. No raw JS. Capped at 20 000 chars by default (maxChars overrides, ceiling 200 000; cut results carry truncated/totalChars/nextOffset). Pas
get_stateCheap one-element probe (CSS or @eN) — {exists, visible, tag, text, box?, inViewport?} without a full snapshot. Verify an action's effect or re-check a ref in o
console_tailRecent page console errors/warnings + uncaught exceptions for a tab ({enabled, entries:[{ts,level,text,origin}]}) — tell "the handler threw and the page is wedg
network_tailRecent XHR/fetch responses for a tab ({enabled, entries:[{ts,method,url,status,type,contentType,size,body?}]}) — the data behind canvas dashboards (Metrika, Cha
handle_dialogSee and steer native JS dialogs (alert/confirm/prompt/beforeunload) — an open dialog freezes the page's JS and is browser UI no other tool can click. With handl
clickDOM .click(). CSS selector or @eN ref. Optional waitFor polls for the click's effect in the same call.
mouse_clickReal Input.dispatchMouseEvent as a full hover→press→release sequence. Auto-aims around partial overlays; a fully covered target reports covered/hitTarget/hitTar
hoverHover the pointer over an element/point without clicking (the mouseMoved preamble only). For CSS :hover-only menus, tooltips, row-action UIs. selector/@eN (auto
fillBlocks password fields without allowPassword=true — the gate checks the resolved node and the node the keystrokes actually reach, following focus through open s
select_optionChoose an option in a native (the OS popup can't be driven via CDP). Sets the value in the DOM and fires input/change instead of opening the menu. One of value/
key_typeRaw text input via CDP. Blocks when focus is on a password field without allowPassword=true.
send_keysMod+A, Shift+Tab, etc. Mod = Cmd on macOS, Ctrl elsewhere. Same password-field gate as key_type.
screenshotPNG/JPEG as a native MCP image block. maxWidth downscales so the returned image is at most that many pixels wide (it accounts for the display's device pixel rat
set_viewportEmulate a device viewport — the way to test responsive/mobile layouts. Per tab, not a window resize: it disturbs nothing the human is looking at, and gives you
print_to_pdfRender the page to a PDF in the download sandbox — returns {path, size, filename}, so the bytes never enter the model context. Unlike screenshot it needs no vis
wait_forPoll (250 ms) until a selector/@eN ref is visible (for CSS: any match — not necessarily the first, which click/fill act on; with absent=true, gone means no matc
settleWait for the DOM to stop changing (no child, text or attribute mutations in the top-level document for stableMs, default 500 ms) — for "the page just did someth
findSemantic element locator — match by role/name/nameExact/value over the accessibility tree instead of a CSS selector, ranked exact-match-first (limit, ≤ 50). No
revealScroll a virtualized list/container and re-snapshot until an element matching find's predicate appears — for infinite-scroll feeds and lazy-rendered tables. con
scrollDeterministic scrolling — the predicate-less companion to reveal. selector → scrollIntoView; or scroll the page (or a selector container) by dx/dy (negatives =
evaluatePer-domain opt-in. Returns {type, value}.
fetch_in_pagefetch() with page cookies/auth. Returns {status, contentType, headers, mode, data}. saveAs= writes the body straight into the download sandbox instead — result
uploadAttach local files to via DOM.setFileInputFiles. Paths must be absolute, ..-free, and resolve under ~/Downloads/sallyport/ (override via SALLYPORT_DOWNLOAD_DIR)
save_to_fileDaemon-local — writes base64 to ~/Downloads/sallyport/ (override via SALLYPORT_DOWNLOAD_DIR). Sandboxed: no path separators or ...
statusDaemon-answered health check: {connected, mode, version, port, pendingCalls, uptimeS, lastCalls, lastError, lastHandshakeError}. mode is broker (explicit owned

How to install the Sallyport MCP Server

{
  "mcpServers": {
    "sallyport": {
      "command": "/Users/you/.local/bin/sallyport-daemon",
      "args": []
    }
  }
}

From the project documentation. Replace placeholders and example paths before connecting.

Example prompts to try

  • “Use Sallyport to list tabs.”
  • “Use Sallyport to navigate.”
  • “Use Sallyport to reload.”

Frequently asked questions

MCP server bridging Claude Code to a browser extension over WS+HMAC Confirm the tools offered by your installed version in the connected client. Tool availability and permissions depend on the server and account configuration.