rtrvr.ai
DocsChrome / Cloud / API / MCP
Search docs⌘ K

RUN

Use your signed-in browser./mcp

Let an MCP client or backend use your signed-in Chrome session, including sites behind logins, SSO, and internal tools.
01

Your signed-in browser

Use the sessions and permissions already available in Chrome.

02

MCP or HTTP

Connect an MCP client or send JSON from your backend.

03

Device and Cloud tools

Use browser tools on your device and knowledge tools in Cloud.

Chrome is required for device-backed tools. Cloud-only tools do not need an extension session.
CLI

Connect an MCP client from your terminal with rtrvr CLI.

rtrvr mcp init --client claude

Video Tutorials

Browser as API Introduction

Introduction

MCP Integration Deep Dive

MCP Deep Dive

Try a browser tool

POST/mcp

Choose a tool, set its inputs, and run the request.

Try an example

Leave blank to let the server pick a browser that answers.

Describe a task for the browser to complete.

URLs to open before starting

Add your API key to run this request.

Endpoint URLhttps://mcp.rtrvr.ai

Shared by both direct HTTP calls and MCP clients. Extension-generated MCP URLs include your API key and deviceId; cloud-only knowledge base tools do not require a device.

The rtrvr.ai Chrome Extension registers as a remote browser device and exposes a single public entrypoint at https://mcp.rtrvr.ai. That same endpoint speaks:

  • MCP: paste the generated MCP URL (includes apiKey + deviceId) into any MCP-enabled client (e.g. Claude).
  • HTTP: POST JSON describing tool + params. Extension-backed tools dispatch into your online browser devices, while cloud-only knowledge base tools execute immediately without a device.

"Your Chrome browser is now an Agentic API Endpoint."

Trigger complex workflows in your own logged-in browser instance from CI/CD, Slack bots, cron jobs, or backend services.

OAuth Support (Recommended)

MCP clients that support OAuth can authenticate by connecting to mcp.rtrvr.ai directly. This triggers a Google Sign-In flow and returns a secure session token.

API Key in URL (Fallback)

For MCP clients without OAuth support, embed your API key directly in the URL:

https://mcp.rtrvr.ai?apiKey=rtrvr_your_api_key&deviceId=your_device_id

For direct HTTP calls, auth can be provided via:

  • Authorization: Bearer YOUR_API_KEY (recommended)
  • Authorization: YOUR_API_KEY (the Bearer prefix is optional)
  • X-API-Key: YOUR_API_KEY
  • Query param: ?apiKey=YOUR_API_KEY
Header
Authorization: Bearer rtrvr_your_api_key

In n8n, Make or Zapier Header Auth, set Name to Authorization and Value to your rtrvr_… key (with or without Bearer), or set Name to x-api-key.

Security: Prefer OAuth or headers in production. Avoid exposing API keys in URLs/logs when possible.

Each Chrome/Chromium profile you install the extension into registers as a separate deviceId. This enables powerful multi-device workflows:

How deviceId works:

  • Your deviceId is embedded in the MCP URL generated by the extension
  • Install the extension on multiple browsers/profiles to get multiple deviceIds
  • Target a specific device by passing deviceId in your request
  • Leave deviceId blank to auto-select a connected browser that answers commands

Device selection rules:

  • Explicit deviceId: Pass deviceId or device_id in the query or body to target a specific device.
  • No deviceId (default): a browser that answers its commands is auto-selected, the most recently active first. A browser that left its last command unanswered (asleep, closed, or its extension not answering) goes behind every browser that answers, and is still tried when no other is left. One that kept missing commands for 7 days after it last answered is not auto-selected until its extension checks in again, and then it goes last; name it with deviceId to try it anyway. list_devices reports the current pick as defaultDeviceId.
  • A browser that does not answer: if the chosen browser does not pick a command up within 15 seconds, nothing runs and the reply (code device_not_responding; HTTP 503 over the API) names that device (id, name, extension version, when it last answered), says whether it was picked automatically, lists your other browsers with their status, and says where to retry. The command is never re-run on another browser for you: tab ids, logins and profiles differ per browser.
  • Unified agent / scrape: with no deviceId and no target, the call runs in your signed-in Chrome on the auto-selected device; if no device can be reached it runs in a cloud browser instead. Pass target to override.
  • Multi-profile orchestration: Install the extension on multiple browser profiles and orchestrate them independently by calling /mcp with different device IDs.
  • Device-independent tools: Utility tools like get_current_credits and list_devices work even if no device is online.

Finding your deviceId:

  • From MCP URL: Open the extension → MCP / Remote Browser → copy the MCP URL. The deviceId parameter is embedded in the URL.
  • Via API: Call list_devices to see all registered devices: extension version, when each last answered a command (lastAckAt, UTC) and its status (responding, not responding since …, never acked, or offline since …).
  • Same names: two browsers can carry the same default name (“Chrome on Linux x86_64”); tell them apart by id, version and last answer, or give each its own name in the extension (Browser as API/MCP → Advanced → Device name, in newer extension builds).
Discovering devices
// List all your devices
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxx" \
  -H "Content-Type: application/json" \
  -d '{"tool": "list_devices"}'

