Busymate DevTools
Capture, inspect & debug HTTPS traffic across iOS, Android, browsers & backends — 304 MCP tools.
Connector by busymate.devOfficial · Domain verified by the MCP Registry
Install
Works with Claude Code, VS Code, Cursor, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install connector/busymate-dev-busymate-devtools
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Remote endpoint
https://mcp.busymate.devRemote (HTTP)
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this server can do and what it asks for, from its tool list and install config. Checked Oct 25, 2026.
- Tools
- 49 read · 0 write · 0 deleteRead-only
- Secrets
- None asked for
- Install scripts
- Nothing to install (hosted)
- Runs as
- Hosted (remote endpoint)
Tools by what they do 49
From the running server's own tool list (tools/list) on Oct 25, 2026.
Read 49 · Look things up without changing anything.
download_snapshotexport_harget_advisor_findingget_audit_eventget_block_rules_deviceget_deviceget_device_egress_fail_postureget_device_egress_statusget_device_healthget_device_settingsget_device_statusget_entry
Show 37 more tools
get_entry_countget_entry_counts_freshnessget_my_accountget_product_pricingget_push_responseget_screen_share_recordingget_service_groupget_statsget_statusget_subscriptionget_todoget_usageget_workspaceinspect_requestslist_advisor_findingslist_audit_eventslist_breakpoint_eventslist_device_audit_modeslist_device_eventslist_device_service_groupslist_deviceslist_entrieslist_invoiceslist_issue_reportslist_push_tokenslist_screen_share_recordingslist_service_groupslist_snapshotslist_tabslist_tagslist_todoslist_wipe_jobslist_workspacessearch_entriesshare_advisor_findingsummarize_device_traffictest_pac_connection
Network hosts it talks to 1
mcp.busymate.dev· found in remote endpoint, install command
Files it touches
- Any path the agent passes to its tools
Tools (49)
As the server listed them on Oct 25, 2026. Descriptions are the server’s own words; hidden characters are shown as [U+…].
download_snapshotDownload Snapshotread-onlyGet a 5-minute signed download URL for a snapshot file (name from list_snapshots).
export_harExport HARread-onlyExport captured entries as a HAR 1.2 log. Optionally scope by device, host, and date range.
get_advisor_findingGet Advisor Findingread-onlyGet 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.
get_audit_eventGet Audit Eventread-onlyGet 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, ev…
get_block_rules_deviceGet Block Rules Deviceread-onlyRead 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.
get_deviceGet Deviceread-onlyGet 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 …
get_device_egress_fail_postureGet Device Egress Fail Postureread-onlyRead a device's PAC egress FAIL POSTURE (#1657) — what the proxy does when the device is handed the #76 PAC DIRECT fallback (its PAC-fetch source IP is not yet in the CONNECT-source admission allowlist, routine on CGNAT). The setting `egressFailPosture` ∈ open | closed | auto rides settings_{global,device}.data and is resolved device→user→service→global by effective_settings_for_device (like the external proxy). Meanings: open → serve DIRECT (stay online, but the device egresses from its REAL IP — a leak for an external-proxy/country-pinned device); closed → serve a HOLD/no-egress PAC (proxy-o…
get_device_egress_statusGet Device Egress Statusread-onlyRead a device's egress-IP set (#1432) — the device→proxy INGRESS / CONNECT-source ADMISSION IPs the proxy allowlists for it (the addresses it will ACCEPT this device's CONNECTs FROM), PLUS any manual dev overrides. These are the CONNECT-source ADMISSION IPs, NOT the target-visible egress ORIGIN the destination server sees (that origin is governed by the device's external (upstream) proxy — see set_device_external_proxy). Each row carries `ip`, `source` ('proxy' = an automatic /allocate row, rolling 48h window + 10-most-recent-per-device cap; 'manual' = a TTL'd dev override, EXEMPT from the cap…
get_device_healthGet Device Healthread-onlyTHE 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 + …
get_device_settingsGet Device Settingsread-onlyRead settings_device for one device (device_uuid or deviceName).
get_device_statusGet Device Statusread-onlyGet 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.
get_entryGet Entryread-onlyGet 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 …
get_entry_countGet Entry Countread-onlyCount entries in a workspace (workspace_id or workspace_slug) with optional device/host/method/status/search filters.
get_entry_counts_freshnessGet Entry Counts Freshnessread-onlyThe ONE freshness surface for every dashboard counter (#2147): mode 'live' — entry_dh_counts is a LEDGER maintained in the write transaction of every insert / delete / wipe / partition drop and broadcast as COUNTS_DELTA (never an hourly snapshot); ledger_since; reconciled_at + drift_rows / drift_abs from the hourly RECONCILER (a bounded drift check that corrects idle groups); reconcile_stale=true ⇒ no successful drift check for >2 h (a REPORTED class — the ledger keeps moving); last_error; and the /stats rollup seal watermark (stats_rollup_sealed_to / stats_rollup_stale). Read-only; no argumen…
get_my_accountGet My Accountread-onlyYOUR 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 targe…
Show 34 more tools
get_product_pricingGet Product Pricingread-onlyReturn the canonical Busymate DevTools plan prices and cloud phone/browser rental rates, with numeric amounts, USD currency, billing periods and https://busymate.dev/pricing as the source. Check draft, publicationStatus and purchasable: draft figures are proposals awaiting approval, never live offers. Public read; no sign-in or account data.
get_push_responseGet Push Responseread-onlyRead 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).
get_screen_share_recordingGet Screen Share Recordingread-onlyFetch ONE saved screen-share recording (#1916) by id — the metadata row plus, with `with_url:true`, a SHORT-TTL (600s) signed playback URL + a download URL for the mp4 (H.264 — plays in any <video> element / on iPhone). YOUR OWN recording by default; `all:true` (devices:view operators, dispatch-policed) reaches any visible recording. The internal storage_path is never surfaced — the signed URL is the only byte access. Read-only, no confirm. Returns { ok, recording, url, download_url, url_ttl_seconds }.
get_service_groupGet Service Groupread-onlyGet one service group by id or name.
get_statsGet Statsread-onlyReturn the live fleet stats aggregate (get_stats_internal RPC). total_entries is the counters LEDGER (Σ entry_dh_counts.n — never an ANALYZE estimate) with total_entries_source ('ledger'|'snapshot') and total_entries_as_of (its stamp); status_class_mix / source_mix / top_domains / top_devices describe the sealed 24 h rollup (rollup_sealed_to, rollup_window_hours); entries_1h / entries_24h / requests_per_sec are live counts; generated_at is the compute time.
get_statusGet Statusread-onlyReturn 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 build…
get_subscriptionGet Subscriptionread-onlyReturn 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.
get_todoGet Todoread-onlyGet 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 }.
get_usageGet Usageread-onlyReturn 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}] }.
get_workspaceGet Workspaceread-onlyGet one workspace by id or slug.
inspect_requestsInspect Requestsread-onlyDeep-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 …
list_advisor_findingsList Advisor Findingsread-onlyBrowse 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.
list_audit_eventsList Audit Eventsread-onlyRead 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 pa…
list_breakpoint_eventsList Breakpoint Eventsread-onlyList 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, devi…
list_device_audit_modesList Device Audit Modesread-onlyEvery 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.
list_device_eventsList Device Eventsread-onlyThe MULTI-PRODUCER device TELEMETRY event stream (#1160/#1208) — every DECISION and STATE TRANSITION reported about the capture pipeline by the iOS app OR by the PAC/proxy server (public.device_events, 14-day retention, weekly-partitioned). iOS kinds — this list is what the app ACTUALLY emits, corrected in #1232 after SEVEN of the fifteen declared categories turned out to have zero emit sites and zero rows while this description told operators they existed. BASELINE (always on, no flag): capture.health (armed|inert + why + decrypt counters), cert.state, config.applied / config.fetch, tunnel.li…
list_device_service_groupsList Device Service Groupsread-onlyList 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.
list_devicesList Devicesread-onlyList 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…
list_entriesList Entriesread-onlyLIST 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 — pol…
list_invoicesList Invoicesread-onlyList 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:[…] }.
list_issue_reportsList Issue Reportsread-onlyList 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…
list_push_tokensList Push Tokensread-onlyList registered device push tokens (masked), PLATFORM-ROUTED (#1542): each `device_push_tokens` row carries a `platform` discriminator — `ios` = an APNs device token (push-notify's APNs leg), `android` = an FCM registration token (push-notify's FCM HTTP v1 leg). The column defaults `ios`, so legacy rows read `ios`. Optionally scope to one device.
list_screen_share_recordingsList Screen Share Recordingsread-onlyList saved screen-share RECORDINGS (#1916) — operator-captured mp4s of live share streams (the dashboard viewer's Record control), saved for later reference in public.screen_share_recordings. YOUR OWN recordings by default (owner-scoped to the calling account — the same reach the row RLS gives the dashboard), or every visible recording with `all:true` (devices:view operators only; re-verified by the dispatch — for a non-operator `all` is rejected, never silently widened). Filter by device_uuid and/or session_id. Each row: id, session_id, device_uuid, device_name (capture-time snapshot), owner,…
list_service_groupsList Service Groupsread-onlyList every service group (full rows incl. ssl_proxy_domains) with each group's primary_agent + ordered agents[] from the service_group_agents join.
list_snapshotsList Snapshotsread-onlyList snapshot files in the snapshots storage bucket.
list_tabsList Tabsread-onlyList a workspace's tabs (workspace_id or workspace_slug).
list_tagsList Tagsread-onlyList every tag (id, name, color, patterns).
list_todosList Todosread-onlyList 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,do…
list_wipe_jobsList Wipe Jobsread-onlyList the workspace's WIPE JOBS (public.entries_wipe_jobs, #2147) — the ONE source of truth for wipe progress, the same rows the dashboard's wipe banner renders. Each job: the EXACT device set, the narrowing predicate (hosts/methods/status_class/search_q/origin), total (from the live entry_dh_counts ledger; total_exact=false ⇒ an upper bound), deleted, percent, status (queued|running|done|failed|cancelled), started/finished/heartbeat timestamps, requested_by, error, plus derived `stalled` (no heartbeat for 90 s — the server re-drive resumes it within a minute) and `terminal`. Filters: job_id, s…
list_workspacesList Workspacesread-onlyList 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.
search_entriesSearch Entriesread-onlyLOCATE captured entries by ANY keyword `q` — matched against the host/url/path AND the DECRYPTED request/response DATA: the request+response HEADERS and the request+response BODY text (#1577). Case-insensitive substring. Body/header matching covers full headers + the head of each body (first ~4KB request / ~8KB response) via a trigram index, and a body is indexed ONLY when its side's content-type is API-shaped (JSON / XML / form / multipart / text-plain / CSV / SSE / GraphQL, or no content-type at all) — JS, CSS, HTML, image, font and binary bodies are not keyword-searchable (#2143), and a key…
share_advisor_findingShare Advisor Findingread-onlyBuild 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.
summarize_device_trafficSummarize Device Trafficread-onlyBOUNDED 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 (w…
test_pac_connectionTest PAC Connectionread-onlyPROVE 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…
Signals
- Last release
- Jul 8, 2026 (3 months ago)
- Repository
- Not found on GitHub (deleted or private)
Details
- Registry name
dev.busymate/busymate-devtools- Version
- 1.0.481
- Auth
- Auth not stated
- License
- License unknown
- Repository
- github.com/serebano/busymate-devtools
- Website
- busymate.dev/mcp
- First seen
- Oct 24, 2026
- Last checked
- Oct 25, 2026
- Source
- Official MCP Registry
Cite this page
Busymate DevTools MCP server. Agent Mart. https://agentmart.dev/connectors/busymate-dev-busymate-devtools (last updated 2026-10-25)