Skip to content

MCP: a run_on_device tool runs simctl, adb or devicectl against the session's lease #949

Closed

Description

@V3RON

Problem

The MCP server has four tools: list_devices, lease_simulator, release_simulator, lease_status. None of them touches the device. After lease_simulator, an agent on MCP still drops into its shell, runs simlock simctl install <UDID> …, and copies the UDID out of the tool result into every command. The docs say so: "The MCP tools lease and release devices. They do not run commands on the device" (getting-started/connect-your-agent.mdx).

The daemon already has the operation this needs. device.exec runs one simctl, adb or devicectl command against a lease on the machine that owns the device and streams the output back (docs/internal/flows/device-exec.md). The HTTP API (POST /v1/leases/{id}/exec), the gateway and the programmatic client use it. The refusal list, the 10 minute limit and the no-terminal rule all live there.

Proposal: one MCP tool, run_on_device, with inputs tool (simctl, adb, devicectl) and args, optionally stdin. It runs device.exec against the session's lease, so no device id is passed or copied. The result carries stdout, stderr and the exit code. Refused commands come back as the same refusal device.exec gives today.

With it, an agent on MCP alone can install, launch and screenshot without a shell. With #948, the shell path gets the same "the device is implied" behaviour, so both paths read the same in the instructions text (#147).

Context

Found in the 2026-10-23 product review. #147 lists "any new MCP tool" as out of scope for the instructions text; this is the tool it left out.

Facts for the spec session:

  • device.exec output is streamed in chunks; a tool result is one message, so the tool collects the output up to a size cap and says when it truncated. Binary output (a screenshot to stdout) does not survive UTF-8 decoding; the docs already tell HTTP users to write to a file, and the same applies here.
  • The MCP session already knows its lease (lease_status), so run_on_device without a lease answers the same way release_simulator does.
  • Through simlock --gateway mcp, the command runs on the worker that holds the device, as device.exec does for every other caller.
  • src/mcp/server.ts registers the four tools with registerTool; the fifth follows the same pattern and the same contract schemas in src/mcp/contracts.ts.

Written by an agent.

Activity

  1. added
    request:newInbox. Never picked up, body never edited.
    on Oct 23, 2026
  2. V3RON commented on Oct 23, 2026

    @V3RON
    ContributorAuthor

    Being specified in #951. This issue stays open until that feature ships.

    Written by an agent.

  3. V3RON commented on Oct 23, 2026

    @V3RON
    ContributorAuthor

    When this is specified: #157 adds simlock instructions, the rules text agents follow, with one ## section per surface. The task that ships this request should update the ## MCP section in the same PR, so agents learn the new command.

    Written by an agent.

  4. github-actions commented on Oct 24, 2026

    @github-actions
    Contributor

    Shipped as #951.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    request:newInbox. Never picked up, body never edited.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions