Tool reference

All 454 tools, grouped by what they do — reads, device control, entries, scripting, settings, and more.

The Busymate MCP server exposes 454 tools — a one-to-one mirror of the dashboard's read/write surface. This page groups and explains them by what they do.

Every served tool is on this page. The named families below are written by hand — they carry the reasoning a generator cannot — and the rest are projected from the same tool registry the server runs, so the two sets together are exactly the roster mcp.busymate.dev serves. A tool added to the product without a row here cannot land.

The authority on arguments is still the server's own tools/list. Each row is one line; the full description and JSON schema come back from tools/list over any transport. Busymate AI's own management tools are not here — they serve only on busymate.ai/mcp.

How to read this page

Each tool carries permission gating, enforced server-side on every call:

  • section:view / section:edit — a capability check against your RBAC role. You need the named capability (e.g. devices:edit) for the call to run. Built-in admin grants all; built-in viewer is read-only.
  • confirm-gated — a destructive action that requires an explicit confirm: true (or confirm: "all") argument. The agent must opt in deliberately; a stray call is rejected.
  • admin-only — restricted to admin roles regardless of capabilities.
  • owner-scoped — no capability needed; the tool only ever reads or writes the caller's own row.
  • per-table — the generic CRUD tools resolve the capability from the table they touch.

Tools are scoped to your account and RLS — you only ever see and touch your own devices, entries, and settings.


Generic CRUD — db_* (5)

Low-level PostgREST access to allowlisted tables. The section gate is per-table: each table maps to a capability section, and db_select/db_rpc need view, the mutators need edit. Update and delete reject empty filters.

ToolWhat it doesGating
db_selectGeneric select against an allowlisted table (columns, filters, order, limit, offset).per-table :view
db_insertGeneric insert / upsert (with onConflict).per-table :edit
db_updateGeneric update; empty filters rejected.per-table :edit
db_deleteGeneric delete; empty filters rejected.per-table :edit
db_rpcCall an allowlisted Postgres function.per-table :view

Realtime & introspection (2)

ToolWhat it doesGating
realtime_broadcastSend a Broadcast message on a Realtime channel (the same fan-out the dashboard uses).global:edit
list_tablesList the tables / RPCs available to the generic CRUD tools.global:view

Device reads (4)

ToolWhat it doesGating
list_devicesList devices — YOUR OWN by default (owner-scoped), or the whole fleet with all:true (devices:view operators, re-verified server-side). Slim rows: uuid/name/model/platform/os_version, parent linkage (host NAME resolved), online + vpn_state, per-device connection type override, pac_port/pac_url.devices:view (own devices via owner-fallback)
test_pac_connectionPROVE whether PAC capture actually works for ONE device — 8 checks, each pass/fail/unverified with a specific human fix: connection mode, PAC port + URL, the served PAC is a PROXY directive and NOT the silent DIRECT fallback (the headline), egress IP allowlisted, the proxy is really routing its traffic, a NON-EMPTY effective SSL list that covers hosts it contacts, genuinely DECRYPTED in-scope traffic (a CONNECT/raw-TCP row is never counted as proof), and the device-reported CA-trust readiness. A check that could not verify returns unverified, never a pass.devices:view (own/demo devices via owner-fallback)
get_deviceFetch one device by uuid or name.devices:view
get_device_statusLive status / heartbeat for a device. For a named bmc device, best-effort windowMode (the persisted on-screen setting — "minimized"/"visible"; null = the class default applies).devices:view

Device realtime control (8)

Control flows delivered over Realtime to a paired device. The destructive ones are confirm-gated.

ToolWhat it doesGating
rename_deviceRename a device.devices:edit
delete_deviceDelete a device record.devices:edit · confirm-gated
unpair_deviceUnpair / revoke a device.devices:edit · confirm-gated
vpn_on_deviceTurn the on-device VPN tunnel on.devices:edit
vpn_off_deviceTurn the on-device VPN tunnel off.devices:edit
open_sheet_deviceRemotely open the iOS app's settings / cert / pac sheet (foreground only).devices:edit
set_device_connection_typeSet a device's connection type (e.g. VPN vs PAC).devices:edit
set_live_activity_messageSet or clear the per-device Live Activity lock-screen pill text.devices:edit

External / upstream proxy control (2)

Route a device's egress through an upstream proxy so its public IP and country become the proxy's.

ToolWhat it doesGating
list_proxiesList available proxies from the MyPrivateProxy pool (filter by country / free-text). Credentials never returned.devices:view
set_device_external_proxySet or clear a device's upstream proxy — by country (auto-select a healthy proxy) or explicit host+port.devices:edit · confirm-gated

Remote browser / CDP control (9)

Drive a real Chrome that a bmc (cdp-connector) device controls. Every command needs the per-device remote-control opt-in to be ON; the raw escape hatch is admin-only.

ToolWhat it doesGating
set_device_cdp_controlTurn the per-device remote-browser/farm opt-in on / off (ON by default for an automation-class device — a CDP browser / bmc-daemon host / bmfarm host — owner-gated opt-out; a personal/iOS device stays OFF).devices:edit
set_device_capture_enabledTurn a bmc device's traffic capture on / off (settings_device.data.captureEnabled). false = a control-only device: Chrome and every browser_* command keep working, but nothing is captured or ingested; the running device flips live. Same row as bmc create/edit --capture.devices:edit · confirm-gated
set_device_autostartTurn a bmc device's autostart on / off (settings_device.data.autostart). true = the supervised bmc daemon starts it on boot and relaunches it with backoff when it exits; turning it off never stops a running device. Same row as bmc create/edit --autostart.devices:edit · confirm-gated
browser_targetsList the open browser targets / tabs the device controls.devices:edit
browser_openOpen a URL in the controlled Chrome.devices:edit
browser_evalEvaluate JavaScript in a target (resolves {{VAR}} env refs server-side).devices:edit
browser_screenshotCapture a screenshot of a target.devices:edit
browser_snapshotCapture an accessibility / DOM snapshot of the page.devices:edit
browser_cdpSend a raw Chrome DevTools Protocol command (arbitrary-code power).devices:edit · admin-only

Named CDP device daemon (7)

Lifecycle of named CDP "devices" (Chrome instances on a bmc machine), plus hot-updating the daemon itself. The mutators are confirm-gated.

ToolWhat it doesGating
list_cdp_instancesList the named CDP instances a machine runs. Each row's windowState ("normal"/"minimized") is that device's live on-screen state, reported once its bmc is on build 100+.devices:view
start_deviceStart a named CDP device. Optional headless: true|false is a one-shot override for this launch only — never persisted (see Named devices & the daemon → Headless).devices:edit · confirm-gated
stop_deviceStop a named CDP device.devices:edit · confirm-gated
create_deviceProvision a new named CDP device (fresh port + profile, pairs its JWT).devices:edit · confirm-gated
update_cdp_hostHot-update the bmc daemon on a machine to the latest build and recycle its supervisor — running captures keep capturing (re-adopted), remote control is briefly unavailable while it reconnects.devices:edit · confirm-gated
set_device_window_modePersist a named device's on-screen window state — windowMode: "minimized"|"visible" — the same row bmc edit/bmc create and the dashboard's Window mode toggle write. Takes effect on the device's next launch (or immediately via focus_device_window for a running one). See Window mode.devices:edit · confirm-gated
focus_device_windowRaise or minimize a running named device's Chrome window right now, without touching its persisted setting — the remote twin of bmc front/bmc minimize. device_uuid/deviceName select the host machine; device names the target device on it; action is "front" or "minimize".devices:edit · confirm-gated

Custom browser profiles (4)

CRUD over the browser_profiles table of custom Chromium-family launch profiles authored in the dashboard (Settings → CDP) and synced to the bmc CLI. The five built-ins (chrome / brave / edge / godbrowser / chromium) live in the CLI code — they're reserved slugs and never appear here.

ToolWhat it doesGating
list_browser_profilesList custom browser profiles (slug, display name, binaries, default flags, flag catalog, CDP notes).devices:view
get_browser_profileGet one custom profile by slug or id — full detail.devices:view
upsert_browser_profileCreate or update a custom profile (matched by slug); reserved built-in slugs are rejected.devices:edit · confirm-gated
delete_browser_profileDelete a custom profile by slug or id.devices:edit · confirm-gated

Android farm (28)

The Android farm (#148) pairs one HOST device per Mac Mini (platform: android-host) and models each connected phone as its own UUID-keyed child android device row, parented to the host (parent_device_id). The Edge function can't run ADB, so every farm control tool dispatches a farm-command to the host over its private device:<uuid> Realtime channel and awaits farm-result — the same host-routed pattern as the CDP daemon tools, gated by the host's cdpControlEnabled opt-in. Identify the host with device_uuid/deviceName; target specific phones with child_uuid/child_uuids (the route-key uuid, never the volatile ADB serial), or omit to target all online phones. The raw executors carry arbitrary device control (browser_cdp-tier) — they're admin-gated, iOS-refused, and never offered to the BusyBro chat LLM.

ToolWhat it doesGating
provision_farm_phoneCreate / update / remove a child android phone row via the farm_provision_child DEFINER RPC (UUID-keyed, parented to the host).devices:edit · confirm-gated
list_farm_devicesList the farm fleet (hosts + their child phones) from the devices table (no host dispatch).devices:view
farm_list_phonesLive adb view of the phones on a host (serial / state / model / Android / battery).devices:view · opt-in ON
farm_capture_statusRead how farm capture is wired (the shared hardened proxy-server path).devices:view · opt-in ON
farm_screenshotPNG screenshot of ONE phone (by child_uuid).devices:view · opt-in ON
farm_dump_uiOn-screen UI hierarchy (interactable nodes) of the targeted phone(s).devices:view · opt-in ON
farm_list_automationsList the host's available automation scripts.devices:view · opt-in ON
farm_list_recordingsList the host's saved input recordings.devices:view · opt-in ON
farm_list_schedulesList the host's active scheduled jobs.devices:view · opt-in ON
farm_find_and_tapFind a UI element by text / resource-id and tap it on the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_set_settingsettings put (system | secure | global) on the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_set_wifiEnable / disable WiFi on the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_app_lifecycleStart | stop | clear an app on the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_grant_permissionGrant a runtime permission to an app on the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_uninstall_appUninstall a package from the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_pull_filePull a file from the targeted phone(s) to the host.devices:edit · opt-in ON · confirm-gated
farm_run_automationRun an automation script (by id) on the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_replay_recordingReplay a saved recording on the targeted phone(s).devices:edit · opt-in ON · confirm-gated
farm_scheduleSchedule an automation / recording on an interval.devices:edit · opt-in ON · confirm-gated
farm_remove_scheduleRemove a scheduled job by id.devices:edit · opt-in ON · confirm-gated
farm_run_shellADMIN — run an arbitrary adb shell command on the targeted phone(s).devices:edit · admin · opt-in ON · confirm-gated
farm_run_adbADMIN — run a raw adb subcommand on the targeted phone(s).devices:edit · admin · opt-in ON · confirm-gated
farm_install_appADMIN — install an APK (host path) onto the targeted phone(s).devices:edit · admin · opt-in ON · confirm-gated
farm_inputADMIN — broadcast a tap / swipe / key / text input event (group control).devices:edit · admin · opt-in ON · confirm-gated
farm_set_proxyADMIN — set / clear the global HTTP proxy (egress redirect).devices:edit · admin · opt-in ON · confirm-gated
farm_set_airplaneADMIN — toggle airplane mode.devices:edit · admin · opt-in ON · confirm-gated
farm_rebootADMIN — reboot the targeted phone(s).devices:edit · admin · opt-in ON · confirm-gated
farm_push_fileADMIN — push a file from the host onto the targeted phone(s).devices:edit · admin · opt-in ON · confirm-gated

Farm fleet components (4)

The per-component lifecycle behind the dashboard Phone Farm → Info tab. A farm device (a host or a phone) reports every driver that makes it controllable — the DevTools app, the DeviceKit runner, the broadcast mirror, the developer disk image, the CA trust, WebDriverAgent, and the host's own go-ios / mobile-mcp / scrcpy / adb / farm-daemon — each with an honest state (absent / outdated / current / unknown). These four tools act on that surface. device_uuid / deviceName selects the host to route to; child_uuid (a phone's route-key uuid) selects the target device, or omit it for the host's own component. Each streams step-by-step farm-action-progress events on the host's device:<host-uuid> channel and returns a run_id to correlate them.

