Agent docs

All the scripts in your CutKit library, reachable from any agent. Write a script in Claude, ChatGPT or your own code, and it's in the teleprompter the next time you open the app. Edit it on the phone, and your agent sees the change.

Quick start

  1. Turn on agent access

    Open CutKit on your iPhone, go to Settings, Agent access, and turn it on. It's off until you do, and until then nothing leaves your phone.

  2. Connect your agent

    In ChatGPT or Claude, add this address as a connector, then sign in.

    Connector address
    https://getcutkit.com/mcp

    Anything else takes your API key. Get your key.

  3. Ask for a script

    Your agent writes it, and it's in the teleprompter the next time you open the app.

Pick a way in

There are 3 ways in, and they do the same things. The REST API and the CLI take an API key. The MCP server takes a sign in, so ChatGPT and Claude connect without one.

Your agent can also read the CutKit Agent Skill. It covers the tools, the limits and how to write a script that reads well on the teleprompter. In Claude Code, save it as ~/.claude/skills/cutkit/SKILL.md.

MCP server

Add CutKit as a connector with this address, then sign in. There's no key to copy.

Connector address
https://getcutkit.com/mcp

Claude (claude.ai and the desktop app)

  1. Open Settings, then Connectors, then Add custom connector.
  2. Paste the address above and press Add.
  3. Sign in to CutKit and press Allow.

ChatGPT (a paid plan, with developer mode on)

  1. Open Settings, turn on Developer mode, then create a new app.
  2. Paste the address above and choose OAuth for authentication.
  3. Sign in to CutKit and press Allow.

Menu names move around, so if one has changed, look for where custom connectors or apps live. Sign in with the same CutKit account you use on your iPhone, and your scripts are already there. On the web, the Apps page lists every connected app and disconnects any of them. Rotating your key disconnects all of them.

Other MCP clients

For a client that reads an mcpServers file (Cursor, Windsurf), the address is enough, and it opens the sign in itself. A key still works too. In Claude Code:

Terminal
claude mcp add --transport http cutkit https://getcutkit.com/mcp \
  --header "Authorization: Bearer ck_your_key"

Or in a config file:

JSON
{
  "mcpServers": {
    "cutkit": {
      "type": "http",
      "url": "https://getcutkit.com/mcp",
      "headers": { "Authorization": "Bearer ck_your_key" }
    }
  }
}

MCP tools

All clients get the same 9 tools:

list_scripts
List every script in the person's CutKit library, pinned first then newest, with ids, titles and word counts. Bodies are left out; use get_script for one.
get_script
Read one script, title and body, by id or by title.
create_script
Add a script to the person's CutKit library. It appears in the iPhone app's teleprompter the next time the app opens. Put only the words to read out loud in body. With no title, the first line becomes the title.
update_script
Change a script's title, body, pin, labels or archive state. Only the fields sent change.
delete_script
Delete a script. It disappears from the phone on its next sync.
list_labels
Every label in use and how many scripts carry it.
rename_label
Rename a label on every script that has it. Renaming onto an existing label merges the two.
delete_label
Take a label off every script that has it. The scripts stay.
set_label_color
Set a label's color, the same on the phone and the web. One of red, orange, amber, green, teal, sky, blue, violet, pink, or null for none.

The server speaks the 2026-07-28 MCP spec and the 4 before it, over Streamable HTTP. It's stateless, so there's no session to keep alive. Calls all need a sign in, and an unsigned one gets a 401 that points to /.well-known/oauth-protected-resource/mcp.

For builders

OAuth 2.1 with PKCE (S256), public clients only. Clients that publish a Client ID Metadata Document use its URL as the client_id. Others register at https://getcutkit.com/oauth/register. Metadata is at /.well-known/oauth-authorization-server, the one scope is scripts, and access tokens last an hour with rotating refresh tokens.

Your API key

The CLI and the REST API take a key. Here's where it lives.

  1. Open CutKit on your iPhone and tap the key button at the top of the Scripts list.
  2. Turn on Agent access. The app makes your library and shows the key.
  3. Tap Copy key. It starts with ck_.

The key syncs to your other Apple devices through iCloud Keychain, so every iPhone signed in to your Apple Account shares one library. Rotate key gives you a new one and stops the old one at once. Turning agent access off deletes the library and every script in it from our server. The scripts on your phone stay.

Give it to your agent

Paste this to any agent that can make HTTP requests or use MCP:

