Jelly / Developer documentation

What can Jelly do?

Jelly gives your AI assistant tools to read pages, click and type, check results, capture evidence, and ask for help. This guide shows which tool to use, then provides the exact inputs and outputs for developers.

What is a tool surface? It is the set of tool names Jelly shows to a connected AI assistant. The default small surface groups browser actions behind three tools: browser-schema, browser-call, and browser-events. The large surface exposes individual actions such as click and read-page as separate tools. Both use the same Jelly browser engine; this choice changes how the AI calls tools, not where Chromium runs. Compare the surfaces below.

Start here: three basic browser tools

An MCP tool is an action an AI assistant can request from Jelly. You do not have to write JSON to use one through a connected AI client. For ordinary browser work, these three tools cover discovery, actions, and live events.

01 / DISCOVER

Find out what Jelly can do

browser-schema shows browser operations such as reading a page, finding a button, or checking a result. It does not change the page.

02 / ACT AND CHECK

Use the browser

browser-call carries out browser operations: read content, click, type, and explicitly verify what happened.

03 / OBSERVE (OPTIONAL)

Follow browser activity

browser-events lets an agent subscribe to and inspect retained browser events when a task needs them.

New to Jelly? Follow Getting Started to install and connect it. When ready, try the first working MCP example, or copy the startup prompt to confirm tool discovery from your AI chat. A successful browser action alone does not prove the requested outcome; use a verification operation when the result matters.

Find a tool by what you want to do

Use these links when you know the task but not the tool name. Each tool below has its own technical reference, including required inputs, permissions, possible failures, and examples.

Browse and interact

Capture what happened

Work with files

Coordinate a task

For developers: authentication and responses

Jelly currently publishes 16 tools through the default MCP configuration. A running Jelly server tells each AI client which tools and parameters are available.

Show MCP schemas, authentication, and response formats

The checked-in [mcp].surface = "small-surface" publishes the three browser tools below plus thirteen system tools. Each has an authentication requirement: a valid static bearer token or OAuth access token with the jelly scope. The envelope for each successful call is result.structuredContent = {ok:true,data:…,error:null,meta:{tool:"…"}}; failures include ok:false, a typed error.kind, human-readable message, and retryable. The data field may be parsed CLI text or a structured value depending on the binding; example data below is schematic, not recorded execution output.

Source of truth: the running server's tools/list schema. Browser semantic operations are discovered with browser-schema and executed with browser-call. The large-surface alternative instead publishes individual browser primitives; see the generated internal capability index, but confirm remote publication through tools/list.

browser-schema

Discover semantic browser operations

