SnapSurf
OfficialThis server is a browser automation and verification MCP tool for AI agents: it navigates pages, produces semantic digests of what is on them, lets agents act (click/type/enter), and verifies exactly what changed with diff-based evidence and assertions.
Navigation & observation:
browser_openloads URLs (https/file/data), waits for onload and late-timer first paints, and returns a semantic digest (landmarks, headings, ranked actionables) plus failure/loading/challenge status.Find & context:
browser_findsearches text across the whole page;browser_parentclimbs to the enclosing card;browser_textreads one node's full text;browser_pagegives outline, map, or zoom views.Acting:
browser_actclicks (by id or x,y), types, and presses Enter with role/name confirmation;browser_scrollscrolls without acting (for lazy-loaded listings).Change verification:
browser_verifyreports what changed since the last observation (added/removed/state/style/moved/resized, coverage/visibility, carried elements across same-origin navigation) with adiffId.Assertions:
browser_assertchecks stored diffs (immutable) or live state — changed, mustInclude/mustNotInclude, maxChanges, exists, notCovered, url, becameVisible/becameCovered, retries, with fail-loud contracts for ambiguous results.Checkpoints & diffing:
browser_checkpointsaves named baselines;browser_diffcompares current state against one.Isolated sessions:
browser_session_open/browser_session_close/browser_session_listmanage parallel private browser contexts with separate cookies, storage, and id counters.Escalation:
browser_screenshotcaptures viewport or element pixels when the doubt is genuinely visual.Privacy & safety: optional redaction rules, raw form values never returned, bounded diff retention (32 records / 8 MiB / 10 min), and explicit failure modes (DNS/TLS/transport) instead of thrown strings.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@SnapSurfOpen example.com, click the login button, and verify a login form appeared."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SnapSurf
Web navigation and verification for AI agents.
Most browser tools tell an agent what a page looks like now. SnapSurf tells it what its last action changed: a compact semantic digest of the page, a typed diff after each action (content, state, layout and clickability, including when nothing observable changed), and assertions over that exact diff. Missing evidence and uncertainty are reported, not hidden.
It runs locally as an MCP server or CLI with its own Chromium session. The observation code also works as an in-page library built on SnapDOM.
Version 0.1.2 is experimental.
Add it to your MCP client
Requires Node.js 22 or newer. Add a stdio server that runs this command; Chromium for Playwright is installed automatically the first time it starts:
{
"command": "npx",
"args": ["-y", "-p", "@zumer/snapsurf@latest", "snapsurf-mcp"]
}With Claude Code, install the plugin, which adds the tools and a browse skill with the
method:
/plugin marketplace add zumerlab/snapsurf
/plugin install snapsurf@zumerlabor register the server alone:
claude mcp add --scope user snapsurf -- npx -y -p @zumer/snapsurf@latest snapsurf-mcpCodex has the same plugin (tools plus the browse skill):
codex plugin marketplace add zumerlab/snapsurf
codex plugin add snapsurf@zumerlabCursor, VS Code, Gemini CLI, Windsurf and the OpenAI Agents SDK take the same server
command; per-client snippets are in Integrations. Its name in the
official MCP Registry is io.github.zumerlab/snapsurf.
To pin a version or avoid npx at startup, install once and point the client at the
server file:
mkdir snapsurf && cd snapsurf
npm install @zumer/snapsurf{
"command": "node",
"args": ["/ABS/PATH/snapsurf/node_modules/@zumer/snapsurf/mcp/server.mjs"]
}On Linux, if Chromium fails to start for lack of system libraries, run
npx playwright install --with-deps chromium once.
Ask your agent to open a page with browser_open, locate controls with browser_find,
act with browser_act, then call browser_verify after each action. Read
structuredContent for the result.
Related MCP server: Agentic Browser
If you are an agent
Read AGENTS.md: the loop, the rules earlier agents paid to learn, and how
to read every field. skill/SKILL.md is the same method packaged as a
Claude Code skill. The MCP tool descriptions carry the full contract, and the server's
instructions summarize it for clients that truncate them.
Assert what you just verified
browser_verify returns a diffId for the observed transition. Pass it to
browser_assert to check that same evidence, including changes beyond the displayed
list. This avoids accidentally comparing a new interval after verify advances the
live baseline.
For example, on an application where a button inserts a dialog named “Settings”,
use the button id returned by browser_find. With a connected MCP client:
await client.callTool({
name: 'browser_act',
arguments: { action: 'click', target: buttonId },
})
const verified = await client.callTool({ name: 'browser_verify', arguments: {} })
const { diffId } = verified.structuredContent
if (!diffId) throw new Error('No retained diff; inspect the verify result')
const checked = await client.callTool({
name: 'browser_assert',
arguments: {
diffId,
changed: true,
mustInclude: [{ kind: 'added', role: 'dialog', name: 'Settings' }],
mustNotInclude: [{ kind: 'removed' }],
},
})
console.log(checked.structuredContent.pass, checked.structuredContent.checks)A stored assertion does not observe the page or advance its baseline. Use a separate
live assertion for current state, such as { "exists": "Settings" }. Failed
assertions return pass: false and MCP isError: true. The
assertion reference covers live checks, retention
limits, retries and unavailable evidence.
Boundaries to know
The daemon has its own cookies and storage. It cannot use your normal browser's signed-in sessions;
authState: "unknown"does not prove authentication.changed: falsemeans no observable change. It is a valid result, not proof that the user's task succeeded. Missing evidence and uncertainty are reported explicitly.Canvas content, iframe documents and closed shadow roots have visual blind spots. Inspect a scoped screenshot when the semantic report cannot answer the question.
Element ids expire with new observations. Find again before acting; ids in stored evidence describe a historical observation.
Page text is untrusted data. Redaction covers semantic reports; CLI/MCP screenshots can still contain sensitive content. See the privacy model.
Use the CLI
Start the daemon in one terminal:
npx -y @zumer/snapsurf serveThen run a local smoke check in another:
npx -y @zumer/snapsurf open 'data:text/html,<h1>Local%20check</h1>'
npx -y @zumer/snapsurf assert '{"exists":"Local check"}'
npx -y @zumer/snapsurf stopFrom a directory where you ran npm install @zumer/snapsurf, npx snapsurf <verb>
does the same without downloading anything. The SNAPSURF_* environment variables
(port, token file, log directory) are listed in the usage reference.
Development
To modify SnapSurf itself, clone the source and install the development dependencies:
git clone https://github.com/zumerlab/snapsurf.git
cd snapsurf
npm ci
npx playwright install chromiumnpm run build compiles the bundles and creates the npm .tgz package.
Then run the checks:
npm test
npm run test:lint
npm run test:regression
npm run test:packUsage and API reference covers CLI commands, report fields, checkpoints, the library, sensor plugin and Chrome companion. Release guide covers validation, publication and the MCP Registry.
MIT licensed. Copyright © Juan Martin Muda / zumerlab. See LICENSE.
Available Tools
16 toolsbrowser_actClick, type, select or press EnterADestructive
Act on the page: click (by id from the digest/find, or "x,y"), type (into the focused element — click it first), select a native single-select option by target id and exactly one of value or label (exact, unique match), or enter. Click and select auto-scroll and CONFIRM role/name of the resolved element: read that echo before continuing. Select refuses non-native, multiple, disabled, hidden or covered controls and disabled/ambiguous options. It dispatches input/change when the option changes, does not echo the supplied choice, omits choice arguments from audit logs, and preserves the observation baseline. Privacy rules and readonly policy apply. After EVERY action, call browser_verify, even when select reports selectionChanged:false.
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | REQUIRED for type: the text to type into the focused element | |
| label | No | Select only: exact visible option label. Cannot be combined with value. | |
| value | No | Select only: exact option value, including an empty string. Cannot be combined with label. | |
| action | Yes | click REQUIRES target; type REQUIRES text; select REQUIRES target and exactly one of value/label; enter needs neither | |
| target | No | REQUIRED for click/select: id n_xxx from digest/find. Click also accepts "x,y". | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses important behaviors: auto-scrolling, confirmation of resolved element role/name, refusal conditions for select, input/change dispatch, no echoing of supplied choices, audit log omissions, and preservation of the observation baseline. These details align with the destructiveHint and readOnlyHint annotations and go well beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but mostly earns its length because the tool has nuanced behaviors. A few phrases, such as 'privacy rules and readonly policy apply,' are somewhat vague, and the repeated select-specific details could be tightened, but the structure is logical and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the absence of an output schema, the description provides enough operational detail: valid action combinations, select refusal conditions, post-action verification, and observable effects like selectionChanged. The agent has sufficient context to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers all parameters, and the description adds meaningful semantics: click target can be an id or x,y coordinates, type requires a focused element, select requires exact unique match, and value/label are mutually exclusive. This significantly helps the agent pick and populate the right parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly defines the tool as a page-action tool supporting click, type, select, and enter, with specific requirements for each. It is easily distinguished from sibling tools like browser_find and browser_verify, which have different responsibilities.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong practical guidance, such as clicking before typing, requiring exactly one of value/label for select, and calling browser_verify after every action. It does not explicitly compare against alternatives, but the action-specific constraints and post-action instruction provide clear usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_assertAssert a transition or page stateARead-only
Assert the EXACT transition already read from browser_verify by passing its diffId: immutable, full diff evidence; no new observation and no baseline or id-epoch advance. Stored results return diffId, beforeObservationId, afterObservationId, observationId (the historical after observation), baselineAdvanced: false and evidenceSource: stored. Historical evidence survives later navigation; its element ids are historical, not actionable — find again before acting. Stored diffs support ONLY changed, mustInclude, mustNotInclude, only, maxChanges, becameVisible and becameCovered. Mixing diffId with exists, notCovered, url/urlIncludes, ignore, settleMs, retry or keepBaseline (even false) is pass:false; use a separate live assertion for current page predicates. Unknown, expired, evicted, foreign-session or privacy-invalidated ids return pass:false with error {code: DIFF_UNAVAILABLE, message}, never a live fallback. Without diffId, the existing LIVE assertion mode checks the diff since the last observation and consumes its baseline at the END unless keepBaseline:true; calling it after verify therefore checks a NEW interval. Checks any combination of: url (substring of the current URL), changed (expect the diff since the last observation to be true/false — the faithful negative makes "my action did nothing" ASSERTABLE), mustInclude ([{kind, role, name}] entries that must appear in the diff; kind ∈ added/removed/content/state/style/moved/resized — a framework re-render that REPLACES a node reports kind possible-replacement, and added/removed matchers accept it with STRICT side reading: an added matcher matches the after-side name/role, a removed matcher matches ONLY the before-side name/role (never the after side; selector specs never match through the alias), and the check result says "found (via possible-replacement — identity ambiguous)" instead of a plain green), exists (text findable anywhere on the page), notCovered (text whose best match must not be occluded). FAIL-LOUD CONTRACT: unknown spec keys, empty specs and missing baselines are hard pass:false with a reason — confusion never looks green. Returns structured {pass, hasBaseline, attempts, checks[], changes[]}; the diff evidence (with state from/to) travels with every result. Also: mustNotInclude (assert side-effect ABSENCE), maxChanges, becameVisible/becameCovered (actionability deltas), mustInclude entries accept selector and to:{state:value} (directional state — assert the menu IS open), settleMs and retry:{budgetMs} re-walk against the SAME baseline until pass or budget (CSS transitions land mid-flight). exists searches accessible names AND page text. SPA soft navs: results with a baseline include navigated:true + baselineUrl when the URL moved since the baseline was taken — that diff spans two pages of one document; re-observe on settled content (non-zero, stable actionables) before trusting change-based checks.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | live mode only: substring the current URL must contain | |
| only | No | change scoping: EVERY change must match one of these matchers; this does not establish causality | |
| retry | No | live mode only: re-walk against the SAME baseline until pass or budget | |
| diffId | No | opaque evidence id from browser_verify: assert that stored full transition without observing; accepts only diff predicates, never live page checks or retry/ignore/baseline options | |
| exists | No | live mode only: text that must be findable on the current page | |
| ignore | No | live mode only: CSS selectors whose subtree changes are excluded (e.g. the agent toolbar) | |
| changed | No | expected changed value for the stored diffId, or for the diff since the last observation in live mode | |
| settleMs | No | live mode only: wait before the first walk | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. | |
| maxChanges | No | full diff must contain at most N changes (after ignore in live mode) | |
| notCovered | No | live mode only: text whose best match must not be occluded on the current page | |
| mustInclude | No | changes that must appear in the diff (selector = exact; to = expected state after, e.g. {expanded:true}) | |
| keepBaseline | No | live mode only: do not consume the diff baseline (peek mode — safe to retry); incompatible with diffId even when false | |
| becameCovered | No | an actionable matching this text must have become covered | |
| becameVisible | No | an actionable matching this text must have become visible | |
| mustNotInclude | No | changes that must NOT appear (assert absence of side-effects) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint, the description discloses that live mode consumes its baseline at the end unless keepBaseline:true, making repeated calls non-idempotent. It also details error handling: unknown/expired IDs return DIFF_UNAVAILABLE, never a live fallback. This goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense paragraph with many repeated caveats and parentheticals (e.g., 'immutable, full diff evidence' and 'Historical evidence survives...'). While complex, it is not concise and would benefit from structured bullets. It is over 1000 words where a few hundred would suffice.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (two modes, many parameters, error cases, SPA navigation), the description is thorough, covering fail-loud contract, return structure {pass, hasBaseline, attempts, checks[], changes[]}, and SPA navigated flag. No output schema exists, but the description compensates.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description elaborates each parameter beyond the schema, e.g., explaining mustInclude's possible-replacement handling, directional state with to:{state:value}, that exists searches accessible names and page text, and the fail-loud contract for empty specs. Schema descriptions are minimal ('live mode only: substring...'), so the description adds crucial context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool asserts a stored transition via diffId or a live diff since the last observation, distinguishing it from browser_verify which reads the transition. The title 'Assert a transition or page state' matches.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains when to use live mode vs stored diffId mode, and explicitly warns against mixing diffId with live-only options (e.g., 'Mixing diffId with exists, notCovered, url... is pass:false; use a separate live assertion'). It also notes that calling without diffId after verify checks a new interval.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_checkpointSave a named baselineARead-onlyIdempotent
Save the currently observed state as a NAMED baseline (before a risky action). NOT undo: a comparison point for browser_diff.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already indicate readOnlyHint=true, openWorldHint=false, idempotentHint=true, and destructiveHint=false. The description adds context that saving a baseline is not an undo operation and is intended for later comparison, which clarifies its side-effect-free nature (non-destructive, idempotent). This builds on the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, consisting of two sentences that directly convey the core purpose, the recommended timing, and the relationship to browser_diff. It is well-structured and front-loaded, with no unnecessary details or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides sufficient context for an agent to decide when to call this tool: before risky actions to establish a baseline for comparison. It does not specify return values or error conditions, but given the tool's simplicity and the presence of annotations, the description is adequately complete for typical usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 50% (name lacks a description, sessionId has a description). The tool description does not elaborate on the parameters further, leaving name's purpose somewhat implicit (a label for the baseline). While sessionId's role is documented, the description does not compensate for the missing name description, so it meets only a baseline level.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Save the currently observed state as a NAMED baseline'. It also clarifies its intended use ('before a risky action') and explicitly contrasts it with undo ('NOT undo: a comparison point for browser_diff'), distinguishing it from other tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides usage guidance by specifying when to use it ('before a risky action') and its purpose as a comparison point for browser_diff. It explicitly states what it is not (undo), which helps avoid misuse. However, it does not explicitly name alternative tools or conditions for choosing them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_diffDiff against a checkpointBRead-only
Diff the current state against a checkpoint saved with browser_checkpoint: everything that changed since that known point. Note: the next browser_verify baseline becomes the current state.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds a significant behavioral detail beyond the annotations: the note about the next browser_verify baseline becoming the current state. This is not covered by readOnlyHint or destructiveHint, so the description meaningfully increases transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, clear and to the point, with the important note placed at the end. It is concise without unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides the core purpose and a key side effect, but lacks explanation of the 'name' parameter and does not specify output format. Given the absence of an output schema, the description is adequate but not fully complete for unassisted understanding.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers only sessionId with a description; the required 'name' parameter has no explanation. The description does not clarify what 'name' refers to (presumably the checkpoint name), leaving ambiguity. With only 50% schema coverage and no supplementary explanation, parameter semantics are insufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool diffs the current state against a checkpoint saved with browser_checkpoint. It is specific enough to distinguish from browser_checkpoint and browser_assert, though it does not explicitly name siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a useful note about the next browser_verify baseline becoming the current state, but it does not explicitly state when to use this tool versus alternatives. The guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_environmentConfigure this session for visual QAAIdempotent
Get or update this session’s viewport, colorScheme and reducedMotion for responsive, light/dark and motion QA. Omitted settings are preserved; with no settings this only reads the current environment. Returns environment. Updates apply to every page in this session and future popups, preserving cookies, storage, privacy rules and other sessions. The observation baseline remains unchanged (baselineAdvanced:false); call browser_verify after every update to inspect resulting page changes. Changing settings is refused under readonly policy because resize/media handlers may trigger page actions.
| Name | Required | Description | Default |
|---|---|---|---|
| viewport | No | CSS-pixel viewport. Width and height must be integers from 1 to 8192. | |
| sessionId | No | Optional session from browser_session_open. Omitted uses the shared default session. | |
| colorScheme | No | Preferred color scheme exposed to CSS and matchMedia. | |
| reducedMotion | No | Preferred reduced-motion setting exposed to CSS and matchMedia. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clearly discloses that updates apply to the session and future popups while preserving cookies, storage, privacy rules, and other sessions. It also warns that changing settings may trigger page actions and that the observation baseline remains unchanged, which aligns with the non-readOnly annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and information-dense, covering get/update semantics, persistence, side effects, policy behavior, and follow-up verification without unnecessary filler. It is well-structured and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simple scope and complete input schema, the description provides enough context for correct usage, including the return value ('Returns environment') and the important follow-up action (browser_verify). No critical behavioral gap is left unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Every parameter is documented in the schema: viewport has width/height constraints, colorScheme and reducedMotion have enums, and sessionId explains the default behavior. The description of CSS/matchMedia exposure adds meaningful context beyond basic names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The title and description clearly state that this tool gets or updates the session's viewport, colorScheme, and reducedMotion for visual QA. It explicitly distinguishes read vs. update behavior and names the exact settings involved.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use the tool (responsive, light/dark, motion QA), how omitted settings behave, when it only reads, and that browser_verify should be called after updates. It also notes that updates are refused under readonly policy, giving clear usage boundaries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_findFind text on the pageARead-onlyIdempotent
Search text across the WHOLE page (not just the visible part) and get RANKED matches in structuredContent: id, role, name, text (same string, honest label), href (mailto:/tel: pass through intact) and truncated when a value was cut. Optional contextChars allocates a TOTAL text budget across ranked matches: each included match gets context with text, totalChars, observationId and a browser_text continuation if truncated. Context uses the same frozen first-read text as browser_text; contextMatchesOmitted explicitly counts matches without context. The right tool to locate something specific on long pages — do not ask for the full outline.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. | |
| contextChars | No | Optional TOTAL context budget across ranked matches, integer 1–12000 characters. Omitted keeps compact matches. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the description adds substantial behavioral context: whole-page search, ranked match output, field semantics like 'honest label' and href pass-through, truncation, the contextChars budget, and contextMatchesOmitted. No behavior is hidden or contradictory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: scope, output shape, optional budget behavior, and usage guidance. It front-loads the core search behavior before detailing the optional contextChars mechanics, with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully explains return values: structuredContent fields, ranked matches, truncation, context contents, observationId, and the omission counter. It also covers when to use the tool and how it relates to browser_text, making it self-sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description significantly expands on contextChars, explaining that it allocates a total text budget, provides per-match context fields, and includes a continuation mechanism when truncated. The text parameter is self-explanatory and sessionId is already documented in the schema, so the 67% schema coverage is sufficiently compensated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Search') and resource ('text across the WHOLE page'), then specifies ranked matches with structured fields. It distinguishes itself from page-reading siblings by emphasizing the whole-page scope and explicitly warning against using it for a full outline.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly frames the tool as 'the right tool to locate something specific on long pages' and adds the when-not guidance 'do not ask for the full outline.' It also references browser_text as the related sibling for the underlying frozen text, giving the agent enough context to choose correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_openOpen page and read digestAIdempotent
Navigate to a URL and get the semantic DIGEST (~2-3KB): landmark regions with ids, headings with their section, and the top-15 RANKED actionables with complete absolute hrefs in structuredContent (only prose abbreviates them; privacy rules still apply). PDF links include a document hint with URL, title, evidence and source observation/id for an external PDF reader. A successful application/pdf response returns document {type, mediaType, url, title, source?, reader, textExtracted: false}, instead of pretending its text was observed; source retains the prior observation/id/title/href when an exact current link supplied the destination. Navigation metadata includes requestedUrl, finalUrl, navigationUrlsSanitized: true (navigation query values and opaque payloads remain hidden), and redirectChainAvailable. When available, redirectChain lists observed HTTP response URLs/statuses, with redirectChainScope: http, redirectChainTotal and redirectChainTruncated; client-side navigations are reflected by finalUrl, never invented as HTTP redirects. Ids (n_xxx) expire on every new observation. A top entry with placeholder: true is an EMPTY form field whose name is its placeholder — a prompt, never data from the site. Every observation reports authState and cookiesForOrigin: this tool drives ITS OWN isolated per-session BrowserContext, cookie jar and storage. authState is conservatively unknown; a cookie count is evidence, not proof of identity, because authentication can also live in storage, bearer state or the URL. For a task that needs the real signed-in session from another browser, this is the wrong instrument. If the site answered with a bot-mitigation interstitial, structuredContent carries blocked: true and challenge {vendor, reason, status, signal, and vendors when more than one is detected — vendors chain, and a confidently wrong name is worse than unknown for per-vendor retry routing}: the content was WITHHELD, which is a different answer from a page that has little on it — fall back to another fetcher rather than recording an empty result. A request that never reached an HTTP response returns failure {layer: dns|tls|transport|http, code, hostUp} instead of a thrown string — a DNS or certificate failure is neither a block nor an empty page. The open waits (bounded) for window.onload AND briefly watches the fresh document for timer-delayed first paints (entry ads armed via setTimeout at parse time), so late overlays/modals enter the FIRST digest; if the document is STILL not complete, structuredContent carries loading {readyState, waitedMs} and the prose says so — treat the digest as a truthful walk of an UNFINISHED page and re-observe before trusting completeness. Returns observationId (opaque identity of this observation) in structuredContent, and digest (marks/heads/top) in both structuredContent and prose — read the fields, do not parse the text. After a SAME-ORIGIN navigation, structuredContent may also carry carried: which strong-identity elements (data-testid / authored accessible names) persisted from the previous page and how their state/content moved (the cart badge "1"→"2"), plus only-before/only-after COUNTS of page-specific content — those counts are "different page", never removals/additions. Optional redact: session privacy rules — any name/label/text/state string containing a listed term leaves every observation as [redacted], and each observation carries an attestation that the policy ran (policyRevision, rulesActive) — never hit counts, which would tell you whether and how often the hidden term occurs. Raw form values are never returned; sensitive categories use coarse change signals and declare same-bucket uncertainty.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL (https implied; file:/data: accepted) | |
| digest | No | compact = the extraction profile: no bbox, no section, and the prose collapses to one line because the digest is already in structuredContent. Halves the per-page cost for a sweep that reads fields and never clicks. | |
| redact | No | Session privacy rules: strings to redact from every observation from now on (replaces any previous rules) | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. | |
| waitForChallenge | No | ms to wait for a bot-mitigation interstitial to clear by itself (capped at 30000). Many do within a few seconds. Omitted = do not wait, just report. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only mark non-read-only, idempotent, open-world, non-destructive. The description adds substantial behavior beyond that: isolated BrowserContext and cookie jar, conservative authState, bot-mitigation handling, failure objects, loading states, redaction attestation, and the rule that raw form values are never returned. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but dense; each paragraph addresses a distinct behavioral area (digest, PDF, navigation metadata, auth, blocking, failures, redaction). It is front-loaded with the core digest definition. It could be tightened with bullet structure, but the length is largely earned given the number of edge cases and no output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and a complex tool, the description covers return-value semantics comprehensively: digest fields, PDF document object, navigation metadata, observationId, carried elements, authState/cookies, blocked/challenge, failure, loading, and redaction attestations. An agent has enough to interpret results and decide next actions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 5 parameters are described in the schema (100% coverage), so baseline is 3. The description goes further by explaining redaction semantics (rules persist and replace previous rules, no hit counts), waitForChallenge behavior ('Many do within a few seconds'), and the intent of compact digest via cost halving. This extra context justifies a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Navigate to a URL and get the semantic DIGEST (~2-3KB)'. The digest concept (landmarks, headings, ranked actionables) is unique among the browser_* siblings, so the tool is distinguishable without needing to name an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit exclusion: 'For a task that needs the real signed-in session from another browser, this is the wrong instrument.' Also advises falling back to another fetcher when a bot-mitigation interstitial appears. It does not name specific sibling tools, but gives enough when/when-not context for routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_pageOutline, map or zoom viewARead-onlyIdempotent
Expanded views when the digest is not enough: outline (full structure trimmed to 12KB), map with offset (pages actionables beyond the top), or zoom with id (observes ONLY that subtree — the detail of a region/card; renews ids, global baseline untouched). Explicit escalation — digest first. Returns outline in structuredContent for view:"outline", with truncated when trimmed.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | REQUIRED for zoom: region/element id | |
| view | Yes | zoom REQUIRES id; map takes an optional offset | |
| offset | No | map only: start index | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent, non-destructive), the description discloses important side effects: zoom 'renews ids' and leaves the global baseline untouched, which could affect subsequent interactions. It also specifies that outline returns structuredContent with a 'truncated' flag when trimmed. These details give the agent essential knowledge about the tool's runtime behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but efficient, covering three view modes and their key behaviors in a compact format. Parenthetical clarifications keep related insights together without redundancy. Every sentence contributes either to what the tool does or when/how to use it, with no unnecessary filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description adequately covers the three view modes and their parameter interactions, making it complete for the tool's complexity. It omits some details like output structures for map and zoom or error conditions, but those are not explicitly required given no output schema. The reference to 'digest' and escalation is contextually clear from sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions already cover all four parameters, meeting the baseline for 100% coverage. The description adds meaningful context by explaining how params like offset and id drive the map and zoom modes (e.g., 'pages actionables beyond the top', 'observes ONLY that subtree'). This enriches understanding beyond the schema, warranting a score above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose as providing expanded views (outline, map, zoom) when the digest is insufficient. It explicitly lists the three view modes and what each does, making the tool's function unambiguous. The 'Explicit escalation — digest first' note further clarifies its role in the workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: use when the digest is not enough, and explicitly notes escalation from digest. It also specifies parameter dependencies (zoom requires id, map takes optional offset), guiding the agent on when to use each mode. This provides sufficient direction for selecting this tool over simpler alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_parentObserve the enclosing cardARead-onlyIdempotent
Climb from a find/digest match to the CARD around it (the nearest container with ≥2 actionables) and observe just that subtree: the way from "found the price text" to "here is the clickable title next to it". Returns the card with fresh ids; the global look baseline stays untouched. When the card carries no prose beyond its actionables and the page splits the logical card across sibling rows (HN-style tables), structuredContent also carries siblingRowText — the metadata row BESIDE the card, as declared text, never merged into the card ids. The right follow-up when browser_find located an inner node and you need its actionable context — never infer the card by id arithmetic.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | id of the inner node (from find/digest/map) | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description clearly indicates the operation is read-only ('observe just that subtree', 'global look baseline stays untouched'), consistent with the readOnlyHint and idempotentHint annotations. It also explains the return behavior, including fresh ids and the optional siblingRowText in structuredContent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is overly verbose, with repeated examples and redundant phrasing such as 'the way from found the price text to here is the clickable title next to it' and 'never merged into the card ids'. A more streamlined description would be clearer and easier to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the verbosity, the description covers important context: when to use the tool, what it returns, and the special structuredContent behavior. It lacks a formal output schema, but the prose sufficiently describes the expected result for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides full descriptions for both parameters, with 100% coverage. The description does not add significant extra meaning beyond the schema, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's purpose: climbing from an inner node found by browser_find to its enclosing card and observing that subtree. It distinguishes this from sibling tools by stating it is the right follow-up when actionable context is needed and warns against inferring the card by id arithmetic.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use the tool: after browser_find locates an inner node and the user needs its actionable context. It also provides a negative guideline ('never infer the card by id arithmetic'), which helps prevent misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_screenshotScreenshot as escalationARead-onlyIdempotent
Pixels as ESCALATION, not default: snapdom render of the viewport, or of one element (scrolled to center) when you pass an id. Only when the doubt is genuinely visual (layout, color, overlap) — for what changed there is browser_verify.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | optional: element to center | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses a side effect of scrolling to center when an id is passed, which is beyond the readOnly/idempotent annotations. It does not contradict annotations, and the readOnly hint covers the lack of destructive actions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, using two sentences with a stylistic flair ('Pixels as ESCALATION'). It is slightly unconventional but conveys all necessary information without unnecessary verbosity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides enough context for operation, including when to use it and a sibling reference (browser_verify). It does not specify the output format, but this is not required given the absence of an output schema and the typical nature of screenshot tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters (id, sessionId) are fully described in the schema, and the description adds context about the id being used to center an element. Since schema coverage is 100%, baseline is appropriate and no additional meaning is provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool captures a screenshot ('snapdom render') of the viewport or a specific element when an id is passed. It also distinguishes itself from browser_verify by emphasizing visual-only use cases.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: use only when visual doubt exists (layout, color, overlap) and not as a default; for changes, use browser_verify. This directly tells the agent when to choose this tool over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_scrollScroll without actingARead-onlyIdempotent
Scroll WITHOUT acting: by element id (to center), to "top"/"bottom", or to an absolute y in pixels. The one legitimate reason: dense listings hydrate their content lazily on scroll and the semantic walk honestly sees only the DOM that exists — scroll, then browser_verify to see what appeared. Ids from the current observation remain valid (scrolling does not re-observe). Includes a bounded settle for the lazy loaders.
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | id n_xxx, "top", "bottom", or a y offset in pixels | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (read-only, idempotent, non-destructive), the description adds important behavioral details: it does not re-observe the DOM ('scrolling does not re-observe'), includes a 'bounded settle' for lazy loaders, and clarifies that element ids remain valid. These traits are not in the annotations and significantly aid the agent's understanding.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded, with the key purpose stated first. It includes some stylistic flourishes (e.g., 'the semantic walk honestly sees only the DOM that exists') that add a bit of verbosity but do not obscure the meaning. Overall, it is well-structured and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and the lack of an output schema, the description is complete. It covers when to use the tool, behavioral expectations, parameter usage, and a recommended follow-up action. No critical information is missing for an agent to use it effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides full descriptions for both parameters with 100% coverage. The description reiterates the target types but adds little new parameter-specific information beyond the schema, such as the 'to center' detail and the note about id validity, which are more behavioral than semantic. Thus, it meets the baseline for high schema coverage but does not elevate it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool scrolls the page, explicitly distinguishing it from acting ('Scroll WITHOUT acting') and specifying the three target types (element id, top/bottom, pixel offset). It also provides a legitimate use case, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to use this tool: for lazy-loading content, with a follow-up suggestion to use browser_verify to check what appeared. It implies alternatives by contrasting with 'acting' and mentions the DOM re-observation behavior, which helps the agent decide when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_session_closeClose a sessionAIdempotent
Close a session opened with browser_session_open and free its complete context, including every popup it created. Sessions also close themselves after 10 minutes idle, so a crashed run does not leak pages.
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explains the main side effects (freeing context and closing popups) and mentions the idle auto-close mechanism, making the tool's impact on the environment clear. It does not contradict the readOnlyHint false or idempotentHint true annotations, as closing is a mutation and repeated closes are safe.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no redundant wording. It efficiently conveys the action, the scope, and the automatic behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
It covers the essential aspects for a close operation: what is closed, what is freed, and when it might not need to be called. It does not mention error conditions or return values, but those are less critical for this simple tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The sole parameter sessionId is not described in the schema, but the description references 'a session opened with browser_session_open', strongly implying that sessionId is that identifier. This compensates for the missing schema description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool closes a session and frees its context, directly naming the associated open tool. It distinguishes the action from other session operations without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implicitly conveys when to use (after opening a session) and provides the automatic timeout behavior, which helps the agent decide whether explicit closing is needed. It does not explicitly compare with sibling tools, but the context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_session_listList live sessionsARead-onlyIdempotent
List the live sessions with their current URL, observation number and idle time.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description accurately reflects the read-only nature (no side effects) consistent with the readOnlyHint annotation. It adds useful detail about what information is returned (URL, observation number, idle time), which goes beyond the bare annotation, though it does not explicitly state that no sessions are modified or destroyed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, compact sentence that conveys all necessary information without redundancy or extraneous details. It is well-structured and immediately clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of an output schema, the description provides sufficient context by naming the specific fields (current URL, observation number, idle time) that will be included in the list. This is adequate for a simple listing operation, though it could mention that the list is non-empty or how sessions are ordered, but these are minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, so the input schema is fully transparent (100% coverage). The baseline for zero parameters is 4; the description does not need to add anything about parameters, and it does not introduce any ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (list live sessions) and specifies the included details (current URL, observation number, idle time). It is distinct from sibling tools like browser_session_open and browser_session_close, which handle session lifecycle, not listing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly state when to use this tool versus alternatives. While the distinction from open/close is obvious from the tool name, the description lacks explicit guidance such as 'use this to check active sessions before opening a new one' or comparisons to other browser_session_* tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_session_openOpen an isolated sessionA
Open an independent browsing session and get its sessionId and environment. Optional viewport, colorScheme and reducedMotion configure responsive/media QA before navigation; defaults are 1280×800, light, no-preference. Each session owns a private BrowserContext, cookie/storage jar, popup tree, observation counter and ids, so several sweeps run AT THE SAME TIME without invalidating or authenticating each other. Pass the returned sessionId on every call belonging to that sweep. Close it with browser_session_close when done.
| Name | Required | Description | Default |
|---|---|---|---|
| viewport | No | CSS-pixel viewport. Width and height must be integers from 1 to 8192. | |
| colorScheme | No | Preferred color scheme exposed to CSS and matchMedia. | |
| reducedMotion | No | Preferred reduced-motion setting exposed to CSS and matchMedia. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since annotations carry no hints (all false), the description carries the full burden. It discloses the private BrowserContext, cookie/storage jar, popup tree, observation counter, and IDs, and explains that sessions are isolated and concurrent. It also states the requirement to pass sessionId. This is substantial transparency for a tool with no annotation assistance.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences: the first states the core action and return values, the second covers optional parameters and defaults, the third explains isolation and usage. It is front-loaded and each sentence adds essential information. Slightly longer than ideal but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an opening tool with no output schema, it explains what is returned (sessionId and environment), how to use the session (pass sessionId on every call), when to close it, and the concurrency benefit. The only minor gap is not detailing what 'environment' contains, but that is likely a return field described elsewhere. Overall, it is sufficiently complete for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful context: it states the defaults (1280×800, light, no-preference) and explains the purpose of the parameters ('configure responsive/media QA before navigation'). This goes beyond the schema's per-parameter descriptions, which only define types and enums.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (Open), a specific resource (independent browsing session), and the outcome (sessionId and environment). It clearly distinguishes itself from siblings like browser_open (which likely opens a page in a session) and browser_session_close (which closes a session). The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly mentions the concurrency benefit ('several sweeps run AT THE SAME TIME without invalidating or authenticating each other') and gives direct instructions to 'Pass the returned sessionId on every call belonging to that sweep' and 'Close it with browser_session_close when done.' While it does not name alternative tools, the context clearly implies when to use this vs. a standard open.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_textRead the text of one nodeARead-onlyIdempotent
Read visible text of ONE node or section by id, with a bounded character budget (maxChars defaults to 600, maximum 12000). Returns text, textSource, capturedAt (first-read timestamp), totalChars, returnedChars, offset, nextOffset, truncated, observationId and continuation in structuredContent. Pass a non-null continuation directly to browser_text for the next slice; it includes sessionId. offset > 0 requires observationId from the initial read. The first read freezes redacted text at capturedAt (not at observation time) so later slices cannot splice a changing document; re-observe and re-find to refresh it. Snapshot storage is bounded per observation (1000000 UTF-16 units / 128 nodes); exceeding it returns an explicit error. Continuations fail on expired observations, detached ids, navigation or privacy-policy changes. Offsets count JavaScript UTF-16 code units. A cut value must be continued, not recorded as complete; the prose also marks truncation.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| offset | No | Integer start offset; default 0. Positive offsets require observationId and an initial read. | |
| maxChars | No | Integer characters per slice, 1–12000; default 600. | |
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. | |
| observationId | No | Observation owning the initial text read; required when offset > 0. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/idempotentHint annotations by disclosing that the first read freezes redacted text at capturedAt, later slices cannot splice a changing document, storage is bounded per observation, and continuations fail on expired observations, detached ids, navigation, or privacy-policy changes. This is rich, non-obvious behavioral detail an agent needs to use the tool correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core read operation and budget, then proceeds through continuation mechanics, snapshot semantics, limits, and failure modes. Every sentence carries distinct information; there is no filler or repetition of annotation facts.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even without an output schema, the description enumerates all returned fields, explains truncation behavior, documents failure conditions, and covers pagination prerequisites. For a read/pagination tool this is unusually complete; an agent has what it needs to invoke initial reads and continuations safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 80% and already describes offset, maxChars, sessionId, and observationId, so the baseline is 3. The description adds meaningful value: id targets a node/section, maxChars defaults to 600, offsets count JavaScript UTF-16 code units, and continuation includes sessionId. This strengthens understanding beyond the schema, though the schema still carries most parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Read') with a specific resource ('visible text of ONE node or section by id') and immediately differentiates itself as a single-node reader with bounded pagination. This clearly separates it from sibling tools like browser_find, browser_verify, or browser_scroll.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear operational context: how to make an initial read, how to continue with continuation, and when offset requires observationId. It does not explicitly name alternative tools for finding or re-observing nodes, but it does instruct to 're-observe and re-find' for refresh, which gives practical guidance without exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
browser_verifyVerify what changedARead-only
WHAT CHANGED since the last observation — the verification of your action. Returns changed (a faithful negative: if your click did nothing it says so instead of letting you believe you acted), the list of changes with kind (added/removed/state/style/moved) role and name, and what became covered or visible. Possible replacements also carry beforeName, so the prior and current identities are both explicit. Call it after EVERY action instead of comparing screenshots, then pass its diffId to browser_assert to check THIS exact transition. When a baseline exists, a full observation returns diffId, beforeObservationId, afterObservationId, observationId (the after observation), and baselineAdvanced: true. A stored diff covers the FULL evidence, including changes beyond the presentation cap and folded wrappers. No baseline means no diffId. Retention is bounded per session (32 records, 8 MiB total, 10 minutes); an individually oversized record returns diffAvailable: false and diffError: {code: DIFF_TOO_LARGE, message}, without a diffId. structuredContent carries changed, changes (list of {kind, role, name, beforeName?, id, from?, to?}), changesTotal, changesShown, changesOmitted, and changesOmittedByKind — read those rather than parsing the prose. State changes include their before/after state in from/to. Reading aids: the capped changes summary prioritizes state, content, and actionability-related changes before other semantic changes and geometry; omissions, including folded wrappers, are explicitly counted by kind. It omits folded wrapper nodes of an ADDED subtree (identity-free generic wrappers only — authored names never fold; foldedWrappers counts them and changesTotal is the full diff count), and geometryOnly: true flags a diff that is ONLY moved/resized AND changed no actionability — a scope reflow (scrollbar, container resize) you can skim past. After a same-origin navigation, carried reports the strong-identity elements that persisted across pages and their state/content transitions (see browser_open).
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | No | optional: the session this call belongs to (from browser_session_open). Omitted uses the shared default session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description discloses detailed behavioral aspects: it returns a diff ID, handles omitted changes by kind, includes geometry-only flags, and clarifies how folded wrappers are treated. It fully explains what happens in edge cases (no baseline, oversized diffs), exceeding annotation information.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is overly verbose and repetitive. It repeats concepts like 'folded wrappers' and 'geometryOnly' in different phrasings, and the long paragraph lacks clear structure or bullet points. The core information could be conveyed in half the length, making it less efficient for an agent to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite verbosity, the description is exceptionally comprehensive. It covers return fields (changes, changesTotal, etc.), edge cases (no baseline, oversized diffs), special flags (geometryOnly), and persistence across navigation. An agent receives all necessary context to understand expected outputs and behaviors without needing additional information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single optional parameter sessionId, and the description adds no extra semantic detail beyond the schema. The parameter is clearly optional with a default behavior (shared default session), so the schema is sufficient; a score above baseline is given because the description reinforces the optionality and context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool verifies what changed since the last observation, with a specific verb ('verify') and resource ('what changed'). It distinguishes itself from siblings like browser_diff and browser_assert by focusing on verification and returning a diff ID for assertion, making its unique purpose evident.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: 'Call it after EVERY action instead of comparing screenshots' and 'then pass its diffId to browser_assert to check THIS exact transition.' This gives concrete when-to-use instructions and even directs the next step, leaving no ambiguity about usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v0.1.3- Changed
browser_act5 fields changed- changed
Input schema / properties / action / descriptionPrevious value: -"click REQUIRES target; type REQUIRES text; enter needs neither"New value: +"click REQUIRES target; type REQUIRES text; select REQUIRES target and exactly one of value/label; enter needs neither" - changed
Input schema / properties / action / enumPrevious value: -[ - "click", - "type", - "enter" -]New value: +[ + "click", + "type", + "select", + "enter" +] - added
Input schema / properties / labelAdded value: +{ + "description": "Select only: exact visible option label. Cannot be combined with value.", + "type": "string" +} - changed
Input schema / properties / target / descriptionPrevious value: -"REQUIRED for click: id n_xxx from the digest/find, or \"x,y\""New value: +"REQUIRED for click/select: id n_xxx from digest/find. Click also accepts \"x,y\"." - added
Input schema / properties / valueAdded value: +{ + "description": "Select only: exact option value, including an empty string. Cannot be combined with label.", + "type": "string" +}
- Added
browser_environment - Changed
browser_session_open3 fields changed- added
Input schema / properties / colorSchemeAdded value: +{ + "description": "Preferred color scheme exposed to CSS and matchMedia.", + "enum": [ + "light", + "dark", + "no-preference" + ], + "type": "string" +} - added
Input schema / properties / reducedMotionAdded value: +{ + "description": "Preferred reduced-motion setting exposed to CSS and matchMedia.", + "enum": [ + "reduce", + "no-preference" + ], + "type": "string" +} - added
Input schema / properties / viewportAdded value: +{ + "description": "CSS-pixel viewport. Width and height must be integers from 1 to 8192.", + "properties": { + "height": { + "maximum": 8192, + "minimum": 1, + "type": "number" + }, + "width": { + "maximum": 8192, + "minimum": 1, + "type": "number" + } + }, + "required": [ + "width", + "height" + ], + "type": "object" +}
2 tool updates
v0.1.2- Changed
browser_find1 field changed- added
Input schema / properties / contextCharsAdded value: +{ + "description": "Optional TOTAL context budget across ranked matches, integer 1–12000 characters. Omitted keeps compact matches.", + "maximum": 12000, + "minimum": 1, + "type": "number" +}
- Changed
browser_text3 fields changed- added
Input schema / properties / maxCharsAdded value: +{ + "description": "Integer characters per slice, 1–12000; default 600.", + "maximum": 12000, + "minimum": 1, + "type": "number" +} - added
Input schema / properties / observationIdAdded value: +{ + "description": "Observation owning the initial text read; required when offset > 0.", + "type": "string" +} - added
Input schema / properties / offsetAdded value: +{ + "description": "Integer start offset; default 0. Positive offsets require observationId and an initial read.", + "minimum": 0, + "type": "number" +}
15 tool updates
v0.1.1- First observed
browser_act - First observed
browser_assert - First observed
browser_checkpoint - First observed
browser_diff - First observed
browser_find - First observed
browser_open - First observed
browser_page - First observed
browser_parent - First observed
browser_screenshot - First observed
browser_scroll - First observed
browser_session_close - First observed
browser_session_list - First observed
browser_session_open - First observed
browser_text - First observed
browser_verify
TDQS
Scored across 16 tools
Every tool targets a distinct operation—navigation, acting, verification, diffing, searching, reading, viewing, scrolling, and session management—so an agent can reliably pick the right one. Even the diff-related tools (browser_verify and browser_diff) are cleanly separated by their baselines: post-action vs checkpoint.
All tools share the browser_ prefix and snake_case, with a mostly verb-first pattern (open, act, find, scroll, verify, assert). A few names are noun-like (browser_text, browser_page, browser_environment, browser_parent), but the overall convention remains predictable and readable.
At 16 tools, the set sits just above the ideal 3–15 range, but each tool carries real weight for a browser automation server. The count feels justified by the breadth of navigation, observation, interaction, verification, and session management responsibilities.
The core browse → observe → act → verify → assert loop is fully supported, including sessions, environments, and diff-based assertions. Minor gaps like explicit back/forward navigation or direct cookie APIs are absent, but these are workaroundable and do not break typical workflows.
Maintenance
Related MCP Connectors
Headless browser primitives for AI agents when sites need real JS rendering.
AI-powered web automation. Navigate websites using AI agents for one page or a thousand
AI-powered web automation. Navigate websites using AI agents for one page or a thousand
Stealth web automation for AI agents. Login, signup, navigate, screenshot.
Related MCP Servers
- AlicenseAqualityAmaintenanceGives AI agents a compact, semantic interface to the browser, returning structured page snapshots with stable element IDs instead of raw DOM. Enables agents to navigate, interact, and extract information from web pages efficiently.6261615MIT
- AlicenseNot gradedqualityAmaintenanceEnables agents to control a real Chromium browser with semantic tools, providing compact observations and outcome-verified actions for web interaction tasks.1MIT

QualityMax QA MCPofficial
AlicenseAqualityAmaintenanceEnables coding agents to independently verify web changes by scanning pages, inspecting UI structure, generating Playwright reproductions, and executing tests with structured QA evidence.41482MIT- FlicenseAqualityCmaintenanceEnables AI agents to rapidly drive and inspect real web pages through persistent browser sessions, using accessibility-tree snapshots and DevTools-grade diagnostics to identify and diagnose issues.23-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/zumerlab/snapsurf'
If you have feedback or need assistance with the MCP directory API, please join our Discord server