ToolWhat it doesGating
farm_component_actionRun ONE lifecycle action — install | update | reinstall | recheck — on ONE component of ONE farm device.devices:edit · opt-in ON · confirm-gated
update_farm_componentUpdate ONE outdated component on ONE farm device to its latest published version.devices:edit · opt-in ON · confirm-gated
update_farm_fleetBulk sweep: update EVERY outdated component on EVERY device under the host.devices:edit · opt-in ON · confirm-gated
onboard_farm_fleetBulk onboard: provision every connected phone, then install every ABSENT component.devices:edit · opt-in ON · confirm-gated

The daemon reports honest evidence — the new installed version on a successful install/update/reinstall, the fresh probe outcome on a recheck, or an explicit refusal for a non-updatable or unknown component (never a false success).

Ad-hoc proof install — farm_component_action extra arguments

Three optional arguments turn farm_component_action into the remote pre-TestFlight proof install. They apply to the devtools-app component on an iPhone only and are refused (never silently ignored) anywhere else — including on an Android phone, where an adb install of the published APK has no code-signing mode.

ArgumentTypeWhat it does
signing"dev" | "adhoc"The code-signing mode. dev (default) is the daemon's hands-off per-device dev-sign. adhoc is the ad-hoc distribution sign used for proof screenshots from a real farm phone: it skips the dev-trust gate and launches the app to confirm a pid. A typo'd value is rejected — never a silent fallback to dev.
buildstringRe-sign a specific cached CFBundleVersion (e.g. "259") instead of whatever the hosted app.zip currently is. Refused when that build is not cached and the hosted zip is a different one — it never signs the wrong build.
launchbooleanLaunch the app after installing and confirm its pid. Defaults to true for signing: "adhoc" (a proof install must actually run) and false for dev.

Switching modes uninstalls the old build first in either direction — iOS refuses an in-place cross-signer replace, so the app's data is reset. On iOS 26 a sideloaded build needs a one-time online verification at first launch, so the phone must have internet; installed-but-not-launched is reported honestly as launch-unverified, never as success. See the farm architecture for the full pipeline.

Farm app sign-in (1)

ToolWhat it doesGating
enroll_farm_phone_appSign the Busymate DevTools app in on ONE connected farm phone — iPhone or Android — with no interactive owner sign-in. ONE tool: the platform comes from the phone's own device row, never from an argument. Returns opened / signed_in / already_signed_in (safe to re-run), or a named refusal — not_configured, offline, engine_not_ready, start_failed, unsafe_credential, no_gate, signin_rejected, signin_timeout, not_supported.devices:edit · opt-in ON · confirm-gated

An installed app is not a proof-ready app: both apps open on a sign-in gate, and a screenshot of a gate proves nothing about the feature being shipped. This is what gets past it without a person at the rack.

identity picks the mechanism, and the two arms are different in kind:

identityPlatformsHow it signs in
farm (default)iOS + AndroidValue-blind federation. The host mints PKCE, signs a bm_farm assertion with the Vault secret FARM_FED_HMAC, gets a single-use 60-second PKCE-bound code and opens the federation deep link on the phone; the app exchanges it and pairs. No password exists on this path — capped-viewer, anti-takeover.
user · admin · demoAndroidA real product account, which is usually what a proof set wants because it shows what a customer sees. The farm host resolves that identity's credential from the Vault and types it on the device. The credential is never an argument, never on the wire, never logged; an iPhone refuses these arms and tells you to use farm.

Two properties worth relying on: it never guesses — a credential that input text cannot reproduce verbatim is refused rather than typed, because a silently altered password is indistinguishable from a wrong one, and a gate left with text in it from an interrupted attempt gets one force-stop and a retry rather than a blind submit. And app is a symbolic name ("devtools"), never a package id, because this path types a real password into whatever is on screen and may only ever drive an app we ship.

The reply is a three-field allowlist — { ok, status, signedInAs, device } — so nothing credential-shaped can travel back. Omitting identity sends no identity argument at all, keeping the payload byte-identical to a call made before the arm existed. The dashboard mirror is the /farm Info tab's App sign-in card; see the pre-TestFlight proof install.

Entries (12)

Read, tag, search, and inspect captured request / response pairs. summarize_device_traffic is the one to reach for first on a busy device — a bounded, index-only profile of which hosts/endpoints dominate, without scanning raw rows. inspect_requests is the deep one — full headers and bodies for reverse-engineering an API. delete_entries is the precise, targeted counterpart to the whole-device wipe_entries.