// Response: which browser answers, and where a call without deviceId goes
{
  "success": true,
  "data": {
    "online": true,
    "defaultDeviceId": "dj75mmaTWP0",
    "devices": [
      { "deviceId": "dj75mmaTWP0", "deviceName": "Work laptop", "extensionVersion": "38.1.1",
        "lastSeen": "2026-10-05T10:30:00.000Z", "lastAckAt": "2026-10-05T10:41:12.000Z",
        "status": "responding", "reachable": true },
      { "deviceId": "abc123XYZ", "deviceName": "Chrome on Linux x86_64", "extensionVersion": "37.9.4",
        "lastSeen": "2026-10-03T18:00:00.000Z", "lastAckAt": "2026-09-25T21:05:00.000Z",
        "status": "not responding since 2026-09-25 21:34 UTC", "missedSinceLastAck": 12, "reachable": true }
    ]
  }
}
POSThttps://mcp.rtrvr.ai

The same endpoint powers both MCP and HTTP. For HTTP, you send a single JSON object describing which tool to run, which parameters to pass through, and optionally which device to target for extension-backed tools.

BrowserAgentApiRequest (conceptual)
interface BrowserAgentApiRequest {
  /**
   * Canonical tool name, e.g. "planner" or "get_browser_tabs".
   * Only one of "tool" or "action" is required.
   */
  tool?: string;

  /**
   * Optional alias of "tool". Use canonical snake_case tool names.
   */
  action?: string;

  /**
   * Parameters for the tool. "params" and "parameters" are equivalent.
   * Prefer canonical snake_case parameter names.
   */
  params?: Record<string, any>;
  parameters?: Record<string, any>;

  /**
   * Optional: route extension-backed tools to a specific Chrome profile / device.
   * Leaving this blank auto-selects a connected browser that answers commands;
   * for the unified agent / scrape tools, a cloud browser if none can be reached.
   * Cloud-only tools ignore this field.
   */
  deviceId?: string;
  device_id?: string;

  /**
   * Accepted but not used — each tool has its own limit (cloud_agent: params.timeoutMs,
   * 30 s–12 min, default 12 min; cloud_scrape: 5 min; device agent runs: 24 min).
   */
  timeout?: number;

  /**
   * Reserved for future async modes.
   */
  async?: boolean;
  webhookUrl?: string;
}

Top-level fields

toolstring

Canonical tool name (snake_case), e.g. 'planner' or 'get_browser_tabs'. Only one of tool/action is required.

actionstring

Optional alias of tool. Use canonical snake_case tool names for reliability.

params / parametersobject

JSON object of tool-specific parameters. 'params' and 'parameters' are aliases. Prefer snake_case parameter names.

params.options.ui.emitEventsbooleandefault false

Opt-in only. Set true to write execution progress events for SSE/polling consumers. If omitted/false, no execution event stream is written.

deviceId / device_idstring

Optional device routing for extension-backed tools. If omitted, we pick the most recently active online browser extension device for that user. Cloud-only knowledge base tools ignore this field.

timeoutnumberdefault —

Accepted but not used: each tool has its own limit. cloud_agent runs up to 12 minutes (set params.timeoutMs, 30 s–12 min), cloud_scrape up to 5 minutes, and agent runs on your device up to 24 minutes (a device run still going after 5 minutes answers with its execution_id).

async / webhookUrlboolean / string

Reserved for future async execution modes. Ignored for now.

emitEvents policy: API and extension/MCP executions only emit events whenoptions.ui.emitEvents: true. CLI streaming defaults on for run, agent, and scrape (use --no-stream to disable). Streamed payloads at or under 1MB stay inline; larger payloads include inline preview markers and storage references (`outputRef` / `resultRef` / `responseRef`) for full downloads.

The Browser as API/MCP exposes extension-backed browser tools, cloud-only tools, scheduling/trigger management, and utility tools. They include browser tools without model credits, credit-based agent tools, cloud tools, utilities, and user-defined functions. Browser tools are free on every plan; agent tools in your Chrome require a subscription.

Unified tools (start here)

  • agent – run an end-to-end task from one prompt. Runs in your own signed-in Chrome whenever the extension is connected (keeps logins, cookies, sessions); falls back to rtrvr's cloud browser, with the logins you saved, only when no device is connected.
  • scrape – read one or more URLs (page content + accessibility tree). Same routing: your Chrome when connected, a cloud browser otherwise.
  • Both accept target: "auto" (default, as above), "extension" (require your Chrome; errors if no device is connected), or "cloud" (force rtrvr's cloud browser, which starts with your saved logins).

Browser tools without model credits

  • get_browser_tabs – list open tabs (filter by all/active/domain).
  • get_page_data – get accessibility-tree representations for specific tab IDs.
  • take_page_action – run system tools like click, type, scroll, etc.

Credit-based tools

  • planner – multi-step planning and tool orchestration from natural language.
  • act_on_tab – intelligent page interaction with optional structured schemas.
  • extract_from_tab – structured extraction to JSON or Google Sheets.
  • crawl_and_extract_from_tab – multi-page crawls with schema extraction.
  • replay_workflow – replay a previously executed workflow by task ID or shared URL.
  • schedule – create a scheduled workflow on the browser extension. Without schedule_id, every call creates a new schedule. To change a saved one in place, pass its schedule_id (from list, kind "schedules") with the complete new task text in user_input, a new period_in_minutes, enabled (false pauses, true resumes) and/or tab_selection. Editing needs extension 37.9.5 or later on that device; an unknown ID fails instead of creating anything.
  • trigger_setup – create or modify a trigger workflow on the browser extension.

Cloud tools (no extension required)

  • cloud_scrape – scrape web pages in rtrvr's cloud browser, returns accessibility trees. Starts with your saved logins.
  • cloud_agent – execute AI agent tasks in rtrvr's cloud browser with structured output. Starts with your saved logins.
  • list_skills – list your skill files (persistent markdown memory the agent reads and updates).
  • get_skill – read one skill file's full markdown by name.
  • check_results – ask about the stored execution results of your scheduled (kind: "schedules") or trigger (kind: "triggers") workflows. Schedules cover cloud and extension schedules, and cloud schedules come back with their recent runs. Pass an execution_id to follow a long-running call (see Long-running calls).

Saved logins in the cloud browser (logins, session_source)

Cloud runs are not signed out. While your account's Cookies setting is on (the default), every cloud run starts with the logins you saved: cloud_agent, cloud_scrape, and agent or scrape when they run in the cloud. A login is saved in two ways:

  • Cookie Sync in the rtrvr extension copies the sites you choose from your Chrome, such as google.com.
  • Signing in inside a task on rtrvr.ai/cloud with Take control saves that session for later cloud runs.

Check which ones a run used: the result lists them as logins, and so does check_results for a cloud run, while it runs and after. The Cookies button in the rtrvr.ai/cloud chat bar lists every saved site with its sign-in state. Cookie names and values are never returned.

logins in a cloud_agent result
{
  "success": true,
  "status": "success",
  "logins": {
    "applied": true,
    "sites": [
      {
        "site": "google.com",
        "domains": ["accounts.google.com", "google.com"],
        "signedIn": true,
        "source": "Cookie Sync from Chrome on MacIntel (device eJq5Q5BqOfQ)",
        "deviceId": "eJq5Q5BqOfQ",
        "syncedAt": "2026-10-05T11:13:04.000Z",
        "taskSite": true
      },
      {
        "site": "substack.com",
        "domains": ["substack.com"],
        "signedIn": true,
        "source": "saved in a cloud task",
        "deviceId": "cloud-browser",
        "syncedAt": "2026-10-04T09:00:00.000Z"
      }
    ]
  }
}
appliedboolean

Saved logins were applied to the run. false when Cookies was off for it or nothing was saved; note says which.

sites[].site / domainsstring / string[]

The site and the saved domains it covers.

sites[].signedInboolean

The saved cookies (or the site's saved sign-in) look signed in.

sites[].source / deviceIdstring

Where the login came from: "Cookie Sync from Chrome on MacIntel (device …)", or "saved in a cloud task" (deviceId "cloud-browser").

sites[].syncedAtstring | null

When it was last synced or saved (ISO 8601).

sites[].taskSitetrue

A URL the task named is on this site.

taskSitesWithoutLoginstring[]

Sites the task named that started without a signed-in saved login.

Run without them: pass session_source: "none" (the same as settings.cookieSync.enabled: false). Every site starts signed out, and nothing the run signs in to is saved. To turn them off for every run, switch Cookies off in the rtrvr.ai/cloud chat bar.

Use one device's logins: pass session_source: {"device_id": "…"} with a deviceId from logins ("cloud-browser" for sessions saved in cloud tasks), and optionally domains to use only those sites. Only that device's saved logins on your account are read. A device with none, or a site it never saved, is refused before the run starts. A sign-in during such a run is saved to that device's copy of the site. Pass the same session_source on every call that continues the run.

On agent and scrape, session_source runs the task in the cloud browser; with target: "extension" it is refused, because your own Chrome always uses its own logins.

Use a saved proxy from MCP or the API

Save your proxy in Cloud Settings → Proxy Config. Choose it as your default and save settings to use it across Cloud, API, and MCP. To override for one call, pass its exact name or ID. Credentials stay in your account.

{
  "settings": {
    "proxyConfig": {
      "mode": "custom",
      "selectedProxyName": "My Taiwan proxy"
    }
  }
}

For cloud_agent and cloud_scrape, put settings inside the MCP tool's arguments or the tool API's params. For POST /agent and POST /scrape, put it in the request body. A saved selectedProxyId can replace selectedProxyName.

  • Omit proxyConfig to use your profile default, falling back to Retriever's managed proxy when none is set. Use {"mode":"default"} to explicitly choose the managed proxy.
  • The Cloud chat-bar selection overrides routing for that chat without changing your profile default. Choose “Use profile default” to reset it. MCP list with kind: "proxies" shows saved proxies and marks the default; managed proxy connection details remain private.
  • Use {"mode":"none"} for a direct cloud connection.
  • Saved names are case-sensitive. Unknown names and IDs fail; duplicate names require an ID. If both selectors are supplied, they must identify the same proxy.
  • Schedules created from a run retain that run's routing snapshot.

You can also provide a proxy for just one request. Use an HTTP or HTTPS proxy that supports CONNECT; keep credentials out of shared snippets and client-side code.

{
  "settings": {
    "proxyConfig": {
      "mode": "custom",
      "selectedProxyId": "request-proxy",
      "customProxies": [
        {
          "id": "request-proxy",
          "host": "proxy.example.net",
          "port": 8080,
          "scheme": "http",
          "username": "YOUR_USERNAME",
          "password": "YOUR_PASSWORD"
        }
      ]
    }
  }
}

Choose where the managed proxy exits

Add location to Retriever's managed proxy to run from a country, and optionally a region or city in it. The cloud browser's time zone and language follow the exit, so sites show dates, prices and pages the way a local visitor sees them.

{
  "settings": {
    "proxyConfig": {
      "mode": "default",
      "location": {
        "country": "IT",
        "city": "Milan"
      }
    }
  }
}
  • country is a two-letter ISO 3166-1 code such as IT, US or GB. region (optional) is the part after the dash of an ISO 3166-2 code: NY for US-NY, 25 for IT-25 (Lombardy). city (optional) is the city's English name, such as Milan or New York.
  • One field may list up to 5 places for an exit in any of them: countries ({"country": ["IT", "FR", "DE"]}, with no region or city), regions of one country ({"country": "US", "region": ["CA", "WA"]}, with no city) or cities of one country ({"country": "IT", "city": ["Milan", "Rome"]}). A comma-separated string such as "IT,FR,DE" works too. egress names the country the run used.
  • If the city or region has no exit right now, the run uses the region, then the whole country. It never exits outside the countries you asked for: when none has an exit, the run is refused before it starts (503 PROXY_LOCATION_UNAVAILABLE) and says so.
  • To check a place first, send POST https://api.rtrvr.ai/proxy-location/check with your API key and {"location": {"country": "IT", "city": "Milan"}}. It answers {"available": true, "egress": {...}} with where a run would exit, or {"available": false, "message": "..."}. Cloud Settings and the chat bar run the same check and only take places that have an exit.
  • The result's egress says where the run exited, for example {"country":"IT","city":"Milan","timezone":"Europe/Rome"}. relaxed: true means the city or region had no exit and the run used more of the country.
  • A location goes only with the managed proxy (mode: "default", which it implies when you leave mode out). Next to a saved proxy or "none" the call is refused.
  • Same field everywhere: settings.proxyConfig.location on POST /agent and POST /scrape, and on the MCP tools cloud_agent and cloud_scrape. MCP and the tool API also take the shorthand proxy_location, such as "proxy_location": "IT", "proxy_location": "IT,FR,DE" or "proxy_location": {"country": "US", "region": "NY"}; with agent or scrape it runs the task in the cloud browser.
  • Save a location under Cloud Settings → Proxy Config next to the managed default to use it for every run that names no route, schedules included. In the Cloud chat bar, pick Retriever managed proxy and set Location for that chat only.
  • A location costs nothing extra. A few hosts that always connect directly from the cloud, such as some government sites and file storage, do not use it.

Utility & user-defined tools

  • list_devices – list all registered extension devices and online/offline status.
  • get_current_credits – fetch current plan, credits used, and credits remaining.
  • upload_file – upload a file (base64, URL import, or signed upload URL) to rtrvr storage and get back a storageUrl to attach to agent tools. Free, no device required.
  • list_executions – list the commands running on your devices, each with its executionId and the tabs it is using. Free, no device required.
  • cancel_execution – stop a running command by its execution_id and get back what it had produced so far. It does not undo actions already taken on a page. Free, no device required.
  • list – list your saved items by kind: "recordings" (ID, name, timestamp), "custom_functions" (metadata only, not code), "schedules" (cloud and extension schedules, each with a source) or "triggers" (trigger configs). Works offline.
  • user_function – user-defined tools created in Cloud and executed in the extension sandbox.

Credit budget (max_credits)

agent, planner and cloud_agent take max_credits: the credit ceiling for that one run. Omit it to use the Credit Ceiling / Task setting (100 credits unless changed; 25 on the Free plan in the cloud). When the run has spent that much it returns status: "requires_input" with a question keyed credit_ceiling_continue: answer "Continue" to go on with a fresh budget of the same size, or "Stop here" to end with what it produced. A value that is not a positive number is refused before the run starts.

Live view (live_view)

cloud_agent, and agent when it runs in the cloud, take live_view: true to let you watch the run's cloud browser while it works: open the run in Executions and choose Watch live. It is off by default, and it must be set when the run starts: a run started without it cannot be watched. A run in your own Chrome needs no live view.

Browser time zone and language (settings.browser)

cloud_agent, and agent when it runs in the cloud, take settings.browser.timezone (an IANA name such as "Asia/Singapore", not an offset or an abbreviation) and settings.browser.locale (a language tag such as "en-US"): the clock and language the cloud browser runs on, which is how pages show times and how date/time pickers read them. Omit them and the clock is set where the cloud browser started (America/Chicago, en-US when that can't be looked up), so set them when times matter. The agent is told the browser's zone and offset either way, converts requested times into it before typing them, and says the converted value in the result. An invalid value is refused before the run starts. A run in your own Chrome uses your computer's clock. See Agent API: Browser time zone and language.

Keep tabs open (keep_tabs_open)

planner, act_on_tab, extract_from_tab and crawl_and_extract_from_tab (and agent when it runs in your Chrome) work in background tabs they open, and close those tabs when the run ends. Pass keep_tabs_open: true to leave them open, whether the run finishes, fails or is cancelled: the result lists them as keptTabs (tabId, url, title; data.keptTabs over HTTP). Read one with get_page_data, continue in it by passing it as tab_id, and close it with take_page_action and close_tab when you are done. A tab you pass as tab_id is never closed either way.

Kept tabs count toward your Max parallel tabs setting for tabs that connected apps leave open in your browser, with the ones take_page_action opens. Past it, a run that would keep its tabs is refused before it starts, with the open tabs listed. An extension too old for keep_tabs_open closes the tabs as before, and warnings says so.

Only the selected model (disable_fallbacks)

planner, agent, cloud_agent, act_on_tab, extract_from_tab, crawl_and_extract_from_tab and schedule take disable_fallbacks: true: the call uses only the selected model, at the reasoning level you asked for. Another provider that serves the same model may still answer (GPT-6 Luna on AWS Bedrock or OpenAI), and a managed model bills credits as usual. The call never switches to another model or a lower reasoning level, and an API key of your own that fails never falls back to credits. When the selected model cannot finish a step, the run stops there with MODEL_UNAVAILABLE (keeping what it already produced) and these details in modelUnavailable. It is final: the step is not retried.

modelUnavailable.productstring

The selected model.

modelUnavailable.effortRequestedstring

The reasoning level asked for; "auto" when none was set.

modelUnavailable.blockedFallbackstring

What the run would have switched to: "rescue" (another model answers the step), "gemini_last_resort" (Gemini as a last resort), "credits" (a managed model on credits after your own key failed), "sibling_model" (another model on the same connection), "effort_step_down" (a lower reasoning level), "web_search_model" (web search through another model) or "caption" (another model reads an image).

modelUnavailable.reasonstring

Why the selected model could not do the step.

It takes true or false, also spelled "true", "false", 1, 0, "1" or "0". Any other value is refused before the run starts. It applies to that call only and never changes your saved settings: omit it to use the Disable fallbacks setting in Settings, or pass false to allow fallbacks for one call while that setting is on (a run in your Chrome on an older extension build keeps the saved setting). On schedule it covers the call that sets the schedule up; the scheduled runs follow your saved setting.

The nested form, settings.llmIntegration.disableCreditsFallback, still works. ChatGPT's hosted MCP connector can keep an old tools list, so a client that does not see disable_fallbacks can send the nested form instead. When the result carries the run's model receipt, model.fallbacks is "disabled" for a run with fallbacks off, and model.fallbacksBlocked lists each fallback it refused (blockedFallback, reason and, when known, at, the step it happened in), including ones the run finished without.

Tool name aliases

Use canonical snake_case tool names. For direct HTTP, action can mirror tool:

  • tool: "agent" – routes to planner in your signed-in Chrome when a device is connected (or target: "extension" is set), otherwise to cloud_agent. target: "cloud" forces the cloud browser. On the extension side a request with a schema routes to act_on_tab.
  • tool: "scrape" – routes to the extension scrape in your signed-in Chrome when a device is connected (or target: "extension" is set), otherwise to cloud_scrape.
  • Retired names still work as aliases: list_recordings, list_custom_functions, list_schedules, list_triggers → list; check_schedule_results, check_trigger_results → check_results. They return the same response shape as before but no longer appear in tools/list.
  • tool: "planner" is equivalent to action: "planner".
  • tool: "act_on_tab" is equivalent to action: "act_on_tab".
  • For MCP protocol calls, use tool names exactly as returned by tools/list.

Parameter aliases

Prefer snake_case parameters. Common compatibility aliases include:

  • user_input ⇔ userInput
  • tab_urls ⇔ tabUrls
  • device_id ⇔ deviceId
  • max_steps ⇔ maxSteps
  • max_credits ⇔ maxCredits
  • live_view ⇔ liveView
  • keep_tabs_open ⇔ keepTabsOpen
  • task_id ⇔ taskId
  • recording_id ⇔ recordingId
  • file_urls ⇔ fileUrls
  • image_urls ⇔ imageUrls
  • shared_workflow_url ⇔ sharedWorkflowUrl
  • store_id ⇔ storeId
  • conversation_context ⇔ conversationContext
  • tab_ids ⇔ tabIds
  • web_page_map ⇔ webPageMap
  • auth_token ⇔ authToken

All credit tools support file and image inputs via publicly fetchable URLs. Files are automatically uploaded to Firebase Storage and passed to the agent as context. For local files that aren't hosted anywhere, use the upload_file tool first (see below) and pass the returned storageUrl.

Each file can be up to 128 MB. The model reads files up to 20 MB; for a larger file it sees only the name, type and size, and the agent can still upload the file into a page or pass it on to tools and later steps.

Supported input parameters:

  • file_urls – array of publicly fetchable file URLs (CSV, PDF, etc.)
  • image_urls – array of publicly fetchable image URLs (JPG, PNG, etc.)
  • recording_id – ID of a recorded workflow to use as context
file_urls

CSV, PDF, text files to use as input data

image_urls

JPG, PNG images for visual context

recording_id

Recorded workflow to use as context

Example with file inputs
{
  "tool": "planner",
  "params": {
    "user_input": "Upload this CSV and submit the form",
    "tab_urls": ["https://example.com/upload"],
    "file_urls": ["https://example.com/data.csv"],
    "image_urls": ["https://example.com/screenshot.png"],
    "recording_id": "rec_abc123"
  }
}

Uploading local files: upload_file

The upload_file tool stores a file under your account and returns a storageUrl + gcsUri. It is free, needs no device, and supports three modes (files up to 128 MB; send large files by URL or signed upload, not base64):

  • Base64: pass name, mimeType, and base64 data — best for small files.
  • URL import: pass url — the file is copied into rtrvr storage.
  • Signed upload URL: pass only name and mimeType — you get back a signed uploadUrl valid for 15 minutes. PUT the raw bytes to it (no base64 inflation), then use the returned storageUrl.
Local file → signed upload → agent attachment
# 1. Request a signed upload URL (no bytes in the request)
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxx" \
  -H "Content-Type: application/json" \
  -d '{"tool": "upload_file", "params": {"name": "resume.pdf", "mimeType": "application/pdf"}}'
# → { "mode": "signed_url", "uploadUrl": "https://storage.googleapis.com/…", "storageUrl": "…", "gcsUri": "gs://…" }

# 2. Upload the raw bytes
curl -X PUT -H "Content-Type: application/pdf" --upload-file ./resume.pdf "<uploadUrl>"

# 3. Attach it to any agent tool
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "planner",
    "params": {
      "user_input": "Apply to this job with my resume",
      "tab_urls": ["https://example.com/careers/apply"],
      "file_urls": ["<storageUrl>"]
    }
  }'

For agent / cloud_agent, attach files via the files parameter instead of file_urls:

cloud_agent / agent files parameter
{
  "tool": "agent",
  "params": {
    "user_input": "Summarize the attached report",
    "files": [
      { "displayName": "report.pdf", "uri": "<storageUrl>", "mimeType": "application/pdf" }
    ]
  }
}

The replay_workflow tool allows you to re-execute a previously completed workflow. You can replay your own workflows by task ID, or replay workflows shared by other users via a shared URL.

Two ways to replay:

  • task_id – replay your own workflow by execution ID
  • shared_workflow_url – replay a workflow shared by another user

At least one of these must be provided.

Parameters

task_idstring

The task ID from a previous workflow execution in your history.

shared_workflow_urlstring

A shared workflow URL (e.g., https://rtrvr.ai/shared/Tasks/userId/taskId/token). Use this to replay workflows shared by other users.

tab_execution_modestringdefault new_tabs

How to handle tabs during replay.

new_tabsreuse_tabscurrent_context
recording_idstring

Optional recording ID to use as additional context.

file_urlsstring[]

Optional file URLs to include as input.

image_urlsstring[]

Optional image URLs to include as input.

Replay workflow examples
// By task ID (your own workflow)
{
  "tool": "replay_workflow",
  "params": {
    "task_id": "abc123xyz",
    "tab_execution_mode": "new_tabs"
  }
}

// By shared URL (another user's workflow)
{
  "tool": "replay_workflow", 
  "params": {
    "shared_workflow_url": "https://rtrvr.ai/shared/Tasks/userId/taskId/token"
  }
}

Below is a conceptual TypeScript view of each tool's parameters.

Agentic tool parameters
// Unified tools — your signed-in Chrome when connected, else a cloud browser
agent({
  user_input: string;
  target?: "auto" | "extension" | "cloud";  // default "auto"
  urls?: string[];
  schema?: object;
  files?: { displayName: string; uri: string; mimeType: string }[];
  device_id?: string;                        // pin a specific Chrome profile
  max_credits?: number;                      // credit budget for this run (default: your Credit Ceiling / Task)
  disable_fallbacks?: boolean;               // only the selected model and reasoning level, else MODEL_UNAVAILABLE (default: your setting)
  keep_tabs_open?: boolean;                  // your Chrome only: keep the tabs the run opens (default: false)
  live_view?: boolean;                       // cloud runs: watch the run live in Executions (default: false)
  session_source?: "none" | { device_id: string; domains?: string[] };  // cloud runs: which saved logins (default: all)
});

scrape({
  urls: string[];
  target?: "auto" | "extension" | "cloud";  // default "auto"
  device_id?: string;
  session_source?: "none" | { device_id: string; domains?: string[] };  // cloud runs: which saved logins (default: all)
});

// Free tools
get_browser_tabs({
  filter?: "all" | "active" | "domain";
  domain?: string;
  device_id?: string;
});

get_page_data({
  tabIds: number[];
  device_id?: string;
});

take_page_action({
  actions: {
    tab_id?: number;
    tool_name: SystemToolName;
    args: Record<string, any>;
  }[];
  device_id?: string;
});

// Credit tools
planner({
  user_input: string;
  context?: string;
  tab_urls?: string[];
  tab_id?: number;            // run in this tab (yours, or one a call left open); never closed
  keep_tabs_open?: boolean;   // keep the tabs this run opens open; listed as keptTabs (default: false)
  max_steps?: number;
  device_id?: string;
  recording_id?: string;      // Recording ID to use as workflow context
  file_urls?: string[];       // Publicly fetchable file URLs
  image_urls?: string[];      // Publicly fetchable image URLs
  max_credits?: number;       // Credit budget for this run (default: your Credit Ceiling / Task)
  disable_fallbacks?: boolean; // Only the selected model and reasoning level, else MODEL_UNAVAILABLE (default: your setting)
});

act_on_tab({
  user_input: string;
  tab_urls?: string[];
  schema?: {
    fields: {
      name: string;
      description: string;
      type: string;
      required?: boolean;
    }[];
  };
  tab_id?: number;
  keep_tabs_open?: boolean;   // keep the tabs this run opens open; listed as keptTabs (default: false)
  disable_fallbacks?: boolean; // only the selected model and reasoning level, else MODEL_UNAVAILABLE (default: your setting)
  device_id?: string;
  recording_id?: string;
  file_urls?: string[];
  image_urls?: string[];
});

extract_from_tab({
  user_input: string;
  tab_urls?: string[];
  schema?: {
    fields: {
      name: string;
      description: string;
      type: string;
      required?: boolean;
    }[];
  };
  output_destination?: {        // omit it for the rows only (extractedData): no sheet is written
    type?: "json" | "google_sheet";   // "json" (default): rows only. "google_sheet": also written to a Google Sheet
    new_sheet_title?: string;
    new_tab_title?: string;
    existing_sheet_id?: string;   // append to this sheet instead of making a new one
    existing_tab_title?: string;
  };
  tab_id?: number;
  keep_tabs_open?: boolean;   // keep the tabs this run opens open; listed as keptTabs (default: false)
  disable_fallbacks?: boolean; // only the selected model and reasoning level, else MODEL_UNAVAILABLE (default: your setting)
  device_id?: string;
  recording_id?: string;
  file_urls?: string[];
  image_urls?: string[];
});

crawl_and_extract_from_tab({
  user_input: string;
  tab_urls?: string[];
  schema?: { fields: { name: string; description: string; type: string; required?: boolean; }[]; };
  max_pages?: number;
  follow_links?: boolean;
  link_pattern?: string;
  output_destination?: { type?: "json" | "google_sheet"; new_sheet_title?: string; };   // as extract: omit it for the rows only
  tab_id?: number;
  keep_tabs_open?: boolean;   // keep the tabs this run opens open; listed as keptTabs (default: false)
  disable_fallbacks?: boolean; // only the selected model and reasoning level, else MODEL_UNAVAILABLE (default: your setting)
  device_id?: string;
  recording_id?: string;
  file_urls?: string[];
  image_urls?: string[];
});

replay_workflow({
  task_id?: string;              // Task ID from previous execution
  shared_workflow_url?: string;  // Shared workflow URL from another user
  tab_execution_mode?: "new_tabs" | "reuse_tabs" | "current_context";
  recording_id?: string;
  file_urls?: string[];
  image_urls?: string[];
});

// Cloud-only skill tools (no device_id required)
list_skills({});

get_skill({
  name: string;
}});

// Cloud-only inventory tools (no device_id required)
list({
  kind: "recordings" | "custom_functions" | "schedules" | "triggers";
  source?: "cloud" | "extension" | "all";  // schedules only, default "all"
  device_id?: string;   // extension schedules / triggers: filter by device
});

check_results({
  kind?: "schedules" | "triggers" | "executions";  // required unless execution_id is given
  user_input?: string;  // question about the stored results
  id?: string;          // schedule / trigger name or ID
  execution_id?: string; // follow a long-running call that answered status "running"
  wait_seconds?: number; // with execution_id: default 25, max 45, 0 = answer now
  source?: "cloud" | "extension" | "all";  // schedules only, default "all"
  device_id?: string;   // extension workflows only
  limit?: number;       // recent runs per schedule / trigger, default 10
});

// Extension schedules (runs on a connected device)
schedule({
  user_input?: string;         // creating: what to run and how often; editing: the complete new task text
  schedule_id?: string;        // edit this schedule in place (from list kind "schedules"); omit to create a NEW one
  period_in_minutes?: number;  // with schedule_id: new cadence
  enabled?: boolean;           // with schedule_id: false pauses, true resumes
  step?: number;               // with schedule_id: 0-based step whose task text user_input replaces
  tab_selection?: "new_tab" | "active_tab";  // where each run starts, default "new_tab"
  device_id?: string;          // the device to create it on, or that holds the schedule being edited
  disable_fallbacks?: boolean; // this call only: only the selected model sets it up (default: your setting)
});

// Runs on your devices (free, no device_id required)
list_executions({ device_id?: string });
cancel_execution({
  execution_id: string;
  wait_for_partial_results?: boolean;  // default true: wait up to 10 s for what the run produced
});

// Utility: upload a local file to rtrvr storage (free, no device_id required)
upload_file({
  name?: string;      // filename incl. extension; required unless url given
  mimeType?: string;  // inferred from extension if omitted
  data?: string;      // base64 content (small files)
  url?: string;       // OR: public URL to import
  // neither data nor url → returns a signed PUT uploadUrl (15 min)
  // → { storageUrl, gcsUri } to pass via file_urls or files[]
});

// User functions (defined in Cloud and executed in the browser sandbox)
user_function({
  functionName: string;
  // your custom parameters...
});

All tools return a consistent envelope with tool-specific data plus metadata:

BrowserAgentApiResponse (conceptual)
interface BrowserAgentApiResponse<TData = any> {
  success: boolean;
  data: TData | null;
  error: string | null;
  metadata: {
    requestId: string;
    executionTime: number;
    tool: string;
    deviceId?: string;
    creditsUsed?: number;
    creditsRemaining?: number;
    inlineOutputMaxBytes?: number;
    outputTooLarge?: boolean;
    responseRef?: StorageReference;
  };
  timestamp: string;
}
Example: get_browser_tabs response
{
  "success": true,
  "data": {
    "tabs": [{ "id": 1, "url": "https://example.com" }],
    "activeTab": { "id": 1, "url": "https://example.com" },
    "tabCount": 1
  },
  "error": null,
  "metadata": {
    "requestId": "req_abc123",
    "executionTime": 1234,
    "tool": "get_browser_tabs",
    "deviceId": "dj75mmaTWP0",
    "creditsUsed": 0,
    "creditsRemaining": 10000
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}
  • metadata.deviceId shows which device executed the request.
  • metadata.requestId is useful for joining logs with rtrvr.ai's internal state.
  • HTTP headers like X-Credits-Used and X-Credits-Remaining are also surfaced.
  • Large payloads keep inline previews and expose storage refs via metadata.responseRef and/or outputRef/resultRef.

An MCP call to a long-running tool (agent, planner, cloud_agent, act_on_tab, extract_from_tab, crawl_and_extract_from_tab, replay_workflow) that is still going after about 40 seconds answers with status: "running" and an execution_id instead of the result. The run keeps going, and its result is kept.

  • Follow it with check_results, passing the execution_id. No kind is needed; if you pass one, use "executions".
  • Each call waits up to 25 seconds for new steps or the result (wait_seconds, max 45; 0 answers immediately). It returns state: "pending" with the latest steps while the run is going, or state: "done" with the full result. Call it again until the state is "done".
  • Don't start the task again: the first run is still going. To stop a run on your device, call cancel_execution with its execution_id.
Following a long-running call
// 1. The call answers while the run is still going
{
  "success": true,
  "status": "running",
  "execution_id": "exec_abc123",
  "next": { "tool": "check_results", "arguments": { "execution_id": "exec_abc123" } }
}

// 2. Follow it
{ "tool": "check_results", "params": { "execution_id": "exec_abc123" } }

// While it runs
{ "success": true, "kind": "executions", "execution_id": "exec_abc123", "state": "pending",
  "execution": { "status": "running", "recentSteps": [ ... ] } }

// Once it finishes: the full result, as the original call returns it
{ "success": true, "kind": "executions", "execution_id": "exec_abc123", "state": "done",
  "execution": { "status": "completed", "result": { ... } } }

MCP clients stop waiting on a tool call after their own timeout: Codex, for example, defaults to 60 seconds (tool_timeout_sec). Because a long call answers with its execution_id first, long tasks keep working whatever that timeout is. Direct HTTP calls (a plain JSON POST, as from n8n or a script) are not cut short at 40 seconds: they wait for the result, and only a run on your device that is still going after 5 minutes answers with its execution_id.

Remote tool execution can be configured at a per-user and per-tool level via the extension settings and the Cloud dashboard.

  • Disable remote browser tools entirely for a given user.
  • Independently enable/disable free tools and credit tools.
  • Toggle individual tools inside each family.
  • All configuration is respected by the MCP handler; disabled tools yield an explanatory error.
Important: Remote tool execution is enabled by default. Review allowed tools in the Chrome extension MCP / Remote Tools settings to match your security posture.

If /mcp calls fail with No online devices found or other errors:

  • Open/close the rtrvr.ai Chrome extension popup to refresh its connection.
  • Rotate your API key from the extension dropdown to re-sync backend state.
  • Sign out and sign back into the extension to reset device registration.
  • Call list_devices to see which devices are online and which answer commands (status, lastAckAt).
  • A device_not_responding reply names the browser that did not pick the command up and your other browsers: retry with the deviceId of one that is responding, or open that browser (a sleeping or closed computer cannot answer) and retry.
  • Ensure the deviceId you're targeting matches an online device.
Most device issues are resolved by refreshing the extension, rotating the API key, or resetting the sign-in.
  1. Install the rtrvr.ai Chrome Extension.
  2. Open the MCP / Remote Browser section in the extension.
  3. Copy the generated MCP URL — your API key and deviceId are already embedded. Alternatively, get your API key from rtrvr.ai/cloud.
  4. For MCP clients: paste the URL directly into your MCP-enabled application (e.g. Claude).
  5. For direct HTTP: call https://mcp.rtrvr.ai with your API key in headers. Optionally pass deviceId to target a specific device.
  6. Multi-device setup: Install the extension on multiple Chrome profiles. Each gets its own deviceId. Target specific devices or leave blank for auto-selection.
  7. Configure which tools to enable/disable in extension settings.
The MCP URL generated by the extension includes your API key and deviceId. Treat this URL as a secret: store it safely, avoid logging it in plaintext, and rotate as needed.

These snippets show the recommended integration pattern: a thin server-side helper that wraps POST /mcp, keeps your API key off the frontend, and centralizes rate limiting + logging.

cURL
# 1) Your browser as an agentic API endpoint
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "planner",
    "params": {
      "user_input": "Go to ChatGPT.com, ask for top Indian restaurants in SF, and extract back citations.",
      "tab_urls": ["https://chatgpt.com"],
      "options": {
        "ui": {
          "emitEvents": true
        }
      }
    },
    "deviceId": "dj75mmaTWP0"
  }'

# 2) Free tool: list all tabs on the auto-selected device (no deviceId = a browser that answers)
curl -X POST "https://mcp.rtrvr.ai" \
  -H "X-API-Key: rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_browser_tabs",
    "params": { "filter": "all" }
  }'

# 3) Replay a workflow with file inputs
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "replay_workflow",
    "params": {
      "task_id": "abc123xyz",
      "tab_execution_mode": "new_tabs",
      "file_urls": ["https://example.com/data.csv"]
    }
  }'

# 4) Planner with image context
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "planner",
    "params": {
      "user_input": "Find similar products to the one in this image",
      "tab_urls": ["https://amazon.com"],
      "image_urls": ["https://example.com/product.jpg"]
    }
  }'

# 5) Cloud-only skills listing (no deviceId required)
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "list_skills",
    "params": {}
  }'

# 6) Cloud-only skill read (no deviceId required)
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_skill",
    "params": {
      "name": "general"
    }
  }'

# 7) Unified agent: runs in YOUR signed-in Chrome when the extension is connected, else a cloud browser
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "agent",
    "params": {
      "user_input": "Open my Gmail and list the subjects of unread emails from this week",
      "target": "auto"
    }
  }'

# 8) Same routing for scrape; target "cloud" forces rtrvr's cloud browser (with your saved logins; session_source "none" reads signed out)
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "scrape",
    "params": {
      "urls": ["https://example.com/pricing"],
      "target": "cloud"
    }
  }' 

YOUR NEXT RUN

Run the example on a real site.

Use Chrome for the page in front of you. Use Cloud when the run should continue on a schedule or across many pages.