> ## Documentation Index
> Fetch the complete documentation index at: https://docs.autogrowth.farm/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> AutoGrowth runs social accounts on real phones. Everything a page describes happens on a physical device in the customer's own fleet, never through a social platform's API.
> The Companion is a macOS desktop app that runs on the customer's own Mac and manages the phones over USB — iPhones through WebDriverAgent, GrapheneOS phones through ADB and scrcpy. Nothing runs while the Companion is closed.
> The Companion builds, signs and installs WebDriverAgent on each iPhone itself. Never tell a customer to sign WebDriverAgent by hand in Xcode; Xcode is a prerequisite the Companion drives, not a step the customer performs.
> Autogrowth MAX is a one-time, invite-only lifetime license bought from the organization's credit balance, not a subscription tier. It is required to run any automation, workflow or Incubator program. Without a price set for that organization, the purchase is refused.
> An automation is one of AutoGrowth's built-in definitions; a script is a graph the customer builds in the Script Builder. The Script Builder is locked platform-wide, so never present building a script as something a customer can do today.
> An API key is a bare 64-character hex string with no prefix. It is shown once, at creation, is sent as `Authorization: Bearer <key>`, and can never be read back.
> An API key sees only the key owner's own accounts, content, collections, prompts, scripts and executions. Devices and tags are organization-scoped, and a non-owner sees only the devices assigned to them or carrying one of their tags. The automation catalog is global.
> There is no pagination. List endpoints return the whole set; the only limiting parameter anywhere is `limit` on `GET /v1/executions`, which defaults to 50 and has no offset to page with.
> Remote control and the live screen are dashboard-only, over WebSocket and MJPEG. Neither is part of the public API.
> The MCP server is hosted at https://mcp.autogrowth.farm and authenticates with OAuth. It is not an npm package and there is nothing to install locally. Its tools inherit exactly the scope of the API key behind them.
> Android support is partial and GrapheneOS-only: those phones appear in the fleet and can be watched and remote-controlled, but they cannot run scripts or automations.
> Never document Hi Katie or any persona feature. When a page and the code disagree, the code wins — check a claim against the source before repeating it.

# MCP tools

> The tools the server exposes for listing devices, accounts, automations and media, and for scheduling runs.

Eleven tools. Five read, four schedule, two handle media.

| Tool                        | What it does                                                | Key inputs                                    |
| --------------------------- | ----------------------------------------------------------- | --------------------------------------------- |
| `list_automations`          | The automation catalog, with each automation's input schema | none                                          |
| `schedule_automation`       | Queue one automation on one phone                           | `automationId`, `deviceId`, `scheduledAt`     |
| `bulk_schedule_automations` | Queue up to 100 automation runs in one call                 | `executions[]`                                |
| `list_scripts`              | Your scripts                                                | none                                          |
| `schedule_script`           | Queue one script on one phone                               | `scriptId`, `deviceId`, `scheduledAt`         |
| `bulk_schedule_scripts`     | Queue up to 100 script runs in one call                     | `executions[]`                                |
| `list_schedules`            | Scheduled and finished runs                                 | `deviceId`, `scriptId`, `from`, `to`, `limit` |
| `list_devices`              | Your phones and their live state                            | none                                          |
| `list_accounts`             | Your social accounts                                        | `platform`                                    |
| `upload_media`              | Add a file to the content library from a public URL         | `url`                                         |
| `list_media`                | Browse library metadata                                     | `folder`, `starred`                           |

