@rudderhq/cli 0.5.1 → 0.5.2-canary.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/index.js CHANGED
@@ -43,7 +43,7 @@ var init_chat_work_manifest = __esm({
43
43
  });
44
44
 
45
45
  // ../packages/shared/dist/constants.js
46
- var ORGANIZATION_STATUSES, ORGANIZATION_INTELLIGENCE_PROFILE_PURPOSES, ORGANIZATION_INTELLIGENCE_PROFILE_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES, AUTH_BASE_URL_MODES, AGENT_STATUSES, AGENT_RUNTIME_TYPES, AGENT_ROLES, AGENT_ICON_NAMES, AGENT_OREO_ICON_PREFIX, AGENT_OREO_SHAPE_IDS, AGENT_OREO_PALETTE_IDS, AGENT_DICEBEAR_NOTIONISTS_ICON_PREFIX, AGENT_AVATAR_BACKGROUND_PRESET_IDS, ISSUE_STATUSES, ISSUE_PRIORITIES, AGENT_INTEGRATION_PROVIDERS, AGENT_INTEGRATION_STATUSES, AGENT_INTEGRATION_TRANSPORTS, AGENT_INTEGRATION_PROVIDER_REGIONS, AGENT_INTEGRATION_CHAT_TYPES, AGENT_INTEGRATION_DROP_REASONS, AGENT_INTEGRATION_OUTBOUND_STATUSES, CUSTOM_INTEGRATION_KINDS, CUSTOM_INTEGRATION_SCOPES, CUSTOM_INTEGRATION_STATUSES, CUSTOM_INTEGRATION_TOOL_STATUSES, CUSTOM_INTEGRATION_BINDING_STATUSES, CUSTOM_INTEGRATION_TOOL_CALL_STATUSES, CALENDAR_SOURCE_TYPES, CALENDAR_OWNER_TYPES, CALENDAR_VISIBILITIES, CALENDAR_SOURCE_STATUSES, CALENDAR_EVENT_KINDS, CALENDAR_EVENT_STATUSES, CALENDAR_SOURCE_MODES, CHAT_CONVERSATION_STATUSES, CHAT_ISSUE_CREATION_MODES, CHAT_MESSAGE_ROLES, CHAT_MESSAGE_KINDS, CHAT_MESSAGE_STATUSES, CHAT_CONTEXT_ENTITY_TYPES, GOAL_LEVELS, GOAL_STATUSES, PROJECT_STATUSES, ORGANIZATION_RESOURCE_KINDS, ORGANIZATION_RESOURCE_SOURCE_TYPES, PROJECT_RESOURCE_ATTACHMENT_ROLES, AUTOMATION_STATUSES, AUTOMATION_CONCURRENCY_POLICIES, AUTOMATION_CATCH_UP_POLICIES, AUTOMATION_OUTPUT_MODES, AUTOMATION_TRIGGER_SIGNING_MODES, PROJECT_COLORS, PROJECT_ICONS, APPROVAL_TYPES, SECRET_PROVIDERS, STORAGE_PROVIDERS, BILLING_TYPES, FINANCE_EVENT_KINDS, FINANCE_DIRECTIONS, FINANCE_UNITS, BUDGET_SCOPE_TYPES, BUDGET_METRICS, BUDGET_WINDOW_KINDS, BUDGET_INCIDENT_RESOLUTION_ACTIONS, INVITE_JOIN_TYPES, JOIN_REQUEST_TYPES, JOIN_REQUEST_STATUSES, PERMISSION_KEYS, PLUGIN_STATUSES, PLUGIN_CATEGORIES, PLUGIN_CAPABILITIES, PLUGIN_UI_SLOT_TYPES, PLUGIN_RESERVED_COMPANY_ROUTE_SEGMENTS, PLUGIN_LAUNCHER_PLACEMENT_ZONES, PLUGIN_LAUNCHER_ACTIONS, PLUGIN_LAUNCHER_BOUNDS, PLUGIN_LAUNCHER_RENDER_ENVIRONMENTS, PLUGIN_UI_SLOT_ENTITY_TYPES, PLUGIN_STATE_SCOPE_KINDS;
46
+ var ORGANIZATION_STATUSES, ORGANIZATION_INTELLIGENCE_PROFILE_PURPOSES, ORGANIZATION_INTELLIGENCE_PROFILE_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES, AUTH_BASE_URL_MODES, AGENT_STATUSES, AGENT_RUNTIME_TYPES, AGENT_ROLES, AGENT_ICON_NAMES, AGENT_OREO_ICON_PREFIX, AGENT_OREO_SHAPE_IDS, AGENT_OREO_PALETTE_IDS, AGENT_DICEBEAR_NOTIONISTS_ICON_PREFIX, AGENT_AVATAR_BACKGROUND_PRESET_IDS, ISSUE_STATUSES, ISSUE_PRIORITIES, AGENT_INTEGRATION_PROVIDERS, AGENT_INTEGRATION_STATUSES, AGENT_INTEGRATION_TRANSPORTS, AGENT_INTEGRATION_PROVIDER_REGIONS, AGENT_INTEGRATION_CHAT_TYPES, AGENT_INTEGRATION_DROP_REASONS, AGENT_INTEGRATION_OUTBOUND_STATUSES, RUDDER_AGENT_V1_MCP_TOOL_NAMES, RUDDER_BROWSER_MCP_TOOL_NAMES2, RUDDER_CORE_MCP_TOOL_NAMES2, CUSTOM_INTEGRATION_KINDS, CUSTOM_INTEGRATION_SCOPES, CUSTOM_INTEGRATION_STATUSES, CUSTOM_INTEGRATION_TOOL_STATUSES, CUSTOM_INTEGRATION_BINDING_STATUSES, CUSTOM_INTEGRATION_TOOL_CALL_STATUSES, CALENDAR_SOURCE_TYPES, CALENDAR_OWNER_TYPES, CALENDAR_VISIBILITIES, CALENDAR_SOURCE_STATUSES, CALENDAR_EVENT_KINDS, CALENDAR_EVENT_STATUSES, CALENDAR_SOURCE_MODES, CHAT_CONVERSATION_STATUSES, CHAT_ISSUE_CREATION_MODES, CHAT_MESSAGE_ROLES, CHAT_MESSAGE_KINDS, CHAT_MESSAGE_STATUSES, CHAT_CONTEXT_ENTITY_TYPES, GOAL_LEVELS, GOAL_STATUSES, PROJECT_STATUSES, ORGANIZATION_RESOURCE_KINDS, ORGANIZATION_RESOURCE_SOURCE_TYPES, PROJECT_RESOURCE_ATTACHMENT_ROLES, AUTOMATION_STATUSES, AUTOMATION_CONCURRENCY_POLICIES, AUTOMATION_CATCH_UP_POLICIES, AUTOMATION_OUTPUT_MODES, AUTOMATION_TRIGGER_SIGNING_MODES, PROJECT_COLORS, PROJECT_ICONS, APPROVAL_TYPES, SECRET_PROVIDERS, STORAGE_PROVIDERS, BILLING_TYPES, FINANCE_EVENT_KINDS, FINANCE_DIRECTIONS, FINANCE_UNITS, BUDGET_SCOPE_TYPES, BUDGET_METRICS, BUDGET_WINDOW_KINDS, BUDGET_INCIDENT_RESOLUTION_ACTIONS, INVITE_JOIN_TYPES, JOIN_REQUEST_TYPES, JOIN_REQUEST_STATUSES, PERMISSION_KEYS, PLUGIN_STATUSES, PLUGIN_CATEGORIES, PLUGIN_CAPABILITIES, PLUGIN_UI_SLOT_TYPES, PLUGIN_RESERVED_COMPANY_ROUTE_SEGMENTS, PLUGIN_LAUNCHER_PLACEMENT_ZONES, PLUGIN_LAUNCHER_ACTIONS, PLUGIN_LAUNCHER_BOUNDS, PLUGIN_LAUNCHER_RENDER_ENVIRONMENTS, PLUGIN_UI_SLOT_ENTITY_TYPES, PLUGIN_STATE_SCOPE_KINDS;
47
47
  var init_constants = __esm({
48
48
  "../packages/shared/dist/constants.js"() {
49
49
  "use strict";
@@ -216,6 +216,104 @@ var init_constants = __esm({
216
216
  "unsupported_message_type"
217
217
  ];
218
218
  AGENT_INTEGRATION_OUTBOUND_STATUSES = ["pending", "streaming", "final", "error"];
219
+ RUDDER_AGENT_V1_MCP_TOOL_NAMES = [
220
+ "rudder_agent_me",
221
+ "rudder_agent_inbox",
222
+ "rudder_agent_capabilities",
223
+ "rudder_agent_update",
224
+ "rudder_agent_skills_create",
225
+ "rudder_agent_skills_enable",
226
+ "rudder_agent_skills_sync",
227
+ "rudder_issue_get",
228
+ "rudder_issue_search",
229
+ "rudder_issue_context",
230
+ "rudder_issue_checkout",
231
+ "rudder_issue_comment",
232
+ "rudder_issue_comments_list",
233
+ "rudder_issue_comments_get",
234
+ "rudder_issue_update",
235
+ "rudder_issue_review",
236
+ "rudder_issue_commit",
237
+ "rudder_issue_done",
238
+ "rudder_issue_block",
239
+ "rudder_project_list",
240
+ "rudder_project_get",
241
+ "rudder_project_create",
242
+ "rudder_project_update",
243
+ "rudder_user_activity",
244
+ "rudder_library_file_list",
245
+ "rudder_library_file_get",
246
+ "rudder_library_file_ref",
247
+ "rudder_library_file_link",
248
+ "rudder_library_file_put",
249
+ "rudder_approval_get",
250
+ "rudder_approval_issues",
251
+ "rudder_approval_comment",
252
+ "rudder_skill_list",
253
+ "rudder_skill_get",
254
+ "rudder_skill_file",
255
+ "rudder_skill_import",
256
+ "rudder_skill_scan_local",
257
+ "rudder_skill_scan_projects",
258
+ "rudder_browser_tabs",
259
+ "rudder_browser_user_tabs",
260
+ "rudder_browser_open",
261
+ "rudder_browser_navigate",
262
+ "rudder_browser_back",
263
+ "rudder_browser_forward",
264
+ "rudder_browser_reload",
265
+ "rudder_browser_viewport",
266
+ "rudder_browser_visibility",
267
+ "rudder_browser_snapshot",
268
+ "rudder_browser_locator",
269
+ "rudder_browser_cua",
270
+ "rudder_browser_dom_cua",
271
+ "rudder_browser_dialog",
272
+ "rudder_browser_clipboard",
273
+ "rudder_browser_logs",
274
+ "rudder_browser_download",
275
+ "rudder_browser_assets",
276
+ "rudder_browser_content",
277
+ "rudder_browser_wait",
278
+ "rudder_browser_read",
279
+ "rudder_browser_click",
280
+ "rudder_browser_type",
281
+ "rudder_browser_screenshot",
282
+ "rudder_browser_close",
283
+ "rudder_automation_list",
284
+ "rudder_automation_get",
285
+ "rudder_automation_runs",
286
+ "rudder_automation_triggers_list",
287
+ "rudder_automation_triggers_create",
288
+ "rudder_automation_triggers_update",
289
+ "rudder_automation_triggers_delete",
290
+ "rudder_automation_triggers_rotate_secret",
291
+ "rudder_automation_create",
292
+ "rudder_automation_update",
293
+ "rudder_automation_enable",
294
+ "rudder_automation_disable",
295
+ "rudder_automation_run",
296
+ "rudder_chat_list",
297
+ "rudder_chat_search",
298
+ "rudder_chat_get",
299
+ "rudder_chat_messages",
300
+ "rudder_chat_transcript",
301
+ "rudder_chat_read",
302
+ "rudder_chat_create",
303
+ "rudder_chat_send",
304
+ "rudder_chat_archive",
305
+ "rudder_runs_list",
306
+ "rudder_runs_by_skill",
307
+ "rudder_runs_get",
308
+ "rudder_runs_events",
309
+ "rudder_runs_log",
310
+ "rudder_runs_transcript",
311
+ "rudder_runs_errors",
312
+ "rudder_runs_cancel",
313
+ "rudder_runs_retry"
314
+ ];
315
+ RUDDER_BROWSER_MCP_TOOL_NAMES2 = RUDDER_AGENT_V1_MCP_TOOL_NAMES.filter((name) => name.startsWith("rudder_browser_"));
316
+ RUDDER_CORE_MCP_TOOL_NAMES2 = RUDDER_AGENT_V1_MCP_TOOL_NAMES.filter((name) => !name.startsWith("rudder_browser_"));
219
317
  CUSTOM_INTEGRATION_KINDS = ["custom_api", "mcp_server"];
220
318
  CUSTOM_INTEGRATION_SCOPES = ["organization", "agent"];
221
319
  CUSTOM_INTEGRATION_STATUSES = ["active", "disabled", "error", "revoked"];
@@ -1149,13 +1247,14 @@ function isCanonicalPortableLibraryPath(value, allowRoot) {
1149
1247
  const segments = value.split("/");
1150
1248
  return segments.every((segment) => Boolean(segment) && segment !== "." && segment !== ".." && !segment.startsWith("~"));
1151
1249
  }
1152
- var uuid, nonBlankId, libraryPathSchema, libraryDirectoryPathSchema, browserUrlSchema, messengerSavedViewTargetSchema, savedViewMetadataShape, createMessengerSavedViewSchema, updateMessengerSavedViewSchema, reorderMessengerSavedViewsSchema, listMessengerSavedViewsQuerySchema;
1250
+ var uuid, nonBlankId, viewInstanceIdSchema, libraryPathSchema, libraryDirectoryPathSchema, browserUrlSchema, messengerSavedViewTargetSchema, savedViewMetadataShape, createMessengerSavedViewSchema, messengerSavedViewAnchorSchema, keepMessengerSavedViewSchema, updateMessengerSavedViewSchema, reorderMessengerSavedViewsSchema, listMessengerSavedViewsQuerySchema;
1153
1251
  var init_messenger = __esm({
1154
1252
  "../packages/shared/dist/validators/messenger.js"() {
1155
1253
  "use strict";
1156
1254
  init_chat();
1157
1255
  uuid = z3.string().uuid();
1158
1256
  nonBlankId = z3.string().trim().min(1).max(240);
1257
+ viewInstanceIdSchema = z3.string().trim().min(1).max(1e3);
1159
1258
  libraryPathSchema = z3.string().max(4096).refine((value) => isCanonicalPortableLibraryPath(value, false), "Library path must be canonical and relative");
1160
1259
  libraryDirectoryPathSchema = z3.string().max(4096).refine((value) => isCanonicalPortableLibraryPath(value, true), "Library directory path must be canonical and relative");
1161
1260
  browserUrlSchema = z3.string().trim().min(1).max(8192).refine((value) => {
@@ -1167,12 +1266,19 @@ var init_messenger = __esm({
1167
1266
  }
1168
1267
  }, "Browser URL must be an absolute HTTP(S) URL");
1169
1268
  messengerSavedViewTargetSchema = z3.discriminatedUnion("kind", [
1170
- z3.object({ kind: z3.literal("browser"), tabId: nonBlankId, url: browserUrlSchema }).strict(),
1171
- z3.object({ kind: z3.literal("automation"), automationId: uuid }).strict(),
1172
- z3.object({ kind: z3.literal("library_document"), documentId: uuid }).strict(),
1173
- z3.object({ kind: z3.literal("library_entry"), entryId: uuid, path: libraryPathSchema }).strict(),
1174
- z3.object({ kind: z3.literal("library_file"), filePath: libraryPathSchema }).strict(),
1175
- z3.object({ kind: z3.literal("library_directory"), directoryPath: libraryDirectoryPathSchema }).strict()
1269
+ z3.object({ kind: z3.literal("browser"), tabId: nonBlankId, url: browserUrlSchema, viewInstanceId: viewInstanceIdSchema }).strict(),
1270
+ z3.object({ kind: z3.literal("automation"), automationId: uuid, viewInstanceId: viewInstanceIdSchema }).strict(),
1271
+ z3.object({ kind: z3.literal("library_document"), documentId: uuid, viewInstanceId: viewInstanceIdSchema }).strict(),
1272
+ z3.object({ kind: z3.literal("library_entry"), entryId: uuid, path: libraryPathSchema, viewInstanceId: viewInstanceIdSchema }).strict(),
1273
+ z3.object({ kind: z3.literal("library_file"), filePath: libraryPathSchema, viewInstanceId: viewInstanceIdSchema }).strict(),
1274
+ z3.object({ kind: z3.literal("library_directory"), directoryPath: libraryDirectoryPathSchema, viewInstanceId: viewInstanceIdSchema }).strict(),
1275
+ z3.object({
1276
+ kind: z3.literal("local_app"),
1277
+ desktopInstallationId: nonBlankId,
1278
+ appPublicId: nonBlankId,
1279
+ localBindingId: nonBlankId,
1280
+ viewInstanceId: viewInstanceIdSchema
1281
+ }).strict()
1176
1282
  ]);
1177
1283
  savedViewMetadataShape = {
1178
1284
  title: z3.string().trim().min(1).max(240),
@@ -1183,12 +1289,27 @@ var init_messenger = __esm({
1183
1289
  target: messengerSavedViewTargetSchema,
1184
1290
  ...savedViewMetadataShape
1185
1291
  }).strict();
1292
+ messengerSavedViewAnchorSchema = z3.discriminatedUnion("kind", [
1293
+ z3.object({ kind: z3.literal("chat"), conversationId: uuid }).strict(),
1294
+ z3.object({ kind: z3.literal("issue"), issueId: uuid }).strict()
1295
+ ]);
1296
+ keepMessengerSavedViewSchema = z3.object({
1297
+ target: messengerSavedViewTargetSchema,
1298
+ ...savedViewMetadataShape,
1299
+ clientMutationId: uuid,
1300
+ placement: z3.discriminatedUnion("kind", [
1301
+ z3.object({ kind: z3.literal("anchor"), anchor: messengerSavedViewAnchorSchema }).strict(),
1302
+ z3.object({ kind: z3.literal("group"), groupId: uuid }).strict()
1303
+ ])
1304
+ }).strict();
1186
1305
  updateMessengerSavedViewSchema = z3.object({
1187
1306
  target: messengerSavedViewTargetSchema.optional(),
1188
1307
  title: savedViewMetadataShape.title.optional(),
1189
1308
  subtitle: savedViewMetadataShape.subtitle,
1190
1309
  favicon: savedViewMetadataShape.favicon,
1191
- hidden: z3.boolean().optional()
1310
+ // Compatibility-only escape hatch for legacy hidden rows. The current
1311
+ // group-only Saved View model has no operation that creates hidden rows.
1312
+ hidden: z3.literal(false).optional()
1192
1313
  }).strict().refine((value) => Object.keys(value).length > 0, "At least one field is required");
1193
1314
  reorderMessengerSavedViewsSchema = z3.object({
1194
1315
  ids: z3.array(uuid).max(500)
@@ -7641,6 +7762,15 @@ var RUDDER_MCP_TOOL_DESCRIPTORS = [
7641
7762
  "requiresAgentId": true,
7642
7763
  "attachesRunIdWhenAvailable": false
7643
7764
  },
7765
+ {
7766
+ "capabilityId": "browser.user-tabs",
7767
+ "name": "rudder_browser_user_tabs",
7768
+ "description": "List user-visible tabs currently open in Rudder's built-in Browser without taking control of them.",
7769
+ "mutating": false,
7770
+ "requiresOrgId": true,
7771
+ "requiresAgentId": true,
7772
+ "attachesRunIdWhenAvailable": false
7773
+ },
7644
7774
  {
7645
7775
  "capabilityId": "browser.open",
7646
7776
  "name": "rudder_browser_open",
@@ -7659,6 +7789,150 @@ var RUDDER_MCP_TOOL_DESCRIPTORS = [
7659
7789
  "requiresAgentId": true,
7660
7790
  "attachesRunIdWhenAvailable": true
7661
7791
  },
7792
+ {
7793
+ "capabilityId": "browser.back",
7794
+ "name": "rudder_browser_back",
7795
+ "description": "Navigate a run-owned Rudder Browser tab back in history.",
7796
+ "mutating": true,
7797
+ "requiresOrgId": true,
7798
+ "requiresAgentId": true,
7799
+ "attachesRunIdWhenAvailable": true
7800
+ },
7801
+ {
7802
+ "capabilityId": "browser.forward",
7803
+ "name": "rudder_browser_forward",
7804
+ "description": "Navigate a run-owned Rudder Browser tab forward in history.",
7805
+ "mutating": true,
7806
+ "requiresOrgId": true,
7807
+ "requiresAgentId": true,
7808
+ "attachesRunIdWhenAvailable": true
7809
+ },
7810
+ {
7811
+ "capabilityId": "browser.reload",
7812
+ "name": "rudder_browser_reload",
7813
+ "description": "Reload a run-owned Rudder Browser tab.",
7814
+ "mutating": true,
7815
+ "requiresOrgId": true,
7816
+ "requiresAgentId": true,
7817
+ "attachesRunIdWhenAvailable": true
7818
+ },
7819
+ {
7820
+ "capabilityId": "browser.viewport",
7821
+ "name": "rudder_browser_viewport",
7822
+ "description": "Inspect, set, or reset the responsive viewport for the current Rudder Browser run.",
7823
+ "mutating": true,
7824
+ "requiresOrgId": true,
7825
+ "requiresAgentId": true,
7826
+ "attachesRunIdWhenAvailable": true
7827
+ },
7828
+ {
7829
+ "capabilityId": "browser.visibility",
7830
+ "name": "rudder_browser_visibility",
7831
+ "description": "Inspect or change whether the current run's selected Rudder Browser tab is visible.",
7832
+ "mutating": true,
7833
+ "requiresOrgId": true,
7834
+ "requiresAgentId": true,
7835
+ "attachesRunIdWhenAvailable": true
7836
+ },
7837
+ {
7838
+ "capabilityId": "browser.snapshot",
7839
+ "name": "rudder_browser_snapshot",
7840
+ "description": "Capture a bounded DOM and accessibility-oriented snapshot, including frame structure and ephemeral node ids.",
7841
+ "mutating": false,
7842
+ "requiresOrgId": true,
7843
+ "requiresAgentId": true,
7844
+ "attachesRunIdWhenAvailable": true
7845
+ },
7846
+ {
7847
+ "capabilityId": "browser.locator",
7848
+ "name": "rudder_browser_locator",
7849
+ "description": "Perform read-only bounded Browser locator text, attribute, state, count, or wait operations.",
7850
+ "mutating": false,
7851
+ "requiresOrgId": true,
7852
+ "requiresAgentId": true,
7853
+ "attachesRunIdWhenAvailable": true
7854
+ },
7855
+ {
7856
+ "capabilityId": "browser.cua",
7857
+ "name": "rudder_browser_cua",
7858
+ "description": "Perform trusted coordinate mouse, scroll, drag, keyboard, and text input in a run-owned Browser tab.",
7859
+ "mutating": true,
7860
+ "requiresOrgId": true,
7861
+ "requiresAgentId": true,
7862
+ "attachesRunIdWhenAvailable": true
7863
+ },
7864
+ {
7865
+ "capabilityId": "browser.dom-cua",
7866
+ "name": "rudder_browser_dom_cua",
7867
+ "description": "Inspect a bounded read-only DOM snapshot with ephemeral node ids.",
7868
+ "mutating": false,
7869
+ "requiresOrgId": true,
7870
+ "requiresAgentId": true,
7871
+ "attachesRunIdWhenAvailable": true
7872
+ },
7873
+ {
7874
+ "capabilityId": "browser.dialog",
7875
+ "name": "rudder_browser_dialog",
7876
+ "description": "Inspect, accept, or dismiss the active JavaScript dialog in a run-owned Browser tab.",
7877
+ "mutating": true,
7878
+ "requiresOrgId": true,
7879
+ "requiresAgentId": true,
7880
+ "attachesRunIdWhenAvailable": true
7881
+ },
7882
+ {
7883
+ "capabilityId": "browser.clipboard",
7884
+ "name": "rudder_browser_clipboard",
7885
+ "description": "Read or write the isolated virtual clipboard for the current Browser run without touching the OS clipboard.",
7886
+ "mutating": true,
7887
+ "requiresOrgId": true,
7888
+ "requiresAgentId": true,
7889
+ "attachesRunIdWhenAvailable": true
7890
+ },
7891
+ {
7892
+ "capabilityId": "browser.logs",
7893
+ "name": "rudder_browser_logs",
7894
+ "description": "Read bounded console and runtime logs captured for a run-owned Browser tab.",
7895
+ "mutating": true,
7896
+ "requiresOrgId": true,
7897
+ "requiresAgentId": true,
7898
+ "attachesRunIdWhenAvailable": true
7899
+ },
7900
+ {
7901
+ "capabilityId": "browser.download",
7902
+ "name": "rudder_browser_download",
7903
+ "description": "Download explicit locator media without dispatching page input into a bounded run-owned artifact.",
7904
+ "mutating": true,
7905
+ "requiresOrgId": true,
7906
+ "requiresAgentId": true,
7907
+ "attachesRunIdWhenAvailable": true
7908
+ },
7909
+ {
7910
+ "capabilityId": "browser.assets",
7911
+ "name": "rudder_browser_assets",
7912
+ "description": "List page assets or bundle an explicit bounded selection into a run-owned temporary artifact.",
7913
+ "mutating": true,
7914
+ "requiresOrgId": true,
7915
+ "requiresAgentId": true,
7916
+ "attachesRunIdWhenAvailable": true
7917
+ },
7918
+ {
7919
+ "capabilityId": "browser.content",
7920
+ "name": "rudder_browser_content",
7921
+ "description": "Export current page content or an eligible Google Workspace document into a bounded run-owned artifact.",
7922
+ "mutating": true,
7923
+ "requiresOrgId": true,
7924
+ "requiresAgentId": true,
7925
+ "attachesRunIdWhenAvailable": true
7926
+ },
7927
+ {
7928
+ "capabilityId": "browser.wait",
7929
+ "name": "rudder_browser_wait",
7930
+ "description": "Wait for bounded URL, text, disappearance, or time conditions in a run-owned Browser tab.",
7931
+ "mutating": false,
7932
+ "requiresOrgId": true,
7933
+ "requiresAgentId": true,
7934
+ "attachesRunIdWhenAvailable": true
7935
+ },
7662
7936
  {
7663
7937
  "capabilityId": "browser.read",
7664
7938
  "name": "rudder_browser_read",
@@ -7999,7 +8273,188 @@ function mcpNumber(description) {
7999
8273
  function mcpStringArray(description) {
8000
8274
  return { type: "array", items: { type: "string" }, description };
8001
8275
  }
8276
+ function browserMcpInputSchema(id) {
8277
+ const string = (description, extra = {}) => ({ type: "string", description, ...extra });
8278
+ const number = (description, extra = {}) => ({ type: "number", description, ...extra });
8279
+ const boolean = (description) => ({ type: "boolean", description });
8280
+ const schema = (properties, required = []) => ({
8281
+ type: "object",
8282
+ additionalProperties: false,
8283
+ properties,
8284
+ ...required.length > 0 ? { required } : {}
8285
+ });
8286
+ const locatorAtom = schema({
8287
+ strategy: string("Locator strategy.", { enum: ["css", "testId", "href", "role", "label", "placeholder", "text"] }),
8288
+ value: string("Selector, role, label, placeholder, href, test id, or text value.", { minLength: 1, maxLength: 2e3 }),
8289
+ name: string("Accessible name used with the role strategy.", { maxLength: 2e3 }),
8290
+ exact: boolean("Require an exact text or attribute match.")
8291
+ }, ["strategy", "value"]);
8292
+ const simpleLocator = schema({
8293
+ ...locatorAtom.properties,
8294
+ filter: schema({
8295
+ hasText: string("Required descendant text.", { maxLength: 2e3 }),
8296
+ hasNotText: string("Excluded descendant text.", { maxLength: 2e3 }),
8297
+ visible: boolean("Filter by current visibility."),
8298
+ has: locatorAtom,
8299
+ hasNot: locatorAtom
8300
+ }),
8301
+ and: locatorAtom,
8302
+ or: locatorAtom,
8303
+ index: number("Zero-based locator match index.", { minimum: 0, maximum: 499 }),
8304
+ position: string("Locator endpoint after an explicit count.", { enum: ["first", "last"] })
8305
+ }, ["strategy", "value"]);
8306
+ const locator = schema({
8307
+ ...simpleLocator.properties,
8308
+ frame: { type: "array", maxItems: 8, items: string("CSS iframe selector.", { minLength: 1, maxLength: 1e3 }) },
8309
+ scope: simpleLocator
8310
+ }, ["strategy", "value"]);
8311
+ const baseTab = { tabId: string("Run-owned Rudder Browser tab id.", { minLength: 1, maxLength: 160 }) };
8312
+ switch (id) {
8313
+ case "browser.tabs":
8314
+ case "browser.user-tabs":
8315
+ return schema({});
8316
+ case "browser.open":
8317
+ return schema({ url: string("HTTP or HTTPS URL.", { minLength: 1, maxLength: 8192 }) }, ["url"]);
8318
+ case "browser.navigate":
8319
+ return schema({ ...baseTab, url: string("HTTP or HTTPS URL.", { minLength: 1, maxLength: 8192 }) }, ["tabId", "url"]);
8320
+ case "browser.back":
8321
+ case "browser.forward":
8322
+ case "browser.reload":
8323
+ case "browser.read":
8324
+ case "browser.close":
8325
+ return schema(baseTab, ["tabId"]);
8326
+ case "browser.viewport":
8327
+ return schema({
8328
+ action: string("Viewport action.", { enum: ["get", "set", "reset"] }),
8329
+ width: number("Viewport width in CSS pixels.", { minimum: 320, maximum: 3840 }),
8330
+ height: number("Viewport height in CSS pixels.", { minimum: 240, maximum: 2160 })
8331
+ }, ["action"]);
8332
+ case "browser.visibility":
8333
+ return schema({ visible: boolean("Whether the selected Agent Browser tab is visible.") });
8334
+ case "browser.snapshot":
8335
+ return schema({
8336
+ ...baseTab,
8337
+ boxes: boolean("Include viewport-relative element boxes."),
8338
+ depth: number("Maximum snapshot tree depth.", { minimum: 1, maximum: 30 }),
8339
+ maxNodes: number("Maximum snapshot nodes.", { minimum: 1, maximum: 3e3 })
8340
+ }, ["tabId"]);
8341
+ case "browser.locator":
8342
+ return schema({
8343
+ ...baseTab,
8344
+ action: string("Read-only locator action.", { enum: ["count", "allTextContents", "textContent", "innerText", "attribute", "visible", "enabled", "checked", "selected", "wait"] }),
8345
+ locator,
8346
+ name: string("Attribute name for attribute reads.", { maxLength: 200 }),
8347
+ state: string("Wait state.", { enum: ["attached", "detached", "visible", "hidden"] }),
8348
+ timeoutMs: number("Wait timeout in milliseconds.", { minimum: 0, maximum: 3e4 })
8349
+ }, ["tabId", "action", "locator"]);
8350
+ case "browser.cua":
8351
+ return schema({
8352
+ ...baseTab,
8353
+ action: string("Coordinate input or inspection action.", { enum: ["click", "doubleClick", "move", "scroll", "drag", "keypress", "type", "elementInfo"] }),
8354
+ x: number("Viewport X coordinate."),
8355
+ y: number("Viewport Y coordinate."),
8356
+ scrollX: number("Horizontal scroll delta."),
8357
+ scrollY: number("Vertical scroll delta."),
8358
+ button: { oneOf: [number("Mouse button number.", { minimum: 1, maximum: 5 }), string("Mouse button.", { enum: ["left", "middle", "right"] })] },
8359
+ keys: { type: "array", maxItems: 10, items: string("Keyboard key or modifier.", { minLength: 1, maxLength: 100 }) },
8360
+ text: string("Text to type.", { maxLength: 1e5 }),
8361
+ path: { type: "array", minItems: 2, maxItems: 200, items: schema({ x: number("Path X coordinate."), y: number("Path Y coordinate.") }, ["x", "y"]) }
8362
+ }, ["tabId", "action"]);
8363
+ case "browser.dom-cua":
8364
+ return schema({
8365
+ ...baseTab,
8366
+ action: string("Read-only DOM snapshot action.", { enum: ["get"] }),
8367
+ depth: number("Maximum DOM depth.", { minimum: 1, maximum: 30 }),
8368
+ maxNodes: number("Maximum DOM nodes.", { minimum: 1, maximum: 3e3 })
8369
+ }, ["tabId", "action"]);
8370
+ case "browser.dialog":
8371
+ return schema({
8372
+ ...baseTab,
8373
+ action: string("Dialog action.", { enum: ["get", "accept", "dismiss"] }),
8374
+ promptText: string("Prompt response text.", { maxLength: 1e4 })
8375
+ }, ["tabId", "action"]);
8376
+ case "browser.clipboard":
8377
+ return schema({
8378
+ action: string("Virtual clipboard action.", { enum: ["read", "readText", "write", "writeText", "clear"] }),
8379
+ text: string("Plain clipboard text.", { maxLength: 5e5 }),
8380
+ items: {
8381
+ type: "array",
8382
+ maxItems: 20,
8383
+ items: schema({
8384
+ presentationStyle: string("Clipboard presentation style.", { enum: ["unspecified", "inline", "attachment"] }),
8385
+ entries: {
8386
+ type: "array",
8387
+ maxItems: 20,
8388
+ items: schema({
8389
+ mimeType: string("Clipboard MIME type.", { minLength: 1, maxLength: 200 }),
8390
+ text: string("Text clipboard payload.", { maxLength: 5e5 }),
8391
+ base64: string("Base64 clipboard payload.", { maxLength: 65e4 })
8392
+ }, ["mimeType"])
8393
+ }
8394
+ }, ["entries"])
8395
+ }
8396
+ }, ["action"]);
8397
+ case "browser.logs":
8398
+ return schema({
8399
+ ...baseTab,
8400
+ levels: { type: "array", maxItems: 5, items: string("Log level.", { enum: ["debug", "info", "log", "warn", "error"] }) },
8401
+ filter: string("Case-insensitive log substring filter.", { maxLength: 2e3 }),
8402
+ limit: number("Maximum log entries.", { minimum: 1, maximum: 500 }),
8403
+ clear: boolean("Clear the tab log buffer after reading.")
8404
+ }, ["tabId"]);
8405
+ case "browser.download":
8406
+ return schema({
8407
+ ...baseTab,
8408
+ mode: string("Read-only media download mode.", { enum: ["media"] }),
8409
+ locator
8410
+ }, ["tabId", "mode", "locator"]);
8411
+ case "browser.assets":
8412
+ return schema({
8413
+ ...baseTab,
8414
+ action: string("Asset action.", { enum: ["list", "bundle"] }),
8415
+ inventoryId: string("Prior asset inventory id.", { maxLength: 160 }),
8416
+ assetIds: { type: "array", minItems: 1, maxItems: 100, items: string("Asset id.", { maxLength: 160 }) },
8417
+ kinds: { type: "array", minItems: 1, maxItems: 4, items: string("Asset kind.", { enum: ["font", "image", "stylesheet", "video"] }) }
8418
+ }, ["tabId", "action"]);
8419
+ case "browser.content":
8420
+ return schema({
8421
+ ...baseTab,
8422
+ format: string("Content export format.", { enum: ["text", "pdf", "md", "docx", "xlsx", "csv", "pptx"] })
8423
+ }, ["tabId", "format"]);
8424
+ case "browser.wait":
8425
+ return schema({
8426
+ ...baseTab,
8427
+ url: string("URL substring.", { maxLength: 8192 }),
8428
+ text: string("Text that must appear.", { maxLength: 1e4 }),
8429
+ textGone: string("Text that must disappear.", { maxLength: 1e4 }),
8430
+ timeMs: number("Fixed bounded delay in milliseconds.", { minimum: 0, maximum: 3e4 }),
8431
+ timeoutMs: number("Wait timeout in milliseconds.", { minimum: 0, maximum: 3e4 })
8432
+ }, ["tabId"]);
8433
+ case "browser.click":
8434
+ return schema({ ...baseTab, ref: string("Element reference returned by rudder_browser_read.", { maxLength: 160 }) }, ["tabId", "ref"]);
8435
+ case "browser.type":
8436
+ return schema({
8437
+ ...baseTab,
8438
+ ref: string("Element reference returned by rudder_browser_read.", { maxLength: 160 }),
8439
+ text: string("Text to enter.", { maxLength: 1e5 }),
8440
+ submit: boolean("Submit the owning form after typing.")
8441
+ }, ["tabId", "ref", "text"]);
8442
+ case "browser.screenshot":
8443
+ return schema({
8444
+ ...baseTab,
8445
+ fullPage: boolean("Capture the full scrollable page."),
8446
+ format: string("Image format.", { enum: ["png", "jpeg"] }),
8447
+ quality: number("JPEG quality.", { minimum: 1, maximum: 100 }),
8448
+ clip: schema({ x: number("Clip X coordinate."), y: number("Clip Y coordinate."), width: number("Clip width.", { minimum: 1 }), height: number("Clip height.", { minimum: 1 }) }, ["x", "y", "width", "height"]),
8449
+ locator
8450
+ }, ["tabId"]);
8451
+ default:
8452
+ return schema({});
8453
+ }
8454
+ }
8002
8455
  function rudderMcpInputSchemaForCapability(id) {
8456
+ if (id.startsWith("browser."))
8457
+ return browserMcpInputSchema(id);
8003
8458
  const properties = {};
8004
8459
  const add = (key, value) => {
8005
8460
  properties[key] = value;
@@ -8244,6 +8699,7 @@ var RUDDER_BROWSER_MCP_TOOL_NAMES = RUDDER_BROWSER_MCP_TOOL_CONTRACTS.map((tool)
8244
8699
 
8245
8700
  // ../packages/agent-runtime-utils/dist/rudder-mcp.js
8246
8701
  var RUDDER_MCP_SERVER_NAME = "rudder-tools";
8702
+ var RUDDER_BROWSER_MCP_SERVER_NAME = "rudder-browser";
8247
8703
  var RUDDER_MCP_LEGACY_SERVER_NAMES = [
8248
8704
  ["rudder", "control", "plane"].join("-"),
8249
8705
  ["rudder", "operating", "layer"].join("-")
@@ -8280,7 +8736,7 @@ import os from "node:os";
8280
8736
  import path2 from "node:path";
8281
8737
  import { fileURLToPath as fileURLToPath2 } from "node:url";
8282
8738
 
8283
- // src/agent-v1-registry.ts
8739
+ // src/agent-v1-capabilities.ts
8284
8740
  var AGENT_CLI_CAPABILITIES = [
8285
8741
  {
8286
8742
  id: "agent.me",
@@ -8894,6 +9350,18 @@ var AGENT_CLI_CAPABILITIES = [
8894
9350
  requiresRunId: true,
8895
9351
  attachesRunIdWhenAvailable: false
8896
9352
  },
9353
+ {
9354
+ id: "browser.user-tabs",
9355
+ command: "rudder browser user-tabs",
9356
+ category: "browser",
9357
+ description: "List user-visible tabs currently open in Rudder's built-in Browser without taking control of them.",
9358
+ mutating: false,
9359
+ contract: "agent-v1",
9360
+ requiresOrgId: true,
9361
+ requiresAgentId: true,
9362
+ requiresRunId: true,
9363
+ attachesRunIdWhenAvailable: false
9364
+ },
8897
9365
  {
8898
9366
  id: "browser.open",
8899
9367
  command: "rudder browser open <url>",
@@ -8918,6 +9386,198 @@ var AGENT_CLI_CAPABILITIES = [
8918
9386
  requiresRunId: true,
8919
9387
  attachesRunIdWhenAvailable: true
8920
9388
  },
9389
+ {
9390
+ id: "browser.back",
9391
+ command: "rudder browser back <tab-id>",
9392
+ category: "browser",
9393
+ description: "Navigate a run-owned Rudder Browser tab back in history.",
9394
+ mutating: true,
9395
+ contract: "agent-v1",
9396
+ requiresOrgId: true,
9397
+ requiresAgentId: true,
9398
+ requiresRunId: true,
9399
+ attachesRunIdWhenAvailable: true
9400
+ },
9401
+ {
9402
+ id: "browser.forward",
9403
+ command: "rudder browser forward <tab-id>",
9404
+ category: "browser",
9405
+ description: "Navigate a run-owned Rudder Browser tab forward in history.",
9406
+ mutating: true,
9407
+ contract: "agent-v1",
9408
+ requiresOrgId: true,
9409
+ requiresAgentId: true,
9410
+ requiresRunId: true,
9411
+ attachesRunIdWhenAvailable: true
9412
+ },
9413
+ {
9414
+ id: "browser.reload",
9415
+ command: "rudder browser reload <tab-id>",
9416
+ category: "browser",
9417
+ description: "Reload a run-owned Rudder Browser tab.",
9418
+ mutating: true,
9419
+ contract: "agent-v1",
9420
+ requiresOrgId: true,
9421
+ requiresAgentId: true,
9422
+ requiresRunId: true,
9423
+ attachesRunIdWhenAvailable: true
9424
+ },
9425
+ {
9426
+ id: "browser.viewport",
9427
+ command: "rudder browser viewport --action <get|set|reset> [--width <px> --height <px>]",
9428
+ category: "browser",
9429
+ description: "Inspect, set, or reset the responsive viewport for the current Rudder Browser run.",
9430
+ mutating: true,
9431
+ contract: "agent-v1",
9432
+ requiresOrgId: true,
9433
+ requiresAgentId: true,
9434
+ requiresRunId: true,
9435
+ attachesRunIdWhenAvailable: true
9436
+ },
9437
+ {
9438
+ id: "browser.visibility",
9439
+ command: "rudder browser visibility [--visible <true|false>]",
9440
+ category: "browser",
9441
+ description: "Inspect or change whether the current run's selected Rudder Browser tab is visible.",
9442
+ mutating: true,
9443
+ contract: "agent-v1",
9444
+ requiresOrgId: true,
9445
+ requiresAgentId: true,
9446
+ requiresRunId: true,
9447
+ attachesRunIdWhenAvailable: true
9448
+ },
9449
+ {
9450
+ id: "browser.snapshot",
9451
+ command: "rudder browser snapshot <tab-id> [--input <json>]",
9452
+ category: "browser",
9453
+ description: "Capture a bounded DOM and accessibility-oriented snapshot, including frame structure and ephemeral node ids.",
9454
+ mutating: false,
9455
+ contract: "agent-v1",
9456
+ requiresOrgId: true,
9457
+ requiresAgentId: true,
9458
+ requiresRunId: true,
9459
+ attachesRunIdWhenAvailable: true
9460
+ },
9461
+ {
9462
+ id: "browser.locator",
9463
+ command: "rudder browser locator <tab-id> --input <json>",
9464
+ category: "browser",
9465
+ description: "Perform read-only bounded Browser locator text, attribute, state, count, or wait operations.",
9466
+ mutating: false,
9467
+ contract: "agent-v1",
9468
+ requiresOrgId: true,
9469
+ requiresAgentId: true,
9470
+ requiresRunId: true,
9471
+ attachesRunIdWhenAvailable: true
9472
+ },
9473
+ {
9474
+ id: "browser.cua",
9475
+ command: "rudder browser cua <tab-id> --input <json>",
9476
+ category: "browser",
9477
+ description: "Perform trusted coordinate mouse, scroll, drag, keyboard, and text input in a run-owned Browser tab.",
9478
+ mutating: true,
9479
+ contract: "agent-v1",
9480
+ requiresOrgId: true,
9481
+ requiresAgentId: true,
9482
+ requiresRunId: true,
9483
+ attachesRunIdWhenAvailable: true
9484
+ },
9485
+ {
9486
+ id: "browser.dom-cua",
9487
+ command: "rudder browser dom-cua <tab-id> --input <json>",
9488
+ category: "browser",
9489
+ description: "Inspect a bounded read-only DOM snapshot with ephemeral node ids.",
9490
+ mutating: false,
9491
+ contract: "agent-v1",
9492
+ requiresOrgId: true,
9493
+ requiresAgentId: true,
9494
+ requiresRunId: true,
9495
+ attachesRunIdWhenAvailable: true
9496
+ },
9497
+ {
9498
+ id: "browser.dialog",
9499
+ command: "rudder browser dialog <tab-id> --input <json>",
9500
+ category: "browser",
9501
+ description: "Inspect, accept, or dismiss the active JavaScript dialog in a run-owned Browser tab.",
9502
+ mutating: true,
9503
+ contract: "agent-v1",
9504
+ requiresOrgId: true,
9505
+ requiresAgentId: true,
9506
+ requiresRunId: true,
9507
+ attachesRunIdWhenAvailable: true
9508
+ },
9509
+ {
9510
+ id: "browser.clipboard",
9511
+ command: "rudder browser clipboard --input <json>",
9512
+ category: "browser",
9513
+ description: "Read or write the isolated virtual clipboard for the current Browser run without touching the OS clipboard.",
9514
+ mutating: true,
9515
+ contract: "agent-v1",
9516
+ requiresOrgId: true,
9517
+ requiresAgentId: true,
9518
+ requiresRunId: true,
9519
+ attachesRunIdWhenAvailable: true
9520
+ },
9521
+ {
9522
+ id: "browser.logs",
9523
+ command: "rudder browser logs <tab-id> [--input <json>]",
9524
+ category: "browser",
9525
+ description: "Read bounded console and runtime logs captured for a run-owned Browser tab.",
9526
+ mutating: true,
9527
+ contract: "agent-v1",
9528
+ requiresOrgId: true,
9529
+ requiresAgentId: true,
9530
+ requiresRunId: true,
9531
+ attachesRunIdWhenAvailable: true
9532
+ },
9533
+ {
9534
+ id: "browser.download",
9535
+ command: "rudder browser download <tab-id> --input <json>",
9536
+ category: "browser",
9537
+ description: "Download explicit locator media without dispatching page input into a bounded run-owned artifact.",
9538
+ mutating: true,
9539
+ contract: "agent-v1",
9540
+ requiresOrgId: true,
9541
+ requiresAgentId: true,
9542
+ requiresRunId: true,
9543
+ attachesRunIdWhenAvailable: true
9544
+ },
9545
+ {
9546
+ id: "browser.assets",
9547
+ command: "rudder browser assets <tab-id> --input <json>",
9548
+ category: "browser",
9549
+ description: "List page assets or bundle an explicit bounded selection into a run-owned temporary artifact.",
9550
+ mutating: true,
9551
+ contract: "agent-v1",
9552
+ requiresOrgId: true,
9553
+ requiresAgentId: true,
9554
+ requiresRunId: true,
9555
+ attachesRunIdWhenAvailable: true
9556
+ },
9557
+ {
9558
+ id: "browser.content",
9559
+ command: "rudder browser content <tab-id> --input <json>",
9560
+ category: "browser",
9561
+ description: "Export current page content or an eligible Google Workspace document into a bounded run-owned artifact.",
9562
+ mutating: true,
9563
+ contract: "agent-v1",
9564
+ requiresOrgId: true,
9565
+ requiresAgentId: true,
9566
+ requiresRunId: true,
9567
+ attachesRunIdWhenAvailable: true
9568
+ },
9569
+ {
9570
+ id: "browser.wait",
9571
+ command: "rudder browser wait <tab-id> --input <json>",
9572
+ category: "browser",
9573
+ description: "Wait for bounded URL, text, disappearance, or time conditions in a run-owned Browser tab.",
9574
+ mutating: false,
9575
+ contract: "agent-v1",
9576
+ requiresOrgId: true,
9577
+ requiresAgentId: true,
9578
+ requiresRunId: true,
9579
+ attachesRunIdWhenAvailable: true
9580
+ },
8921
9581
  {
8922
9582
  id: "browser.read",
8923
9583
  command: "rudder browser read <tab-id>",
@@ -8956,7 +9616,7 @@ var AGENT_CLI_CAPABILITIES = [
8956
9616
  },
8957
9617
  {
8958
9618
  id: "browser.screenshot",
8959
- command: "rudder browser screenshot <tab-id>",
9619
+ command: "rudder browser screenshot <tab-id> [--input <json>]",
8960
9620
  category: "browser",
8961
9621
  description: "Capture a screenshot of a run-owned Rudder Browser tab.",
8962
9622
  mutating: false,
@@ -9351,6 +10011,8 @@ var AGENT_CLI_CAPABILITIES = [
9351
10011
  attachesRunIdWhenAvailable: true
9352
10012
  }
9353
10013
  ];
10014
+
10015
+ // src/agent-v1-registry.ts
9354
10016
  var CATEGORY_TITLES = {
9355
10017
  agent: "Agent",
9356
10018
  issue: "Issue",
@@ -9392,14 +10054,19 @@ function buildAgentCliCapabilitiesManifest(contract = "agent-v1") {
9392
10054
  };
9393
10055
  }
9394
10056
  function buildAgentV1McpToolsManifest(contract = "agent-v1", options = {}) {
9395
- const capabilities = buildAgentCliCapabilitiesManifest(contract).capabilities.filter((entry) => options.browserEnabled !== false || entry.category !== "browser");
10057
+ const surface = options.surface ?? "core";
10058
+ const capabilities = buildAgentCliCapabilitiesManifest(contract).capabilities.filter((entry) => {
10059
+ if (surface === "all") return true;
10060
+ if (surface === "browser") return entry.category === "browser";
10061
+ return entry.category !== "browser";
10062
+ });
9396
10063
  const semanticContractByCapability = new Map(
9397
10064
  RUDDER_MCP_CANONICAL_TOOL_DEFINITIONS.map((tool) => [tool.capabilityId, tool])
9398
10065
  );
9399
10066
  return {
9400
10067
  schema: "rudder.agent-mcp-tools/v1",
9401
10068
  contract,
9402
- serverName: "rudder-tools",
10069
+ serverName: surface === "browser" ? "rudder-browser" : "rudder-tools",
9403
10070
  tools: capabilities.map((entry) => {
9404
10071
  const semanticContract = semanticContractByCapability.get(entry.id);
9405
10072
  if (!semanticContract) {
@@ -9457,12 +10124,14 @@ var RudderApiClient = class {
9457
10124
  apiKey;
9458
10125
  agentId;
9459
10126
  runId;
10127
+ signal;
9460
10128
  recoverAuth;
9461
10129
  constructor(opts) {
9462
10130
  this.apiBase = opts.apiBase.replace(/\/+$/, "");
9463
10131
  this.apiKey = opts.apiKey?.trim() || void 0;
9464
10132
  this.agentId = opts.agentId?.trim() || void 0;
9465
10133
  this.runId = opts.runId?.trim() || void 0;
10134
+ this.signal = opts.signal;
9466
10135
  this.recoverAuth = opts.recoverAuth;
9467
10136
  }
9468
10137
  get(path24, opts) {
@@ -9520,7 +10189,8 @@ var RudderApiClient = class {
9520
10189
  }
9521
10190
  const response = await fetch(url, {
9522
10191
  ...init,
9523
- headers
10192
+ headers,
10193
+ signal: init.signal ?? this.signal
9524
10194
  });
9525
10195
  if (opts?.ignoreNotFound && response.status === 404) {
9526
10196
  return null;
@@ -9602,7 +10272,9 @@ function toStringRecord(headers) {
9602
10272
  // src/agent-v1-mcp-server.ts
9603
10273
  init_version();
9604
10274
  var RUDDER_MCP_MAX_TOOL_RESULT_BYTES = 1e6;
10275
+ var RUDDER_BROWSER_MCP_MAX_TOOL_RESULT_BYTES = 16e6;
9605
10276
  var RUDDER_MCP_MAX_INLINE_TEXT_BYTES = 32e3;
10277
+ var RUDDER_BROWSER_LIVENESS_INTERVAL_MS = 1e3;
9606
10278
  var RESERVED_MODEL_ARGUMENTS = /* @__PURE__ */ new Set([
9607
10279
  "orgId",
9608
10280
  "org_id",
@@ -9650,6 +10322,7 @@ function buildAgentV1ToolCallPlan(toolName, rawArgs, env = buildMcpServerEnv())
9650
10322
  const capability = getAgentCliCapabilityById(capabilityId);
9651
10323
  rejectModelProvidedRuntimeIdentity(input);
9652
10324
  rejectUnsupportedToolArguments(toolName, input);
10325
+ rejectUnsupportedBrowserLocatorAction(toolName, input);
9653
10326
  assertBrowserCapabilityEnabled(capabilityId, env);
9654
10327
  assertRuntimeMcpContext(capability, env);
9655
10328
  const tempFiles = [];
@@ -9671,7 +10344,7 @@ function buildAgentV1ToolCallPlan(toolName, rawArgs, env = buildMcpServerEnv())
9671
10344
  tempFiles
9672
10345
  };
9673
10346
  }
9674
- async function runAgentV1McpJsonRpcMessage(message, env = buildMcpServerEnv()) {
10347
+ async function runAgentV1McpJsonRpcMessage(message, env = buildMcpServerEnv(), surface = "core", options = {}) {
9675
10348
  const isNotification = message.id === void 0;
9676
10349
  const id = message.id ?? null;
9677
10350
  try {
@@ -9679,13 +10352,10 @@ async function runAgentV1McpJsonRpcMessage(message, env = buildMcpServerEnv()) {
9679
10352
  case "notifications/initialized":
9680
10353
  return isNotification ? null : rpcResult(id, {});
9681
10354
  case "initialize":
9682
- const contractManifest = buildAgentV1McpToolsManifest("agent-v1").tools.map(rudderMcpSemanticToolContract);
9683
- const coreContractHash = fingerprintRudderMcpToolManifest(
9684
- contractManifest.filter((tool) => !tool.name.startsWith("rudder_browser_"))
9685
- );
9686
- const browserContractHash = fingerprintRudderMcpToolManifest(
9687
- contractManifest.filter((tool) => tool.name.startsWith("rudder_browser_"))
9688
- );
10355
+ const coreContractManifest = buildAgentV1McpToolsManifest("agent-v1").tools.map(rudderMcpSemanticToolContract);
10356
+ const browserContractManifest = buildAgentV1McpToolsManifest("agent-v1", { surface: "browser" }).tools.map(rudderMcpSemanticToolContract);
10357
+ const coreContractHash = fingerprintRudderMcpToolManifest(coreContractManifest);
10358
+ const browserContractHash = fingerprintRudderMcpToolManifest(browserContractManifest);
9689
10359
  return rpcResult(id, {
9690
10360
  protocolVersion: requestedProtocolVersion(message.params) ?? "2024-11-05",
9691
10361
  capabilities: {
@@ -9698,16 +10368,21 @@ async function runAgentV1McpJsonRpcMessage(message, env = buildMcpServerEnv()) {
9698
10368
  }
9699
10369
  }
9700
10370
  },
9701
- serverInfo: { name: RUDDER_MCP_SERVER_NAME, version: resolveCliVersion() }
10371
+ serverInfo: {
10372
+ name: surface === "browser" ? RUDDER_BROWSER_MCP_SERVER_NAME : RUDDER_MCP_SERVER_NAME,
10373
+ version: resolveCliVersion()
10374
+ }
9702
10375
  });
9703
10376
  case "tools/list":
9704
10377
  return rpcResult(id, {
9705
- tools: buildAgentV1McpToolsManifest("agent-v1", {
9706
- browserEnabled: browserCapabilityEnabled(env)
9707
- }).tools.map(toMcpToolListEntry)
10378
+ tools: surface === "browser" && !browserCapabilityEnabled(env) ? [] : buildAgentV1McpToolsManifest("agent-v1", { surface }).tools.map(toMcpToolListEntry)
9708
10379
  });
9709
10380
  case "tools/call":
9710
- return boundedToolCallRpcResponse(id, await callToolSafely(message.params, env));
10381
+ return boundedToolCallRpcResponse(
10382
+ id,
10383
+ await callToolSafely(message.params, env, surface, options.signal),
10384
+ surface
10385
+ );
9711
10386
  default:
9712
10387
  if (isNotification) return null;
9713
10388
  return rpcError(id, -32601, `Unsupported JSON-RPC method: ${String(message.method ?? "")}`);
@@ -9717,26 +10392,84 @@ async function runAgentV1McpJsonRpcMessage(message, env = buildMcpServerEnv()) {
9717
10392
  return rpcError(id, -32e3, errorMessage(err), errorDetails(err));
9718
10393
  }
9719
10394
  }
9720
- async function runMcpStdioServer(env = buildMcpServerEnv()) {
10395
+ async function runMcpStdioServer(env = buildMcpServerEnv(), surface = "core", options = {}) {
10396
+ const stdin = options.input ?? process.stdin;
10397
+ const output = options.output ?? process.stdout;
10398
+ let revoked = false;
10399
+ let activeRequest = null;
10400
+ const revoke = () => {
10401
+ revoked = true;
10402
+ activeRequest?.abort();
10403
+ stdin.destroy();
10404
+ };
10405
+ const stopLivenessMonitor = surface === "browser" ? (options.startLivenessMonitor ?? startBrowserMcpLivenessMonitor)(env, revoke) : () => void 0;
9721
10406
  let buffer = "";
9722
10407
  let mode = null;
9723
- process.stdin.setEncoding("utf8");
9724
- for await (const chunk of process.stdin) {
9725
- buffer += chunk;
9726
- const parsed = parseMcpStdioMessages(buffer, mode);
9727
- mode = parsed.mode ?? mode;
9728
- buffer = parsed.remainder;
9729
- for (const message of parsed.messages) {
9730
- const response = await runAgentV1McpJsonRpcMessage(message, env);
9731
- if (!response) continue;
9732
- const payload = JSON.stringify(response);
9733
- process.stdout.write(parsed.mode === "framed" ? `Content-Length: ${Buffer.byteLength(payload, "utf8")}\r
10408
+ stdin.setEncoding("utf8");
10409
+ try {
10410
+ for await (const chunk of stdin) {
10411
+ if (revoked) break;
10412
+ buffer += chunk;
10413
+ const parsed = parseMcpStdioMessages(buffer, mode);
10414
+ mode = parsed.mode ?? mode;
10415
+ buffer = parsed.remainder;
10416
+ for (const message of parsed.messages) {
10417
+ if (revoked) break;
10418
+ activeRequest = new AbortController();
10419
+ const response = await runAgentV1McpJsonRpcMessage(
10420
+ message,
10421
+ env,
10422
+ surface,
10423
+ { signal: activeRequest.signal }
10424
+ );
10425
+ activeRequest = null;
10426
+ if (revoked) break;
10427
+ if (!response) continue;
10428
+ const payload = JSON.stringify(response);
10429
+ output.write(parsed.mode === "framed" ? `Content-Length: ${Buffer.byteLength(payload, "utf8")}\r
9734
10430
  \r
9735
10431
  ${payload}` : `${payload}
9736
10432
  `);
10433
+ }
9737
10434
  }
10435
+ } catch (error) {
10436
+ if (!revoked) throw error;
10437
+ } finally {
10438
+ activeRequest?.abort();
10439
+ stopLivenessMonitor();
9738
10440
  }
9739
10441
  }
10442
+ function startBrowserMcpLivenessMonitor(env, onRevoked, options = {}) {
10443
+ const intervalMs = Math.max(100, options.intervalMs ?? RUDDER_BROWSER_LIVENESS_INTERVAL_MS);
10444
+ const probe = options.probe ?? (async () => {
10445
+ await mcpApiClient(env).post("/api/browser/liveness", {});
10446
+ });
10447
+ let stopped = false;
10448
+ let timer = null;
10449
+ const schedule = () => {
10450
+ if (stopped) return;
10451
+ timer = setTimeout(() => void tick(), intervalMs);
10452
+ timer.unref?.();
10453
+ };
10454
+ const tick = async () => {
10455
+ try {
10456
+ await probe();
10457
+ } catch (error) {
10458
+ if (error instanceof ApiRequestError && ["browser_disabled", "browser_runtime_unsupported", "browser_run_inactive", "browser_run_forbidden"].includes(error.code ?? "")) {
10459
+ stopped = true;
10460
+ onRevoked(error.code ?? "browser_disabled");
10461
+ return;
10462
+ }
10463
+ }
10464
+ schedule();
10465
+ };
10466
+ schedule();
10467
+ return () => {
10468
+ stopped = true;
10469
+ if (timer) clearTimeout(timer);
10470
+ timer = null;
10471
+ };
10472
+ }
9740
10473
  function parseMcpStdioMessages(buffer, mode = null) {
9741
10474
  const messages = [];
9742
10475
  const detectedMode = mode ?? detectMcpStdioMode(buffer);
@@ -9778,9 +10511,9 @@ function detectMcpStdioMode(buffer) {
9778
10511
  if (/^Content-Length:/iu.test(trimmed)) return "framed";
9779
10512
  return "newline";
9780
10513
  }
9781
- async function callToolSafely(params, env) {
10514
+ async function callToolSafely(params, env, surface, signal) {
9782
10515
  try {
9783
- return await callTool(params, env);
10516
+ return await callTool(params, env, surface, signal);
9784
10517
  } catch (err) {
9785
10518
  const details = errorDetails(err);
9786
10519
  const payload = {
@@ -9799,12 +10532,18 @@ async function callToolSafely(params, env) {
9799
10532
  };
9800
10533
  }
9801
10534
  }
9802
- async function callTool(params, env) {
10535
+ async function callTool(params, env, surface, signal) {
9803
10536
  const record = isRecord2(params) ? params : {};
9804
10537
  const toolName = typeof record.name === "string" ? record.name : "";
10538
+ const exposed = buildAgentV1McpToolsManifest("agent-v1", { surface }).tools.some((tool) => tool.name === toolName);
10539
+ if (!exposed) {
10540
+ const err = new Error(`Rudder MCP tool is not exposed by the ${surface} server: ${toolName || "(missing)"}`);
10541
+ err.code = "rudder_mcp_tool_not_available";
10542
+ throw err;
10543
+ }
9805
10544
  const args = record.arguments;
9806
10545
  const plan = buildAgentV1ToolCallPlan(toolName, args, env);
9807
- const directResult = await callToolDirectlyIfSupported(toolName, args, env);
10546
+ const directResult = await callToolDirectlyIfSupported(toolName, args, env, signal);
9808
10547
  if (directResult) return directResult;
9809
10548
  const tempDir = plan.tempFiles.length > 0 ? await fs.mkdtemp(path2.join(os.tmpdir(), "rudder-mcp-")) : null;
9810
10549
  const materializedArgs = [...plan.args];
@@ -9820,7 +10559,10 @@ async function callTool(params, env) {
9820
10559
  const result = await runRudderCli(materializedArgs, plan.env);
9821
10560
  if (result.exitCode === 0) {
9822
10561
  const text6 = result.stdout.trim() || "{}";
9823
- return mcpSuccessFromJsonText(text6);
10562
+ return mcpSuccessFromJsonText(
10563
+ text6,
10564
+ surface === "browser" ? RUDDER_BROWSER_MCP_MAX_TOOL_RESULT_BYTES : RUDDER_MCP_MAX_TOOL_RESULT_BYTES
10565
+ );
9824
10566
  }
9825
10567
  const payload = {
9826
10568
  status: "error",
@@ -9840,24 +10582,28 @@ async function callTool(params, env) {
9840
10582
  if (tempDir) await fs.rm(tempDir, { recursive: true, force: true });
9841
10583
  }
9842
10584
  }
9843
- async function callToolDirectlyIfSupported(toolName, rawArgs, env) {
10585
+ async function callToolDirectlyIfSupported(toolName, rawArgs, env, signal) {
9844
10586
  const capabilityId = toolNameToCapabilityId(toolName);
9845
10587
  if (!capabilityId) return null;
9846
10588
  const input = isRecord2(rawArgs) ? rawArgs : {};
9847
- const api = mcpApiClient(env);
10589
+ const api = mcpApiClient(env, signal);
10590
+ const success = (data) => mcpSuccess(
10591
+ data,
10592
+ capabilityId.startsWith("browser.") ? RUDDER_BROWSER_MCP_MAX_TOOL_RESULT_BYTES : RUDDER_MCP_MAX_TOOL_RESULT_BYTES
10593
+ );
9848
10594
  switch (capabilityId) {
9849
10595
  case "agent.me":
9850
- return mcpSuccess(await api.get("/api/agents/me"));
10596
+ return success(await api.get("/api/agents/me"));
9851
10597
  case "agent.inbox":
9852
- return mcpSuccess(await api.get("/api/agents/me/inbox-lite"));
10598
+ return success(await api.get("/api/agents/me/inbox-lite"));
9853
10599
  case "issue.get":
9854
- return mcpSuccess(await api.get(`/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}`));
10600
+ return success(await api.get(`/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}`));
9855
10601
  case "issue.context": {
9856
10602
  const params = new URLSearchParams();
9857
10603
  const wakeCommentId = optionalString(input.wakeCommentId);
9858
10604
  if (wakeCommentId) params.set("wakeCommentId", wakeCommentId);
9859
10605
  const query = params.toString();
9860
- return mcpSuccess(await api.get(
10606
+ return success(await api.get(
9861
10607
  `/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}/heartbeat-context${query ? `?${query}` : ""}`
9862
10608
  ));
9863
10609
  }
@@ -9867,7 +10613,7 @@ async function callToolDirectlyIfSupported(toolName, rawArgs, env) {
9867
10613
  agentId: optionalString(env.RUDDER_AGENT_ID),
9868
10614
  expectedStatuses
9869
10615
  });
9870
- return mcpSuccess(await api.post(
10616
+ return success(await api.post(
9871
10617
  `/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}/checkout`,
9872
10618
  payload
9873
10619
  ));
@@ -9877,58 +10623,87 @@ async function callToolDirectlyIfSupported(toolName, rawArgs, env) {
9877
10623
  body: requiredAnyString(input, ["body", "comment"]),
9878
10624
  reopen: input.reopen === true ? true : void 0
9879
10625
  });
9880
- return mcpSuccess(await api.post(
10626
+ return success(await api.post(
9881
10627
  `/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}/comments`,
9882
10628
  payload
9883
10629
  ));
9884
10630
  }
9885
10631
  case "issue.done": {
9886
10632
  const comment = requiredAnyString(input, ["comment", "body"]);
9887
- return mcpSuccess(await api.patch(
10633
+ return success(await api.patch(
9888
10634
  `/api/issues/${encodeURIComponent(requiredAnyString(input, ["issue", "issueId"]))}`,
9889
10635
  { status: "done", comment }
9890
10636
  ));
9891
10637
  }
9892
10638
  case "browser.tabs":
9893
- return mcpSuccess(await api.post("/api/browser/tabs", {}));
10639
+ return success(await api.post("/api/browser/tabs", {}));
10640
+ case "browser.user-tabs":
10641
+ return success(await api.post("/api/browser/user_tabs", {}));
9894
10642
  case "browser.open":
9895
- return mcpSuccess(await api.post("/api/browser/open", {
10643
+ return success(await api.post("/api/browser/open", {
9896
10644
  url: requiredString(input, "url")
9897
10645
  }));
9898
10646
  case "browser.navigate":
9899
- return mcpSuccess(await api.post("/api/browser/navigate", {
10647
+ return success(await api.post("/api/browser/navigate", {
9900
10648
  tabId: requiredString(input, "tabId"),
9901
10649
  url: requiredString(input, "url")
9902
10650
  }));
10651
+ case "browser.back":
10652
+ case "browser.forward":
10653
+ case "browser.reload":
10654
+ return success(await api.post(`/api/browser/${capabilityId.slice("browser.".length)}`, {
10655
+ tabId: requiredString(input, "tabId")
10656
+ }));
10657
+ case "browser.viewport":
10658
+ return success(await api.post("/api/browser/viewport", {
10659
+ action: requiredString(input, "action"),
10660
+ ...input.width !== void 0 ? { width: input.width } : {},
10661
+ ...input.height !== void 0 ? { height: input.height } : {}
10662
+ }));
10663
+ case "browser.visibility":
10664
+ return success(await api.post("/api/browser/visibility", {
10665
+ ...typeof input.visible === "boolean" ? { visible: input.visible } : {}
10666
+ }));
10667
+ case "browser.snapshot":
10668
+ case "browser.locator":
10669
+ case "browser.cua":
10670
+ case "browser.dialog":
10671
+ case "browser.clipboard":
10672
+ case "browser.logs":
10673
+ case "browser.download":
10674
+ case "browser.assets":
10675
+ case "browser.content":
10676
+ case "browser.wait":
10677
+ return success(await api.post(`/api/browser/${capabilityId.slice("browser.".length)}`, input));
10678
+ case "browser.dom-cua":
10679
+ return success(await api.post("/api/browser/dom_cua", input));
9903
10680
  case "browser.read":
9904
- return mcpSuccess(await api.post("/api/browser/read", {
10681
+ return success(await api.post("/api/browser/read", {
9905
10682
  tabId: requiredString(input, "tabId")
9906
10683
  }));
9907
10684
  case "browser.click":
9908
- return mcpSuccess(await api.post("/api/browser/click", {
10685
+ return success(await api.post("/api/browser/click", {
9909
10686
  tabId: requiredString(input, "tabId"),
9910
10687
  ref: requiredString(input, "ref")
9911
10688
  }));
9912
10689
  case "browser.type":
9913
- return mcpSuccess(await api.post("/api/browser/type", {
10690
+ return success(await api.post("/api/browser/type", {
9914
10691
  tabId: requiredString(input, "tabId"),
9915
10692
  ref: requiredString(input, "ref"),
9916
10693
  text: requiredString(input, "text"),
9917
10694
  ...input.submit === true ? { submit: true } : {}
9918
10695
  }));
9919
10696
  case "browser.screenshot":
9920
- return mcpSuccess(await api.post("/api/browser/screenshot", {
9921
- tabId: requiredString(input, "tabId")
9922
- }));
10697
+ return success(await api.post("/api/browser/screenshot", input));
9923
10698
  case "browser.close":
9924
- return mcpSuccess(await api.post("/api/browser/close", {
10699
+ return success(await api.post("/api/browser/close", {
9925
10700
  tabId: requiredString(input, "tabId")
9926
10701
  }));
9927
10702
  default:
9928
10703
  return null;
9929
10704
  }
9930
10705
  }
9931
- function mcpApiClient(env) {
10706
+ function mcpApiClient(env, signal) {
9932
10707
  const apiBase = optionalString(env.RUDDER_API_URL);
9933
10708
  if (!apiBase) {
9934
10709
  const err = new Error("Rudder MCP runtime context is incomplete. Missing RUDDER_API_URL.");
@@ -9939,13 +10714,22 @@ function mcpApiClient(env) {
9939
10714
  apiBase,
9940
10715
  apiKey: optionalString(env.RUDDER_API_KEY) ?? void 0,
9941
10716
  agentId: optionalString(env.RUDDER_AGENT_ID) ?? void 0,
9942
- runId: optionalString(env.RUDDER_RUN_ID) ?? void 0
10717
+ runId: optionalString(env.RUDDER_RUN_ID) ?? void 0,
10718
+ signal
9943
10719
  });
9944
10720
  }
9945
- function mcpSuccess(data) {
9946
- return mcpSuccessFromJsonText(JSON.stringify(data ?? {}));
10721
+ function mcpSuccess(data, maxResultBytes = RUDDER_MCP_MAX_TOOL_RESULT_BYTES) {
10722
+ if (isRecord2(data) && (data.mimeType === "image/png" || data.mimeType === "image/jpeg") && typeof data.base64 === "string" && data.base64.length > 0) {
10723
+ const { base64, ...metadata } = data;
10724
+ return {
10725
+ content: [{ type: "image", data: base64, mimeType: data.mimeType }],
10726
+ structuredContent: metadata,
10727
+ isError: false
10728
+ };
10729
+ }
10730
+ return mcpSuccessFromJsonText(JSON.stringify(data ?? {}), maxResultBytes);
9947
10731
  }
9948
- function mcpSuccessFromJsonText(text6) {
10732
+ function mcpSuccessFromJsonText(text6, maxResultBytes = RUDDER_MCP_MAX_TOOL_RESULT_BYTES) {
9949
10733
  const structured = structuredContentFromJsonText(text6);
9950
10734
  const textBytes = Buffer.byteLength(text6, "utf8");
9951
10735
  const inlineText = textBytes <= RUDDER_MCP_MAX_INLINE_TEXT_BYTES ? text6 : JSON.stringify({
@@ -9960,22 +10744,23 @@ function mcpSuccessFromJsonText(text6) {
9960
10744
  isError: false
9961
10745
  };
9962
10746
  const resultBytes = Buffer.byteLength(JSON.stringify(result), "utf8");
9963
- if (resultBytes <= RUDDER_MCP_MAX_TOOL_RESULT_BYTES) return result;
9964
- return mcpResponseTooLarge(resultBytes);
10747
+ if (resultBytes <= maxResultBytes) return result;
10748
+ return mcpResponseTooLarge(resultBytes, maxResultBytes);
9965
10749
  }
9966
- function boundedToolCallRpcResponse(id, result) {
10750
+ function boundedToolCallRpcResponse(id, result, surface) {
9967
10751
  const response = rpcResult(id, result);
9968
10752
  const responseBytes = Buffer.byteLength(JSON.stringify(response), "utf8");
9969
- if (responseBytes <= RUDDER_MCP_MAX_TOOL_RESULT_BYTES) return response;
9970
- return rpcResult(id, mcpResponseTooLarge(responseBytes));
10753
+ const maxBytes = surface === "browser" ? RUDDER_BROWSER_MCP_MAX_TOOL_RESULT_BYTES : RUDDER_MCP_MAX_TOOL_RESULT_BYTES;
10754
+ if (responseBytes <= maxBytes) return response;
10755
+ return rpcResult(id, mcpResponseTooLarge(responseBytes, maxBytes));
9971
10756
  }
9972
- function mcpResponseTooLarge(responseBytes) {
10757
+ function mcpResponseTooLarge(responseBytes, maxBytes = RUDDER_MCP_MAX_TOOL_RESULT_BYTES) {
9973
10758
  const payload = {
9974
10759
  status: "error",
9975
10760
  code: "rudder_mcp_response_too_large",
9976
10761
  message: "Rudder MCP response exceeded the bounded tool-result budget. Use pagination or a ranged log read.",
9977
10762
  details: {
9978
- maxBytes: RUDDER_MCP_MAX_TOOL_RESULT_BYTES,
10763
+ maxBytes,
9979
10764
  responseBytes
9980
10765
  }
9981
10766
  };
@@ -10200,10 +10985,46 @@ function cliArgsForCapability(capabilityId, input, tempFiles, env) {
10200
10985
  }
10201
10986
  case "browser.tabs":
10202
10987
  return ["browser", "tabs"];
10988
+ case "browser.user-tabs":
10989
+ return ["browser", "user-tabs"];
10203
10990
  case "browser.open":
10204
10991
  return ["browser", "open", requiredString(input, "url")];
10205
10992
  case "browser.navigate":
10206
10993
  return ["browser", "navigate", requiredString(input, "tabId"), requiredString(input, "url")];
10994
+ case "browser.back":
10995
+ return ["browser", "back", requiredString(input, "tabId")];
10996
+ case "browser.forward":
10997
+ return ["browser", "forward", requiredString(input, "tabId")];
10998
+ case "browser.reload":
10999
+ return ["browser", "reload", requiredString(input, "tabId")];
11000
+ case "browser.viewport": {
11001
+ const args = ["browser", "viewport", "--action", requiredString(input, "action")];
11002
+ pushOptional(args, "--width", input.width);
11003
+ pushOptional(args, "--height", input.height);
11004
+ return args;
11005
+ }
11006
+ case "browser.visibility": {
11007
+ const args = ["browser", "visibility"];
11008
+ if (typeof input.visible === "boolean") args.push("--visible", String(input.visible));
11009
+ return args;
11010
+ }
11011
+ case "browser.snapshot":
11012
+ case "browser.locator":
11013
+ case "browser.cua":
11014
+ case "browser.dom-cua":
11015
+ case "browser.dialog":
11016
+ case "browser.logs":
11017
+ case "browser.download":
11018
+ case "browser.assets":
11019
+ case "browser.content":
11020
+ case "browser.wait": {
11021
+ const tabId = requiredString(input, "tabId");
11022
+ const payload = { ...input };
11023
+ delete payload.tabId;
11024
+ return ["browser", capabilityId.slice("browser.".length), tabId, "--input", JSON.stringify(payload)];
11025
+ }
11026
+ case "browser.clipboard":
11027
+ return ["browser", "clipboard", "--input", JSON.stringify(input)];
10207
11028
  case "browser.read":
10208
11029
  return ["browser", "read", requiredString(input, "tabId")];
10209
11030
  case "browser.click":
@@ -10213,8 +11034,12 @@ function cliArgsForCapability(capabilityId, input, tempFiles, env) {
10213
11034
  pushBoolean(args, "--submit", input.submit);
10214
11035
  return args;
10215
11036
  }
10216
- case "browser.screenshot":
10217
- return ["browser", "screenshot", requiredString(input, "tabId")];
11037
+ case "browser.screenshot": {
11038
+ const tabId = requiredString(input, "tabId");
11039
+ const payload = { ...input };
11040
+ delete payload.tabId;
11041
+ return Object.keys(payload).length > 0 ? ["browser", "screenshot", tabId, "--input", JSON.stringify(payload)] : ["browser", "screenshot", tabId];
11042
+ }
10218
11043
  case "browser.close":
10219
11044
  return ["browser", "close", requiredString(input, "tabId")];
10220
11045
  case "automation.list": {
@@ -10446,7 +11271,7 @@ function requestedProtocolVersion(params) {
10446
11271
  return typeof params.protocolVersion === "string" && params.protocolVersion.trim().length > 0 ? params.protocolVersion.trim() : null;
10447
11272
  }
10448
11273
  function toolNameToCapabilityId(toolName) {
10449
- const manifest = buildAgentV1McpToolsManifest("agent-v1");
11274
+ const manifest = buildAgentV1McpToolsManifest("agent-v1", { surface: "all" });
10450
11275
  return manifest.tools.find((tool) => tool.name === toolName)?.id ?? null;
10451
11276
  }
10452
11277
  function requiredString(input, key) {
@@ -10524,7 +11349,7 @@ function rejectModelProvidedRuntimeIdentity(input) {
10524
11349
  throw err;
10525
11350
  }
10526
11351
  function rejectUnsupportedToolArguments(toolName, input) {
10527
- const tool = buildAgentV1McpToolsManifest("agent-v1").tools.find((entry) => entry.name === toolName);
11352
+ const tool = buildAgentV1McpToolsManifest("agent-v1", { surface: "all" }).tools.find((entry) => entry.name === toolName);
10528
11353
  if (!tool) return;
10529
11354
  const supported = new Set(Object.keys(tool.inputSchema.properties));
10530
11355
  const unsupported = Object.keys(input).filter((key) => !supported.has(key)).sort();
@@ -10533,6 +11358,26 @@ function rejectUnsupportedToolArguments(toolName, input) {
10533
11358
  err.code = "rudder_mcp_invalid_arguments";
10534
11359
  throw err;
10535
11360
  }
11361
+ var READ_ONLY_BROWSER_LOCATOR_ACTIONS = /* @__PURE__ */ new Set([
11362
+ "count",
11363
+ "allTextContents",
11364
+ "textContent",
11365
+ "innerText",
11366
+ "attribute",
11367
+ "visible",
11368
+ "enabled",
11369
+ "checked",
11370
+ "selected",
11371
+ "wait"
11372
+ ]);
11373
+ function rejectUnsupportedBrowserLocatorAction(toolName, input) {
11374
+ const locatorActionUnsupported = toolName === "rudder_browser_locator" && !READ_ONLY_BROWSER_LOCATOR_ACTIONS.has(String(input.action));
11375
+ const downloadModeUnsupported = toolName === "rudder_browser_download" && input.mode !== "media";
11376
+ if (!locatorActionUnsupported && !downloadModeUnsupported) return;
11377
+ const err = new Error(locatorActionUnsupported ? "rudder_browser_locator is read-only; use rudder_browser_click, rudder_browser_type, or rudder_browser_cua to interact." : "rudder_browser_download supports read-only media downloads only; use an explicit interaction tool before reading download evidence.");
11378
+ err.code = "rudder_mcp_invalid_arguments";
11379
+ throw err;
11380
+ }
10536
11381
  function normalizeRuntimeIdentityKey(key) {
10537
11382
  return key.replace(/[^a-z0-9]/giu, "").toLowerCase();
10538
11383
  }
@@ -12857,6 +13702,16 @@ function formatAutomationRun(row) {
12857
13702
  }
12858
13703
 
12859
13704
  // src/commands/client/browser.ts
13705
+ function parseBrowserInput(input) {
13706
+ if (!input) return {};
13707
+ try {
13708
+ const parsed = JSON.parse(input);
13709
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("not an object");
13710
+ return parsed;
13711
+ } catch {
13712
+ throw new TypeError("--input must be a JSON object");
13713
+ }
13714
+ }
12860
13715
  async function runBrowserAction(action, payload, options) {
12861
13716
  try {
12862
13717
  const context = resolveCommandContext(options, { requireCompany: true });
@@ -12872,6 +13727,10 @@ function registerBrowserCommands(program) {
12872
13727
  browser.command("tabs").description(getAgentCliCapabilityById("browser.tabs").description),
12873
13728
  { includeCompany: true }
12874
13729
  ).action((options) => runBrowserAction("tabs", {}, options));
13730
+ addCommonClientOptions(
13731
+ browser.command("user-tabs").description(getAgentCliCapabilityById("browser.user-tabs").description),
13732
+ { includeCompany: true }
13733
+ ).action((options) => runBrowserAction("user_tabs", {}, options));
12875
13734
  addCommonClientOptions(
12876
13735
  browser.command("open").description(getAgentCliCapabilityById("browser.open").description).argument("<url>", "HTTP or HTTPS URL"),
12877
13736
  { includeCompany: true }
@@ -12880,6 +13739,60 @@ function registerBrowserCommands(program) {
12880
13739
  browser.command("navigate").description(getAgentCliCapabilityById("browser.navigate").description).argument("<tab-id>", "Run-owned Browser tab id").argument("<url>", "HTTP or HTTPS URL"),
12881
13740
  { includeCompany: true }
12882
13741
  ).action((tabId, url, options) => runBrowserAction("navigate", { tabId, url }, options));
13742
+ for (const action of ["back", "forward", "reload"]) {
13743
+ addCommonClientOptions(
13744
+ browser.command(action).description(getAgentCliCapabilityById(`browser.${action}`).description).argument("<tab-id>", "Run-owned Browser tab id"),
13745
+ { includeCompany: true }
13746
+ ).action((tabId, options) => runBrowserAction(action, { tabId }, options));
13747
+ }
13748
+ addCommonClientOptions(
13749
+ browser.command("viewport").description(getAgentCliCapabilityById("browser.viewport").description).requiredOption("--action <action>", "get, set, or reset").option("--width <pixels>", "Viewport width", Number).option("--height <pixels>", "Viewport height", Number),
13750
+ { includeCompany: true }
13751
+ ).action((options) => runBrowserAction("viewport", {
13752
+ action: options.action,
13753
+ ...options.width !== void 0 ? { width: options.width } : {},
13754
+ ...options.height !== void 0 ? { height: options.height } : {}
13755
+ }, options));
13756
+ addCommonClientOptions(
13757
+ browser.command("visibility").description(getAgentCliCapabilityById("browser.visibility").description).option("--visible <boolean>", "Show or hide the selected Agent Browser tab"),
13758
+ { includeCompany: true }
13759
+ ).action((options) => {
13760
+ const visible = options.visible === void 0 ? void 0 : options.visible === "true" ? true : options.visible === "false" ? false : (() => {
13761
+ throw new TypeError("--visible must be true or false");
13762
+ })();
13763
+ return runBrowserAction("visibility", {
13764
+ ...visible !== void 0 ? { visible } : {}
13765
+ }, options);
13766
+ });
13767
+ for (const action of [
13768
+ "snapshot",
13769
+ "locator",
13770
+ "cua",
13771
+ "dom-cua",
13772
+ "dialog",
13773
+ "logs",
13774
+ "download",
13775
+ "assets",
13776
+ "content",
13777
+ "wait"
13778
+ ]) {
13779
+ addCommonClientOptions(
13780
+ browser.command(action).description(getAgentCliCapabilityById(`browser.${action}`).description).argument("<tab-id>", "Run-owned Browser tab id").option("--input <json>", "JSON object with bounded Browser action arguments"),
13781
+ { includeCompany: true }
13782
+ ).action((tabId, options) => runBrowserAction(
13783
+ action === "dom-cua" ? "dom_cua" : action,
13784
+ { tabId, ...parseBrowserInput(options.input) },
13785
+ options
13786
+ ));
13787
+ }
13788
+ addCommonClientOptions(
13789
+ browser.command("clipboard").description(getAgentCliCapabilityById("browser.clipboard").description).requiredOption("--input <json>", "JSON object with virtual clipboard action arguments"),
13790
+ { includeCompany: true }
13791
+ ).action((options) => runBrowserAction(
13792
+ "clipboard",
13793
+ parseBrowserInput(options.input),
13794
+ options
13795
+ ));
12883
13796
  addCommonClientOptions(
12884
13797
  browser.command("read").description(getAgentCliCapabilityById("browser.read").description).argument("<tab-id>", "Run-owned Browser tab id"),
12885
13798
  { includeCompany: true }
@@ -12898,9 +13811,9 @@ function registerBrowserCommands(program) {
12898
13811
  ...options.submit ? { submit: true } : {}
12899
13812
  }, options));
12900
13813
  addCommonClientOptions(
12901
- browser.command("screenshot").description(getAgentCliCapabilityById("browser.screenshot").description).argument("<tab-id>", "Run-owned Browser tab id"),
13814
+ browser.command("screenshot").description(getAgentCliCapabilityById("browser.screenshot").description).argument("<tab-id>", "Run-owned Browser tab id").option("--input <json>", "JSON object with full-page, clip, locator, or format options"),
12902
13815
  { includeCompany: true }
12903
- ).action((tabId, options) => runBrowserAction("screenshot", { tabId }, options));
13816
+ ).action((tabId, options) => runBrowserAction("screenshot", { tabId, ...parseBrowserInput(options.input) }, options));
12904
13817
  addCommonClientOptions(
12905
13818
  browser.command("close").description(getAgentCliCapabilityById("browser.close").description).argument("<tab-id>", "Run-owned Browser tab id"),
12906
13819
  { includeCompany: true }
@@ -18696,8 +19609,11 @@ function createProgram() {
18696
19609
  await doctor(opts);
18697
19610
  });
18698
19611
  program.command("env").description("Print environment variables for deployment").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).action(envCommand);
18699
- program.command("mcp-server").description("Run the first-party Rudder Agent V1 MCP server over stdio").action(async () => {
18700
- await runMcpStdioServer();
19612
+ program.command("mcp-server").description("Run the first-party Rudder Agent V1 MCP server over stdio").option("--server <surface>", "MCP surface to expose (core or browser)", "core").action(async (opts) => {
19613
+ if (opts.server !== "core" && opts.server !== "browser") {
19614
+ throw new Error(`Unsupported Rudder MCP server surface: ${opts.server}`);
19615
+ }
19616
+ await runMcpStdioServer(void 0, opts.server);
18701
19617
  });
18702
19618
  program.command("configure").description("Update configuration sections").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("-s, --section <section>", "Section to configure (llm, database, logging, server, storage, secrets)").action(configure);
18703
19619
  program.command("db:backup").description("Create a one-off database backup using current config").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--dir <path>", "Backup output directory (overrides config)").option("--retention-days <days>", "Retention window used for pruning", (value) => Number(value)).option("--filename-prefix <prefix>", "Backup filename prefix", "rudder").option("--json", "Print backup metadata as JSON").action(async (opts) => {