# Use Silan from your agent

Give your own AI agent or test tool real devices through Silan's MCP server, command line, REST API, WebDriver endpoint, skills and Python library.

Silan's engine serves four ways in, all on the Mac that holds the devices, all through the same safety rules:

| Way in | For | Address |
|---|---|---|
| MCP server | AI apps and agents (Claude Code, Codex, Cursor, OpenCode, the Claude app, any MCP client) | `silan mcp` over stdio, or `/mcp` over HTTP with a key |
| Command line | Scripts and people in Terminal | `silan` inside Silan.app |
| REST API | Your own programs | `http://127.0.0.1:47800/v1` |
| WebDriver endpoint | Appium-style test clients | `http://127.0.0.1:47800/wd/hub` |

The engine listens on this Mac only (127.0.0.1 and ::1). Every call needs a key, or a one-time **Allow** from you for an app connected through the Silan app.

## Connect an AI app

In **Settings › Connections** (or setup's **Your AI tools**), press **Connect** next to the app:

| App | What Connect does |
|---|---|
| Claude Code | Writes Silan into Claude Code's MCP settings. Start a new session. |
| Claude app | Writes Silan into the Claude app's settings. Quit the app and open it again. |
| Codex | Writes Silan into Codex's settings. Start Codex again. |
| Cursor | Writes Silan into Cursor's settings. Quit Cursor and open it again. |
| OpenCode | Writes Silan into OpenCode's settings. Start OpenCode again. |

For a coding app, Connect asks which tools it gets: the everyday set, or the testing set for testing an app you make. For any other MCP client, copy **The setup text for other apps**, a complete `mcpServers` entry, into that client's settings.

The first time a connected app calls a tool, Silan asks you: **Allow**, **Allow this time** or **Don't allow**. Silan names the app from the signature of the program that started it, so a program that only calls itself "Claude Code" is not Claude Code. Each app gets its own grant, and the Connections page shows what it did and when.

## MCP server

`silan mcp` is a stdio MCP server. It speaks to the engine on this Mac and offers a profile of tools:

| Profile | Tools | For |
|---|---|---|
| `core` (default) | 16 | Everyday tasks: look, tap, type, swipe, wait, open apps and links, hand over logins |
| `testing` | 32 | App testing: core plus scenarios, recordings, checks, notifications, test pushes, installs, location, clipboard, rotation, text size |
| `full` | 50 | Everything, including the built-in agent, routines and raw element queries |

Pick a profile with `silan mcp --profile testing`. The `SILAN_MCP_PROFILE` variable is read by the plugin launchers and the Claude app bundle, not by `silan mcp` itself. With `--key` or `SILAN_API_KEY`, `silan mcp` uses that key against the engine's `/mcp` listener instead and asks you nothing.

Every tool is a direct mapping of one REST operation, so the two never differ. The [MCP tools reference](/reference/mcp/) lists all 50 with their parameters.

### The loop an agent runs

1. `list_devices`, then `claim_devices` so no other agent uses the same device.
2. `observe`: a screenshot plus a compact list of elements with refs.
3. Act on a ref: `tap`, `type_text`, `swipe`, `launch_app`, `open_url`.
4. `wait_for` a condition inside the engine (an element shows or goes, text, an app, a notification, a stable screen) instead of sleeping.
5. `release_devices` when done.

A risky step answers `APPROVAL_REQUIRED` until you say yes in Silan. Passwords never reach the agent: it calls `fill_credential` (your Vault, 1Password or Bitwarden) or `request_person_login`, and you type.

### Plugins for Claude Code and Codex

The Silan plugin carries the MCP server config and the skills below. From a copy of the plugin folder:

```sh
claude plugin marketplace add /path/to/silan/Plugins
claude plugin install silan@silan
```

`claude mcp list` then shows the Silan server connected while Silan runs. The Codex plugin and the Claude app bundle (`silan.mcpb`) exist in the same folder; the Connect buttons in the app are the proven path for those two today.

## Skills

Public skills, MIT licensed, teach an agent to drive phones well through Silan. The Claude Code and Codex plugins install them. To use one without the plugin, copy its folder into your agent's skills folder, for example `~/.claude/skills/silan/`.

| Skill | Teaches |
|---|---|
| `silan` | The observe-act loop, element refs before pixels, leases, capabilities, errors, tool profiles |
| `silan-text-entry` | Typing, editing, keyboards, pickers, one-time codes, and never typing passwords |
| `silan-waits` | Waiting for screens, loading and notifications with `wait_for` instead of sleeps |
| `silan-safety` | What an agent must not do alone: send, pay, post, delete, logins, other people's data |
| `silan-app-guides` | Short maps of common iPhone and Android apps, plus patterns for shopping, forms and system prompts |

## Bring your own model

The `Examples/agent-loops` folder has three small, complete phone agents that start `silan mcp` and use the skills as their system prompt: one on the Claude API, one on any OpenAI Responses model, and one on any OpenAI-compatible local server (Ollama, LM Studio, llama.cpp, vLLM).

## Command line

The `silan` command ships inside the app at `/Applications/Silan.app/Contents/Helpers/silan`. It is not on your PATH; call it by that path or link it yourself.

```sh
SILAN=/Applications/Silan.app/Contents/Helpers/silan
$SILAN devices
$SILAN observe ios:00008120-001A2B3C4D5E6F70 --elements interactive
$SILAN tap ios:00008120-001A2B3C4D5E6F70 --text "Checkout"
$SILAN stop
```

The [command line reference](/reference/cli/) lists every command. On this Mac, `silan` finds the engine and its local key by itself through `~/Library/Application Support/Silan/engine.json`.

## REST API

The engine's REST API is described by one OpenAPI 3.1 document with 64 operations. The [REST reference](/reference/rest/) is generated from it.

- Base address `http://127.0.0.1:47800` (the real port is in `engine.json`). Loopback only.
- `Authorization: Bearer silan_sk_...` with a key you made on the **Connections** page under **For developers**. The `silan keys create` command answers `403` on the current release: make keys in the app.
- Requests with an `Origin` header are refused unless the origin is on the engine's allow list.
- Errors are RFC 9457 problem documents with a stable `code`, such as `TARGET_NOT_FOUND` or `DEVICE_LEASED`.
- Any device call accepts `Prefer: respond-async` and then returns `202` with a job.
- A device under another holder's lease returns `409 DEVICE_LEASED`; pass your lease token in the `Silan-Lease` header.

```sh
KEY=silan_sk_...
curl -s -H "Authorization: Bearer $KEY" http://127.0.0.1:47800/v1/devices
curl -s -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  -d '{"action":{"type":"tap","target":{"query":{"text":"Checkout"}}}}' \
  http://127.0.0.1:47800/v1/devices/ios:00008120-001A2B3C4D5E6F70/actions
```

Keys are scoped: which devices, which tool profile, which policy profile, and when they expire (30 days, 90 days, 1 year or never).

## WebDriver endpoint

`/wd/hub` is a W3C WebDriver endpoint in the Appium style, so an existing WebDriver client can open a session on a device, find elements (accessibility id, id, name, link text, partial link text, class name), act and take screenshots. It is not a full Appium server. Risky steps answer with a 500 until you approve them in Silan, then the same call works.

## Python

A Python library lives in the repository at `SDKs/python` (standard library only, Python 3.9 or later). It is not published yet (coming soon). Its shape:

```python
import silan

client = silan.Client()                      # finds the engine; the key comes from SILAN_API_KEY
with client.claim("ios:00008120-001A2B3C4D5E6F70") as lease:
    phone = lease.device()
    phone.tap(text="Checkout")
    assert phone.wait_for(text="Sent", timeout_ms=5000)
```

## Event stream

`GET /v1/events` is a server-sent event stream of device, approval, job and run events, for clients that follow a long task without polling.