Computer MCP
Computer use you can actually leave running.
A macOS computer-use MCP server with the guardrails on by default. Passwordfields are blacked out while the screenshot is still in memory. Nothing clicksor types until a human says yes. Every call is written to an append-only log.
No account, no API key, no model inside it. MIT.
npx @agent360/computer-mcp
No Swift needed: the package ships a universal binary for Apple siliconand Intel. It carries the ad-hoc signature macOS needs to run it at all -not a Developer ID signature, and not notarized. Gatekeeper may thereforeask you the first time.
computermcp.dev · Security model
Why
Handing an agent your keyboard, mouse and screen is the most useful thing youcan give it and the least reversible. A screenshot of a working developer's Maccan contain a password manager mid-unlock, a .env open in the editor, orcustomer data. A stray keystroke in a terminal is not a typo - it is a command.
Most desktop-automation MCP servers hand all of that over at once, with no wayto say that, but not that. So the careful people don't run them on the machinewhere the work actually is.
This is the same capability with the dangerous edges answered.
The three gates
1. Passwords never reach the model. Secure text fields and password-managerwindows are painted opaque black on the bitmap in memory, before the PNG iswritten. There is no moment where an unredacted picture of your desktop existsas a file. Native fields expose the role AXSecureTextField; fields in a webpage expose role AXTextField with the subrole AXSecureTextField. Checkingonly the role would catch native fields and let every browser password boxthrough - so both are checked.
2. Nothing clicks until you say yes. The first write action opens a realmacOS dialog naming what is about to happen. Password managers and terminals askevery single time, even after the session was approved, even in allow mode -that one is not configurable. If nobody answers the dialog, the answer is no.
3. Everything is written down. ~/.local/state/computer-mcp/audit.jsonl,mode 0600, append-only: every call, its target app, and whether it was allowedor refused with the reason. Typed text is stored as a length and a saltedSHA-256 prefix, never in clear - an audit trail full of passwords is its ownbreach. The salt is random per run and never written down, because an unsaltedhash of a short password can be guessed offline by whoever holds the log. Thehonest cost: two actions can be compared within one run, not across runs.
Each gate has a test, and each test has been mutation-checked: break the code onpurpose and the test goes red. See Testing.
Install
# Claude Code
claude mcp add computer -- npx -y @agent360/computer-mcp
// Cursor, VS Code, Codex CLI, Windsurf - mcp.json
{
"mcpServers": {
"computer": { "command": "npx", "args": ["-y", "@agent360/computer-mcp"] }
}
}
Then grant two macOS permissions: System Settings → Privacy & Security →Accessibility, and the same under Screen Recording. Ask your agent to callcomputer_permissions and it will tell you what is still missing.
Which app do you grant them to? macOS attributes these to the responsibleprocess, and which process that is depends on how you launched the server. Runfrom a terminal, it is usually the terminal. Run by an MCP client over npx, itmay be the client instead. The honest answer is: grant it to whichever app thesystem dialog names, and if no dialog appears, start with the app that launchedthe client and check computer_permissions again.
Untested, and we would rather say so: we have not yet measured this from aclean machine with permissions reset, so we cannot tell you with certaintywhich of the two it will be in your setup, nor whether upgrading the packagere-prompts. The helper is ad-hoc signed, which means its code identity changeswith every build - if macOS keys your grant to the helper rather than to thehost app, an upgrade could silently revoke it.Issue #4 tracks themeasurement. If you hit either behaviour, telling us what you saw is a realcontribution.
Modes
CMCP_MODE |
Behaviour |
|---|---|
readonly |
Write tools are not even listed. The agent can look and cannot touch. |
ask |
Default. One dialog grants the session. Dangerous apps still ask every time. |
allow |
Writes proceed without asking, still logged. Dangerous apps still ask. |
CMCP_ASK_TIMEOUT (seconds, default 60) controls how long a dialog waits beforeit refuses.
Tools
28 tools: twelve that look, sixteen that touch. In background mode - thedefault - the sixteen that could take over your screen are not offered at all.
**Look:** `computer_pending` · `computer_screenshot` · `computer_inspect` · `computer_find` ·What you get today, honestly.
npx @agent360/computer-mcpcurrently serves 0.1.0, which has 12 tools. The 28 tools described here are the source: they are built and tested, but not published yet. Building from source takes about seventeen seconds if you want them now.
computer_wait_for · computer_focused · computer_apps · computer_windows ·computer_permissions · computer_displays · computer_menus · computer_audit
Touch: computer_launch · computer_quit · computer_paste · computer_window · computer_space · computer_menu · computer_press · computer_set_value · computer_ask_user ·computer_click · computer_drag · computer_type · computer_key · computer_scroll ·computer_move · computer_activate
computer_ask_user is the one that cannot carry a secret. It returns trueor false, never text. The agent puts the cursor in the field, the dialog namesthe app and the window it is about to land in - written by the server, not bythe model - and you type on your own keyboard. There is deliberately no routethrough this server for a password to reach a model.
computer_set_value writes into a field behind another window withoutmoving your pointer, and refuses on a secure field every time. We removed thatcheck on purpose once: the modified build wrote into the password box. It is theonly thing standing there.
computer_wait_for waits for an element to appear instead of takingscreenshots in a loop. Twenty polls cost one call here and twenty images theother way.
computer_inspect reads the accessibility tree - roles, titles, values, frames -so the agent can click a button by knowing where it is instead of guessing frompixels. computer_find narrows that to the elements matching a role, a title ora substring. Values of secure fields are never returned, not even to the agent.
Deliberately absent: no shell execution, no arbitrary file access, no URLfetching. Each would be one line of code. A computer-control server with a shellinside it is remote access under a friendlier name. If you want a shell, installa shell MCP server - then you have chosen it, and the choice is visible in yourconfig.
Without taking over your screen
computer_click and computer_type go through the system's own input tap, sothey land wherever the keyboard focus is and they move your real pointer. Thatis fine when you are watching. It is not fine when you are working in anotherwindow.
computer_press takes the other route: it fires the element's ownaccessibility action. That works while the window is behind another one, and itmoves nothing on your screen. computer_find is how the agent locates theelement to press.
computer_find { "app": "com.apple.Safari", "role": "AXButton", "contains": "Log in" }
computer_press { "app": "com.apple.Safari", "contains": "Log in" }
Two or more matches is a refusal, not a guess - the agent gets the candidatesand has to narrow it down, because pressing the first plausible button isexactly the kind of almost-right action nobody notices afterwards.
The consent dialog still comes to the front, and the apps on the always-ask liststill ask every time. computer_press names its target app, and that name iswhat the gate judges - so pressing something in 1Password asks even when1Password is nowhere near the front.
Several agents at once. Each MCP client starts its own server, so a secondchat is just a second process. They share one audit log, and every line carriesa per-server session mark - set CMCP_CLIENT=<name> and the line carries thattoo, so the log answers which conversation clicked. Fifty interleaved writesfrom two servers, zero torn lines: test/concurrent.mjs.
What is not solved yet: two servers pressing at the same time still shareone pointer and one focused window, and there is no lock between them. Usecomputer_press for the background work, and keep the coordinate tools for thesession you are actually watching.
What it does not do
- macOS only (14+). No Windows or Linux build, and none planned.
- Only what macOS marks as secure is redacted. A password in a plain texteditor or a token in a terminal buffer is not marked and will not be hidden.Use
readonlywhen the screen holds something the system cannot know about. - Consent is not containment. After you approve, the agent drives your realMac - that is what you approved. If you need a boundary rather than adecision, run it in a VM. That is the honest answer, not a missing feature.
- Prompt injection stays possible. The dialogs and the log make it visiblerather than silent. They do not make it impossible.
Building from source
git clone https://github.com/Agent360dk/computerMCP
cd computerMCP/helper && swift build -c release # the privileged binary
cd ../mcp-server && npm install
CMCP_MODE=readonly node index.js
The helper is a separate Swift binary with zero third-party dependencies.It is the part that uses Accessibility and Screen Recording, it is smallenough to read in one sitting, and it can be replaced without touching theserver. (Which process macOS grants those permissions to is a separatequestion, and an open one - see the note under Install.) Every package inside a binary that privileged is a vendoryou are trusting without having chosen to.
Testing
./test/run-all.sh # everything, full output kept in a log
python3 test/redaction-unit.py # the four redaction checks
node test/server-e2e.mjs # the MCP protocol, read paths, readonly refusal
node test/failclosed.mjs # an unanswered dialog must refuse
node test/claims.mjs # every claim this README makes
node test/concurrent.mjs # two servers at once: no torn lines, both identifiable
./test/redaction-proof.sh # live secure-field detection (needs a normal desktop)
claims.mjs checks the sentences on the front page against the code: that aterminal still asks in allow mode, that a harmless app does not (otherwise"refuse everything" would pass), that typed text reaches the log only as alength and a hash, and that no shell, file or URL tool has appeared.
Where a check cannot be made meaningfully - no secure field happens to be onscreen - it reports SKIPPED, not passed. A green suite that measured nothing isthe failure mode these tests exist to avoid.
redaction-unit.py builds its own image instead of measuring the live screen.The first version measured the real desktop - and on a machine where the editorruns full-screen the test window could not appear at all, so the test measuredan empty screenshot and called it a pass. A security test that passes when itcannot see anything is worse than no test.
redaction-proof.sh still exercises the live path and needs a desktop that isnot in full-screen mode. It fails loudly rather than skipping quietly.
Help build it
The redaction list holds the password managers we thought of. It does not holdyour banking app, your company's secrets manager, or whatever is popular whereyou live. One team cannot write that list; many people adding one line eachcan - and every app someone contributes makes the tool safer for everyone whoinstalls it afterwards.
That takes an issue formand no code. So does writing down how some Mac app actually behaves, which isknowledge that currently only exists in the heads of people who already fought it.
The wishlist is the rest: open items, sized honestly, none of themassigned. How contributing works.
Who makes this
Built by Agent360, a Danish shop building agents thatdo real work:
- Browser MCP - the same idea for a real,logged-in Chrome. Written alongside this one, and the two share their lessons.
- JesperAI - voice agents that hold an actualconversation on the phone.
- ForbrugerAgenten - an agent that reads yourhousehold bills and switches your provider for you.
Everything here is MIT and runs on your machine. None of the above is required,bundled, or phoned home to.
Privacy
Nothing leaves your machine because of this server. There is no account, notelemetry, no server of ours in the path, and no network call the server makeson its own.
- Screenshots go to the MCP client you configured - the same place the restof your conversation goes - and nowhere else. Secure text fields are blackedout in the image buffer before the PNG is ever written, so a password is notin the file that is sent.
- The audit log lives only on your disk, at
~/.local/state/computer-mcp/audit.jsonl. It stores a salted fingerprint oftyped text, never the text. Delete the file and it is gone. - We collect nothing. No identifiers, no usage counts, no crash reports.
Full policy: https://computermcp.dev/privacy.html
Licence
MIT © Agent360 Group ApS.