Skip to main content
Glama

Robot Actions — Remote Device Control

iOS gamepad state

ios_gamepad_state

Present a REAL game controller to an iOS device and set its state. The device registers a virtual DualShock 4 and receives genuine controller HID, so NATIVE apps see a GCExtendedGamepad and a web page sees a W3C standard-mapping pad in navigator.getGamepads(). It shows up in Settings > General > Game Controller. No Safari page is required.

HOW TO FIRE INPUT PROPERLY: • One call = ONE frame = one instant in time. A button stays pressed until you send a frame WITHOUT it, so every press needs a matching release frame — exactly like keydown then keyup. Sending press after press just holds them all down. • For anything that should look played rather than stepped — mashing, combos, a stick sweep — pass frames instead of calling repeatedly. The device plays the whole sequence out at intervalMs (default 33 ms ≈ 30 fps). A round trip per frame cannot reach that cadence, so a rapid sequence built out of single calls will always read as held buttons. • Alternate press and release inside frames: [{buttons:[1]}, {}, {buttons:[0,1]}, {}] is tap A, release, tap A+B, release. • Axes are [leftX, leftY, rightX, rightY], -1..1. Sweep them across frames to roll a stick; omitted axes read as 0. • READ THIS BEFORE REPORTING A STICK BUG: a stick axis can only express RIGHT and UP on axes[0..1], because the report's joystick fields are unsigned. The left stick's full 360-degree analog push IS delivered, but it arrives on the D-PAD — buttons[12..15], and GCExtendedGamepad.dpad.xAxis/yAxis for native apps, which are bipolar. Reconstruct it as x = right - left, y = down - up. Pushing left and reading axes[0] === 0 is the EXPECTED, structural behaviour, not a fault to debug. • While a sequence is playing, this call owns the pad — a controller streamed from a live viewer is paused and resumes on its own shortly after. • Confirm the pad EXISTS with ios_gamepad_status; confirm VALUES in the app under test.

Input routes to whatever holds focus, so foreground the app under test first — measuring while Settings or another app is in front reads as "nothing works".

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idNoIGNORED. Accepted so older callers do not break. The controller is a real device on the phone and its identity is fixed when it is registered, so passing an id here does NOT re-attach it as that controller and does NOT change what a tester displays — it is silently discarded. Read the current identity with ios_gamepad_status. Button mapping is always W3C standard order regardless.
axesNoAxis values -1..1: [leftX, leftY, rightX, rightY]. Omitted axes read as 0.
udidYesiOS device UDID
resetNoRegister a FRESH controller before sending this frame, instead of reusing the one already there. Use ONLY when the controller has stopped responding — the usual sign is that calls keep succeeding while the app under test sees nothing, and ios_gamepad_status still reports one as registered. Two costs, so do not pass it routinely: the call takes several seconds while the device adopts the new controller, and every registration leaves a permanent extra entry under Settings > General > Game Controller that the device never expires.
framesNoPlay a SEQUENCE of frames at intervalMs instead of setting one state. This is how you produce real gameplay input: include the release frames (an entry with no buttons releases everything). Capped at 300 frames. Overrides axes/buttons when present.
buttonsNoButton values 0..1 in W3C standard order (0-3 face, 4/5 shoulders, 6/7 triggers, 12-15 d-pad, 16 home, 17 touchpad on a DualShock). >= 0.5 counts as pressed. An empty/omitted entry releases everything.
intervalMsNoGap between frames in ms (default 33). Lower = faster mashing; 33 ms matches a 30 fps controller poll.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Added

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only give the generic mutation profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false), yet the description discloses far more: press persists until a release frame, sequences own the pad and pause a live-viewer stream, `reset` costs seconds and leaves permanent Settings entries, and the focus-routing behavior. It also warns which readings are expected (unsigned joystick fields) rather than bugs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long, but front-loaded with the core behavior and organized into labeled bullets where each sentence carries non-redundant operational information (frame timing, sequence format, stick quirk, reset cost, focus prerequisite). For a tool with this much footgun potential, nothing reads as filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description still tells the agent how to verify results (ios_gamepad_status for existence, the app under test for values) and covers registration side effects, cancellation behavior, and prerequisites. An agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, but the description meaningfully extends it: frames-to-intervalMs relationship and 300-frame cap, release semantics of an empty entry, the axes order and -1..1 range, the d-pad reconstruction formula for sticks, and the idle-passing `id` parameter. This is well beyond baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource: present a REAL game controller to an iOS device and set its state, plus what native apps and browsers observe. It is clearly distinct from the sibling ios_gamepad_status (which only confirms existence) and ios_gamepad_disconnect.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use guidance for every mode: single call for one frame, `frames` for played sequences, `reset` only when the controller has stopped responding, and foregrounding the app under test first. It also routes confirmation work to ios_gamepad_status and the app under test.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources