Tools and flow
Tool names have thebrowser_ prefix:
create_upload {name,size,sha256?}prepares one exact-length upload (optional lowercase hex SHA-256).- PUT the bytes using the returned capability.
transfer_status {resourceId}reports browser-local verification state. Gateway transfer status is separately keyed bytransferId. upload_files {tabId,fileIds,ref?|selector?|chooserId?,frames?}explicitly attaches completed staged IDs. No arbitrary filesystem path or inline bytes are accepted. The runtime retains the exact target element and checks its document generation; it never re-resolves a stale chooser. Attachment can immediately submit data to a website. An uncertain attachment must not be retried automatically.list_downloads {}lists actual browser download files.create_download {fileId}grants GET for that exact completed file, never a replay of its URL/request. POST/blob/data/one-use links work through Chrome’s actual Download stream.cancel_transfer {resourceId}cancels a staged data resource. The existing{tabId,eventId}chooser/download cancellation has separate runtime semantics. Already attached bytes cannot be recalled; backing files remain until document/session lifecycle ends.capture_secrets {tabId,code,frames?}admits a bounded transaction. Within that function only, useawait browserMcp.secrets.set('TOKEN', document.querySelector('#token').value). The helper is not installed onwindowor as a global Playwright binding. It has no reader.list_secrets {}returns vault IDs/names/counts/expiry only;delete_secrets {vaultIds}deletes selected captures.create_secret_export {vaultId,names,format:'json'|'dotenv'}explicitly selects names from one capture and creates a short-lived immutable export. No automatic all-secrets export.
HTTP contract
Capability JSON includestransferId, resourceId, method, url, headers.Authorization, expiresAt (epoch ms), and limits. The agent endpoint is /api/native-data/<opaque-id>; a distinct bearer on /runtime is only for the browser host. Credentials are header-only; query strings, ambient cookies, Origin headers, redirects and ranges are rejected. No cookie authority or CORS permission.
Both sides and all joined streams expire at the absolute 60-second grant deadline (or earlier issuer expiry); attachment never extends it. The server revalidates issuer scope before issuance/redemption and every second during active leases, with a 900 ms fail-closed authorization deadline. All grants permit exactly one request per side, including ordinary files. Ranges/resumption/automatic retries are unsupported. After an ambiguous reply, query state rather than repeat the PUT or browser attachment. Request a new grant when needed; secret exports always require a fresh grant after uncertain delivery. Revocation aborts joined streams. Relay restart loses all grants.
Default ceilings: 256 MiB/file; 512 MiB/session; 1 GiB/browser-local spool and gateway browser reservations; 4 GiB/global gateway reservations; 32 concurrent gateway leases and 4 per authenticated session; 1,024 retained gateway lease records (including completed/cancelled metadata, expiring after four minutes); 128 local resources. Gateway queue watermarks are 64 KiB measured in bytes. Incoming HTTP chunks are sliced into 64 KiB writes with awaited backpressure; only one upstream chunk is retained at a time. The HTTP parser’s incoming allocation remains bounded by the request/file ceiling and concurrency, not by the gateway queue watermark. Streams use bounded backpressure, not full-file memory buffers. Prepared files expire after five minutes; attached upload backing files survive until document/tab/session cleanup (relay disconnect/pause retains already attached backing files while pages survive). Private directories/files use modes 0700/0600. Only manifest-owned paths are deleted. Crash directories are intentionally retained rather than guessed safe to delete.
Chrome’s original temporary spool is guarded by the native lifecycle’s CDP download-progress admission: 256 MiB/file, 512 MiB aggregate active downloads, eight concurrent downloads and a ten-minute deadline. Installation fails closed if CDP download admission cannot be enabled. The plugin makes a bounded Download.createReadStream() copy, then deletes only that exact Download’s original spool (also on failure). Progress cancellation is reactive and can overshoot between events; production needs an OS/filesystem quota for a hard whole-profile disk ceiling. No user’s Downloads directory is scanned.
HTTPS is mandatory. Server/plugin constructors can explicitly enable allowInsecureLoopback for development-only localhost/127.0.0.1/[::1] HTTP fixtures; this is not permitted for remote origins. Agent helpers remain HTTPS-only.
Agent commands
Store capability JSON in a private mode-0600 file (or supply it via stdin), never a literal bearer argument:exec invokes an executable with shell:false, injecting parsed values directly into its environment. The child can expose those values through its own output; its output is not magically redacted. NUL-containing environment values are rejected.
Curl interoperability uses a protected header file, not a token in command arguments:
Authorization: Bearer ..., must be mode 0600, and must never be committed. Curl output permissions/overwrite protection are the caller’s responsibility (prefer helper commands). Do not use --location or automatic retries.
Secret contract and limits
Variable names match[A-Za-z_][A-Za-z0-9_]*. Duplicate names within a capture reject the entire transaction; each successful capture creates a separate immutable version/vault ID. Maximum 128 variables/capture and 128 characters/name, 64 KiB UTF-8/value and 1 MiB aggregate runtime vault accounting (including names and per-entry overhead), five-minute TTL. Empty captures are rejected; entry ceilings are 32/session, 64/browser and 128/runtime. Exports recheck revocation and document identity after asynchronous resolution and immediately before resource admission. The capture deadline is 15 seconds. A timed-out page function may still execute, but it cannot commit to the vault; do not blindly re-run it. Diagnostics remain suppressed until its actual evaluation settles.
Capture return values are discarded. Exceptions are replaced with fixed errors; normal metadata contains no plaintext or plaintext-derived digest. Vault scope includes browser instance, authenticated credential/session, tab, origin and document generation. Navigation/tab close/session end/disconnect revoke vaults and exports and abort in-progress browser data requests. JavaScript memory offers no secure-erasure guarantee.
JSON is lossless for arbitrary strings. The documented dotenv dialect is exactly NAME=<JSON string> per line, with JSON escaping for newlines/quotes/backslashes/Unicode. The matching parser does no interpolation. This deliberately is not shell syntax and is not guaranteed compatible with every third-party dotenv package. Never source untrusted page-derived text.
This protects the dedicated capture path from accidental transcript leakage; it is not universal redaction. Arbitrary JavaScript, normal page text, screenshots/live view, malicious same-user processes, authorized client shells and the TLS-terminating server operator remain outside that guarantee. Operator-blind encryption and a trusted non-model capability delivery channel are not implemented.