Prompt
My CutKit API key is ck_your_key. Use the CutKit API
(https://getcutkit.com/docs/api) to manage my teleprompter scripts.

Treat the key like a password. Anybody holding it can read and change your scripts, and nothing else: it opens no account, no recordings and no purchases.

CLI

cutkit-scripts is one Node file with no extra installs, so it runs anywhere Node 24 does. Run it with node ios/cli/cutkit-scripts.mjs, or symlink it onto PATH as cutkit-scripts. It reads the key from CUTKIT_API_KEY and the base URL from CUTKIT_API_URL (it defaults to https://getcutkit.com).

Terminal
export CUTKIT_API_KEY=ck_your_key
# optional: export CUTKIT_API_URL=https://getcutkit.com

node ios/cli/cutkit-scripts.mjs list
# or symlink it onto PATH as cutkit-scripts, then:
cutkit-scripts list
cutkit-scripts whoami
cutkit-scripts push intro.md --title "Launch video intro"
echo "New words" | cutkit-scripts push - --title "Launch video intro"
cutkit-scripts push intro.md --title "New title" --replace "Launch video intro"
cutkit-scripts push intro.md --pin --title "Launch video intro"
cutkit-scripts show "Launch video intro"
cutkit-scripts rm "Launch video intro"
cutkit-scripts list --json      # one JSON value on stdout, for scripts and agents
cutkit-scripts mcp              # the same tools as a local stdio MCP server

Commands are list, show, push, rm, whoami, mcp and help. Pushing the same title twice updates the script, never adds a copy. Use --replace to retitle one, and --pin to keep it at the top. whoami shows which library the key opens.

JSON and errors

All commands take --json. A refusal is {"error": {...}} with exit code 1. show, rm and push --replace take an id or a title.

REST API

Base URL https://getcutkit.com. JSON in and out, the key in an Authorization: Bearer header, CORS open to every origin. The full spec is openapi.json (OpenAPI 3.1).

  • GET/api/v1/scripts Live scripts, pinned first then newest. With ?since=, every change since then.
  • POST/api/v1/scripts Create a script. Send an id to make a retry safe.
  • GET/api/v1/scripts/{id} Read one script.
  • PUT/api/v1/scripts/{id} Create or replace the script with this id.
  • PATCH/api/v1/scripts/{id} Change only the fields you send.
  • DELETE/api/v1/scripts/{id} Delete a script. Leaves a tombstone for syncing.
  • GET/api/v1/labels Every label in use, how many scripts carry it and its color.
  • PATCH/api/v1/labels/{name} Rename a label on every script. Merges onto an existing label.
  • DELETE/api/v1/labels/{name} Take a label off every script.
  • PUT/api/v1/labels/{name}/color Color a label, or send null to clear it. The phone shows the same color.
  • GET/api/v1/me Check a key: its library and how many scripts it holds.
  • DELETE/api/v1/me Delete the library, every script and the key.
  • POST/api/v1/keys/rotate A new key for the same scripts. The old one stops at once.
  • POST/api/v1/keys Make an empty library and its key. No key needed. For testing.

Examples

Check your key.

Terminal
curl https://getcutkit.com/api/v1/me \
  -H "Authorization: Bearer $CUTKIT_API_KEY"

Create a script. Send body, the words to read out loud, and optionally title and pinned. With no title, the body's first line becomes the title.

Terminal
curl https://getcutkit.com/api/v1/scripts \
  -H "Authorization: Bearer $CUTKIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Launch video intro", "body": "Hi, I'"'"'m Sam. Here is what we shipped."}'

Answers 201:

JSON
{
  "script": {
    "id": "0b8f6c1e-4f5d-4c2a-9a57-6e1d3f0c2b91",
    "title": "Launch video intro",
    "body": "Hi, I'm Sam. Here is what we shipped.",
    "pinned": false,
    "words": 8,
    "created_at": "2026-09-29T18:04:11.201Z",
    "updated_at": "2026-09-29T18:04:11.201Z",
    "deleted": false
  }
}

List, change and delete.

List
curl https://getcutkit.com/api/v1/scripts \
  -H "Authorization: Bearer $CUTKIT_API_KEY"
Pin
curl -X PATCH https://getcutkit.com/api/v1/scripts/0b8f6c1e-4f5d-4c2a-9a57-6e1d3f0c2b91 \
  -H "Authorization: Bearer $CUTKIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pinned": true}'
Delete
curl -X DELETE https://getcutkit.com/api/v1/scripts/0b8f6c1e-4f5d-4c2a-9a57-6e1d3f0c2b91 \
  -H "Authorization: Bearer $CUTKIT_API_KEY"

The script object

id string
8 to 64 letters, digits, dashes or underscores. A UUID when you don't choose one.
title string
One line, at most 200 characters.
body string
At most 200,000 characters. Empty on a deleted script.
pinned boolean
Pinned scripts sit at the top of the library.
words integer
Read only. What the phone counts to estimate reading time.
created_at, updated_at string
ISO 8601, set by the server.
deleted boolean
Only ever true in an answer to ?since=.

Syncing

To keep a copy in step, call GET /api/v1/scripts once, keep its server_time, and pass it back as since next time. You get every script that changed at or after that instant, oldest first, deleted ones marked deleted: true.

HTTP
GET /api/v1/scripts?since=2026-09-29T18:00:00.000Z

{
  "scripts": [
    { "id": "…", "title": "Launch video intro", "deleted": false, … },
    { "id": "…", "title": "", "body": "", "deleted": true, … }
  ],
  "server_time": "2026-09-29T18:10:00.000Z"
}

The phone does exactly this. It chooses its own ids and pushes with PUT, so a script made offline lands once however many times the push is retried. The last write wins.

Errors and limits

Refusals all share one shape, with a code you can branch on:

HTTP
HTTP/1.1 401 Unauthorized

{
  "error": {
    "code": "invalid_key",
    "message": "That API key isn't valid. It may have been rotated in the app.",
    "docs": "https://getcutkit.com/docs/api"
  }
}

The codes: missing_key, invalid_key, invalid_json, invalid_body, missing_body, invalid_title, title_too_long, body_too_long, invalid_pinned, invalid_labels, too_many_labels, invalid_archived, invalid_id, invalid_since, not_found, already_exists, library_full, rate_limited, not_configured, internal.

  • At most 2,000 scripts in a library (409 library_full).
  • At most 5 new libraries an hour from one address (429 rate_limited).
  • 401 means the key is missing or no longer valid. Ask the person for their current key.

Questions or a missing endpoint: hello@getcutkit.com.