UNPKG

@kolbo/mcp

Version:

Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code

127 lines (97 loc) • 10.9 kB
# Media Library Load this file when the user wants to browse, list, organize, delete, restore, move, favorite, share, or otherwise manage their media library — or when you produce a media file locally and need to surface it back to the user. The library covers both **uploaded files** and **AI-generated outputs the user has saved**. Tools fall into five groups: ingest, browse, lifecycle (delete/restore/move), folders, and favorites. `list_media` returns the complete requested page in both text and widget results. Follow `pagination.has_next` using the returned page size; use smaller pages (for example 20) when reviewing detailed assets to keep context manageable. `project_id` restricts SDK results to that project's recorded membership, not the project-looking segment in a CDN URL (files can be moved). A folder filter takes precedence over the project filter. For production research, `get_visual_dna` provides the full stored description and references; list descriptions are compact previews. Internal extraction system prompts are intentionally private. `get_project_profile` reads the stored synthesized brief; it is not a substitute for the original project documents or session history. ## ⚠️ Already-hosted URLs — never re-upload `generate_*` / `list_media` / `get_media` / a prior `upload_media` already return a Kolbo CDN URL (`media.kolbo.ai`, `*.kolbo.ai`, Spaces). Pass that exact URL into the next generation tool. Calling `upload_media` on it duplicates the file. `upload_media` is only for a local path or an external (non-Kolbo) URL. If you already have a Kolbo URL, skip ingest. ## ⚠️ Present locally-produced media to the user When you produce a media file LOCALLY — `ffmpeg` via the `video-production` skill, Remotion render, manual `Bash` mux of audio + video, `edit_image` outputs saved to disk, any save-to-file flow — make sure the user can actually find and open it. Local files are invisible in the chat / canvas UI by default; only the path string makes it through. **Rules:** 1. **Surface the file in chat as a clickable thing**, not just a path string. Write the line as a markdown link to a `file://` URL so the user can click to open it in their default app: ``` ✅ Final video ready: [zohar_hagai_campaign.mp4](file:///Users/mymac/Documents/test agent 1/zohar_hagai_campaign.mp4) (45s · 1440×1440 · with music) ``` The user clicks the link → the desktop app shell hands the path to the system → opens in QuickTime / VLC / Finder reveal, etc. 2. **Always log the local path in `.kolbo/production.md`** under the artifact's entry — that's the durable record: ```md ## Final - **Campaign video (45s)** - local: /Users/mymac/Documents/test agent 1/zohar_hagai_campaign.mp4 - resolution: 1440×1440 - audio: Gilded Horizon (Track 1 & 2, 3:03) - rendered: 2026-05-16 ``` 3. **Don't auto-upload to `upload_media`**. The user wants local-only files to stay local; they have the file on disk and can move/share it themselves. Upload only when the user explicitly asks ("upload this", "share publicly", "give me a CDN URL"). 4. **Reveal-in-Finder affordance for macOS** when finishing a multi-step production: in addition to the `file://` link, mention the parent directory path so the user can `cd` or open the folder. Many users want to see all the intermediate files (frames, alt cuts, original audio) in one place. 5. **Files served via `file://` won't render inline** in the chat as `<video>` / `<img>` — the desktop WebView blocks file:// for security. Don't try to embed; just link. ## Local files — pick by where the SERVER runs, not by which client you are A tool call executes on the Kolbo server. Handing it `C:\Users\...` or `/Users/...` gives it a *string*, not the bytes — so a local path only resolves when server and client share a filesystem. Choose by transport: | Situation | Call | |---|---| | **Local (stdio) install** — `npx @kolbo/mcp` on the same machine | `upload_media` with the absolute path | | **Remote connector + you can run shell commands** (Claude Code, Codex, Cursor, CI) | `create_upload_ticket`, then POST each file to `upload_url` | | **Remote connector, no filesystem** (claude.ai web/mobile) | `media_upload_widget` — the user picks the file | `create_upload_ticket` returns `upload_url` + a short-lived `token`. Upload with multipart field `file` and `Authorization: Bearer <token>`; the stable CDN URL comes back at `media.url`. One POST per file, ticket reusable for a batch. Then pass those URLs to any generation tool. ```bash curl -X POST "<upload_url>" -H "Authorization: Bearer <token>" -F "file=@/abs/path/clip.mp3" ``` Do **not** fall back to `upload_media`'s `source_base64` for anything but a tiny file — it pushes the whole file through the model's context, twice. And do not reach for cloud credentials or a bucket of your own; the ticket is the sanctioned path. On Windows, give `curl` a native `C:/Users/...` path — a Git Bash `/c/Users/...` path fails to open (exit 26). ## Routing — user says → call | User says | Call | |---|---| | "Upload this file" / "host this" / "give me a public URL for this" | `upload_media` — but see "Local files" above if it's a path on the user's disk | | "Show my media" / "list my images/videos" / "what do I have?" | `list_media` (pass `type` / `category` / `project_id` / `folder_id` / `search`) | | "Show my favorites" / "list starred items" | `list_media` with `category=favorites` | | "List everything in project X" | `list_media` with `project_id=X` | | "List all videos in folder X" | `list_media` with `folder_id=X, type=video` | | "What was the prompt for [item]?" / "tell me about this generation" | `get_media` | | "How many videos do I have?" / "what's my storage usage?" | `get_media_stats` | | "Favorite this" / "star this" / "save to favorites" | `favorite_media` | | "Unfavorite" / "remove from favorites" / "unstar" | `unfavorite_media` | | "Delete this" / "remove this image" | `delete_media` (soft, recoverable for 30 days) | | "Restore it" / "undelete" / "bring it back from trash" | `restore_media` | | "Permanently delete" / "wipe it forever" / "free up space" | **confirm with user** → `permanently_delete_media` | | "Move this to project X" | `move_media` | | "Move this whole session/chat to project X" / "this landed in the wrong project" | `move_session` (moves the session + ALL its media in one call — prefer over per-item `move_media`) | | "Clean up old [type]" / "delete everything from [time period]" | `list_media` (find ids) → **confirm** → `bulk_delete_media` | | "Restore all from trash" | `list_media include_deleted=true` → `bulk_restore_media` | | "Empty my trash" / "purge deleted items" | `list_media include_deleted=true` → **show count, confirm** → `bulk_permanently_delete_media` | | "Move all these to project X" | `bulk_move_media` | | "Move everything in folder X to project Y" | `move_folder_contents` | | "Make a folder for X" / "create a 'campaigns' folder" | `create_media_folder` | | "Rename folder" / "change folder color or icon" | `update_media_folder` | | "Delete the [name] folder" | **confirm with user** → `delete_media_folder` (items stay in library) | | "Add these to [folder]" / "put these in folder X" | `add_media_to_folder` | | "Remove these from [folder]" | `remove_media_from_folder` | | "Share [folder] with alice@…" | `share_media_folder` with `user_emails: [...]` | | "Revoke [user]'s access to [folder]" | `unshare_media_folder` with `user_id` | | "Show my folders" / "what folders do I have?" | `list_media_folders` | ## Rules and gotchas 1. **"Delete" is soft by default.** Use `delete_media` / `bulk_delete_media` for normal "delete" intent — items go to trash for 30 days and are recoverable. Only use `permanently_delete_media` / `bulk_permanently_delete_media` when the user explicitly asks for unrecoverable deletion ("permanently", "forever", "wipe", "free up space"). **Always confirm before either permanent variant.** 2. **Confirm before destructive folder ops.** `delete_media_folder` detaches items (they stay in the library) but the folder itself is gone — no undo. Confirm with the user. 3. **`bulk_move_media` is atomic.** If you get a "not all items owned by you" error, do NOT retry partially. Surface the error to the user and let them pick a smaller batch. 4. **`upload_media` accepts `project_id`** — when the user works in a named project, pass it on uploads too (resolve via `list_projects`), or the file lands outside the project. 5. **Prefer `list_media` filters over post-filtering.** Pass `project_id` / `folder_id` / `category` / `type` / `search` to the backend; don't fetch the whole library and filter client-side. 6. **`is_favorited` is per-user.** On shared projects, an item can be favorited by you and not by your teammates — the value reflects the calling user only. 7. **"Empty trash" flow:** `list_media` with `include_deleted=true` → show the count → confirm → `bulk_permanently_delete_media`. Never call the bulk-permanent endpoint without listing first so the user knows the scope. 8. **Bulk caps:** 1000 ids for `bulk_delete_media` / `bulk_restore_media` / `bulk_permanently_delete_media` / `bulk_move_media`; 500 ids for `add_media_to_folder` / `remove_media_from_folder`. Split larger jobs into successive calls. 9. **Folder share resolution:** `share_media_folder` takes emails; users not found come back in `not_found`. Report those to the user — don't assume the share succeeded silently. Members can list/add/remove items but cannot delete the folder or reshare it. 10. **`get_media` accepts a generation_id as a fallback** for the `media_id` arg, so you can chase down items the user references by their original generation rather than by library id. ## SYNCI licensed music — operational detail The `*_music_library` tools (`search_music_library` / `browse_music_library` / `get_music_library_facets` / `get_music_track_audio` / `get_music_track_lyrics` / `get_music_track_related` / `analyze_script_for_music` / `acquire_clean_music_track` / `import_music_track_to_library`) front **SYNCI**, a commercially licensed catalog — not free stock. - Discovery and previews are free but **watermarked** — there is no unwatermarked URL until you pay. - `acquire_clean_music_track` **CHARGES CREDITS** for the clean master. Confirm with the user first, and pass a stable `requestId` so a retry doesn't buy the track twice. - `import_music_track_to_library` charges the same way AND also copies the clean track into the media library. - `analyze_script_for_music` turns a script into search terms for `search_music_library`. - Use this family when the user needs music cleared for commercial use. When free stock will do, use `search_stock_media` with `mediaType: "music"` instead.