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
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.
Connect your agent
In ChatGPT or Claude, add this address as a connector, then sign in.
https://getcutkit.com/mcpAnything else takes your API key. Get your key.
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.
- MCP server ChatGPT, Claude, Cursor, Claude Code and any MCP client. Sign in
- CLI One Node file for your terminal, your scripts and local agents. API key
- REST API JSON over HTTPS, from your own code. API key
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.
https://getcutkit.com/mcpClaude (claude.ai and the desktop app)
- Open Settings, then Connectors, then Add custom connector.
- Paste the address above and press Add.
- Sign in to CutKit and press Allow.
ChatGPT (a paid plan, with developer mode on)
- Open Settings, turn on Developer mode, then create a new app.
- Paste the address above and choose OAuth for authentication.
- 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:
claude mcp add --transport http cutkit https://getcutkit.com/mcp \
--header "Authorization: Bearer ck_your_key"Or in a config file:
{
"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.
- Open CutKit on your iPhone and tap the key button at the top of the Scripts list.
- Turn on Agent access. The app makes your library and shows the key.
- 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:
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).
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 serverCommands 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/scriptsLive scripts, pinned first then newest. With ?since=, every change since then.POST/api/v1/scriptsCreate 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/labelsEvery 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}/colorColor a label, or send null to clear it. The phone shows the same color.GET/api/v1/meCheck a key: its library and how many scripts it holds.DELETE/api/v1/meDelete the library, every script and the key.POST/api/v1/keys/rotateA new key for the same scripts. The old one stops at once.POST/api/v1/keysMake an empty library and its key. No key needed. For testing.
Examples
Check your key.
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.
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:
{
"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.
curl https://getcutkit.com/api/v1/scripts \
-H "Authorization: Bearer $CUTKIT_API_KEY"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}'curl -X DELETE https://getcutkit.com/api/v1/scripts/0b8f6c1e-4f5d-4c2a-9a57-6e1d3f0c2b91 \
-H "Authorization: Bearer $CUTKIT_API_KEY"The script object
idstring- 8 to 64 letters, digits, dashes or underscores. A UUID when you don't choose one.
titlestring- One line, at most 200 characters.
bodystring- At most 200,000 characters. Empty on a deleted script.
pinnedboolean- Pinned scripts sit at the top of the library.
wordsinteger- Read only. What the phone counts to estimate reading time.
created_at,updated_atstring- ISO 8601, set by the server.
deletedboolean- 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.
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/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.