Package Exports
- @crabcut/mcp-server
- @crabcut/mcp-server/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@crabcut/mcp-server) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@crabcut/mcp-server
Turn YouTube videos into short clips -- from Claude, Cursor, or any AI assistant that supports MCP.
You give it a YouTube link. It finds the best moments, reframes them for vertical video (9:16), adds subtitles, and gives you download links. All from a chat or automation workflow.
Quick Start
- Get an API key at app.crabcut.ai/developers
- Run:
CRABCUT_API_KEY=sk_live_... npx @crabcut/mcp-serverThat's it. The server connects via stdio and works with any MCP client.
Setup
Claude Desktop
Add this to your Claude config (claude_desktop_config.json):
{
"mcpServers": {
"crabcut": {
"command": "npx",
"args": ["@crabcut/mcp-server"],
"env": {
"CRABCUT_API_KEY": "sk_live_..."
}
}
}
}Cursor
Add to .cursor/mcp.json in your project:
{
"mcpServers": {
"crabcut": {
"command": "npx",
"args": ["@crabcut/mcp-server"],
"env": {
"CRABCUT_API_KEY": "sk_live_..."
}
}
}
}Smithery
npx @smithery/cli mcp add crabcut/crabcut-mcp-serverRemote (Streamable HTTP)
For n8n, custom integrations, or any client that supports remote MCP:
- Endpoint:
https://mcp.crabcut.ai/mcp - Auth:
Authorization: Bearer sk_live_... - Transport: Streamable HTTP (POST)
Tools
| Tool | What it does |
|---|---|
generate_clips |
Start clip generation from a YouTube URL. Returns a project_id right away. |
get_project_status |
Check progress and get clips when ready. Clips are sorted by score (best first). |
list_projects |
List your projects with status and clip counts. |
get_clip |
Get full details for a single clip. |
check_usage |
See your plan, remaining credits, and usage. |
How It Works
Clip generation takes a few minutes. Here is the flow:
- Call
generate_clipswith a YouTube URL - You get back a
project_idimmediately - Wait for results using one of two methods (polling or webhook)
- When done, you get an array of clips sorted by score (best first), each with a
download_url
Project Statuses
As your project moves through the pipeline, status changes:
| status | Meaning |
|---|---|
pending |
Job is queued, not started yet |
processing |
Video is being downloaded, analyzed, or clips are being cut/exported |
completed |
All clips are exported and ready to download |
completed_no_clips |
Processing finished but no good clips were found |
failed |
Something went wrong (check error field) |
The step field gives more detail during processing:
| step | Meaning |
|---|---|
queued |
Waiting to start |
DOWNLOADING_VIDEO |
Downloading from YouTube |
EXTRACTING_AUDIO |
Extracting audio for transcription |
TRANSCRIBING |
Transcribing speech to text |
DETECTING_HIGHLIGHTS |
AI is finding the best moments |
CUTTING_CLIPS |
Creating individual clips |
EXPORTING_CLIPS |
Rendering final videos with subtitles |
done |
Everything is finished |
Clip Statuses
Each clip in the response has its own clip_status:
| clip_status | Meaning |
|---|---|
pending |
Clip is created, export not started yet |
exporting |
Video is being rendered with subtitles |
completed |
Ready -- download_url is available |
failed |
Export failed for this clip |
API Reference
generate_clips
Start clip generation from a YouTube video.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | Full YouTube video URL |
start_time |
number | No | Start time in seconds (to process only a segment) |
end_time |
number | No | End time in seconds (to process only a segment) |
callback_url |
string | No | Webhook URL to receive results when done |
Response:
{
"project_id": "43dbe622-8ac6-4579-9625-0ad7f0f9db0b",
"status": "processing",
"poll_url": "/api/v1/projects/43dbe622-8ac6-4579-9625-0ad7f0f9db0b",
"estimated_minutes": 5,
"message": "Processing started. Poll with get_project_status every 10-15 seconds until status is 'completed'."
}get_project_status
Check progress and get clips. Poll every 10-15 seconds.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
project_id |
string | Yes | The project ID from generate_clips |
Response (while processing):
{
"id": "43dbe622-8ac6-4579-9625-0ad7f0f9db0b",
"name": "Video Title",
"status": "processing",
"step": "CUTTING_CLIPS",
"error": null,
"expected_clips": 9,
"duration": 639,
"created_at": "2026-03-15T02:21:46.226Z",
"clips": [
{
"id": "a567a875-...",
"title": "They Overthink a Chair Like a Crisis",
"duration": 29.19,
"score": 74,
"reason": "Focused on one absurd premise with escalating comedy.",
"clip_status": "exporting",
"download_url": null,
"quality": "1080p",
"thumbnail_url": null,
"created_at": "2026-03-15T02:27:16.629Z",
"updated_at": "2026-03-15T02:27:16.666Z"
}
]
}Response (when completed):
{
"id": "43dbe622-8ac6-4579-9625-0ad7f0f9db0b",
"name": "Video Title",
"status": "completed",
"step": "done",
"error": null,
"expected_clips": 9,
"duration": 639,
"created_at": "2026-03-15T02:21:46.226Z",
"clips": [
{
"id": "32538b9c-...",
"title": "One Dating Theory Leads to Chaos",
"duration": 41.83,
"score": 90,
"reason": "Sharp universal joke that hooks instantly with strong reactions.",
"clip_status": "completed",
"download_url": "https://cdn.crabcut.ai/exports/premium/.../clip-32538b9c-....mp4",
"quality": "1080p",
"thumbnail_url": "https://cdn.crabcut.ai/exports/premium/.../clip-32538b9c-...-thumb.jpg",
"created_at": "2026-03-15T02:29:10.954Z",
"updated_at": "2026-03-15T02:30:43.907Z"
},
{
"id": "a567a875-...",
"title": "They Overthink a Chair Like a Crisis",
"duration": 29.19,
"score": 74,
"reason": "Focused on one absurd premise with escalating comedy.",
"clip_status": "completed",
"download_url": "https://cdn.crabcut.ai/exports/premium/.../clip-a567a875-....mp4",
"quality": "1080p",
"thumbnail_url": "https://cdn.crabcut.ai/exports/premium/.../clip-a567a875-...-thumb.jpg",
"created_at": "2026-03-15T02:27:16.629Z",
"updated_at": "2026-03-15T02:28:22.816Z"
}
]
}Clips are sorted by score (highest first). The first clip in the array is the best one.
list_projects
List your projects.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
limit |
number | No | Max projects to return. Default 20, max 100. |
status |
string | No | Filter by status: pending, processing, completed, completed_no_clips, failed |
Response:
{
"projects": [
{
"id": "43dbe622-...",
"name": "Video Title",
"status": "completed",
"step": "done",
"expected_clips": 9,
"clips_count": 8,
"duration": 639,
"created_at": "2026-03-15T02:21:46.226Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}get_clip
Get full details for a single clip.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
clip_id |
string | Yes | The clip ID from a project's clips array |
Response:
{
"id": "32538b9c-...",
"project_id": "43dbe622-...",
"title": "One Dating Theory Leads to Chaos",
"duration": 41.83,
"score": 90,
"reason": "Sharp universal joke that hooks instantly.",
"export_status": "completed",
"export_quality": "1080p",
"is_exported": true,
"video_url": "https://cdn.crabcut.ai/...",
"video_url_720p": "https://cdn.crabcut.ai/...",
"video_url_1080p": "https://cdn.crabcut.ai/...",
"thumbnail_url": "https://cdn.crabcut.ai/...",
"created_at": "2026-03-15T02:29:10.954Z",
"updated_at": "2026-03-15T02:30:43.907Z"
}check_usage
Check your credits and plan.
Input: None.
Response:
{
"plan": "pro",
"credits_remaining": 450,
"credits_total": 500,
"period_start": "2026-03-01T00:00:00.000Z",
"period_end": "2026-04-01T00:00:00.000Z"
}Error Responses
When something goes wrong, the API returns an error object:
{ "error": "Insufficient credits", "required": 10, "available": 3 }Common errors:
| HTTP Status | Error | What to do |
|---|---|---|
| 400 | Invalid YouTube URL | Check the URL format |
| 401 | Unauthorized | Check your API key |
| 402 | Insufficient credits | Buy more credits or use a shorter video |
| 429 | Rate limit exceeded | Wait and try again |
| 500 | Internal server error | Try again later |
Callback Webhook
Pass a callback_url when calling generate_clips. We will POST to that URL when all clips are exported and ready.
Payload:
{
"event": "project.completed",
"project_id": "43dbe622-...",
"status": "completed",
"source_url": "https://www.youtube.com/watch?v=H51iLa1leOU",
"clips": [
{
"id": "32538b9c-...",
"title": "One Dating Theory Leads to Chaos",
"duration": 41.83,
"score": 90,
"download_url": "https://cdn.crabcut.ai/exports/premium/.../clip-32538b9c-....mp4",
"thumbnail_url": "https://cdn.crabcut.ai/exports/premium/.../clip-32538b9c-...-thumb.jpg",
"quality": "1080p"
}
]
}For failed projects:
{
"event": "project.failed",
"project_id": "43dbe622-...",
"status": "failed",
"source_url": "https://www.youtube.com/watch?v=...",
"error": "YouTube video is unavailable",
"clips": []
}Clips are sorted by score (highest first). We retry the webhook up to 3 times if your server doesn't respond.
Verifying webhooks (optional): Each callback includes an X-Crabcut-Signature header. To verify it came from Crabcut:
- Compute
SHA-256of your API key to get your signing key - Compute
HMAC-SHA256of the raw request body using that signing key - Compare with the header value (format:
sha256=<hex>)
This step is optional. If you skip it, everything still works.
Using with n8n
There are two ways to set this up in n8n:
Option A -- Webhook (recommended):
- Create a new workflow with a Webhook trigger node. Copy its URL (e.g.
https://your-n8n.com/webhook/abc123). - Add an HTTP Request node:
- Method:
POST - URL:
https://api.crabcut.ai/api/v1/clips/generate - Authentication: Header Auth
- Header Name:
Authorization - Header Value:
Bearer sk_live_... - Body (JSON):
{ "url": "https://www.youtube.com/watch?v=...", "callback_url": "https://your-n8n.com/webhook/abc123" }
- Method:
- When clips are ready, the Webhook node receives the payload and your workflow continues.
- Access the best clip:
{{ $json.clips[0].download_url }}
Option B -- Polling loop:
- HTTP Request node:
POST https://api.crabcut.ai/api/v1/clips/generatewith body{"url": "..."}. Same auth as above. - Wait node: 15 seconds.
- HTTP Request node:
GET https://api.crabcut.ai/api/v1/projects/{{ $json.project_id }} - IF node: if
{{ $json.status }}is notcompleted, loop back to the Wait node. - When complete, the response includes all clips with download URLs.
- Access the best clip:
{{ $json.clips[0].download_url }}
Tips for n8n:
clipsis sorted by score. Index0is always the best clip.- Use
{{ $json.clips.length }}to check how many clips were generated. - Each clip has a
clip_status. You can filter for only completed clips. - Free plans export at 720p. Pro plans export at 1080p.
REST API
If you want to call the API directly (without MCP), here are the endpoints:
| Method | Endpoint | Description |
|---|---|---|
POST |
https://api.crabcut.ai/api/v1/clips/generate |
Start clip generation |
GET |
https://api.crabcut.ai/api/v1/projects/:id |
Get project status and clips |
GET |
https://api.crabcut.ai/api/v1/projects |
List projects |
GET |
https://api.crabcut.ai/api/v1/clips/:id |
Get single clip details |
GET |
https://api.crabcut.ai/api/v1/account/usage |
Check credits and plan |
All endpoints require the header: Authorization: Bearer sk_live_...
Billing
Each minute of source video costs credits. A 10-minute video costs more credits than a 2-minute video. Check your balance with check_usage. Get credits at crabcut.ai/pricing.
Environment Variables
| Variable | Required | Default |
|---|---|---|
CRABCUT_API_KEY |
Yes | -- |
CRABCUT_API_URL |
No | https://api.crabcut.ai |
Links
- Website: crabcut.ai
- Get your API key: app.crabcut.ai/developers
- REST API base:
https://api.crabcut.ai/api/v1
License
MIT