> For the complete documentation index, see [llms.txt](https://docs.twistly.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.twistly.ai/api-reference/twistly-mcp-server.md).

# Twistly MCP Server

Connect any compatible MCP client to Twistly, then simply ask for a deck — "make me a 12-slide presentation about renewable energy" — and get back a downloadable PowerPoint or PDF.

Server URL: `https://mcp.twistly.ai/mcp`

## How MCP differs from the REST API

Both interfaces use the same generation pipeline. What changes is who calls it and how the caller is identified — MCP is designed for interactive AI clients.

* **No API key.** Users sign in with their normal Twistly account (Google, Microsoft, or an emailed code). Nothing to issue, paste, or rotate.
* **No Twistly account needed up front.** If the email that signed in has no Twistly account yet, a Free one is created automatically on the first generation.
* **The AI client calls the tools, not your code.** The client's model reads the tool schemas and decides when to call which tool from what the user says.
* **Four tools instead of four endpoints:** `create_from_topic`, `create_from_text`, `create_from_file`, `get_job_status`.
* **Asynchronous, same as the REST API.** A `create_*` tool returns a `job_id`; `get_job_status` returns the download link.
* **Default image source is `flux`** (AI-generated), where the REST API defaults to `unsplash`. The REST API's `ai` value doesn't exist here — `flux` replaces it.
* **Billed by account, not by key** — see [Plans and billing](#plans-and-billing).

Use the REST API when integrating from code. Use MCP when users need Twistly inside an AI client.

## Get started

### What you need

* An email address the user can sign in with — Google, Microsoft, or any inbox that can receive a code. A Twistly account is **not** a prerequisite: a Free one is created automatically on the first generation.
* An MCP client that supports **Streamable HTTP** and **OAuth**.
* The server URL: `https://mcp.twistly.ai/mcp`.

### Your first presentation

**Step 1 — Connect Twistly.** Add Twistly using the server URL in your MCP client's connector settings. The client opens the Twistly sign-in page: continue with **Google**, **Microsoft**, or **email** (a 6-digit code arrives by email). Access is granted automatically and the page closes itself after a 5-second countdown.

**Step 2 — Ask for a deck.** In natural language:

```
Make a presentation about the history of coffee — 12 slides, Berlin template
```

The client calls `create_from_topic` and receives a queued job:

```json
{
  "job_id": "9f1c2a4e-6e2c-4f8a-9b3d-1a2b3c4d5e6f",
  "status": "queued",
  "created_at": "2026-07-30T10:15:00.000Z"
}
```

**Step 3 — Get the file.** The client checks the job until generation completes, then shows a permanent download link from `result.url`. Generation usually takes **30–90 seconds**, with status updates while it runs.

### Use with ChatGPT

ChatGPT is one supported MCP client. Add a connector with the server URL above — or, when Twistly appears in the ChatGPT app directory, select it there and choose **Connect**.

## Authentication

Twistly uses OAuth — neither the user nor the MCP client ever handles an API key.

|                         |                                                                                                                    |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Sign-in methods**     | Google, Microsoft, email code (6 digits)                                                                           |
| **Permissions granted** | `presentations:create` — create presentations. `presentations:read` — read the status of presentations it created  |
| **Session length**      | 7 days, then sign-in again                                                                                         |
| **Account binding**     | The connection is bound to the account that signed in. Switching accounts means reconnecting                       |
| **New accounts**        | An email with no Twistly account gets a Free one created automatically — on the first *generation*, not at sign-in |

Everything is billed to the email the user signed in with, so MCP generations draw on the **same plan and balance** as that person's generations in the add-in or on the web. Signing in with an email that already has a Twistly account picks up that account — plan, balance, and history included.

When a session expires or a permission is missing, the client receives an authorization challenge instead of an error and prompts the user to reconnect.

## The tools

| Tool                | Use when                                                  | Permission             |
| ------------------- | --------------------------------------------------------- | ---------------------- |
| `create_from_topic` | The user has a topic or idea — the AI writes the content  | `presentations:create` |
| `create_from_text`  | The user already has text and wants it turned into slides | `presentations:create` |
| `create_from_file`  | The user has a PDF / PPTX / DOCX / TXT to convert         | `presentations:create` |
| `get_job_status`    | Check status, fetch the download URL                      | `presentations:read`   |

Every `create_*` tool replies immediately with `{ job_id, status: "queued", created_at }`. The file URL is delivered by `get_job_status` once `status` becomes `completed`.

`get_job_status` also accepts `wait: true`, which polls internally for up to **25 seconds** (2s → 5s backoff) before answering. If the job hasn't finished by then it returns `processing` with an explicit "call again in a few seconds" message. Status is one of `queued`, `processing`, `completed`, `failed`.

### 1. `create_from_topic`

Generates a presentation from a short topic prompt.

| Field               | What it does                                                                                                                                                 | Required | Default     |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ----------- |
| `topic`             | Subject of the presentation (1–450 chars)                                                                                                                    | Yes      | —           |
| `num_slides`        | Slide count (`-1` for auto, or `1`–`50`; `0` is invalid)                                                                                                     | No       | auto        |
| `language`          | Output language                                                                                                                                              | No       | auto-detect |
| `template`          | Design theme (see [Templates](#templates))                                                                                                                   | No       | `Tokyo`     |
| `format`            | `pptx` \| `pdf`                                                                                                                                              | No       | `pptx`      |
| `image_source`      | `unsplash` \| `pexels` \| `scrapingdog` \| `flux`                                                                                                            | No       | `flux`      |
| `image_style`       | `auto` \| `photorealistic` \| `illustration` \| `neon` \| `abstract` \| `black-and-white` \| `3d` \| `linear` *(applies only when `image_source` is `flux`)* | No       | —           |
| `content`           | Text verbosity: `short` \| `detailed` \| `bulletPoints`                                                                                                      | No       | `detailed`  |
| `presentation_type` | `General` \| `Educational Project` \| `Business Pitch` \| `Reports and Insights`                                                                             | No       | —           |
| `target_audience`   | Free text, ≤ 200 chars                                                                                                                                       | No       | —           |
| `tone_and_style`    | Free text, ≤ 200 chars                                                                                                                                       | No       | —           |

Example — the user asks for "a 5-slide illustrated digital-marketing pitch for marketing managers with upbeat bullet points", and the client sends:

```json
{
  "topic": "Digital Marketing Strategy",
  "num_slides": 5,
  "image_source": "flux",
  "image_style": "illustration",
  "content": "bulletPoints",
  "presentation_type": "Business Pitch",
  "target_audience": "Marketing managers",
  "tone_and_style": "Enthusiastic"
}
```

### 2. `create_from_text`

Turns text the user supplies in the MCP client into slides.

| Field                 | What it does                                        | Required | Default     |
| --------------------- | --------------------------------------------------- | -------- | ----------- |
| `text`                | Source text (1–2,000,000 chars at this layer)       | Yes      | —           |
| `num_slides`          | Slide count (`-1` for auto, or `1`–`50`)            | No       | auto        |
| `language`            | Output language                                     | No       | auto-detect |
| `template`            | Design theme                                        | No       | `Tokyo`     |
| `format`              | `pptx` \| `pdf`                                     | No       | `pptx`      |
| `content_modificator` | `preserve` \| `expand` \| `condense`                | No       | `expand`    |
| `text_density`        | `minimal` \| `concise` \| `detailed`                | No       | `concise`   |
| `verbosity`           | `short` \| `detailed` \| `bulletPoints`             | No       | —           |
| `image_source`        | `unsplash` \| `pexels` \| `scrapingdog` \| `flux`   | No       | `flux`      |
| `image_style`         | See `image_style` values above *(only with `flux`)* | No       | —           |

The 2,000,000-character ceiling is only this layer's input guard. The real limit is the backend's **665,000-token** budget (≈ 500,000 words) — longer input returns `input_too_large`.

### 3. `create_from_file`

Converts an uploaded document into slides. The file arrives one of three ways, and **exactly one** must be used.

| Field                 | What it does                                                                                                                                                                                                  | Required     | Default     |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ----------- |
| `file`                | **Preferred.** The file the user attached in the MCP client. The client passes a reference (`download_url`, `file_id`, `mime_type`, `file_name`) and the server fetches the bytes itself, so large files work | one of three | —           |
| `file_base64`         | Inline bytes for small files. Requires `mime_type`                                                                                                                                                            | one of three | —           |
| `file_url`            | An `https` URL the server downloads. Requires `mime_type`                                                                                                                                                     | one of three | —           |
| `filename`            | Name to use for the upload, ≤ 255 chars                                                                                                                                                                       | No           | derived     |
| `mime_type`           | Declared type — required with `file_base64` / `file_url`                                                                                                                                                      | conditional  | —           |
| `num_slides`          | Slide count (`-1`, or `1`–`50`)                                                                                                                                                                               | No           | auto        |
| `language`            | Output language                                                                                                                                                                                               | No           | auto-detect |
| `template`            | Design theme                                                                                                                                                                                                  | No           | `Tokyo`     |
| `format`              | `pptx` \| `pdf`                                                                                                                                                                                               | No           | `pptx`      |
| `content_modificator` | `preserve` \| `expand` \| `condense`                                                                                                                                                                          | No           | `expand`    |
| `text_density`        | `minimal` \| `concise` \| `detailed`                                                                                                                                                                          | No           | `concise`   |
| `verbosity`           | `short` \| `detailed` \| `bulletPoints`                                                                                                                                                                       | No           | —           |
| `image_source`        | as above                                                                                                                                                                                                      | No           | `flux`      |
| `image_style`         | as above                                                                                                                                                                                                      | No           | —           |

**Accepted file types** (validated by content, not just extension — extension spoofing is rejected):

* PDF (`application/pdf`)
* PowerPoint (`application/vnd.openxmlformats-officedocument.presentationml.presentation`)
* Word (`application/vnd.openxmlformats-officedocument.wordprocessingml.document`)
* Plain text (`text/plain`)

With `file_base64` or `file_url`, the detected type must match the declared `mime_type` — otherwise the call fails with `unsupported_file_type`.

{% hint style="info" %}
**Attach files through the MCP client whenever possible.** Attachments and URL files support up to **100 MB** because the server downloads them directly; inline base64 is limited to **25 MB**.
{% endhint %}

### 4. `get_job_status`

Owner-scoped: a job is visible only to the account that created it.

| Field    | What it does                                    | Required | Default |
| -------- | ----------------------------------------------- | -------- | ------- |
| `job_id` | The id returned by a `create_*` tool (UUID)     | Yes      | —       |
| `wait`   | Poll internally for up to 25 s before answering | No       | `false` |

Response shape:

```
{
  "job_id": "uuid",
  "status": "queued" | "processing" | "completed" | "failed",
  "created_at": "ISO-8601",
  "completed_at": "ISO-8601",   // only when status ∈ {completed, failed}
  "result": {                   // only when status = completed
    "url": "https://...",
    "export_url": "https://..." // only when the backend returns one
  },
  "error": {                    // only when status = failed
    "code": "UPSTREAM_FAILURE",
    "message": "human-readable reason"
  },
  "message": "…"                // only while queued / processing
}
```

## Responses and errors

A `create_*` tool returns the job descriptor; the download URL appears in `result.url` once `get_job_status` reports `completed`.

Every failure carries a user-facing message, a machine-readable code, and whether it is retryable. `rate_limited` can additionally carry `retry_after`, and upstream failures can carry a `request_id` for support.

| Code                    | Meaning                                                                    | Retryable |
| ----------------------- | -------------------------------------------------------------------------- | --------- |
| `invalid_input`         | A parameter failed validation, or the request was rejected upstream        | No        |
| `input_too_large`       | Source content exceeded the backend's token budget                         | No        |
| `file_too_large`        | Inline base64 file over 25 MB — attach it or use `file_url` instead        | No        |
| `unsupported_file_type` | Not a PDF/PPTX/DOCX/TXT, or content doesn't match the declared `mime_type` | No        |
| `credits_exhausted`     | Out of AI credits — upgrade the plan                                       | No        |
| `job_not_found`         | No job with that id for this account                                       | No        |
| `rate_limited`          | Too many requests. Carries `retry_after` when available                    | Yes       |
| `upstream_unavailable`  | The generation service is unreachable or returned an error                 | Yes       |
| `service_misconfigured` | Server-side auth problem between MCP and the backend                       | No        |
| `not_authenticated`     | The session carries no usable account email                                | No        |

**Authorization challenges** are returned as OAuth challenges rather than plain errors, which is what makes the MCP client prompt the user to reconnect: `invalid_token` (not connected, session expired, or the account email couldn't be resolved) and `insufficient_scope` (the connection lacks a permission a tool needs).

## Limits

| Limit                     | Value                                                                 |
| ------------------------- | --------------------------------------------------------------------- |
| Slides per presentation   | 1–50 (or `-1` for auto)                                               |
| `topic` length            | 450 characters                                                        |
| `text` length             | 2,000,000 characters at this layer; **665,000 tokens** at the backend |
| Inline `file_base64` size | 25 MB decoded                                                         |
| Attached / URL file size  | 100 MB                                                                |
| File download timeout     | 30 seconds                                                            |
| `wait: true` poll budget  | 25 seconds                                                            |
| Typical generation time   | 30–90 seconds                                                         |
| Sign-in session           | 7 days                                                                |
| Output formats            | `pptx`, `pdf`                                                         |

## Plans and billing

Which balance a generation is charged to depends on the plan — and, for Pro/Team, on whether the user ever issued an API key.

| Account                                    | Charged to                                                                      | Cost                                                |
| ------------------------------------------ | ------------------------------------------------------------------------------- | --------------------------------------------------- |
| Free / Starter                             | The account's AI-credit balance                                                 | **20 credits per generation** (any `create_*` tool) |
| Pro / Team **without** an API key          | A per-account daily quota                                                       | **100 generations per day** by default              |
| Pro / Team **with** an API key they issued | That key's daily limits — MCP usage shares the balance with their own API calls | per the key's limits                                |

An MCP connection **never creates an API key**. A Pro/Team user who has never issued one simply runs on the daily quota.

A brand-new account starts with **60 AI credits** — 3 generations before it needs an upgrade. When the balance is too low, the tool returns `credits_exhausted` with an upgrade link, and nothing is generated.

**Failed generations are refunded.** Credits and quota are reserved when the job is submitted and returned if it fails, so a crashed job costs nothing.

## Templates

Pass the exact id (case-sensitive, no spaces). All 51 built-in themes are available:

`Tokyo`, `NewYork`, `Seoul`, `Rome`, `Berlin`, `Copenhagen`, `Oslo`, `Rotterdam`, `Cambridge`, `Houston`, `Pasadena`, `Lisbon`, `MexicoCity`, `Doha`, `Vienna`, `Edinburgh`, `Toronto`, `Melbourne`, `Boston`, `SantaFe`, `FlowerMound`, `Tallinn`, `Porto`, `Dubai`, `BuenosAires`, `Seattle`, `Zurich`, `Reykjavik`, `Helsinki`, `Nairobi`, `Dublin`, `Oxford`, `Brussels`, `LosAngeles`, `Florence`, `Havana`, `TelAviv`, `Portland`, `Milan`, `Madrid`, `Singapore`, `Stockholm`, `Geneva`, `Chicago`, `HongKong`, `Tashkent`, `SanFrancisco`, `Batumi`, `PalmSprings`, `Paris`, `Marrakech`

Custom user-uploaded templates are **not** available over MCP.

## What you get

Each generated presentation includes:

* A title slide with an image
* An outline of the main points
* Content slides with images and text
* Professional formatting
* A permanent download link, delivered in the chat
* A file ready to edit in PowerPoint or Google Slides

## Limitations

* **Generation only.** There are no tools for editing, restyling, or appending to an existing presentation.
* **No custom templates** — only the 51 built-in themes.
* **No layout controls.** Layout selection is entirely up to the generation pipeline.
* **`pptx` and `pdf` only.**
* **One account per connection.** Switching Twistly accounts means reconnecting the connector.
* **7-day sessions.** After that the user signs in again.
* Free/Starter users can run out of credits mid-conversation. The tool says so explicitly, but partial work isn't refunded.

## FAQ

**Does the user need an API key?** No — that's the point of MCP. They sign in with an email, and MCP never issues a key.

**What if they've never used Twistly before?** It still works. The first generation creates a Free account for that email automatically, with 60 AI credits — 3 generations. Nothing to sign up for beforehand.

**Does this work on a Free Twistly plan?** Yes. Connector availability depends on the MCP *client's* plan and capabilities, not the Twistly plan.

**If a user already has a Twistly subscription, does MCP see it?** Yes, as long as they sign in with the same email. Their plan, balance, and history are the same account.

**How long is the download link valid?** It's permanent — the file stays in storage and the URL keeps working.

**Can the user attach a 60 MB PDF?** Yes, as a client attachment — attachments and URL files support up to 100 MB. Inline base64 is capped at 25 MB.

**What if the user asks for 80 slides?** The tool rejects it — the maximum is 50.

**Does the MCP server see the conversation?** No. It receives only the tool calls the client's model makes, with their parameters.

**Which languages are supported?** Any. The AI auto-detects from the input, or the user can pin it with `language`.

**Are the images copyrighted?** Unsplash and Pexels images are stock — credit photographers when sharing publicly. `flux` images are AI-generated and free to use.

**Which MCP clients can connect?** Any client that supports Streamable HTTP and standard OAuth discovery. ChatGPT is one supported client experience.

## Support

If something fails:

1. Disconnect and reconnect Twistly in the MCP client — this covers expired sessions and half-finished sign-ins.
2. Check the error code the tool returned. `credits_exhausted` and `rate_limited` reflect account state, not bugs.
3. Confirm the signed-in email is the account you expect to be billed.
4. For anything server-side, [contact us](/help/contact-us.md) with the `job_id` — every generation is logged against it.

## Next steps

* Connect Twistly in your MCP client and generate a first deck.
* Try all three inputs — a topic, pasted text, and an attached PDF — they produce noticeably different decks from the same source material.
* Mix `template`, `image_source`, and `presentation_type` to tune the output for an audience.
