MCP server

Connect Claude, Cursor, or any MCP client to your workspace and drive Onepin in natural language.

Onepin runs a remote Model Context Protocol server at https://mcp.onepin.ai. Connect it once and your agent — Claude Code, Claude Desktop, Cursor, ChatGPT — gets nineteen tools that browse the voice catalog, author and validate workflows, price a run, start it, and hand the audio back as a link you can play.

It acts on the same workspace the console and the REST API do, with exactly the permissions your workspace role already gives you. It doesn’t replace the CLI — what it adds is a one-command connection with nothing to install, and a confirmation step the server enforces before anything is spent or overwritten.

The CLI’s agent skill is the other way to hand Onepin to an agent, and the two coexist. The skill has your agent run the local CLI under your API key; this runs the tools server-side under your sign-in. Which to pick.

Sign in — there is no API key

MCP authenticates by OAuth only. You don’t mint, paste, or store anything: your client sends you to a normal Onepin sign-in, you approve it once, and it holds a token that refreshes itself. The connector acts as you.

API keys are not accepted here. A client configured with an Authorization: Bearer op_live_… header gets a 401 telling it to sign in — remove the header and reconnect. Keys still work everywhere else; see Authentication.

Revoke the connection from your account settings at any time; the token stops working within a minute.

Connect

Paste the bare hostname. There is no path and no trailing slash — MCP has its own subdomain, and the OAuth resource identifier has to equal what you typed, character for character. A stray /mcp is a discovery failure your client then caches for about five minutes.

Claude Code

claude mcp add --transport http onepin https://mcp.onepin.ai --scope user

Then run /mcp, pick onepin, and choose Authenticate — Claude Code never opens a browser by itself. --scope user makes the server available in every project; the default (local) registers it only for the directory you ran the command in.

Claude Desktop and claude.ai

Settings → Connectors → Add custom connector, paste https://mcp.onepin.ai, and sign in when the browser opens.

Cursor

Add it to ~/.cursor/mcp.json (or .cursor/mcp.json for a single project):

{
"mcpServers": {
"onepin": {
"url": "https://mcp.onepin.ai"
}
}
}

Anything else

The server speaks streamable HTTP and advertises OAuth 2.1 at https://mcp.onepin.ai/.well-known/oauth-protected-resource. Any client that can discover an authorization server connects with the URL alone.

api.onepin.ai/mcp is retired and answers 410 Gone. A connector still pointed at it must be re-added with the hostname above — the resource identifier is per-URL, so the old one signs you in and then fails the match.

Verify

Ask for something small — “list my Onepin workflows”. If you belong to more than one workspace, the first tool call says so and lists them: list_workspaces, then select_workspace. The choice is remembered for 30 days and across reconnects.

Tools

Workspace

ToolWhat it does
list_workspacesList the workspaces you can work in, and which one is selected
select_workspaceChoose which workspace the other tools act in — remembered across sessions

Workflows

ToolWhat it does
list_workflowsThis workspace’s workflows, most recently updated first
get_workflowOne workflow as a markdown page describing what its graph does
get_node_infoThe node types you can use, or one node’s config schema and ports
validate_workflow_definitionCheck a definition against every gate a run start applies — saves nothing
create_workflowCreate a workflow from a definition validate_workflow_definition approved
update_workflowReplace an existing workflow’s graph with an edited definition (destructive)
list_templatesBrowse the template gallery
create_workflow_from_templateClone a template into this workspace as a runnable workflow

Voices

ToolWhat it does
list_providersThe speech providers you can use, or one provider’s models
find_voicesSearch the voice catalog — search takes a plain-language description
preview_voicePlay a voice, in the language it will actually speak
set_workflow_voicePin a catalog voice onto one locale of a generator node (destructive)

Runs

ToolWhat it does
estimate_runPrice a run before starting it — creates nothing, charges nothing
run_workflowStart a run (destructive — spends credits)
get_run_statusHow far a run has got
get_run_outputsThe audio a run produced, one entry per output node
download_runOne ZIP link containing every audio file a completed run produced

Destructive means it can destroy or overwrite work you already have. run_workflow spends credits irreversibly, set_workflow_voice is a last-write-wins overwrite of a voice map an open canvas may be editing, and update_workflow is that same overwrite over the whole graph — the definition it replaces is not versioned anywhere you can get it back from. Creating a workflow is additive, so it isn’t marked.

Nothing is spent or overwritten on the first call

