cua-driver Python SDK
Rust-backed Python SDK and bundled executable for Cua Driver.
Product boundary
This package is for client applications importing Cua Driver as an SDK:
from cua_driver import CuaDriver
It does not contain a Python MCP protocol implementation. The optional
cua_driver.fleet module forwards service bytes to the shared Rust typed-MCP
client. See the candidate Fleet connection guide
for prerequisites, ownership, and release limits. Agents already have runtime-neutral
MCP clients and should configure the bundled server directly:
cua-driver mcp
The removed pre-release MCP facade used CuaDriver.stdio(),
AsyncCuaDriver, *Args, and transport classes. Application code imports the
typed Rust-backed SDK shown below; agent code supplies cua-driver mcp to its
agent SDK.
Installation
Install and usage docs live at https://cua.ai/docs/how-to-guides/driver/install and https://cua.ai/docs/reference/cua-driver/mcp-tools.
The wheel contains generated UniFFI bindings, a platform-specific Rust SDK
library, and the cua-driver executable. CuaDriver.create() loads the runtime
in the importing process and does not require the executable or daemon.
SDK example
import asyncio
from cua_driver import (
CuaDriver,
CursorReducedMotion,
EndSessionInput,
GetDesktopStateInput,
SetAgentCursorThemeInput,
StartSessionInput,
)
async def main() -> None:
driver = CuaDriver.create()
await driver.start_session(
StartSessionInput(session="demo", capture_scope=None, cursor_theme=None)
)
try:
await driver.set_agent_cursor_theme(
SetAgentCursorThemeInput(
session="demo",
theme_id="cua.default",
reduced_motion=CursorReducedMotion.AUTO,
)
)
desktop = await driver.get_desktop_state(
GetDesktopStateInput(session="demo", screenshot_out_file=None)
)
print(desktop.images[0].mime_type)
finally:
await driver.end_session(EndSessionInput(session="demo"))
await driver.shutdown()
asyncio.run(main())
SDK operations are asynchronous. Desktop observations return a typed ToolResult with
text, images, verification/error metadata, and structured_json / raw_json
for platform-extensible results. Session lifecycle calls return dedicated
generated records.
start_session is optional for ordinary calls. The runtime creates one
implicit session for this SDK transport and reuses it until shutdown, explicit
end, or five minutes of inactivity. Use a named session when application code
needs to configure or inspect that run explicitly.
The agent cursor is session-owned and initializes on the first cursor-bearing
action, including move_cursor. Its default theme and custom dotLottie
authoring workflow are documented in
docs/cursor-themes.md. Custom source is compiled
and installed with the local CLI; SDK and MCP tools select only an installed
theme ID. The built-in cursor shows the sanitized public session name in a
badge below the pointer.
Typed native-window migration
The next breaking release adds typed app and window discovery, window snapshots, and token-based clicks. Version 0.25 supports native-window operations through the generic tool surface; it does not expose this typed window API. Upgrade the bindings and native library together.
list_apps returns ListAppsOutput, list_windows returns ListWindowsOutput,
and get_window_state returns WindowStateOutput. click takes a required exact
target, a coordinate or element-token position, and an explicit delivery mode.
It returns ActionResult directly and raises DriverError.Tool on refusal.
Other action methods retain ToolResult.
Select a unique app and window, resolve an element from a fresh snapshot, request background delivery explicitly, then capture again to verify the intended UI change. An unsupported background route must not trigger an automatic foreground retry. Refresh stale tokens from the same exact window.
See the migration guide for input and return-type changes, and the complete Python and TypeScript examples for discovery, token selection, verification, and shutdown.
Authorization integrations
standard is promptless for normal automation. An application that needs to
authorize attachment to an existing logged-in Chromium profile can construct a
configured runtime with
CuaDriver.create_configured_with_authorization_host(options, host).
Implement DriverAuthorizationHost.authorize() in trusted application code
and return the request's exact digest with ALLOW, DENY, or CANCEL.
CuaDriver.create_configured_with_activity_observer(options, observer) emits
content-free action, refusal, grant, and session events. The observer cannot
change authorization or tool results. Use
create_configured_with_host_integrations when the application needs both.
See the SDK reference for complete examples and the callback trust rules.
CuaDriver.connect(socket_path) remains available while existing applications
migrate. It exposes the same methods over the installed daemon, but it does not
provide a second SDK contract.
shutdown() closes admission, waits for already admitted operations to finish,
and is idempotent. Calls started after shutdown fail with DriverError.Shutdown.
Destroying a binding handle releases native resources, but orderly applications
should still await shutdown().
Daemon-backed MCP host
Applications that must also expose MCP to an external agent can own a private daemon child. The child provides a stable permission identity and session lifetime for short-lived or external clients:
import asyncio
from cua_driver import CuaDriver, EmbeddedCuaDriverHost, get_binary_path
async def main() -> None:
host = EmbeddedCuaDriverHost(
binary_path=str(get_binary_path()),
host_bundle_id="com.example.your-app",
)
connection = await host.start()
driver = CuaDriver.connect(connection.socket_path)
try:
# Application calls use driver. An agent runtime can launch
# connection.mcp.command with connection.mcp.args and environment.
print(await driver.metadata())
finally:
del driver
await host.stop()
asyncio.run(main())
start() coalesces concurrent callers, stop() cancels startup and is
idempotent, and restart() returns a new generation/PID/endpoint. Destroy SDK
clients and MCP proxies before stopping or restarting, then reconnect from the
new connection. wait_for_exit(connection.generation) observes unexpected
termination. Dropping the host closes its parent-liveness pipe and kills the
child as a fallback, but orderly applications should still await stop().
Binary wrapper
The package also exposes the bundled executable:
from cua_driver import get_binary_path, run_cua_driver
print(get_binary_path())
exit_code = run_cua_driver(["mcp"])
Platform support
| Platform | Architecture | Status |
|---|---|---|
| macOS 13+ | Universal (ARM64 + x86_64) | Supported |
| Linux | x86_64 | Supported |
| Windows | x86_64 | Supported |
| Windows | ARM64 | Supported |
License
MIT License — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cua_driver-0.28.0-py3-none-win_arm64.whl.
File metadata
- Download URL: cua_driver-0.28.0-py3-none-win_arm64.whl
- Upload date:
- Size: 24.9 MB
- Tags: Python 3, Windows ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd457f963d5731e06c9dda77a319f005c33879c483c0fcdb96663ed9637ce1af
|
|
| MD5 |
2543d8e3f838eae697443859dde177dc
|
|
| BLAKE2b-256 |
b92b7f0d6bb60c328bd47bf604199e7de964d8fafeb5f7eace2c24636452a05b
|
File details
Details for the file cua_driver-0.28.0-py3-none-win_amd64.whl.
File metadata
- Download URL: cua_driver-0.28.0-py3-none-win_amd64.whl
- Upload date:
- Size: 26.7 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c31af3cadc8403d9b23e87f50cd8e24a6c0e975442aab9e998a1b636c4458e61
|
|
| MD5 |
b150f2eb16b481c3a26e64e156227c38
|
|
| BLAKE2b-256 |
46f0dcab528921332dc705494244e7f70028222ce5ac3216be1885cb2284724e
|
File details
Details for the file cua_driver-0.28.0-py3-none-manylinux_2_31_x86_64.whl.
File metadata
- Download URL: cua_driver-0.28.0-py3-none-manylinux_2_31_x86_64.whl
- Upload date:
- Size: 29.0 MB
- Tags: Python 3, manylinux: glibc 2.31+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
880d88118c6fd66b064c675d33ccb50bc0945721359b1e85b377ab1e41225b37
|
|
| MD5 |
c6a3c6a0cd8d6d3d876a3b6a60c36890
|
|
| BLAKE2b-256 |
1c7adf032ebf005bab6eef578e34559ed18e4c532eaffd6c7ec71a771d67ea9f
|
File details
Details for the file cua_driver-0.28.0-py3-none-manylinux_2_31_aarch64.whl.
File metadata
- Download URL: cua_driver-0.28.0-py3-none-manylinux_2_31_aarch64.whl
- Upload date:
- Size: 29.1 MB
- Tags: Python 3, manylinux: glibc 2.31+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc1e97553db297ae32f328d116ce3092ff7dcbabdfbafbb13226caace3da0874
|
|
| MD5 |
849058981e687d01f8334b0f6c7a285d
|
|
| BLAKE2b-256 |
e88b1e69c4181ee67007ae972ed8a55812b3e4e9f5ec72fffe65a2109aa9171a
|
File details
Details for the file cua_driver-0.28.0-py3-none-macosx_13_0_universal2.whl.
File metadata
- Download URL: cua_driver-0.28.0-py3-none-macosx_13_0_universal2.whl
- Upload date:
- Size: 40.8 MB
- Tags: Python 3, macOS 13.0+ universal2 (ARM64, x86-64)
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a30cdd8e07912e97c238dad4ef754e22e765c989626ab6683da67babe4af520
|
|
| MD5 |
f5ae1906cbabe15359b947fc70cd704d
|
|
| BLAKE2b-256 |
4db315d0c837e0050064e6c681512b4f65a16ea51853befe73930523340c063c
|