Skip to content

MCP Agent Integration

The Sa2web MCP server exposes the remote browser as standard MCP tools for clients such as Claude Code, Claude Desktop, Cursor, Windsurf, VS Code Copilot, Cline, Roo Code, opencode, Gemini CLI, Zed, Hermes Agent, and OpenClaw.

The MCP project is open source at sa2web/sa2web-mcp and published on npm as @sa2web/mcp. For normal use, install the npm package; clone the source only for development or debugging.

For direct terminal operation, see Remote Browser CLI.

The target site is rendered inside iframe#rbi-frame. The server controls that frame through Playwright; the agent does not access the target site directly.

Prerequisites

  • Node.js 18 or later.
  • A global @sa2web/mcp installation, or a cloned source checkout for development.
  • A working agent login URL for the remote browser. It normally contains clientId and clientSecret and must be treated as a secret.
  • Access to the required SaaS sites, workspaces, internal sites, and proxies assigned to the agent account.

Install

Install the published package globally. This exposes sa2, sa2-browser, and sa2-mcp on your PATH:

bash
npm install @sa2web/mcp -g
npx playwright install --with-deps

sa2-mcp is the stdio server entry for MCP clients. sa2 and sa2-browser are CLI entries for terminal debugging and automation.

For source development, use the open-source repository:

bash
git clone https://github.com/sa2web/sa2web-mcp.git
cd sa2web-mcp
npm install
npx playwright install --with-deps
npm run build

The source build creates dist/server.js. Run npm start to check that the server starts. MCP uses stdio, so no interactive interface is expected.

Configure an MCP client

Most clients accept the mcpServers format below. With the global npm package, call sa2-mcp directly:

json
{
  "mcpServers": {
    "sa2-remote-browser": {
      "command": "sa2-mcp",
      "env": {
        "SA2_LOGIN_URL": "https://<APP_DOMAIN>/agent/login?clientId=...&clientSecret=...",
        "SA2_LOGIN_REDIRECT_PATH": "/app/login",
        "SA2_HEADLESS": "false",
        "SA2_IGNORE_HTTPS_ERRORS": "true"
      }
    }
  }
}

If the client cannot resolve global commands, use the full path to sa2-mcp, or point to a source build:

json
{
  "mcpServers": {
    "sa2-remote-browser": {
      "command": "node",
      "args": ["/absolute/path/to/sa2web-mcp/dist/server.js"],
      "env": {
        "SA2_LOGIN_URL": "https://<APP_DOMAIN>/agent/login?clientId=...&clientSecret=...",
        "SA2_LOGIN_REDIRECT_PATH": "/app/login",
        "SA2_HEADLESS": "false",
        "SA2_IGNORE_HTTPS_ERRORS": "true"
      }
    }
  }
}

On Windows, use an absolute path and escape backslashes in JSON, for example E:\\sa2web-mcp\\dist\\server.js.

ClientConfiguration note
Claude Code, Claude Desktop, Cursor, Windsurf, Cline, Roo CodeUse mcpServers
VS Code CopilotThe root field is servers
opencodeThe root field is mcp
ZedThe root field is context_servers
Gemini CLIAdd the server to Gemini CLI settings.json
Hermes AgentMerge it into mcp_servers in ~/.hermes/config.yaml
OpenClawMerge it into Gateway mcp.servers; allow the MCP tools when sandboxing is enabled

Restart the client after saving. The connection is ready when its tool list contains sa2_help, sa2_open_target, and browser_snapshot.

Protect credentials

Never commit a real clientSecret to Git or paste it into documentation. Inject production secrets through the MCP client or deployment platform and rotate any exposed credential.

Main environment variables

VariableDefaultPurpose
SA2_LOGIN_URLnoneRequired agent login URL; the remote-browser origin is inferred from it
SA2_LOGIN_REDIRECT_PATH/app/loginExpected path after login
SA2_AUTO_LOGIN_BEFORE_NAVIGATEtrueLog in before opening a target
SA2_HEADLESSfalseRun the local Playwright browser headlessly
SA2_BROWSERchromiumchromium, firefox, or webkit
SA2_IGNORE_HTTPS_ERRORStrueIgnore HTTPS certificate errors; set to false to require valid certificates
SA2_RBI_FRAME_SELECTOR#rbi-frameTarget-page iframe selector
SA2_RBI_FRAME_CONTENT_WAIT_MS15000Wait time for target-frame content
SA2_NAVIGATION_TIMEOUT_MS45000Navigation timeout
SA2_ACTION_TIMEOUT_MS15000Action and element timeout
SA2_LOG_LEVELinfotrace, debug, info, warn, error, fatal, or off
SA2_LOG_STDERRtrueWrite logs to stderr, leaving stdout for MCP stdio
SA2_LOG_FILEnoneOptional append-only log file

