Skill instructions
content-discovery4.33 KB
View saved version →
---
name: content-discovery
description: Use when the user wants to search, find, list, browse, or retrieve their Riverside content — productions, studios, projects, recordings, edits, exports, transcripts — by what was said in it, by its title or topic, or by where it lives; when they ask for a download or share link; or when another workflow first needs a studioId, productionId, projectId, sessionId, or editId. Not for creating or changing an edit (see video-editing), and not for publishing to social platforms (see social-publishing).
---
# Content discovery
Read-only search and navigation over the Riverside platform. Hierarchy tools
carry a `platform_` prefix and search tools carry a `search_` prefix; nothing on
this surface modifies content. Copy tool names verbatim.
**The live tool schemas are the authority.** Required and nullable fields, date
windows, limits, defaults, page sizes, and pagination tokens all come from the
schema of the tool you are about to call — never from memory, from an earlier
session, or from a number written in a skill file. Read the schema, then call.
## The entity bridge
A production contains studios. A studio contains projects. A project contains
both recordings and edits. An edit produces exports.
Which id crosses into another skill:
- **`studioId`** — social publishing needs one, and so do the brand and captions
editing tools. No editing or social tool can discover a studio, so it has to
come from here. A studio also carries its `productionId`.
- **`sessionId`** — the recording-session identifier used by transcript reads
and edit creation. Reuse a recording's `id` only when the live response or
schema says that item is the same session (for example, some upload or
single-take records). For multi-take material, confirm the intended take or
start from an existing project edit instead of assuming the ids coincide.
- **`editId`** — one cut of one or more recordings. Social publishing consumes
it as the `clipId`.
- **`exportId`** — one rendered file. No tool returns its download link; send
the user to the edit's `riversideUrl` instead.
## Where to read next
| Need | Read |
|---|---|
| Find content by exact words, topic, or title | [Search](references/search.md) |
| Browse hierarchy, determine latest, page completely, or get a rendered file | [Hierarchy navigation](references/hierarchy-navigation.md) |
| Resolve or hand off IDs for editing or social publishing | [Cross-skill handoffs](references/cross-skill-handoffs.md) |
**Routing contract:** Before the first Riverside workflow call, evaluate every
row against the observable request and state. Read every matching reference and
no unrelated reference. After each Riverside response, evaluate every row
again before the next workflow call; read any newly matching reference first.
Only this table routes references — a reference never routes to another one.
## Rules that hold in every flow
- **Ask, don't guess.** When more than one studio, project, recording, or edit
fits what the user described, show the candidates and let them pick. Guessing
produces a confident answer about the wrong content.
- **Keep broad requests broad.** Scoping parameters such as `projectId` on
`platform_list_recordings` and `platform_list_edits` are optional. Omit them
for "all my recordings"-style requests, and never carry a narrow scope
captured in an earlier step into a request the user did not scope that way.
- **Links come from the platform.** Studios, projects, recordings, and edits
each carry a `riversideUrl`. Return the one the server gave you; never
construct or guess a URL, and never build one from an export's `s3Key`.
- **Preview links are opt-in.** `platform_get_recording` withholds the
token-bearing `previewUrl` unless asked. Set `includePreviewUrl` only once the
user has explicitly asked for a shareable preview, and read a null value as
"no share link exists right now".
- **Verify readiness before sharing.** Recordings and exports carry a `status`.
Confirm the content is ready before sharing or operating on it — a record
existing does not mean its file is finished.
- **Export-ready is not publish-ready.** A ready export means the render
finished. It is not the clip state `social_upload_create`
checks, and no tool here exposes that state — so never offer a ready export as
evidence that something can be published.
Referenced files: 4
podcast-hosting5.22 KB
View saved version →
---
name: podcast-hosting
description: Use when the user wants to browse or manage a Riverside hosted podcast, create or update an episode, change podcast artwork, distribute a show, or read podcast download analytics. For video edits use video-editing; for clips posted to social accounts use social-publishing.
---
# Podcast hosting
Manage hosted shows and episodes through the `hosting_` tools on the same
Riverside connection. Read the current tool schema before each call; schemas,
`hosting_get_hosting_config`, and `hosting_get_podcast_guidelines` govern valid
values and prerequisites. A missing tool is unavailable in this connection.
## Resolve the show and source
Use `hosting_get_user_context` to establish the connected account. Browse with
`hosting_list_podcasts` and `hosting_list_episodes`; inspect selected objects
with `hosting_get_podcast` and `hosting_get_episode`. Page according to the
current schemas. Ask the user to choose when several shows or episodes fit.
Podcast and episode IDs are UUIDs. Studio identifiers are not interchangeable:
`hosting_create_podcast` takes the studio **slug**, while
`hosting_list_podcasts` takes the studio **id**. Resolve both from
`platform_list_studios` or `platform_get_studio`; keep their field names.
Episode creation takes exactly one source:
- `sessionId`: the recording session ID. The hosting schema identifies the
`id` returned by `platform_list_recordings` or `platform_get_recording` as
this value; verify the intended recording.
- `idClip`: a verified Riverside clip ID. Do not substitute an edit ID from
`platform_list_edits`. If the clip ID is unknown, ask the user for the clip
ID displayed beneath the recording on the Riverside project page.
## Create and update
Before metadata writes, read `hosting_get_hosting_config` and
`hosting_get_podcast_guidelines`. Collect the fields required by the live
schema, including podcast categories and language. Podcast categories are
hosting metadata, independent of the plugin directory's Creativity category.
`hosting_create_podcast` creates a draft. If its optional artwork upload fails,
the show may already exist: preserve the returned podcast ID and retry only
`hosting_upload_cover_art` when requested. Do not create a second show.
Use `hosting_create_episode` for the chosen source and
`hosting_edit_podcast` or `hosting_edit_episode` for requested changes. Preserve
fields the user did not ask to change. For a publication date, resolve the
user's timezone and supply the schema's date and timezone fields; clarify an
ambiguous wall-clock time before writing.
Before publishing, scheduling, changing public metadata, replacing artwork,
or connecting a distribution platform, show the target show/episode and exact
changes and obtain confirmation. Confirmation of draft creation does not
authorize subsequent publication or distribution.
After a write, read the affected podcast or episode. Episode processing can
continue after creation; report the returned state and use bounded status
reads instead of recreating it. Before publishing a new episode, read
`hosting_get_episode` and wait until it is ready. Stop and report processing or
failed instead of sending a publish update. Do not force a processing episode
to ready. After an unknown mutation outcome, reconcile with list/get reads
before considering another write.
## Artwork and distribution
`hosting_upload_cover_art` replaces show artwork.
`hosting_upload_episode_artwork` replaces square episode art or a video
thumbnail; a linked YouTube thumbnail may change as well. Use the current
schema's size, format, and dimension rules. Image sources must be final public
HTTPS URLs; do not send private URLs or credentials, or rely on redirects.
Use `hosting_connect_platform` only for a requested, confirmed destination.
The current workflow requires a nonprivate show and a published episode.
Read live platform guidance: submitting a new show differs from supplying the
URL of an existing show. A YouTube connection requests uploading existing
episodes for the whole show; include that scope in the confirmation before
calling the tool. Its returned authorization URL requires the user to complete
OAuth. Do not treat an authorization URL as a completed connection.
Verify distribution with `hosting_get_platform_links`. An empty
connected-platform field on a podcast alone is not proof of disconnection.
Submission, connection, and a playable episode on the destination are
different outcomes; report only the returned evidence.
There are no exposed hosting operations for deleting a show or episode,
disconnecting a distribution platform, or managing subscribers. Do not invent
them or use a social-account operation as a substitute.
## Analytics
Use `hosting_get_podcast_analytics` or `hosting_get_episode_analytics` for the
requested show, episodes, period, and mode. Read the schema's window and
pagination requirements. Distinguish RSS downloads from YouTube views in the
returned metrics; do not infer unique listeners or subscribers from either.
`hosting_export_podcast_analytics_csv` returns inline CSV text, not a download
URL. Its date window is inclusive in UTC. Respect the live window and response
size bounds; narrow a window that exceeds them and describe the resulting
coverage. Export analytics only when requested.
Referenced files: 1
setup6.7 KB
View saved version →
---
name: setup
description: Use when installing or connecting Riverside on Claude Code, Cursor, ChatGPT, or Codex; when authentication, 401, auth-loop, tool-not-found, account, or plan issues prevent tools from working; or when a feature-disabled or precondition error might be mistaken for a connection failure. Do not use for normal content, editing, or publishing after the connection works.
---
# Setup and connection
This plugin wraps Riverside's remote MCP server at `https://mcp.riverside.com/mcp`.
The tools run against the user's own Riverside account over an authenticated
connection.
## Requirements
- **A Riverside account.** Sign up or sign in at https://riverside.com.
- **A qualifying paid plan.** The MCP is available only on qualifying Riverside
paid plans; Free and Pro accounts are not admitted, and their tool calls will
not authorize. Plan details are at https://riverside.com/pricing.
- A supported client with this plugin installed and enabled — Claude Code (CLI,
desktop, or IDE extension), Cursor, ChatGPT, or Codex.
Each client authenticates separately. Connecting Riverside in one client does not
connect it in another.
## First-time connection
How the connection is established depends on the host family. Every path ends in
the same place: a browser sign-in at Riverside, after which the tools work.
### Claude Code and Cursor — connect on the first tool call
The connection is set up once, on the **first tool call**:
1. Trigger any Riverside tool (e.g. ask to list your studios or productions).
2. The client opens Riverside's hosted sign-in in your browser. It finds that
page automatically by discovering the MCP endpoint, so there is no URL to
enter by hand. Clients register themselves via Dynamic Client Registration —
there is no client ID or secret to configure.
3. Sign in and approve access. The prompt asking whether to grant the client
access belongs to your client, not to Riverside.
4. The browser hands the authorization back to the client, the MCP server
connects, and the tool call proceeds.
### ChatGPT and Codex — connect before the first tool call
There is no first-tool-call prompt on these hosts. Use the connection lane the
host currently exposes.
Before connecting ChatGPT:
- The Riverside account must be on a qualifying paid plan; Riverside Free and
Pro accounts are not admitted.
- Write actions must be separately enabled for the ChatGPT workspace. Which
plans allow them is OpenAI's to define and changes, so check their
developer-mode docs. Admins may also need Developer Mode on and Riverside
approved.
- Use ChatGPT on the web. MCP apps are not available on mobile.
#### Before the directory listing is available
- **ChatGPT:** in the browser, enable Developer Mode under **Settings → Security
and login**. Open **Plugins**, select **+**, name the connection Riverside, use
`https://mcp.riverside.com/mcp`, choose OAuth, create it, and complete the
Riverside sign-in.
- **Codex:** run
`codex mcp add riverside --url https://mcp.riverside.com/mcp`, then
`codex mcp login riverside`. Run `/mcp` in a Codex session to confirm the tools
are listed.
Do not use an `npx` or `mcp-remote` bridge; both hosts support the remote HTTP
endpoint and OAuth directly.
#### After the directory listing is available
Two independent things have to be true:
1. **The plugin is installed and enabled.** This supplies the five Riverside
skills — the guidance the model follows.
2. **The Riverside app is enabled, connected, and signed in.** This supplies the
tools themselves. Find Riverside among the host's apps or connectors and
complete the sign-in from its settings.
In either lane, the plugin and Riverside connection are managed separately and
can fail separately:
| State | What the user sees |
|---|---|
| Plugin installed, connection signed in | Riverside skills load and the tools work |
| Plugin installed, connection missing | The skill still loads, but no Riverside tools exist |
| Plugin installed, connection present but signed out | Tools may be listed, but calling one fails as not-logged-in |
| Plugin removed, connection still present | The tools keep working; only the skill guidance is gone |
Removing the plugin is not a way to disconnect Riverside — remove the custom
connection or disconnect the listed app instead. Equally, if the tools are
missing, reinstalling the plugin will not fix the separate MCP connection.
After the first connection on any host, it is remembered — subsequent tool calls
run without re-prompting until the authorization expires or is revoked. A
connection currently lasts about a week, and there is no silent refresh, so
reconnecting through the browser periodically is expected rather than a fault.
## Troubleshooting
Reconnect only for authentication or connection failures. A feature-disabled or
precondition error is an operational result, not evidence that authentication
failed.
| Symptom | Likely cause | Fix |
|---|---|---|
| `401` / repeated auth loop / "unauthorized" | Authorization expired or was revoked | Reconnect Riverside from the host's connection settings or CLI and re-authenticate. Complete the browser sign-in fully. |
| No Riverside tools listed | Riverside is not connected | Check the separate Riverside connection and reconnect it; enabling the plugin alone provides no tools. |
| A tool is not listed — including reads working while every write is missing | Not exposed here, or writes are off for this ChatGPT workspace | Report it as unsupported; do not reconnect, the connection is fine. Use a listed alternative only if it fits the request. |
| Tools appear but every call fails to authorize | Account on a plan that is not admitted | The MCP requires a qualifying paid plan; Free and Pro accounts cannot use it. Plan details are at https://riverside.com/pricing. |
| Sign-in never returns / hangs | Browser/redirect interrupted | Close the tab, retry to restart the flow, and complete the browser step in one go. |
| A specific tool reports feature disabled or a missing prerequisite | Tool or workflow unavailable or incomplete (e.g. an edit with no transcript) | Surface the message; do not reconnect or retry blindly. Load the relevant operational skill only if the user asks to recover or continue. |
Tips:
- The connection control point differs by client: Claude Code uses `/mcp`;
Cursor uses **Settings → MCP** (or the Plugins panel); ChatGPT uses **Plugins**
for a custom connection or the Riverside app settings after listing; Codex
uses `codex mcp login riverside` and `/mcp`.
## Getting help
- Product, plans, and account: https://riverside.com
- Connection steps for each client:
https://support.riverside.com/hc/en-us/articles/37803607978141-Connect-to-Riverside-MCP
- Support: https://support.riverside.com/hc/en-us
Referenced files: 1
social-publishing3.46 KB
View saved version →
---
name: social-publishing
description: Publish/schedule Riverside clips, manage unpublished posts and social accounts, or read analytics on YouTube, TikTok, Instagram, Facebook, LinkedIn or X. Clip editing uses video-editing; live posts must be edited/removed on their platform.
---
# Social publishing
| Tool | Purpose |
|---|---|
| `social_get_connected_platforms` | Accounts and live limits |
| `social_get_publishing_guidelines` | Platform rules and recovery |
| `social_upload_create` | Publish or schedule a clip |
| `social_get_upload_status` | Publish outcome |
| `social_list_uploads` | Find posts |
| `social_get_upload` | Content and capability flags |
| `social_update_upload` | Change an unpublished post |
| `social_cancel_upload` | Permanently cancel a cancellable post |
| `social_get_upload_analytics` | Collected metrics |
| `social_connect_social_account` | User authorization link |
| `social_disconnect_social_account` | Disconnect and cancel scheduled posts |
## Safety contract
Create and `publishNow` can produce real posts: never call them to test or
diagnose. No tool can edit, delete or unpublish a live post. Cancellation cannot
be undone. Success, processing, timeout, transport failure and unknown outcomes
may have posted: never repeat the publish. Only explicit failures passing the
recovery gate can become eligible for a fresh publish.
Use current schemas, connected account limits and live guidelines. Resolve
studio/production ids through content-discovery. Publishing needs `clipId`
(typically an exported edit id) and a connected account.
## Mandatory routing
Before social calls, read all matching references and no unrelated ones. After
every response/failure, re-evaluate and read new matches before the next call.
| Observable condition | Required reference |
|---|---|
| Wall-clock/future time, or draft export may need `composeSettings` | [Scheduling and draft export](references/scheduling-and-draft-export.md) |
| Posts, analytics, accounts, or processing/partial/failed/unknown publish (timeout, transport failure or unusable response) | [Results, management and recovery](references/results-and-recovery.md) |
| A publish was made and its outcome is unconfirmed | [Publish outcome](references/upload-status.md) |
"Tomorrow at 9" matches scheduling before its timezone is known.
## Publish workflow
1. Resolve `studioId` and read connected platforms. Select a valid
`platformAccountId` by account/channel name; ask if studio/account is unclear.
Empty `accounts: []` may mean failed account-detail lookup. Retry this read
once; if still empty, report unavailable details and stop.
2. Load `social_get_publishing_guidelines` for the platform. Use current create
schema and platform counting rules, not raw string length. Ask for YouTube
privacy from live values; never infer/default it. Before YouTube publishing,
inspect `editing_get_export_publish_data` and surface copyright/Content-ID
flags instead of publishing over them.
3. Show exact metadata, account/channel, visibility, resolved schedule and
compose choices. Explain that a live post cannot be undone here; wait for
explicit confirmation. It covers one call for that target/payload. Preview
material changes; retries need new confirmation even if unchanged. Stop on
refusal, hesitation, changed direction or withdrawn confirmation.
4. Make one `social_upload_create` call per separately confirmed target/payload.
5. Report account, visibility, schedule and outcome per target; re-run routing.
Referenced files: 4
video-editing8.29 KB
View saved version →
---
name: video-editing
description: Use when the user wants to cut, trim, clean up, caption, lay out, crop, brand, add overlays, stock media or music to, or otherwise change the content of a Riverside edit, or to turn a raw recording into an editable edit. Not for browsing or searching existing content (see content-discovery), and not for publishing to social platforms (see social-publishing). If the question is whether an editing error is really an authentication or connection problem, use setup first.
---
# Video editing
Server-side timeline editing. Tools are exposed at the gateway with the
`editing_` prefix. Work is keyed by an **`editId`**; revision-aware writes
advance a **`revision`**.
Current tool schemas and the live `editing_get_editing_guide` response are
authoritative for parameters, enums, limits, defaults, and recoverable errors.
This file carries only the invariants no single schema can state.
## Three rules that override everything
1. **Keep operating on the same edit.** When iterating on an existing edit, do
NOT create a new edit or clone — keep passing the same `editId` and its
latest `revision`. Create or clone only when the user explicitly asks for a
separate version. The currently listed entry points
(`editing_create_edit_from_recording` and `editing_clone_edit`) each return
an `editId` that becomes the working edit for the rest of the flow.
2. **Thread the revision on revision-aware writes.** When the current write
schema exposes `expectedRevision`, pass the latest revision back as that
value; omitting it risks clobbering a concurrent edit. After a successful
revision-changing write, use the revision it returns for the next such
write. Preserve the revision's live type and value rather than coercing it.
Do not generalize this into an argument for every tool that accepts an
`editId`: reads and some non-revisioned operations do not accept
`expectedRevision`. The live schema of the specific call decides whether the
argument exists; the invariant is that you never omit or stale it when it
does.
A revision conflict is not retryable. Never replay the same write with a
newer revision substituted. Stop before another write and evaluate the
routing table again; the now-observable conflict selects the recovery
workflow that re-reads and re-derives the operation.
3. **Never mix time axes.** See below. This is the easiest way to silently
corrupt an edit.
## Time axes — read before computing any time
The timeline has two axes, and tools disagree about which one they take.
- **Source time** — positions in the original recorded media, before cuts.
- **Playable time** — positions on the edited, post-cut timeline the viewer sees.
With no cuts yet the two coincide and the distinction is harmless. Once any cut
exists they diverge, and a number from one axis fed to a tool on the other lands
in the wrong place with no error.
| Axis & unit | Tools |
|---|---|
| **Source**, `{n,d}` fractions of seconds | `editing_read_timeline_in_range` (every returned time: `trackTime`, `timeRange`, `duration`, scene times), fraction-based `editing_batch` params |
| **Source**, integer ms | `editing_add_lower_third` (`startMs`), `editing_add_text_overlay` (`startMs`), `editing_insert_overlay` (`startMs`) |
| **Playable**, integer ms | `editing_cut_time_ranges` (`startMs`/`endMs`), `editing_insert_audio` (`startMs`), `editing_insert_media_as_scene` (`startMs`), `editing_read_aligned_transcript` (`playableStartMs`/`playableEndMs`, and its `startMs`/`endMs` window), `editing_resolve_transcript_selection` (in and out) |
Rules that follow:
- **Never compare or reason across the axes** — not in a tool argument, and not
in your own analysis. Converting a source `{n,d}` to milliseconds does not
make it comparable to a playable millisecond value: once cuts exist, "these
two numbers differ" tells you nothing about whether they name the same moment.
Two values are comparable only when both came from the same axis.
- Convert a `{n,d}` fraction to ms *within one axis* with
`Math.round(1000 * n / d)`.
- Derive playable-ms placements from `editing_read_aligned_transcript` or
`editing_resolve_transcript_selection`, and source-ms placements from
`editing_read_timeline_in_range`. Never cross over.
- `editing_insert_stock_media` places an overlay the same way
`editing_insert_overlay` does; treat its `startMs` the same.
- `position` on the overlay tools is a **canvas** fraction, not a time — it
shares the `{n,d}` shape and means something else entirely.
## Read the guide, then follow the guide
For anything beyond a single common operation, call `editing_get_editing_guide`
first — and then use only what that response actually lists.
**Ask for the narrowest slice that answers the question.** The guide is
sectioned, and one section can outweigh this whole skill, so an unscoped call is
the most expensive read on this surface. Take the current section and category
names off the tool's schema and request the one covering the task in hand. Never
pass a section or category from memory or inferred from a wrapper's name; if the
one you expected is absent, choose from what is present and say which you used.
**An unavailable operation is not a dead end.** When a tool is missing from the
live surface or comes back unavailable, say so — then offer a fallback that
response or the guide actually names, described as what it does, never as an
equivalent. Assemble no substitute of your own.
## Prefer the dedicated tool over batch
Each common operation has a dedicated high-level tool that resolves timeline
details for you. Reach for the low-level batch tool only for a multi-operation
atomic change, or for an operation with no standalone wrapper.
> **The batch tool's callable name is `editing_batch`.** An earlier surface
> exposed it under a doubled prefix; **`editing_editing_batch` is not a callable
> tool.** Confirm the name against the live tool surface rather than either
> spelling written from memory.
## Transcript handles fail closed
`editing_resolve_transcript_selection` returns opaque handles and a
ready-to-execute payload scoped to **one edit and one revision**. Never carry a
handle across edits or across revisions.
Execute `payload.input` **unchanged, and only when `readyToApply` is true**.
When it is false, or unresolved warnings leave `payload: null`, stop: report the
warning and re-resolve. Never synthesize a call from a null payload, and never
hand-edit the payload into something executable.
## Handing an edit off to publishing
When an edit is going out to a social platform, publishing itself belongs to
the social-publishing skill, and the exported edit id is the `clipId` it takes.
Before a YouTube handoff, clear the copyright / Content-ID pre-check on the
edit's media with `editing_get_export_publish_data`, and surface a flagged match
instead of publishing over it. For another platform, use its current live
guidance rather than generalizing the YouTube check. The YouTube pre-check
condition selects the Edit lifecycle row below.
## Where to read next
| Need | Read |
|---|---|
| Create or clone an edit, inspect an edit, compare revisions as the primary task, recover an actual revision conflict, run a verified plan, or prepare a YouTube handoff that requires the copyright pre-check | [Edit lifecycle](references/edit-lifecycle.md) |
| Keep, remove, or move transcript-selected speech | [Transcript editing](references/transcript-editing.md) |
| Cut, reorder, clean up, restore, or adjust audio | [Cuts and audio](references/cuts-and-audio.md) |
| Apply captions, presets, or a brand kit | [Captions and brand](references/captions-and-brand.md) |
| Change layout/crop/visual media, place existing assets, or use stock | [Visuals and media](references/visuals-and-media.md) |
**Routing contract:** Before the first Riverside workflow call, evaluate every
row against the observable request and state. Read every matching reference and
no unrelated reference. After each Riverside response, evaluate every row
again before the next workflow call; read any newly matching reference first.
Only this table routes references — a reference never routes to another one.
A post-operation revision comparison already prescribed by the owning
workflow reference does not activate an additional reference by itself. Every
condition listed in the routing table remains authoritative.
Referenced files: 6