Computer use accessibility permissions stop working on macOS for three reasons: the grant landed on the wrong process, you granted it but never restarted the process that needs it, or macOS invalidated the grant when the binary changed on disk. The fix has the same shape every time. Grant both Accessibility and Screen Recording to the process that hosts your agent, quit that process, then launch it again.
macOS gates desktop automation behind TCC, the Transparency, Consent, and Control subsystem. Two TCC services matter for a computer use agent, and they fail in ways that look nothing alike.
| Permission | What it unlocks | What breaks without it |
|---|
| Screen Recording | Screen capture, window contents, window titles | Screenshots come back black or wallpaper-only, OCR finds no text, window titles return empty strings |
| Accessibility | Synthetic mouse and keyboard events, AXUIElement queries | Clicks and keystrokes go nowhere, accessibility tree queries error out, the agent reports success while nothing moves |
OpenOwl checks both at startup, before it registers any of its 42 tools. It calls AXIsProcessTrustedWithOptions for Accessibility and CGPreflightScreenCaptureAccess for Screen Recording. When either is missing, the server writes to stderr:
[OpenOwl] macOS permissions needed: Accessibility and Screen Recording
[OpenOwl] Grant access in System Settings > Privacy & Security,
[OpenOwl] then restart the server for changes to take effect.
Your MCP client captures that output into its own log, so it never reaches a terminal. Claude Desktop writes MCP server stderr under ~/Library/Logs/Claude/. Read the log first. The message names which of the two permissions is missing, so you can skip toggling switches at random.
OpenOwl ships for macOS 12 (Monterey) and later, on Apple Silicon and Intel. Everything below applies to that platform. Other computer use tools that support Windows or Linux have their own permission models, and none of this transfers to them.
Open System Settings, then Privacy & Security. Apple has moved the pane name between OS versions:
- macOS 12 through 14: Screen Recording
- macOS 15 and later: Screen & System Audio Recording
Find the process in the list, flip the toggle on, and take the "Quit & Reopen" offer if macOS presents one. If nothing in the list matches, add it by hand. Click the plus button, press Cmd+Shift+G, and paste a full path. macOS hides /usr/local/bin, /opt/homebrew/bin, and everything under ~ in the file picker, so typing the path is the one way to reach a CLI binary or a Homebrew install.
Run which owl to get the path if you installed through Homebrew or npm. Point at the .app bundle in /Applications if you are granting to a desktop client.
Accessibility sits in the same pane, one row away: Privacy & Security > Accessibility. The list works the same way, with a plus button and the same hidden-path problem.
Accessibility covers two capabilities that look separate but share one grant. Posting synthetic mouse and keyboard events needs it, which is how clicking and typing work. Reading the accessibility tree needs it too, which is how an agent finds a button by its label instead of guessing at pixel coordinates. Lose the grant and both stop at once. OpenOwl returns an error string on the tool result:
Cannot get focused element (accessibility permission may be required)
An agent that reads that message and keeps going will click at coordinates it computed from a stale screenshot. Stop the run when you see it.
You grant the permission, the dialog goes away, and two days later it is back. Four causes, ordered by how often they come up:
The binary changed. TCC stores a grant against a code signature and a path. Update through npm install -g openowl or brew upgrade, and the executable's hash changes. For an ad-hoc signed binary, macOS treats the new build as a different program and asks again. This works as designed, and you cannot pre-approve a future build.
You granted to a different client. Each MCP client gets its own grant. Approve Terminal while testing, then switch to Claude Desktop, and you start from zero.
macOS 15 shows a periodic reminder. Sequoia re-prompts apps that hold Screen Recording on a recurring basis. That dialog asks you to confirm a grant you already gave, and it revokes nothing on its own. Clicking anything other than allow does revoke it, so read before you dismiss.
The row went stale. The app sits in the list with the toggle on, but the row points at a path that no longer exists. The toggle looks correct and grants nothing. Remove the row with the minus button, then add it again.
When you want a clean slate, reset the service for one app:
# Find the bundle identifier for the app you launch the agent from
osascript -e 'id of app "Claude"'
# Reset both services for that bundle id
tccutil reset ScreenCapture com.example.yourclient
tccutil reset Accessibility com.example.yourclient
Omitting the bundle id wipes the grant for every app on the machine. Screen sharing, meeting tools, window managers, and clipboard utilities all lose access at once. Pass the bundle id.
A missing Screen Recording grant does not throw. The capture APIs return a valid image at the correct resolution and a normal file size, and they strip out every window's contents. What survives is the desktop wallpaper and the menu bar. The agent receives an image that looks plausible, describes an empty desktop, and clicks on nothing.
Look for this failure signature:
- Correct screen dimensions, plausible file size
- Wallpaper visible, menu bar visible
- Zero window contents, and an accessibility tree that returns no window titles
- A tool result that reports no error at all
Three other causes produce a black frame and are worth ruling out before you blame TCC. DRM-protected playback (Netflix, Apple TV, some Safari video) renders black in any capture by design, and no permission changes that. A window on another Space or on a display that is asleep captures as empty. And a capture during the login window, before you unlock with FileVault, has nothing to capture.
If the wallpaper is visible but every window is gone, TCC is your answer. If the entire frame is uniform black including where the menu bar should be, look at the other three.
TCC caches its decision per process. When a process asks whether it is trusted for Accessibility, macOS binds that answer to the process, and granting the permission afterward does not upgrade a running process in place. The same holds for screen capture access. OpenOwl's startup check runs once, so a server that started without permissions keeps behaving as if it has none until it starts over.
The subtlety is which process to restart. Restarting the MCP server alone does nothing when the grant belongs to the client that spawns it. Quit the client:
# Confirm the client process is gone
pgrep -fl "Claude|iTerm|Terminal"
# Confirm no stray server process survived
pgrep -fl owl
Cmd+Q closes the window on many Electron apps while the process keeps running. If pgrep still prints a PID, the app is alive and still holds the old TCC answer. Kill it, then launch it again.
Order matters here: grant first, then restart. If you restart before you finish granting, you get the same failure, which is how people convince themselves the permission "does not stick."
TCC attributes a permission request to the responsible process. For a child process, that is the parent that launched it. An MCP server binary like owl runs as a child of your MCP client over stdio, so macOS asks the client for permission and lists the client. The binary itself never appears, and adding it does not help.
Which row you need depends on how you launch the agent:
| How you run the agent | Process that needs the grants |
|---|
| Claude Desktop | Claude |
claude CLI from Terminal.app | Terminal |
claude CLI from iTerm2 | iTerm |
| Another MCP client | The client application itself |
| A launchd job or background agent | The executable the plist names |
| An SSH session | None. TCC has no graphical session to grant against |
That last row matters for anyone building a remote setup. TCC ties grants to a logged-in GUI session. Screen capture and synthetic input both fail over SSH no matter what you approve in System Settings. Run the agent on the machine whose screen it drives.
An app that has never requested a permission does not appear in the list at all. Launch the agent once so the request fires, then check again. If it still does not show, add it with the plus button and a pasted path.
Check the Accessibility bit from a shell:
python3 -c 'from ApplicationServices import AXIsProcessTrusted; print(AXIsProcessTrusted())'
That reports the state for whatever process is responsible for python3, which is your terminal app. It confirms the terminal's grant and tells you nothing about Claude Desktop's, so run the equivalent check through the client you use.
The end-to-end test is faster and covers both permissions at once. Open TextEdit with an empty document, then ask your agent to do three things in order:
- Take a screenshot and report the title of the frontmost window
- Read any visible text on screen
- Type the word
owl into the document
Now map the failure:
| Symptom | Missing permission |
|---|
| Window title comes back empty, screenshot shows wallpaper | Screen Recording |
| Screenshot is correct, typing produces nothing | Accessibility |
| Both fail | Neither grant is active, or you did not restart |
| Both succeed | You are done |
Confirm the binary itself runs before you go further:
owl --version
If that fails, the problem sits in your installation, and the quick setup guide walks through the install and API key steps in order. For anything the checks above do not cover, the OpenOwl help center has the installation, billing, and community support entry points.
One last note for anyone testing on the free tier. Free accounts get 50 tool calls per day, and retrying screenshots in a loop while you debug will spend them. Watch the count while you troubleshoot so you do not mistake a quota error for a permission error.
Three causes cover almost every case. You granted the permission to the wrong process, because macOS attributes the request to the parent app that spawned the agent binary. You granted it without quitting and relaunching that parent process. Or the binary changed on disk after an update, and macOS no longer matches it against the stored grant. Check which process owns the row in System Settings, quit that process, then launch it again.
That is the signature of a missing Screen Recording grant. macOS raises no error when a process lacks it. The capture API returns an image at the correct size with the wallpaper and menu bar drawn, and it strips out every window's contents. A black or empty screenshot at normal resolution and normal file size points at the missing permission.
Yes. TCC caches its decisions for the lifetime of a process. The process reads accessibility trust and screen capture access once, when it asks, and granting the permission mid-session does not hand a running process the new capability. Quit the MCP client with Cmd+Q, confirm the process is gone with pgrep, then launch it again.
macOS lists an app after it has requested the permission at least once, and it lists the responsible parent process instead of the child binary. Launch the agent once so the request fires, or add the process by hand with the plus button and Cmd+Shift+G to paste a path. macOS hides Homebrew and /usr/local/bin paths in the file picker, so run which owl first and paste the result.
No. TCC ties grants to a logged-in graphical session, and an SSH session has none. Screen capture and synthetic input both fail regardless of what you grant in System Settings. Run the agent from a local terminal or a local MCP client on the machine whose screen you want to control.