bb-browser 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  COMMAND_TIMEOUT,
4
4
  DAEMON_BASE_URL,
5
5
  generateId
6
- } from "./chunk-XYKHDJST.js";
6
+ } from "./chunk-5WGFUZLM.js";
7
7
  import {
8
8
  __commonJS,
9
9
  __export,
@@ -20971,13 +20971,11 @@ import { execFile, spawn } from "child_process";
20971
20971
  import { existsSync } from "fs";
20972
20972
  import { fileURLToPath } from "url";
20973
20973
  import { dirname, resolve } from "path";
20974
- var EXT_HINT = [
20975
- "Chrome extension not connected.",
20974
+ var CHROME_NOT_CONNECTED_HINT = [
20975
+ "Chrome is not connected to the daemon.",
20976
20976
  "",
20977
- "1. Download extension: https://github.com/epiral/bb-browser/releases/latest",
20978
- "2. Unzip the downloaded file",
20979
- "3. Open chrome://extensions/ \u2192 Enable Developer Mode",
20980
- '4. Click "Load unpacked" \u2192 select the unzipped folder'
20977
+ "Make sure Chrome is running and the daemon can connect to it via CDP.",
20978
+ "Run: bb-browser daemon --help for details."
20981
20979
  ].join("\n");
20982
20980
  var sessionOpenedTabs = /* @__PURE__ */ new Set();
20983
20981
  function getDaemonPath() {
@@ -21029,7 +21027,7 @@ async function sendCommand(request) {
21029
21027
  });
21030
21028
  clearTimeout(timeoutId);
21031
21029
  if (response.status === 503) {
21032
- return { id: request.id, success: false, error: EXT_HINT };
21030
+ return { id: request.id, success: false, error: CHROME_NOT_CONNECTED_HINT };
21033
21031
  }
21034
21032
  return await response.json();
21035
21033
  } catch {
@@ -21152,8 +21150,8 @@ async function runSiteCli(args) {
21152
21150
  return parsed ?? result.stdout.trim();
21153
21151
  }
21154
21152
  var server = new McpServer(
21155
- { name: "bb-browser", version: "0.10.1" },
21156
- { instructions: `bb-browser lets you control the user's real Chrome browser \u2014 with their login state, cookies, and sessions.
21153
+ { name: "bb-browser", version: "0.11.0" },
21154
+ { instructions: `bb-browser lets you control the user's real Chrome browser via CDP (Chrome DevTools Protocol).
21157
21155
 
21158
21156
  Your browser is the API. No headless browser, no cookie extraction, no anti-bot bypass.
21159
21157
 
@@ -21161,11 +21159,18 @@ Key capabilities:
21161
21159
  - browser_snapshot: Read page content via accessibility tree (use ref numbers to interact)
21162
21160
  - browser_click/fill/type: Interact with elements by ref from snapshot
21163
21161
  - browser_eval: Run JavaScript in page context (most powerful \u2014 full DOM/fetch access)
21164
- - browser_network: Capture network requests/responses (API reverse engineering)
21162
+ - browser_network: Capture network requests/responses (API reverse engineering). Supports incremental queries with since: "last_action"
21163
+ - browser_console: Read console messages. Supports since/filter/limit
21164
+ - browser_errors: Read JavaScript errors. Supports since/limit
21165
21165
  - browser_screenshot: Visual page capture
21166
- - browser_tab_list/tab_new: Multi-tab support \u2014 use tab parameter for concurrent operations
21166
+ - browser_tab_list/tab_new: Multi-tab support \u2014 use tab parameter (short ID like "c416") for concurrent operations
21167
21167
  - browser_close_all: Close tabs opened by bb-browser during the current MCP session
21168
21168
 
21169
+ Tab management:
21170
+ - Tab IDs are short hex strings (e.g. "c416") returned by tab_list or open commands
21171
+ - Pass tab short ID to any tool to target a specific tab
21172
+ - Omit tab to target the active tab
21173
+
21169
21174
  Site adapters (pre-built commands for popular sites):
21170
21175
  - site_list/site_search/site_info: Discover available adapters and their signatures
21171
21176
  - site_recommend: Suggest adapters based on browsing history
@@ -21179,7 +21184,7 @@ server.tool(
21179
21184
  "browser_snapshot",
21180
21185
  "Get accessibility tree snapshot of the current page",
21181
21186
  {
21182
- tab: external_exports.number().optional().describe("Tab ID to target (omit for active tab)"),
21187
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)"),
21183
21188
  interactive: external_exports.boolean().optional().describe("Only show interactive elements")
21184
21189
  },
21185
21190
  async ({ tab, interactive }) => {
@@ -21193,7 +21198,7 @@ server.tool(
21193
21198
  "Click an element by ref",
21194
21199
  {
21195
21200
  ref: external_exports.string().describe("Element ref from snapshot"),
21196
- tab: external_exports.number().optional().describe("Tab ID to target")
21201
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21197
21202
  },
21198
21203
  async ({ ref, tab }) => {
21199
21204
  const resp = await runCommand({ action: "click", ref, tabId: tab });
@@ -21207,7 +21212,7 @@ server.tool(
21207
21212
  {
21208
21213
  ref: external_exports.string().describe("Element ref from snapshot"),
21209
21214
  text: external_exports.string().describe("Text to fill"),
21210
- tab: external_exports.number().optional().describe("Tab ID to target")
21215
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21211
21216
  },
21212
21217
  async ({ ref, text, tab }) => {
21213
21218
  const resp = await runCommand({ action: "fill", ref, text, tabId: tab });
@@ -21221,7 +21226,7 @@ server.tool(
21221
21226
  {
21222
21227
  ref: external_exports.string().describe("Element ref from snapshot"),
21223
21228
  text: external_exports.string().describe("Text to type"),
21224
- tab: external_exports.number().optional().describe("Tab ID to target")
21229
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21225
21230
  },
21226
21231
  async ({ ref, text, tab }) => {
21227
21232
  const resp = await runCommand({ action: "type", ref, text, tabId: tab });
@@ -21234,7 +21239,7 @@ server.tool(
21234
21239
  "Navigate to a URL",
21235
21240
  {
21236
21241
  url: external_exports.string().describe("URL to open"),
21237
- tab: external_exports.number().optional().describe("Tab ID to target")
21242
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21238
21243
  },
21239
21244
  async ({ url, tab }) => {
21240
21245
  const resp = await runCommand({ action: "open", url, tabId: tab });
@@ -21273,7 +21278,7 @@ server.tool(
21273
21278
  "Press a keyboard key",
21274
21279
  {
21275
21280
  key: external_exports.string().describe("Key name to press, e.g. Enter or Control+a"),
21276
- tab: external_exports.number().optional().describe("Tab ID to target")
21281
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21277
21282
  },
21278
21283
  async ({ key, tab }) => {
21279
21284
  const parts = key.split("+");
@@ -21292,7 +21297,7 @@ server.tool(
21292
21297
  {
21293
21298
  direction: external_exports.enum(["up", "down", "left", "right"]).describe("Scroll direction"),
21294
21299
  pixels: external_exports.number().optional().default(500).describe("Scroll distance in pixels"),
21295
- tab: external_exports.number().optional().describe("Tab ID to target")
21300
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21296
21301
  },
21297
21302
  async ({ direction, pixels, tab }) => {
21298
21303
  const resp = await runCommand({ action: "scroll", direction, pixels, tabId: tab });
@@ -21305,7 +21310,7 @@ server.tool(
21305
21310
  "Execute JavaScript in page context",
21306
21311
  {
21307
21312
  script: external_exports.string().describe("JavaScript source to execute"),
21308
- tab: external_exports.number().optional().describe("Tab ID to target")
21313
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21309
21314
  },
21310
21315
  async ({ script, tab }) => {
21311
21316
  const resp = await runCommand({ action: "eval", script, tabId: tab });
@@ -21318,27 +21323,100 @@ server.tool(
21318
21323
  "Inspect or clear network activity",
21319
21324
  {
21320
21325
  command: external_exports.enum(["requests", "clear"]).describe("Network command"),
21321
- filter: external_exports.string().optional().describe("Optional URL substring filter"),
21322
- withBody: external_exports.boolean().optional().describe("Include request and response bodies"),
21323
- tab: external_exports.number().optional().describe("Tab ID to target")
21326
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)"),
21327
+ filter: external_exports.string().optional().describe("URL substring filter"),
21328
+ since: external_exports.union([external_exports.literal("last_action"), external_exports.number()]).optional().describe("Incremental query: 'last_action' for events since last operation, or seq number"),
21329
+ method: external_exports.string().optional().describe("Filter by HTTP method (GET, POST, etc.)"),
21330
+ status: external_exports.string().optional().describe("Filter by status: '4xx', '5xx', or exact code like '200'"),
21331
+ limit: external_exports.number().optional().describe("Max number of results to return"),
21332
+ withBody: external_exports.boolean().optional().describe("Include request and response bodies")
21324
21333
  },
21325
- async ({ command, filter, withBody, tab }) => {
21334
+ async ({ command, tab, filter, since, method, status, limit, withBody }) => {
21326
21335
  const resp = await runCommand({
21327
21336
  action: "network",
21328
21337
  networkCommand: command,
21329
21338
  filter,
21339
+ since,
21340
+ method,
21341
+ status,
21342
+ limit,
21330
21343
  withBody,
21331
21344
  tabId: tab
21332
21345
  });
21333
21346
  if (!resp.success) return responseError(resp);
21334
- return textResult(command === "requests" ? resp.data?.networkRequests || [] : resp.data || "Cleared");
21347
+ if (command === "requests") {
21348
+ const data = resp.data;
21349
+ return textResult({
21350
+ requests: data?.networkRequests || data?.requests || [],
21351
+ cursor: data?.cursor
21352
+ });
21353
+ }
21354
+ return textResult(resp.data || "Cleared");
21355
+ }
21356
+ );
21357
+ server.tool(
21358
+ "browser_console",
21359
+ "Get or clear console messages",
21360
+ {
21361
+ command: external_exports.enum(["get", "clear"]).describe("Console command"),
21362
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)"),
21363
+ since: external_exports.union([external_exports.literal("last_action"), external_exports.number()]).optional().describe("Incremental query: 'last_action' for events since last operation, or seq number"),
21364
+ filter: external_exports.string().optional().describe("Filter console messages by text substring"),
21365
+ limit: external_exports.number().optional().describe("Max number of results to return")
21366
+ },
21367
+ async ({ command, tab, since, filter, limit }) => {
21368
+ const resp = await runCommand({
21369
+ action: "console",
21370
+ consoleCommand: command,
21371
+ filter,
21372
+ since,
21373
+ limit,
21374
+ tabId: tab
21375
+ });
21376
+ if (!resp.success) return responseError(resp);
21377
+ if (command === "get") {
21378
+ const data = resp.data;
21379
+ return textResult({
21380
+ messages: data?.consoleMessages || data?.messages || [],
21381
+ cursor: data?.cursor
21382
+ });
21383
+ }
21384
+ return textResult(resp.data || "Cleared");
21385
+ }
21386
+ );
21387
+ server.tool(
21388
+ "browser_errors",
21389
+ "Get or clear JavaScript errors",
21390
+ {
21391
+ command: external_exports.enum(["get", "clear"]).describe("Errors command"),
21392
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)"),
21393
+ since: external_exports.union([external_exports.literal("last_action"), external_exports.number()]).optional().describe("Incremental query: 'last_action' for events since last operation, or seq number"),
21394
+ limit: external_exports.number().optional().describe("Max number of results to return")
21395
+ },
21396
+ async ({ command, tab, since, limit }) => {
21397
+ const resp = await runCommand({
21398
+ action: "errors",
21399
+ errorsCommand: command,
21400
+ since,
21401
+ limit,
21402
+ tabId: tab
21403
+ });
21404
+ if (!resp.success) return responseError(resp);
21405
+ if (command === "get") {
21406
+ const data = resp.data;
21407
+ return textResult({
21408
+ errors: data?.jsErrors || data?.errors || [],
21409
+ cursor: data?.cursor
21410
+ });
21411
+ }
21412
+ return textResult(resp.data || "Cleared");
21335
21413
  }
21336
21414
  );
21337
21415
  server.tool(
21338
21416
  "browser_screenshot",
21339
21417
  "Take a screenshot",
21340
21418
  {
21341
- tab: external_exports.number().optional().describe("Tab ID to target")
21419
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21342
21420
  },
21343
21421
  async ({ tab }) => {
21344
21422
  const resp = await runCommand({ action: "screenshot", tabId: tab });
@@ -21360,7 +21438,7 @@ server.tool(
21360
21438
  {
21361
21439
  attribute: external_exports.enum(["text", "url", "title", "value", "html"]).describe("Attribute to retrieve"),
21362
21440
  ref: external_exports.string().optional().describe("Optional element ref"),
21363
- tab: external_exports.number().optional().describe("Tab ID to target")
21441
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21364
21442
  },
21365
21443
  async ({ attribute, ref, tab }) => {
21366
21444
  const resp = await runCommand({ action: "get", attribute, ref, tabId: tab });
@@ -21372,7 +21450,7 @@ server.tool(
21372
21450
  "browser_close",
21373
21451
  "Close the current or specified tab",
21374
21452
  {
21375
- tab: external_exports.number().optional().describe("Tab ID to close")
21453
+ tab: external_exports.string().optional().describe("Tab short ID to close")
21376
21454
  },
21377
21455
  async ({ tab }) => {
21378
21456
  const resp = await runCommand({ action: tab === void 0 ? "close" : "tab_close", tabId: tab });
@@ -21418,7 +21496,7 @@ server.tool(
21418
21496
  "Hover over an element",
21419
21497
  {
21420
21498
  ref: external_exports.string().describe("Element ref from snapshot"),
21421
- tab: external_exports.number().optional().describe("Tab ID to target")
21499
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21422
21500
  },
21423
21501
  async ({ ref, tab }) => {
21424
21502
  const resp = await runCommand({ action: "hover", ref, tabId: tab });
@@ -21431,7 +21509,7 @@ server.tool(
21431
21509
  "Wait for a number of milliseconds",
21432
21510
  {
21433
21511
  time: external_exports.number().describe("Time to wait in milliseconds"),
21434
- tab: external_exports.number().optional().describe("Tab ID to target")
21512
+ tab: external_exports.string().optional().describe("Tab short ID (from tab list or open command)")
21435
21513
  },
21436
21514
  async ({ time: time3, tab }) => {
21437
21515
  const resp = await runCommand({ action: "wait", waitType: "time", ms: time3, tabId: tab });
@@ -21508,7 +21586,7 @@ server.tool(
21508
21586
  name: external_exports.string().describe("Adapter name, e.g. twitter/search"),
21509
21587
  args: external_exports.array(external_exports.string()).optional().describe("Positional arguments in adapter-defined order"),
21510
21588
  namedArgs: external_exports.record(external_exports.string()).optional().describe("Named adapter arguments passed as --key value"),
21511
- tab: external_exports.number().optional().describe("Optional tab ID to target"),
21589
+ tab: external_exports.string().optional().describe("Optional tab short ID to target"),
21512
21590
  openclaw: external_exports.boolean().optional().describe("Prefer the OpenClaw browser instead of the extension flow")
21513
21591
  },
21514
21592
  async ({ name, args, namedArgs, tab, openclaw }) => {