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.
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.
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.
Tool
What it does
Gating
db_select
Generic select against an allowlisted table (columns, filters, order, limit, offset).
List 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_connection
PROVE 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_device
Fetch one device by uuid or name.
devices:view
get_device_status
Live 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).
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.
Tool
What it does
Gating
set_device_cdp_control
Turn 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_enabled
Turn 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_autostart
Turn 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_targets
List the open browser targets / tabs the device controls.
devices:edit
browser_open
Open a URL in the controlled Chrome.
devices:edit
browser_eval
Evaluate JavaScript in a target (resolves {{VAR}} env refs server-side).
devices:edit
browser_screenshot
Capture a screenshot of a target.
devices:edit
browser_snapshot
Capture an accessibility / DOM snapshot of the page.
devices:edit
browser_cdp
Send a raw Chrome DevTools Protocol command (arbitrary-code power).
Lifecycle of named CDP "devices" (Chrome instances on a bmc machine), plus hot-updating the daemon itself. The mutators are confirm-gated.
Tool
What it does
Gating
list_cdp_instances
List 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_device
Start 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_device
Stop a named CDP device.
devices:edit · confirm-gated
create_device
Provision a new named CDP device (fresh port + profile, pairs its JWT).
devices:edit · confirm-gated
update_cdp_host
Hot-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_mode
Persist 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_window
Raise 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".
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.
Tool
What it does
Gating
list_browser_profiles
List custom browser profiles (slug, display name, binaries, default flags, flag catalog, CDP notes).
devices:view
get_browser_profile
Get one custom profile by slug or id — full detail.
devices:view
upsert_browser_profile
Create or update a custom profile (matched by slug); reserved built-in slugs are rejected.
The Android farm (#148) pairs one HOST device per Mac Mini (platform: android-host) and models each connected phone as its own UUID-keyed childandroid 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.
Tool
What it does
Gating
provision_farm_phone
Create / 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_devices
List the farm fleet (hosts + their child phones) from the devices table (no host dispatch).
devices:view
farm_list_phones
Live adb view of the phones on a host (serial / state / model / Android / battery).
devices:view · opt-in ON
farm_capture_status
Read how farm capture is wired (the shared hardened proxy-server path).
devices:view · opt-in ON
farm_screenshot
PNG screenshot of ONE phone (by child_uuid).
devices:view · opt-in ON
farm_dump_ui
On-screen UI hierarchy (interactable nodes) of the targeted phone(s).
devices:view · opt-in ON
farm_list_automations
List the host's available automation scripts.
devices:view · opt-in ON
farm_list_recordings
List the host's saved input recordings.
devices:view · opt-in ON
farm_list_schedules
List the host's active scheduled jobs.
devices:view · opt-in ON
farm_find_and_tap
Find a UI element by text / resource-id and tap it on the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_set_setting
settings put (system | secure | global) on the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_set_wifi
Enable / disable WiFi on the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_app_lifecycle
Start | stop | clear an app on the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_grant_permission
Grant a runtime permission to an app on the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_uninstall_app
Uninstall a package from the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_pull_file
Pull a file from the targeted phone(s) to the host.
devices:edit · opt-in ON · confirm-gated
farm_run_automation
Run an automation script (by id) on the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_replay_recording
Replay a saved recording on the targeted phone(s).
devices:edit · opt-in ON · confirm-gated
farm_schedule
Schedule an automation / recording on an interval.
devices:edit · opt-in ON · confirm-gated
farm_remove_schedule
Remove a scheduled job by id.
devices:edit · opt-in ON · confirm-gated
farm_run_shell
ADMIN — run an arbitrary adb shell command on the targeted phone(s).
devices:edit · admin · opt-in ON · confirm-gated
farm_run_adb
ADMIN — run a raw adb subcommand on the targeted phone(s).
devices:edit · admin · opt-in ON · confirm-gated
farm_install_app
ADMIN — install an APK (host path) onto the targeted phone(s).
devices:edit · admin · opt-in ON · confirm-gated
farm_input
ADMIN — broadcast a tap / swipe / key / text input event (group control).
devices:edit · admin · opt-in ON · confirm-gated
farm_set_proxy
ADMIN — set / clear the global HTTP proxy (egress redirect).
devices:edit · admin · opt-in ON · confirm-gated
farm_set_airplane
ADMIN — toggle airplane mode.
devices:edit · admin · opt-in ON · confirm-gated
farm_reboot
ADMIN — reboot the targeted phone(s).
devices:edit · admin · opt-in ON · confirm-gated
farm_push_file
ADMIN — push a file from the host onto the targeted phone(s).
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.
Tool
What it does
Gating
farm_component_action
Run ONE lifecycle action — install | update | reinstall | recheck — on ONE component of ONE farm device.
devices:edit · opt-in ON · confirm-gated
update_farm_component
Update ONE outdated component on ONE farm device to its latest published version.
devices:edit · opt-in ON · confirm-gated
update_farm_fleet
Bulk sweep: update EVERY outdated component on EVERY device under the host.
devices:edit · opt-in ON · confirm-gated
onboard_farm_fleet
Bulk 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).
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.
Argument
Type
What 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.
build
string
Re-sign a specific cachedCFBundleVersion (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.
launch
boolean
Launch 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.
Sign 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:
identity
Platforms
How it signs in
farm (default)
iOS + Android
Value-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 · demo
Android
A 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
/farmInfo tab's App sign-in card; see
the pre-TestFlight proof install.
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.
Newest 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_count
Count entries matching a filter.
devices:view
list_wipe_jobs
The 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_freshness
The 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_traffic
Bounded, 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_requests
Deep-inspect FULL request + response headers and bodies for ONE host (requires a full hostname with a dot).
devices:view
export_har
Export matching entries as a HAR 1.2 log (scope by device / host / date).
devices:view
tag_entry
Add a tag to an entry.
tags:edit
untag_entry
Remove a tag from an entry.
tags:edit
wipe_entries
Delete 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_entries
Targeted 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.
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.)
Tool
What it does
Gating
list_api_projects
List active projects, scope, latest revision, and requested/measured schedule health; optionally include archives.
authenticated owner
create_api_project
Create a host/device/time-scoped project and optionally infer revision 1.
authenticated owner + confirm
update_api_project
Change name or advanced scope and immediately rebuild a revision.
authenticated owner + confirm
set_api_project_archived
Archive/restore a project; archive disables its schedule.
authenticated owner + confirm
delete_api_project
Permanently cascade-delete the project store (published artifacts stay independent).
authenticated owner + confirm
set_api_project_schedule
Enable/pause refreshes, set requested cadence, and opt into drift notifications.
authenticated owner + confirm
refresh_api_project
Re-scan the scope, apply reviews, append an immutable revision, and record drift.
authenticated owner + confirm
get_api_revision
Read a revision's graph, OpenAPI, evidence map, stats, and source window.
authenticated owner
list_api_candidates
List weak path-template candidates that require review.
authenticated owner
review_api_candidate
Accept a template, keep literal paths, or exclude them; refreshes by default.
authenticated owner + confirm
export_api_spec
Export deterministic OpenAPI JSON or YAML with no captured values/examples.
authenticated owner
generate_api_asset
Generate a TypeScript SDK, placeholder Node mock, or safe-default Vitest contract suite.
authenticated owner
list_api_drift
List operation, status, and structural schema changes between revisions.
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[].
Tool
What it does
Gating
list_service_groups
List service groups, each with its primary_agent + ordered linked agents[].
services:view
get_service_group
Fetch one service group, with its primary_agent + ordered linked agents[].
services:view
upsert_service_group
Create or update a service group.
services:edit
delete_service_group
Delete a service group.
services:edit
set_service_group_agents
Full-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.
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 scope — global 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.
Tool
What it does
Gating
get_global_settings
Read settings_global.data.
global:view
get_device_settings
Read a device's settings row.
devices:view
get_env_global
List the GLOBAL env vars (values masked).
global:view
get_env_device
List ONE device's env vars (values masked).
devices:view · owner-scoped
set_env_var_global
Set one GLOBAL env var (value never echoed).
global:edit
set_env_var_device
Set one env var on ONE device (value never echoed).
devices:edit · owner-scoped
delete_env_var_global
Remove one env var from the GLOBAL store.
global:edit
delete_env_var_device
Remove one env var from ONE device's store.
devices:edit · owner-scoped
import_env_global
Bulk-import vars from .env text into the GLOBAL store (merge or replace).
global:edit
import_env_device
Bulk-import vars from .env text into ONE device's store (merge or replace).
devices:edit · owner-scoped
set_breakpoint_patterns_global
Set the global breakpoint patterns per direction — requestPatterns (outbound) / responsePatterns (inbound); patterns is a legacy alias for the request direction.
global:edit
set_breakpoint_patterns_device
Set a device's breakpoint patterns per direction — requestPatterns / responsePatterns; patterns is a legacy alias for the request direction.
devices:edit
set_breakpoint_patterns_user
Set 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_service
Set 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_type
Set the global default connection type.
global:edit
set_user_connection_type
Set the per-user connection type.
users:edit
set_my_display_name
Change 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_account
YOUR 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_account
PERMANENTLY 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_reports
List 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.
Realtime control directed at the proxy-server / device handling a paused request.
Tool
What it does
Gating
resend_request
Replay a captured request (resolves {{VAR}} env refs server-side).
devices:edit · confirm-gated
breakpoint_continue
Release a request paused at a breakpoint.
devices:edit · confirm-gated
list_breakpoint_events
List 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.
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.
Read the GLOBAL block rules — the fleet-wide tier that applies to every device.
global:view
get_block_rules_device
Read 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_global
Replace 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_user
Replace 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_service
Replace 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_device
Replace a device's per-device block rules (full list, each rule may carry maxRuns); additive on top of the global ++ user lists.
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? }.
Tool
What it does
Gating
get_scripts_global
Read the GLOBAL scripts — the fleet-wide tier — plus engine_enabled (the master kill-switch).
scripts:view
get_scripts_device
Read 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_global
Replace the global scripts (full list); merged into settings_global.data without clobbering other keys.
scripts:edit · admin-only · confirm-gated
set_scripts_user
Replace 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_service
Replace 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_device
Replace a device's per-device scripts (full list); additive on top of the global ++ user lists.
scripts:edit · admin-only · confirm-gated
dry_run_script
Statically 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.
Manage capability-based roles. All mutators are confirm-gated.
Tool
What it does
Gating
list_roles
List roles and their capabilities.
users:view
create_role
Create a custom role.
users:edit · confirm-gated
update_role
Update a role's capabilities.
users:edit · confirm-gated
delete_role
Delete a custom role.
users:edit · confirm-gated
set_user_role
Assign a role to a user.
users:edit · confirm-gated
list_users
Admin 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_user
Look 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_user
PERMANENTLY 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.
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.
Tool
What it does
Gating
list_demo_users
Enriched roster of every demo/trial account — role, template staleness, idle vs TTL, device count, turns today.
users:view · admin-only
get_demo_status
The demo program at a glance — kill-switch, template version, fleet cap, USD budget breaker, config knobs.
users:view
create_demo_user
Mint a fresh demo account, seed the storyline, return a one-time sign-in link.
users:edit · admin-only · confirm-gated
reset_demo_user
Reset/regenerate one demo account — full reseed or a surgical sections subset. Refuses a non-demo target.
users:edit · admin-only · confirm-gated
regenerate_demo_content
Regenerate the shared demo content — catalog, fleet stream, or every demo account.
users:edit · admin-only · confirm-gated
delete_demo_user
PERMANENTLY 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).
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.
Live 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).
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.
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.
Tool
What it does
Gating
list_memories
List or semantically search your own durable memories (facts / preferences / corrections / episodes).
users:view
save_memory
Save one durable memory about you / your work; near-duplicates merge, a correction overwrites.
users:edit
forget_memory
Delete your memories — by id, by best semantic query match, or all.
users:edit · confirm-gated
get_busybro_share
Read a shared BusyBro conversation by its /busybro/share/<id> id — title, context, full transcript — so you can continue it.
public (by id)
delete_busybro_share
REVOKE 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.
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.
Tool
What it does
Gating
list_busybro_sessions
List your chat sessions, newest-active first — {thread_id, title, context_key, updated_at, last_active_at, turns}.
users:view
get_busybro_session
Load 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_session
Create 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_session
Rename one of your sessions (owner-gated no-op on a foreign id).
users:edit · confirm-gated
delete_busybro_session
Permanently delete one of your sessions (owner-gated no-op on a foreign id).
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.
Tool
What it does
Gating
list_busybro_attachments
List 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.
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.
Tool
What it does
Gating
list_global_memories
Operator 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_stats
Memory dashboard counters: personal vs global totals, the global pending / approved / rejected split, and distinct_contributors (count only).
users:view
list_memory_contributors
Operator 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_memory
Propose 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_memory
Promote a pending team fact to approved (recallable); stamps approved_by = you.
users:edit · confirm-gated
reject_global_memory
Reject a candidate (kept for audit / dedup, never recalled).
users:edit · confirm-gated
update_global_memory
Edit a team fact's content / kind / importance; editing content flags it for re-embedding.
users:edit · confirm-gated
admin_list_user_memories
Admin / support drill-down — read ONE user's personal memories by user_id (never feeds another user's recall).
users:view
admin_forget_user_memory
Admin / support — delete ONE of a user's personal memories by id (a correction, not the full GDPR wipe).
users:edit · confirm-gated
gdpr_forget_user
Admin 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 identity — match_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.
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.
Tool
What it does
Gating
list_mcp_servers
The GLOBAL admin registry (metadata only; auth_secret_ref is a Vault NAME, never a value). Personal connectors never appear here.
users:view
upsert_mcp_server
Create / 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_server
Remove a global server from the registry.
users:edit · admin-only · confirm-gated
set_mcp_server_enabled
The global kill-switch — a disabled server is not advertised to BusyBro.
users:edit · admin-only · confirm-gated
inspect_mcp_server
Probe 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_connectors
YOUR OWN personal connectors — value-blind rows incl. conn_status (draft / connecting / authorizing / ready / needs_reauth / error).
users:view
upsert_my_mcp_connector
Create / update your own connector — auth_type ∈ none / bearer / oauth (#899); URL SSRF-vetted; owner pinned server-side.
users:edit · confirm-gated
delete_my_mcp_connector
Remove your own connector + its Vault credential.
users:edit · confirm-gated
set_my_mcp_connector_enabled
Your per-connector kill-switch.
users:edit · confirm-gated
set_my_mcp_connector_secret
Set the Bearer credential — written value-blind to Vault under a server-derived name, never read back.
Start (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_connector
Wipe 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.
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).
Tool
What it does
Gating
get_subscription
The caller's own Stripe subscription(s); operators pass all_users:true for the fleet.
billing:view
list_invoices
The caller's own invoices (amounts / hosted URL / period); all_users:true for the fleet.
billing:view
get_usage
The caller's own metered usage rollup (captured_entries) by period; all_users:true for the fleet.
billing:view
create_checkout_session
Open a Checkout (subscribe) or Customer Portal (manage) session; customer derived server-side from the caller.
billing:view · confirm-gated
get_stripe_config
Value-blind connection status: { mode, publishable_key } only (mode derived from the pub-key prefix; secret/whsec_ never read).
billing:view
list_prices
The Stripe Products' prices (value-blind projection: amounts, recurring/metered, lookup_key).
billing:view
list_customers
The stripe_customers ↔ users mapping (fleet — the local mapping table, not the Stripe API).
billing:view
get_webhook_events
The stripe_webhook_events idempotency ledger (fleet) — event_id / type / received.
billing:view
get_billing_settings
The billing_settings singleton (default price, quota/overage, dunning, mode, …).
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}.
Tool
What it does
Gating
list_directory
The consumer read — PUBLISHED listings only, joined to each item's slug/label/description.
users:view
list_directory_listings
The operator read — every status incl. the pending moderation queue (empty in v1).
Older names kept for backward compatibility. Prefer the generic db_* tools or the typed reads / writes above for new work.
Tool
What it does
Gating
list_entries
Paginated entries query.
devices:view
get_entry
Fetch 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.
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).
Add a device to a service group — edits the delegation-boundary membership.
devices:edit · admin-only · confirm-gated
clear_manual_egress_ip
Remove 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_recording
Permanently 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_status
Get 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_logs
Read 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_posture
Read a device's PAC egress FAIL POSTURE (#1657) — what the proxy does when the #76 PAC DIRECT fallback fires.
devices:view
get_device_egress_status
Read a device's egress-IP set (#1432/#1721) — the CONNECT-source IPs the proxy allowlists plus any manual dev overrides.
devices:view
get_device_health
THE 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_recording
Fetch 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_modes
Every device with audit-mode telemetry currently armed — expiry, level, categories, who armed it.
devices:view
list_device_events
The 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_groups
List 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_recordings
List 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_group
Remove a device from a service group — edits the delegation-boundary membership.
devices:edit · admin-only · confirm-gated
request_screen_share
Request 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_daemon
Restart 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_mode
Arm/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_posture
Set a device's PAC egress FAIL POSTURE (#1657) — posture ∈ open|closed|auto.
devices:edit · confirm-gated
set_manual_egress_ip
Pin 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_share
End a live customer screen-share session (either side may stop) and signal the device to tear down its broadcast (#1891).
devices:edit
transfer_device_ownership
ADMIN: 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_daemon
Update 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.
ONE 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_enabled
Read the GLOBAL, PER-SURFACE "busybro enabled" feature flag (settings_global.data.busybroEnabled — an object { ios, dashboard, telegram, mcp }).
global:view
get_inspect_all_requests
Read 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_hosts
Read the "MITM all hosts" decrypt-master toggle (settings_{global,device}.data.mitmAllHosts) — when ON, the proxy/iOS decrypt EVERY host.
global:view
set_busybro_enabled
Set ONE surface of the GLOBAL, PER-SURFACE "busybro enabled" flag (settings_global.data.busybroEnabled).
global:edit · confirm-gated
set_inspect_all_requests
Set the "inspect all requests" capture-master toggle.
Read 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.
Grant 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_impersonation
End (revoke) a "Login as" impersonation session by its jti — the one-click exit (#933 P1).
owner-scoped
impersonate_user
Mint 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_grants
List 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_permissions
The "what can <user> do, and WHY" read: role capabilities + held scoped grants (each with the grant's role capabilities).
users:view
revoke_access_grant
Revoke a scoped access-grant by id — immediate (DB-evaluated scope).
users:edit · admin-only · confirm-gated
set_default_role
Set the configurable default role every new native signup receives (#474).
Fix → 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_todo
Fix → add a finding to YOUR /todo board (source='advisor') with the same max-context markdown in the notes.
todos:edit · confirm-gated
get_advisor_finding
Get 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_findings
Browse the Advisor Center findings (public.advisor_findings) — the advisor-monitor's deduped audit/health findings.
audit:view
share_advisor_finding
Build a shareable package for ONE finding — the max-context markdown + flat LLM prose + the permalink (Finding · Analysis · Evidence · Deep links · Repro · Meta).
Live 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).
Runs 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_tools
Lists 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.
Take EXCLUSIVE control of a farm phone (the per-phone control lock — 'In control by XXX', #1476).
devices:edit · confirm-gated
admin_force_release_device_control
ADMIN: 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_port
TARGETED 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_logs
Tail 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_tool
Run ONE WebMCP tool a FARM PHONE's Chrome page registers (document.modelContext.executeTool) and return its string result.
devices:edit · confirm-gated
farm_get_variables
Read the farm automation variables (global / per-device / merged effective view) from settings_{global,device}.data.farmVars.
devices:view
farm_list_page_tools
List the WebMCP tools a FARM PHONE's Chrome page registers (document.modelContext.getTools()) — name, title, description, inputSchema, origin, annotations.
devices:view
farm_mobile_double_tap
Double-tap ONE farm phone at pixel (x,y) via mobile-mcp mobile_double_tap_on_screen.
devices:edit · confirm-gated
farm_mobile_get_crash
Get one crash report's full content (by id) on a farm phone via mobile-mcp mobile_get_crash.
devices:view
farm_mobile_get_orientation
Get the current screen orientation of ONE farm phone via mobile-mcp mobile_get_orientation.
devices:view
farm_mobile_get_screen_size
Get the pixel screen size of ONE farm phone via mobile-mcp mobile_get_screen_size.
devices:view
farm_mobile_install_app
Install 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_appstore
Search 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_app
Launch an app (by bundle id) on ONE farm phone via mobile-mcp mobile_launch_app.
devices:edit · confirm-gated
farm_mobile_list_apps
List the installed apps on ONE farm phone (by child_uuid) via mobile-mcp mobile_list_apps.
devices:view
farm_mobile_list_crashes
List the crash reports on ONE farm phone via mobile-mcp mobile_list_crashes.
devices:view
farm_mobile_list_devices
List every device the farm host's mobile-mcp sees (mobile_list_available_devices).
devices:view
farm_mobile_list_elements
List 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_press
Long-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_url
Open a URL on ONE farm phone via mobile-mcp mobile_open_url.
devices:edit · confirm-gated
farm_mobile_press_button
Press a hardware button (HOME/ENTER/VOLUME_*/BACK) on ONE farm phone via mobile-mcp mobile_press_button.
devices:edit · confirm-gated
farm_mobile_screenshot
Capture a PNG screenshot of ONE farm phone (by child_uuid), served PER-DEVICE on the host (go-ios).
devices:view
farm_mobile_set_orientation
Set the screen orientation (portrait|landscape) on ONE farm phone via mobile-mcp mobile_set_orientation.
devices:edit · confirm-gated
farm_mobile_start_recording
Start 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_recording
Stop the active screen recording on ONE farm phone via mobile-mcp mobile_stop_screen_recording.
devices:edit · confirm-gated
farm_mobile_swipe
Swipe ONE farm phone (direction + optional x/y/distance) via mobile-mcp mobile_swipe_on_screen.
devices:edit · confirm-gated
farm_mobile_tap
Tap ONE farm phone at pixel (x,y) via mobile-mcp mobile_click_on_screen_at_coordinates.
devices:edit · confirm-gated
farm_mobile_terminate_app
Terminate an app on ONE farm phone via mobile-mcp mobile_terminate_app.
devices:edit · confirm-gated
farm_mobile_type
Type text on ONE farm phone (optional submit) via mobile-mcp mobile_type_keys.
devices:edit · confirm-gated
farm_mobile_uninstall_app
Uninstall an app (by bundle id) from ONE farm phone via mobile-mcp mobile_uninstall_app.
devices:edit · admin-only · confirm-gated
farm_reap_tunnels
HOST-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_tunnel
SOFTWARE-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_phone
SOFTWARE-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_variables
Write the farm automation variables (replace or merge) into settings_{global,device}.data.farmVars.
devices:edit · confirm-gated
farm_start_mirror
ADMIN — 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_status
Get 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_logs
Read 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_health
THE per-phone health answer (#1433): the exact status + WHY + what-to-expect + how-to-fix for ONE farm phone.
devices:view
heal_farm_fleet
FLEET 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_reboot
REMOTE-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_hub
LAST-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_control
Give up YOUR control of a farm phone (release the per-phone control lock you hold), freeing it immediately.
devices:edit · confirm-gated
restart_farm_daemon
Restart 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_transport
SET 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_daemon
Update 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.
Launch | terminate an app on the targeted iOS farm phone(s) by bundle id.
devices:edit · confirm-gated
ios_dump_ui
On-screen UI hierarchy (interactable elements: text / accessibility label / type + tap centre) of the targeted iOS farm phone(s).
devices:view
ios_find_and_tap
Find a UI element by visible text / accessibility label and tap it on the targeted iOS farm phone(s).
devices:edit · confirm-gated
ios_input
Send an input event (tap/swipe/type/button; normalized 0..1 coords) to the targeted iOS farm phone(s).
devices:edit · confirm-gated
ios_install_app
ADMIN — 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_apps
List the installed apps (bundle id + name) on the targeted iOS farm phone(s).
devices:view
ios_list_phones
LIVE go-ios/mobile-mcp view of the iPhones on an iOS farm host (udid/state/model/iOS version).
devices:view
ios_open_url
Open a URL (deep-link or web) on the targeted iOS farm phone(s).
devices:edit · confirm-gated
ios_screenshot
PNG screenshot of ONE iOS farm phone (by its child_uuid route-key).
devices:view
ios_set_orientation
Set the screen orientation (portrait|landscape) on the targeted iOS farm phone(s).
devices:edit · confirm-gated
ios_start_mirror
Open 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_app
ADMIN — uninstall an app (by bundle id) from the targeted iOS farm phone(s).
devices:edit · admin-only · confirm-gated
list_ios_phones
List the iOS farm fleet (ios-hosts + their child iPhones) from the devices table, RLS owner-scoped.
devices:view
provision_ios_phone
Create/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_devicekit
ADMIN — 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.
Merge-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.
Delete a skill bundled file by id (same writability as upsert_skill_file).
skills:edit · admin-only · confirm-gated
draft_skill
PURE 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_skill
Replace 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_skill
Get one BusyBro skill (full detail incl.
users:view
get_skill_file
ONE skill bundled file WITH content, by id OR (skill_id + path).
users:view
list_repo_skills
List 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_files
List 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_skills
List BusyBro skills (loadable instruction+tool bundles loaded mid-chat via load_skill) — the team catalog + your own.
users:view
remove_repo_skill
Delete 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_enabled
Flip 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_enabled
Enable/disable a BusyBro skill by id (a disabled skill stays but never loads).
skills:edit · admin-only · confirm-gated
upsert_skill
Create (omit id) or update (set id) a BusyBro skill.
Cancel an in-flight dispatch run (verdict-less, unfinished).
tester:run · confirm-gated
get_test_coverage
Read 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_coverage
Read 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_history
Per-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_suites
List the canonical tester suite registry — every registered suite with { id, component, suite, tier, phase, critical, expand, description }.
tester:view
rerun_test_suite
Re-dispatch a prior run — filter='all' repeats its tier+component; filter='failed' re-runs only the components whose suites failed.
Read 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_history
Read ONE WIP-board task's append-only progress TIMELINE — how it progressed over time + which agents/skills worked it.
users:view
wip_update
UPSERT 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).
YOUR 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_issue
One-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_settings
Change 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_name
Set how BusyBro should ADDRESS you — the "What should BusyBro call you?" nickname (≤60 chars); '' or whitespace clears it (falls back to your display name).
Delete 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_plugin
ONE 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_plugin
Install 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_plugins
List the plugin catalog — admin-authored bundles of skills + connectors.
users:view
set_plugin_install_enabled
Toggle YOUR plugin install on/off (own-data, confirm-free — the set_my_mcp_connector_enabled class).
users:edit
uninstall_plugin
Uninstall 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_plugin
Create/update a plugin catalog row — THE sole manifest writer (inline defs are admin-authored only, the v1 trust boundary).
Remove a federation client from the registry (cascades its issued federation_codes).
federation:edit · admin-only · confirm-gated
list_federation_clients
List 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_client
Create/update a federation client (the broker's trust anchor).
Set 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).
Bulk-import { key: value } for one (locale,namespace) from an external translator round-trip.
i18n:edit · admin-only · confirm-gated
list_i18n_keys
List the canonical key registry for a namespace: key + description + declared ICU placeholders.
i18n:view
list_i18n_messages
List translation values (key×locale): value (raw ICU), status (translated|machine|needs_review|missing).
i18n:view
list_i18n_namespaces
List string-group namespaces (ios.common, ios.setup, …) with platforms[].
i18n:view
list_locales
List the i18n locale registry (BCP-47) — code/native/enabled/rtl/fallback/default/tier.
i18n:view
machine_translate_i18n
REAL 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_catalog
Materialize 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_rows
The reviewer's queue: machine rows with base value, back-translation, similarity, checks, model, cost (paged).
i18n:view
set_default_locale
Set the default/base locale (atomic clear-then-set).
i18n:edit · admin-only · confirm-gated
set_i18n_settings
Merge the i18n singleton knobs.
i18n:edit · admin-only · confirm-gated
upsert_i18n_key
Create/update a canonical key + its declared ICU placeholders.
i18n:edit · confirm-gated
upsert_i18n_message
Create/update ONE translation value (raw ICU).
i18n:edit · confirm-gated
upsert_i18n_namespace
Create/update a namespace (surface/platforms/enabled).
i18n:edit · admin-only · confirm-gated
upsert_locale
Add / enable / configure a locale (rtl/fallback/tier).