Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, email [email protected] and we’ll put it right.

Busymate DevTools

REMOTE · MCP.BUSYMATE.DEV · SCANNED AUG 3

Capture, inspect & debug HTTPS traffic across iOS, Android, browsers & backends — 304 MCP tools.

Available components

+41 this week 78 Trust /100
Trust breakdown (6 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score →

Endpoint Security94
Transport & Reachability100
Schema Quality & AI Usability61
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 9743 tokens (~231/item across 42 items; 42 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management27
  • Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage90
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 71% of tool parameters carry a description.Partial
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Install

Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.

remote · mcp.busymate.dev

# add to Claude Code
claude mcp add --transport http dev-busymate-busymate-devtools https://mcp.busymate.dev/
# ~/.codex/config.toml
[mcp_servers.dev-busymate-busymate-devtools]
url = "https://mcp.busymate.dev/"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "dev-busymate-busymate-devtools": {
      "type": "remote",
      "url": "https://mcp.busymate.dev/",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add dev-busymate-busymate-devtools --url https://mcp.busymate.dev/ --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  dev-busymate-busymate-devtools:
    url: "https://mcp.busymate.dev/"
// mcp.json
{
  "mcpServers": {
    "dev-busymate-busymate-devtools": {
      "type": "http",
      "url": "https://mcp.busymate.dev/"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 3 Aug 26 +2
    • Tool “list_device_events” rewrote its description, which is the text the model reads security
    • Tool “get_device_health” rewrote its description, which is the text the model reads security
    • Schema quality: good → excellent functional
    • Server version: 1.0.592 → 1.0.586 functional
    • “list_device_events” reworded the description of “category” cosmetic
    • “list_device_events” dropped the optional parameter “producer” cosmetic
  • 2 Aug 26 +2
    • Tool “list_device_events” rewrote its description, which is the text the model reads security
    • Server version: 1.0.589 → 1.0.592 functional
    • “list_device_events” reworded the description of “category” cosmetic
  • 1 Aug 26 0
    • Server version: 1.0.588 → 1.0.589 functional
  • 31 Jul 26 +6
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 30 Jul 26 +30
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 29 Jul 26 +1
    • Server version: 1.0.580 → 1.0.582 functional
  • 28 Jul 26 0
    • Server version: 1.0.575 → 1.0.580 functional
  • 27 Jul 26 +1
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 3 Aug 2026 · Probed https://mcp.busymate.dev

TLS valid

Negotiated TLS 1.3 with TLS_AES_256_GCM_SHA384 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=api.busymate.dev CN=YE2,O=Let's Encrypt,C=US 19 Jun 2026 17 Sept 2026 ECDSA 256 ECDSA-SHA384 5ee5072b160078f248294488effb692664d
SANs: api.busymate.dev, mcp.busymate.dev
CN=YE2,O=Let's Encrypt,C=US (CA) CN=Root YE,O=ISRG,C=US 3 Sept 2025 2 Sept 2028 ECDSA 384 ECDSA-SHA384 4df3b15dd6c0784c507cd37b58e6f115
CN=Root YE,O=ISRG,C=US (CA) CN=ISRG Root X2,O=Internet Security Research Group,C=US 13 May 2026 2 Sept 2032 ECDSA 384 ECDSA-SHA384 872165fc34b6e5fba8add5b3705fb53a
CN=ISRG Root X2,O=Internet Security Research Group,C=US (CA) CN=ISRG Root X1,O=Internet Security Research Group,C=US 13 May 2026 2 Sept 2032 ECDSA 384 SHA256-RSA 6c8f1dc727c7117f7baf853ac980f9cd
DNSSEC insecure

Validation of mcp.busymate.dev. Not signed

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
dev. present 60074 8 Verified
busymate.dev. absent Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation
Authentication Enforced and verified

The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.

Result Enforced and verified
Enforced On tool calls
HTTP status 200

WWW-Authenticate challenge Bearer resource_metadata="https://mcp.busymate.dev/.well-known/oauth-protected-resource", scope="mcp", error="invalid_token", error_description="missing Bearer token"

Bearer resource_metadata="https://mcp.busymate.dev/.well-known/oauth-protected-resource", scope="mcp", error="invalid_token", error_description="missing Bearer token"
Header Value
strict-transport-security max-age=31536000; includeSubDomains; preload
www-authenticate Bearer resource_metadata="https://mcp.busymate.dev/.well-known/oauth-protected-resource", scope="mcp", error="invalid_token", error_description="missing Bearer token"

Protected resource metadata

Document https://mcp.busymate.dev/.well-known/oauth-protected-resource
Retrieved Yes
Resource https://mcp.busymate.dev
Authorisation server https://mcp.busymate.dev
Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://mcp.busymate.dev Verified 200
http (plaintext) http://mcp.busymate.dev HTTPS enforced 301 https://mcp.busymate.dev/
MCP tools — 42 exposed · ~9,432 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.

Tool Tokens
download_snapshot ~34

Get a 5-minute signed download URL for a snapshot file (name from list_snapshots).

NameTypeReqDescription
namestringyes

No output schema declared.

No examples provided.

export_har ~77

Export captured entries as a HAR 1.2 log. Optionally scope by device, host, and date range.

NameTypeReqDescription
beforestring
deviceNamestring
device_uuidstring
hoststring
limitnumber
sincestring

No output schema declared.

No examples provided.

get_advisor_finding ~154

Get ONE advisor finding in FULL by its `fingerprint` (from list_advisor_findings) — with its up-to-20 resolved (already-redacted) audit EVENTS, the SCOPED /audit deep link, and the /advisor permalink, so you can act with zero re-investigation. Returns { found, finding, events:[{id,at,surface,action,status,actor_label,target_kind,target_id,request_id}], deep_link (absolute https://dash.busymate.dev/audit?…), advisor_url (https://dash.busymate.dev/advisor?f=…) }. Gated audit:view.

NameTypeReqDescription
fingerprintstringyesThe finding fingerprint (from list_advisor_findings).

No output schema declared.

No examples provided.

get_audit_event ~210

Get ONE audit-trail row in FULL by its `id` (from list_audit_events) — including the fields the list omits: the REDACTED `detail` (old→new diffs for allowlisted keys, redacted at write time — never raw args/secrets) and `statement_excerpt` (the left-400-char SQL for a direct-PG write). Owner-scoped: a row whose actor isn't YOU returns not-found (found:false) unless you hold audit:view (operators can read any row) — an out-of-reach row is never distinguished from a non-existent one. Pass `at` (the row's timestamp from the list) to prune the partition for a faster lookup. Returns { ok, found, event }.

NameTypeReqDescription
atstringThe row's `at` timestamp (ISO, from list_audit_events) — partition-prune hint.
idnumberyesThe audit_log row id (from list_audit_events).

No output schema declared.

No examples provided.

get_block_rules_device ~149

Read what ONE device ENFORCES — the EFFECTIVE 4-tier block-rule union (global ++ service ++ user ++ device, de-duped by id, device wins then user then service then global) plus the SERVICE list (the applied service groups' rules, flattened in service-group name order), the device owner's USER list, and that device's per-device list. Pass device_uuid or deviceName. A rule shadowed on this device by a same-id higher tier is correctly absent — this is the policy in force here, not the fleet catalogue. For the fleet-wide global tier use get_block_rules_global.

NameTypeReqDescription
deviceNamestring
device_uuidstring

No output schema declared.

No examples provided.

get_device ~358

Get one device row by uuid, name, OR its PAC PORT — the DIRECT resolver for a KNOWN device: when you already hold a device uuid/name (from traffic rows, audit events, another tool's result) or a per-device PAC/proxy endpoint, call this instead of browsing or paging list_devices. `pac_port` accepts EVERY spelling: a bare port (10807), the PAC hostname (10807.busymate.net), a full PAC URL (http://10807.busymate.net/ or https://10807.busymate.net/proxy.pac), or host:port — the leading label of a PAC host IS the device's allocated port. A host with no numeric leading label and no explicit port is REFUSED as ambiguous rather than guessed, and a port owned by NO device returns { ok:true, found:false, note } — a normal complete answer, never an error and never an empty list you could misread as 'unsupported'. Returns the canonical record (uuid, name, model, os_version, setup, last_seen_at) plus found:true and the derived pac_port/pac_url. Owner-scoped: without devices:view you may still resolve YOUR OWN device by uuid/name/pac_port (the PAC-port match is pinned to devices you own, so port-guessing can never reach another account).

NameTypeReqDescription
deviceNamestringDevice display name (fallback)
device_uuidstringDevice UUID (preferred)
pac_portstring|numberThe device's PAC/manual-proxy port, as a number (10807), a PAC hostname (10807.busymate.net), a PAC URL (http://10807.busymate.net/), or host:port.

No output schema declared.

No examples provided.

get_device_health ~372

THE ONE QUERY (#1157/#1160): the latest capture-health projection for ONE device — one `device_health` row, no scan, no on-device access needed. Answers "is the TLS-intercept engine armed, and if not, WHY": engine_state ('armed'|'inert') + engine_reason (e.g. no_ca_key) + state_established_at (when that state was first established, so a stale fact is visibly stale), the CA triple (ca_loaded / ca_key_present / ca_trusted — 'trusted CA, missing key' means refetch the cert BUNDLE; 'CA not trusted' means reinstall the profile: opposite fixes today's signals cannot distinguish), ssl_domain_count + ssl_domain_hash (compare against the server's expected effective-settings hash: mismatch = config-delivery fault, match + inert = engine fault), config_hash/config_fetched_at, the decrypt counters (flows_total / flows_decrypted / flows_reasons {reason: count} over no_engine|no_sni|out_of_scope|leaf_mint_failed|ca_untrusted|pinned|upstream_failed), events_dropped + last_seq/seq_gaps (the telemetry stream's own honesty detectors), tunnel_state, app_build + ios_version + boot_id, and last_error. The row is trigger-written from device_events (the device's own claims about itself — diagnostic, never authorization). A device with NO row returns found:false + a note (it has never emitted telemetry — needs an iOS build with the #1160 emitter); that is a NORMAL complete answer, and absence of telemetry is never evidence of health. Owner-scoped: without devices:view you may still read YOUR OWN device by uuid/name.

NameTypeReqDescription
deviceNamestring
device_uuidstring

No output schema declared.

No examples provided.

get_device_settings ~38

Read settings_device for one device (device_uuid or deviceName).

NameTypeReqDescription
deviceNamestring
device_uuidstring

No output schema declared.

No examples provided.

get_device_status ~129

Get a device's live status: `online` is DERIVED truth (#776 — devices.last_seen_at within 90s, 150s for farm hosts; the same derivation as every other surface, so it can't latch stale), plus the device_status row (last_heartbeat_at, ip, vpn_state, source, reported_online = the raw stored flag, diagnostics only). Works even for a device that never wrote a status row (entries-only clients) — `online` still evaluates from last_seen_at.

NameTypeReqDescription
deviceNamestring
device_uuidstring

No output schema declared.

No examples provided.

get_entry ~421

Get ONE captured entry's FULL detail by the id you already hold — method, URL, host, path, status, timing (duration_ms) + sizes, the request AND response HEADERS, and the request AND response BODIES (size-capped, truncation stated explicitly). The ID-SCOPED twin of inspect_requests (which is per-HOST): when a live feed row, an audit event or another tool hands you an `entry_id` (or a `request_id`), call this to see THAT exact request — never re-query by host and guess which result matched. This is the MCP/widget parity twin of the dashboard's request-detail pane, and the tool the live-traffic widget's row-expand invokes. Owner-scoped like the dashboard: an entry belongs to the owner of the device that captured it, so YOUR OWN devices' entries need no capability; reading an entry captured by ANOTHER account's device requires devices:view, re-verified in-handler fail-closed (a foreign id is DENIED with a clear reason, never silently empty). Bodies default to 8000 chars each and cap at 40000 via `max_body_chars`; anything clipped is reported in `truncation` (truncated + returned_chars/total_chars + the encoding, `base64` when the captured body was binary) and named in `note` — a truncated body is NEVER presented as complete. For the complete artifact use export_har. Treat any tokens / cookies / credentials in headers + bodies as SECRETS. Read-only, no confirm. Returns { ok, entry, truncation, note }.

NameTypeReqDescription
entry_idnumberThe entry's numeric id — the `id` field of a list_entries / search_entries row (preferred).
max_body_charsnumberPer-body character budget (default 8000, cap 40000). Anything beyond is reported as truncated, never silently dropped.
request_idstringThe capture request id (alternative locator); the newest matching entry is returned.

No output schema declared.

No examples provided.

get_entry_count ~109

Count entries in a workspace (workspace_id or workspace_slug) with optional device/host/method/status/search filters.

NameTypeReqDescription
afterstring
beforestring
device_uuidsarray
hostsarray
methodsarray
originstring
search_qstring
status_classnumber
workspace_idstring
workspace_slugstring

No output schema declared.

No examples provided.

get_my_account ~246

YOUR account at a glance — ONE self-scoped read returning the calling account's profile (name, display_name, email, role, sign-in providers, user_id, created_at), your per-user default connection type (own value + the global default + the effective fold), your linked Telegram accounts, the devices YOU own (uuid/name/model/last_seen_at — the uuids feed get_device / rename_device / …), your Stripe subscription status, and the API endpoints callable with this token. The MCP mirror of the dashboard Account page. SELF-ONLY: every read is pinned server-side to the verified caller — it takes NO target args and CANNOT read another user's account (cross-account browsing stays the admin surface: /users, list_telegram_links, get_subscription all_users:true). Own-data, read-only → no capability gate, no confirm; any signed-in user may call it. Use when a user asks "who am I" / "what's my account/role/email" / "what devices do I own" / "is my Telegram linked" / "am I subscribed". Returns { ok, account, connection, telegram, devices, subscription, endpoints }.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

get_push_response ~150

Read back a device's answer to an actionable push (#75) by the correlation_id returned from send_push. Returns the push_responses row { correlation_id, device_uuid, action (accept|reject|skip), context, responded_at, action_intent } or null if the user hasn't responded yet. action_intent (or null) carries the SERVER-RECORDED action-binding + its outcome: { action_kind, params, issued_by, created_at, executed_at, result } — so you learn BOTH the user's choice and what the binding actually did (e.g. block_rule_toggle result.enabled_after).

NameTypeReqDescription
correlation_idstringyesThe correlation_id returned by send_push when actionable:true.

No output schema declared.

No examples provided.

get_service_group ~32

Get one service group by id or name.

NameTypeReqDescription
idstring
namestring

No output schema declared.

No examples provided.

get_stats ~18

Return the live stats snapshot (get_stats RPC).

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

get_status ~246

Return the latest infra status snapshot (service_status) MERGED with the Edge tier's self-reported deployed build. The VPS posts the StatusBody (overall, host{cpu,load,mem,uptime}, components[], and — when it supplies one — builds[]); this RECONCILES that builds[] against the Edge tier's own numbers and adds `buildDrift` (#987: the VPS cannot ask the Edge bundle what build it runs, so its supabase/busybro rows arrive running:null and were being counted as in-sync — the reconciled rows + buildDrift replace that green-while-dead reading; both keys are present only when the snapshot carried builds[]). It also always adds `edge: { supabase: {component,version,build,commit}, bro: {…} }` — version/build baked into the deployed Edge bundle (buildInfo.ts), `commit` resolved at runtime from a deploy-time env var (#210) — so it reflects what mcp/ask/busybro-bot ACTUALLY run, letting the dashboard infra board show declared-vs-running drift (version-everywhere). Gated by status:view.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

get_subscription ~112

Return the caller's OWN Stripe subscription(s) — status/price/product/quantity/period/trial/cancel-at-period-end (from stripe_subscriptions, owner-scoped to the caller's OAuth sub). A billing:view operator (admin via grants_all) may pass `all_users:true` for the whole fleet. Returns { count, subscriptions:[…] }. Phase 1 is Stripe TEST mode.

NameTypeReqDescription
all_usersbooleanbilling:view/admin only — return EVERY account's subscriptions instead of just the caller's.

No output schema declared.

No examples provided.

get_todo ~65

Get ONE of YOUR to-dos by id — its full row. Owner-scoped: an id you don't own returns not-found (never reveals another user's to-do). Returns { todo }.

NameTypeReqDescription
idstringyesThe to-do's uuid (from list_todos).

No output schema declared.

No examples provided.

get_usage ~191

Return the caller's OWN metered usage rollup (metric `captured_entries` = count of captured entries per device per period; from stripe_usage_events, owner-scoped to the caller's OAuth sub) aggregated by period over a window. `since_days` (default 30, max 365), `metric` (default captured_entries). A billing:view operator may pass `all_users:true` for the fleet. Returns { metric, since, count, total_quantity, usage:[{period_start, device_uuid, quantity, reported_at}] }.

NameTypeReqDescription
all_usersbooleanbilling:view/admin only — return EVERY account's usage.
metricstringUsage metric (default 'captured_entries').
since_daysnumberLook back this many days (1–365, default 30).
user_idstringbilling:view/admin only — a specific target user.

No output schema declared.

No examples provided.

get_workspace ~30

Get one workspace by id or slug.

NameTypeReqDescription
idstring
slugstring

No output schema declared.

No examples provided.

inspect_requests ~392

Deep-inspect FULL captured request/response detail for ONE host — method, URL, request + response HEADERS, and request + response BODIES (size-capped). The tool for reverse-engineering how a real app/API works from its actual captured traffic (auth flows, required headers, payload shapes) and for building repro (curl/fetch). `host` MUST be a full hostname containing a dot (e.g. 'identity.doordash.com') — a bare brand word is rejected (an exact-host index scan is fast; a substring scan times out). Scoped to a device (device_uuid/deviceName) it scans that device's full history; WITHOUT a device (fleet-wide) it defaults to the last 7 days — pass `after`/`before` (up to 31 days back) to widen. Optionally narrow by path substring, method, or status. Newest first. Treat any tokens / cookies / credentials in headers + bodies as SECRETS.

NameTypeReqDescription
afterstringOptional — only requests with ts >= this ISO date/datetime, e.g. '2025-05-20'.
beforestringOptional — only requests with ts < this ISO date/datetime ('before/older than <date>').
deviceNamestring
device_uuidstring
hoststringyesFULL hostname (must contain a dot), e.g. 'identity.doordash.com'. Bare brand words are rejected.
limitnumberMax requests (default 8, capped at 15).
methodstringOptional HTTP method filter, e.g. POST.
path_containsstringOptional — only requests whose path contains this substring (e.g. 'login', 'token', 'auth').
statusnumberOptional exact response status filter, e.g. 200.

No output schema declared.

No examples provided.

list_advisor_findings ~249

Browse the ADVISOR CENTER findings (public.advisor_findings) — the advisor-monitor's deduped audit/health findings you see on the dashboard /advisor view. Filter by `severity` (info|warning|alert), `kind` (a taxonomy slug like audit.denied_spike / advisor.security), and `q` (free-text over the finding title + kind + fingerprint). Newest-first (last_seen_at); keyset-paginate by passing the returned `next_cursor` as `before`. Each row: fingerprint, kind, severity, first_seen_at, last_seen_at, times_seen, analysis {title,body,suggestion,fix}, filters, sample_event_ids. Gated audit:view.

NameTypeReqDescription
beforestringKeyset cursor — the previous page's last last_seen_at (from next_cursor).
kindstringFilter by taxonomy kind slug (e.g. audit.denied_spike, advisor.security).
limitnumberMax rows (default 50, cap 200).
qstringFree-text substring over the finding title + kind + fingerprint.
severitystringFilter by severity.

No output schema declared.

No examples provided.

list_audit_events ~975

Read the platform AUDIT TRAIL (public.audit_log) — the unified who-did-what-when-how ledger across every surface (mcp / busybro / dashboard / rest / db / auth / proxy / daemon / cron / ios / cdp / farm / edge:<fn> — #533: the surface is DERIVED at the DB trigger tier by HOW a write ARRIVED — a direct-Postgres write→db (the tamper class, also flagged by is_direct_pg), a device PostgREST write→ios/cdp/farm/rest by its platform, a dashboard PostgREST write→dashboard, a plain REST write→rest). YOUR OWN events by default (owner-scoped to the calling account's actor_id — the same reach the /audit page gives you), or the WHOLE FLEET with `all:true` (audit:view operators only; re-verified server-side, fail-closed — for a non-operator `all` is rejected, never silently widened). Each row is a SLIM projection (no detail/statement_excerpt — fetch those with get_audit_event): id, at, actor_kind (user|service|device|webhook|anon|system), actor_id + actor_label (the human name snapshot), client_id, jti, actor_ip, user_agent, db_session_user, is_direct_pg (a DIRECT-Postgres write — the #026 tamper signature), surface, action, target_kind/target_id/target_label, device_uuid, rows_changed, status (ok|denied|error|timeout), method, latency_ms, request_id (correlate one action across layers). MANDATORY time window: `since`/`until` (ISO; since defaults to 24h ago, clamped to ≥ 90 days ago — the retention horizon). Filters: `surface`, `status`, `actor_id` (exact — operators only for a foreign actor), `actor_q`/`action_q`/`target_q` (per-field substring), `target_kind`+`target_id` (exact — the history deep-link), `request_id`, `direct_only:true` (only direct-PG writes), `q` (free-text multi-column substring across action/actor/target/surface). KEYSET pagination: pass the returned `next_cursor` {before_at, before_id} to page further; `asc:true` for oldest-first; `limit` (default 100, cap 500). detail is REDACTED at write time (never raw args/secrets). Returns { ok, scope: own|fleet, count…

NameTypeReqDescription
action_qstringSubstring match on the action (tool name / route / db:op:table).
actor_idstringExact actor id (OAuth sub / device uuid / db role). A FOREIGN actor requires audit:view (all:true).
actor_qstringSubstring match on actor_label or actor_id.
allbooleanaudit:view operators only — read EVERY actor's events (the fleet trail) instead of just YOUR OWN.
ascbooleanOldest-first (default false = newest-first).
before_atstringKeyset cursor — the previous page's last `at` (from next_cursor).
before_idnumberKeyset cursor — the previous page's last `id` (from next_cursor).
direct_onlybooleanOnly DIRECT-Postgres writes (is_direct_pg=true — the tamper signal).
limitnumberMax rows (default 100, cap 500).
qstringFree-text substring across action/actor_label/target_label/actor_id/target_id/surface/db_session_user.
request_idstringExact request_id (uuid) — correlate one action across layers.
sincestringISO timestamp — window start (default 24h ago; clamped to ≥ 90 days ago).
statusstringExact status filter (ok|denied|error|timeout).
surfacestringExact surface filter (mcp|busybro|dashboard|rest|db|auth|proxy|daemon|cron|ios|cdp|farm|edge:<fn>).
target_idstringExact target_id (paired with target_kind = the history deep-link).
target_kindstringExact target_kind (e.g. 'devices', 'roles', 'settings_device').
target_qstringSubstring match on target_label/target_id/target_kind.
untilstringISO timestamp — window end (default now).

No output schema declared.

No examples provided.

list_breakpoint_events ~309

List HELD (paused) breakpoint exchanges — the READ side of the breakpoint-continue flow (public.breakpoint_events; a row with resumed_at NULL is a request/response the proxy is holding RIGHT NOW, waiting for breakpoint_continue — feed it the returned request_id). YOUR OWN devices' events by default (owner-scoped to the calling account — the same reach the dashboard /breakpoints page gives you), or EVERY device with `all:true` (devices:view operators only; re-verified server-side — for a non-operator `all` is rejected, never silently widened). Each row is a SLIM projection: id, request_id, device_uuid + device_name (the human name, resolved via the devices join — never a bare uuid), workspace_id, kind (request|response), paused_at, resumed_at, outcome (continued|dropped|edited|timeout|null), held. Currently-held rows only by default; pass include_resumed:true for the recent resolved history too. Never returns the raw HTTP bodies (slim payloads). Read-only, no confirm. Returns { ok, scope: own|fleet, count, events }.

NameTypeReqDescription
allbooleandevices:view operators only — held breakpoints for EVERY device instead of just YOUR OWN.
include_resumedbooleanInclude already-resumed rows (the recent history) — default false lists only currently-held pauses.
limitnumberMax rows (default 100, cap 500).

No output schema declared.

No examples provided.

list_device_audit_modes ~128

Every device with AUDIT-mode telemetry currently armed — device_uuid + name, enabled, expires_at + expires_in, level, categories, who armed it (set_by_label) and when (set_at). The 'standing cost is never invisible' list (#1160 spec §5): audit mode is per-device + TTL-expiring, and this is where you see everything armed right now. YOUR OWN devices by default; devices:view operators see the whole fleet (re-verified server-side). Read-only, no confirm. Backed by the list_device_audit_modes DEFINER RPC.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

list_device_events ~704

The device TELEMETRY event stream (#1160) — every DECISION and STATE TRANSITION a device reports about its own capture pipeline (public.device_events, 14-day retention, weekly-partitioned): capture.health (armed|inert + why + decrypt counters), cert.state, config.applied, tunnel.lifecycle, process/app lifecycle, plus the opt-in audit-tier kinds (mitm.decision, cert.mint, config.fetch, applink, ui.action, push.received, net.error) and the server-authored telemetry.rate_clipped / audit_mode.ended breadcrumbs. Newest-first slim rows { id, at (server receive time), device_uuid, level (baseline|debug), category, action (the dotted kind = category.action), outcome, reason, host, ts (device clock), boot_id, seq, app_build, ios_version }; `with_detail:true` adds the redacted `detail` jsonb (≤4 KB, redacted at write — parameter NAMES only, never query values/bodies/keys). A gap in (boot_id, seq) = a dropped event (detectable at read time even when the drop counter itself was lost). Filters: category / action / outcome / reason / host / boot_id (exact), level, failures:true (outcome ∈ fail|deny|inert — the partial-index fast path), since / until (ISO, on `at`). KEYSET pagination: when a page is full, feed next_cursor's before_at + before_id back verbatim (both together — a bulk insert lands a whole batch on ONE timestamp, so at-only paging would skip batches). ONE device by device_uuid/deviceName (owner-scoped: without devices:view you may read YOUR OWN device), or omit the selector for the FLEET-WIDE stream (devices:view operators only, re-verified server-side). limit default 50, cap 200.

NameTypeReqDescription
actionstringExact action verb (the dotted kind is category.action, e.g. capture + health).
before_atstringKeyset cursor (from next_cursor) — pass with before_id.
before_idnumberKeyset cursor (from next_cursor) — pass with before_at.
boot_idstringOne process lifetime — pair with seq to walk a single boot's ordered stream.
categorystringExact category (capture|cert|config|tunnel|process|app|mitm|applink|ui|push|net|telemetry|audit_mode).
deviceNamestring
device_uuidstring
failuresbooleantrue → only outcome ∈ fail|deny|inert (the indexed failure path).
hoststringExact bare host.
levelstringTelemetry tier.
limitnumberMax events (default 50, cap 200).
outcomestringExact outcome (armed|inert|ok|fail|deny|start|stop|decrypted|…).
reasonstringExact machine reason slug (e.g. no_ca_key).
sincestringISO — only events with at >= this.
untilstringISO — only events with at <= this.
with_detailbooleantrue → include the redacted detail jsonb per row (≤4 KB each).

No output schema declared.

No examples provided.

list_device_service_groups ~153

List the device↔service-group membership edges (public.device_service_groups) — the delegation boundary: which devices belong to which service group. Resolves device_name + service_group_name. Filters: `service_group_id`, `device_uuid`, `limit` (default 500, cap 1000). This is the ADMIN-CONTROLLED authz edge (never traffic-derived); it powers "users whose devices are in group X". Gated devices:view. Read-only.

NameTypeReqDescription
device_uuidstringFilter to one device's groups.
limitnumberMax rows (default 500, cap 1000).
service_group_idstringFilter to one service group's devices.

No output schema declared.

No examples provided.

list_devices ~740

List devices, ONE PAGE at a time — YOUR OWN by default (owner-scoped to the calling account: the same reach the dashboard gives you), or the WHOLE fleet with `all:true` (devices:view operators only; re-verified server-side — for a non-operator `all` is rejected, never silently widened). PAGINATION (read this before concluding anything is absent): every response carries `total` (the EXACT count in scope), `returned` (rows in THIS page), `has_more`, and `next_cursor`. If `has_more` is true the answer is INCOMPLETE — call again with `cursor: <next_cursor>` (same `order` and same scope) and repeat until `has_more` is false. NEVER report that a device/port/name is absent from a page where has_more was true; page to the end or resolve it directly with get_device. `truncated_by:"byte_budget"` means the page stopped early to fit the response budget — the cut rows are simply the NEXT page, nothing was lost. ORDERING: `order:"last_seen"` (default) is recency-first and best for browsing, but last_seen_at moves whenever a device heartbeats, so a row can shift ahead of the cursor mid-run — for a GUARANTEED complete enumeration pass `order:"uuid"` (immutable key, `stable_enumeration:true`). Each row is a slim projection: uuid, name, platform, online (DERIVED from last_seen_at freshness — #776, never the raw device_status latch), last_seen_at, vpn_state, the per-device connection_type override (null = inherits user → global), and pac_port/pac_url for PAC-provisioned devices; null keys are omitted. `fields:"full"` adds model, os_version and parent_device_id + parent_name (farm/iOS children resolve their host's NAME) at ~2x the bytes per row. Fleet rows also resolve each owner to a human name. Use to answer "what devices do I own" / "list my devices" / "which devices are online". BROWSING ONLY: to resolve a device you ALREADY have a uuid, name, or PAC port/URL for, call get_device with it directly — never scan or page this list hunting for a known device. Read-only, no confirm. Ret…

NameTypeReqDescription
allbooleandevices:view operators only — list EVERY device (the whole fleet) instead of just YOUR OWN.
cursorstringResume token from the previous page's `next_cursor`. Must be used with the SAME order and scope it was issued for.
fieldsstring"slim" (default) = identity + status + PAC, null keys omitted. "full" adds model, os_version and the parent linkage (~2x bytes per row).
limitnumberMax devices per page (default 100, cap 500). The byte budget may return fewer — check has_more.
max_bytesnumberPage byte budget for the devices array (default 24000, min 2000, max 60000). Lower it for a small tool-result window.
orderstring"last_seen" (default) = most-recently-seen first, best for browsing. "uuid" = the immutable key — the ONLY ordering that guarantees a complete, skip-free enumeration across pages.

No output schema declared.

No examples provided.

list_entries ~581

LIST the newest captured traffic entries as SLIM feed rows (id, ts, device, kind, request_id, host, path, method, status, contentType, url — NO bodies/headers) — the dashboard main live feed's MCP-parity read (#778). No search term needed (unlike search_entries' required `q`). FULL /feed filter set (#819): scope to ONE device (device_uuid/deviceName), an EXACT `host` or a `host_contains` substring, an HTTP `method`, a `status` (exact code or a class '2xx'/'4xx'/'5xx'), and/or an absolute ts range; `since_id` returns ONLY rows newer than an id you already hold (the live-tail append cursor — poll cheaply for what's new); order newest (default) or oldest; limit default 30, capped 100. Owner-scoped like the dashboard: your own devices' traffic by default. OPERATORS (devices:view, re-verified in-handler fail-closed) may scope the feed to ANOTHER user's account via `owner_email` (exact) or `owner_user_id` — that user's devices only. For full bodies/headers use inspect_requests; for substring search use search_entries. Returns { ok, count, entries:[…] }.

NameTypeReqDescription
afterstringOnly entries with ts >= this ISO date/datetime.
beforestringOnly entries with ts < this ISO date/datetime.
deviceNamestringScope to one device by display name.
device_uuidstringScope to one device by uuid.
hoststringEXACT hostname filter (e.g. 'api.busymate.net'). Use host_contains for a substring.
host_containsstringSubstring hostname filter, case-insensitive (e.g. 'doordash' matches every *.doordash.com host).
limitnumberMax rows (default 30, cap 100).
methodstringHTTP method filter, case-insensitive exact (e.g. GET, POST).
orderstringSort direction (default 'newest').
owner_emailstringOPERATOR cross-user scope (devices:view required, re-verified): another user's account email (exact, case-insensitive) — the feed covers THAT user's devices.
owner_user_idstringOPERATOR cross-user scope by user id (uuid) — the deterministic spelling the live-traffic widget re-poll uses.
since_idnumberOnly entries with id > this — the live-tail append cursor (pass the max id you already rendered).
statusstringResponse status filter: an exact code ('404') or a class ('2xx'|'4xx'|'5xx').

No output schema declared.

No examples provided.

list_invoices ~127

List the caller's OWN Stripe invoices — status/amounts (minor units)/currency/hosted_invoice_url/period (from stripe_invoices, owner-scoped to the caller's OAuth sub), newest first. Optional `limit` (default 50, max 200). A billing:view operator may pass `all_users:true` for the fleet. Returns { count, invoices:[…] }.

NameTypeReqDescription
all_usersbooleanbilling:view/admin only — return EVERY account's invoices.
limitnumberMax invoices to return (1–200, default 50).

No output schema declared.

No examples provided.

list_issue_reports ~302

List issue reports from the one-tap reporter (public.issue_reports — the durable rows behind report_issue + the dashboard ⌘⇧1 dialog). YOUR OWN reports by default (owner-scoped to the calling account — the same reach the RLS gives you), or EVERY reporter's with `all:true` (audit:view operators only; re-verified server-side, fail-closed — for a non-operator `all` is rejected, never silently widened). Each row is a SLIM projection: id, title, category, status (pending|filed|closed), occurrences (the dedup-coalesced repeat count), issue_number + issue_url (the auto-created GitHub issue once filed), source (dashboard|mcp|busybro|telegram), route + build + version (unpacked server-side from the report's captured context), created_at, last_seen_at (newest activity first — a coalesced repeat bumps it); fleet rows resolve the reporter to a human name (never a bare uuid). Filter with `status`; `limit` default 100, cap 500. Read-only, no confirm. Returns { ok, scope: own|fleet, count, reports }.

NameTypeReqDescription
allbooleanaudit:view operators only — EVERY reporter's reports instead of just YOUR OWN.
limitnumberMax rows (default 100, cap 500).
statusstringFilter by report status.

No output schema declared.

No examples provided.

list_push_tokens ~41

List registered APNs push tokens (masked). Optionally scope to one device.

NameTypeReqDescription
deviceNamestring
device_uuidstring

No output schema declared.

No examples provided.

list_service_groups ~38

List every service group (full rows incl. ssl_proxy_domains) with each group's primary_agent + ordered agents[] from the service_group_agents join.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

list_snapshots ~18

List snapshot files in the snapshots storage bucket.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

list_tabs ~36

List a workspace's tabs (workspace_id or workspace_slug).

NameTypeReqDescription
workspace_idstring
workspace_slugstring

No output schema declared.

No examples provided.

list_tags ~20

List every tag (id, name, color, patterns).

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

list_todos ~251

List YOUR to-dos from the /todo app (public.todos) — the shared "what to do / what's done" list you + the user both maintain. Owner-scoped to the calling account. Filters: `status` (open|in_progress|done|blocked), `priority` (low|medium|high|urgent), `source` (user|claude|ask), `tag` (one tag to match). By DEFAULT hides completed todos (the active worklist); pass include_done:true (or an explicit status) to include them. Ordered by manual `position` (nulls last) then newest-first. Returns { count, todos:[{id,owner,title,notes,status,priority,tags,source,position,due_at,created_at,updated_at,done_at}] }.

NameTypeReqDescription
include_donebooleanInclude completed todos (default false hides them).
limitnumberMax rows (default 200, cap 500).
prioritystringFilter by priority.
sourcestringFilter by who added it.
statusstringFilter by status.
tagstringOnly todos carrying this tag.

No output schema declared.

No examples provided.

list_workspaces ~106

List workspaces. YOUR OWN by default (owner-scoped to the caller — the reach the dashboard RLS owner arm gives you); `all:true` lists EVERY account's workspaces and needs the workspaces.view capability (re-verified in-handler, fail-closed). Omits archived unless include_archived.

NameTypeReqDescription
allbooleanList every account's workspaces instead of just your own. Requires the workspaces.view capability.
include_archivedboolean

No output schema declared.

No examples provided.

search_entries ~162

LOCATE captured entries by host/url substring (`q`). Optionally scope to a device_uuid and an absolute date range. Returns SLIM locator rows ({id, ts, device_uuid, kind, request_id, host, path, method, status, contentType, url} + a ~200-char requestBodyPreview/responseBodyPreview) — NOT full bodies; limit defaults 50, capped 100. For full request/response bodies + headers use inspect_requests (deep per-host detail), export_har, or db_select on the row id.

NameTypeReqDescription
afterstring
beforestring
device_uuidstring
limitnumber
orderstring
qstringyes

No output schema declared.

No examples provided.

share_advisor_finding ~172

Build a SHAREABLE package for ONE advisor finding — the max-context markdown + flat LLM prose + the permalink, so it can be dropped into a doc/chat/issue with full context (Finding · Analysis · Evidence · Deep links · Repro · Meta). Returns { format, permalink (https://dash.busymate.dev/advisor?sev&kind&f), advisor_url, markdown, llm_text } — `format` is an emphasis hint (markdown|llm|links) ECHOED BACK in the result (defaulted to markdown when omitted or unrecognized); every other field is returned regardless of it. Read-only. Gated audit:view.

NameTypeReqDescription
fingerprintstringyesThe finding fingerprint.
formatstringEmphasis hint (default markdown); all fields returned.

No output schema declared.

No examples provided.

summarize_device_traffic ~315

BOUNDED traffic aggregation for ONE device — the FIRST tool to call to report what a device is doing, find the busy/flooding host, or pick a host to clean up. REQUIRES a device (`device_uuid` or `deviceName`) — a host alone is NOT enough: if you don't know which device, ask the user (or check list_devices) BEFORE calling. NEVER scans or returns raw rows (use it instead of search_entries/inspect_requests on a high-volume device — those time out at scale). Omit `host` → top hosts by request count (which host dominates). Pass `host` → top path-bases on that host with per-path count + last-seen (which endpoint floods). Optional absolute time range. Fast on 17k+ rows (one index-only GROUP BY). Returns ONLY {host|path_base, count, last_seen} — no headers/bodies.

NameTypeReqDescription
afterstringOnly entries with ts >= this ISO date/datetime.
beforestringOnly entries with ts < this ISO date/datetime.
deviceNamestringThe device's name — an alternative to device_uuid; one of the two is REQUIRED.
device_uuidstringREQUIRED unless deviceName is given — the device to summarize.
hoststringOmit for top hosts; pass a full hostname to get its top path-bases.
limitnumberMax groups (default 25, capped 100).

No output schema declared.

No examples provided.

test_pac_connection ~472

PROVE whether PAC capture actually works for ONE device — the "is it really working?" answer, not "does it look configured". Runs 8 independent checks and returns a per-check verdict with a specific human fix: (1) connection mode — is the device even on `pac` (a `vpn`/`off` device is SAID SO plainly, never reported as broken PAC); (2) PAC port + URL — a pool port is allocated and http://<port>.busymate.net/ + /proxy.pac + /wpad.dat each serve HTTP 200 with the PAC content type; (3) THE HEADLINE — the PAC the proxy really serves this device carries a PROXY directive and is NOT the silent DIRECT fallback (a DIRECT PAC means the device bypasses capture ENTIRELY while looking perfectly configured — ~11k serves/day hit this); (4) egress IP is in the asserted allowlist (the dominant cause of that DIRECT fallback); (5) the proxy is really routing this device's requests right now; (6) the effective SSL-proxying list is NON-EMPTY and covers hosts the device actually contacts (an empty list = configured to decrypt NOTHING, which FAILS); (7) live decryption evidence — genuinely DECRYPTED requests for hosts in this device's OWN resolved list (a CONNECT envelope or a raw-TCP row is never counted as proof); (8) the device-reported CA-trust readiness + its exact remediation. Every check is pass | fail | unverified — a check that could not reach the thing it judges returns UNVERIFIED and is NEVER reported as healthy. Overall verdict ok | degraded | broken | unverified plus ONE plain-language next action. YOUR OWN (or demo) devices by default; testing someone else's device requires devices:view (re-verified server-side, fail-closed). Read-only, no confirm, changes nothing.

NameTypeReqDescription
deviceNamestringThe device's name — an alternative to device_uuid; one of the two is REQUIRED.
device_uuidstringREQUIRED unless deviceName is given — the device to test.
window_minutesnumberLookback for the traffic + decryption checks (default 60, min 5, max 1440).

No output schema declared.

No examples provided.