@browserbridge/bbx 1.6.0 → 1.6.2

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.
@@ -5,6 +5,7 @@ import {
5
5
  DEFAULT_NETWORK_LIMIT,
6
6
  METHOD_SET,
7
7
  } from '../../protocol/src/index.js';
8
+ import { createBridgeClientForDestination } from '../../agent-client/src/remotes.js';
8
9
  import {
9
10
  annotateBridgeSummary,
10
11
  applyLimitBudgetPreset,
@@ -65,7 +66,7 @@ export const PAGE_ACTIONS = {
65
66
  };
66
67
 
67
68
  /**
68
- * @param {{ action: string, expression?: string, awaitPromise?: boolean, timeoutMs?: number, returnByValue?: boolean, level?: string, clear?: boolean, limit?: number, type?: string, keys?: string[], textBudget?: number, urlPattern?: string, tabId?: number, budgetPreset?: 'quick' | 'normal' | 'deep' }} args
69
+ * @param {{ action: string, expression?: string, awaitPromise?: boolean, timeoutMs?: number, returnByValue?: boolean, level?: string, clear?: boolean, limit?: number, type?: string, keys?: string[], textBudget?: number, urlPattern?: string, tabId?: number, destinationId?: string, budgetPreset?: 'quick' | 'normal' | 'deep' }} args
69
70
  * @returns {Promise<ToolResult>}
70
71
  */
71
72
  export async function handlePageTool(args) {
@@ -96,11 +97,12 @@ export async function handlePageTool(args) {
96
97
  return callBridgeTool(entry.method, entry.params(normalizedArgs), {
97
98
  tabId: typeof normalizedArgs.tabId === 'number' ? normalizedArgs.tabId : null,
98
99
  tokenBudget: getToolTokenBudget(normalizedArgs),
100
+ destinationId: normalizedArgs.destinationId ?? null,
99
101
  });
100
102
  }
101
103
 
102
104
  /**
103
- * @param {{ calls?: Array<{ method?: string, params?: Record<string, unknown>, tabId?: number, budgetPreset?: 'quick' | 'normal' | 'deep' }> }} args
105
+ * @param {{ calls?: Array<{ method?: string, params?: Record<string, unknown>, tabId?: number, destinationId?: string, budgetPreset?: 'quick' | 'normal' | 'deep' }> }} args
104
106
  * @returns {Promise<ToolResult>}
105
107
  */
106
108
  export async function handleBatchTool(args) {
@@ -149,20 +151,30 @@ export async function handleBatchTool(args) {
149
151
  : null
150
152
  : null;
151
153
  const tokenBudget = getToolTokenBudget(call);
154
+ const destinationId = typeof call.destinationId === 'string' ? call.destinationId : null;
152
155
 
153
156
  const startTime = Date.now();
157
+ const callClient = destinationId
158
+ ? await createBridgeClientForDestination(destinationId)
159
+ : client;
154
160
  try {
155
- const response = await requestBridgeWithRetry(client, method, call.params || {}, {
161
+ if (destinationId) {
162
+ await callClient.connect();
163
+ }
164
+ const response = await requestBridgeWithRetry(callClient, method, call.params || {}, {
156
165
  tabId,
157
166
  source: REQUEST_SOURCE,
158
167
  tokenBudget,
159
168
  });
160
- return summarizeBatchResponseItem({
161
- method,
162
- tabId,
163
- response,
164
- durationMs: Date.now() - startTime,
165
- });
169
+ return {
170
+ destinationId,
171
+ ...summarizeBatchResponseItem({
172
+ method,
173
+ tabId,
174
+ response,
175
+ durationMs: Date.now() - startTime,
176
+ }),
177
+ };
166
178
  } catch (error) {
167
179
  return summarizeBatchErrorItem({
168
180
  method,
@@ -170,6 +182,10 @@ export async function handleBatchTool(args) {
170
182
  error,
171
183
  durationMs: Date.now() - startTime,
172
184
  });
185
+ } finally {
186
+ if (destinationId) {
187
+ await callClient.close();
188
+ }
173
189
  }
174
190
  })
175
191
  );
@@ -191,7 +207,7 @@ export async function handleBatchTool(args) {
191
207
  }
192
208
 
193
209
  /**
194
- * @param {{ method: string, params?: Record<string, unknown>, tabId?: number }} args
210
+ * @param {{ method: string, params?: Record<string, unknown>, tabId?: number, destinationId?: string }} args
195
211
  * @returns {Promise<ToolResult>}
196
212
  */
197
213
  export async function handleRawCallTool(args) {
@@ -199,34 +215,37 @@ export async function handleRawCallTool(args) {
199
215
  return summarizeToolError(`Unknown bridge method "${args.method}".`);
200
216
  }
201
217
 
202
- return withToolClient(async (client) => {
203
- const response = await requestBridgeWithRetry(
204
- client,
205
- /** @type {BridgeMethod} */ (args.method),
206
- args.params || {},
207
- {
208
- tabId: typeof args.tabId === 'number' ? args.tabId : null,
209
- source: REQUEST_SOURCE,
210
- }
211
- );
212
-
213
- if (!response.ok) {
214
- return createToolResult(
215
- response.error.message,
218
+ return withToolClient(
219
+ async (client) => {
220
+ const response = await requestBridgeWithRetry(
221
+ client,
222
+ /** @type {BridgeMethod} */ (args.method),
223
+ args.params || {},
216
224
  {
217
- ok: false,
218
- error: response.error,
219
- response,
220
- },
221
- true
225
+ tabId: typeof args.tabId === 'number' ? args.tabId : null,
226
+ source: REQUEST_SOURCE,
227
+ }
222
228
  );
223
- }
224
229
 
225
- return createToolResult(`Called ${args.method}.`, {
226
- ok: true,
227
- response: response.result,
228
- });
229
- });
230
+ if (!response.ok) {
231
+ return createToolResult(
232
+ response.error.message,
233
+ {
234
+ ok: false,
235
+ error: response.error,
236
+ response,
237
+ },
238
+ true
239
+ );
240
+ }
241
+
242
+ return createToolResult(`Called ${args.method}.`, {
243
+ ok: true,
244
+ response: response.result,
245
+ });
246
+ },
247
+ { destinationId: args.destinationId ?? null }
248
+ );
230
249
  }
231
250
 
232
251
  /**
@@ -290,7 +309,7 @@ const INVESTIGATE_SCOPES = {
290
309
  };
291
310
 
292
311
  /**
293
- * @param {{ objective: string, scope?: 'quick' | 'normal' | 'deep', tabId?: number, selector?: string }} args
312
+ * @param {{ objective: string, scope?: 'quick' | 'normal' | 'deep', tabId?: number, destinationId?: string, selector?: string }} args
294
313
  * @returns {Promise<ToolResult>}
295
314
  */
296
315
  export async function handleInvestigateTool(args) {
@@ -305,62 +324,65 @@ export async function handleInvestigateTool(args) {
305
324
  return summarizeToolError(`Unsupported investigation scope "${scopeName}".`);
306
325
  }
307
326
 
308
- return withToolClient(async (client) => {
309
- const requestedTabId = typeof args.tabId === 'number' ? args.tabId : null;
327
+ return withToolClient(
328
+ async (client) => {
329
+ const requestedTabId = typeof args.tabId === 'number' ? args.tabId : null;
310
330
 
311
- /** @type {Array<{ method: string, ok: boolean, summary: string, evidence: unknown, durationMs: number }>} */
312
- const stepResults = [];
331
+ /** @type {Array<{ method: string, ok: boolean, summary: string, evidence: unknown, durationMs: number }>} */
332
+ const stepResults = [];
313
333
 
314
- for (const step of scope.steps) {
315
- const startTime = Date.now();
316
- try {
317
- const response = await requestBridgeWithRetry(client, step.method, step.params(args), {
318
- tabId: requestedTabId,
319
- source: REQUEST_SOURCE,
320
- tokenBudget: null,
321
- });
322
- const bridgeSummary = annotateBridgeSummary(
323
- summarizeBridgeResponse(response, step.method),
324
- response
325
- );
326
- stepResults.push({
327
- method: step.method,
328
- ok: bridgeSummary.ok,
329
- summary: bridgeSummary.summary,
330
- evidence: bridgeSummary.evidence,
331
- durationMs: Date.now() - startTime,
332
- });
333
- } catch (error) {
334
- const message = error instanceof Error ? error.message : String(error);
335
- stepResults.push({
336
- method: step.method,
337
- ok: false,
338
- summary: `ERROR: ${message}`,
339
- evidence: null,
340
- durationMs: Date.now() - startTime,
341
- });
334
+ for (const step of scope.steps) {
335
+ const startTime = Date.now();
336
+ try {
337
+ const response = await requestBridgeWithRetry(client, step.method, step.params(args), {
338
+ tabId: requestedTabId,
339
+ source: REQUEST_SOURCE,
340
+ tokenBudget: null,
341
+ });
342
+ const bridgeSummary = annotateBridgeSummary(
343
+ summarizeBridgeResponse(response, step.method),
344
+ response
345
+ );
346
+ stepResults.push({
347
+ method: step.method,
348
+ ok: bridgeSummary.ok,
349
+ summary: bridgeSummary.summary,
350
+ evidence: bridgeSummary.evidence,
351
+ durationMs: Date.now() - startTime,
352
+ });
353
+ } catch (error) {
354
+ const message = error instanceof Error ? error.message : String(error);
355
+ stepResults.push({
356
+ method: step.method,
357
+ ok: false,
358
+ summary: `ERROR: ${message}`,
359
+ evidence: null,
360
+ durationMs: Date.now() - startTime,
361
+ });
362
+ }
342
363
  }
343
- }
344
364
 
345
- const failedSteps = stepResults.filter((s) => !s.ok);
346
- const allOk = failedSteps.length === 0;
347
- const totalDuration = stepResults.reduce((sum, s) => sum + s.durationMs, 0);
365
+ const failedSteps = stepResults.filter((s) => !s.ok);
366
+ const allOk = failedSteps.length === 0;
367
+ const totalDuration = stepResults.reduce((sum, s) => sum + s.durationMs, 0);
348
368
 
349
- const summaryText = allOk
350
- ? `Investigation complete (${scope.label}, ${stepResults.length} steps, ${totalDuration}ms). Objective: ${objective}`
351
- : `Investigation partial (${scope.label}, ${stepResults.length} steps, ${failedSteps.length} failed, ${totalDuration}ms). Objective: ${objective}`;
369
+ const summaryText = allOk
370
+ ? `Investigation complete (${scope.label}, ${stepResults.length} steps, ${totalDuration}ms). Objective: ${objective}`
371
+ : `Investigation partial (${scope.label}, ${stepResults.length} steps, ${failedSteps.length} failed, ${totalDuration}ms). Objective: ${objective}`;
352
372
 
353
- return createToolResult(
354
- summaryText,
355
- {
356
- ok: allOk,
357
- objective,
358
- scope: scopeName,
359
- heuristicFallback: true,
360
- steps: stepResults,
361
- failedSteps,
362
- },
363
- !allOk
364
- );
365
- });
373
+ return createToolResult(
374
+ summaryText,
375
+ {
376
+ ok: allOk,
377
+ objective,
378
+ scope: scopeName,
379
+ heuristicFallback: true,
380
+ steps: stepResults,
381
+ failedSteps,
382
+ },
383
+ !allOk
384
+ );
385
+ },
386
+ { destinationId: args.destinationId ?? null }
387
+ );
366
388
  }
@@ -17,6 +17,10 @@ import {
17
17
  resolveRef,
18
18
  withBridgeClient,
19
19
  } from '../../agent-client/src/runtime.js';
20
+ import {
21
+ createBridgeClientForDestination,
22
+ listBridgeDestinations,
23
+ } from '../../agent-client/src/remotes.js';
20
24
  import { annotateBridgeSummary, summarizeBridgeResponse } from '../../agent-client/src/subagent.js';
21
25
 
22
26
  /** @typedef {import('../../protocol/src/types.js').BridgeMethod} BridgeMethod */
@@ -130,11 +134,21 @@ export function summarizeToolError(error) {
130
134
 
131
135
  /**
132
136
  * @param {(client: import('../../agent-client/src/client.js').BridgeClient) => Promise<ToolResult>} callback
137
+ * @param {{ destinationId?: string | null }} [options]
133
138
  * @returns {Promise<ToolResult>}
134
139
  */
135
- export async function withToolClient(callback) {
140
+ export async function withToolClient(callback, options = {}) {
136
141
  try {
137
- return await withBridgeClient(callback);
142
+ if (!options.destinationId) {
143
+ return await withBridgeClient(callback);
144
+ }
145
+ const client = await createBridgeClientForDestination(options.destinationId);
146
+ await client.connect();
147
+ try {
148
+ return await callback(client);
149
+ } finally {
150
+ await client.close();
151
+ }
138
152
  } catch (error) {
139
153
  return summarizeToolError(error);
140
154
  }
@@ -306,18 +320,28 @@ export async function requestBridgeWithRetry(client, method, params, options) {
306
320
  /**
307
321
  * @param {BridgeMethod} method
308
322
  * @param {Record<string, unknown>} [params={}]
309
- * @param {{ tabId?: number | null, summaryMethod?: string, tokenBudget?: number | null }} [options]
323
+ * @param {{ tabId?: number | null, summaryMethod?: string, tokenBudget?: number | null, destinationId?: string | null }} [options]
310
324
  * @returns {Promise<ToolResult>}
311
325
  */
312
326
  export async function callBridgeTool(method, params = {}, options = {}) {
313
- return withToolClient(async (client) => {
314
- const response = await requestBridgeWithRetry(client, method, params, {
315
- tabId: options.tabId ?? null,
316
- source: REQUEST_SOURCE,
317
- tokenBudget: options.tokenBudget ?? null,
318
- });
319
- return summarizeToolResponse(response, options.summaryMethod || method);
320
- });
327
+ return withToolClient(
328
+ async (client) => {
329
+ const response = await requestBridgeWithRetry(client, method, params, {
330
+ tabId: options.tabId ?? null,
331
+ source: REQUEST_SOURCE,
332
+ tokenBudget: options.tokenBudget ?? null,
333
+ });
334
+ return summarizeToolResponse(response, options.summaryMethod || method);
335
+ },
336
+ { destinationId: options.destinationId ?? null }
337
+ );
338
+ }
339
+
340
+ /**
341
+ * @returns {Promise<Array<{ id: string, local: boolean, host: string | null, port: number | null }>>}
342
+ */
343
+ export async function getBridgeDestinations() {
344
+ return listBridgeDestinations();
321
345
  }
322
346
 
323
347
  /**
@@ -333,22 +357,25 @@ export async function callBridgeTool(method, params = {}, options = {}) {
333
357
  export async function dispatchToolAction(actions, args, toolName) {
334
358
  const entry = actions[args.action];
335
359
  if (!entry) return summarizeToolError(`Unsupported ${toolName} action "${args.action}".`);
336
- return withToolClient(async (client) => {
337
- const requestedTabId = typeof args.tabId === 'number' ? args.tabId : null;
338
- const ref = entry.ref
339
- ? await resolveToolRef(
340
- client,
341
- /** @type {{ elementRef?: string, selector?: string }} */ (args),
342
- requestedTabId
343
- )
344
- : undefined;
345
- const response = await requestBridgeWithRetry(client, entry.method, entry.params(args, ref), {
346
- tabId: requestedTabId,
347
- source: REQUEST_SOURCE,
348
- tokenBudget: getToolTokenBudget(/** @type {{ budgetPreset?: unknown }} */ (args)),
349
- });
350
- return summarizeToolResponse(response, entry.method);
351
- });
360
+ return withToolClient(
361
+ async (client) => {
362
+ const requestedTabId = typeof args.tabId === 'number' ? args.tabId : null;
363
+ const ref = entry.ref
364
+ ? await resolveToolRef(
365
+ client,
366
+ /** @type {{ elementRef?: string, selector?: string }} */ (args),
367
+ requestedTabId
368
+ )
369
+ : undefined;
370
+ const response = await requestBridgeWithRetry(client, entry.method, entry.params(args, ref), {
371
+ tabId: requestedTabId,
372
+ source: REQUEST_SOURCE,
373
+ tokenBudget: getToolTokenBudget(/** @type {{ budgetPreset?: unknown }} */ (args)),
374
+ });
375
+ return summarizeToolResponse(response, entry.method);
376
+ },
377
+ { destinationId: typeof args.destinationId === 'string' ? args.destinationId : null }
378
+ );
352
379
  }
353
380
 
354
381
  export {
@@ -357,6 +384,7 @@ export {
357
384
  requestBridge,
358
385
  resolveRef,
359
386
  withBridgeClient,
387
+ listBridgeDestinations,
360
388
  annotateBridgeSummary,
361
389
  summarizeBridgeResponse,
362
390
  summarizeBatchErrorItem,
@@ -8,6 +8,7 @@ import {
8
8
  createToolResult,
9
9
  getDoctorReport,
10
10
  getToolTokenBudget,
11
+ getBridgeDestinations,
11
12
  applyLimitBudgetPreset,
12
13
  summarizeToolError,
13
14
  summarizeToolResponse,
@@ -71,6 +72,22 @@ const HOME_DIR = os.homedir();
71
72
  export async function handleStatusTool() {
72
73
  try {
73
74
  const report = await getDoctorReport();
75
+ const destinations = await Promise.all(
76
+ (await getBridgeDestinations()).map(async (destination) => {
77
+ if (destination.local) {
78
+ return {
79
+ ...destination,
80
+ reachable: report.daemonReachable,
81
+ extensionConnected: report.extensionConnected,
82
+ accessEnabled: report.accessEnabled,
83
+ routeReady: report.routeReady,
84
+ routeTabId: report.routeTabId,
85
+ };
86
+ }
87
+ const result = await callRemoteHealth(destination.id);
88
+ return { ...destination, ...result };
89
+ })
90
+ );
74
91
  const summary =
75
92
  report.issues.length === 0
76
93
  ? 'Browser Bridge is ready.'
@@ -78,12 +95,25 @@ export async function handleStatusTool() {
78
95
  return createToolResult(summary, {
79
96
  ok: report.issues.length === 0,
80
97
  evidence: report,
98
+ destinations,
81
99
  });
82
100
  } catch (error) {
83
101
  return summarizeToolError(error);
84
102
  }
85
103
  }
86
104
 
105
+ /**
106
+ * @param {string} destinationId
107
+ * @returns {Promise<Record<string, unknown>>}
108
+ */
109
+ async function callRemoteHealth(destinationId) {
110
+ const result = await callBridgeTool('health.ping', {}, { destinationId });
111
+ return {
112
+ reachable: result.structuredContent.ok === true,
113
+ health: result.structuredContent,
114
+ };
115
+ }
116
+
87
117
  /**
88
118
  * @returns {Promise<ToolResult>}
89
119
  */
@@ -138,21 +168,33 @@ export async function handleLogTool(args) {
138
168
  }
139
169
 
140
170
  /**
171
+ * @param {{ destinationId?: string }} [args]
141
172
  * @returns {Promise<ToolResult>}
142
173
  */
143
- export async function handleHealthTool() {
144
- return withToolClient(async (client) => {
145
- const response = await client.request({
146
- method: 'health.ping',
147
- meta: { source: REQUEST_SOURCE },
148
- });
149
- return summarizeToolResponse(response, 'health.ping');
150
- });
174
+ export async function handleHealthTool(args = {}) {
175
+ const destinationId = typeof args.destinationId === 'string' ? args.destinationId : null;
176
+ return withToolClient(
177
+ async (client) => {
178
+ const response = await client.request({
179
+ method: 'health.ping',
180
+ meta: { source: REQUEST_SOURCE },
181
+ });
182
+ return summarizeToolResponse(response, 'health.ping');
183
+ },
184
+ { destinationId }
185
+ );
151
186
  }
152
187
 
153
188
  /**
189
+ * @param {{ destinationId?: string }} [args]
154
190
  * @returns {Promise<ToolResult>}
155
191
  */
156
- export async function handleAccessTool() {
157
- return callBridgeTool('access.request');
192
+ export async function handleAccessTool(args = {}) {
193
+ return callBridgeTool(
194
+ 'access.request',
195
+ {},
196
+ {
197
+ destinationId: typeof args.destinationId === 'string' ? args.destinationId : null,
198
+ }
199
+ );
158
200
  }
@@ -40,11 +40,13 @@ import {
40
40
  getMethodsByMaxComplexity,
41
41
  } from '../../protocol/src/index.js';
42
42
  import { applyWindowsTcpTransportDefaults } from '../../native-host/src/config.js';
43
- import { MCP_SERVER_INSTRUCTIONS, registerBridgeMcpGuidance } from './guidance.js';
43
+ import { MCP_SERVER_INSTRUCTIONS } from './guidance.js';
44
44
 
45
45
  export const BUDGET_PRESET_DESCRIPTION = `Budget preset: "quick", "normal", or "deep" (defaults: query ${BUDGET_PRESETS.normal.maxNodes} nodes / depth ${BUDGET_PRESETS.normal.maxDepth} / text ${BUDGET_PRESETS.normal.textBudget}). Numeric fields override the preset when both are provided.`;
46
46
  export const TAB_ID_DESCRIPTION =
47
47
  'Target a specific tab instead of the active tab in the enabled window.';
48
+ export const DESTINATION_ID_DESCRIPTION =
49
+ 'Optional Browser Bridge destination ID from browser_status/browser_tabs; omit for local.';
48
50
 
49
51
  const MCP_SERVER_VERSION = loadPackageVersion();
50
52
 
@@ -109,7 +111,9 @@ export function createBridgeMcpServer() {
109
111
  title: 'Browser Bridge Status',
110
112
  description:
111
113
  'Check bridge readiness: daemon connectivity, extension state, and window access. Call first to confirm the bridge is usable. If access is not enabled, ask the user to click Enable in the extension popup or side panel, then retry.',
112
- inputSchema: {},
114
+ inputSchema: {
115
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
116
+ },
113
117
  },
114
118
  handleStatusTool
115
119
  );
@@ -155,7 +159,9 @@ export function createBridgeMcpServer() {
155
159
  {
156
160
  title: 'Browser Bridge Health',
157
161
  description: 'Ping the bridge to verify daemon and extension connectivity.',
158
- inputSchema: {},
162
+ inputSchema: {
163
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
164
+ },
159
165
  },
160
166
  handleHealthTool
161
167
  );
@@ -173,6 +179,7 @@ export function createBridgeMcpServer() {
173
179
  url: z.string().optional().describe('URL for create action'),
174
180
  active: z.boolean().optional().describe('Focus the new tab (default: true)'),
175
181
  tabId: z.number().int().positive().optional().describe('Tab ID (required for close)'),
182
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
176
183
  },
177
184
  },
178
185
  handleTabsTool
@@ -199,6 +206,7 @@ export function createBridgeMcpServer() {
199
206
  ])
200
207
  .describe('DOM operation to perform'),
201
208
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
209
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
202
210
  budgetPreset: z
203
211
  .enum(['quick', 'normal', 'deep'])
204
212
  .optional()
@@ -291,6 +299,7 @@ export function createBridgeMcpServer() {
291
299
  .enum(['computed', 'matched_rules', 'box_model', 'hit_test'])
292
300
  .describe('Style/layout operation to perform'),
293
301
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
302
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
294
303
  budgetPreset: z
295
304
  .enum(['quick', 'normal', 'deep'])
296
305
  .optional()
@@ -336,6 +345,7 @@ export function createBridgeMcpServer() {
336
345
  ])
337
346
  .describe('Page operation to perform'),
338
347
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
348
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
339
349
  budgetPreset: z
340
350
  .enum(['quick', 'normal', 'deep'])
341
351
  .optional()
@@ -397,6 +407,7 @@ export function createBridgeMcpServer() {
397
407
  .enum(['navigate', 'reload', 'go_back', 'go_forward', 'scroll', 'resize'])
398
408
  .describe('Navigation operation to perform'),
399
409
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
410
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
400
411
  budgetPreset: z
401
412
  .enum(['quick', 'normal', 'deep'])
402
413
  .optional()
@@ -451,6 +462,7 @@ export function createBridgeMcpServer() {
451
462
  ])
452
463
  .describe('Input operation to perform'),
453
464
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
465
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
454
466
  budgetPreset: z
455
467
  .enum(['quick', 'normal', 'deep'])
456
468
  .optional()
@@ -533,6 +545,7 @@ export function createBridgeMcpServer() {
533
545
  .enum(['apply_styles', 'apply_dom', 'list', 'rollback', 'commit_baseline'])
534
546
  .describe('Patch operation to perform'),
535
547
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
548
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
536
549
  budgetPreset: z
537
550
  .enum(['quick', 'normal', 'deep'])
538
551
  .optional()
@@ -593,6 +606,7 @@ export function createBridgeMcpServer() {
593
606
  'element (preferred), region (tight crop), full_page (document-level only), or cdp_* for low-level data'
594
607
  ),
595
608
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
609
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
596
610
  budgetPreset: z
597
611
  .enum(['quick', 'normal', 'deep'])
598
612
  .optional()
@@ -638,6 +652,7 @@ export function createBridgeMcpServer() {
638
652
  .optional()
639
653
  .describe('Method params for this call'),
640
654
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
655
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
641
656
  budgetPreset: z
642
657
  .enum(['quick', 'normal', 'deep'])
643
658
  .optional()
@@ -664,6 +679,7 @@ export function createBridgeMcpServer() {
664
679
  .optional()
665
680
  .describe('Method parameters as object'),
666
681
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
682
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
667
683
  },
668
684
  },
669
685
  handleRawCallTool
@@ -675,7 +691,9 @@ export function createBridgeMcpServer() {
675
691
  title: 'Browser Bridge Runtime Context',
676
692
  description:
677
693
  'Return runtime context: budget presets, method groups, and active limits. Call to discover defaults before inspecting a page.',
678
- inputSchema: {},
694
+ inputSchema: {
695
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
696
+ },
679
697
  },
680
698
  handleSkillTool
681
699
  );
@@ -726,6 +744,7 @@ export function createBridgeMcpServer() {
726
744
  '"deep" (state + DOM + text + console + network).'
727
745
  ),
728
746
  tabId: z.number().int().positive().optional().describe(TAB_ID_DESCRIPTION),
747
+ destinationId: z.string().optional().describe(DESTINATION_ID_DESCRIPTION),
729
748
  selector: z
730
749
  .string()
731
750
  .optional()
@@ -735,8 +754,6 @@ export function createBridgeMcpServer() {
735
754
  handleInvestigateTool
736
755
  );
737
756
 
738
- registerBridgeMcpGuidance(server);
739
-
740
757
  return server;
741
758
  }
742
759