<Info>
  Every tool runs against the [REST API](/api/overview) as you. If a tool returns
  less than you expect, check [what a key can
  see](/api/authentication#what-a-key-can-see) before assuming a bug.
</Info>

## Reading

### list\_automations

No parameters. Returns every automation in the catalog: `id`, `name`,
`description`, `category`, `estimatedDuration` in minutes, and an `inputs` array.

`inputs` is the schema for `inputValues` when you schedule. Each entry has an `id`
(the key to use), a `type`, a display `name`, sometimes `options` and a
`defaultValue`. **Call this before scheduling anything** — automation IDs and their
inputs are not guessable, and an assistant that invents them gets a 404.

### list\_scripts

No parameters. Returns your scripts with their IDs, names, descriptions and
estimated durations. Scripts with an empty graph are omitted.

<Note>
  The Script Builder is locked platform-wide, so most fleets have no scripts and
  this returns an empty list. Automations are the thing to schedule.
</Note>

### list\_devices

No parameters. Returns every phone you can reach — an owner sees the whole
organization, anyone else sees phones assigned to them or carrying one of their
tags — with `id`, `name`, model, OS, `online`, `status`, `battery`, `slotState`,
tags, and the accounts on the phone.

The `id` is what `deviceId` wants. `slotState` must be `active` for a run to be
accepted.

### list\_accounts

| Parameter  | Type                    | Notes                            |
| ---------- | ----------------------- | -------------------------------- |
| `platform` | `instagram` \| `tiktok` | Optional. Omit for all accounts. |

Returns the accounts **you** own, with username, platform, status, follower counts
and growth. The `username` is the value an `account_selection` input wants — pass
it back exactly as returned. Usernames are stored lowercase and without a leading
`@`, whatever an assistant's example shows.

<Warning>
  The filter only accepts `instagram` and `tiktok`. X and Threads accounts exist
  in AutoGrowth and are returned when you omit `platform`, but they cannot be
  filtered for.
</Warning>

### list\_schedules

| Parameter  | Type   | Notes                                      |
| ---------- | ------ | ------------------------------------------ |
| `deviceId` | string | Only runs on this phone                    |
| `scriptId` | string | Only runs of this script                   |
| `from`     | string | ISO 8601 lower bound on the scheduled time |
| `to`       | string | ISO 8601 upper bound                       |
| `limit`    | number | Defaults to 50                             |

Returns executions newest scheduled first. The device, script, account and
container references are expanded into objects in place; `automationId` stays a
plain string. Each carries a `status` — `pending`, `processing`, `completed`,
`failed`, `skipped` or `cancelled`.

There is no offset, so `limit` is a cap and not a page. Raising it on a busy fleet
returns a lot of JSON; see [limitations](/mcp/limitations).

## Scheduling

### schedule\_automation

| Parameter          | Type    | Notes                                                                                    |
| ------------------ | ------- | ---------------------------------------------------------------------------------------- |
| `automationId`     | string  | Required. From `list_automations`.                                                       |
| `deviceId`         | string  | Required. From `list_devices`.                                                           |
| `scheduledAt`      | string  | Required. ISO 8601, e.g. `2026-09-01T14:00:00Z`.                                         |
| `inputValues`      | object  | Keyed by input `id`. See the table below.                                                |
| `enableAIRecovery` | boolean | Let the Companion recover from an unexpected screen.                                     |
| `switchMobileData` | boolean | Cycle cellular data off and on first, for a fresh carrier IP. Only `true` does anything. |

### schedule\_script

Identical, with `scriptId` in place of `automationId`. A script's `inputValues`
keys are node IDs from its graph, not friendly names.

### Building inputValues

Use each input's `id` as the key. The value's shape depends on the input's `type`:

| Input type          | Value                                                                                                                  |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `account_selection` | The account's username, as a string                                                                                    |
| `user_input`        | A string                                                                                                               |
| `user_toggle`       | A boolean                                                                                                              |
| `user_select`       | One of that input's `options`, as a string                                                                             |
| `user_multi_select` | An array of `options` values                                                                                           |
| `push_media`        | An array of content IDs from `list_media`                                                                              |
| `container_select`  | An existing container's **name**, as a string                                                                          |
| `container_target`  | A container ID, optionally with sibling keys `containerName` and `proxyId` when a fresh container is being provisioned |

<Note>
  The tool's own description only teaches an assistant the first six types. If an
  automation asks for `container_select` or `container_target`, say so explicitly
  in your prompt, or the assistant will guess.
</Note>

### bulk\_schedule\_automations and bulk\_schedule\_scripts

Both take a single `executions` array of 1 to 100 items. Each item carries its own
`deviceId`, `scheduledAt`, `inputValues`, `enableAIRecovery` and `switchMobileData`,
plus `automationId` or `scriptId` — so one call can put a different account and
different media on every phone.

Items are validated independently. The response reports `created` and `failed`,
with each failure naming its `deviceId`, an error and sometimes a code such as
`MAX_REQUIRED` or `SLOT_EXPIRED`. **A call where every item failed is still a
success at the protocol level**, so read the counts rather than trusting "done".

### What scheduling rejects

| Cause                                            | What comes back                 |
| ------------------------------------------------ | ------------------------------- |
| No Autogrowth MAX, and the run is an automation  | `MAX_REQUIRED`                  |
| The phone's slot has expired                     | `SLOT_EXPIRED`                  |
| The create-account automation without its add-on | `CREATE_ACCOUNT_ADDON_REQUIRED` |
| Unknown automation, script, device or account    | Not found                       |

The codes are explained in [Errors](/api/errors).

<Warning>
  Overlapping runs are **not** skipped. A phone runs one execution at a time and
  queues the rest, so scheduling two things at 14:00 gives you two runs, the
  second starting late. Some assistants claim a one-minute conflict rule exists;
  it does not.
</Warning>

## Media

### upload\_media

| Parameter | Type                                                  | Notes                                     |
| --------- | ----------------------------------------------------- | ----------------------------------------- |
| `url`     | string                                                | Required. A **publicly reachable** URL.   |
| `title`   | string                                                | Display title.                            |
| `type`    | `image` \| `video` \| `carousel` \| `reel` \| `story` | Detected from the file when omitted.      |
| `folder`  | string                                                | Legacy folder name. Defaults to `images`. |

The server fetches the URL itself, so a signed link, a localhost address or
anything behind a login fails. The file name is taken from the URL. The response
includes the new content ID, which is what `push_media` inputs want.

An upload that would exceed your organization's storage allowance is rejected with
`STORAGE_LIMIT_EXCEEDED`. There is no way to file the upload into a collection
through this tool — see [limitations](/mcp/limitations).

### list\_media

| Parameter | Type    | Notes                                                 |
| --------- | ------- | ----------------------------------------------------- |
| `folder`  | string  | Filter by legacy folder. Pass `all` for every folder. |
| `starred` | boolean | `true` returns only starred items.                    |

Returns metadata only: ID, title, type, folder, size, dimensions, status, usage
count and dates. **File and thumbnail URLs are stripped**, so an assistant can list
your media but cannot look at it or link to it.