Show parameters, permissions, and example request
Parameters
action: string (required: capabilities | search | schema); query: string required for search; limit: integer 1–50, default 8; operation: string required for schema
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Read-only; no browser session required
Expected failures
Invalid action/arguments; unknown operation (unsupported)
Output
structuredContent with ok, data, error, meta; example data shape: {"action": "capabilities", "schema_version": 1, "operation_count": "number", "categories": "array"}
Example tools/call parameters
{
  "name": "browser-schema",
  "arguments": {
    "action": "capabilities"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

browser-call

Read pages, interact with controls, and explicitly check results. Raw CDP is an advanced option.

Show parameters, permissions, and example request
Parameters
calls: array of 1–64 items (required), each {call:{jelly:string,params?:object},target?:string}; when raw CDP enabled, a call may have scope: target | browser and {call:{method:string,params?:object}}; on_error: stop | continue (default stop)
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Mutates/reads browser; raw CDP can access browser-wide state
Expected failures
browser_unavailable, invalid_arguments, target_stale, cdp_failed
Output
structuredContent with ok, data, error, meta; example data shape: {"calls": "per-call outcomes, ordered"}
Example tools/call parameters
{
  "name": "browser-call",
  "arguments": {
    "calls": [
      {
        "call": {
          "jelly": "read-page",
          "params": {}
        }
      }
    ]
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

browser-events

Subscribe/poll/unsubscribe retained Chromium events

Show parameters, permissions, and example request
Parameters
action: subscribe | poll | unsubscribe (required); subscribe accepts target?: string, methods?: string[], method_prefixes?: string[]; poll requires subscription_id: string, limit?: integer; unsubscribe requires subscription_id: string
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Reads CDP event stream; uses process-wide persistent browser session
Expected failures
subscription_not_found, browser_unavailable, unsupported
Output
structuredContent with ok, data, error, meta; example data shape: {"action": "subscribe", "subscription_id": "opaque ID", "cursor": "stream cursor"}
Example tools/call parameters
{
  "name": "browser-events",
  "arguments": {
    "action": "subscribe",
    "methods": [
      "Target.targetCreated"
    ]
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

open-browser

Start native Chromium, or connect to the selected remote CDP browser, and optionally open a URL

Show parameters, permissions, and example request
Parameters
url?: string
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Starts browser and may navigate to URL
Expected failures
browser_unavailable
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "browser start result"}
Example tools/call parameters
{
  "name": "open-browser",
  "arguments": {
    "url": "https://example.com"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

close-browser

Stop managed native Chromium; remote mode detaches Jelly without stopping external Chromium

Show parameters, permissions, and example request
Parameters
No arguments ({})
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Stops process-wide browser; may interrupt other clients
Expected failures
browser_unavailable
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "browser stop result"}
Example tools/call parameters
{
  "name": "close-browser",
  "arguments": {}
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

browser-task

Open page and perform a scoped CLI operation

Show parameters, permissions, and example request
Parameters
url: string, tool: string (required); args?: string[]; persist?: boolean (default false)
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Starts browser, runs operation; normally closes browser
Expected failures
browser_unavailable, tool failure
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "tool execution result"}
Example tools/call parameters
{
  "name": "browser-task",
  "arguments": {
    "url": "https://example.com",
    "tool": "read-page"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

profile-import

Copy a closed Chromium profile into Jelly

Show parameters, permissions, and example request
Parameters
source: string (required); force?: boolean (default false)
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Replaces/imports sensitive cookies and profile state
Expected failures
interaction_failed
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "import result"}
Example tools/call parameters
{
  "name": "profile-import",
  "arguments": {
    "source": "/path/to/closed-profile"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

screenshot

Capture viewport or selected page target

Show parameters, permissions, and example request
Parameters
target?: string; output?: string
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Writes browser screenshot artifact
Expected failures
artifact_failed
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "screenshot metadata"}
Example tools/call parameters
{
  "name": "screenshot",
  "arguments": {
    "target": "css:body"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

record-browser

Start/stop a browser-only video recording

Show parameters, permissions, and example request
Parameters
action: start | stop (required); mode?: continuous | steps; interval_ms?: integer ≥100 (default 500); hold_ms?: integer ≥100 (default 1000)
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Writes recordings and temporary frame state
Expected failures
artifact_failed
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "recording state"}
Example tools/call parameters
{
  "name": "record-browser",
  "arguments": {
    "action": "start",
    "mode": "steps"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

download

List, inspect, wait for, explicitly transfer, or cancel Chromium downloads

Show parameters, permissions, and example request
Parameters
action: list | status | wait | transfer | cancel (required); id?: string (required for status/wait/transfer/cancel); seconds?: integer ≥1 (default 30); destination?: string; collision?: fail | overwrite | uniquify (default fail)
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Reads download state; cancel/wait/transfer/destination can mutate/write files. Remote-only waits do not copy files; transfer requires an operator-provided HTTP(S) artifact bridge.
Expected failures
download_failed, condition_timeout
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "download lifecycle records"}
Example tools/call parameters
{
  "name": "download",
  "arguments": {
    "action": "list"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

downloads

List files in legacy download directories

Show parameters, permissions, and example request
Parameters
No arguments ({})
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Read-only filesystem listing
Expected failures
download_failed
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "file listing"}
Example tools/call parameters
{
  "name": "downloads",
  "arguments": {}
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

verify-artifact

Check an existing screenshot/download artifact

Show parameters, permissions, and example request
Parameters
artifact: string (required); semantic_checks?: string[]
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Reads artifact and may update verification state
Expected failures
artifact_failed
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "verification metadata"}
Example tools/call parameters
{
  "name": "verify-artifact",
  "arguments": {
    "artifact": "artifact-id-from-screenshot"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

wait-download

Wait for a recently initiated download

Show parameters, permissions, and example request
Parameters
after_ms: integer ≥0 (required); seconds?: integer ≥1 (default 30); name_contains?: string
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Waits for/registers a completed artifact
Expected failures
download_failed, condition_timeout
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "download result"}
Example tools/call parameters
{
  "name": "wait-download",
  "arguments": {
    "after_ms": 0
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

inspect-network

Start, stop or inspect CDP request capture

Show parameters, permissions, and example request
Parameters
action: start | stop | show (required); filters?: string[]
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Starts/stops capture; writes network metadata
Expected failures
internal, browser_unavailable
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "network capture result"}
Example tools/call parameters
{
  "name": "inspect-network",
  "arguments": {
    "action": "show"
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

call-routine

Save, list, inspect, run, or resume named JSON graph workflows. Routines can have descriptions, variables, conditions, loops, and calls to other routines. See a practical routine example →

Show parameters, permissions, and example request
Parameters
Run with name and optional string vars; resume with resume_id; or use action: "list" | "describe" | "save". Saving requires a JSON graph with its name, description, entry, and nodes.
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Running a routine may modify browser state. Saving validates and writes a new JSON file without executing it or overwriting an existing routine.
Expected failures
typed routine/tool errors
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "routine result"}
Example tools/call parameters
{
  "name": "call-routine",
  "arguments": {
    "name": "verified-screenshot",
    "vars": {
      "url": "https://example.com/",
      "target": "css:body"
    }
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

hitl

Request human intervention via Telegram

Show parameters, permissions, and example request
Parameters
message: string (required); video?: path; screenshot_target?: string; no_screenshot?: boolean
Permissions
Bearer token or OAuth jelly scope (global tool access)
Side effects
Sends message/screenshots/video to external Telegram chat
Expected failures
delivery_failed
Output
structuredContent with ok, data, error, meta; example data shape: {"stdout": "delivery result"}
Example tools/call parameters
{
  "name": "hitl",
  "arguments": {
    "message": "Please review the current page",
    "no_screenshot": true
  }
}

Replace placeholder IDs and paths with real runtime values before calling this tool. The request uses JSON-RPC method tools/call.

Advanced: multiple browsers and remote downloads

Show browser IDs, remote storage, and security details

When the remote CDP backend is configured, tools/list adds optional top-level browser_id to tool inputs. Select the immutable UUID or an easy name such as Jelly-Applepie. This chooses a Chromium instance; target still chooses a page inside that browser. The native backend omits this field. Remote download policies are remote-only, shared-volume and transfer. Explicit download action: "transfer" uses a separately configured HTTP(S) file bridge; HTTP transfers are unencrypted and warned about. Browser connection and sandbox security choices are independent of the MCP client authentication policy.

Choosing a tool surface

A surface is the list of MCP tools visible to your AI client. The small surface (the default) offers three general browser tools plus 13 system tools. The large surface offers individual browser operations, such as click and read-page, plus the same system tools. You do not need to switch surfaces to choose native Chromium, Docker/Podman, or remote CDP.

Query tools/list on the running MCP server for the active catalog and input schemas. See the MCP reference for deployment settings and advanced configuration.

Expanded large-surface API

When [mcp].surface = "large-surface", the three browser façade tools are replaced by 47 individual browser primitives described below. All 13 system tools above remain published. Since the current raw CDP configuration, this alternate mode additionally exposes cdp-call, totaling 61 tools. Confirm the active set using the runtime tools/list.

Shared permissions: bearer token or OAuth jelly scope. Shared result: structuredContent containing ok, data, error, meta.tool. Common errors: invalid_arguments, browser_unavailable, plus typed target/condition/script failures as appropriate. Each example below is a JSON params.arguments object for a tools/call request with params.name equal to the corresponding primitive name.

Show the expanded browser operations, arguments and raw CDP reference

On smaller screens, scroll sideways within the table to view all five columns.

Tool Description / usage Named parameters (* required) Side effects Example arguments
clickinput Dispatch a click to a visible element. This confirms the interaction was performed, not the resulting application state.click <target> target *: target Modifies page/input state {"target": "css:body"}
type-textinput Type text into a visible editable element, optionally targeting a specific element.type-text <text> [target] text *: string, target: target Modifies page/input state {"text": "Example"}
fillinput Replace the current contents of a visible editable element and dispatch input/change events.fill <text> [target] text *: string, target: target Modifies page/input state {"text": "Example"}
press-keyinput Dispatch a keyboard key to the currently focused page element.press-key <key> key *: string Modifies page/input state {"key": "name"}
selectinput Select an option in a native select element by value or visible option text.select <target> <value> target *: target, value *: string Modifies page/input state {"target": "css:body", "value": "Example"}
checkinput Ensure a checkbox or other checkable element is checked.check <target> target *: target Modifies page/input state {"target": "css:body"}
dialoginput Accept or dismiss the active JavaScript dialog, optionally supplying prompt text.dialog <accept|dismiss> [text] action *: string, text: string Modifies page/input state {"action": "dismiss"}
draginput Drag an element to another element or explicit viewport coordinates using pointer events.drag <source> <target|x:N,y:N> source *: target, destination *: string Modifies page/input state {"source": "css:body", "destination": "css:main"}
waitnavigation Wait until text, CSS, visibility, URL, disappearance, or a JavaScript condition is satisfied.wait <text|css|visible|url|gone|js> <value> [seconds] condition *: string, value *: string, seconds: integer Navigation/wait; may change page {"condition": "visible", "value": "Example"}
navigatenavigation Navigate the active tab and report the observed URL/title/readiness. Use verification primitives for application-state guarantees.navigate <url> url *: string Navigation/wait; may change page {"url": "https://example.com/"}
tab-historynavigation Move the active tab backward or forward in its navigation history.tab-history <back|forward> direction *: string Navigation/wait; may change page {"direction": "back"}
wait-forverify Wait with a finite deadline for an explicit page or target condition and return the observed evidence.wait-for <exists|visible|hidden|text|url|title|image-ready> <value> [seconds] condition *: string, value *: string, seconds: integer Read-only assertion or wait {"condition": "visible", "value": "Example"}
assert-urlverify Require the current page URL to match the expected value before dependent work continues.assert-url <expected> [exact|contains] expected *: string, match: string Read-only assertion or wait {"expected": "https://example.com/"}
assert-titleverify Require the current document title to match the expected value.assert-title <expected> [exact|contains] expected *: string, match: string Read-only assertion or wait {"expected": "https://example.com/"}
assert-visibleverify Require a target to exist and be visibly rendered, returning geometry as evidence.assert-visible <target> target *: target Read-only assertion or wait {"target": "css:body"}
assert-textverify Require a target's current text to match an expected value.assert-text <target> <text> [exact|contains] target *: target, text *: string, match: string Read-only assertion or wait {"target": "css:body", "text": "Example"}
assert-image-readyverify Require a visible image to be complete with nonzero natural dimensions before capture or downstream use.assert-image-ready <target> target *: target Read-only assertion or wait {"target": "css:body"}
snapshot-interactiveinspect Return visible interactive elements with document-scoped refs, optionally bounded and paged by result limit and offset.snapshot-interactive [limit] [offset] limit: integer, offset: integer Read-only observation {}
find-interactiveinspect Search visible interactive elements by semantic name, rank useful matches in the browser, and return a bounded, pageable result set with document-scoped refs.find-interactive <query> [limit] [offset] query *: string, limit: integer, offset: integer Read-only observation {"query": "Example"}
read-pageinspect Return the active page title, URL, headings, and main readable text.read-page None Read-only observation {}
inspect-inputsinspect List visible form controls with type, label, placeholder, name, value, and checked state.inspect-inputs None Read-only observation {}
inspect-elementsinspect Inspect up to 100 visible elements matching a CSS selector with text, attributes, and geometry.inspect-elements [css] css: string Read-only observation {}
element-infoinspect Return detailed content, attributes, state, geometry, and computed style for one target.element-info <target> target *: target Read-only observation {"target": "css:body"}
scrollinspect Scroll the page by direction or bring a target element into the center of the viewport.scroll [down|up|top|bottom|target] destination: string Read-only observation {}
query-selectorinspect Return matching DOM elements for a CSS selector with text, HTML, visibility, and geometry.query-selector <css> css *: string Read-only observation {"css": "body"}
get-elementinspect Return the text, outer HTML, or both for a single target element.get-element <target> [text|html|both] target *: target, mode: string Read-only observation {"target": "css:body"}
accessibility-treeinspect Return a compact view of non-ignored nodes from the page accessibility tree.accessibility-tree [max] max: integer Read-only observation {}
inspect-linksinspect List visible links with normalized visible text and resolved URLs.inspect-links None Read-only observation {}
inspect-imagesinspect Inspect images with DOM-backed page-order refs, source, visibility, load completion, natural dimensions, and rendered dimensions.inspect-images None Read-only observation {}
tabstabs List browser page targets by stable logical label, with title, URL, and low-level target ID as diagnostics.tabs None May change/close targets {}
switch-tabtabs Activate and attach to a tab by logical label, with target ID/title/URL matching retained for compatibility.switch-tab <label|id|title|url> query *: string May change/close targets {"query": "Example"}
close-tabtabs Close the active tab and reattach the session to a remaining page target when available.close-tab None May change/close targets {}
open-in-new-tabtabs Open the link or image URL represented by a target in a new active tab.open-in-new-tab <target> target *: target May change/close targets {"target": "css:body"}
uploadfiles Set a local file on a targeted HTML file input using the DOM protocol.upload <target> <file> target *: target, file *: string Reads and uploads local file {"target": "css:body", "file": "/path/to/authorized-file.txt"}
cookiesstorage List browser cookies applicable to the active page URL or an explicitly supplied URL, including HttpOnly cookies.cookies [url] url: string Reads or changes browser storage {}
set-cookiestorage Set one browser cookie through CDP. The cookie object requires name/value and may include url, domain, path, secure, httpOnly, sameSite, and expires.set-cookie <cookie-json> cookie *: object Reads or changes browser storage {"cookie": {"name": "example", "value": "redacted", "url": "https://example.com/"}}
delete-cookiestorage Delete cookies matching a selector object. The selector requires name and may include url, domain, and path.delete-cookie <selector-json> selector *: object Reads or changes browser storage {"selector": {"name": "example", "url": "https://example.com/"}}
clear-cookiesstorage Delete all cookies applicable to the active page URL or an explicitly supplied URL without clearing unrelated browser cookies.clear-cookies [url] url: string Reads or changes browser storage {}
storage-liststorage List key/value entries from localStorage or sessionStorage for the active page origin.storage-list <local|session> area *: string Reads or changes browser storage {"area": "local"}
storage-getstorage Read one localStorage or sessionStorage key for the active page origin.storage-get <local|session> <key> area *: string, key *: string Reads or changes browser storage {"area": "local", "key": "name"}
storage-setstorage Set one localStorage or sessionStorage key for the active page origin.storage-set <local|session> <key> <value> area *: string, key *: string, value *: string Reads or changes browser storage {"area": "local", "key": "name", "value": "Example"}
storage-removestorage Remove one localStorage or sessionStorage key for the active page origin.storage-remove <local|session> <key> area *: string, key *: string Reads or changes browser storage {"area": "local", "key": "name"}
storage-clearstorage Clear localStorage or sessionStorage for the active page origin.storage-clear <local|session> area *: string Reads or changes browser storage {"area": "local"}
highlightvisual Draw a Jelly-owned non-interactive halo over a visible target without modifying the target element itself. Auto mode uses rendered text fragments for text-centric elements and a shape halo for controls; content forces text-fragment geometry; box preserves the rectangular outline. The highlight follows the element until cleared or navigation replaces the document.highlight <target> [label] [auto|content|box] target *: target, label: string, mode: string Adds/removes overlay {"target": "css:body"}
clear-highlightvisual Remove the active Jelly visual highlight from the current page.clear-highlight None Adds/removes overlay {}
evaluate-jsscript Evaluate a JavaScript expression in the active page and return its by-value result.evaluate-js <expression> expression *: string Executes page JavaScript {"expression": "document.title"}
inject-jsscript Execute a JavaScript body now, optionally persisting it across jelly navigations.inject-js [--persistent] [--file path | <script>] script *: string Executes page JavaScript {"script": "document.title"}

Examples show argument types and request structure. Replace targets, URLs and paths with real runtime values; consult tools/list for exact active input/output schemas and constraints.

cdp-call | privileged raw protocol

Parameters
calls: required array, 1–64 items. Each item requires scope: "target" | "browser" and call: {method: "Domain.command", params?: object}; target scope optionally accepts a logical target. on_error: "stop" | "continue" defaults to stop.
Permissions
Bearer/OAuth jelly scope; raw CDP enabled by operator.
Side effects
Privileged browser/page observation or mutation; bypasses semantic policy.
Errors
invalid_arguments, browser_unavailable, cdp_failed.
Output
Same MCP envelope with per-call outcomes; protocol success is not proof of a workflow goal.
Example cdp-call arguments
{"calls":[{"scope":"browser","call":{"method":"Target.getTargets","params":{}}}]}