Composite tool

compose — many commands, one call

Multi-step browser actions usually mean a round-trip per command. compose runs a whole sequence against one tab in a single call: one command per line, executed in order, stopping at the first failure.

The format

Each line is <tool>?<query-string> — a URL query string whose keys are exactly that tool's parameters. No new syntax to learn: serialize it with URLSearchParams (JS), urlencode (Python), or anything that speaks query strings.

fill?selector=%23email&value=me%40example.com
fill?selector=%23password&value=hunter2
click?selector=%23login
wait?t=500

Encoding: only &, %, and newlines (%0A) must be encoded in a value; spaces can be + or %20. An XPath's internal = is fine unencoded, since each pair only splits on its first =.

Eligible commands

The action commands, plus the compose-only wait:

navigatebackforwardreload clickhoverfocusblur filltypeinsertTextclearselectkeypressscroll wait?t=<ms>

Data-returning commands (screenshot, dom, elements, console_logs…), lifecycle commands (new_tab, close, show), and evaluate are not eligible — they're meant to read a result or change the tab set, not advance a sequence.

How it runs

  • Validated up front. The whole script is checked first (known command, parseable query, valid args). If anything is wrong, nothing runs and you get the offending line.
  • Stops at the first failure. If a command errors or can't find its element, the run halts there — later lines don't execute.
  • Returns an array of the per-command responses, in order. On a failure, the last entry holds the error, and the array length tells you how far it got.
  • Long batches stay alive. compose emits progress as it goes, so a script with waits won't trip your client's request timeout.

Examples

Search a site and submit:

fill?selector=.search-box&value=browser+automation
click?selector=button%5Btype%3D%22submit%22%5D

Open a page, let it settle, scroll down, and type into a rich editor:

navigate?url=https%3A%2F%2Fexample.com%2Fdoc
wait?t=800
scroll?y=600
type?selector=.editor&text=Drafting+from+an+AI+agent.

Replace a field's contents (clear, then type) and move focus on:

clear?selector=%23title
type?selector=%23title&text=Q3+roadmap
keypress?key=Tab

Calling it

Over MCP, call the compose tool with tabId and script. Over HTTP, POST the same script:

curl -X POST http://localhost:61822/tab/{tabId}/compose \
  -H 'Content-Type: application/json' \
  -d '{"script":"fill?selector=%23q&value=hi\nclick?selector=%23go"}'

Full MCP docs More examples