Protocol

SDK, then remote MCP.

Unbrowse is an authenticated action surface. The SDK is the product. MCP is a thin remote harness over it. Agent Skills are the YAML those harnesses already are.

Canonical REST

All agent traffic goes through /api/v1. The authenticated principal determines the workspace — a caller-supplied workspace id is never authority.

POST /api/v1/runs
GET  /api/v1/runs/:id
POST /api/v1/runs/:id/responses
POST /api/v1/runs/:id/cancel
GET  /api/v1/runs/:id/events
POST /api/v1/capabilities/search
POST /api/v1/accounts/connections   { origin, username, password } → vault:// ref
POST /api/v1/accounts/register      { origin, username } → generated, vaulted
GET  /api/v1/vault                  refs + audit, never secrets
POST /api/v1/learn                  { har | traces, goal?, title? } → learned.* capability
GET  /api/v1/learned
GET  /api/v1/learned/:id/harness.yaml
GET  /api/v1/learned/:id/skill.md
GET  /api/v1/usage                  verified calls this month, rendered, passthrough, quota
GET  /api/v1/sites?q=                compiled sites (public registry) with tool counts
GET  /api/v1/sites/:host             that site's tools
GET  /api/v1/sites/:host/openapi.json  OpenAPI 3.1: one operation per tool, typed input and output
POST /api/v1/sites/:host/call/:tool  run a tool (same metered, verified run)
     /api/v1/sites/:host/mcp         the site as its own MCP server
POST /api/v1/org                    { name, appName?, domain? } → your org (see "For agent builders")
GET  /api/v1/org                    users, usage per user, shared tools, keys, balance
POST /api/v1/org/keys               mint an org key (a signed-in person only)
POST /api/v1/org/keys/revoke        { id }
POST /api/v1/org/users              { user } → a key for one of your users
POST /api/v1/org/settings           { sharePublic }
GET  /api/v1/connect/:id            a one-time connect link: app, site, status (no sign-in)
GET  /api/v1/replays?source=&site=&outcome=&hasError=&from=&to=&limit=   recorded sessions
GET  /api/v1/replays/:sid            one session: details, signals, summary
GET  /api/v1/replays/:sid/events     the rrweb recording, agent steps and screenshots
GET  /api/v1/replays/:sid/timeline   ?from=&to=&kinds=&format=text  the session as text lines
GET  /api/v1/replays/:sid/shots?key= one agent step screenshot (JPEG)
POST /api/v1/replays/search         { q, filter? } → moments with a time into the session
POST /api/v1/replays/ask            { question, filter? } → answer with [session, time] citations
DELETE /api/v1/replays/:sid         erase a session

Authorization: Bearer ub_live_…
X-Unbrowse-End-User: <your user's id>   (org keys: act as that user)

TypeScript SDK

import { Unbrowse } from "@unbrowse/sdk";

const ub = new Unbrowse({
  apiKey: process.env.UNBROWSE_API_KEY!,
  baseUrl: "https://unbrowse.ai/api/v1",
});

const run = await ub.run({
  task: "top stories on Hacker News",
  interactionMode: "unattended",
  idempotencyKey: "hn-1",
});

if (run.status === "input_required") {
  await ub.resume(run.runId, run.stateRevision, [{
    requirementId: run.requirements[0].id,
    expectedRevision: run.requirements[0].revision,
    action: "accept",
    values: { export_format: "csv" },
  }]);
}

MCP tools

Remote MCP at /mcp is Streamable HTTP (Grok, Claude, Cursor). /api/mcp is the same adapter over JSON-RPC. authorization and run actor. When three or fewer skills match, dedicated unbrowse.skill.* tools are listed with slot schemas from the harness YAML.

Sites as tools

Unbrowse is a browser engine and a compiler: it compiles a website's own requests into an API, and the API into tools. Every compiled site is an MCP server at /api/v1/sites/<host>/mcp and an OpenAPI 3.1 document at /api/v1/sites/<host>/openapi.json; each tool carries its input schema and an output schema learned from verified responses. The public registry holds pre-indexed sites (search and page reads, re-verified on a schedule); your own learned capabilities appear as my__… tools in the main server, tools shared inside your org as org__…, and public ones you use stay in your tool list.

For agent builders

Building agents for other people? Create an org at /app/org and run Unbrowse for all of your users under one key and one bill.

Full guide: docs/orgs.md.

Logins

Unbrowse is a remote MCP server: agents call it, and it signs in to sites for them in its own cloud browser, or replays the site's API with the kept session. Agents never receive a password — they get a masked hint and which fields were filled. You keep logins in the password manager; Unbrowse seals each one (AES-256-GCM under a per-workspace key), types it into the site's own login form, and logs every use. Learned tools that sign in take the login from the vault by themselves.

Statuses

Every error code, and what to do about each: Errors & statuses.

succeeded
Declared business outcome independently verified. HTTP 200 is not enough.
input_required
Waiting on a versioned requirement. Not a capability failure. Resume the same run.
outcome_unknown
A mutation may have landed. Automatic mutating retries stay suspended until reconciliation.
failed / cancelled
Known effects are retained. Cancellation cannot unsend a delivered request.

Harness YAML

unbrowse/v1alpha1 packages declare slots, operations, bindings, guards and independent outcome checks. YAML is authoring; the runtime executes a typed IR. No eval, no shell, no website-provided expressions.