katto-mcp 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QUICKSTART.md +35 -0
- package/README.md +1 -0
- package/SKILL.md +45 -0
- package/index.mjs +50 -7
- package/package.json +45 -43
package/QUICKSTART.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Katto — 60-second quickstart
|
|
2
|
+
|
|
3
|
+
Turn a long video into captioned 9:16 short clips from your assistant, your terminal, or
|
|
4
|
+
your code. **One quota** (Creator: 25 videos/mo, ≤90 min each · Free: 2/mo), shared across
|
|
5
|
+
all three. Create a key at https://katto.tech/dashboard/api-keys (keys can be read-only).
|
|
6
|
+
|
|
7
|
+
## MCP — in Claude, Cursor, ChatGPT
|
|
8
|
+
Hosted, zero-install, OAuth 2.1:
|
|
9
|
+
```json
|
|
10
|
+
{ "mcpServers": { "katto": { "url": "https://mcp.katto.tech/mcp" } } }
|
|
11
|
+
```
|
|
12
|
+
Then just ask: *"Clip the best 6 moments from <url> and caption them."*
|
|
13
|
+
Prefer local? `npx -y katto-mcp` with `KATTO_API_KEY=sk_live_...`.
|
|
14
|
+
|
|
15
|
+
## CLI — in your terminal or a cron
|
|
16
|
+
```bash
|
|
17
|
+
npm i -g katto-cli
|
|
18
|
+
katto login # or set KATTO_API_KEY=sk_live_...
|
|
19
|
+
katto clip <url> --clips 6 --wait --json | jq '.clips[].url'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## REST API — in your product
|
|
23
|
+
```bash
|
|
24
|
+
curl -X POST https://katto.tech/api/v1/jobs \
|
|
25
|
+
-H "Authorization: Bearer sk_live_..." \
|
|
26
|
+
-H "Idempotency-Key: $(uuidgen)" \
|
|
27
|
+
-H "Content-Type: application/json" \
|
|
28
|
+
-d '{"url":"https://youtube.com/watch?v=..."}'
|
|
29
|
+
# → { "job_id": "..." }
|
|
30
|
+
# then poll GET /v1/jobs/{id}, or pass a "webhook_url" for a signed completion callback.
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
What comes back: finished clips (MP4 + SRT captions + a title and a 0–100 score), 9:16,
|
|
34
|
+
word-timed captions, reframed. Re-render the layout/caption style or dub into 8 languages
|
|
35
|
+
for free (no quota). Full reference: https://katto.tech/docs/api
|
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ Account and reference:
|
|
|
85
85
|
- **`katto_get_webhook_secret()`** your webhook signing secret and how to verify signed callbacks (returns a secret — treat it like a credential).
|
|
86
86
|
- **`katto_list_sources()`** the video platforms Katto can clip from, with an example url each.
|
|
87
87
|
- **`katto_list_clip_lengths()`** the valid target clip-length buckets.
|
|
88
|
+
- **`katto_list_caption_styles()`** the caption-style presets you can pass as `caption_style` when creating a job or re-rendering a clip.
|
|
88
89
|
|
|
89
90
|
Jobs draw from your Katto plan's monthly video quota (25 on Creator, 2 on Free), videos up to 90 minutes. The underlying REST API also supports `Idempotency-Key` safe retries, read-only scoped keys, and signed HMAC webhooks. See the [docs](https://katto.tech/docs/api).
|
|
90
91
|
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: katto-clip
|
|
3
|
+
description: Turn a long video (a YouTube / Twitch / Vimeo / Rumble / Zoom / Dailymotion link, or an upload) into scored, captioned, 9:16 short clips using Katto's cloud pipeline. Use when the user wants to clip, repurpose, or make shorts from long-form video, or to dub / re-render an existing clip.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Katto clipping skill
|
|
7
|
+
|
|
8
|
+
Katto runs the whole pipeline in its cloud — download → transcript → moment scoring →
|
|
9
|
+
cut → captions → reframe → optional dub → publish. You trigger it; nothing renders on
|
|
10
|
+
the local machine.
|
|
11
|
+
|
|
12
|
+
## Connect
|
|
13
|
+
- **Hosted MCP (recommended, zero-install):** point the client at `https://mcp.katto.tech/mcp`
|
|
14
|
+
(OAuth 2.1 + Dynamic Client Registration; no key on disk).
|
|
15
|
+
- **Local:** `npx -y katto-mcp` with `KATTO_API_KEY=sk_live_...` (Cursor, CI, cron).
|
|
16
|
+
- Tools are prefixed `katto_`. `tools/list` works without a key; every tool **call** needs a key.
|
|
17
|
+
|
|
18
|
+
## Core flow
|
|
19
|
+
1. `katto_create_clip_job({ url, config? })` → returns a `job_id`. Spends **1 video** from the
|
|
20
|
+
monthly quota. Pass an idempotency key so a retry never double-spends.
|
|
21
|
+
2. Poll `katto_get_job({ id })` until `status` is `"completed"`.
|
|
22
|
+
3. `katto_get_clips({ id })` → finished clips (MP4 url + SRT + title + score 0–100).
|
|
23
|
+
|
|
24
|
+
## Editing — never counts against quota
|
|
25
|
+
- `katto_rerender_clip({ id, clip_index, layout_mode?, caption_style? })`, then `katto_get_rerender(...)`.
|
|
26
|
+
- `katto_dub_clip({ id, clip_index, languages })` → dub into any of **8 languages**: en, es, fr, it, pt, hi, ja, zh.
|
|
27
|
+
|
|
28
|
+
## Reference / account
|
|
29
|
+
- `katto_get_usage`, `katto_get_account` — remaining quota, plan, this key's scopes.
|
|
30
|
+
- `katto_list_sources` (accepted platforms), `katto_list_clip_lengths` (valid length buckets).
|
|
31
|
+
- `katto_get_transcript` (timestamped), `katto_get_brand_kit`, `katto_get_webhook_secret` (treat as a credential).
|
|
32
|
+
|
|
33
|
+
## Rules of the road
|
|
34
|
+
- **One quota**, shared with the app / API / CLI: Creator = 25 videos/month, ≤90 min each; Free = 2/month.
|
|
35
|
+
Re-renders and dubs are free.
|
|
36
|
+
- Captions: **99 languages** (word-timed in 41, sentence-level in the rest). Dubbing: **8**. Publish: **7 platforms**.
|
|
37
|
+
- **Don't invent timings.** The only measured figure is ~5 minutes for 8 clips on a 20-minute video;
|
|
38
|
+
longer sources take longer. Say that, not a number you'd like.
|
|
39
|
+
|
|
40
|
+
## Example
|
|
41
|
+
User: *"Clip the best 6 moments from this podcast, then dub clip 2 in Spanish."*
|
|
42
|
+
→ `katto_create_clip_job(url, { clips: 6 })` → poll `katto_get_job` → `katto_get_clips`
|
|
43
|
+
→ `katto_dub_clip(id, 2, ["es"])` → `katto_get_rerender`.
|
|
44
|
+
|
|
45
|
+
Full reference: https://katto.tech/docs/api · OpenAPI: https://katto.tech/openapi.json
|
package/index.mjs
CHANGED
|
@@ -153,7 +153,14 @@ const TOOLS = [
|
|
|
153
153
|
name: "katto_list_clip_lengths",
|
|
154
154
|
description:
|
|
155
155
|
"List the valid values for the optional config.clipLength on katto_create_clip_job (target clip " +
|
|
156
|
-
"duration buckets).",
|
|
156
|
+
"duration buckets). Note: clipLength is fixed at job creation and cannot be changed by re-render.",
|
|
157
|
+
inputSchema: { type: "object", properties: {} },
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "katto_list_caption_styles",
|
|
161
|
+
description:
|
|
162
|
+
"List the valid caption_style preset names for katto_rerender_clip (e.g. 'hormozi' for bold " +
|
|
163
|
+
"word-by-word highlight). Call this before re-rendering so you pass a real preset, not a guess.",
|
|
157
164
|
inputSchema: { type: "object", properties: {} },
|
|
158
165
|
},
|
|
159
166
|
{
|
|
@@ -170,7 +177,12 @@ const TOOLS = [
|
|
|
170
177
|
type: "string",
|
|
171
178
|
enum: ["face_tracking", "wide", "split_screen", "stacked", "passthrough", "grid_3", "grid_4"],
|
|
172
179
|
},
|
|
173
|
-
caption_style: {
|
|
180
|
+
caption_style: {
|
|
181
|
+
type: "string",
|
|
182
|
+
// Keep in sync with CAPTION_STYLES below (katto_list_caption_styles).
|
|
183
|
+
enum: ["default", "hormozi", "yellowPop", "redAlert", "skyline", "bubblegum", "aqua", "violet", "headline", "centerPop", "topLime", "impactMax", "bebasGold", "robotoBold", "montserratClean", "poppinsSoft", "robotoDoc", "broadcast", "wideClean", "mono", "bebasWhite", "rainbow", "multicolor"],
|
|
184
|
+
description: "A caption style preset name. See katto_list_caption_styles for the labels.",
|
|
185
|
+
},
|
|
174
186
|
},
|
|
175
187
|
required: ["id", "clip_index"],
|
|
176
188
|
},
|
|
@@ -240,6 +252,7 @@ const ANNOTATIONS = {
|
|
|
240
252
|
katto_get_account: { title: "Get account", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
241
253
|
katto_list_sources: { title: "List supported sources", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
242
254
|
katto_list_clip_lengths: { title: "List clip-length options", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
255
|
+
katto_list_caption_styles: { title: "List caption styles", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
243
256
|
katto_rerender_clip: { title: "Re-render a clip", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
244
257
|
katto_dub_clip: { title: "Dub a clip", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
245
258
|
katto_get_rerender: { title: "Poll a re-render", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
@@ -251,16 +264,17 @@ const ANNOTATIONS = {
|
|
|
251
264
|
// on tools/list — identical across all sources, enriching the terser inline text.
|
|
252
265
|
const DESCRIPTIONS = {
|
|
253
266
|
katto_create_clip_job: "Submit a long video (YouTube, Twitch, Vimeo, Rumble, Zoom, Dailymotion) for clipping. Consumes 1 video from your monthly quota — check katto_get_usage first. Clips are produced asynchronously; returns a job id, then poll katto_get_job until status is 'completed'. Fails if the URL is unsupported or the video is over 90 minutes.",
|
|
254
|
-
katto_get_job: "Read-only. Get the status, progress and clips of a job by id.
|
|
267
|
+
katto_get_job: "Read-only. Get the status, progress and clips of a job by id. Clips come ranked by virality score (0-100, highest first; ties broken by clip_index). Each clip is { url, captions_url, title, score, clip_index, hd }: when status is 'completed' every url is a finished, downloadable clip; hd is true once the 1080p high-quality render is ready. hd=false does NOT mean broken — the url already works, the 1080p is just still rendering in the background (and stays the standard render on the free plan). The job-level hd_ready flag turns true once every clip is hd, i.e. the URLs are final and won't be swapped again (status='completed' fires earlier). Returns 404 for an unknown id.",
|
|
255
268
|
katto_list_jobs: "Read-only. List your recent jobs, newest first. Paginate with 'cursor' (pass the previous next_cursor); optional 'status' filter. Returns { jobs: [{id, status, source, created_at, completed_at}], next_cursor }.",
|
|
256
|
-
katto_get_clips: "Read-only convenience:
|
|
269
|
+
katto_get_clips: "Read-only convenience: the clips of a job as { url, captions_url, title, score, clip_index, hd }, ranked by score (highest first). hd=true means the 1080p render is ready; hd=false means the url is the standard render (HD still finishing, or the free plan). Empty until the first clip is ready.",
|
|
257
270
|
katto_get_usage: "Read-only. Your current plan and monthly video quota: { plan, videos_used, videos_limit, videos_remaining }. Call before katto_create_clip_job to confirm remaining quota.",
|
|
258
271
|
katto_get_transcript: "Read-only. The transcript of a completed job as timestamped segments [{ start, end, text }]. Returns 404 while the job is still processing.",
|
|
259
272
|
katto_cancel_job: "Cancel a still-running job (queued/processing) and refund the video back to your monthly quota. Safe to retry (idempotent). Returns an error if the job already finished, failed, or was cancelled.",
|
|
260
273
|
katto_get_account: "Read-only. The account behind this key: plan, this key's scopes (read/write), and monthly quota { videos_used, videos_limit, videos_remaining }.",
|
|
261
274
|
katto_list_sources: "Read-only. The video platforms Katto can clip from, each with an example URL. Use it to confirm a URL is supported before calling katto_create_clip_job.",
|
|
262
|
-
katto_list_clip_lengths: "Read-only. The valid values for the optional config.clipLength on katto_create_clip_job (target clip-duration buckets).",
|
|
263
|
-
|
|
275
|
+
katto_list_clip_lengths: "Read-only. The valid values for the optional config.clipLength on katto_create_clip_job (target clip-duration buckets). Note: clipLength is fixed at creation and cannot be changed by re-render.",
|
|
276
|
+
katto_list_caption_styles: "Read-only. The valid caption_style preset names for katto_rerender_clip (id + label), e.g. 'hormozi' for bold word-by-word highlight. Call this before re-rendering so you pass a real preset instead of guessing.",
|
|
277
|
+
katto_rerender_clip: "Re-render one already-finished clip with a new reframe layout and/or caption style (get valid caption_style values from katto_list_caption_styles). Free — does NOT use video quota. Each call starts a new render (not idempotent); the original clip is kept. Returns a rerender_id; poll katto_get_rerender for the new clip url.",
|
|
264
278
|
katto_dub_clip: "Re-render one finished clip dubbed into one or more of 8 languages (en, es, fr, it, pt, hi, ja, zh). Free — does NOT use video quota. Each call starts a new render (not idempotent). Returns a rerender_id; poll katto_get_rerender for the result.",
|
|
265
279
|
katto_get_rerender: "Read-only. Poll a re-render started by katto_rerender_clip or katto_dub_clip. Returns { status, clip_url, captions_url } — clip_url is null until status is 'completed'.",
|
|
266
280
|
katto_get_brand_kit: "Read-only. Your saved brand kits (colors, caption font and position, default layout, watermark url).",
|
|
@@ -289,8 +303,35 @@ const CLIP_LENGTHS = [
|
|
|
289
303
|
{ value: '60_90', label: '60 to 90 seconds' },
|
|
290
304
|
{ value: '90_180', label: '90 to 180 seconds' },
|
|
291
305
|
];
|
|
306
|
+
// Valid values for caption_style on katto_rerender_clip. Mirrors the editor's
|
|
307
|
+
// named presets. Keep in sync with mcp-worker/src/index.js CAPTION_STYLES.
|
|
308
|
+
const CAPTION_STYLES = [
|
|
309
|
+
{ value: 'default', label: 'Default' },
|
|
310
|
+
{ value: 'hormozi', label: 'Hormozi (bold word-by-word highlight)' },
|
|
311
|
+
{ value: 'yellowPop', label: 'Yellow Pop' },
|
|
312
|
+
{ value: 'redAlert', label: 'Red Alert' },
|
|
313
|
+
{ value: 'skyline', label: 'Skyline' },
|
|
314
|
+
{ value: 'bubblegum', label: 'Bubblegum' },
|
|
315
|
+
{ value: 'aqua', label: 'Aqua' },
|
|
316
|
+
{ value: 'violet', label: 'Violet' },
|
|
317
|
+
{ value: 'headline', label: 'Headline' },
|
|
318
|
+
{ value: 'centerPop', label: 'Center Pop' },
|
|
319
|
+
{ value: 'topLime', label: 'Top Lime' },
|
|
320
|
+
{ value: 'impactMax', label: 'Impact Max' },
|
|
321
|
+
{ value: 'bebasGold', label: 'Bebas Gold' },
|
|
322
|
+
{ value: 'robotoBold', label: 'Roboto Bold' },
|
|
323
|
+
{ value: 'montserratClean', label: 'Montserrat' },
|
|
324
|
+
{ value: 'poppinsSoft', label: 'Poppins' },
|
|
325
|
+
{ value: 'robotoDoc', label: 'Roboto Doc' },
|
|
326
|
+
{ value: 'broadcast', label: 'Broadcast' },
|
|
327
|
+
{ value: 'wideClean', label: 'Wide Clean' },
|
|
328
|
+
{ value: 'mono', label: 'Mono' },
|
|
329
|
+
{ value: 'bebasWhite', label: 'Bebas' },
|
|
330
|
+
{ value: 'rainbow', label: 'Rainbow (per-word colour cycle)' },
|
|
331
|
+
{ value: 'multicolor', label: 'Multicolor' },
|
|
332
|
+
];
|
|
292
333
|
|
|
293
|
-
const server = new Server({ name: "katto", version: "0.5.
|
|
334
|
+
const server = new Server({ name: "katto", version: "0.5.5" }, { capabilities: { tools: {} } });
|
|
294
335
|
|
|
295
336
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS_LISTED }));
|
|
296
337
|
|
|
@@ -327,6 +368,8 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
327
368
|
data = { sources: SOURCES, note: "You can also clip a local file via the REST API (POST /v1/uploads)." };
|
|
328
369
|
} else if (name === "katto_list_clip_lengths") {
|
|
329
370
|
data = { clip_lengths: CLIP_LENGTHS };
|
|
371
|
+
} else if (name === "katto_list_caption_styles") {
|
|
372
|
+
data = { caption_styles: CAPTION_STYLES };
|
|
330
373
|
} else if (name === "katto_rerender_clip") {
|
|
331
374
|
const b = {};
|
|
332
375
|
if (args.layout_mode) b.layout_mode = args.layout_mode;
|
package/package.json
CHANGED
|
@@ -1,43 +1,45 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "katto-mcp",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"mcpName": "io.github.miracleweasel/katto-mcp",
|
|
5
|
-
"description": "AI video clipping MCP server: turn long videos, podcasts and Twitch VODs into scored, captioned 9:16 shorts from Claude, Cursor, ChatGPT and any MCP client.",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"katto-mcp": "index.mjs"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"index.mjs",
|
|
12
|
-
"README.md",
|
|
13
|
-
"LICENSE"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"video-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "katto-mcp",
|
|
3
|
+
"version": "0.5.6",
|
|
4
|
+
"mcpName": "io.github.miracleweasel/katto-mcp",
|
|
5
|
+
"description": "AI video clipping MCP server: turn long videos, podcasts and Twitch VODs into scored, captioned 9:16 shorts from Claude, Cursor, ChatGPT and any MCP client.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"katto-mcp": "index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.mjs",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"SKILL.md",
|
|
15
|
+
"QUICKSTART.md"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"mcp",
|
|
22
|
+
"model-context-protocol",
|
|
23
|
+
"katto",
|
|
24
|
+
"video",
|
|
25
|
+
"clips",
|
|
26
|
+
"shorts",
|
|
27
|
+
"ai",
|
|
28
|
+
"ai-video-clipper",
|
|
29
|
+
"video-to-shorts",
|
|
30
|
+
"youtube-to-shorts",
|
|
31
|
+
"podcast-clips",
|
|
32
|
+
"ai-captions",
|
|
33
|
+
"ai-video-editor",
|
|
34
|
+
"repurpose-video",
|
|
35
|
+
"video-dubbing"
|
|
36
|
+
],
|
|
37
|
+
"homepage": "https://katto.tech/docs/api",
|
|
38
|
+
"repository": { "type": "git", "url": "git+https://github.com/miracleweasel/katto-mcp.git" },
|
|
39
|
+
"bugs": { "url": "https://katto.tech/contact" },
|
|
40
|
+
"author": "Katto (https://katto.tech)",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|