- Brand
- Kapwing
- Category
- Content & Design
- Primary Subcategory
- Video & Podcast Editing
Integration details
Description
Translate, subtitle, and dub videos and audio from one language to another using Kapwing. Upload a video from your computer, transcribe it, add subtitles in the original or a translated language, and dub the speech into other languages in voices cloned from the original speakers. You can also browse your workspace's recent projects and media library, check your remaining credits, and export projects to MP4 with a download link when they're done. Every result links to the project in the Kapwing editor for further changes. Limitations: the plugin only works with workspaces your connected Kapwing account belongs to, and it cannot delete projects or media. Transcription, translation, and dubbing use your workspace's existing Kapwing credits. Timeline edits such as trims and transitions happen in the Kapwing editor. Dubbing replaces the audio only and is not lip-synced.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Video & Podcast Editing
- Secondary Subcategories
- None listed
- Brand
- Kapwing
- Access
- Account required
- First tracked
- 2026-10-16
- Tool count
- 48
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Your score is coming
ChatGPT now suggests Plugins on its own when they match a user's request.Your Plugin Discovery Score measures how often yours appears, and it will show here as soon as it’s ready.
What discovery looks like

Get alerts for Kapwing
Get updates when Kapwing’s Discoverability Score or category rank changes.
Competing in ChatGPT Video & Podcast Editing
View Category48 tools agents can invoke
Turn subtitles on for one asset in a Kapwing project. Returns the project's `editorUrl` to view, edit, restyle, or export them. Needs a finished `start_transcription` for the asset, then this call with the transcript's `languageCode` (the code given to `start_transcription`, or the detected code `poll_transcription` reports when it was auto-detected). For translated captions, either run `start_transcription` with `translateLanguageCode` and pass the same value here, or pass a finished translation job's `translationId` (translation tools, when enabled for you). A `translateLanguageCode` the asset has no transcript for is refused, since the project would show source-language words labelled as translated. This does not transcribe or translate anything, and it does not produce a downloadable file; the subtitles live on the project. Pass `styling` to change placement, size, colour, or word-by-word animation, or omit it to keep the current look.
add_captions
Add one glossary override (sourceText → targetText) for a team/language-pair. Applied to future `start_translation` runs — the translator emits `targetText` verbatim wherever it sees `sourceText`. Use for brand names, proper nouns, or terms the model consistently mis-translates. No dedup — adding the same source text twice creates two rows.
add_glossary_term
Start a chunked-upload session that the sidecar drives against GCS on your behalf. Upload paths at a glance (pick the smallest fit): Hosted URL, ≤500MB → upload_asset_from_url (1 MCP call; server-side fetch) Local, up to ~1GB → create_upload_url → single HTTP PUT → register_asset_from_blob Local, up to 5GB, no HTTP → begin_upload → N × upload_chunk (isFinal) → register_asset_from_blob Local, caller can't read it → upload_asset_from_computer (browser panel; user picks file; up to 5GB) Egress: only `create_upload_url` (PUT to `storage.googleapis.com`) makes an outbound request of your own, so it is the only path ruled out when a request is refused for egress or sandbox reasons. Use `upload_asset_from_url` when the file is hosted. `begin_upload` needs no outbound request either, but its chunks are base64 you would have to emit yourself and that corrupts far below one chunk (sc-59914) — a scripted-caller path and not your fallback. If you write the tool arguments yourself and the network is refused, go to `upload_asset_from_computer`; the user can instead allow the domain in their sandbox's network egress settings and retry, if they would rather not re-pick the file. Follow up with N × `upload_chunk` and set `isFinal:true` on the last one — the sidecar finalizes and you then call `register_asset_from_blob` with the returned `assetId`. Use this when your MCP client can only make tool calls (no out-of-band HTTP). Prefer `create_upload_url` whenever you can make one outbound HTTP PUT — two MCP calls plus the PUT, instead of N chunk calls. Small totals do work here: GCS's 256KB rule binds only NON-final chunks, so a lone `isFinal:true` chunk may be any size. Chunks cross as base64 through MCP; suggested chunk size is 8MB. Returns `{uploadId, assetId, blobName, chunkSizeBytes, expiresAtMs}` — or, if a prior `assetId` you passed turns out to already have its bytes landed, `{assetId, blobName, alreadyUploaded:true}` with no `uploadId` (skip straight to registering). Session token embeds all resumption state and is portable across sidecar pods; expires after 1h. Refused before the session opens when the team's storage is full.
begin_upload
Poll a brand-kit voice-cloning job's status. On `status:'complete'` the trained ElevenLabs `voiceId` is populated — feed it into `start_dubbing_tts` chunks, or into any other tool that takes an ElevenLabs voiceId. Persisting it as a named team preset is done from the Kapwing web UI and is intentionally not on the MCP surface. On `status:'error'`, `error` carries the failure details.
poll_brandkit_voice_cloning
Poll a dubbing TTS job. `status:'complete'` populates `ttsCacheIds` — pass those directly to `list_dubbing_tts_cache({ttsCacheIds})` for the generated audio URLs. `status:'error'` puts details in `error`. `status:'pending'` means poll again. A complete job means the audio was generated, NOT that the project was dubbed: the dub is a standalone audio asset and nothing is written to the project. `projectId` / `editorUrl` name the source project, which still plays its original audio.
poll_dubbing_tts
Poll dubbing started by `start_dubbing`. Returns one entry per workflow with `status`, `done`, `failed` and the current stage (and `failureReason` when the backend stopped it for a known cause, such as no speech in the video), plus `projectIdByLanguage` / `editorUrlByLanguage` once known, and `dubbedAudioAssets` / `backgroundAudioAssetId` once the audio has rendered. `done:true` on every entry means the dubbed audio has been laid onto the project's timeline, so the editorUrl is worth opening and an export of that project will carry the dub. Dubbing runs a transcribe, translate, voice-clone, TTS and audio-render chain, so expect minutes — poll every 15-30 seconds rather than tightly.
poll_dubbing
Poll a voice-cloning job's status. `status:'complete'` means the clones are trained and the speaker→voiceId map is in `speakerVoiceCloneIds`; persist it with `save_dubbing_voice_clones({assetId, teamId, speakerVoiceCloneIds})` — `list_dubbing_voice_clones({assetId})` reads only what that save writes, so it stays empty until then — or feed the voiceIds straight into `start_dubbing_tts` chunks. `status:'error'` puts the failure in `error` — retry with adjusted time ranges. `status:'pending'` means poll again.
poll_dubbing_voice_cloning
Poll a project's export status. Companion to the dedicated export tool — call in an out-of-process loop until `ready === true`. Returns `status`: `processing` (export in flight), `done` (completed export available, `url` set), or `none` (nothing running and no completed export yet). An export sits in `processing` until the ks-jobs worker finishes. A project that has never been exported answers `none` — creating a project does not export one, and polling never starts an export. Use `download_export` for a strictly URL-first read. Hand the user the `editorUrl` this returns, verbatim. Never build a project link yourself: the path is `/{projectId}/studio/editor`, not `/projects/{projectId}` and not `/videos/{projectId}`. `/videos/{projectId}` is the finished-video page, which shows the project's last export rather than the project, so subtitles and dubs are missing from it.
poll_export
Smoke test that the MCP server can reach the configured Kapwing backend. Calls a trivial GET endpoint and returns the parsed body.
ping
Poll a translation job's progress. Returns `done:true` once the translated subtitles are ready — at that point call `get_translation({translationId})` for the aligned output (or read the `subtitles` array directly off this response, which the backend also includes when done). `progress` is a fraction 0..1 while running.
poll_translation
Poll a translate-text job's status and, if complete, its translated chunks. Poll this after `start_translate_text` until `status:'complete'` — each entry in `translations` pairs the original `text` with `translatedText`. On `status:'error'`, `error` carries the failure details. On `status:'pending'`, poll again in a few seconds.
poll_translate_text
Poll a transcription's progress. Returns `done:true` once the transcription is ready — at that point `assetTranscriptionId` is populated and you should hand it to `get_asset_transcription` to fetch the actual words. While pending, `progress` reports which stages have completed (downloaded → extracted → conformed → speech → done). If `progress.error` is set the job failed and further polling won't help. If `stalled:true` the job has gone too long without progress: stop polling and ask the user before starting a new transcription, since a new job is charged transcription credits again.
poll_transcription
Poll an asset's ingest status. Its companion is URL ingest, which returns before the server-side download finishes — call this in an out-of-process loop (once every few seconds) until `ready === true`. Returns `status` mapped to a string (`pending` / `uploading` / `uploaded` / `failed` / `queued`) plus a `ready` boolean and, when available, the signed URL, content type, name, and duration. An upload that completed synchronously already returns `ready:true` on the first call. Once the media has been probed, usually within a minute of `ready:true`, `dimensions` appears for images and video and `durationSeconds` for audio and video; a PDF gets neither. This tool only reads, so it never starts that probe; the tools that need the metadata start it themselves when it is missing.
poll_asset
Start a brand-kit voice-cloning job. Consumes one clone against the team's plan-tier max-clones quota. Rate-limited to 2 calls per minute — training runs are expensive and the quota is only enforced against clones already saved from the web UI. Returns the job — poll `poll_brandkit_voice_cloning({jobId})` until `status:'complete'` to get the ElevenLabs voiceId. This differs from `start_dubbing_voice_cloning` in two ways: (a) it's team-level (a preset voice, not per-source-asset) and (b) it takes full assets (no time-range slicing per speaker). Only clone or reproduce voices the user owns or has permission to use.
start_brandkit_voice_cloning
Advanced / single-stage. Prefer `start_dubbing`, which runs this stage as part of the full pipeline and leaves a playable dub on the project; this tool trains voice clones only and attaches nothing. Start a voice-cloning job that trains a per-speaker voice clone from segments of a source asset. Returns the job. Reuse behavior: a COMPLETED job on the same asset whose speaker labels all still have live voice ids is returned as-is — the match is asset + speaker labels, NOT the ranges, so re-running with different ranges for the same labels reuses the old clones instead of retraining (use new speaker labels to force a retrain); an IN-PROGRESS job matches on assetId ONLY — starting a new clone with different ranges while another one is running on the same asset returns the in-flight job, not a new one. Poll with `poll_dubbing_voice_cloning({jobId})` until `status:'complete'`; that response (and the reuse response here) carries the speaker→voiceId map in `speakerVoiceCloneIds`. Persist it with `save_dubbing_voice_clones` and feed those voiceIds into `start_dubbing_tts` chunks. `list_dubbing_voice_clones` reads what the save writes, so it stays empty until then. Only clone or reproduce voices the user owns or has permission to use.
start_dubbing_voice_cloning
Create a new Kapwing project from a single asset — the returned `editorUrl` opens it in the browser for editing. This is the tool to reach for when the user says "make a project from this image/video/audio" after an upload. Returns `{projectId, editorUrl, thumbnailSeeded, hint}`. It creates the project only and renders nothing, so `download_export({projectId})` and `poll_export({projectId})` report no export until one runs. To get a finished video file, export the returned `projectId` with the project export tool, which renders the project as it stands including later edits, then poll `poll_export`. The asset export tool is a different starting point: it builds and renders its own project straight from an `assetId`. Export tools are not enabled on every account; if neither is in your tool list, export from `editorUrl` in Studio. Exporting is always explicit, never a side effect of creating a project. Hand the user the `editorUrl` this returns, verbatim. Never build a project link yourself: the path is `/{projectId}/studio/editor`, not `/projects/{projectId}` and not `/videos/{projectId}`. `/videos/{projectId}` is the finished-video page, which shows the project's last export rather than the project, so subtitles and dubs are missing from it.
create_project_from_asset
Add one pronunciation override for a team. Once saved, `start_dubbing_tts` runs for this team will apply the override automatically to any occurrence of `sourceTerm`. Use for brand names that TTS mispronounces, foreign-language proper nouns, or acronyms.
create_pronunciation
Mint a GCS resumable-upload URL for a local file the caller will PUT themselves, then register with `register_asset_from_blob`. Your PUT goes to `storage.googleapis.com`. If your environment uses an egress allowlist, an agent proxy or a sandbox and you cannot confirm that host is allowed, do not spend a call here — go to `upload_asset_from_computer`, where the user's browser does the transfer. Being able to read the file is not evidence of egress. Upload paths at a glance (pick the smallest fit): Hosted URL, ≤500MB → upload_asset_from_url (1 MCP call; server-side fetch) Local, up to ~1GB → create_upload_url → single HTTP PUT → register_asset_from_blob Local, up to 5GB, no HTTP → begin_upload → N × upload_chunk (isFinal) → register_asset_from_blob Local, caller can't read it → upload_asset_from_computer (browser panel; user picks file; up to 5GB) Egress: only `create_upload_url` (PUT to `storage.googleapis.com`) makes an outbound request of your own, so it is the only path ruled out when a request is refused for egress or sandbox reasons. Use `upload_asset_from_url` when the file is hosted. `begin_upload` needs no outbound request either, but its chunks are base64 you would have to emit yourself and that corrupts far below one chunk (sc-59914) — a scripted-caller path and not your fallback. If you write the tool arguments yourself and the network is refused, go to `upload_asset_from_computer`; the user can instead allow the domain in their sandbox's network egress settings and retry, if they would rather not re-pick the file. Sweet spot: local files up to ~1GB, when your client can do one HTTP PUT to an opaque URL. Beyond ~1GB or on flaky networks, prefer `begin_upload` (chunked, no HTTP needed) from a script, or `upload_asset_from_computer`. Returns `{uploadUrl, assetId, blobName, readUri, contentType}` — or, if a prior `assetId` you passed turns out to already have its bytes landed, `{assetId, blobName, alreadyUploaded:true, readUri}` with no `uploadUrl` (skip straight to registering). Two-step flow: (1) PUT the entire body to `uploadUrl` in one request; (2) call `register_asset_from_blob({assetId})` (or `{blobName, fileName, contentType, teamId}` for an older client) to attach it as a team asset. URL is single-use and expires — pass this call's `assetId` back in on a retry instead of starting a new pending upload. Refused before minting when the team's storage is full.
create_upload_url
Return the download URL for a Kapwing project's latest completed export. Read-only, URL-first framing. Pass `projectId` for a specific project, or omit it (passing `teamId` instead) to get the caller's most recent export across projects the caller created (creator-scoped, not team-wide — will not surface a coworker's export). If the project has no export yet, nothing has exported it — creating a project does not. To export a project, use the project export tool, which renders an existing `projectId` as it stands; if no export tool is in your list, export from Studio via its `editorUrl`. `get_export_history` lists historical exports. For a status-first framing that also detects in-flight exports, use `poll_export`. Hand the user the `editorUrl` this returns, verbatim. Never build a project link yourself: the path is `/{projectId}/studio/editor`, not `/projects/{projectId}` and not `/videos/{projectId}`. `/videos/{projectId}` is the finished-video page, which shows the project's last export rather than the project, so subtitles and dubs are missing from it.
download_export
Dub a project's audio into one or more languages, end to end, and leave the result on the project's timeline. This is the dubbing tool to reach for: it runs the whole pipeline (transcribe, translate, clone the speakers' voices, synthesize speech, split the original vocals out, lay the new audio onto the timeline) and the finished dub is playable in the editor. Returns one `workflowId` per source asset plus `projectIdByLanguage`; poll with `poll_dubbing({workflowIds, projectId})` until `done:true`. For a single target language the dub replaces the audio on the project you passed. For several, the backend copies the project once per language and `projectIdByLanguage` names each copy — the project you passed is left alone. The `start_dubbing_voice_cloning` / `start_dubbing_tts` tools are the individual stages of this same pipeline, exposed for callers that need to drive one step by hand; they do NOT attach anything to a project, so use them only when this tool does not fit. Dubbing is audio-only: mouth movement is not re-timed, so the result is not lip-synced. Only clone or reproduce voices the user owns or has permission to use.
start_dubbing
EXPORT an existing Kapwing project to MP4 and return a job to poll. Use this when the user wants a finished video file from a project that already exists — "export this project", "render it", "give me the MP4". Takes the `projectId` of a project you already have; it exports that project as it currently stands — including edits made in the browser and any captions added with the subtitle tools, with their styling and animation — and does NOT create a new one. Returns `{projectId, editorUrl, jobId, hint}`; the export runs asynchronously, so poll `poll_export({projectId})` until `ready === true` and then take the `url`. This spends real time and the account's export quota, so never call it speculatively, and if a project is already exporting, poll it rather than exporting it again — a second call queues a second export and bills for both. Settings are fixed: MP4, source resolution, fast encode — there is nothing to configure. A project longer than the plan's per-export cap (4 minutes on Free, 2 hours on paid plans) is refused before anything is queued, with the cap and remedy in the error; so is a Free-plan export that would take the workspace past its 30 exported minutes for the month. A project with AI persona (lip-synced avatar) layers is refused, because its lip sync spends credits the user confirms in the editor: send them to `editorUrl` for that one. It is also not enabled on every account: if it is absent from your tool list, open `editorUrl` and export from the browser rather than substituting another tool.
export_project
Create a Kapwing project from a single asset and EXPORT it to MP4 with default export settings. Use this when the user wants a finished video file — "export this", "render it", "give me the MP4". Returns `{projectId, editorUrl, jobId, hint}`; the export runs asynchronously, so poll `poll_export({projectId})` until `ready === true` and then take the `url`. Unlike `create_project_from_asset`, which only creates a project and exports nothing, this runs a real export, so it takes real time and consumes the account's export quota. Never call it speculatively. It is also not enabled on every account: if it is absent from your tool list, say so rather than substituting `create_project_from_asset`, which creates a project without exporting anything and is not the same result. Settings are fixed: MP4, source resolution, fast encode — there is nothing to configure. A source longer than the plan's per-export cap (4 minutes on Free, 2 hours on paid plans) is refused before anything is queued, with the cap and remedy in the error; so is a Free-plan export that would take the workspace past its 30 exported minutes for the month.
export_project_from_asset
Register a GCS blob (previously uploaded via `create_upload_url` or a completed `upload_chunk` chain) as a Kapwing team asset. Final step for the self-upload paths. Upload paths at a glance (pick the smallest fit): Hosted URL, ≤500MB → upload_asset_from_url (1 MCP call; server-side fetch) Local, up to ~1GB → create_upload_url → single HTTP PUT → register_asset_from_blob Local, up to 5GB, no HTTP → begin_upload → N × upload_chunk (isFinal) → register_asset_from_blob Local, caller can't read it → upload_asset_from_computer (browser panel; user picks file; up to 5GB) Egress: only `create_upload_url` (PUT to `storage.googleapis.com`) makes an outbound request of your own, so it is the only path ruled out when a request is refused for egress or sandbox reasons. Use `upload_asset_from_url` when the file is hosted. `begin_upload` needs no outbound request either, but its chunks are base64 you would have to emit yourself and that corrupts far below one chunk (sc-59914) — a scripted-caller path and not your fallback. If you write the tool arguments yourself and the network is refused, go to `upload_asset_from_computer`; the user can instead allow the domain in their sandbox's network egress settings and retry, if they would rather not re-pick the file. Returns `{assetId, teamAssetId, status, ...}` — same shape as `upload_asset_from_url`. On this path the blob is already in GCS so the returned status is typically `uploaded` (settled) on the first call. If it isn't, poll with `poll_asset({assetId})` until `ready:true`. Prefer `{assetId}` — the id a mint tool returned. `{blobName}` alone also still works, for compatibility with an older mint result. A rejection that cannot be retried (e.g. the file was too large for the team's plan) is a structured MCP error containing `{assetId, permanentlyFailed:true, error}` — do not retry with this assetId; start a new upload instead.
register_asset_from_blob
Advanced / single-stage. Prefer `start_dubbing`, which runs this stage inside the full pipeline and leaves a playable dub on the project timeline. Start a text-to-speech pass over translated word chunks to generate a dub. Returns the AI job — poll `poll_dubbing_tts({jobId})` until `status:'complete'`, then fetch the generated audio via `list_dubbing_tts_cache({ttsCacheIds})` using the ids on the completed job. Consumes team credits per character spoken. The dub is delivered as standalone audio assets: nothing is added to the project, and `projectId` / `editorUrl` here name the project the dub was generated FROM, not a dubbed version of it. Opening that project shows the original, unchanged. Tell the user the dub is an audio file to download, and do not describe the project as dubbed. Only clone or reproduce voices the user owns or has permission to use.
start_dubbing_tts
Get the calling user's Kapwing account overview: their workspaces/teams with plan tier, member count, and the same-email-domain subset of members (so the caller can see their coworkers), plus the caller's own email. Each workspace also reports its plan state — credits and other allowances as used/limit/REMAINING, which allowances are depleted, storage used against the plan's cap, and the plan's export duration, watermark, and per-file upload limits. Call this to answer "how many credits do I have left?" and to check headroom BEFORE starting a transcription, dubbing, translation, or export, since those actions are not blocked with a legible reason when an allowance runs out. Read `notes` before reporting any of these numbers — it says which are enforced and which are plan policy only. Read-only. Members outside the caller's email domain are excluded — a personal-email member of a company workspace is not surfaced.
get_account
Look up a dubbing voice-clone record by its provider `voiceId`. Reverse of `list_dubbing_voice_clones` (which is by source asset). Returns `found:false` when the voiceId isn't tracked as a Kapwing dubbing clone — a stock provider voice would return `found:false`.
get_dubbing_voice_clone_by_voice_id
Get preview details for a single Kapwing export — status, format, resolution, output URL, plus the owning team and whether the caller is a member. Read-only. Pass an `exportId` from get_export_history.
get_export_preview
Per-project (not team-scoped): page through the export history for one Kapwing project — each export's status, format, resolution, timestamps and output URL. Read-only, cursor-paginated. Required arg is `projectId`, not `teamId`. Hand the user the `editorUrl` this returns, verbatim. Never build a project link yourself: the path is `/{projectId}/studio/editor`, not `/projects/{projectId}` and not `/videos/{projectId}`. `/videos/{projectId}` is the finished-video page, which shows the project's last export rather than the project, so subtitles and dubs are missing from it.
get_export_history
Fetch the glossary terms that apply to one specific (source → target) language pair for a team, as a flat map of source text → target text. This is the exact map `start_translation` merges into the translation request. Empty map means no overrides for this pair.
get_glossary_terms_for_pair
Read a project's existing subtitles. Returns every asset on its timeline, which transcript each one's subtitles are reading from (`attachedTranscript`), every other transcript the asset already has, and the timed lines themselves. Read-only. This is how you translate or re-caption a project someone else built — the `lines` come back in exactly the shape the translation tools take, `linesLanguageCode` is the language they are written in, and the `assetTranscriptionId` it reports is the one `get_asset_transcription` wants, so neither needs a transcription job of your own. `linesSource` says what the lines are: `frames` is what the viewer sees now, `uploaded` is an SRT or an earlier translation, `transcript` means Studio has never cached lines for this project and these were built from the transcript the same way Studio would. An asset with `attachedTranscript: null` has no subtitles turned on yet; `attachedTranscript.status: "missing"` alongside a `translationId` means the lines came from a translation job rather than a transcript. Hand the user the `editorUrl` this returns, verbatim. Never build a project link yourself: the path is `/{projectId}/studio/editor`, not `/projects/{projectId}` and not `/videos/{projectId}`. `/videos/{projectId}` is the finished-video page, which shows the project's last export rather than the project, so subtitles and dubs are missing from it.
get_project_subtitles
Fetch a completed translation. Returns the translated subtitle lines aligned to the source timings, plus provider metadata. Provide `translationId` (preferred) OR `transcriptionId` (looks up the translation attached to that transcription). Passing neither is rejected client-side.
get_translation
Report a Kapwing team's media-library storage: bytes used against the plan's storage cap and the room left, plus the media library's all-origins total. Read-only. Pass a `teamId` from the get_account tool. Two different byte counts come back — compare `usedAgainstLimitBytes` with `storageLimitBytes`, and never subtract `totalSizeBytes` (a wider set) from the cap. See `note`.
get_team_storage_usage
Fetch a completed transcription's words. Returns the full word list with per-word timestamps and speaker labels when available. Use the `assetTranscriptionId` returned by `poll_transcription` once `done:true` — not the transcription-job id. Word objects use snake_case `start_time` / `end_time`, matching the backend transcription shape so downstream per-word/per-chunk tooling can consume them without remapping. English transcripts include filler words (`um`, `uh`) unless `start_transcription` was called with `disfluencies:false`; the Studio strips them from subtitles at render time.
get_asset_transcription
List the team's saved brand-kit voice clones — team-level presets a caller can plug into `start_dubbing_tts` chunks via `elevenLabsId`. Distinct from `list_dubbing_voice_clones`, which is scoped to one source asset's speaker-derived clones. Response includes a signed `sampleURL` for playing back the training sample (may be omitted if no sample was retained).
list_brandkit_voice_clones
List the trained voice clones attached to one source asset. Each entry pairs a speaker label with the provider `voiceId` you feed into `start_dubbing_tts` chunks. If the same speaker has multiple entries, prefer the most recent (higher `lastUsed`).
list_dubbing_voice_clones
List the folders in a Kapwing workspace/team (folder id, name, type, parent). Read-only. Pass a `teamId` from `get_account`. Use `parentFolderId` (or `"root"`) to walk one level at a time; use `limit` to cap the response. Unfiltered team trees can be hundreds of folders.
list_folders
Fetch the cached TTS records for a set of ids. Each record carries a signed `outputAssetUrl` to play or download the generated audio (it expires; call again for a fresh one), the audio's `outputAssetId`, and `outputTranscriptionId` (transcription of the generated audio, useful for timing checks). The URL here is the way to reach the audio: `outputAssetId` is minted outside team storage, so `poll_asset` and the project tools refuse it. Batched: pass all ids from `poll_dubbing_tts`'s completed response in one call. Order of returned items is not guaranteed to match input order — join on `ttsCacheId`. Pass the `teamId` the dub ran under.
list_dubbing_tts_cache
List all glossary terms saved for one team. Glossary terms are source→target text overrides the translation pipeline uses to force specific translations (e.g. brand names, proper nouns). Returned as an array; group by (sourceLanguageCode, targetLanguageCode) client-side to filter for a specific language pair. For a single language pair, use `get_glossary_terms_for_pair` instead.
list_glossary_terms
Page through a Kapwing workspace's media library — the team's uploads and AI generations (filename, type, dimensions, duration, size, AI-generated flag). Read-only, cursor-paginated: pass the returned `nextCursor` to walk all items. Pass a `teamId` from `get_account`; every `assetId` returned is one the team-scoped tools accept for that same team, so carry the `teamId` straight through to your next call (unless the envelope carries `assetIdsUnverified`, which means that check could not run — see its note). `search` is a tokenized full-text match, not a substring filter — see its arg description before relying on it to narrow results. Brand kit assets are not listed here, so an id for one has to come from elsewhere. Rate limited to 60 calls/minute per authenticated caller (a transport with no caller identity, the same one that sets `assetIdsUnverified`, has nothing to bucket against and is not limited): pass `pageSize: 100` when walking a whole library, since the server default of 25 makes a large library run out of budget before it runs out of pages.
list_media_library
List all pronunciation overrides for a team. Each entry pairs a `sourceTerm` (the raw word) with a `pronunciation` (either an IPA string or a plain phonetic respelling — the `format` field says which). The TTS pipeline for dubbing consults this list per team before speaking, so a brand name written unusually can be forced to sound right without editing the source transcript.
list_pronunciations
List the calling user's most recent Kapwing projects (name, duration, last editor, last-saved, thumbnail, share code) and their most recent Kai chats. Read-only. Default scope is `personal` (only projects the caller created). Pass `scope: "team"` to fan out to the whole team surface — that view includes coworkers' projects and thumbnails, so use it only when the caller explicitly wants the team view. Pass a `teamId` from the get_account tool. When you show these to a user, include each project's `lastSaved` date: "recent" here means recent for the workspace, not recent in time, and the list routinely reaches back months. Without dates, an old project by a since-departed teammate reads as current activity — a real report from release review, 2026-08-06. Hand the user the `editorUrl` this returns, verbatim. Never build a project link yourself: the path is `/{projectId}/studio/editor`, not `/projects/{projectId}` and not `/videos/{projectId}`. `/videos/{projectId}` is the finished-video page, which shows the project's last export rather than the project, so subtitles and dubs are missing from it.
list_recent_projects
Persist a speaker→voiceId mapping for one source asset. Writes one `dubbing_voice_clones` row per entry, all with `provider:'elevenlabs'`. Not idempotent — repeat calls with the same map insert duplicates (the read side prefers the most recent). Empty map is a no-op. Response carries no body; success = no exception.
save_dubbing_voice_clones
Start a transcription job for one asset. The spoken language may be given as `languageCode` or left for the pipeline to detect. Returns a `transcriptionId` immediately — the actual transcription runs in the background. Poll with `poll_transcription({transcriptionId})` until `done:true`, then fetch the words with `get_asset_transcription({assetTranscriptionId})`. If `translateLanguageCode` is set, `sourceTranscriptionId` is also returned for the untranslated source transcription. Consumes transcription credits from the caller's team.
start_transcription
Translate a batch of timed subtitle lines. Returns a `translationId` immediately — the job runs in the background. Poll `poll_translation({translationId})` until `done:true`, then fetch the aligned translation with `get_translation({translationId})`. The job is not attached to any project. To show its lines as captions, pass the finished `translationId` to the captioning tool. For source→target on plain text without timings, use `start_translate_text` instead. Consumes translation credits from the caller's team; the team's glossary (if any) is applied automatically.
start_translation
Translate plain-text chunks (no subtitle-frame identifiers) into a target language via the AI-jobs pipeline. Returns a `translateTextJobId` immediately — poll with `poll_translate_text({translateTextJobId})` until `status:'complete'`. For timed subtitle lines with frame ids, use `start_translation` instead (that path polls via `poll_translation`). Consumes translation credits.
start_translate_text
Push one chunk of a session started by `begin_upload`. Upload paths at a glance (pick the smallest fit): Hosted URL, ≤500MB → upload_asset_from_url (1 MCP call; server-side fetch) Local, up to ~1GB → create_upload_url → single HTTP PUT → register_asset_from_blob Local, up to 5GB, no HTTP → begin_upload → N × upload_chunk (isFinal) → register_asset_from_blob Local, caller can't read it → upload_asset_from_computer (browser panel; user picks file; up to 5GB) Egress: only `create_upload_url` (PUT to `storage.googleapis.com`) makes an outbound request of your own, so it is the only path ruled out when a request is refused for egress or sandbox reasons. Use `upload_asset_from_url` when the file is hosted. `begin_upload` needs no outbound request either, but its chunks are base64 you would have to emit yourself and that corrupts far below one chunk (sc-59914) — a scripted-caller path and not your fallback. If you write the tool arguments yourself and the network is refused, go to `upload_asset_from_computer`; the user can instead allow the domain in their sandbox's network egress settings and retry, if they would rather not re-pick the file. Set `isFinal:true` on the last chunk. The sidecar streams your chunk into GCS with proper `Content-Range` and lets GCS enforce contiguity — you don't touch GCS. Returns `{ok, nextOffsetBytes, assetId, blobName, committedBytes, finalized}`. `committedBytes` is what GCS reports it actually persisted, which can fall SHORT of what you sent — always start the next chunk at the returned `nextOffsetBytes` rather than at your own running total, and when a `hint` names a short commit, resend from there instead of advancing. On `isFinal:true` success, call `register_asset_from_blob({assetId})` (or `{blobName, fileName, contentType, teamId}` for an older session) to attach it.
upload_chunk
Open an interactive upload panel so the user can pick media off their own computer and upload it into a Kapwing team library. Reach for a byte path first when you can read the file AND you know your outbound HTTP is unrestricted. Come here when you cannot read the bytes at all, and when the network is refused and you are the one writing the arguments. In a sandbox or behind an egress allowlist or agent proxy, come straight here instead of spending a call to find out — `create_upload_url` PUTs to `storage.googleapis.com`. Being able to read an attached file is not evidence of egress: in some clients the bytes are readable and the network is not. Upload paths at a glance (pick the smallest fit): Hosted URL, ≤500MB → upload_asset_from_url (1 MCP call; server-side fetch) Local, up to ~1GB → create_upload_url → single HTTP PUT → register_asset_from_blob Local, up to 5GB, no HTTP → begin_upload → N × upload_chunk (isFinal) → register_asset_from_blob Local, caller can't read it → upload_asset_from_computer (browser panel; user picks file; up to 5GB) Egress: only `create_upload_url` (PUT to `storage.googleapis.com`) makes an outbound request of your own, so it is the only path ruled out when a request is refused for egress or sandbox reasons. Use `upload_asset_from_url` when the file is hosted. `begin_upload` needs no outbound request either, but its chunks are base64 you would have to emit yourself and that corrupts far below one chunk (sc-59914) — a scripted-caller path and not your fallback. If you write the tool arguments yourself and the network is refused, go to `upload_asset_from_computer`; the user can instead allow the domain in their sandbox's network egress settings and retry, if they would rather not re-pick the file. Use this when the user points at a file only THEY can reach ("these photos", "the video on my desktop") and you cannot read its bytes — it is the ONLY upload path that works in that case. The user's browser uploads directly to storage, so file size is bounded by their connection rather than by anything on your side, and no base64 passes through the conversation. Returns team scope for the panel; the panel reports each finished upload's assetId back into the conversation, along with a link to the media library, so you can hand the user the asset or feed it to whichever project tool you have. Do not ask the user to hand over a file you have already uploaded successfully — being asked to re-pick clips they had just attached is a real report from release review, 2026-08-06, and it reads as the tool being broken. Uploads land in ONE workspace and the user should know which. Pass `teamId` when you already know the target; omit it and a single-workspace user resolves automatically. If they have several and you did not pass one, this call comes back with the list — ask the user which workspace, then call again with their answer. The result then carries `teamName`: say it back to the user, since the panel is the last chance to catch a wrong destination before their files are in it. The exception is `workspaceVerified:false`, which means the workspace lookup was unreachable and the id went unchecked — there is no name to give in that case, so say the destination could not be confirmed instead of naming one. A workspace whose storage is full is refused here, before the panel opens. Requires a host supporting the MCP Apps extension (Claude Desktop, claude.ai). On hosts without it, fall back to `upload_asset_from_url` for hosted media, or `create_upload_url` if you can make an outbound HTTP PUT.
upload_asset_from_computer
Import media into the caller's Kapwing team library from a URL. Upload paths at a glance (pick the smallest fit): Hosted URL, ≤500MB → upload_asset_from_url (1 MCP call; server-side fetch) Local, up to ~1GB → create_upload_url → single HTTP PUT → register_asset_from_blob Local, up to 5GB, no HTTP → begin_upload → N × upload_chunk (isFinal) → register_asset_from_blob Local, caller can't read it → upload_asset_from_computer (browser panel; user picks file; up to 5GB) Egress: only `create_upload_url` (PUT to `storage.googleapis.com`) makes an outbound request of your own, so it is the only path ruled out when a request is refused for egress or sandbox reasons. Use `upload_asset_from_url` when the file is hosted. `begin_upload` needs no outbound request either, but its chunks are base64 you would have to emit yourself and that corrupts far below one chunk (sc-59914) — a scripted-caller path and not your fallback. If you write the tool arguments yourself and the network is refused, go to `upload_asset_from_computer`; the user can instead allow the domain in their sandbox's network egress settings and retry, if they would rather not re-pick the file. Server downloads the bytes; returns an asset id immediately — the background download continues out of process, so the asset may still be `pending`. Poll `poll_asset({assetId})` until `ready:true` before assuming the URL resolves. Use for direct media URLs or signed URLs from an external DAM. Social/video platform pages (YouTube, TikTok, Instagram, X, Vimeo, Facebook) and Google Drive share links are not supported and are rejected. Refused before the fetch starts when the team's storage is full or the probed size would not fit.
upload_asset_from_url
Kapwing ChatGPT Plugin FAQ
How the directory, categories and Discoverability Score work.
Read the methodologyHow do I improve Kapwing's ChatGPT Plugin discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Kapwing alternatives on ChatGPT?
As of 2026-10-16, Kapwing competes with Descript, AI Producer by OpusClip, BlitzReels, Butter, DevMotion, Klap, Montage, NewsTune Studio and 8 more in ChatGPT Video & Podcast Editing, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.