---
title: MCP tool reference
description: Current Jellypod MCP tools and core behavior.
---

Connect to `https://mcp.jellypod.com/mcp`. Call `tools/list` for the current
input and output schemas.

## Tools

| Tool | Purpose |
| --- | --- |
| `list_content` | Browse podcasts, episodes, videos, shorts, and voiceovers together. |
| `get_content` | Get one content item, its progress, outputs, and Studio link by ID. |
| `list_characters` | Find a saved character and its voice details. |
| `list_voices` | Find a built-in voice. |
| `list_video_styles` | Find a built-in video style and preview it. |
| `generate_episode` | Create a podcast episode from a prompt or script. |
| `export_episode` | Produce audio, video, or both from an existing episode without regenerating narration or publishing. |
| `export_video` | Render an existing video, short, or voiceover again, for example after a caption or watermark change, without regenerating narration. |
| `generate_video` | Create a video from a prompt, research sources, or finished script. |
| `generate_short` | Alias of `generate_video` that defaults to a 30-second short. |
| `save_podcast` | Create or update a podcast. |
| `save_character` | Create or update a character. |
| `update_content` | Update descriptive metadata, captions, or watermark position for an episode, video, short, or voiceover. |
| `set_episode_publication` | Publish, schedule, reschedule, or unpublish an episode. |
| `delete_content` | Permanently delete a podcast, episode, video, short, or voiceover. |
| `list_automations` | Browse automations with their prompt, schedule, state, and output settings. |
| `get_automation` | Get one automation by ID. |
| `save_automation` | Create or update an automation, including enabling or pausing it. |
| `delete_automation` | Delete an automation on an explicit request. |
| `submit_feedback` | Report an MCP error or confusing workflow. |

## Read content

Content kinds are `podcast`, `episode`, `video`, `short`, and `voiceover`.

`list_content` returns all content kinds by default, newest first. It can filter
by kind, title, generation state, episode publication state, or parent podcast.
Pass `nextCursor` as `cursor` for the next page.

`list_characters` returns each character's profile and voice details.
`list_voices` returns built-in voice IDs. Filter by `gender`, `language`,
`voice_type`, or an exact `accent`, or pass a plain-text `query` such as
`irish male storyteller`: a voice matches when any word appears in its
description, accent, or style tags, and `male` or `female` filters by gender.
Results are not ranked by how many words match. `list_video_styles` returns built-in style IDs,
descriptions, and preview URLs.

`get_content` accepts an ID and resolves the content kind. It returns progress,
the Studio URL, and the state of share, playback, stream, download, transcript,
and caption outputs. `outputs.audio_stream` and `outputs.video_stream` are
direct URLs for playback, separate from the `audio_download` and
`video_download` links. Pass `include_transcript: true` to read a rendered
episode's transcript: `outputs.transcript` then carries the speaker-attributed
`text` inline, capped at 100,000 characters at a speaker turn, with `truncated`
and `total_characters` showing whether it was cut. Without it, an episode's
transcript reads `not_requested`. During a regeneration the previous render's
transcript stays available; an episode with no transcript yet reads `preparing`
while it generates or renders, and `unavailable` once settled. Every other
content kind reads `unavailable`. When
`progress.poll_after_seconds` is greater than zero, wait that long and poll
again. `progress.needs_attention` counts the gaps a usable episode or video
still has (`unvoiced_lines`, `missing_visuals`, `skipped_sources`), and is
`null` when nothing is missing. A failed output request can still have a usable
file of another format. Reading
content never starts generation or rendering.

A client that supports MCP Apps renders `get_content` results in a native
audio or video player, using `audio_stream` for episodes and `video_stream`
for videos, shorts, and voiceovers by default, with a control to switch when
both are available. A client without MCP Apps support should offer the
available stream as a Listen or Watch link instead.

For an episode, a render started after generation completes can still delay
its output. `get_content` keeps `progress.status` at `generating` until that
render attaches or fails, then reports `failed` with an explanation if it
fails; an older published output stays available in `outputs` throughout.

## Create and update

`save_podcast` and `save_character` create without `id` and update with `id`.
Creating a podcast requires `title` and `character_ids`, since a podcast cannot
exist without a cast; find character IDs with `list_characters`.
`save_podcast` also sets `author`, `primary_category`, and an optional
`secondary_category` (Apple Podcasts category or subcategory names, which the
RSS feed nests under their parent category). A podcast created without a
category gets one chosen from its title and description. Character
Voice changes and archiving require Studio. `update_content` resolves
an episode, video, short, or voiceover from its ID and changes descriptive
metadata, caption visibility and style (`captions_enabled`, `caption_style_id`),
and the watermark corner (`watermark`). Caption and watermark values override
the podcast default for an episode and the organization default for a video;
`null` returns a field to its default. Production edits such as scripts,
narration, cast, sources, visuals, timeline, and new watermark images require
Studio.

`generate_episode`, `generate_video`, and `generate_short` accept either
`prompt` or `script`. Script speaker labels match saved Characters, or use
`speaker_characters: [{"label": "Narrator", "character_id": "..."}]` to assign
active Characters from `list_characters`. Create missing Characters with
`save_character` first. Script mode does not accept prompt cast fields or sources. Video and short generation require `style_id` in
both modes. A video or short script's speakers can resolve to at most four
distinct Characters; give extra speakers a Character already in the script.

