Tool reference
Every tool, its input and output schema, its annotations, and the scope it
needs.
Error reference
The error envelope and every code that can reach you.
How the surface is organised
Tools fall into four groups, and the groups are also the permission model.
Each group maps to one scope:
devices:read, devices:act, devices:lease,
and runs:start. The mapping partitions the surface exactly, so every tool
belongs to exactly one scope and a new tool that forgot to declare one would
be invisible to every credential. See Authentication.
What is not on this surface
Billing, purchasing, returning an order, revoking a key and leaving an organisation are not on the MCP tool surface. The REST API lets an API key withorders:place start a prepaid Checkout order; an admin
must issue or approve that key. Checkout still requires a person to complete
payment. Billing, returning an order, revoking a key and leaving an
organisation remain outside the MCP tool surface.
Every result is typed
A successful call returnsstructuredContent, validated against the
outputSchema that tool publishes. The same value is also written into a text
block, which is what earlier consumers read.
That duplication is transitional. structuredContent is the machine readable
source of truth; the text block’s promise to parse as JSON is on a deprecation
track and will retire once the typed shape has been stable for at least one
release cycle. Read structuredContent in new code.
Errors are the exception, and deliberately so. An error result carries its
envelope in the text block and never in structuredContent, because a
standard MCP client validates any structuredContent it sees against the
tool’s output schema with no exemption for errors. See
Reading a trace for how to consume one.
Every tool is annotated
Each tool publishes all four MCP annotation hints explicitly, because an omitted hint is indistinguishable from an unconsidered one, and because the protocol’s defaults are the wrong ones for a closed device surface.openWorldHintisfalseeverywhere. Tools reach the fleet you configured and nothing else.destructiveHintmarks the tools that can destroy state you did not create: the two run tools hand the device to an autonomous loop. A tap, a swipe, a hold, typing and a key press are not marked, because they do what a finger does and a client that prompts on the hint would prompt on every one of them. The flag that keeps a person in the loop is_meta.requiresUserInteraction, which is ours and which no “do not ask again” turns off.idempotentHinton action tools reflects the idempotency key contract: a retry that reuses its key replays the recorded outcome rather than executing again.readOnlyHintmarks the tools that only observe.
Inputs are strict
Every tool’s input schema rejects unknown keys rather than stripping them. A misspelledleaseid, or a parameter your model invented, fails loudly instead
of travelling on to a real device with a silently missing argument.
leaseId is optional on every action and observation tool. If you provide it,
it must match the lease your organization currently holds; a stale id returns
lease_mismatch without acting. Omit it to use the current lease, or to take a
free device when your key has devices:lease. release_device still requires
the id. When your organization does not hold the device and the tool will not
take it for you, the refusal is lease_required.
The surface is a frozen contract
The tool surface is frozen from the launch on 2026-09-25 onward. The tool names and fields published on that date are the baseline, and from then on the surface evolves under a published program rather than at will.- Additive changes are allowed at any time: new tools, new optional parameters, new output fields, new error codes. Existing callers are unaffected.
- A change of meaning without a change of shape is declared rather than
versioned: the tool description carries an
@sincenote and the changelog records what changed. - Renames and removals are breaking. There is no
tap_v2family and no parallel endpoint. A breaking change goes through the deprecation program in Versioning and compatibility, and it is announced in the changelog before anything moves.
Do not hard code a tool count. The count has changed more than once, and any
number written into prose ages badly. Ask the server:
listTools reflects
your credential’s true surface at that moment.The surface is stateless
The HTTP transport builds a fresh server per request. There is no session affinity, and a lease is not session state: it travels as an explicit parameter on every call. That is what lets any process holding aleaseId
continue a session, and what makes GET and DELETE on the endpoint
meaningless.
Some capabilities do depend on a live bidirectional connection. Progress
notifications and human takeover both need one, and the stateless HTTP path
cannot carry either. See Transports and
Progress and takeover.
Where to go next
Transports
stdio and hosted HTTP, and what actually differs.
Authentication
Two credential channels and role-based scopes in one auth context.
First session
The four beats of a session, one call at a time.
Agent tier
Hand a goal to a worker instead of driving each step.