toolstringCanonical tool name (snake_case), e.g. 'planner' or 'get_browser_tabs'. Only one of tool/action is required.
RUN
/mcpUse the sessions and permissions already available in Chrome.
Connect an MCP client or send JSON from your backend.
Use browser tools on your device and knowledge tools in Cloud.
Introduction
MCP Deep Dive
/mcpChoose a tool, set its inputs, and run the request.
Leave blank to let the server pick a browser that answers.
Describe a task for the browser to complete.
URLs to open before starting
https://mcp.rtrvr.aiShared 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:
apiKey + deviceId) into any MCP-enabled client (e.g. Claude).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_idFor 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?apiKey=YOUR_API_KEYAuthorization: Bearer rtrvr_your_api_keyIn 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.
Each Chrome/Chromium profile you install the extension into registers as a separate deviceId. This enables powerful multi-device workflows:
How deviceId works:
deviceId is embedded in the MCP URL generated by the extensiondeviceId in your requestdeviceId or device_id in the query or body to target a specific device.deviceId to try it anyway. list_devices reports the current pick as defaultDeviceId.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.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./mcp with different device IDs.get_current_credits and list_devices work even if no device is online.deviceId parameter is embedded in the URL.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 …).// 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 }
]
}
}https://mcp.rtrvr.aiThe 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.
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;
}toolstringCanonical tool name (snake_case), e.g. 'planner' or 'get_browser_tabs'. Only one of tool/action is required.
actionstringOptional alias of tool. Use canonical snake_case tool names for reliability.
params / parametersobjectJSON object of tool-specific parameters. 'params' and 'parameters' are aliases. Prefer snake_case parameter names.
params.options.ui.emitEventsbooleandefault falseOpt-in only. Set true to write execution progress events for SSE/polling consumers. If omitted/false, no execution event stream is written.
deviceId / device_idstringOptional 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 / stringReserved for future async execution modes. Ignored for now.
options.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.
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.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).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.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_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).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:
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.
{
"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"
}
]
}
}appliedbooleanSaved 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[].signedInbooleanThe saved cookies (or the site's saved sign-in) look signed in.
sites[].source / deviceIdstringWhere the login came from: "Cookie Sync from Chrome on MacIntel (device …)", or "saved in a cloud task" (deviceId "cloud-browser").
sites[].syncedAtstring | nullWhen it was last synced or saved (ISO 8601).
sites[].taskSitetrueA 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.
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.
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.list with kind: "proxies" shows saved proxies and marks the default; managed proxy connection details remain private.{"mode":"none"} for a direct cloud connection.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"
}
]
}
}
}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.{"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.503 PROXY_LOCATION_UNAVAILABLE) and says so.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.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.mode: "default", which it implies when you leave mode out). Next to a saved proxy or "none" the call is refused.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.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.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)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.
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)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.
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.productstringThe selected model.
modelUnavailable.effortRequestedstringThe reasoning level asked for; "auto" when none was set.
modelUnavailable.blockedFallbackstringWhat 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.reasonstringWhy 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.
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.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".tools/list.Prefer snake_case parameters. Common compatibility aliases include:
user_input ⇔ userInputtab_urls ⇔ tabUrlsdevice_id ⇔ deviceIdmax_steps ⇔ maxStepsmax_credits ⇔ maxCreditslive_view ⇔ liveViewkeep_tabs_open ⇔ keepTabsOpentask_id ⇔ taskIdrecording_id ⇔ recordingIdfile_urls ⇔ fileUrlsimage_urls ⇔ imageUrlsshared_workflow_url ⇔ sharedWorkflowUrlstore_id ⇔ storeIdconversation_context ⇔ conversationContexttab_ids ⇔ tabIdsweb_page_map ⇔ webPageMapauth_token ⇔ authTokenAll 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 contextfile_urlsCSV, PDF, text files to use as input data
image_urlsJPG, PNG images for visual context
recording_idRecorded workflow to use as context
{
"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"
}
}upload_fileThe 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):
name, mimeType, and base64 data — best for small files.url — the file is copied into rtrvr storage.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.# 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:
{
"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 IDshared_workflow_url – replay a workflow shared by another userAt least one of these must be provided.
task_idstringThe task ID from a previous workflow execution in your history.
shared_workflow_urlstringA 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_tabsHow to handle tabs during replay.
new_tabsreuse_tabscurrent_contextrecording_idstringOptional 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.
// 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.
// 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:
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;
}{
"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.X-Credits-Used and X-Credits-Remaining are also surfaced.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.
check_results, passing the execution_id. No kind is needed; if you pass one, use "executions".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".cancel_execution with its execution_id.// 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.
If /mcp calls fail with No online devices found or other errors:
list_devices to see which devices are online and which answer commands (status, lastAckAt).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.https://mcp.rtrvr.ai with your API key in headers. Optionally pass deviceId to target a specific device.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.
# 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