For episodes, videos and shorts, `prompt` always writes a new script from the supplied material.
Use `script` to preserve finished narration, with `speaker_characters` when its
labels differ from saved Character names.

`generate_episode` accepts `outputs: ["audio"]`, `["video"]`, both, or `[]`
for editable content without exported files. Audio-only requests skip video
work. Omission preserves the existing automatic export behavior. With explicit
`outputs`, `auto_publish: true` requires audio in the selection.

For episodes, `get_content` also returns `files.audio` and `files.video`.
Each has `status` (`not_requested`, `preparing`, `available`, or `failed`),
`download_url`, `current`, and `error`. Requested files become available
independently. `progress.status` becomes `completed` when all requested work
finishes. Existing `outputs` playback, download, and transcript fields remain
available. For published and scheduled episodes, existing media links keep
serving the published version; `files` exposes newer draft exports separately.

Call `export_episode` with the saved episode ID and `outputs` to produce or
refresh audio, video, or both. It reuses current files when possible and never
regenerates narration or publishes. A failed replacement preserves the previous
successful download; `current` reports whether that file reflects current
content. Retry failed output work with a new idempotency key. Signed storage
links last 24 hours; read the episode again to refresh them.

Video and short generation continue to produce video automatically. A caption
or watermark change through `update_content` clears the current render: its
result names the outputs that are now unavailable, and `get_content` reports
`progress.render_required` until you call `export_video` (or `export_episode`
for an episode). `export_video` reuses a current render when one exists and
spends no credits.

Episode generation remains a draft unless `auto_publish` is true. Set it only
when the creator explicitly asks to publish after a successful render.

Every generation tool returns `id`, `kind`, `studio_url`, and `progress`.
`generate_episode` also returns `publication_state`, always `draft` at
creation. Video and short results also return the settings Jellypod applied.

`generate_episode`'s `studio_url` is the draft editing workspace. `get_content`
returns the stable `/episodes/<id>` address for the same episode.

Episodes, videos, and shorts accept public webpage or YouTube URLs and plain
text held by the client. MCP does not accept file uploads or saved source IDs.
When a creator provides a file, the client can extract its text and pass that
text inline. File-backed sources and voiceover creation remain in Studio.

Generation and metadata write tools accept an optional `idempotency_key`.
Without one, each call starts a new operation. Save a key before the call when
a resend must not run twice, reuse it with the same input after a lost response,
and use a new key for a different request once work has started. A rejection
before work starts can release its claim; follow `recovery.idempotency_key`
to reuse that key with corrected input.

## Automations

`list_automations` returns every automation, newest first, with its name,
prompt, `enabled` state, `paused_reason`, `trigger_type`, schedule or
`inbound_address`, `output_type` (`episode`, `video`, or `short`), output
settings, and linked `podcast_id` or `character_id`. Automations with the same
prompt are all returned. Filter by `podcast_id` and follow `nextCursor`.

`save_automation` creates without `id` and updates with `id`. An update
changes only the fields supplied; `schedule`, `episode_settings`, and
`video_settings` merge key by key. `trigger_type` and `output_type` cannot
change after creation. Setting `enabled` to `false` pauses an automation. An
automation paused because Credits ran out returns
`code: "credit_recovery_required"` with a Studio link instead of resuming. If
other fields saved but pausing or resuming failed, the error says so and the
same request can be retried.
`delete_automation` stops future runs; a run in progress still finishes.

## Publish

`set_episode_publication` accepts `mode: "publish"`, `"schedule"`, or
`"unpublish"`. Scheduling also requires `scheduled_time`; scheduling an
already scheduled episode reschedules it. Publishing an episode does not make
a private podcast public.

A publish or schedule receipt also carries `episode_url` and `rss_feed_url`,
the public episode page and the parent podcast's RSS feed. Both are `null`
while the podcast is private. Neither field is present after `unpublish`.

`set_episode_publication` refuses while the episode's newest render is still
producing or attaching its output, and names `get_content` as the way to wait
for it. A newest render that fails does not block publishing an already
attached, working output.

## Delete

`delete_content` permanently deletes a podcast, episode, video, short, or
voiceover by ID and cannot be undone. Deleting a published episode removes it
from the podcast feed, and deleting a podcast deletes all of its episodes.
Agents call it only when the creator explicitly asks to delete a named item.
The receipt carries `id`, `kind`, and `operation: "delete"`, plus the
episode's prior `publication_state` or the podcast's deleted `episode_count`.
An ID that is unknown or already deleted returns `not_found`.

## Results and errors

Every tool returns structured or text output.

Jellypod domain and cross-field errors contain `code`, `message`,
`retry_with_same_input`, `recovery` (next action and any key policy), and, when useful, `field`, `studio_url`, or
`speakers`. A script naming a speaker with no matching character returns
`code: "unresolved_speakers"` and the unmatched labels in `speakers`. A video
or short script past the four-Character ceiling returns `code: "host_ceiling"`.
Invalid
tool arguments return the standard MCP `InvalidParams` error.

See the [agent guide](/api/agents) for complete request sequences.
