Session MCP Server
The Session MCP Server exposes the Automation API over the Model Context Protocol (MCP). Connect any MCP-compatible AI agent to a live proxied browser session — your agent can open URLs, read the page, fill in forms, click buttons, select text, and take screenshots, all without modifying the underlying website.
Use Cases
Section titled “Use Cases”- Third-party agents — connect Cognigy, ElevenLabs, or similar platforms to a live browser session without modifying the underlying website.
- Agent orchestration — use MCP-capable orchestrators (LangGraph, AutoGen, CrewAI) to build agentic workflows on top of any proxied web page.
- Agent development — iterate on prompts and tool calls interactively against a live session from Cursor, VS Code, or any MCP client.
Configuration
Section titled “Configuration”-
Create an Automation Space
Section titled “Create an Automation Space”We recommend creating an Automation Space in Webfuse Studio. It comes with the Automation app installed and a Space Automation API key already created. See Getting Started for a step-by-step guide.
-
Copy the Space Automation API Key
Section titled “Copy the Space Automation API Key”Copy the Space Automation API key (prefixed
ak_) from the Automation app settings, or from the Space’s Developers → API in Webfuse Studio. Both locations provide the same key. It authorizes remote automation in the Space’s Sessions through their available tools. Treat the key as a secret: do not publish it in client-side code, logs, or URLs. -
Configure Available Tools (optional)
Section titled “Configure Available Tools (optional)”By default all automation tools are available. To restrict which tools agents can use, open the Automation app settings and click Configure tools. Uncheck any tools you want to disable for this Space — the change applies to all sessions in the Space. To disable automation entirely, uninstall the Automation app instead.
-
Start a Session
Section titled “Start a Session”Start a Session in your Automation Space, then connect your MCP client as described below.
Authentication
Section titled “Authentication”Use a Space Automation API key (ak_) to give your agent automation access to Sessions in one Space.
Send it as a Bearer token on every request to the Session MCP Server:
Authorization: Bearer ak_<key>The key is scoped to Sessions in its Space. It authorizes Session MCP tool calls, Session creation, and REST Session termination in that Space. It does not authorize access to other Spaces or Space administration.
The Space’s REST key (rk_) can do everything its Automation key can, so it is accepted the same way.
Prefer the Automation key for agents: it grants only the access they need, while a REST key also administers the Space.
API Key Permissions
Section titled “API Key Permissions”An Automation key’s permissions are a fixed subset of the Space REST key’s. Compare the credentials used for Session MCP and related REST operations:
| Credential | Call Session MCP Tools | Start a Restricted Session¹ | End a Session via REST | Retrieve or Create an Automation Key | Space Scope |
|---|---|---|---|---|---|
Space Automation (ak_) | ✅ | ✅ | ✅ | ❌ | One Space |
Space REST (rk_) | ✅ | ✅ | ✅ | ❌ | One Space |
Company (ck_) | ❌ | ✅ | ✅ | ✅ | All Spaces in the company |
Space Widget (wk_) | ❌ | ❌ | ❌ | ❌ | One Space |
¹ A restricted Space has Members-only or Company access control. A Space’s own Automation or REST key, and a Company key from the owning company, can start a Session there. Widget keys and keys from other Spaces or companies still only open public Spaces.
Space REST and Company keys also authorize REST administration within their scope. Widget keys are for browser integrations, including supported Space and Session reads; configure allowed origins for your integration.
Retrieve an Automation Key Programmatically
Section titled “Retrieve an Automation Key Programmatically”Installing the Automation app creates the Space’s Automation key if one does not already exist. A Space can have at most one key of each type. To retrieve the Automation key, use a Company key to list the Space's keys:
curl --fail-with-body \ -H 'Authorization: Token <company-key>' \ 'https://HOSTNAME/api/spaces/<space_id>/keys/'Find the entry whose type is ak in the response’s results array. Its key is the credential
to use as your MCP Bearer token. Follow the response’s next link if the list spans multiple pages.
If the Space has no Automation key, create one with the same Company key:
curl --fail-with-body \ -X POST \ -H 'Authorization: Token <company-key>' \ -H 'Content-Type: application/json' \ -d '{"type": "ak"}' \ 'https://HOSTNAME/api/spaces/<space_id>/keys/'The response contains the new key. Enable the Automation app and start a new Session before
using it. Space REST, Automation, and Widget keys cannot list or create API keys.
Find the Key’s Space
Section titled “Find the Key’s Space”To start and end Sessions from code, your integration needs the Space that its key belongs to. Send the Automation key to the Space endpoint:
curl --fail-with-body \ -H 'Authorization: Bearer <your-space-automation-key>' \ 'https://HOSTNAME/api/automation/space/'The response describes the key’s Space:
{ "space_id": 123, "slug": "support", "link": "https://HOSTNAME/+support/", "type": "meeting", "enable_parallel_sessions": false}link– send aPOSTto it with the same key to start a Session.space_id– use it to end a Session through/api/spaces/<space_id>/sessions/<session_id>/end/.typeandenable_parallel_sessions– a Meeting Space without parallel Sessions returns its running Session instead of starting a new one.
A Space REST key gets the same answer. Company and Widget keys get HTTP 401: a Company key covers every Space of the company, and a Widget key is public.
Connect your MCP Client
Section titled “Connect your MCP Client”Configure your MCP client to connect to the Session MCP Server endpoint for your domain:
https://session-mcp.HOSTNAME/mcpSend the Space Automation API key as a Bearer token. See Authentication.
Dynamic tool discovery
Section titled “Dynamic tool discovery”By default, the server returns all tools on the first tools/list request and every tool requires a session_id parameter.
If you append ?dynamic=true to the endpoint URL, the server starts with only the connectToSession tool. Call it with a session_id to bind the connection to a session — the server then registers the full tool set and sends a notifications/tools/list_changed notification so the client can re-fetch the tool list. Calling connectToSession with a different session_id rebinds the connection without reconnecting.
Dynamic mode is also the only mode that lists custom tools an Extension or the page registers at runtime, and updates the list as they change. The default mode lists only tools declared in an Extension’s manifest.json.
https://session-mcp.HOSTNAME/mcp?dynamic=trueOr add manually to .vscode/mcp.json in your workspace, or to user settings:
{ "servers": { "webfuse-session": { "type": "http", "url": "https://session-mcp.HOSTNAME/mcp", "headers": { "Authorization": "Bearer ${input:automation_key}" } } }, "inputs": [ { "type": "promptString", "id": "automation_key", "description": "Space Automation API Key", "password": true } ]}
Or add manually to .cursor/mcp.json:
{ "mcpServers": { "webfuse-session": { "type": "http", "url": "https://session-mcp.HOSTNAME/mcp", "headers": { "Authorization": "Bearer <your-space-automation-key>" } } }}Add to claude_desktop_config.json:
{ "mcpServers": { "webfuse-session": { "type": "http", "url": "https://session-mcp.HOSTNAME/mcp", "headers": { "Authorization": "Bearer <your-space-automation-key>" } } }}Or use the Claude CLI:
claude mcp add-json webfuse-session '{"type":"http","url":"https://session-mcp.HOSTNAME/mcp","headers":{"Authorization":"Bearer <your-space-automation-key>"}}'# To install the required library: pip install mcp
import asyncioimport httpxfrom mcp import ClientSessionfrom mcp.client.streamable_http import streamable_http_client
async def main(): async with streamable_http_client( "https://session-mcp.HOSTNAME/mcp", http_client=httpx.AsyncClient( headers={"Authorization": "Bearer <your-space-automation-key>"}, timeout=httpx.Timeout(timeout=None, connect=10.0), ), ) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() result = await session.call_tool( "see_domSnapshot", {"session_id": "<session-id>"} )
print(result)
if __name__ == "__main__": asyncio.run(main())Try it
Section titled “Try it”Start a fresh session, then ask your agent:
“In Webfuse session, open https://webfuse.com and describe what you see.”
The agent will ask for a session ID, then use navigate to load the page and see_domSnapshot or see_guiSnapshot to read it.
From there you can ask it to interact with the page in natural language — click a link, fill in a form, or summarise the content.
Limits
Section titled “Limits”| Limit | Value | Notes |
|---|---|---|
| Tool call inactivity timeout | 15s | A tool call fails with a timeout error if neither its result nor a progress update arrives for 15 seconds. This covers network transfer in both directions and tool execution in the browser. Progress updates reset the timer. |
| Tool call duration | 5min | Absolute cap per call, progress updates or not. It covers sending the call to the session and waiting for its result. |
| Browser execution timeout | 10s | A built-in tool that has not finished in the browser after 10 seconds fails with Client-side automation timed out. |
waitForTargetMs | 0ms | How long an action tool waits for its target to appear when waitForTargetMs is greater than 0. With 0, a missing target fails at once. |
| Tool call input size | 16KiB | Maximum decompressed size of one tool call’s arguments. In act_batch this applies to each step’s arguments. act_uploadFile has its own limit, below. |
act_uploadFile file size | 5MiB | Maximum decoded size of all files in one act_uploadFile call together. The call’s arguments, with the base64 file contents, may be up to about 6.7MiB, also as an act_batch step. |
| Tool call response size | 10MiB | Maximum decompressed size of a tool result. Larger results are rejected, and the agent receives an error instead. |
| Response inactivity | 3min | A request or event stream that receives no data for 3 minutes is closed by the proxy. Only act_batch and custom tools run that long. For those, ask for progress updates: they keep the response active (see Batches). |
| MCP session idle time | 30min | An MCP session (Mcp-Session-Id) with no requests for 30 minutes is closed. Requests with a closed session’s ID get HTTP 400, and the client must initialize a new session. |
act_batch steps | 50 | A batch with no steps or more than 50 is rejected before any step runs. |
act_batch parallel steps | 4 | A parallel batch runs at most 4 steps at the same time. |
act_batch duration | 5min | Each step has the inactivity timeout above, and the whole batch must also finish within 5 minutes. |
act_batch response size | 10MiB | Total step output a batch returns. Once it is reached, later read-only steps are skipped, and action steps still run but their output is replaced by a note. |
act_batch step error | 500 characters | Longer step error messages are cut off. |
Defaults, overrides and enforcement
Section titled “Defaults, overrides and enforcement”- Defaults are filled in by the server: tool schemas declare allowed values and defaults (for example
act_clickbuttonandmoveMouse). An option the agent omits is filled in with its default before the call reaches the browser, so the browser always receives an explicit value. - Arguments are validated: every call is checked against its tool’s input schema, including the allowed values. A call that fails is rejected before anything runs.
- Enabled tools: tools disabled for the Space (see Configuration) are not listed, and calling one fails with
Tool "<name>" is not allowed for this session.act_batchcan only run enabled tools as steps. Custom tools are not affected by this list. - Tool list lookup: if the server cannot look up the Space’s enabled tools when a client connects, it lists every built-in tool except
act_batch. Disabled tools are still rejected when called.act_batchis left out because it could not reject a disabled step before running the others. - When tool changes take effect: the tool list is read when a client connects, or in dynamic mode when it calls
connectToSession. After changing the Space’s enabled tools, reconnect the client (or callconnectToSessionagain) to see the change. - Custom tools by mode: a client in the default (static) mode sees only custom tools declared in an Extension’s
manifest.json. Tools registered at runtime, byregisterToolwithout a manifest declaration or declared by the page itself, are only listed to clients in dynamic mode afterconnectToSession. See Custom MCP Tools. - Session not ready: if the session has no active tab, or the tab owner is not connected, the call returns a tool result with
isError: truesaying which. Retry once the session is ready. - Browser origins: a browser-based MCP client must run on an HTTPS Webfuse domain, or a direct subdomain of one, on the default port. Requests from any other
Originget HTTP 403. Clients that send noOriginheader, such as server-side agents, are not affected. - Parallel batches override options: see Batches.
Tool behaviour
Section titled “Tool behaviour”act_typetyping speed: text of up to 33 characters is typed one character at a time, about 75ms per character. Longer text, and empty text, is pasted in one step.act_typeinput types: inputs other thantext,password,email,tel,urlandsearch(for exampledateorcolor) get their value set directly.dateanddatetime-localvalues are converted to ISO format first.act_typeon one field: calls that type into the same field run one after another, never interleaved.act_typechangeevent: fires when the field loses focus after typing. If it loses focus while typing is still in progress,changefires when typing ends, with the full value.moveMousecosts time: each pointer move takes at least 0.5 seconds. SetmoveMousetofalsewhen the visible pointer is not needed.act_selectandmoveMouse:act_selectmoves the pointer to the select element unlessmoveMouseisfalse.act_scroll: the scroll animation lasts up to 1 second before the call returns.act_uploadFile: see Uploading files.see_domSnapshotdefaults:quality1 (the complete DOM) andcrossShadowon;crossFrame,interactiveOnly,revealMaskedElementsandwebfuseIDsoff. For agents,quality0.1 withwebfuseIDskeeps snapshots small.see_domSnapshotiframes: withcrossFrame, content is included up to 3 frames deep, and each frame has 1.5 seconds to respond.see_domSnapshotinput values: values longer than 500 characters are cut off.see_domSnapshotmasking: elements hidden by the Webfuse Masking App are left out unlessrevealMaskedElementsis set.maxTokens: one token counts as 4 bytes. If a snapshot cannot be made small enough, the call fails.see_guiSnapshot:qualitydefaults to 0.6, and the screenshot must be captured within 5 seconds.see_accessibilityTree:webfuseIDsdefaults to on.- First snapshot of a page: if the page body is still empty, the snapshot is retried once after 350ms.
Batches
Section titled “Batches”act_batch runs several tool calls in one request. The server checks every step before running any, so a batch with one invalid step is rejected as a whole.
Which tools can be steps: act_click, act_highlight, act_keyPress, act_mouseMove, act_scroll, act_select, act_textSelect, act_type, act_uploadFile, navigate, pageInfo, see_accessibilityTree, see_domSnapshot, see_guiSnapshot, see_textSelection and the custom tools the connection lists, plus act_eval while the Enable eval tool setting of the Automation app is on. act_batch itself, connectToSession and tools disabled for the Space cannot.
Custom tool steps:
- Listed tools only: a step can name a custom tool only if the connection lists it when the batch arrives. In the default (static) mode that means tools declared in an extension manifest. Tools registered at runtime or by the page need dynamic mode. A page tool that only registers after a
navigatestep of the same batch is rejected: split the batch atnavigate. - Arguments: checked against the tool’s schema before any step runs, but without filling in defaults, so the tool gets the same arguments as from a direct call. A direct call is not checked, so arguments that work directly can be rejected in a batch.
- Schemas the server cannot read: a tool whose schema cannot be resolved, for example one with a
$refto another document, cannot be a step. Call it directly. - Enabled tools: the Space’s enabled tools do not apply, as for direct calls.
- Always treated as actions: a custom step runs even after the output limit is reached, and an unclear failure marks it
outcomeUnknown. ItsreadOnlyHintis ignored. - Changes during a batch: a tool removed while the batch runs fails when reached. A tool whose schema changes runs with arguments checked against the old schema. Names that got a suffix after a name clash can point to a different tool after a reload.
- Output: text only, as for direct calls.
Step arguments:
- Same rules as a direct call: each built-in step’s arguments are validated against its tool’s schema, with defaults filled in. Custom steps follow the rules above. A step’s arguments may be up to 16KiB, or about 6.7MiB for
act_uploadFile. session_id: leave it out of the steps. The batch’ssession_idis used for every step, replacing any value a step sets.- Enabled tools are checked twice (built-in steps): before running, against the tools the connection lists, and again for each step as it runs, against the session’s own settings. In the default (static) mode the connection’s list is read when the client connects. If a tool was disabled after that, the batch starts, and the step using it fails when reached, after earlier steps have run. Reconnect the client after changing which tools are enabled.
Serial mode (default):
- Order: steps run one after another, in the order given.
- Failures: the batch stops at the first failed step, and the remaining steps are reported as
skipped. SetstopOnErrortofalseto run every step regardless. - Cancellation: when the batch deadline passes or the request is cancelled, the running step is reported as
cancelledand the rest asskipped, even withstopOnError: false. - Progress: if the client asked for progress updates, one follows each finished step, naming the tool and its status, e.g.
act_click: ok.
Parallel mode:
- Concurrency: up to 4 steps run at the same time, and every step runs even if another fails.
stopOnErrorhas no effect. - Pointer and focus:
moveMouse(onact_click,act_keyPress,act_scroll,act_select,act_textSelect,act_typeandact_uploadFile) andfollowFocus(onact_type) default tofalse, because concurrent steps would otherwise move the one virtual pointer and read focus another step just moved. A step that sets either option totrueis rejected. - Steps that take turns:
- Text selection:
act_textSelectandsee_textSelection, because a page has a single text selection. - Pointer:
act_mouseMovesteps, because moving the pointer is their purpose.
- Text selection:
navigate: not allowed, because steps running alongside it would act on a page that is unloading.- Custom tool steps run alone, where they stand: the steps before a custom step finish first, and the steps after it wait until it is done. For example,
[act_click, act_click, my_tool, pageInfo]runs both clicks together, thenmy_tool, thenpageInfo. Consecutive custom steps run one after another. The server cannot turn off a custom tool’s pointer and focus moves, and the tool may navigate. Its options are passed on unchanged. act_evalsteps run concurrently with the other steps, so the evaluated code must not depend on the order in which concurrent steps touch the page. Code that moves focus or navigates belongs in a serial batch.- Focus redirects: with
followFocusoff,act_typedoes not follow a field that moves focus to an inner input when focused. Target the inner input, or use a serial batch.
Timing and output:
- Timeouts: each step has the usual 15s inactivity timeout, and the whole batch must finish within 5 minutes.
- Keep-alive: if the client asked for progress updates, the server also sends one every 10 seconds while steps run. A client that resets its request timeout on progress therefore keeps a long batch open.
- Uncertain outcome: an action step is marked
outcomeUnknownwhen it may have run without a confirmed result: it timed out, was cancelled, failed with an internal error, or its delivery to the session failed partway. Check the page before retrying it. Read-only steps are never marked, since repeating them is safe. - Output size: once the batch’s output reaches 10MiB, later read-only steps (
see_*,pageInfo) are reported asskippedwithout running. Action steps still run, but their output is replaced by a note.
Result:
- Content: a summary line, then each step’s output under a
[step N: tool] statusheader. Steps that never ran are left out. - Structured result:
summary,isErrorand, per step,index,name,status(ok,error,skippedorcancelled),reason(tool,timeout,relayorinternal),error,outcomeUnknown,outputOmitted,durationMs,output(the step’s output items, images as base64) andoutputItems(how many content items follow the step’s header, socontentcan be split without parsing it). isError:trueunless every step isok.- Rejected batch: if any step is invalid, nothing runs and the summary lists every problem.
Not supported: a step cannot use the result of an earlier step. Call the tools one by one when a step depends on what an earlier one reveals.
Uploading files
Section titled “Uploading files”act_uploadFile attaches files to an <input type="file"> element, as if the user had chosen them in the file picker. The OS file picker never opens, so the agent does not need access to the user’s file system: it sends the file contents with the call.
{ "name": "act_uploadFile", "arguments": { "session_id": "sGpUNaFXihCSxCUfb3zezgaCw", "target": "input[type=file][name=resume]", "files": [ { "name": "resume.txt", "mimeType": "text/plain", "data": "SGVsbG8sIFdlYmZ1c2Uh" } ] }}On success the result names the attached files and their sizes, e.g. Attached 1 file(s): resume.txt (15 bytes).
- Target: a CSS selector or a
wf-idfrom a snapshot. It must resolve to an<input type="file">. Sites often hide the input behind a styled button or drop zone: target the input itself, e.g.input[type=file]. Hidden inputs are accepted. - Files:
nameanddata(base64, standard alphabet with padding) are required. LeavemimeTypeout if it is unknown. The files replace any already attached. - Several files: need an input with the
multipleattribute. - Events: the input gets
inputandchangeevents, as after a choice in the file picker, so the site’s upload handlers run. - What it does not do: the files are only attached. Submitting the form or clicking the site’s upload button is a separate action, for example an
act_clickstep afteract_uploadFilein anact_batch. - Not checked: the input’s
acceptattribute, which the file picker uses only as a filter. Sites that check file types after thechangeevent still do. - Frames: inputs inside an iframe can be targeted by
wf-idor a cross-frame selector, e.g.iframe input[type=file]. - Errors: the call fails with
isError: trueand attaches nothing if the target is not a file input, the input is disabled, several files are sent to an input withoutmultiple, a file has no name or invalid base64 data, or the files exceed 5MiB in total. - Privacy: file contents are not written to the session’s audit log or shown in the Automation debugger. Only the file names and types are.
All tools require a session_id identifying the target session.
Starting a session from code: send a POST to the Space link, authenticated with the Space Automation API key. The key starts Sessions in its own Space whatever the Space’s access control. To get the Space link and space_id from the key alone, see Find the Key’s Space. The response contains the new session’s session_id and link:
curl -X POST \ -H 'Accept: application/json' \ -H 'Authorization: Bearer <your-space-automation-key>' \ 'https://HOSTNAME/+<space-slug>/'Ending a session from code: send a POST to the session end endpoint with the same key:
curl -X POST \ -H 'Authorization: Bearer <your-space-automation-key>' \ 'https://HOSTNAME/api/spaces/<space_id>/sessions/<session_id>/end/'Outside Session MCP, the Automation key only reads its own Space and starts and ends Sessions there. Managing the Space itself still requires a REST key, which can also start and end Sessions and call Session MCP tools.
Open the returned link in a browser before calling tools. Until then the session has no tab, and tool calls fail.
Finding your session ID: it is the path segment after the hostname in the session URL, for example https://HOSTNAME/sGpUNaFXihCSxCUfb3zezgaCw. To get it programmatically:
-
REST API: list the Space's sessions with a REST key:
Terminal window curl -H 'Authorization: Token <rest-key>' 'https://HOSTNAME/api/spaces/<space_id>/sessions/?active=true' -
Webhooks: the
space.session.startedevent carries thesession_id. -
Inside the session:
sessionIdfromwebfuseSession.getSessionInfo().
Most actuation tools also accept a target — a CSS selector, Webfuse ID, or [x,y] coordinates.
Execution context: All commands are executed on the active tab of the session, on the tab owner’s browser. If the active tab or its tab owner is not present when a tool call arrives, the call fails with an error.
Opt-in tool: act_eval, which runs JavaScript in the page, is not listed and calls to it are rejected unless the Enable eval tool setting of the Automation app is on. It is off by default and is not part of the “Available tools” selection. After changing the setting, reconnect the MCP client in static mode, or call connectToSession again in dynamic mode, to refresh the tool list.
Tool schemas for code generators: the tools.json file lists every built-in tool, act_eval included, with its input and output schema. Each entry also says whether the tool only reads the page (readOnly, also sent to MCP clients as the tool’s readOnlyHint), whether act_batch accepts it as a step (batch), and which setting must be on for it to be listed (optIn). The server builds it from its own tool registration, so the schemas always match the ones that server validates calls against. It needs no API key:
curl -o tools.json 'https://session-mcp.HOSTNAME/tools.json'act_batch
Section titled “act_batch”Run several tool calls in one request, built-in or custom, e.g. filling a form (act_type, act_type, act_click) or reading the page several ways at once. Steps run in order and stop at the first failure; set mode to ‘parallel’ for steps that don’t affect each other. Do not use when a step depends on the result of an earlier step.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
steps | array | ✓ | Steps to run. Each step is a tool name, built-in or custom, and its arguments, without session_id. At most 50 steps. |
mode | string | ‘serial’ (default): run steps in order. ‘parallel’: run independent steps concurrently, up to 4 at a time, with moveMouse and followFocus off; steps using the text selection take turns; a custom tool step runs alone where it stands, after the steps before it and before the steps after it (navigate is not allowed). | |
stopOnError | boolean | Serial mode only. Stop at the first failed step and skip the rest (default: true). |
act_click
Section titled “act_click”Click a target element with the specified mouse button. Use for buttons, links, checkboxes, and any other interactive element. Defaults to a left-button click.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a Webfuse ID (wf-id) string from a snapshot, a Webfuse Locator string, or coordinates as ‘[x,y]’ |
options.button | string | Mouse button to use: ‘left’ (default), ‘middle’, or ‘right’. | |
options.moveMouse | boolean | Move the virtual mouse pointer to the target center before clicking. When false, the click is sent directly without moving the pointer (default: true). | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
act_eval
Section titled “act_eval”Run JavaScript on the page and return the result. Use only when no dedicated tool can do the job, e.g. to read application state that is not visible in a snapshot. Prefer act_click, act_type, see_domSnapshot and the other dedicated tools for interaction, and act_batch to run several tool calls in one request. The code runs as a global script in the page’s main document; with options.context ‘background’ it runs in the extension’s background worker instead, which has the extension APIs but no page DOM. The value of the last expression is returned as JSON (promises are awaited). Errors thrown by the code are returned as tool errors.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
code | string | ✓ | JavaScript source to evaluate in the page. |
options.context | string | Where to run the code: ‘content’ (default) runs it in the page’s main document, ‘background’ runs it in the Automation app’s background worker. |
act_highlight
Section titled “act_highlight”Draw a frame around an element on the page for a while, so the user can see which element is meant. The frame is drawn on top of the page and does not change the page. A new highlight replaces the current one. Use it to point out an element, not to verify it: read the page with see_domSnapshot or see_guiSnapshot for that.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a wf-id string from a snapshot, or coordinates as ‘[x,y]’ |
durationMs | number | How long the frame stays visible, in milliseconds (default: 5000). |
act_keyPress
Section titled “act_keyPress”Press a single key on a target element, with optional modifier keys. Key events are dispatched directly to the page, not to the operating system. OS-level shortcuts such as Ctrl+C (copy) or Ctrl+V (paste) will NOT work unless the page has explicitly implemented them. Standard editing keys (Enter, Backspace, Delete) and page-handled shortcuts work as expected.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a Webfuse ID (wf-id) string from a snapshot, a Webfuse Locator string, or coordinates as ‘[x,y]’ |
key | string | ✓ | Key to press using the KeyboardEvent.key name (e.g. ‘Enter’, ‘ArrowUp’, ‘a’, ‘B’, ‘F5’). |
options.altKey | boolean | Hold the Alt key while pressing the key. Only effective if the page handles the resulting combination (default: false). | |
options.ctrlKey | boolean | Hold the Control key while pressing the key. Only effective if the page handles the resulting combination - OS shortcuts like Ctrl+C will not work (default: false). | |
options.metaKey | boolean | Hold the Meta (Cmd on macOS, Win on Windows) key while pressing the key (default: false). | |
options.shiftKey | boolean | Hold the Shift key while pressing the key (default: false). | |
options.moveMouse | boolean | Move the virtual mouse pointer to the target center before pressing the key. When false, the action is sent directly without moving the pointer (default: true). | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
act_mouseMove
Section titled “act_mouseMove”Move the virtual mouse pointer to a target element or coordinates without clicking. Use to trigger hover states, tooltips, or drop-down menus that require mouse proximity. Can optionally keep the pointer visible on screen after the move.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a Webfuse ID (wf-id) string from a snapshot, a Webfuse Locator string, or coordinates as ‘[x,y]’ |
options.persistent | boolean | Keep the pointer visible on screen indefinitely after the move. When false (default), the pointer fades out automatically after a short delay. | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
act_scroll
Section titled “act_scroll”Scroll a target element or the page by a given number of pixels. Use to bring off-screen content into view or to navigate long pages. Positive amounts scroll down or right; negative amounts scroll up or left. When scrolling the full page rather than a specific element, use ‘html’ as the target - ‘body’ often does not respond to scrolling.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a Webfuse ID (wf-id) string from a snapshot, a Webfuse Locator string, or coordinates as ‘[x,y]’ |
amount | number | ✓ | Number of pixels to scroll. Positive scrolls down or right; negative scrolls up or left. |
options.direction | string | Axis to scroll along: ‘vertical’ (up/down, default) or ‘horizontal’ (left/right). | |
options.moveMouse | boolean | Move the virtual mouse pointer to the target center before scrolling. When false, the action is sent directly without moving the pointer (default: true). | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
act_select
Section titled “act_select”Select an option in a <select> dropdown element by matching its value attribute. Use this instead of act_click when interacting with native HTML dropdowns.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a Webfuse ID (wf-id) string from a snapshot, a Webfuse Locator string, or coordinates as ‘[x,y]’ |
value | string | ✓ | The value attribute of the option to select, not the visible display text. |
options.moveMouse | boolean | Move the virtual mouse pointer to the target center before selecting. When false, the action is sent directly without moving the pointer (default: true). | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
act_textSelect
Section titled “act_textSelect”Select a continuous run of text within a container element by matching its content. Use to highlight text before copying, replacing, or applying formatting. Pass an empty string as text to clear the current selection.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a Webfuse ID (wf-id) string from a snapshot, a Webfuse Locator string, or coordinates as ‘[x,y]’ |
text | string | ✓ | Exact text string to find and highlight within the target element. Pass an empty string to clear any existing selection. |
options.occurrence | number | Which occurrence to select when the text appears more than once in the element. 1 selects the first match (1-based index, default: 1). | |
options.moveMouse | boolean | Move the virtual mouse pointer to the target center before selecting. When false, the action is sent directly without moving the pointer (default: true). | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
act_type
Section titled “act_type”Type text into a target input element. Short inputs are typed character by character; longer inputs are pasted directly. Use for text fields, search boxes, and any editable element. By default, overwrites existing content. If the target resolves to a non-editable wrapper (error: ‘Target must resolve to editable element’), re-take a DOM snapshot with webfuseIDs: true and target the inner input element directly using its wf-id.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target element: a CSS selector, a Webfuse ID (wf-id) string from a snapshot, a Webfuse Locator string, or coordinates as ‘[x,y]’ |
text | string | ✓ | Text to type into the target element. |
options.followFocus | boolean | Continue typing into whichever element holds focus, even if focus moved away from the original target. Set to false to strictly type into the target (default: true). | |
options.overwrite | boolean | Replace the existing content of the input before typing. Set to false to append or insert at the current cursor position (default: true). | |
options.moveMouse | boolean | Move the virtual mouse pointer to the target center before typing. When false, the action is sent directly without moving the pointer (default: true). | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
act_uploadFile
Section titled “act_uploadFile”Attach one or more files to an <input type=‘file’> element without opening the OS file picker, and fire its input and change events. File contents are passed as base64, at most 5 MiB in total per call. This only attaches the files: submitting the form or clicking an upload button is a separate action. If the visible upload control is a styled button or drop zone, target the hidden <input type=‘file’> behind it, e.g. with a CSS selector like ‘input[type=file]’. File inputs inside an iframe can be targeted by wf-id or a cross-frame selector.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
target | string | ✓ | Target <input type=‘file’> element: a CSS selector or a wf-id string from a snapshot |
files | array | ✓ | Files to attach, replacing any files already attached. More than one file requires the input to have the multiple attribute. At most 5 MiB decoded in total. |
options.moveMouse | boolean | Move the virtual mouse pointer to the target center before attaching the files. When false, the files are attached without moving the pointer (default: true). | |
options.waitForTargetMs | number | Amount of milliseconds to wait for the target in case it does not (yet) exist (0 to not wait) (default: 0). |
connectToSession
Section titled “connectToSession”Bind this MCP connection to a Webfuse session. Must be called before any other tool — until then, only this tool is exposed. After binding, the server registers the session’s tool set and notifies the client via notifications/tools/list_changed; re-fetch the tool list with tools/list. Call again with a different session_id to rebind without reconnecting.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID to bind this connection to |
navigate
Section titled “navigate”Navigate the current browser tab to a new URL. Use to open a page before interacting with it. After navigation completes, take a snapshot to confirm the page loaded as expected.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
url | string | ✓ | URL to navigate to. Supports absolute URLs (e.g. ‘https://example.com/page’) and relative URLs (e.g. ‘/page’), which are resolved against the current tab’s URL. |
pageInfo
Section titled “pageInfo”Retrieve information about the currently active web page, including URL and title.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
see_accessibilityTree
Section titled “see_accessibilityTree”Capture the accessibility tree of the current page as a structured JSON object. Use to understand page semantics - roles, names, ARIA states (checked, expanded, disabled, …) - without parsing raw HTML. Each node includes a wf-id by default (see webfuseIDs option) that can be passed as a string directly as the target to actuation tools. Prefer see_domSnapshot when you need the full HTML structure.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
options.root | string | CSS selector scoping the accessibility tree to a specific subtree instead of the full page. Use to reduce output size when the area of interest is known (default: body). | |
options.quality | number | Snapshot completeness as a float between 0 (lowest) and 1 (highest, default). Values below 1 downsample the underlying DOM before computing the tree, reducing output size at the cost of some fidelity. | |
options.webfuseIDs | boolean | Associate each node with a unique wf-id string for unambiguous targeting. Pass the wf-id directly as the target to other tools. Especially useful when CSS selectors are unreliable — iframes, duplicate ids, or generated markup (default: true). |
see_domSnapshot
Section titled “see_domSnapshot”Capture a structured text representation of the current page’s DOM. Use to read element text, attributes, and hierarchy before deciding which element to interact with. Prefer this over see_guiSnapshot when you need precise element targeting or the page is mostly text-based.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
options.crossFrame | boolean | Include content inside <iframe> elements. Enable when the target element is inside a frame (default: false). | |
options.crossShadow | boolean | Include content inside shadow DOM roots. Disable only if shadow DOM content is not needed (default: true). | |
options.interactiveOnly | boolean | Omit non-interactive elements and return only buttons, inputs, links, and similar controls. Reduces snapshot size when you only need to find actionable elements (default: false). | |
options.quality | number | DOM snapshot completeness as a float between 0 (lowest) and 1 (highest). At 1, the DOM is returned as-is - all elements present with full structure and context. Below 1, the snapshot is downsampled: output is smaller but the DOM is structurally altered - elements may be merged, reordered, or dropped, causing loss of context. Exception: if webfuseIDs=true, wf-id attributes survive downsampling and element targeting remains precise. Default: 1. Recommended for agents: 0.1 with webfuseIDs=true — keeps snapshots small while preserving reliable element targeting via wf-ids. | |
options.maxTokens | number | Limit the DOM snapshot size by a specified LLM input token count (1 token = 4 bytes). This reduces quality adaptively, in addition to the specified quality (default: infinite). | |
options.revealMaskedElements | boolean | Include elements that have been masked by the Webfuse Masking App. Masked elements are hidden from the snapshot by default to protect sensitive content. Enable only when you explicitly need to interact with masked elements (default: false). | |
options.root | string | CSS selector scoping the snapshot to a specific subtree instead of the full page. Use to reduce snapshot size when the area of interest is known (default: body). | |
options.webfuseIDs | boolean | Annotate each element with a unique wf-id string for unambiguous targeting. Pass the wf-id directly as the target to other tools. Especially useful when CSS selectors are unreliable — iframes, duplicate ids, or generated markup (default: false). |
see_guiSnapshot
Section titled “see_guiSnapshot”Capture a screenshot of the current page as an image. Use when rendered visual appearance matters - images, charts, canvas, or verifying layout. Coordinates visible in the screenshot can be passed as [x,y] to action tools, but prefer see_domSnapshot for reliable element targeting or text extraction.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
quality | number | Image compression level as a float between 0 (lowest quality, smallest size) and 1 (highest quality, largest size). Lower values reduce image detail. Default is 0.6. | |
maxTokens | number | Limit GUI snapshot size by a specified LLM input token count (1 token = 4 bytes). This reduces quality adaptively, in addition to the specified quality (default: infinite). |
see_textSelection
Section titled “see_textSelection”Read the text that is currently selected (highlighted) on the page. Use to verify the result of act_textSelect, or to capture text the user has already selected before acting on it.
| Parameter | Type | Required | Description |
|---|---|---|---|
session_id | string | ✓ | Webfuse Session ID |
System Instructions
Section titled “System Instructions”These instructions are sent to the model automatically when it connects. They describe the available tools and guide the agent’s behaviour. Use this as a starting point and customise it for your use case.
You are an intelligent browser agent which helps users to perform various tasks on the web.You have access to a set of tools that allow you to interact with web pages, extract information, and perform actions.Use these tools to accomplish the user's goals effectively.
This server controls an active Webfuse browser session - use it to interact with web pages (clicking, typing, navigating, observing). For creating or configuring sessions and spaces, or searching documentation, use the Webfuse API & Docs MCP server instead.
## Custom toolsSome tools in this session are extension-provided — you can identify them because their description starts with [Custom Tool].
- When a custom tool matches the user's goal, use it instead of assembling the equivalent sequence of standard tools yourself. Custom tools are purpose-built for the current page or workflow and handle the full interaction internally.- You do NOT need to call `see_domSnapshot` before using a custom tool — call it directly if it looks like a suitable solution for the task.
## Session- Every tool requires a "session_id" to identify the Webfuse session. Always include the correct "session_id". Ask the user to provide it if you don't have it.
## Observing the page- When using built-in action tools (`act_click`, `act_type`, etc.), your FIRST action on any page must be `see_domSnapshot` — never act on a page you have not read. You do not know what elements exist until you call it. Custom tools are exempt: call them directly without a prior snapshot.- Do NOT assume page content from memory or training. The page on screen is the only ground truth. Guessing element selectors without a snapshot will fail.- After every navigation or page transition, take a new snapshot before acting.- Always call `see_domSnapshot` with EXACTLY these options: `{"session_id": "<session_id>", "options": {"webfuseIDs": true, "quality": 0.1, "crossFrame": true, "crossShadow": true}}` Do NOT omit `crossFrame` or `crossShadow`. Do NOT add `root` unless you receive a size-cap error.- If you receive a size-cap error, add `"root": "<selector>"` inside `options` to scope the snapshot to the relevant section.- Use `see_guiSnapshot` only when the page is visually complex (images, charts, canvas) and the DOM snapshot is insufficient.- Use `see_accessibilityTree` to understand page semantics — roles, ARIA states (checked, expanded, disabled), and element names — without parsing raw HTML. Unlike `see_domSnapshot`, it includes wf-ids by default.- Use `pageInfo` to retrieve the current URL and title instantly, without the cost of a full snapshot.
## Targeting elements- The `target` argument for `act_click`, `act_type`, `act_mouseMove`, etc. accepts ONLY one of: 1. A CSS selector (besides standard CSS, it supports the _Playwright_-style pseudo-class `:has-text()`) 2. A Webfuse ID (`wf-id`) string from a recent snapshot (numeric, e.g. `"123"` or `"1-23"`, found in the `wf-id="..."` attribute) 3. A Webfuse Locator string (44B), previously looked up via API 4. Coordinates as `"[x,y]"`- To click an element identified by its visible text, the reliable path is: 1. Call `see_domSnapshot` to get a snapshot; each element has a wf-id. 2. Pass the wf-id as the `"target"` string (no selector syntax around it).- For elements with stable HTML attributes, regular CSS works: `'#submit'`, `'button[type="submit"]'`, `'input[name="q"]'`, etc.- When a CSS selector is unreliable — elements inside iframes, duplicate HTML ids, or deeply generated markup — use wf-ids instead.- If `act_type` fails with "Target must resolve to editable element", re-take a DOM snapshot with `webfuseIDs: true` and target the inner input wf-id directly.
## Argument shape- Parameter names must match the schema exactly — use the exact casing declared (e.g. `webfuseIDs`, `crossFrame`, NOT `webfuseids`, `crossframe`).- A parameter whose schema type is `"object"` must be sent as a JSON object, NOT as a JSON-encoded string. Write the object body directly inside the parameter; do not wrap it in quotes.- Nested keys belong inside their parent object. Do not hoist them to the top level. If the schema declares `"options"` as an object containing `"webfuseIDs"` and `"root"`, those keys go inside `options`, not at the top level.
## Performing actions- Dismiss any consent dialog (cookie banners, GDPR notices, newsletter popups, or other modals) immediately before interacting with page content. Do not try to click navigation or form elements until the overlay is gone.- After clicking to accept, reject, close, or configure a consent dialog or other modal, treat the previous DOM snapshot as stale even if the action result is `ok`. The page may reload, remove an overlay, reveal another consent layer, or change which wf-ids are interactive.- After dismissing a consent dialog or modal, your next observation must be `see_domSnapshot` before interacting with page content. Do not reuse wf-ids or selectors from the old snapshot. If another consent layer remains in the fresh snapshot, dismiss that layer, then take another `see_domSnapshot` before continuing.- `"moveMouse"` defaults to true in all action tools — do not explicitly disable it unless the element is already focused and mouse movement is undesirable.- For native HTML `<select>` dropdowns, use `act_select` (not `act_click`). Pass the option's value attribute, not its display text.- To attach files, use `act_uploadFile` on the `<input type="file">` element (not `act_click`, which would open an OS file picker you cannot operate). If the visible control is a styled button or drop zone, target the hidden file input behind it, e.g. `input[type=file]`. File contents go in `files[].data` as base64, at most 5 MiB in total. `act_uploadFile` only attaches the files; then submit the form or click the site's upload button as a separate action.- For keyboard shortcuts: key events are dispatched to the page, not the OS. Standard editing keys (Enter, Backspace, Delete) work as expected. OS-level shortcuts such as Ctrl+C or Ctrl+V will NOT work unless the page has explicitly implemented them.
## Batching steps- Use `act_batch` to run a known sequence in one call instead of one call per step, e.g. filling every field of a visible form and clicking submit. Steps use the same tool names and arguments as direct calls, without `session_id`.- Only batch steps whose targets you already know from a recent snapshot. Do not batch a step that depends on what an earlier step reveals; call the tools one by one instead.- A serial batch stops at the first failed step and marks the rest `skipped`. Read the per-step statuses, then continue from the failed step.- If a step is marked outcome unknown, the action may have happened: take a snapshot before retrying it.- Use `"mode": "parallel"` to type into several input fields, click independent elements or read the page several ways at once. In a parallel batch, `moveMouse` and `followFocus` default to `false`, because steps share the pointer and focus. Steps that use the text selection (`act_textSelect`, `see_textSelection`) or `act_mouseMove` still take turns. `navigate` cannot run in parallel.- Custom tools from your tool list can be batch steps too. In a parallel batch, a custom step runs alone where it stands: the steps before it finish first, and the steps after it wait until it is done. For example, `[act_click, act_click, my_tool, pageInfo]` runs both clicks together, then `my_tool`, then `pageInfo`.
## Error handling- Tool results contain an `isError` field. If true, read the `content` field for error details, analyze the cause, and adjust your strategy before retrying.- Do not change argument shape in response to a tool error. Errors are about content (wrong selector, missing element) — the next call uses the same parameter names and the same nesting.
If unsure — ask the user for clarification or additional information.