ToolWhat it doesGating
search_entriesSearch captured entries (host, status, method, date).devices:view
list_entriesNewest captured entries as slim feed rows (no bodies) — the main live feed's MCP-parity read; device/exact-host/ts filters + a since_id live-tail append cursor. Owner-scoped, newest-first, capped 100. The live-traffic widget's output tool.devices:view
get_entry_countCount entries matching a filter.devices:view
list_wipe_jobsThe workspace's wipe JOBS (entries_wipe_jobs) — the one source of truth for wipe progress (the dashboard banner renders the same rows): exact device set, predicate, total from the live ledger (total_exact), deleted, percent, status, heartbeat + a derived stalled flag (no heartbeat for 90 s; the server re-drives it within a minute). Filter by job_id / status (or active) / device_uuid.devices:view
get_entry_counts_freshnessThe one freshness surface for every counter: mode: live (the per-device / per-host ledger is maintained in the write transaction and broadcast as COUNTS_DELTA), ledger_since, reconciled_at + drift from the hourly reconciler (reconcile_stale after 2 h without a pass), and the /stats rollup seal watermark.devices:view
summarize_device_trafficBounded, index-only traffic profile for ONE device — top hosts by request count, or (with host) the top path-bases on that host with per-path count + last-seen. Never scans or returns raw rows; fast on 17k+ rows. The first tool to call to find the busy/flooding host.devices:view
inspect_requestsDeep-inspect FULL request + response headers and bodies for ONE host (requires a full hostname with a dot).devices:view
export_harExport matching entries as a HAR 1.2 log (scope by device / host / date).devices:view
tag_entryAdd a tag to an entry.tags:edit
untag_entryRemove a tag from an entry.tags:edit
wipe_entriesDelete captured entries as a server-state WIPE JOB: one device, device_uuids[], or every device with all: true (spelled out per device — the job and its audit_log row carry the exact set); optional hosts/methods/status_class/search_q/origin narrowing (the feed's own predicate); total from the live ledger, batch shrinks on a timed-out step, stalled jobs are re-driven. Waits up to ~100 s (wait: false returns the queued job for list_wipe_jobs). Requires confirm: true (irreversible).devices:edit
delete_entriesTargeted filter-then-delete on ONE device (host / path_contains / method / time range; at least one filter required). Optional keep_latest_n keeps the N newest matching rows and deletes the rest — trim a flooding endpoint while keeping recent samples. Destructive + irreversible.devices:edit + admin + confirm

inspect_requests and export_har return real captured headers and bodies — treat any tokens, cookies, or credentials in them as secrets.

Observed API (13)

Evidence-backed API discovery over traffic visible to the caller. The immutable observation graph is the stored truth; OpenAPI 3.1 is a deterministic, secret-safe projection. All thirteen tools are owner-scoped through user-token RLS and are available to BusyBro from the same canonical registry. Every writer is confirm-gated. (The former publish_api_artifact — Observed-API revision → self-contained artifact — was removed from the DevTools MCP under #1985 La, since artifacts are Busymate AI only.)

ToolWhat it doesGating
list_api_projectsList active projects, scope, latest revision, and requested/measured schedule health; optionally include archives.authenticated owner
create_api_projectCreate a host/device/time-scoped project and optionally infer revision 1.authenticated owner + confirm
update_api_projectChange name or advanced scope and immediately rebuild a revision.authenticated owner + confirm
set_api_project_archivedArchive/restore a project; archive disables its schedule.authenticated owner + confirm
delete_api_projectPermanently cascade-delete the project store (published artifacts stay independent).authenticated owner + confirm
set_api_project_scheduleEnable/pause refreshes, set requested cadence, and opt into drift notifications.authenticated owner + confirm
refresh_api_projectRe-scan the scope, apply reviews, append an immutable revision, and record drift.authenticated owner + confirm
get_api_revisionRead a revision's graph, OpenAPI, evidence map, stats, and source window.authenticated owner
list_api_candidatesList weak path-template candidates that require review.authenticated owner
review_api_candidateAccept a template, keep literal paths, or exclude them; refreshes by default.authenticated owner + confirm
export_api_specExport deterministic OpenAPI JSON or YAML with no captured values/examples.authenticated owner
generate_api_assetGenerate a TypeScript SDK, placeholder Node mock, or safe-default Vitest contract suite.authenticated owner
list_api_driftList operation, status, and structural schema changes between revisions.authenticated owner

Service groups (5)

A service group can link one or more BusyBro specialist agents from the busybro_agents registry, with exactly one primary (the service's lens + default run_task target) and an explicit order. list_service_groups / get_service_group return each group's primary_agent plus its ordered agents[].

ToolWhat it doesGating
list_service_groupsList service groups, each with its primary_agent + ordered linked agents[].services:view
get_service_groupFetch one service group, with its primary_agent + ordered linked agents[].services:view
upsert_service_groupCreate or update a service group.services:edit
delete_service_groupDelete a service group.services:edit
set_service_group_agentsFull-replace the agents linked to a group: pass the complete desired [{agent_id, is_primary?, position?}] set (exactly one primary; an empty set clears all links).services:edit + confirm

The legacy service_groups.ai_agent jsonb (the old single inline {enabled, name, instructions} per-service agent) and the deprecated service_groups.agent_id FK have been dropped — link agents with set_service_group_agents instead (the service_group_agents join is the single source of truth). upsert_service_group still accepts an ai_agent arg for back-compat but ignores it.

Tags (3)

ToolWhat it doesGating
list_tagsList defined tags.tags:view
upsert_tagCreate or update a tag.tags:edit
delete_tagDelete a tag.tags:edit

Settings & environment (20)

Effective settings (global / per-user / per-service / per-device), environment variables, connection types, and breakpoint patterns. Env values are masked on read and never echoed on write; reference them later as {{KEY}} in resend_request and browser_eval. The env tools gate dynamically by scopeglobal checks global:*, device checks devices:*.

#965 — one tool per scope. These were once four tools taking a scope: 'global'|'device' argument. That shape could not be owner-scoped: an ownership tag authorizes the caller against an owned device, but the handler picked its resource from scope, so {scope:'global', device_uuid:<a device you own>} would have passed the ownership check and been served the ownerless settings_global singleton. Splitting per scope makes the gate and the dispatch agree by construction — each tool addresses exactly one store.

ToolWhat it doesGating
get_global_settingsRead settings_global.data.global:view
get_device_settingsRead a device's settings row.devices:view
get_env_globalList the GLOBAL env vars (values masked).global:view
get_env_deviceList ONE device's env vars (values masked).devices:view · owner-scoped
set_env_var_globalSet one GLOBAL env var (value never echoed).global:edit
set_env_var_deviceSet one env var on ONE device (value never echoed).devices:edit · owner-scoped
delete_env_var_globalRemove one env var from the GLOBAL store.global:edit
delete_env_var_deviceRemove one env var from ONE device's store.devices:edit · owner-scoped
import_env_globalBulk-import vars from .env text into the GLOBAL store (merge or replace).global:edit
import_env_deviceBulk-import vars from .env text into ONE device's store (merge or replace).devices:edit · owner-scoped
set_breakpoint_patterns_globalSet the global breakpoint patterns per direction — requestPatterns (outbound) / responsePatterns (inbound); patterns is a legacy alias for the request direction.global:edit
set_breakpoint_patterns_deviceSet a device's breakpoint patterns per direction — requestPatterns / responsePatterns; patterns is a legacy alias for the request direction.devices:edit
set_breakpoint_patterns_userSet a USER's breakpoint patterns per direction (the middle tier global → user → device). Effective per device = global ++ user ++ device.users:edit · confirm-gated
set_breakpoint_patterns_serviceSet a SERVICE GROUP's breakpoint patterns per direction (the SERVICE tier global → user → service → device); applies to every device that has applied the group. Effective per device = global ++ service ++ user ++ device.services:edit · confirm-gated
set_global_connection_typeSet the global default connection type.global:edit
set_user_connection_typeSet the per-user connection type.users:edit
set_my_display_nameChange YOUR OWN account display name (profiles.display_name for the calling account). Self-scoped — writes only the caller's own row (cannot name another user; '' clears it).own-data (any signed-in user)
get_my_accountYOUR account at a glance — one self-scoped read: profile (name/email/role/providers/user_id/created_at), per-user connection type (own + global default + effective), linked Telegram accounts, owned devices, subscription status, callable endpoints. Takes no target args — cannot read another user's account.own-data (any signed-in user)
delete_my_accountPERMANENTLY delete YOUR OWN account — the App Store 5.1.1(v) self-service deletion over MCP (profile + owned devices + captured traffic + API tokens + auth user). Self-only (no target args) + HUMAN-only (a device/service caller is refused). A protected reviewer/demo account is preserved ({ protected: true }). BusyBro-denylisted.own-data · confirm-gated
list_issue_reportsList issue reports from the one-tap reporter — your own by default, every reporter's with all:true (audit operators). Slim rows: title, status, occurrences, GitHub issue link, route + build.own-data (audit:view for all:true)

Control flows (3)

Realtime control directed at the proxy-server / device handling a paused request.

ToolWhat it doesGating
resend_requestReplay a captured request (resolves {{VAR}} env refs server-side).devices:edit · confirm-gated
breakpoint_continueRelease a request paused at a breakpoint.devices:edit · confirm-gated
list_breakpoint_eventsList HELD (paused) breakpoint exchanges — your own devices' by default, every device with all:true (operators). Slim rows with the device name; feed request_id into breakpoint_continue.devices:view (own-data by default)

Pauses (2)

ToolWhat it doesGating
get_paused_domainsRead the global paused-domains list — the dedicated, confirm-free read twin.pauses:view
set_paused_domainsRead (omit domains) or replace the global paused-domains list.pauses:view / pauses:edit

Block rules (6)

Auto-block requests matching a method + host/path wildcard, before they reach upstream. The rule action is one of three variants: block returns a synthetic error response (status default 403, body, contentType); drop tears the connection down; mock returns a synthetic SUCCESS response (status default 200, optional string→string headers map, body, contentType). Stored in settings_{global,device}.data.blockRules; effective per device = global ++ device (de-duped by id).

Each rule also accepts an optional maxRuns integer — a run-count cap. Omit it (or pass a non-positive value) for unlimited (the default); maxRuns: 1 makes the rule fire once then auto-disable. The cap is set at creation right here on the rule object and applies to any action type. The count is tracked per device and persisted (it survives reconnect/restart — "once ever"), and a global rule that hits its cap is suppressed only on the device that reached it, never fleet-wide. See Block rules for the full semantics.

Example mock rule (force a JSON 200):

json
{ "id": "33333333-3333-3333-3333-333333333333", "enabled": true, "method": "GET",
  "pattern": "api.doordash.com/v3/feature_flags",
  "action": { "type": "mock", "status": 200, "headers": { "x-mocked-by": "busymate" },
    "contentType": "application/json", "body": "{\"flags\":{\"new_ui\":true}}" } }

Example one-shot mock rule (maxRuns: 1 — fire a single synthetic 401 to force a token refresh, then auto-disable):

json
{ "id": "44444444-4444-4444-4444-444444444444", "enabled": true, "method": "GET",
  "pattern": "api.example.com/v1/me",
  "action": { "type": "mock", "status": 401, "contentType": "application/json",
    "body": "{\"error\":\"token_expired\"}" },
  "maxRuns": 1 }
ToolWhat it doesGating
get_block_rules_globalRead the GLOBAL block rules — the fleet-wide tier that applies to every device.global:view
get_block_rules_deviceRead what ONE device ENFORCES (device_uuid/deviceName required) — the effective 4-tier union (global ++ service ++ user ++ device) plus the service, owner-user and per-device tiers. A rule shadowed here is correctly absent.devices:view (owner-scoped)
set_block_rules_globalReplace the global block rules (full list, each rule may carry maxRuns); merged into settings_global.data without clobbering other keys.global:edit
set_block_rules_userReplace a USER's block rules (the middle tier); additive (effective = global ++ user ++ device). A {type:'script'} action stays privilege-gated (scripts:edit + admin + confirm).users:edit · confirm-gated
set_block_rules_serviceReplace a SERVICE GROUP's block rules (the SERVICE tier); applies to every device that has applied the group. Additive (effective = global ++ service ++ user ++ device, device wins then user then service then global). A {type:'script'} action stays privilege-gated (scripts:edit + admin + confirm).services:edit · confirm-gated
set_block_rules_deviceReplace a device's per-device block rules (full list, each rule may carry maxRuns); additive on top of the global ++ user lists.devices:edit

Scripting engine (7)

Scripts are sandboxed JavaScript hooks (onRequest / onResponse) the proxy-server, cdp-connector, and iOS VPN run inline to mutate or synthesize matching requests/responses — the grown-up evolution of a Mock block rule. They live in settings_{global,user,device}.data.scripts; effective per device = global ++ user ++ device (de-duped by id, device wins then user then global), the same model as block rules. Writing a script is arbitrary-code power (browser_cdp-tier): the write tools need scripts:edit + admin + confirm: true at EVERY tier (the user tier does not lower the bar), enforced at the database layer (settings_{global,user,device}_scripts_gate) so no surface can smuggle a script in via a blocks write or a self-write.

A script object is { id, enabled, name, pattern, method?, phase: "request" | "response" | "both", code, version?, note? }.

ToolWhat it doesGating
get_scripts_globalRead the GLOBAL scripts — the fleet-wide tier — plus engine_enabled (the master kill-switch).scripts:view
get_scripts_deviceRead what ONE device RUNS (device_uuid/deviceName required) — the effective 4-tier union plus the service, owner-user and per-device tiers, with engine_enabled. A script shadowed here is correctly absent.scripts:view (owner-scoped)
set_scripts_globalReplace the global scripts (full list); merged into settings_global.data without clobbering other keys.scripts:edit · admin-only · confirm-gated
set_scripts_userReplace a USER's scripts (the middle tier); additive (effective = global ++ user ++ device). IDENTICAL bar to the global/device writers — the user tier does NOT lower it.scripts:edit · admin-only · confirm-gated
set_scripts_serviceReplace a SERVICE GROUP's scripts (the SERVICE tier); applies to every device that has applied the group. Additive (effective = global ++ service ++ user ++ device). IDENTICAL bar — the service tier does NOT lower it (services:edit alone is not enough; the DB service_groups_scripts_gate enforces it).scripts:edit · admin-only · confirm-gated
set_scripts_deviceReplace a device's per-device scripts (full list); additive on top of the global ++ user lists.scripts:edit · admin-only · confirm-gated
dry_run_scriptStatically check a candidate script before saving — parse-only compile + contract check (no write, no live execution). Full semantic dry-run runs in the live sandbox / dashboard, not the Edge function.scripts:view

Workspaces (6)

ToolWhat it doesGating
list_workspacesList workspaces.global:view
get_workspaceFetch one workspace.global:view
create_workspaceCreate a workspace.global:edit
rename_workspaceRename a workspace.global:edit
delete_workspaceDelete a workspace.global:edit · confirm-gated
set_workspace_retentionSet a workspace's retention window.global:edit

Tabs (6)

ToolWhat it doesGating
list_tabsList tabs.global:view
create_tabCreate a tab.global:edit
rename_tabRename a tab.global:edit
delete_tabDelete a tab.global:edit
set_tab_filtersSet a tab's filters.global:edit
set_tab_selected_entrySet a tab's selected entry.global:edit

Snapshots (3)

ToolWhat it doesGating
create_snapshotCreate a snapshot of captured state.snapshots:edit
list_snapshotsList snapshots.snapshots:view
download_snapshotDownload a snapshot's contents.snapshots:view

Push (2)

ToolWhat it doesGating
list_push_tokensList registered APNs push tokens.push:view
send_pushSend a push notification via APNs.push:edit · confirm-gated

Roles & RBAC (8)

Manage capability-based roles. All mutators are confirm-gated.

ToolWhat it doesGating
list_rolesList roles and their capabilities.users:view
create_roleCreate a custom role.users:edit · confirm-gated
update_roleUpdate a role's capabilities.users:edit · confirm-gated
delete_roleDelete a custom role.users:edit · confirm-gated
set_user_roleAssign a role to a user.users:edit · confirm-gated
list_usersAdmin roster of platform users — email, display name, role, providers, login source (the dashboard /users directory projection). Optional q searches the whole roster server-side (literal — LIKE wildcards escaped — before the page limit); total reports the full matching count.users:view
get_userLook up one user by email (exact, case-insensitive) — the direct answer for "is X an admin?". Returns the /users directory projection; found:false (not an error) when no account matches.users:view
admin_delete_userPERMANENTLY delete another user's account by user_id or email — the twin of the dashboard /users Remove user action (both run one shared core). Two scopes mirroring the dialog: the default keep leaves the person's devices + captured traffic in place, unowned; purge:true deletes those too, returning the exact devices_deleted. Refuses yourself, the last remaining admin, and a protected App Store reviewer/demo login. Idempotent (already_gone). Irreversible.users:edit · admin-only · confirm-gated

Demo program admin (6)

The demo-account lifecycle (mint → reset → regenerate → delete). Every mutator is admin-only + confirm-gated and re-asserts admin in-handler; everything is inert while the demo kill-switch is off.

ToolWhat it doesGating
list_demo_usersEnriched roster of every demo/trial account — role, template staleness, idle vs TTL, device count, turns today.users:view · admin-only
get_demo_statusThe demo program at a glance — kill-switch, template version, fleet cap, USD budget breaker, config knobs.users:view
create_demo_userMint a fresh demo account, seed the storyline, return a one-time sign-in link.users:edit · admin-only · confirm-gated
reset_demo_userReset/regenerate one demo account — full reseed or a surgical sections subset. Refuses a non-demo target.users:edit · admin-only · confirm-gated
regenerate_demo_contentRegenerate the shared demo content — catalog, fleet stream, or every demo account.users:edit · admin-only · confirm-gated
delete_demo_userPERMANENTLY delete ONE demo account by user_id or email. Fail-closed: only an account whose role is exactly demo — a real user, admin, trial or protected reviewer login is refused. Idempotent (already_gone).users:edit · admin-only · confirm-gated

Tenancy & white-label — served elsewhere

The white-label tenancy tools are not on this server. set_tenant_branding, add_tenant_admin, rename_tenant_slug, set_tenant_slug_aliases, set_tenant_domain and the rest of the tenant lifecycle are Busymate AI management tools, served only at busymate.ai/mcp. The separation is enforced in code, not by convention: a DevTools host refuses them as unknown tools, and a Busymate AI host refuses the DevTools surface the same way. This page listed two of them until docs 233; a call to either against mcp.busymate.dev was always rejected.

Busymate AI's own profile is a separate, larger surface, documented with that product.

Stats & status (2)

ToolWhat it doesGating
get_statsLive fleet stats — total_entries is the counters ledger (never an estimate) with its total_entries_as_of stamp; mixes + top-N describe the sealed 24 h rollup (rollup_sealed_to).stats:view
get_statusInfrastructure / service health.status:view

Tester (2)

The architecture-prove verdict board — read the latest test run + trigger a new one.

ToolWhat it doesGating
get_test_statusRead the latest tester run (the prove verdict + per-phase / per-suite results + recent history) or one run by id.tester:view
run_test_suiteTrigger a tester run (a tier / component); records a requested run that CI runs + reconciles. Confirm-gated.tester:run + confirm

Telegram linking (5)

Link a Busymate account to a Telegram identity for BusyBro chat.

ToolWhat it doesGating
get_telegram_linkGet your Telegram link.users:view
list_telegram_linksList Telegram links.users:view
link_telegramLink a Telegram account.users:edit
unlink_telegramUnlink your Telegram account.users:edit · confirm-gated
admin_unlink_telegramAdmin: unlink any account's Telegram link.users:edit · confirm-gated

TestFlight beta admin (13)

Manage TestFlight groups, testers, and invitations via the testflight-admin Edge Function. Reads need testflight:view; every write needs testflight:edit and is confirm-gated.

ToolWhat it doesGating
list_testflight_groupsList beta groups.testflight:view
list_testflight_testersList testers.testflight:view
get_testflight_testerGet one tester.testflight:view
list_testflight_invitationsList tester invitations.testflight:view
list_testflight_usersList App Store Connect users.testflight:view
list_testflight_user_invitationsList user invitations.testflight:view
invite_testflight_testerInvite a beta tester.testflight:edit · confirm-gated
delete_testflight_testerRemove a tester.testflight:edit · confirm-gated
add_testflight_tester_to_groupAdd a tester to a group.testflight:edit · confirm-gated
remove_testflight_tester_from_groupRemove a tester from a group.testflight:edit · confirm-gated
send_testflight_invitationSend a tester invitation.testflight:edit · confirm-gated
invite_testflight_userInvite an App Store Connect user.testflight:edit · confirm-gated
cancel_testflight_user_invitationCancel a user invitation.testflight:edit · confirm-gated

BusyBro memory & shares (5)

BusyBro's long-term memory and shared-conversation reader. The memory trio is owner-scoped — you only ever see and touch your own account's memories, the same store the dashboard and Telegram BusyBro read and write.

ToolWhat it doesGating
list_memoriesList or semantically search your own durable memories (facts / preferences / corrections / episodes).users:view
save_memorySave one durable memory about you / your work; near-duplicates merge, a correction overwrites.users:edit
forget_memoryDelete your memories — by id, by best semantic query match, or all.users:edit · confirm-gated
get_busybro_shareRead a shared BusyBro conversation by its /busybro/share/<id> id — title, context, full transcript — so you can continue it.public (by id)
delete_busybro_shareREVOKE one of YOUR OWN shared BusyBro conversations by id — the /busybro/share/<id> link stops resolving. Owner-scoped no-op on a foreign/stale id.users:edit · confirm-gated

BusyBro sessions (5)

Multi-session chat management — a "session" is one busybro_threads row (a resumable conversation), shared across the dashboard, iOS, and the bmc CLI. All five are owner-scoped — you only ever list / load / rename / delete your own sessions. context_key is the dashboard nav-binding find-or-create key (UUID-keyed, e.g. device:<uuid>); last_active_at is the sidebar ordering anchor.

ToolWhat it doesGating
list_busybro_sessionsList your chat sessions, newest-active first — {thread_id, title, context_key, updated_at, last_active_at, turns}.users:view
get_busybro_sessionLoad one of your sessions by id — title, context_key, and ordered turns. A session you don't own returns not-found.users:view
create_busybro_sessionCreate a new empty session; optionally seed a title + nav-binding context_key. Find-or-create: a colliding context_key returns the existing session.users:edit · confirm-gated
rename_busybro_sessionRename one of your sessions (owner-gated no-op on a foreign id).users:edit · confirm-gated
delete_busybro_sessionPermanently delete one of your sessions (owner-gated no-op on a foreign id).users:edit · confirm-gated

BusyBro attachments (1)

The read leg of the BusyBro attachments program (files / photos / videos uploaded to BusyBro chats — the durable rows in public.busybro_attachments, bytes in the private busybro-attachments bucket). Owner-scoped — you only ever see your own uploads, and there is no fleet arm.

ToolWhat it doesGating
list_busybro_attachmentsList your attachments, newest first — names + metadata only by default (id / kind / mime / size_bytes / filename / status / thread_id / created_at; the storage path and bytes are never returned). Filter by thread_id / kind / status. with_url:true adds a short-TTL (600 s) signed download url per ready row.users:view

BusyBro global (team) memory governance (10)

The shared, non-personal team-knowledge store and its review queue — see Global (team) memory and the shareable Connect to team memory page. The shared store has no user_id and is leak-proof on the recall path; contributor identity surfaces only through list_memory_contributors, never in what an LLM recalls. Proposals land pending (not recallable) until an operator approves them.

ToolWhat it doesGating
list_global_memoriesOperator browse of the team store across all statuses (pending / approved / rejected); filter by status / kind / origin / query. Returns each row's origin + contributor_count — never contributor ids.users:view
get_memory_statsMemory dashboard counters: personal vs global totals, the global pending / approved / rejected split, and distinct_contributors (count only).users:view
list_memory_contributorsOperator attribution lookup for ONE team fact — who proposed it (joined to email / display name from the leak-proof busybro_global_contributions ledger) + who approved it (approved_by). Strictly off the recall path.users:view
propose_global_memoryPropose one candidate team fact — third-person, subject-less, ≤ 600 chars, no PII / secrets. Writes a pending row (not recallable) + records you as a contributor.users:edit · confirm-gated
approve_global_memoryPromote a pending team fact to approved (recallable); stamps approved_by = you.users:edit · confirm-gated
reject_global_memoryReject a candidate (kept for audit / dedup, never recalled).users:edit · confirm-gated
update_global_memoryEdit a team fact's content / kind / importance; editing content flags it for re-embedding.users:edit · confirm-gated
admin_list_user_memoriesAdmin / support drill-down — read ONE user's personal memories by user_id (never feeds another user's recall).users:view
admin_forget_user_memoryAdmin / support — delete ONE of a user's personal memories by id (a correction, not the full GDPR wipe).users:edit · confirm-gated
gdpr_forget_userAdmin GDPR erasure — wipe ALL of a user's personal memory + drop their global contributions; the recompute trigger then deletes any team fact that loses its last contributor.users:edit · admin-only · confirm-gated

The recall store (busybro_global_memories) carries no identitymatch_global_memories returns no user_id. Per-person provenance lives only in the busybro_global_contributions side-table, read only by list_memory_contributors (operator-gated), for dedup, corroboration, stats, and erasure — never on the recall path. The dashboard review queue shows a candidate's contributor count, never identities.

External MCP servers & personal connectors (13)

BusyBro consumes other MCP servers as a client — a GLOBAL, admin-managed registry (busybro_mcp_servers, rows with owner_user_id IS NULL) plus personal connectors (#830): the same table with owner_user_id set, self-service for any signed-in user, owner-scoped end-to-end. Credentials are value-blind everywhere — a Bearer token is written to Vault and never read back; an OAuth connector's tokens (#899) are acquired by the server-side consent flow and never pass through any tool argument or response.

ToolWhat it doesGating
list_mcp_serversThe GLOBAL admin registry (metadata only; auth_secret_ref is a Vault NAME, never a value). Personal connectors never appear here.users:view
upsert_mcp_serverCreate / update a global server; mint_token:true mints a Bearer token value-blind into Vault and returns it exactly once.users:edit · admin-only · confirm-gated
delete_mcp_serverRemove a global server from the registry.users:edit · admin-only · confirm-gated
set_mcp_server_enabledThe global kill-switch — a disabled server is not advertised to BusyBro.users:edit · admin-only · confirm-gated
inspect_mcp_serverProbe ONE registered server by id — initialize + tools/list exactly as an LLM sees it (loopback for the system self-row). Read-only, fail-soft.users:view
list_my_mcp_connectorsYOUR OWN personal connectors — value-blind rows incl. conn_status (draft / connecting / authorizing / ready / needs_reauth / error).users:view
upsert_my_mcp_connectorCreate / update your own connector — auth_typenone / bearer / oauth (#899); URL SSRF-vetted; owner pinned server-side.users:edit · confirm-gated
delete_my_mcp_connectorRemove your own connector + its Vault credential.users:edit · confirm-gated
set_my_mcp_connector_enabledYour per-connector kill-switch.users:edit · confirm-gated
set_my_mcp_connector_secretSet the Bearer credential — written value-blind to Vault under a server-derived name, never read back.users:edit · confirm-gated
probe_mcp_connectorPaste-a-URL preview — SSRF-guarded initialize + tools/list handshake; nothing stored.users:view
connect_my_mcp_connectorStart (or restart) the OAuth consent flow for your own oauth connector (#899) — RFC 9728/8414 discovery → DCR where offered → PKCE S256 mandatory, every endpoint SSRF-vetted; returns a single-use authorize_url to open in a browser. Also the reconnect path when conn_status = needs_reauth.users:edit · confirm-gated
disconnect_my_mcp_connectorWipe your OAuth connector's stored tokens from Vault and flip it back to draft (the row + client registration are kept, so reconnect skips re-registering).users:edit · confirm-gated

An OAuth connector's access / refresh tokens live only in Vault under server-derived names — no tool, REST read, or log ever returns one. A dead grant (revoked / expired refresh) flips the connector to needs_reauth and BusyBro says so honestly at turn start ("needs to be reconnected") instead of silently advertising zero tools.

Stripe billing & admin (9)

Subscription + metered (captured_entries) billing (Phase 1 = Stripe TEST mode). The owner-scoped reads filter on the caller's identity; operators pass all_users:true for the fleet. The admin reads back the /billing-admin operator surface — all value-blind (get_stripe_config derives test/live mode from the publishable-key prefix and NEVER returns the secret key or webhook signing secret).

ToolWhat it doesGating
get_subscriptionThe caller's own Stripe subscription(s); operators pass all_users:true for the fleet.billing:view
list_invoicesThe caller's own invoices (amounts / hosted URL / period); all_users:true for the fleet.billing:view
get_usageThe caller's own metered usage rollup (captured_entries) by period; all_users:true for the fleet.billing:view
create_checkout_sessionOpen a Checkout (subscribe) or Customer Portal (manage) session; customer derived server-side from the caller.billing:view · confirm-gated
get_stripe_configValue-blind connection status: { mode, publishable_key } only (mode derived from the pub-key prefix; secret/whsec_ never read).billing:view
list_pricesThe Stripe Products' prices (value-blind projection: amounts, recurring/metered, lookup_key).billing:view
list_customersThe stripe_customers ↔ users mapping (fleet — the local mapping table, not the Stripe API).billing:view
get_webhook_eventsThe stripe_webhook_events idempotency ledger (fleet) — event_id / type / received.billing:view
get_billing_settingsThe billing_settings singleton (default price, quota/overage, dunning, mode, …).billing:view

Directory catalogue (9)

The BusyBro Directory — the operator-curated catalogue that merchandises skills, connectors, and plugins to the consumer BusyBro app. ONE model (busybro_directory_listings) backs all three collections; the item tables stay about function, the listing owns presentation. install_count is real installs only (RPC-incremented, never operator-editable — a fresh catalogue renders no counts); the Community and New badges derive from author_kind / published_at, so the stored badge taxonomy is exactly {verified, trending}.

ToolWhat it doesGating
list_directoryThe consumer read — PUBLISHED listings only, joined to each item's slug/label/description.users:view
list_directory_listingsThe operator read — every status incl. the pending moderation queue (empty in v1).directory:view
upsert_directory_listingCreate/update a listing's presentation (status, attribution, badges, rank, POPULAR-FOR featured, category).directory:edit · admin · confirm-gated
set_directory_listing_statusPublish / unpublish / moderate one listing; first publish stamps published_at.directory:edit · admin · confirm-gated
delete_directory_listingRemove a listing (the underlying item is untouched).directory:edit · admin · confirm-gated
install_skillInstall a PUBLISHED Directory skill into YOUR OWN set (sub-pinned own-data; the honest count bumps only on a genuinely new install).users:edit · confirm-gated
uninstall_skillRemove a Directory skill from YOUR OWN set — a DEFAULT-installed skill keeps an opt-out so it never silently returns (#1066).users:edit · confirm-gated
list_install_defaultsThe operator read of the default-installed configuration — platform tier + per-tenant overrides in one shape (#1066).directory:view
set_install_defaultSet/clear a default-installed row (platform or tenant tier); refuses runtime-unhonored collections + unpublished items (#1066).directory:edit · admin · confirm-gated

Legacy aliases (2)

Older names kept for backward compatibility. Prefer the generic db_* tools or the typed reads / writes above for new work.

ToolWhat it doesGating
list_entriesPaginated entries query.devices:view
get_entryFetch one entry by id / request_id.devices:view

Removed, not renamed. The blanket settings patchers get_settings, set_global_settings, set_device_settings and clear_device_settings were listed here until docs 233 and no longer exist on any host. Each was replaced by a first-class tool that writes exactly one thing without clobbering its neighbours — get_global_settings / get_device_settings to read, and set_inspect_all_requests, set_mitm_all_hosts, set_device_capture_enabled, set_device_autostart, the set_block_rules_* / set_breakpoint_patterns_* / set_scripts_* families and the per-scope env tools to write. A call to an old name is rejected as an unknown tool.


Total: 454 tools.

Every other tool — generated from the registry

The families above are written by hand and do not cover the whole surface. The other 203 are listed here, projected from the same tool registry the server itself dispatches from — its own name, opening line and permission gating — so this page cannot fall behind the product. A tool added to the surface without a row here fails the build.

Each cell is the tool's own opening line. The full text, arguments and JSON schema are what tools/list returns — ask the server when you need the exact contract.

Busymate AI's management tools are deliberately absent. They serve only on busymate.ai/mcp; a call to one against mcp.busymate.dev is rejected (STRICT NO-MIX).

Devices (22)

ToolWhat it doesGating
add_device_to_service_groupAdd a device to a service group — edits the delegation-boundary membership.devices:edit · admin-only · confirm-gated
clear_manual_egress_ipRemove a MANUAL egress-IP override from a device (#1432) — deletes the source='manual' row for ip; the proxy's automatic /allocate rows are never touched.devices:edit · admin-only · confirm-gated
delete_screen_share_recordingPermanently delete a saved screen-share recording (#1916) — removes the mp4 from the private screen-share-recordings bucket AND its row.devices:edit · confirm-gated
get_cdp_daemon_statusGet the LIVE status of the bmc DAEMON on a machine (running build/version, pid, uptime, autostart, serving, host pairing, managed CDP devices online/total, self-update state) — a structured superset of bmc status.devices:view
get_cdp_logsRead recent bmc DAEMON log lines from a machine (the remote backend of bmc log --ops) — the last N daemon-log lines, no shelling onto the machine.devices:view
get_device_egress_fail_postureRead a device's PAC egress FAIL POSTURE (#1657) — what the proxy does when the #76 PAC DIRECT fallback fires.devices:view
get_device_egress_statusRead a device's egress-IP set (#1432/#1721) — the CONNECT-source IPs the proxy allowlists plus any manual dev overrides.devices:view
get_device_healthTHE ONE QUERY (#1157/#1160): the latest capture-health projection for one device — engine armed/inert + WHY (engine_reason), the CA triple (loaded/key_present/trusted), ssl_domain_count + hash, config fetch, the decrypt-reason counters (flows_reasons), drop/gap detectors, app_build/ios_version.devices:view
get_screen_share_recordingFetch ONE saved screen-share recording (#1916) by id — the metadata row plus, with with_url:true, a short-TTL (600s) signed playback URL + download URL for the mp4 (H.264 — plays in any <video>/on iPhone).devices:view
list_device_audit_modesEvery device with audit-mode telemetry currently armed — expiry, level, categories, who armed it.devices:view
list_device_eventsThe MULTI-PRODUCER device telemetry event stream (#1160/#1208) — every capture-pipeline decision + state transition from iOS (capture.health, cert.state, config.applied, tunnel.lifecycle, the audit-tier kinds) AND from the PAC/proxy server (process.lifecycle, config.pac_serve/port_allocation, capture.entry/flush/drop …devices:view
list_device_service_groupsList the device↔service-group membership edges (public.device_service_groups) — the admin-controlled delegation boundary; resolves device_name + service_group_name.devices:view
list_screen_share_recordingsList saved screen-share RECORDINGS (#1916) — operator-captured mp4s of live share streams (the viewer's Record control), saved in public.screen_share_recordings.devices:view
remove_device_from_service_groupRemove a device from a service group — edits the delegation-boundary membership.devices:edit · admin-only · confirm-gated
request_screen_shareRequest a LIVE screen share from a paired CUSTOMER device for support (#1891) — asks the customer's Busymate DevTools app to prompt them to broadcast their screen.devices:edit · confirm-gated
restart_cdp_daemonRestart the bmc DAEMON on a machine (recycle the supervisor) — it re-pairs; running capture devices keep capturing (the successor re-adopts them, gap-free), only remote control briefly unavailable.devices:edit · confirm-gated
set_device_audit_modeArm/disarm the opt-in, TTL-expiring verbose AUDIT telemetry tier for one device (#1160) — per-flow MITM decisions, cert mints, config fetches, UI actions.devices:edit · confirm-gated
set_device_egress_fail_postureSet a device's PAC egress FAIL POSTURE (#1657) — posture ∈ open|closed|auto.devices:edit · confirm-gated
set_manual_egress_ipPin a MANUAL egress IP for a device (#1432/#1721) — a source='manual' override EXEMPT from the 10-most-recent proxy cap.devices:edit · admin-only · confirm-gated
stop_screen_shareEnd a live customer screen-share session (either side may stop) and signal the device to tear down its broadcast (#1891).devices:edit
transfer_device_ownershipADMIN: transfer a device to another account, atomically — freezes the prior owner's captured history, then moves ownership.devices:edit · admin-only · confirm-gated
update_cdp_daemonUpdate the bmc DAEMON on a machine (bmc update) — checks for a newer published bmc build and, if one is out, re-installs + recycles the daemon to load it.devices:edit · confirm-gated

Settings (7)

ToolWhat it doesGating
enroll_device_captureONE curated call that enrolls a device toward capturing DECRYPTED traffic — consolidates the 4-call, 2-confirm chain (set_device_connection_type → set_inspect_all_requests → set_mitm_all_hosts / SSL host list → vpn_on_device) into a single confirm.global:edit · confirm-gated
get_busybro_enabledRead the GLOBAL, PER-SURFACE "busybro enabled" feature flag (settings_global.data.busybroEnabled — an object { ios, dashboard, telegram, mcp }).global:view
get_inspect_all_requestsRead the "inspect all requests" capture-master toggle (settings_{global,device}.data.inspectAllRequests) — when ON, the proxy/iOS capture EVERY request.global:view
get_mitm_all_hostsRead the "MITM all hosts" decrypt-master toggle (settings_{global,device}.data.mitmAllHosts) — when ON, the proxy/iOS decrypt EVERY host.global:view
set_busybro_enabledSet ONE surface of the GLOBAL, PER-SURFACE "busybro enabled" flag (settings_global.data.busybroEnabled).global:edit · confirm-gated
set_inspect_all_requestsSet the "inspect all requests" capture-master toggle.global:edit
set_mitm_all_hostsSet the "MITM all hosts" decrypt-master toggle.global:edit · confirm-gated

Push (APNs) (1)

ToolWhat it doesGating
get_push_responseRead back a device's answer to an actionable push (#75) by correlation_id — { action: accept|reject|skip, context, responded_at, action_intent } or null if unanswered.push:view

Roles & capabilities (7)

ToolWhat it doesGating
create_access_grantGrant an assignable, non-admin role over a scope to a user (grant-monotonicity: never admin/grants_all; scope must exist; a user-scope may never target an admin/protected account; admin-only).users:edit · admin-only · confirm-gated
end_impersonationEnd (revoke) a "Login as" impersonation session by its jti — the one-click exit (#933 P1).owner-scoped
impersonate_userMint a secure READ-ONLY "Login as <user>" (impersonation) session for a target user_id, for testing/view-as/support (#933 P1).users:impersonate · confirm-gated
list_access_grantsList the scoped access-grants (public.access_grants): WHO holds WHICH assignable role over WHICH scope (service_group|device|user), with grantee_email + scope_label resolved.users:view
preview_effective_permissionsThe "what can <user> do, and WHY" read: role capabilities + held scoped grants (each with the grant's role capabilities).users:view
revoke_access_grantRevoke a scoped access-grant by id — immediate (DB-evaluated scope).users:edit · admin-only · confirm-gated
set_default_roleSet the configurable default role every new native signup receives (#474).users:edit · admin-only · confirm-gated

Audit trail (2)

ToolWhat it doesGating
get_audit_eventGet ONE audit-trail row in FULL by id (from list_audit_events) — including the redacted detail (old→new diffs) + statement_excerpt the list omits.audit:view
list_audit_eventsRead the platform audit trail (public.audit_log) — the who-did-what-when-how ledger across every surface.audit:view

Advisor Center (5)

ToolWhat it doesGating
fix_advisor_finding_issueFix → create a GitHub issue for a finding carrying MAXIMUM context (finding + audit events + deep links + suggested fix + repro + severity + actor/target/window).audit:view · admin-only · confirm-gated
fix_advisor_finding_todoFix → add a finding to YOUR /todo board (source='advisor') with the same max-context markdown in the notes.todos:edit · confirm-gated
get_advisor_findingGet ONE advisor finding in FULL by fingerprint — with its up-to-20 resolved (redacted) audit events, the scoped /audit deep link, and the /advisor permalink, so you can act with zero re-investigation.audit:view
list_advisor_findingsBrowse the Advisor Center findings (public.advisor_findings) — the advisor-monitor's deduped audit/health findings.audit:view
share_advisor_findingBuild a shareable package for ONE finding — the max-context markdown + flat LLM prose + the permalink (Finding · Analysis · Evidence · Deep links · Repro · Meta).audit:view

TestFlight (1)

ToolWhat it doesGating
get_app_store_statusLive App Store Connect version status for the iOS app: the approved (live) version + the one in preparation/rejected, each with version/state/build/what's-new/review/rejection (+ optional screenshots).testflight:view

Scripting engine (2)

ToolWhat it doesGating
get_script_engine_enabledRead the GLOBAL master "script engine enabled" flag (settings_global.data.scriptEngineEnabled) — the fleet kill-switch.scripts:view
set_script_engine_enabledSet the GLOBAL master "script engine enabled" flag.scripts:edit · admin-only · confirm-gated

Remote browser control (2)

ToolWhat it doesGating
browser_execute_page_toolRuns ONE tool the CURRENT PAGE declares via WebMCP (document.modelContext.executeTool) and returns its string result — the page's own action, discovered with browser_list_page_tools.devices:edit · confirm-gated
browser_list_page_toolsLists the tools the CURRENT PAGE declares via WebMCP (document.modelContext.getTools()) — not Busymate's own MCP tools; call it first on any page, because an empty MCP catalog is no evidence about what a page publishes.devices:view

Android farm (45)

ToolWhat it doesGating
acquire_device_controlTake EXCLUSIVE control of a farm phone (the per-phone control lock — 'In control by XXX', #1476).devices:edit · confirm-gated
admin_force_release_device_controlADMIN: force-free a farm phone's control lock — steal it from the current holder so the phone is free for anyone (#1476).devices:edit · admin-only · confirm-gated
cycle_farm_phone_portTARGETED PER-PORT USB POWER-CYCLE for ONE farm phone (#1761): cut + restore the USB power on EXACTLY that phone's own hub port via uhubctl, so a usbmux-dark phone (electrically connected but not enumerable) re-enumerates with ZERO collateral to the healthy rack — UNLIKE power_cycle_farm_hub which replugs EVERY phone.devices:edit · admin-only · confirm-gated
farm_device_logsTail ONE farm phone's SYSTEM LOGS (Android logcat / iOS syslog) — the live device logs, distinct from get_farm_logs (the daemon's own log).devices:view
farm_execute_page_toolRun ONE WebMCP tool a FARM PHONE's Chrome page registers (document.modelContext.executeTool) and return its string result.devices:edit · confirm-gated
farm_get_variablesRead the farm automation variables (global / per-device / merged effective view) from settings_{global,device}.data.farmVars.devices:view
farm_list_page_toolsList the WebMCP tools a FARM PHONE's Chrome page registers (document.modelContext.getTools()) — name, title, description, inputSchema, origin, annotations.devices:view
farm_mobile_double_tapDouble-tap ONE farm phone at pixel (x,y) via mobile-mcp mobile_double_tap_on_screen.devices:edit · confirm-gated
farm_mobile_get_crashGet one crash report's full content (by id) on a farm phone via mobile-mcp mobile_get_crash.devices:view
farm_mobile_get_orientationGet the current screen orientation of ONE farm phone via mobile-mcp mobile_get_orientation.devices:view
farm_mobile_get_screen_sizeGet the pixel screen size of ONE farm phone via mobile-mcp mobile_get_screen_size.devices:view
farm_mobile_install_appInstall an app (.ipa/.apk path on the farm host) onto ONE farm phone via mobile-mcp mobile_install_app.devices:edit · admin-only · confirm-gated
farm_mobile_install_from_appstoreSearch the App Store for a named app (or numeric id) and install it on ONE farm iPhone — the host resolves the id, opens the product page via per-device WDA, taps Get, and polls list_apps for real install evidence.devices:edit · confirm-gated
farm_mobile_launch_appLaunch an app (by bundle id) on ONE farm phone via mobile-mcp mobile_launch_app.devices:edit · confirm-gated
farm_mobile_list_appsList the installed apps on ONE farm phone (by child_uuid) via mobile-mcp mobile_list_apps.devices:view
farm_mobile_list_crashesList the crash reports on ONE farm phone via mobile-mcp mobile_list_crashes.devices:view
farm_mobile_list_devicesList every device the farm host's mobile-mcp sees (mobile_list_available_devices).devices:view
farm_mobile_list_elementsList the on-screen UI elements (text/label/coords) of ONE farm phone via mobile-mcp mobile_list_elements_on_screen.devices:view
farm_mobile_long_pressLong-press ONE farm phone at pixel (x,y) via mobile-mcp mobile_long_press_on_screen_at_coordinates (optional duration).devices:edit · confirm-gated
farm_mobile_open_urlOpen a URL on ONE farm phone via mobile-mcp mobile_open_url.devices:edit · confirm-gated
farm_mobile_press_buttonPress a hardware button (HOME/ENTER/VOLUME_*/BACK) on ONE farm phone via mobile-mcp mobile_press_button.devices:edit · confirm-gated
farm_mobile_screenshotCapture a PNG screenshot of ONE farm phone (by child_uuid), served PER-DEVICE on the host (go-ios).devices:view
farm_mobile_set_orientationSet the screen orientation (portrait|landscape) on ONE farm phone via mobile-mcp mobile_set_orientation.devices:edit · confirm-gated
farm_mobile_start_recordingStart a screen recording on ONE farm phone (.mp4 saved on the host) via mobile-mcp mobile_start_screen_recording.devices:edit · confirm-gated
farm_mobile_stop_recordingStop the active screen recording on ONE farm phone via mobile-mcp mobile_stop_screen_recording.devices:edit · confirm-gated
farm_mobile_swipeSwipe ONE farm phone (direction + optional x/y/distance) via mobile-mcp mobile_swipe_on_screen.devices:edit · confirm-gated
farm_mobile_tapTap ONE farm phone at pixel (x,y) via mobile-mcp mobile_click_on_screen_at_coordinates.devices:edit · confirm-gated
farm_mobile_terminate_appTerminate an app on ONE farm phone via mobile-mcp mobile_terminate_app.devices:edit · confirm-gated
farm_mobile_typeType text on ONE farm phone (optional submit) via mobile-mcp mobile_type_keys.devices:edit · confirm-gated
farm_mobile_uninstall_appUninstall an app (by bundle id) from ONE farm phone via mobile-mcp mobile_uninstall_app.devices:edit · admin-only · confirm-gated
farm_reap_tunnelsHOST-LEVEL FIX: reap ALL orphaned/squatting userspace go-ios tunnels on a farm host + free their stuck tunnel-info ports — the fix for the farm_restart_tunnel "didn't release port <N> in time (a local port conflict on the host, not the phone)" error.devices:edit · confirm-gated
farm_restart_tunnelSOFTWARE-FIRST FIX for a wedged control tunnel (control.tunnel_wedge): restart ONE farm iPhone's per-device userspace go-ios tunnel — the fix to try BEFORE unplug/replug.devices:edit · confirm-gated
farm_retry_phoneSOFTWARE-FIRST FIX: force an immediate reconcile + control-engine re-attempt on ONE farm phone, clearing its provision backoff/circuit-breaker — the fix to try BEFORE a physical replug.devices:edit · confirm-gated
farm_set_variablesWrite the farm automation variables (replace or merge) into settings_{global,device}.data.farmVars.devices:edit · confirm-gated
farm_start_mirrorADMIN — open a live touch/keyboard INPUT scrcpy mirror reverse-channel to the targeted farm phone (the full VPS relay).devices:edit · admin-only · confirm-gated
get_farm_daemon_statusGet the LIVE status of the bmfarm DAEMON on a farm host (running build/version, pid, uptime, autostart, mobile-mcp state, phones online/total, iOS-farm leg, self-update state) — a structured superset of bmfarm status.devices:view
get_farm_logsRead RETAINED farm-daemon log lines for a host (the remote backend of bmfarm logs; the same logs stream live to the dashboard).devices:view
get_farm_phone_healthTHE per-phone health answer (#1433): the exact status + WHY + what-to-expect + how-to-fix for ONE farm phone.devices:view
heal_farm_fleetFLEET RECOVERY (#1739) for a farm host that has lost phones to the usbmux-dark class — electrically connected but not enumerable by usbmux/lockdown, so no per-device ladder can reach them and the only remote lever is a hub power-cycle.devices:edit · confirm-gated
ios_rebootREMOTE-REBOOT one farm iPhone over the healthy lockdown, NO physical replug (#1739): the recovery for a Class-B wedge (a testmanagerd/instruments RemoteXPC wedge, or a control tunnel farm_restart_tunnel can't clear) where the userspace tunnel + lockdown stay healthy but the on-device services are wedged — a remote …devices:edit · confirm-gated
power_cycle_farm_hubLAST-RESORT REMOTE RECOVERY (#1668): power-cycle the office smart plug that powers a farm hub's USB phone rack — the recovery for the terminal control.needs_power_cycle (the auto-recovery ladder's last resort, a dead USB link no restart/reap/reboot clears).devices:edit · confirm-gated
release_device_controlGive up YOUR control of a farm phone (release the per-phone control lock you hold), freeing it immediately.devices:edit · confirm-gated
restart_farm_daemonRestart the bmfarm DAEMON on a farm host (bmfarm restart) — recycles the supervisor so it re-pairs; the physical phones keep running (gap-free for the fleet, only remote control briefly unavailable).devices:edit · confirm-gated
set_farm_mirror_transportSET how ONE farm iPhone's screen is live-mirrored (#1763): native (USB native H.264 via ReplayKit, default — lowest latency, keeps the phone charging + USB-controllable), wifi (native H.264 over the phone's LAN IP <phone_ip>:12005, for a flaky/absent USB link), or mjpeg (force the MJPEG@30 screenshot fallback).devices:edit · confirm-gated
update_farm_daemonUpdate the bmfarm DAEMON on a farm host (bmfarm update) — checks for a newer published farm build and, if one is out, re-installs + recycles the daemon to load it.devices:edit · confirm-gated

iOS farm (15)

ToolWhat it doesGating
ios_app_lifecycleLaunch | terminate an app on the targeted iOS farm phone(s) by bundle id.devices:edit · confirm-gated
ios_dump_uiOn-screen UI hierarchy (interactable elements: text / accessibility label / type + tap centre) of the targeted iOS farm phone(s).devices:view
ios_find_and_tapFind a UI element by visible text / accessibility label and tap it on the targeted iOS farm phone(s).devices:edit · confirm-gated
ios_inputSend an input event (tap/swipe/type/button; normalized 0..1 coords) to the targeted iOS farm phone(s).devices:edit · confirm-gated
ios_install_appADMIN — install an .ipa/.app (path on the iOS farm host) onto the targeted iOS farm phone(s).devices:edit · admin-only · confirm-gated
ios_list_appsList the installed apps (bundle id + name) on the targeted iOS farm phone(s).devices:view
ios_list_phonesLIVE go-ios/mobile-mcp view of the iPhones on an iOS farm host (udid/state/model/iOS version).devices:view
ios_open_urlOpen a URL (deep-link or web) on the targeted iOS farm phone(s).devices:edit · confirm-gated
ios_screenshotPNG screenshot of ONE iOS farm phone (by its child_uuid route-key).devices:view
ios_set_orientationSet the screen orientation (portrait|landscape) on the targeted iOS farm phone(s).devices:edit · confirm-gated
ios_start_mirrorOpen a LIVE screen mirror of ONE iOS farm phone (by child_uuid) through the VPS relay, WITH a touch/keyboard input reverse-channel.devices:edit · admin-only · confirm-gated
ios_uninstall_appADMIN — uninstall an app (by bundle id) from the targeted iOS farm phone(s).devices:edit · admin-only · confirm-gated
list_ios_phonesList the iOS farm fleet (ios-hosts + their child iPhones) from the devices table, RLS owner-scoped.devices:view
provision_ios_phoneCreate/update/remove a child ios iPhone device row via ios_provision_child (UUID-keyed, parented to the ios-host).devices:edit · confirm-gated
setup_ios_devicekitADMIN — trigger the devicekit XCUITest control-runner onboarding (build + re-sign + install via the farm's auto-resolved Apple/ASC team) on ONE already-paired iOS farm phone OVER THE WIRE (#1418), so an iOS-only farm Mac needs no terminal / re-pair.devices:edit · admin-only · confirm-gated

App secrets (Vault) (4)

ToolWhat it doesGating
create_app_secretCreate a new Vault-backed app secret.global:edit · admin-only · confirm-gated
delete_app_secretPermanently delete a Vault-backed app secret (drops the ciphertext + its metadata row).global:edit · admin-only · confirm-gated
list_app_secretsList the Vault-backed app secrets — NAMES + metadata ONLY (secret_class, hint, note, timestamps).global:view
update_app_secretRotate an existing Vault-backed secret's value (re-encrypted, same name).global:edit · admin-only · confirm-gated

Stripe admin (4)

ToolWhat it doesGating
cancel_subscriptionCancel a fleet Stripe subscription — immediately, or at_period_end.billing:edit · admin-only · confirm-gated
report_usage_nowManually KICK the metered-usage reporter NOW (the pg_cron job also runs hourly).billing:edit · admin-only · confirm-gated
set_billing_settingsMerge-patch the billing_settings singleton (Stripe-admin knobs) for the fleet — change one knob without clobbering the rest.billing:edit · admin-only · confirm-gated
set_default_priceSet the DEFAULT subscription price (billing_settings.default_price_id) the /billing Subscribe button uses; needs no redeploy.billing:edit · admin-only · confirm-gated

BusyBro settings (2)

ToolWhat it doesGating
get_busybro_settingsRead BusyBro's configurable brain knobs (busybro_settings singleton): provider / base_url / api_key_secret_name (Vault NAME, never the value) / model + per-surface surface_models / max_tokens / agent_max_iters / prompt_cache / web_search / memory_auto_save / persona_addendum / default_prefs / suggested_prompts.users:view
set_busybro_settingsMerge-patch BusyBro's brain config (change one knob without clobbering the rest): provider / base_url (SSRF-guarded) / api_key_secret_name (Vault NAME) / model + surface_models / max_tokens / loop limits / prompt_cache / etc. Applies on the next turn.users:edit · admin-only · confirm-gated

BusyBro usage & cost (1)

ToolWhat it doesGating
get_busybro_usageBusyBro usage + cost analytics: per-response token usage with computed USD cost, totals + breakdown by surface/user/model/day, prompt-cache savings, projected monthly spend.users:view

To-dos (6)

ToolWhat it doesGating
complete_todoCheck off ONE of YOUR to-dos — shortcut for status→done (done_at stamped).todos:edit
create_todoAdd a to-do. title required; optional notes / status / priority / tags[] / due_at / position / source.todos:edit
delete_todoDelete ONE of YOUR to-dos (permanent).todos:edit · confirm-gated
get_todoGet ONE of YOUR to-dos by id (full row).todos:view
list_todosList YOUR to-dos (public.todos) — the shared "what to do / what's done" list.todos:view
update_todoUpdate ONE of YOUR to-dos — any field (title / notes / status / priority / tags / due_at / position / source).todos:edit

Notifications (7)

ToolWhat it doesGating
create_notificationLeave YOURSELF a durable notification (remind/flag-me-later) — SELF-NOTIFY ONLY (owner pinned server-side).users:edit · confirm-gated
get_notification_prefsRead YOUR notification prefs — the merged per-type {default, override, effective} map + muted_until.users:view
list_notificationsList YOUR in-app notifications (public.notifications) — the advisor-monitor + platform alerts on the bell.users:view
list_web_push_subscriptionsList YOUR registered browser/OS Web-Push endpoints (web_push_subscriptions) — where you receive SYSTEM notifications.users:view
mark_notification_readMark YOUR notification(s) read or archived — id, or all:true for mark-all; status:'archived' to archive.users:edit
notify_usersADMIN: send ONE in-app notice to a LIST of OTHER accounts — the only path that notifies another user.users:edit · admin-only · confirm-gated
set_notification_prefsPatch YOUR notification prefs — a { type: bool|null } override map (null clears) + mute-all (mute_hours / muted_until / unmute).users:edit · confirm-gated

BusyBro agents (4)

ToolWhat it doesGating
delete_agentDelete a BusyBro agent by id (referencing service groups are SET NULL).agents:edit · admin-only · confirm-gated
get_agentGet one BusyBro agent (full detail incl.users:view
list_agentsList BusyBro specialist agents (reusable {label,instructions,tool_allowlist,model} bundles run_task delegates to + service groups reference).users:view
upsert_agentCreate (omit id) or update (set id) a BusyBro agent.agents:edit · admin-only · confirm-gated

BusyBro skills (14)

ToolWhat it doesGating
delete_skillDelete a BusyBro skill by id.skills:edit · admin-only · confirm-gated
delete_skill_fileDelete a skill bundled file by id (same writability as upsert_skill_file).skills:edit · admin-only · confirm-gated
draft_skillPURE no-write skill-draft presenter (#930 — Create-with-BusyBro): validates + echoes a drafted skill (shared slug/description/when-to-use rules, findings never thrown) with the reconstructed SKILL.md and can_save; renders the skill-draft review widget whose Save issues the audited upsert_skill (human-click).users:view
edit_repo_skillReplace one repo SKILL.md's full content and COMMIT it to git (main) via the GitHub Contents API.skills:edit · admin-only · confirm-gated
get_skillGet one BusyBro skill (full detail incl.users:view
get_skill_fileONE skill bundled file WITH content, by id OR (skill_id + path).users:view
list_repo_skillsList the repo's portable SKILL.md corpus (the agentskills.io skills committed in git — the repo's committed skill folders), the SAME set the Skills Hub reads.skills:view
list_skill_filesList a skill's BUNDLED FILES (scripts/references/assets) — metadata only (id/path/kind/size_bytes), the progressive-disclosure corpus the brain reads.users:view
list_skillsList BusyBro skills (loadable instruction+tool bundles loaded mid-chat via load_skill) — the team catalog + your own.users:view
remove_repo_skillDelete a repo SKILL.md from the corpus and COMMIT the removal to git via the GitHub Contents API.skills:edit · admin-only · confirm-gated
set_repo_skill_enabledFlip a repo SKILL.md's enabled frontmatter (the Skills Hub v2 toggle — false ⇒ listed-but-inactive) and COMMIT it to git.skills:edit · admin-only · confirm-gated
set_skill_enabledEnable/disable a BusyBro skill by id (a disabled skill stays but never loads).skills:edit · admin-only · confirm-gated
upsert_skillCreate (omit id) or update (set id) a BusyBro skill.skills:edit · admin-only · confirm-gated
upsert_skill_fileCreate/update a skill bundled file.skills:edit · admin-only · confirm-gated

BusyBro memory imports (4)

ToolWhat it doesGating
delete_importDelete a BusyBro memory-import job AND every global fact it produced (bulk undo).users:edit · confirm-gated
get_importGet one BusyBro memory-import job by id — full progress + status + error.users:view
import_resourceQueue a BusyBro memory-import job (trains the TEAM store): a GitHub/GitLab repo (private via a write-only credential_ref PAT) or an uploaded file.users:edit · admin-only · confirm-gated
list_importsList BusyBro memory-import jobs (newest first) with live progress counters (files/chunks/facts approved/pending/duplicate, status).users:view

Tester (6)

ToolWhat it doesGating
cancel_test_runCancel an in-flight dispatch run (verdict-less, unfinished).tester:run · confirm-gated
get_test_coverageRead the feature→tier→test coverage inventory (the DB snapshot of the committed coverage map, materialized by CI) with covered/partial/gap totals.tester:view
get_test_path_coverageRead exhaustive path-coverage (the DB snapshot of the path-coverage audit over the committed path-coverage audit) — pathsEnumerated/Covered/Gap/HappyOnly + criticalPathsGap.tester:view
get_test_suite_historyPer-suite history for flake/trend analysis — the last N runs of ONE suite (run_id, verdict, tier, source, status, duration, flaky, started_at), newest first.tester:view
list_test_suitesList the canonical tester suite registry — every registered suite with { id, component, suite, tier, phase, critical, expand, description }.tester:view
rerun_test_suiteRe-dispatch a prior run — filter='all' repeats its tier+component; filter='failed' re-runs only the components whose suites failed.tester:run · confirm-gated

WIP board (4)

ToolWhat it doesGating
wip_clear_donePrune terminal (done/failed) WIP-board rows older than older_than_minutes (default 1440 = 24h).users:edit · admin-only · confirm-gated
wip_listRead the FULL PLAN shaped to render the WIP board: program → phase → task grouped, with per-phase + per-program rollups (done/total + a derived % complete + per-status counts + a derived state) AND the live 'who's on what now' slice.users:view
wip_task_historyRead ONE WIP-board task's append-only progress TIMELINE — how it progressed over time + which agents/skills worked it.users:view
wip_updateUPSERT one WIP-board task by task_key — the live ingest the boss + agents call as they work to record WHO is on WHAT, in WHICH phase of WHICH program (program → phase → task).users:edit

Account (4)

ToolWhat it doesGating
get_my_busybro_settingsYOUR OWN per-user BusyBro settings (busybro_user_settings) — the Memory-pane toggles memory_generate ("Generate memory from chats", default on) + chat_search ("Search and reference chats", default off), your Directory role pick, and the data bag.owner-scoped
report_issueOne-tap issue reporter (#586, the dashboard ⌘⇧1 dialog's MCP twin) — file a bug/problem as a durable public.issue_reports row (INSERT-FIRST: a GitHub outage never loses it) + an auto-created GitHub issue (labels user-report + dashboard, repo hard-pinned).owner-scoped · confirm-gated
set_my_busybro_settingsChange YOUR OWN per-user BusyBro settings — a partial patch of memory_generate / chat_search / directory_role (≤80 chars; '' clears) / data.owner-scoped
set_my_preferred_nameSet how BusyBro should ADDRESS you — the "What should BusyBro call you?" nickname (≤60 chars); '' or whitespace clears it (falls back to your display name).owner-scoped

Plugins (7)

ToolWhat it doesGating
delete_pluginDelete a plugin catalog row — cascades installs + every user's materialised rows (Vault cleanup on cascade — M1) and removes its Directory listings.skills:edit · admin-only · confirm-gated
get_pluginONE plugin by id or slug INCLUDING its full manifest — the itemised list of every skill + connector template an install would materialise as YOUR OWN rows (the itemised-consent source).users:view
install_pluginInstall a PUBLISHED plugin — atomically materialises its manifest as YOUR OWN skill/connector rows tagged source_plugin_id, exclusively through the shared validation cores (SSRF vet, namespace/transport/auth guards — H2).users:edit · confirm-gated
list_pluginsList the plugin catalog — admin-authored bundles of skills + connectors.users:view
set_plugin_install_enabledToggle YOUR plugin install on/off (own-data, confirm-free — the set_my_mcp_connector_enabled class).users:edit
uninstall_pluginUninstall a plugin YOU installed — deletes YOUR materialised rows (the Vault-cleanup trigger covers connector credentials — M1) + the install row; decrements install_count.users:edit · confirm-gated
upsert_pluginCreate/update a plugin catalog row — THE sole manifest writer (inline defs are admin-authored only, the v1 trust boundary).skills:edit · admin-only · confirm-gated

Federation clients (3)

ToolWhat it doesGating
delete_federation_clientRemove a federation client from the registry (cascades its issued federation_codes).federation:edit · admin-only · confirm-gated
list_federation_clientsList the registered federation clients (metadata only — client_id, client_name, verify_mode, directus_base_url, hmac_secret_ref the Vault NAME never the value, OIDC fields, capped_role, rate-limit knobs, enabled).federation:view
upsert_federation_clientCreate/update a federation client (the broker's trust anchor).federation:edit · admin-only · confirm-gated

MCP servers (1)

ToolWhat it doesGating
set_my_connector_oauth_client_secretSet the NON-DCR OAuth CLIENT SECRET for YOUR OWN oauth connector by id — the value is written value-blind to Vault under MCP_CONN_<id>_OAUTHCLIENT and is NEVER read back (the set_my_mcp_connector_secret discipline).users:edit · confirm-gated

Localization (i18n) (23)

ToolWhat it doesGating
approve_i18n_machine_rowsApprove machine rows → translated/human-reviewed (identity → per-row same_ok) or reject → needs_review.i18n:edit · confirm-gated
delete_i18n_keyRetire a canonical key + cascade-delete its translations across every locale.i18n:edit · admin-only · confirm-gated
delete_i18n_messageDelete ONE translation value by (namespace,key,locale).i18n:edit · confirm-gated
delete_localeDelete a locale + its messages (never the default).i18n:edit · admin-only · confirm-gated
get_i18n_catalogAssemble the sparse translated catalog for a locale + namespaces ({ ns:{ key:value } }).i18n:view
get_i18n_manifestThe published-catalog manifest (version/etag map).i18n:view
get_i18n_missing_reportThe missing-key anti-join for a locale (non-translated keys).i18n:view
get_i18n_settingsRead the i18n singleton knobs (default_locale, publish_debounce_ms, pseudo_locale, allow_machine_seed).i18n:view
get_i18n_statsPer-locale coverage stats (translated/machine/needs_review + coverage_pct).i18n:view
import_i18nBulk-import { key: value } for one (locale,namespace) from an external translator round-trip.i18n:edit · admin-only · confirm-gated
list_i18n_keysList the canonical key registry for a namespace: key + description + declared ICU placeholders.i18n:view
list_i18n_messagesList translation values (key×locale): value (raw ICU), status (translated|machine|needs_review|missing).i18n:view
list_i18n_namespacesList string-group namespaces (ios.common, ios.setup, …) with platforms[].i18n:view
list_localesList the i18n locale registry (BCP-47) — code/native/enabled/rtl/fallback/default/tier.i18n:view
machine_translate_i18nREAL machine translation (#2313): cheapest model that meets the requirement suite (ICU/placeholders/glossary/length/script + same-model back-translation), per-key escalation Haiku→Sonnet, spend-capped; writes status='machine' with provenance, never over a human row; {key,en} seeds register inline keys first; dry_run …i18n:edit · admin-only · confirm-gated
publish_i18n_catalogMaterialize the store into immutable catalog JSON on the public i18n bucket + rebuild manifest.json + bust i18n:catalog (invokes the i18n-publish Edge fn).i18n:edit · admin-only · confirm-gated
review_i18n_machine_rowsThe reviewer's queue: machine rows with base value, back-translation, similarity, checks, model, cost (paged).i18n:view
set_default_localeSet the default/base locale (atomic clear-then-set).i18n:edit · admin-only · confirm-gated
set_i18n_settingsMerge the i18n singleton knobs.i18n:edit · admin-only · confirm-gated
upsert_i18n_keyCreate/update a canonical key + its declared ICU placeholders.i18n:edit · confirm-gated
upsert_i18n_messageCreate/update ONE translation value (raw ICU).i18n:edit · confirm-gated
upsert_i18n_namespaceCreate/update a namespace (surface/platforms/enabled).i18n:edit · admin-only · confirm-gated
upsert_localeAdd / enable / configure a locale (rtl/fallback/tier).i18n:edit · admin-only · confirm-gated
Ask your mate