feat(cua-driver): add stable health_report MCP tool - #1905
Conversation
…iver diagnostics
Downstream consumers (Hermes Agent and similar) want one stable diagnostic
call against cua-driver, not a tangle of check_permissions, doctor, version,
bundle-attribution, and screenshot probes glued together. This new MCP tool
gives them that: a single call with a stable, versioned JSON output shape.
The tool owns the health model entirely. Consumers stay thin and cua-driver
evolves freely.
Schema:
{
"schema_version": "1",
"platform": "darwin",
"driver_version": "<semver>",
"overall": "ok" | "degraded" | "failed",
"checks": [
{
"name": "<canonical check name>",
"status": "pass" | "fail" | "skip",
"message": "<one-line summary>",
"hint": "<remediation, present on fail>",
"data": { ... optional per-check structured fields ... }
},
...
]
}
schema_version="1" is the stability commitment. Adding new check names
under the same version is non-breaking; consumers must tolerate unknown
names. Breaking shape changes go to "2".
Reuses Permissions.currentStatus() for the TCC checks rather than
duplicating the probe logic. Adds a ScreenCaptureKit reachability probe
(in-memory, nothing hits disk) and a CFBundleIdentifier check that
surfaces the runtime bundle id so consumers can detect TCC attribution
drift without parsing message text.
Tests: 15 unit + 6 stdio MCP integration tests, all green.
Rust port (libs/cua-driver-rs / libs/cua-driver/rust) is left as a
follow-up — adding the same tool to three platform crates plus parity
tests is too much for one pass.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughAdds a new Changeshealth_report MCP Tool
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Closing — wrong target. The Swift implementation under Re-implementing in the Rust workspace in a follow-up PR. The schema design from this PR ( The branch Apologies for the noise — wrong framing on my end when dispatching the original work. |
…iver diagnostics Single-call diagnostic tool so downstream consumers (Hermes Agent's `hermes computer-use doctor`, NousResearch/hermes-agent#47065) get a stable health-check contract without knowing cua-driver internals — specific MCP tool names, TCC field names, bundle IDs, per-platform check matrix. cua-driver owns the health model entirely; consumers stay thin and the driver evolves freely. This is the canonical Rust port of the now-closed Swift PR #1905. The Swift implementation landed by mistake in the deprecated swift/ tree; this lands the same schema + test contract in the canonical Rust workspace (libs/cua-driver/rust/). Architecture: - cua-driver-core/src/health_report.rs — cross-platform skeleton: Report / CheckEntry / CheckStatus / CheckData types, the HealthCheckProvider trait, select_checks / compute_overall / parse_string_set logic, and the HealthReportTool MCP wrapper. - platform-macos/src/tools/health_report.rs — macOS provider (binary, platform, session, bundle_identity via CFBundleGetMainBundle, TCC reuse via existing permissions::status plumbing, live SCShareableContent probe for screen_capture_capability). - platform-windows/src/health_report.rs — Windows provider (UIA via the existing diagnostics::ui_automation_available, D3D11CreateDevice probe for screen capture, tcc_* + bundle_identity skipped with "not applicable on Windows"). - platform-linux/src/health_report.rs — Linux provider (X11 connect probe shared between ax_capability and screen_capture_capability, tcc_* + bundle_identity skipped with "not applicable on Linux"). Wire-format contract is stable: schema_version="1" is the commitment, future breaking changes go to "2". Adding new check names is non-breaking; consumers must tolerate unknown names. health_report NEVER itself sets isError — that's the whole point of a "what's broken?" probe. Tests: - cua-driver-core: 16 unit tests for selectChecks, computeOverall, parseStringSet, end-to-end dispatcher round-trip, fail-mode contract, schema_version=1 description commitment. - platform-macos: 5 tests including a documented fail-mode fixture (the test host's bundle id is not com.trycua.driver, so bundle_identity reliably fails with the full message+hint+data shape consumers see in the wild). - platform-windows: 4 tests covering the canonical skip("not applicable on Windows") shape for TCC/bundle. - platform-linux: 4 tests covering the canonical skip("not applicable on Linux") shape for TCC/bundle. - tests/integration/test_health_report_mcp.py: 6 stdio MCP tests (tools/list discovery + schema_version commitment, no-args round trip, include filter, skip filter, fail-mode shape, never-isError). Refs: - Closed Swift PR: #1905 (deprecated swift/ tree) - Downstream consumer: NousResearch/hermes-agent#47065 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…iver diagnostics Single-call diagnostic tool so downstream consumers (Hermes Agent's `hermes computer-use doctor`, NousResearch/hermes-agent#47065) get a stable health-check contract without knowing cua-driver internals — specific MCP tool names, TCC field names, bundle IDs, per-platform check matrix. cua-driver owns the health model entirely; consumers stay thin and the driver evolves freely. This is the canonical Rust port of the now-closed Swift PR #1905. The Swift implementation landed by mistake in the deprecated swift/ tree; this lands the same schema + test contract in the canonical Rust workspace (libs/cua-driver/rust/). Architecture: - cua-driver-core/src/health_report.rs — cross-platform skeleton: Report / CheckEntry / CheckStatus / CheckData types, the HealthCheckProvider trait, select_checks / compute_overall / parse_string_set logic, and the HealthReportTool MCP wrapper. - platform-macos/src/tools/health_report.rs — macOS provider (binary, platform, session, bundle_identity via CFBundleGetMainBundle, TCC reuse via existing permissions::status plumbing, live SCShareableContent probe for screen_capture_capability). - platform-windows/src/health_report.rs — Windows provider (UIA via the existing diagnostics::ui_automation_available, D3D11CreateDevice probe for screen capture, tcc_* + bundle_identity skipped with "not applicable on Windows"). - platform-linux/src/health_report.rs — Linux provider (X11 connect probe shared between ax_capability and screen_capture_capability, tcc_* + bundle_identity skipped with "not applicable on Linux"). Wire-format contract is stable: schema_version="1" is the commitment, future breaking changes go to "2". Adding new check names is non-breaking; consumers must tolerate unknown names. health_report NEVER itself sets isError — that's the whole point of a "what's broken?" probe. Tests: - cua-driver-core: 16 unit tests for selectChecks, computeOverall, parseStringSet, end-to-end dispatcher round-trip, fail-mode contract, schema_version=1 description commitment. - platform-macos: 5 tests including a documented fail-mode fixture (the test host's bundle id is not com.trycua.driver, so bundle_identity reliably fails with the full message+hint+data shape consumers see in the wild). - platform-windows: 4 tests covering the canonical skip("not applicable on Windows") shape for TCC/bundle. - platform-linux: 4 tests covering the canonical skip("not applicable on Linux") shape for TCC/bundle. - tests/integration/test_health_report_mcp.py: 6 stdio MCP tests (tools/list discovery + schema_version commitment, no-args round trip, include filter, skip filter, fail-mode shape, never-isError). Refs: - Closed Swift PR: #1905 (deprecated swift/ tree) - Downstream consumer: NousResearch/hermes-agent#47065 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Motivation
Downstream consumers (Hermes Agent and similar) want an end-to-end health check for
cua-driverbut should not have to knowcua-driverinternals: specific MCP tool names, TCC field names, bundle IDs, per-platform check matrix. Today they stitch togethercheck_permissions,doctor, version probes, bundle-attribution checks, and a screenshot smoke test — which means every diagnostic refactor insidecua-driverbreaks them.The right shape is for
cua-driverto own the health model entirely and expose it as one stable MCP tool. Consumers stay thin.cua-driverevolves freely.This PR adds that tool:
health_report.Schema (stable contract,
schema_version: "1"){ "schema_version": "1", "platform": "darwin" | "win32" | "linux", "driver_version": "<semver>", "overall": "ok" | "degraded" | "failed", "checks": [ { "name": "binary_version" | "platform_supported" | "tcc_accessibility" | "tcc_screen_recording" | "bundle_identity" | "ax_capability" | "screen_capture_capability" | "session_active", "status": "pass" | "fail" | "skip", "message": "<one-line summary, always present>", "hint": "<remediation step — present when status == fail>", "data": { /* check-specific structured data — optional */ } } ] }overallrulesok— every non-skipped check passesdegraded— at least one non-core check fails (binary still usable)failed— any core check fails (binary_version,platform_supported,session_active)Input (all optional)
{ "include": ["<check_name>", ...], "skip": ["<check_name>", ...] }Both use canonical check names from the output enum. If both are given,
includewins. Unknown names inincludeare silently ignored (forward-compat — a consumer may know names from a newer driver).Stability commitment
schema_version: "1"is the contract. Future breaking changes go to"2".Non-breaking under v1: adding new check names. Consumers must tolerate unknown check names.
Breaking (would bump to v2): removing fields, renaming canonical check names, changing
status/overallenum values, changing JSON-key casing.What runs
macOS check matrix (everything in this PR):
binary_version— always pass; surfacesCuaDriverCore.version.platform_supported— pass withdata.os_version,data.architecture.session_active— pass by construction.bundle_identity— pass iffCFBundleIdentifier == com.trycua.driver; fails withdata.bundle_identifierpopulated for downstream attribution-drift detection.tcc_accessibility— reusesPermissions.currentStatus().tcc_screen_recording— reusesPermissions.currentStatus().ax_capability—AXIsProcessTrusted()probe.screen_capture_capability— liveSCShareableContent.excludingDesktopWindowsprobe withdata.display_count. Nothing hits disk. No stream is started.TCC checks delegate to
Permissions.currentStatus()— no duplication.Test strategy
HealthReportTests, 15 tests) — registry advertisement, schema_version commitment in tool description,selectChecks/computeOveralltruth tables,parseStringSetedge cases, end-to-end Codable round-trip asserting documented top-level + per-check keys,skipfilter honored, and the documentedbundle_identityfail-mode shape (status=fail + hint + data.bundle_identifier).test_health_report_mcp.py, 6 tests) — spawns the realcua-driver mcpstdio server, performs JSON-RPC handshake, assertstools/listadvertiseshealth_report, calls it with no args /skipfilter /includefilter, validates the schema shape, assertsisErroris never set, and exercises the documented fail mode end-to-end.swift test) — 51 tests, all green.Scope notes — Rust follow-up
libs/cua-driver-rs(and thelibs/cua-driver/rustworkspace) exists with macOS + Windows + Linux ports. Addinghealth_reportthere means landing it in threeplatform-*crates plus extending the parity suite — too much for one pass. Filing as a follow-up. Swift is shipped here; the schema contract above will drive the Rust port verbatim.Constraints honored
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests