Potion turns text and audio into an unlisted podcast feed that the user adds to any podcast app. This page documents the connector Potion offers on Meta's Muse, at https://api.withpotion.io/mcp/muse: how it connects, what each tool does, which tools Muse should treat as sensitive, and how errors and limits come back. Inputs and outputs for every tool are in each tool's own schema (tools/list) and in the API reference at https://api.withpotion.io/docs.
https://api.withpotion.io/mcp/muse.https://api.withpotion.io/oauth/register; no client ID or secret is issued in advance. Discovery: https://api.withpotion.io/.well-known/oauth-protected-resource/mcp/muse and https://api.withpotion.io/.well-known/oauth-authorization-server/mcp/muse.account, which gives the connection the same access to the user's Potion account as its own API key. Potion does not offer a narrower scope yet. Every token is bound to https://api.withpotion.io/mcp/muse (RFC 8707) and is refused on Potion's other connectors.get_plans and https://api.withpotion.io/pricing describe them. Plans are bought on Potion's website, not through this connector.Every tool acts only on the signed-in user's own account, and none needs a permission beyond the account scope. Read tools change nothing. Write tools change only the user's own feeds, episodes and narration jobs. A feed is unlisted: it asks podcast directories not to list it, and anyone holding its address can subscribe, so adding an episode puts it in front of whoever has that address. Each episode also gets a share page link that plays it for anyone holding the link. We mark a write as sensitive when it cannot be undone, when it sends an email, or when it spends the user's narration allowance.
| Tool | Class | What it does and changes |
|---|---|---|
start_signupStart Potion signup |
Sensitive write | Creates a pending Potion account and emails a confirmation link to the address given. Not needed when the user connected through Muse, because that sign-in already made the account. Sensitive because: It sends an email to an address the caller supplies. |
check_signupCheck signup status |
Read | Reports whether a pending signup has been confirmed. Changes nothing. |
create_feedCreate a podcast feed |
Write | Creates a podcast feed on the user's account and returns its address (rss_url). The feed is unlisted: it asks podcast directories not to list it, and anyone holding the address can subscribe. |
list_feedsList podcast feeds |
Read | Lists the user's feeds, with whether a podcast app has fetched each one yet. |
get_feedGet a podcast feed |
Read | Returns one of the user's feeds, with whether a podcast app has fetched it yet. |
update_feedUpdate a podcast feed |
Write | Changes a feed's title, description, author, artwork or settings. The new values are what podcast apps show from their next refresh; the old values are not kept. |
delete_feedDelete a podcast feed |
Sensitive write | Deletes a feed with all its episodes and their stored audio. Podcast apps subscribed to it stop receiving it. Sensitive because: It cannot be undone. |
add_episodeAdd an episode |
Write | Adds an episode to one of the user's feeds from audio already at a public address, and returns the episode's share page link, which plays it for anyone holding that link. |
add_episodes_batchAdd many episodes at once |
Write | The same as add_episode for several episodes in one call. Each gets its own share page link. |
list_episodesList episodes in a feed |
Read | Lists the episodes in one of the user's feeds. |
get_episodeGet an episode |
Read | Returns one episode, including its share page link if it has one. |
update_episodeUpdate an episode |
Write | Changes an episode's title, description, artwork or publish date. The old values are not kept. |
delete_episodeDelete an episode |
Sensitive write | Deletes an episode and any audio Potion stored for it. Its share page stops working. Sensitive because: It cannot be undone. |
renderNarrate text into an episode |
Sensitive write | Narrates the text given into an episode in one of the user's feeds. Returns a job; the episode appears when the job completes. Sensitive because: It spends the user's narration allowance, the paid part of their plan, charged on the length of the audio produced. |
ingest_urlRead an article and prepare it for narration |
Write | Fetches a public web page, extracts its article text and holds it in a job, with the word count and an estimate of the audio length. Narrates nothing and spends nothing; start_render does that. |
start_renderStart a waiting render |
Sensitive write | Narrates the text held in a job (from ingest_url or append_text) into an episode. Sensitive because: It spends the user's narration allowance, the paid part of their plan, charged on the length of the audio produced. |
append_textAdd more text to a render |
Sensitive write | Adds text to a job that has not run yet, for text too long for one call. With is_final=true it also starts the narration, as start_render does. Sensitive because: Its final call starts the narration. It spends the user's narration allowance, the paid part of their plan, charged on the length of the audio produced. |
get_jobCheck a render |
Read | Reports a narration job's state and, once it has completed, the episode it made. |
list_jobsList recent renders |
Read | Lists the user's recent narration jobs and their states. |
get_accountGet account and usage |
Read | Returns the user's plan, limits, usage and how much narration time is left. |
request_account_deletionRequest account deletion |
Sensitive write | Emails the account holder a link that deletes the whole account (every feed, episode and audio file). Nothing is deleted unless that link is opened within an hour. Sensitive because: It sends an email, and its purpose is a deletion that cannot be undone. |
check_confirmationCheck a confirmation |
Read | Reports whether an emailed confirmation (such as an account deletion) has been opened yet. It cannot carry the action out. |
get_changelogGet the Potion changelog |
Read | Returns Potion's published version history. |
get_legal_linksGet terms and privacy links |
Read | Returns the addresses of Potion's Terms of Service and Privacy Policy. |
list_voicesList narration voices |
Read | Lists the narration voices with links to a sample of each. Spends nothing. |
get_plansGet plans and limits |
Read | Returns Potion's plans with their prices and limits. Nothing is bought or changed. |
render, start_render and the final append_text start a job and return straight away. A job moves through collecting (text still arriving), queued, rendering, and ends completed or failed. The response carries expected_wait_seconds (how long the wait is, which is not the length of the audio) and poll_after_seconds; one get_job call after that usually finds it completed, with the episode already in the feed. The allowance is charged on the length of the audio produced, once it exists. A failed job charges nothing and says so. Calling render again after a failure starts a new job; it does not retry the old one.
isError: true and a message that says what happened and what the user can do, plus _meta["io.withpotion/refusal"] with the HTTP status and Potion's error codes. Nothing is written when a call is refused.WWW-Authenticate header pointing at the resource metadata, and a JSON-RPC error with the same explanation.-32602, Unknown tool.isError: true, Potion error code 4007 and the time the limit resets. Waiting until then is the remedy; nothing else is affected.create_upload_link: Held back while the Muse listing is in Meta's review: adding a tool to a surface under review is its own decision, and whether Muse's runtime can send an HTTP PUT has not been checked. The full surface at /mcp carries it.get_upgrade_link: Meta's Muse connector guidelines (platform.muse.ai/docs, section 1.1) ask that a connector finish the tasks it starts, and say: "Sending the user to finish the entire checkout does not meet the completion requirement." This tool's whole job is to hand the user a Stripe page to finish on, so it would fail that test in Meta's tool review ("Connector approval does not cover unapproved tools", section 6.2). get_plans stays, because describing the plans accurately is what section 4.3 asks for; a limit refusal here ends with the neutral note, since there is no checkout tool to point at. The full surface at /mcp carries it.get_billing_portal_link: Meta's Muse connector guidelines (platform.muse.ai/docs, section 1.1) ask that a connector finish the tasks it starts, and say: "Sending the user to finish the entire checkout does not meet the completion requirement." This tool's whole job is to hand the user a Stripe page to finish on, so it would fail that test in Meta's tool review ("Connector approval does not cover unapproved tools", section 6.2). get_plans stays, because describing the plans accurately is what section 4.3 asks for; a limit refusal here ends with the neutral note, since there is no checkout tool to point at. The full surface at /mcp carries it.dismiss_notifications: This surface does not attach the notifications array, so there is nothing here to dismiss.Support and security issues: christo@withpotion.io. Terms and privacy: https://api.withpotion.io/legal.