Screen time parental control apps all report their own status. Read the accessibility tree instead.
Four enforcement models, one blind spot, and a separate accessibility-tree audit on top. Every app you can choose from on macOS, Apple Screen Time included, answers the question “is it still on?” with its own opinion. If a child disables the app, the status view goes with it. This guide names the four enforcement models underneath the category, admits what each one is good at, and documents a separate audit layer that reads the accessibility tree directly so tamper shows up as a plain text diff.
The blind spot every “best screen time apps” article misses
Pick up any ten roundups of screen time parental control apps and the top picks rotate through the same short list: Apple Screen Time, Qustodio, Bark, Norton Family, Mobicip, Circle. The comparisons are about features. Web filtering. App limits. Schedules. Location. Reports. The comparisons are honest, and if you are picking for features, pick whichever app fits.
What no roundup asks: what does the reporting path look like when a child turns the app off? The answer for every listed app is the same. Each one reports its own status, through its own channel. Apple Screen Time reports inside System Settings, which the child also controls. Qustodio, Bark, and Norton Family stream a heartbeat from an agent on the device, which the child can quit. A DNS filter is bypassed by switching Wi-Fi networks. An MDM profile is removable from the Profiles pane.
The blind spot is category-wide. It is not “pick a better app.” It is “add a verifier that is independent of whichever app you picked.”
Four enforcement models, and an audit layer that sits on top
Whichever enforcement model you pick, the accessibility tree is the signal.
The four models, named honestly
Every parental control app you can run on macOS falls into one of these four. Mix them if you like; in practice most households end up with two.
Built-in: Apple Screen Time
Enforced by the OS through Family Controls. Strongest on iPhone, weakest on macOS where a child with admin rights can flip it off in Settings and keep the passcode screen from ever appearing.
Network: DNS + VPN filters
Block at the edge. Great for YouTube, Reddit, adult sites over HTTPS. Useless the moment the device leaves the network or uses DoH.
Agent: Qustodio, Bark, Norton Family, Mobicip
Third-party daemon enforces time and site rules locally and streams reports to a vendor cloud. Shrink-wrapped UX. Each vendor's dashboard reports its own liveness.
Managed: MDM profile
A configuration profile pushes restrictions through the OS. Usually via Apple School Manager, Jamf, Kandji, or a family-tier MDM. Enterprise-grade, but visible as a removable row in Settings.
On top of any of them: AX audit
Read the same accessibility tree the OS renders. No kernel extension. No vendor SDK. One timer loop, one diff per tick, and the signal is independent of whichever app you chose.
What the AX audit actually produces
The server exposes a tool called refresh_traversal. Given a process id, it re-reads that app’s entire accessibility tree, diffs it against the prior snapshot, and returns a compact summary plus a file path on disk. On a minute timer pointed at System Settings, it looks like this when a Screen Time toggle flips:
The important line is ~ 'Screen Time' AXValue '1' -> '0'. Three things matter about it. One, it names the element by its visible title, so it is grep-able. Two, it records the before and after values, so the direction of the change is unambiguous. Three, it is a plain text line, so it ships into any alerting channel without a parser.
The anchor: one loop in Swift decides what a tamper looks like
The diff pipeline is a single for loop that walks the set of modified elements between two consecutive snapshots and emits one text line per AXValue transition. It lives in the main server binary, around line 843 of Sources/MCPServer/main.swift. It is short enough to read in one sitting.
The loop does not know that the element is a Screen Time checkbox. It does not care which vendor rendered the UI. It treats every AXUIElement the same way. That is why the same code path works for the System Settings window and for a third-party parental control app’s main window, assuming the vendor exposes state to accessibility APIs.
The numbers, verifiable from the repo
Six tools defined between main.swift:1300 and main.swift:1408. Traversal truncates at 5000 elements per call (enforced inside the tree walker, tested by scripts/test_mcp.py). The AXValue diff emission sits at main.swift:843. No kernel extension participates in the audit path.
Model vs. model: what the AX audit catches that the vendor cannot
This is not a feature comparison of vendors. It is a side-by-side of what each enforcement model tells you versus what the AX tree tells you, so you can see why the two should run together.
| Feature | Vendor self-report | AX audit layer |
|---|---|---|
| Built-in (Apple Screen Time) | Reports status inside Settings, which the child also controls. | AX tree shows 'Screen Time' AXCheckBox value even if the child hides the Settings window. |
| Agent apps (Qustodio, Bark, Norton Family) | Vendor dashboard shows online/offline, driven by the agent's own heartbeat. | AX snapshot of the vendor's UI records whether its toggles match the vendor-reported state. |
| Network filters (DNS, VPN) | Blocks at the network edge. If the device switches to a hotspot, filter is gone. | AX snapshot of System Settings Wi-Fi pane reveals SSID changes and VPN connection state. |
| MDM profile | Profile visible inside Settings > Privacy and Security > Profiles, can be removed. | AX diff fires when the profile row disappears from the Profiles list in System Settings. |
Setting this up alongside an existing app
The whole point of this layer is that it does not replace whatever parental control app you already use. You keep that app. You add an audit on top. The setup is five steps, and none of them touch your vendor.
Pick whichever parental control app you already trust
Apple Screen Time, Qustodio, Bark, Norton Family, Circle, a DNS filter, your MDM. This audit layer is vendor-neutral and the enforcement app keeps its own job.
Install and grant the MCP server Accessibility permission
System Settings, Privacy and Security, Accessibility, add the mcp-server-macos-use binary. No Full Disk Access. No Screen Recording unless you want PNG evidence.
Prime a snapshot of the panes you care about
Call macos-use_open_application_and_traverse with identifier com.apple.systempreferences to open System Settings, then click into the Screen Time pane. The first traversal sets the baseline.
Run refresh_traversal on a timer from your agent or cron
Once a minute is usually enough. The tool returns a compact diff with added, removed, and modified elements. Store the file path, not the full tree, to keep context small.
Alert on any AXValue transition on tracked toggles
A Screen Time flip emits `~ 'Screen Time' AXValue '1' -> '0'`. A Downtime flip emits `~ 'Scheduled' AXValue '1' -> '0'`. Pipe those lines to your alerter.
“One attribute transition emits one line. Everything else in the audit path is downstream of that.”
Sources/MCPServer/main.swift:843
Surfaces the AX audit has been pointed at
The counted numbers
Enforcement models in the category
Audit layer that rides on top
Line of main.swift where the diff fires
Kernel extensions in the audit path
The honest trade
This audit layer does not replace enforcement. It is not a parental control app. It does not block YouTube, it does not meter Roblox, it does not ship a vendor dashboard for your phone. It reads the accessibility tree. A child who knows what they are doing can still kill its process, the same way they can kill Qustodio or Bark.
What it buys you is independence. The enforcement app and the audit layer die separately. If the app is killed, the audit is still reading the System Settings tree and sees the state drift. If the audit is killed, the app is still enforcing. Two separate processes, two separate termination events, and both of them are loud, not silent.
That is the only correction this page is offering to the category. Every “best parental control apps” review picks a winner on features. None of them picks a second process that verifies the first one is still on. That is the gap, and it is the one worth filling.
Want to see the AX audit running against your setup?
Fifteen minutes, real hardware, any of the four enforcement models. We show the diff, you decide if it belongs next to your chosen app.
Frequently asked questions
Why isn't this article a ranked list of the best screen time parental control apps?
Because the SERP already has fifty of those. Every listicle compares features and prices and lands on some mix of Qustodio, Bark, Norton Family, Apple Screen Time, and Circle. They all miss the same thing: every one of those apps reports its own status. If the app is disabled, the status page is also disabled. That is a category-wide blind spot, and it is unrelated to which app you pick. This page describes the four enforcement models underneath those apps and an independent audit layer that reads the macOS accessibility tree so tamper shows up regardless of which vendor you trust.
What are the four enforcement models parental control apps use on macOS?
Built-in, network, agent, and MDM. Built-in means Apple Screen Time, enforced by the OS itself through Family Controls. Network means DNS filtering on the home router or an always-on VPN, so traffic gets blocked before it reaches the device. Agent means a third-party app installs a macOS process that enforces time limits and site blocks locally (Qustodio, Bark, Norton Family, Mobicip). MDM means enrollment into a device management profile that pushes restrictions down as a policy. Each model has different failure modes, and this article lists them honestly.
What is the anchor fact the audit approach is built on?
Sources/MCPServer/main.swift line 843 watches attributeName == 'AXValue' across successive accessibility-tree snapshots and emits a text_changes line whenever that attribute transitions on any element. Applied to the System Settings process (bundle com.apple.systempreferences), this produces output like `~ 'Screen Time' AXValue '1' -> '0'` when the master Screen Time toggle flips off, and `~ 'Scheduled' AXValue '1' -> '0'` when Downtime gets disabled. Because the signal comes from the same tree Apple's UI renders, it is independent of whatever parental control vendor you chose.
Does this work for third-party parental control apps, not just Apple Screen Time?
Partially. The MCP server can open any macOS app by bundle ID and traverse its accessibility tree with macos-use_open_application_and_traverse, then refresh_traversal produces snapshots and diffs. So if Qustodio, Bark, or Norton Family exposes its on/off state as an AXCheckBox or AXButton title (most accessible apps do), the same AXValue transition signal works. Apps that do not expose their state to accessibility APIs are not observable from this layer, and that is a reason to favor accessible vendors.
What permissions does the audit layer require?
Accessibility only. Grant at System Settings, Privacy and Security, Accessibility. Screen Recording is optional and only needed if you want PNG screenshots saved alongside the traversal text file. Full Disk Access is not required. MDM enrollment is not required. A Managed Apple ID is not required. The audit works as a pure read of the AX tree with no kernel extension and no TCC-protected storage.
Can my kid disable the MCP audit layer by killing its process?
Yes, in the same way they could disable any parental app by killing its process, so this is not a silver bullet. The useful property is that the audit layer is separate from the enforcement app. If the enforcement app is killed, the audit layer survives and the next refresh_traversal call sees 'Screen Time' AXValue still at '1' even though the enforcement process is gone, and you can alert on the mismatch. If the audit layer is killed, the enforcement app is still running. Killing both requires two separate actions and is loud, not silent.
How many MCP tools does the server expose and what are they?
Six, defined between main.swift:1300 and main.swift:1408. They are: macos-use_open_application_and_traverse (open an app by name, bundle ID, or file path and return its AX tree), macos-use_click_and_traverse (click a point or an element found by text, optionally type and press a key, then traverse), macos-use_type_and_traverse (type text into the focused field then traverse), macos-use_press_key_and_traverse (send a key with modifiers then traverse), macos-use_scroll_and_traverse (scroll at a point then traverse), and macos-use_refresh_traversal (re-read the tree with no action). For audit, refresh_traversal is the one that runs on a timer; the others are only needed for setup.
Why is the coordinate system worth knowing for this use case?
Because the audit runs on macOS where many setups have multiple displays with negative x coordinates. The server uses a single logical point space: screen 0 starts at (0, 0), a left external monitor can sit at x around -3840, a right external monitor at x around 3456, and backingScaleFactor is 1.0 so one point equals one pixel. Click and scroll calls use the same space as the AX tree reports. Setting the audit up from the side, not from the child's main display, is a small operational win.