PodcastsToText
Agents & MCP

MCP server

The same account over the Model Context Protocol: how it authenticates, and the exact config for every client.

POST/api/mcpscope: OAuth, or a bearer API key

The same account, reached a second way. An MCP client (the Claude app, ChatGPT, Claude Code, Cursor, VS Code, Windsurf, Codex, Gemini CLI) connects once and gets 13 tools it can call on its own: find a show's feed, transcribe an episode, and turn the transcript into show notes, chapters, a translation or a published page.

UseWhenBecause
MCPA model is choosing the next callEvery tool returns its result and the next step.
RESTYour code is choosing the next callStatus codes, how_to_fix on every error, and budget headers to pace with.
WebhooksNobody is watchingOver MCP the model polls get_transcript, which is fine in a conversation. A batch or an overnight job should take a delivery instead.

Authentication

Two ways in. A connector (the Claude app on web, desktop or mobile, or ChatGPT) signs in with OAuth: it sends you to podcaststotext.com, you choose what it may do, and there is no key to copy. Disconnect it from Developer → Connected apps. Every other client uses an API key, below.

The server takes the same ptt_ API key as the REST API, as a bearer token, and revoking it cuts off any agent holding it on the next call. Every tool is scoped to the key's owner. Scopes are enforced per tool: a key carrying all of ai:write, shows:write, transcriptions:read, transcriptions:write reaches everything, and a narrower key produces a server that refuses the tools it is not entitled to, naming the missing scope.

Every request
POST /api/mcp
Authorization: Bearer ptt_your_key_here
Content-Type: application/json
Accept: application/json, text/event-stream

Scope the key to what you want the agent to be able to do. A key with only transcriptions:read gives an agent a server that can find and read your episodes but cannot spend a credit, delete anything, or publish. That is the right key to hand something you have not watched work yet.

Connect a client

Every client needs the same three facts: the URL, the Authorization header, and a name to file the server under. They disagree about what to call them, and that disagreement is the entire difficulty of this step. Copy a block, replace ptt_your_key_here, put it where the note under it says, and restart the client.

Claude app
https://podcaststotext.com/api/mcp

Claude on the web, desktop or mobile: Settings → Connectors → Add custom connector. Paste this URL, choose "Sign in now" and "Register automatically", then approve access on podcaststotext.com. No API key.

Claude Code
claude mcp add --transport http podcaststotext https://podcaststotext.com/api/mcp \
  --header "Authorization: Bearer ptt_your_key_here"

Run this in your terminal, from any directory. Add --scope user to make it available in every project.

Claude Desktop
{
  "mcpServers": {
    "podcaststotext": {
      "type": "http",
      "url": "https://podcaststotext.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ptt_your_key_here"
      }
    }
  }
}

Settings → Developer → Edit Config, then restart Claude Desktop.

Cursor
{
  "mcpServers": {
    "podcaststotext": {
      "url": "https://podcaststotext.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ptt_your_key_here"
      }
    }
  }
}

Add to .cursor/mcp.json in your project, or ~/.cursor/mcp.json for every project.

VS Code
{
  "servers": {
    "podcaststotext": {
      "type": "http",
      "url": "https://podcaststotext.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ptt_your_key_here"
      }
    }
  }
}

Add to .vscode/mcp.json in your project root. Note the key is "servers", not "mcpServers".

Windsurf
{
  "mcpServers": {
    "podcaststotext": {
      "serverUrl": "https://podcaststotext.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ptt_your_key_here"
      }
    }
  }
}

Add to ~/.codeium/windsurf/mcp_config.json. Windsurf calls the field "serverUrl".

Codex
[mcp_servers.podcaststotext]
url = "https://podcaststotext.com/api/mcp"
http_headers = { "Authorization" = "Bearer ptt_your_key_here" }

Add to ~/.codex/config.toml: this one is TOML, not JSON.

Gemini CLI
{
  "mcpServers": {
    "podcaststotext": {
      "httpUrl": "https://podcaststotext.com/api/mcp",
      "headers": {
        "Authorization": "Bearer ptt_your_key_here"
      }
    }
  }
}

Add to ~/.gemini/settings.json.

Anything else
{
  "mcpServers": {
    "podcaststotext": {
      "command": "npx",
      "args": [
        "-y",
        "podcaststotext-mcp"
      ],
      "env": {
        "PODCASTSTOTEXT_API_KEY": "ptt_your_key_here"
      }
    }
  }
}

Only if your client cannot do remote HTTP with headers: this bridges the endpoint to a local stdio process. The key goes in env, not argv, where every other process could read it.

The differences that break a setup

ClientWantsNot
VS CodeserversmcpServers
WindsurfserverUrlurl
Gemini CLIhttpUrlurl
CodexTOMLJSON

A wrong key fails silently. None of these produce an error: the client reports the server as configured and lists no tools, which looks identical to a server that is down. Check the key name first.

Check it from outside the client

tools/list
curl -s https://podcaststotext.com/api/mcp \
  -X POST \
  -H "Authorization: Bearer $PTT_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Responses are SSE-framed. A 13-entry tools array means the server and your key are both fine and the problem is in the client config; a 401 means the key is wrong or revoked. The Accept header is not optional. Streamable HTTP requires both types, and omitting it is the usual reason a hand-rolled client gets a 406.

The server publishes a card at `/.well-known/mcp/server-card.json`: transport, auth, version (currently 2.2.0) and every input's JSON Schema, generated from the same source as this page.