run_workflow, create_workflow, and update_workflow do nothing the first time they are called. Each returns requires_confirmation: true carrying what you need to judge it, and acts only on a second call with confirm=true:

  • A run comes back with workflow_name, workflow_summary, expected_credits, max_credits, and current_balance — plus estimated_overage_cents when it would bill past your plan allowance.
  • A create comes back with name and workflow_summary, and not_included when the graph leaves something out: no translator, no normalizer, no quality check, or a check whose failing lines are discarded. If the workspace already holds something that looks like what you asked for, those candidates come back instead, and force=true is how you decline the offer.
  • An edit adds replaces — the graph that is there now — content_changes for any node text the edit would rewrite, and an edit_token the confirming call must carry. That token is signed over the workflow, the definition, and the graph as it stood, so a workflow someone else changed while you were reading is refused rather than silently overwritten.

Two tools also require a token from a read-only call, so that what you approved is what happens: create_workflow needs the validation_token from validate_workflow_definition, and run_workflow needs the run_token from estimate_run. The run token is single-use and is refused if the workflow moved after you priced it, or if the price rose above the ceiling you approved. Both expire after 10 minutes, and a refusal always means nothing happened — the remedy is one more read-only call.

Confirmation is relayed by your client, so no MCP server can prove a person saw it. For a ceiling that doesn’t depend on the client, put it on the caller’s authority instead: a viewer role cannot start a run, and the workspace credit balance is a hard cap.

Every audio URL this server hands back — find_voices and preview_voice samples, get_run_outputs’ per-line files — is a plain presigned file: no auth header, no page to log into, good for about an hour.

What that looks like depends on your client. One with a shell (Claude Code, Cursor) fetches the URL and plays it with whatever your machine has. A host that supports MCP Apps (Claude Desktop, claude.ai, Cursor, VS Code) renders an inline player — one row per sample, one per line for a run, nothing autoplaying, and past 20 lines it points at download_run instead. Anything else gets a titled link on its own line rather than a raw presigned URL.

Nothing plays unasked. preview_voice(search=…) searches and hands back a shortlist with played: false, leaving the choice to you; pass catalog_voice_id when you’ve already named a voice and it plays straight away.

Authoring a workflow through an agent

get_node_info() with no argument returns three things: the node catalog, definition_shape — the envelope, where nodes and edges live under graph rather than at the top level — and pipeline_choices, the stages that are a decision rather than a default (a translator, a normalizer, a quality check) with what skipping each one does instead.

Two things no config_schema will tell you:

  • Don’t compute positions. create_workflow lays the whole graph out with the product’s own canvas layout, so send {"x": 0, "y": 0} for every node. On an update only the nodes your edit touched are re-placed — cards someone dragged stay where they put them.
  • Wire a validator’s fail port, or know why you aren’t. Connect it to the generator’s lines port and a failing line is regenerated, bounded by that validator’s max_retries. Leaving it unconnected is legal and means the opposite: failing lines are discarded, and the run completes with a shorter export than the script. See How validators work.

Editing a workflow you already have is a round trip:

get_workflow(include_definition=true) → edit → validate_workflow_definition
→ update_workflow() # writes nothing; returns replaces + an edit_token
→ update_workflow(confirm=true, edit_token=…)

Existing runs are untouched by an edit — hearing the difference means estimate_run and run_workflow again, which charges credits again.

Troubleshooting

SymptomCause
Claude Code says ! Needs authentication and nothing happensThat’s the resting state, not a fault — it never opens a browser by itself. Run /mcp, pick the server, choose Authenticate
A 401 telling you to sign inAn API key was sent. Remove the Authorization header from your client config and reconnect
The server doesn’t appear in your client at allIt’s registered to one project rather than to you. Run claude mcp list from that directory and re-add with --scope user
410 Gone naming a different URLYou’re connecting to the retired api.onepin.ai/mcp. Re-add the connector with https://mcp.onepin.ai
”Couldn’t reach the MCP server”, although the host is upThe URL you pasted carries a path or a trailing slash. Re-add the bare hostname — discovery is cached for about five minutes, so the fix isn’t instant
Sign-in completes but tools say the account is unknownThat account has no Onepin user yet. Open app.onepin.ai once — MCP won’t create one from an OAuth token
Tools say the workspace is ambiguousYou’re a member of several. list_workspaces, then select_workspace
A tool answers requires_confirmation: true and does nothingThat’s the design. Read the details back to the user, then call the same tool again with confirm=true. Nothing was created, started, or charged
run_workflow says the workflow changed since you priced itSomething wrote to it between estimate_run and run_workflow. Nothing started and nothing was charged — price it again and run with the new run_token
run_workflow says the run token was already usedIt already started a run. Poll get_run_status rather than pricing and running again, which would charge twice
A token is rejected as expiredTokens last 10 minutes. Call estimate_run (or validate_workflow_definition) again and use the fresh one
Tools missing after a server updateRestart the client — the tool list is fetched on connect and cached