OP3 MCP
OP3 MCP
OP3 sits in front of the audio file, so it counts every download whatever app made it.
That is why its numbers differ from Apple's or Spotify's, which each report only their own listeners.
22 tools, including unique listeners, retention cohorts and episode benchmark curves that OP3's own API does not expose.
Built and maintained by Navid Moazzez.
Contents
1. What you can ask it 💬
How many downloads did my podcast get this month?
How many actual people is that, not downloads?
Are my listeners coming back, or is it a new audience every month?
Is this week's episode tracking ahead or behind my usual?
Where in the world is my audience, down to the state?
Which podcast apps do my listeners use, and is that unusual?
Compare my show against these three others.
What day and hour do most downloads happen?
Which of my episodes share the same listeners?
OP3 shows nothing for my feed. What is wrong?
The one that is impossible without this server is the second. Every podcast analytics dashboard reports downloads. A download is an app fetching a file, not a person, and one listener whose app re-requests across three days counts three times. OP3's raw rows carry a privacy-preserving per-listener hash, so unique listeners, returning listeners and retention can be computed from them. None of OP3's own aggregated endpoints expose that, and this server does.
2. Quick install ⚡
Node 20 or newer. Nothing else.
npx -y @thenavidm/op3-mcp@latest --versionThat is the whole install. npx fetches it on demand, so there is nothing to
update later: with @latest, a new version reaches you the next time your
client starts the server.
To build from source instead:
git clone https://github.com/thenavidm/op3-mcp.git
cd op3-mcp
npm install
npm run build
npm test
node dist/index.js --version3. Setup 🔑
You can skip this. The server works with no credential at all, because OP3 publishes a shared preview token and that is what it falls back to. It is rate limited and OP3 can withdraw it, so get your own before relying on it.
Have an agent do it
The agent cannot sign in to OP3 for you. What it can do is walk you through it and wire up the config.
Paste this into Claude Code, Cursor, or any agent with terminal access:
Help me set up the OP3 MCP server.
1. Open https://op3.dev/api/keys and tell me what to click to create an
API key and its bearer token.
2. Stop and wait for me to paste the token back.
3. Add the server to my MCP client config with that token as OP3_TOKEN.
4. Run the doctor command and tell me whether it worked.Or do it yourself
Go to op3.dev/api/keys.
Create an API key and copy its bearer token.
Set it as
OP3_TOKENin your client config, as in section 4.
You do not need to own a podcast. The token reads public OP3 data, which covers every show that has the OP3 prefix on its feed.
To revoke
Delete the key at op3.dev/api/keys. It stops working immediately.
If you want your own show in here
Your podcast needs the OP3 prefix on its episode audio URLs. That is a change to your feed, not to this server, and it is documented at op3.dev/setup. Until a listener downloads an episode through the prefix, OP3 has no data for your show and neither does this.
4. Connect your client 🔌
The long version, every step with what to do when one fails, is in INSTALL.md.
OP3_TOKEN is optional in every block below. Leave it out to use OP3's preview
token.
Claude Code
claude mcp add op3 \
-e OP3_TOKEN=your-token \
-- npx -y @thenavidm/op3-mcp@latestAdd --scope user to make it available in every project rather than just this
one.
Claude Desktop
Platform | Config path |
macOS |
|
Windows |
|
{
"mcpServers": {
"op3": {
"command": "npx",
"args": ["-y", "@thenavidm/op3-mcp@latest"],
"env": { "OP3_TOKEN": "your-token" }
}
}
}Tip Claude Desktop does not inherit your shell PATH. If
npxis not found, use the absolute path fromwhich npx.
Quit Claude Desktop completely and reopen it.
claude.ai on the web
claude.ai runs a connector from Anthropic's cloud rather than your machine, so it cannot launch a local command. It needs a public HTTPS URL.
Run the server over HTTP:
npx -y @thenavidm/op3-mcp@latest --http --port 8000Host it somewhere with a public HTTPS URL, then in claude.ai go to Customize, Connectors, +, Add custom connector, paste the URL and click Add.
On Team and Enterprise plans an owner adds it first under Organization settings, Connectors, then each member enables it under Customize, Connectors.
Set OP3_HTTP_TOKEN to require a bearer token on every request, and
OP3_HTTP_HOST=0.0.0.0 if it needs to accept connections from outside the
machine. It binds to 127.0.0.1 by default.
Cursor
.cursor/mcp.json, same JSON shape as Claude Desktop, key mcpServers.
Windsurf
~/.codeium/windsurf/mcp_config.json, key mcpServers.
VS Code
.vscode/mcp.json. The key is servers, not mcpServers, and each entry takes
"type": "stdio".
{
"servers": {
"op3": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@thenavidm/op3-mcp@latest"],
"env": { "OP3_TOKEN": "your-token" }
}
}
}Codex CLI
~/.codex/config.toml:
[mcp_servers.op3]
command = "npx"
args = ["-y", "@thenavidm/op3-mcp@latest"]
[mcp_servers.op3.env]
OP3_TOKEN = "your-token"Gemini CLI
~/.gemini/settings.json, key mcpServers.
Everything else
Any stdio MCP client takes the same three things: the command npx, the args,
and the env block.
Docker
docker build -t op3-mcp .
docker run --rm -i -e OP3_TOKEN=your-token op3-mcp5. Check it worked 🩺
npx -y @thenavidm/op3-mcp@latest doctorIt tests the token against the cheapest OP3 endpoint, tests the raw query endpoints separately because they fail for their own reasons, and prints the settings in force.
Symptom | Cause |
| The key was deleted at op3.dev/api/keys, or |
Every show lookup returns not found | The podcast does not have the OP3 prefix on its feed. Run |
Rolled-up tools work, raw ones time out | The window is too wide. Narrow it, or raise |
Numbers do not match the OP3 dashboard | Rolled-up figures lag by about a day. Check the |
| Desktop does not inherit your shell PATH. Use the absolute path |
6. What it costs to have connected
Every MCP server sends its whole tool list to the model on every turn, whether you mention it or not. Measured on this one:
Sent per turn | |
22 tool definitions, plus the server instructions | ~7,500 tokens |
That is the price of it being connected at all, before you ask anything. It is not unusual, and almost nobody publishes it.
Two ways to spend less.
Turn it off when you are not using it. In Claude Code that is
@op3 to toggle, and every client has an equivalent.
Or reach for a shell instead. A command is not in the context window, so it costs nothing on the turns you do not use it. It is not free either: an agent still needs the skill file, roughly 1,200 tokens, but only once the subject comes up rather than on every turn regardless.
7. Tools 🛠️
Every tool is a read. Nothing here changes anything.
Finding a show
Tool | Does |
| Any identifier to an OP3 show uuid. Takes a feed URL and encodes it for you |
| Show title, uuid, podcast guid, stats page, optionally the episode list |
| Episodes with OP3 episode ids and publication dates, searchable by title |
Downloads, from OP3's rolled-up data
Fast. Prefer these whenever they answer the question.
Tool | Does |
| Monthly downloads, the week-by-week breakdown, and the weekly average |
| Downloads at 1, 3, 7 and 30 days after publication, plus all-time |
| Several shows ranked side by side, in one request |
Audience, from the raw rows
The tools OP3's own API cannot give you.
Tool | Does |
| Unique listeners against downloads, and the ratio between them |
| First-time against repeat listeners, over a baseline you choose |
| Cohort carry-over between two periods, as two separate rates |
| Which episodes share an audience, and how much |
Where and how
Tool | Does |
| Downloads and listeners by continent, country, region, metro or timezone |
| Podcast apps, over any window rather than OP3's fixed three months |
| All four dimensions at once: agent type, app, device type, device |
| App market share across every show OP3 measures |
| This show against that global mix, indexed so 100 is average |
Over time
Tool | Does |
| Downloads and listeners by day, week or month, with a growth rate |
| Hour of day and day of week, in UTC |
| One episode against the show's median at the same age |
Discovery and setup
Tool | Does |
| Episodes across OP3 that carry a |
| Whether OP3 is receiving downloads for a feed, and what is wrong if not |
| Raw download rows, every filter OP3 offers. The escape hatch |
| Raw request log across OP3. A verification surface, not an analytics one |
8. Reading the numbers 📊
The part worth more than the upstream API docs. All of it was found by probing the live API, because OP3's OpenAPI document declares no response schemas.
A download is not a person. It is an app fetching a file. Podcast analytics
across the industry quotes downloads, and a show with a loyal audience whose
apps re-request looks larger than a show with more actual listeners.
op3_audience_summary gives both numbers and the ratio.
Episodes are not comparable on totals. An older episode has had longer to
accumulate downloads. op3_episode_curve compares at equal age against the
show's own median, and excludes episodes younger than the horizon from that
median so a three-day-old episode does not drag a thirty-day comparison down.
App share on its own says almost nothing. Nearly every show's biggest app is
Apple Podcasts, because Apple is around 38% of all podcast listening. A show at
40% Apple is under-indexed. op3_benchmark_apps divides by the global share
so the number means something.
bots does more than add bots. With it off, OP3 applies its published
download calculation, which deduplicates repeat requests. With it on you get raw
request rows. On one probe the same window returned 213 against 345, and only 79
of the difference were bot rows.
Rolled-up figures lag about a day. They carry an asof date. That is why
they will not match a live dashboard exactly.
An empty episode list is normal for a small show. OP3's daily rollup has not covered it yet. The show-level total may still be there.
Metro codes are US-only. They are a US broadcast concept. Use
level=region for a worldwide breakdown.
Raw download rows come back oldest first. OP3 offers no way to reverse that on this endpoint, so a limit takes the earliest rows in the window. Narrow the window to see recent activity rather than raising the limit.
Some shows cannot be filtered by episode. OP3 derives the episode id from
the episode audio URL, so a host that regenerates those URLs leaves historical
rows carrying ids that no longer appear in the feed. Checked across three shows,
two matched exactly and one had no overlap at all. op3_episode_curve detects
this and says so rather than returning silent zeros.
The raw endpoints are scans, not indexes. Two rows took 2790ms when probed. Cost grows with the window. The server pages with a continuation token, caps what it will pull, and labels any result that was cut short, because a truncated result presented as complete makes every rate computed from it wrong.
9. Your data 🔐
There is no backend. The server runs on your machine, talks to op3.dev, and
stores nothing on disk.
Responses are cached in memory for five minutes so an agent asking several
questions about one show does not pay for the same scan repeatedly. That cache
dies with the process. Set OP3_CACHE_TTL_MS=0 to disable it.
Per-listener identifiers never leave the server. OP3's raw row carries
audienceId and hashedIpAddress. Both are aggregated over inside the process
and stripped from anything returned. Every audience figure is a count, a rate or
a distribution.
This is deliberate. OP3 exists to be a privacy-preserving analytics service, and
a wrapper that streamed stable per-listener keys into a model context would undo
that. op3_query_downloads can emit a shortened, non-reversible label if you
need to tell rows apart by listener, and it is off by default.
Third-party text. Show and episode titles come from arbitrary RSS feeds. Anyone can publish a podcast, so that text is attacker-controlled and reaches the model inside a tool result. The server neutralises fence-breaking and tells the model in its instructions to treat it as data. That raises the cost of an injection rather than removing it. The real reason the blast radius is small is that this server is read-only and reaches nothing but OP3.
Settings
Variable | Default | Does |
| preview token | Your bearer token from op3.dev/api/keys |
| 45000 | Per-request deadline |
| 150 | Spacing between requests |
| 50000 | Cap on rows any one analysis pulls |
| 40 | Cap on continuation pages |
| 300000 | Response cache lifetime, 0 disables |
| 8787 | Port for |
| 127.0.0.1 | Bind address for |
| none | Require this bearer token on HTTP requests |
10. Troubleshooting 🔧
Run doctor first. It names the problem in one command.
npx -y @thenavidm/op3-mcp@latest doctorSymptom | Cause and fix |
"OP3 has nothing at /shows/..." | The show has no OP3 prefix on its feed. Run |
Downloads are zero but the show exists | The prefix was added recently and nothing has come through. Widen the lookback |
Every row is a bot | The prefix works but no listener has downloaded yet |
A tool times out | The window is too wide for a scan. Narrow it or raise |
A result says it was truncated | A cap stopped the pull. Narrow the window, or raise |
| The host regenerates episode URLs, so episode ids do not line up. Show-level tools still work |
Rate limited on the preview token | It is shared. Get your own at op3.dev/api/keys |
FAQ ❓
An MCP server is a standard way to give an AI assistant tools it can actually call. Model Context Protocol is the agreement they speak, so any MCP client connects to any MCP server. This one exposes 22 read-only tools over OP3.
It does not. The token reads public OP3 data, which covers every show that has the prefix on its feed.
You do not need an account, though you should get a token. Without one the server uses OP3's shared preview token, which is rate limited.
It works with any podcast whose feed carries the OP3 prefix, whoever hosts it.
Those report only their own listeners. OP3 sits in front of the audio file, so it sees every download regardless of app.
It does not. OP3's API is read-only and so is this.
It does not. Per-listener identifiers are aggregated inside the server and stripped from every response.
The raw endpoints are scans. Cost grows with the window. The rolled-up tools answer in milliseconds; prefer them.
It works over the HTTP transport, which needs a public HTTPS URL. See section 4.
With @latest in the install line, the next published version reaches you the next time your client starts the server.
Questions
Run into a problem or have a question? Open an issue and I will help.
About the author 👋
Navid Moazzez is a leading AI business strategist, and the host of the AI Creator Summit, watched by 100,000+ creators. He helps creators and founders master AI and build their own AI Operating System (AI OS) to automate their business and life. This MCP server is one piece of that system.
Links
Personal website: navid.me
Navid Media: navid.media
YouTube: @thenavidm and @thenavidai
X: @thenavidm
Instagram: @thenavidm
LinkedIn: thenavidm
If this is useful, star the repo and come say hi on X.
Dependencies
Library | License | What it does |
MIT | The MCP server and transports | |
MIT | Tool argument schemas and validation |
Nothing else. The OP3 client, the pagination, the aggregation and the time handling are all built in, so the install is two packages deep.
License
MIT. Free to use, modify, and share.
Not affiliated with, endorsed by, or connected to the Open Podcast Prefix Project.
© 2026 NM Media. Made with ❤️ by Navid Moazzez.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/thenavidm/op3-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server