Skip to content

0.4.0: works alongside you, clipboard tools, MCP 2025-11-25, CI - #2

Merged
sheehanmunim merged 12 commits into
mainfrom
feat/0.4.0-hardening
Sep 19, 2026
Merged

sheehanmunim merged 12 commits into
mainfrom
feat/0.4.0-hardening

Conversation

@sheehanmunim

Copy link
Copy Markdown
Member
  • Never takes over the user's pointer or keyboard on macOS (no cursor warps, no global event-tap posts; per-process delivery or AX actions). Windows/Linux prefer UIA/window messages and label any fallback that uses the real pointer as via cursor. README: Works alongside you.
  • New clipboard_read / clipboard_write tools (30 total).
  • press_key: real virtual keys on Windows (pageup/F-keys no longer typed as text), layout-aware keys on macOS, punctuation/numpad/F13+ everywhere.
  • MCP protocol negotiation (2025-11-25 / 2025-06-18 / 2025-03-26, falls back to 2024-11-05), instructions, tool and server titles, identical tool order on both hosts, -32700 on malformed JSON (macOS).
  • macOS argument bounds match Rust (scroll amount, max_depth, max_elements, max_width).
  • npm launcher honours COMPUTER_USE_BINARY before the platform check (Linux), installs atomically, times out downloads.
  • CI: cargo test on Ubuntu + Windows, swift build on macOS, extension test, tool-parity check; mcp-publisher pinned with sha256; checkout v7.
  • interprocess 2.4.4, uiautomation 0.25.1; version 0.4.0 everywhere.

…ime out downloads

The override was checked after the no-prebuilt-binary exit, so Linux users
could never use a binary built from source. Downloads now extract into a
staging directory that is renamed into the cache, so an interrupted or
concurrent first run cannot leave a half-written binary behind, and a
stalled connection fails after COMPUTER_USE_DOWNLOAD_TIMEOUT_MS (120 s).
…more names everywhere

Windows sent any name the uiautomation key syntax did not know (pageup,
pagedown, forwarddelete, f-keys past its table, punctuation names) as
literal text, and treated { } ( ) as markup. press_key now builds SendInput
records from virtual-key codes, resolves characters through VkKeyScanW, and
sends the whole chord in one batch.

A shared keys module parses names once for Windows and Linux: punctuation
names, numpad0-9 and operators, F1-F24 (F20 on macOS), insert, and
separator-tolerant spellings like Page_Down. macOS resolves characters
through the current keyboard layout (TIS + UCKeyTranslate) with the ANSI
table as fallback, and posts key events from a private event source so the
user's held modifiers never leak into the agent's keystrokes.
…server

max_depth is clamped to 1-60, max_elements to 1-5000 and max_width to
0-8000, so an oversized request cannot walk a huge tree for minutes or ask
ScreenCaptureKit for an absurd image. The get_app_state window property now
declares its type (a window index or "agent").
…gn tool order

Both servers advertised only 2024-11-05. They now echo 2025-11-25,
2025-06-18 or 2025-03-26 when a client asks for one and fall back to
2024-11-05 otherwise. initialize carries short usage instructions and
serverInfo gains title and websiteUrl (name stays mt-desktop); every tool
gets a top-level title derived from annotations.title.

The Swift tool list now uses the Rust order (desktop tools, then browser
tools) and the press_key modifiers text that had drifted between them. The
macOS stdin loop answers malformed JSON with -32700 and non-request JSON
with -32600 instead of staying silent.
…p-publisher

ci.yml runs cargo test on ubuntu-latest and windows-latest, swift build on
macos-15, the Chrome extension test, and scripts/check-tool-parity.mjs,
which parses the Swift and Rust tool literals and fails on any difference
in order, text or schema other than the two deliberate extras. The
registry workflows download a pinned mcp-publisher (1.8.1) and verify its
sha256 instead of running whatever "latest" is; checkout moves to v7.
Plain-text clipboard access, for pasting long or multi-line values where
set_value is rejected and type_text is slow, and for reading what a copy
shortcut produced. macOS uses NSPasteboard; Windows (Win32 clipboard) and
Linux (X11 CLIPBOARD selection) use arboard with its image support off.
The Linux handle lives for the whole process because an X11 selection
owner must stay alive to answer pastes. Reads are capped by max_chars
(default 20000, at most 200000) with a note when text is cut off.

Neither tool needs the accessibility backend or permission, so both answer
when it is unavailable. 30 tools now; the Rust surface test and the README
list are updated.
uiautomation_derive 0.7.9 needs syn 3.0.4 or later, so syn moves from
3.0.3 to 3.0.6 with it.
Every fallback that warped the real cursor (CGWarpMouseCursorPosition) or
posted to the global HID tap is gone: clicks, right-clicks, hovers, drags
and scrolls that cannot use the SkyLight window route are now posted to
the target app's process, and when no target app is known the call is
refused with an error instead of borrowing the pointer. The user-presence
yield guard only existed to soften those takeovers and is removed with
them (COMPUTER_USE_COMPUTER_USE_YIELD_SECS no longer does anything).

New non-pointer routes: right_click tries AXShowMenu on an element, and
scroll steps the enclosing scroll area's scroll bar when events cannot be
routed. scroll now rejects amount <= 0 and caps it at 100 like the Rust
server, and aims at the window centre instead of a fixed offset. Synthetic
events come from a private event source, so modifiers the user is holding
cannot turn the agent's click into a cmd-click.
…en it is not

Windows scroll no longer moves the cursor onto an element: it uses the
element's UI Automation ScrollPattern (or the nearest ancestor's), then
wheel messages posted to a classic Win32 control, and only as a last
resort moves the real pointer. Drags inside one classic Win32 control are
delivered as posted messages. Every result that used real mouse input on
Windows or Linux (XTEST) now ends in "via cursor".

The click, right_click, hover, scroll and drag descriptions state the
per-platform guarantee on both hosts, and the README gains a "Works
alongside you" section: on macOS the user's pointer and keyboard are never
taken over and uncovered cases are refused; on Windows and Linux it is best
effort and reported. The retired macOS yield flag leaves the README.
npm/package.json, server.json (server and package), the Rust crate and
lock, both servers' serverInfo, and the Chrome extension manifest, which
had drifted at 0.2.8. Host ids and the extension name are unchanged.
Copilot AI lite review requested due to automatic review settings September 19, 2026 05:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sheehanmunim
sheehanmunim merged commit 4c08a9a into main Sep 19, 2026
4 checks passed
@sheehanmunim
sheehanmunim deleted the feat/0.4.0-hardening branch September 19, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants