# MCP quickstart: schedule social posts from Claude Code

**Early access:** the MCP server is built and being tested. `@turboyap/mcp` isn't published to npm yet, so the `npx` commands below work once it is. [Ask for early access](mailto:hello@turboyap.com?subject=Early%20access) to hear first.

The Turboyap MCP server runs on your machine, so your agent can upload files straight from disk, including a whole folder of slides. You need a Turboyap **agent key**. Start with a test key (`ty_agent_test_…`): it runs the whole flow against simulated accounts and never posts anywhere real. Switch to a live agent key (`ty_agent_…`) when you're ready.

## Claude Code

```bash
claude mcp add turboyap -e TURBOYAP_API_KEY=ty_agent_test_… -- npx -y @turboyap/mcp
```

## Cursor and other MCP clients

```json
{
  "mcpServers": {
    "turboyap": {
      "command": "npx",
      "args": ["-y", "@turboyap/mcp"],
      "env": { "TURBOYAP_API_KEY": "ty_agent_test_…" }
    }
  }
}
```

The server reads `TURBOYAP_API_KEY`, plus an optional `TURBOYAP_API_URL` that defaults to `https://api.turboyap.com`.

## With a test key, create test accounts first

A test key only sees test accounts, and the MCP server has no tool that creates them. Create a simulated TikTok and Instagram account once, with the same key:

```bash
for platform in tiktok instagram; do
  curl https://api.turboyap.com/v1/accounts/test \
    -H "Authorization: Bearer ty_agent_test_…" \
    -H "Content-Type: application/json" \
    -d "{\"platform\": \"$platform\"}"
done
```

They start on autonomy level 1, like real accounts, so your agent's posts wait for approval. Approve them with your human test key (`ty_human_test_…`), as the [test mode quickstart](/docs/test-mode) shows.

## Try it

Ask your agent something like:

> Upload the slides in ~/content/icecream and schedule them to our TikTok and Instagram for Tuesday 6pm ET. Dry-run first and fix anything Instagram can't take.

The agent works through the tools in this order:

1. `list_accounts` finds your connected accounts and their autonomy level.
2. `get_platform_rules` reads slide limits, formats and aspect ratios.
3. `upload_media` uploads the folder in natural filename order (`slide-2` before `slide-10`).
4. `create_post` with `dry_run: true` shows what each platform will get, plus every problem with a fix.
5. `create_post` applies the fixes, for example `fit: { overflow: "truncate", aspect: "pad" }`, and schedules.
6. `get_post` reports each account's status and a `next_step` to relay to you.

## Tools

| Tool | What it does |
|---|---|
| `get_workspace` | Workspace, kill-switch state, and this key's type, mode, scopes, account allowlist and `can` summary |
| `list_accounts` | Connected accounts, ids, autonomy levels |
| `get_platform_rules` | Limits per platform and post type |
| `upload_media` | Upload files, folders, or URLs; returns media ids in order |
| `create_post` | Preview (`dry_run`), save a draft, or schedule. Idempotent with `idempotency_key` |
| `list_posts` / `get_post` | Status per account, post URLs once published, errors with fixes |
| `update_post` | Reschedule or re-caption before publishing |
| `cancel_post` | Cancel before publishing |

Agents can't approve posts. On accounts set to autonomy level 1, agent posts wait for a human; see [the autonomy dial](/docs/autonomy-dial).

## Scopes

Agent keys default to `read`, `draft` and `schedule`. They can schedule a future time but not publish with `"now"`, and a key without `schedule` saves drafts (no `schedule_at`) for a human to schedule. A key can also be limited to some accounts. When a call fails with `insufficient_scope` or `account_not_allowed`, the agent can call `get_workspace` to see what its key may do.

## Every post records which agent made it

The MCP server sends an `X-Turboyap-Client` header with every call, filled in from the name and version your MCP client reports when it connects, or `turboyap-mcp` if it reports none. Turboyap stores it in each post's `created_by.client` and in the audit log, so you can tell which agent made a post.

## Errors are written for agents

Every error includes a `code`, the `field` that caused it, and a `fix`:

```json
{
  "error": {
    "code": "too_many_items",
    "message": "instagram allows 10 slides per post; got 12.",
    "field": "media_ids",
    "fix": "Set fit.overflow to \"truncate\" to post the first 10, or pass targets[1].media_ids with your best 10 slides (keep your call-to-action slide)."
  }
}
```

Agents apply the fix and retry without asking you, unless the fix needs a human (like reconnecting an account).
