# MCP server

`agentlane mcp` serves `look`, `run` and `screenshot` over MCP on stdio, for agents that call tools rather than shell commands. The tools act on the lane this session claimed for this folder, and `look` and `screenshot` read a browser lane too. `init` writes the server into each agent's config.

## Starting the server

You don't start it yourself: each agent starts it from the entry `init` wrote. By hand it is:

```sh
npx agentlane mcp
```

The server speaks MCP over stdio. It finds the lane from the agent session that started it and the folder it runs in, so no tool takes a device id or a browser session, and no tool can reach another lane. A tool called before the session has a lane answers with the command that makes one.

The server serves the whole agent session. When one session holds lanes in several folders, as parallel subagents in their own worktrees do, each subagent should run `look`, `run` and `screenshot` as shell commands from its own worktree, or pass them `--worktree <dir>`.

The site builds the tool sections below from the server's own tool definitions.

## Tools

### look

What's on this session's simulator screen now, one line per element: role, id (testID), label and state. Read it before acting and after the screen changes. A nearly empty read (maps, canvases) comes with a screenshot: tap what it shows by point. On a lane that holds a browser and no simulator, or with browser: true, it reads the page in the lane's browser instead: role, ref (what the browser driver's CLI acts on), name and state.

Its title is "Look at the screen". It only reads.

| Argument | Type | What it is |
| --- | --- | --- |
| `interactiveOnly` | `boolean` | Only elements you can tap, toggle or type into. |
| `within` | `string` | An id or label: show only that element's subtree. |
| `depth` | `integer` | How many levels of elements to show. |
| `bounds` | `boolean` | Add each element's bounds in points, [x1,y1][x2,y2]. Simulator only. |
| `browser` | `boolean` | Read the lane's browser, when the lane holds a simulator as well. |

### run

Run Maestro flow YAML on this session's simulator and get back what changed on screen. A failure names the step, its kind, whether it reached the device, the screen now and selectors to try. Passing steps are recorded: 'node_modules/.bin/agentlane record save `<file>`' writes them as a flow.

Its title is "Run a Maestro flow". It acts on the app.

| Argument | Type | What it is |
| --- | --- | --- |
| `yaml` | `string` | Maestro commands, with or without an `appId:` header and `---`. Without one, appId or the last app used is added. |
| `file` | `string` | A flow file instead, absolute or relative to the lane's folder. |
| `appId` | `string` | The bundle id for YAML without a header. |
| `quick` | `boolean` | Tap without waiting for the screen to settle; for exploring, not for proof. |
| `env` | `object` | Flow variables, read as ${NAME}. |

### screenshot

This session's simulator screen as a JPEG, or the lane's browser viewport as a PNG when the lane holds a browser and no simulator, or with browser: true. `look` finds elements more cheaply; use this to judge how the screen looks.

Its title is "Screenshot the simulator". It only reads.

| Argument | Type | What it is |
| --- | --- | --- |
| `scale` | `number` | Shrink the image, e.g. 0.5. |
| `browser` | `boolean` | Screenshot the lane's browser, when the lane holds a simulator as well. |
| `crop` | `{ x, y, width, height }` | A region in points, as look prints bounds. Simulator only. |

## Where init registers it

`init` adds the server under the name `agentlane` to each agent's own config:

| Agent          | File                      |
| -------------- | ------------------------- |
| Claude Code    | `.mcp.json`               |
| Codex          | `.codex/config.toml`      |
| Cursor         | `.cursor/mcp.json`        |
| GitHub Copilot | `.mcp.json`               |
| Gemini CLI     | `.gemini/settings.json`   |
| Antigravity    | `.agents/mcp_config.json` |

Each entry runs a short `sh` script that looks for `node_modules/.bin/agentlane` from the project folder upwards and runs its `mcp` command, so the tools always come from the version the project installed. Without agentlane installed, the server exits with a message that says to add it:

```json title=".mcp.json"
{
  "mcpServers": {
    "agentlane": {
      "command": "sh",
      "args": ["-c", "d=\"$PWD\"; while [ ! -x \"$d/node_modules/.bin/agentlane\" ] && [ \"$d\" != / ]; do d=$(dirname \"$d\"); done; if [ -x \"$d/node_modules/.bin/agentlane\" ]; then exec \"$d/node_modules/.bin/agentlane\" mcp; fi; echo \"agentlane: no node_modules/.bin/agentlane in $PWD or the folders above it; add the toolkit to this project\" >&2; exit 1"]
    }
  }
}
```

With the Claude Code plugin, the same server is `plugin:agentlane:device`, and in a project without agentlane it still starts and answers every call with the install command.