Do not configure the obsolete SA2_REMOTE_BROWSER_PREFIX or SA2_REMOTE_BROWSER_BASE_URL. Secrets, passwords, cookies, tokens, and authorization fields are redacted from logs.

text
sa2_help
  -> sa2_list_available_targets    # only for SaaS, workspace, or internal targets
  -> sa2_open_target
  -> browser_snapshot or browser_extract_text
  -> browser_click / browser_type / browser_press / browser_wait

Open a public URL:

json
{ "type": "cloud", "url": "https://example.com" }

For a saved SaaS site, workspace, or internal site, call sa2_list_available_targets, select a stable ID, and pass it to sa2_open_target:

json
{ "targetId": "workspace:123" }

After opening the page, prefer browser_snapshot. It assigns actionable references such as ref=e3. Pass those refs to click, type, select, check, upload, hover, or drag tools. Snapshot values such as id=t3 and context=[t3] are text references, not DOM IDs, CSS selectors, or actionable refs. A selector argument must always be a real CSS selector.

Tool groups

GroupTools
Recommended entry pointssa2_help, sa2_list_available_targets, sa2_open_target
Inspectionbrowser_snapshot, browser_extract_text
Interactionbrowser_click, browser_type, browser_press, browser_wait, browser_scroll
Forms and pointerbrowser_fill_form, browser_select_option, browser_check, browser_uncheck, browser_hover, browser_drag
Files and clipboardbrowser_file_upload, browser_paste
Browser controlsbrowser_navigate_back, browser_navigate_forward, browser_reload, browser_resize, browser_list_devices, browser_toggle_device, browser_handle_dialog
Output and debuggingbrowser_screenshot, browser_take_screenshot, browser_evaluate, browser_run_code, browser_close
Advanced compatibilitybrowser_open_login, browser_navigate, browser_list_proxies, browser_list_*, browser_enter_*

Complete tool reference

The table below covers every tool registered by the current server. Arguments refer to the MCP arguments object.

ToolPurpose, key arguments, and result
sa2_helpNo arguments. Returns the recommended workflow, examples, and compatibility-tool list. Use it as an agent's first call.
sa2_list_available_targetsNo arguments. Lists accessible proxies, SaaS sites, workspace accounts, and internal sites with stable targetId values.
sa2_open_targetPreferred navigation tool. Open a public URL with type=cloud, url, optional surf; or a saved target with targetId, type plus id/name, and optional waitUntil. Returns the matched target and load/login state.
browser_open_loginOpens SA2_LOGIN_URL; optional waitUntil. Intended for login diagnostics because sa2_open_target normally logs in automatically.
browser_navigateCompatibility public-URL navigation. Requires url; accepts surf and waitUntil; returns the remote URL, selected proxy, and frame/login state.
browser_navigate_backNo arguments. Clicks the remote-browser toolbar back button. Take a new snapshot afterward.
browser_navigate_forwardNo arguments. Clicks the toolbar forward button. Take a new snapshot afterward.
browser_reloadNo arguments. Reloads through the toolbar. Old snapshot refs must be discarded.
browser_list_proxiesNo arguments. Returns free-browse settings, raw proxy data, and options including direct.
browser_list_saas_sitesNo arguments. Returns raw SaaS categories plus a flattened sites list. Prefer sa2_list_available_targets for normal use.
browser_enter_saas_siteOpens a SaaS site by optional id or name, with waitUntil. Returns the matched site and open result.
browser_list_workspacesNo arguments. Returns raw workspace data and flattened account-level targets.
browser_enter_workspaceOpens an account by accountId, or siteId plus username; optional waitUntil. Returns the matched account.
browser_list_inner_sitesNo arguments. Returns internal sites available to the current account.
browser_enter_inner_siteOpens an internal site by id or name; optional waitUntil. Returns the matched site.
browser_snapshotOptional real CSS filter. Returns a flat semantic snapshot across the target iframe tree. Use actionable ref=eN; id=tN and context=[tN] are text references only. Raw URLs are omitted.
browser_extract_textOptional real CSS selector. Returns visible text from the target iframe tree. Snapshot text IDs are not selectors.
browser_clickClick by ref, CSS selector, role/name, visible text, or paired x/y coordinates. May report a pending JavaScript dialog.
browser_typeRequires text; locates by ref, selector, or textbox/searchbox/combobox role and name, otherwise uses the focused editor. append preserves existing content; pressEnter submits after typing.
browser_pressRequires a Playwright key, for example Enter, Escape, Tab, or Control+A.
browser_press_keyCompatibility alias of browser_press with identical arguments and behavior.
browser_waitWait by selector, text, urlIncludes, or positive ms (default 1000). Conditions are checked in that priority order.
browser_scrollScroll the root or a located element. Supports mode=by/to/intoView, directions, amount, coordinates, smooth behavior, and alignment. With no arguments, scrolls down 600 px.
browser_hoverHover an element located by ref, selector, role/name, or text.
browser_dragDrag from startRef/startSelector to endRef/endSelector; both endpoints are required.
browser_fill_formRequires a fields array. Each field has locator data plus required value; fills fields sequentially and replaces existing values.
browser_select_optionLocate a <select> by ref or selector, then select by values, value, label, or zero-based index. Returns actual selected values.
browser_checkChecks a checkbox or radio located by ref, selector, role/name, or text.
browser_uncheckUnchecks a checkbox using the same locator forms; radio is not supported for unchecking.
browser_file_uploadLocate a file input by ref or selector; provide single path or paths. Paths must be readable on the MCP server machine.
browser_pastePaste any combination of text, html, rtf, path, or paths into a located/focused target. File inputs use direct upload mode. Returns paste mode, types, and file count.
browser_handle_dialogAccept or dismiss the current/pending alert, confirm, or prompt. accept defaults true; optional promptText and timeoutMs. Returns dialog details.
browser_resizeRequires positive integer width and height. Resizes desktop viewport or reapplies the active device emulation with new dimensions.
browser_list_devicesNo arguments and does not open a page. Lists Desktop plus every Playwright device preset with viewport, screen, DPR, mobile/touch flags, and default browser type.
browser_toggle_deviceToggle device emulation without rebuilding the context. Accepts enabled, Playwright device, dimensions, deviceScaleFactor, hasTouch, userAgent, orientation, and reload. Desktop restores desktop mode. Returns expected state, outer observed, iframe targetObserved, and warnings.
browser_screenshotOptional fullPage, default false. Returns a base64 PNG as MCP image content.
browser_take_screenshotScreenshot compatibility alias; unlike the previous tool, fullPage defaults to true.
browser_evaluateExecutes an expression in iframe#rbi-frame, with optional serializable arg, and returns JSON. High privilege; prefer dedicated tools for routine work.
browser_run_codeRuns async JavaScript with Playwright page, rootFrame, and locator helpers. Requires code; returns its JSON result or null. Use only trusted code.
browser_closeNo arguments. Closes browser/context and clears refs, login, dialog, CDP, and device-emulation state.

Device switching examples

List presets before selecting one:

json
{ "name": "browser_list_devices", "arguments": {} }

Enable a preset without losing cookies or login state:

json
{
  "name": "browser_toggle_device",
  "arguments": {
    "device": "Pixel 7",
    "orientation": "portrait"
  }
}

Use reload: true when subsequent requests must carry the new user agent. Chromium uses CDP for viewport, screen, DPR, touch, orientation, and user-agent overrides. Firefox and WebKit can only resize the viewport dynamically and report that limitation in warnings. The observed and targetObserved fields let you compare the outer shell with the target iframe. Restore the previous desktop viewport with { "device": "Desktop" }, then take a new snapshot after every switch.

Suggested agent instructions

text
Use the sa2-remote-browser MCP whenever web access is required.
For a public URL, call sa2_open_target with {"type":"cloud","url":"https://example.com"}.
For SaaS, workspace, or internal targets, call sa2_list_available_targets first and pass its targetId to sa2_open_target.
After opening, call browser_snapshot or browser_extract_text. Prefer snapshot refs for clicks and typing.
Obtain explicit user confirmation before publishing, submitting, deleting, purchasing, authorizing, transferring money, or sending messages.

Troubleshooting

SymptomResolution
No MCP tools appearBuild the project; verify absolute paths to node and dist/server.js; restart the client
Login failsVerify SA2_LOGIN_URL, credentials, and account status; call browser_open_login once if needed
Only the toolbar appearsCall browser_wait or increase SA2_RBI_FRAME_CONTENT_WAIT_MS and SA2_LOGIN_SETTLE_MS
A saved target is missingCheck the agent account's group, site, workspace, internal-site, and proxy permissions
An action cannot find an elementTake a new snapshot and use the latest ref=eN; never use tN as a selector
stdio connection errorsReserve stdout for MCP; send logs to stderr or SA2_LOG_FILE

Sa2web 1.0.0