关于 Apple Podcasts MCP Server
Apple Podcasts MCP Server 通过 Apple Podcasts Connect Reporter 提供只读的节目所有者分析数据,适用于已加入计划、需要节目及单集收听和关注者指标的所有者,而非查询公开目录。
主要功能
- 01检查 Reporter 访问权限
- 02节目级收听摘要
- 03单集收听数据排行
- 04按周期查看关注者趋势
- 05指定日期范围和结果上限
适用场景
- 01查看节目播放量和听众数
- 02找出高参与度单集
- 03跟踪关注者变化
- 04验证 Reporter 凭据
MCP 相关
该 MCP 服务向客户端提供只读 Reporter 分析工具,使用访问令牌和供应商编号获取节目、单集及关注者指标。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @conorbronsdon/apple-podcasts-mcpAPPLE_PODCASTS_ACCESS_TOKEN密钥Reporter access token from Apple Podcasts Connect (Settings > Access Token). Expires 180 days after it is generated.APPLE_PODCASTS_VENDOR_IDVendor number from Apple Podcasts Connect Settings, e.g. 87654321APPLE_PODCASTS_ACCOUNT_IDApple account number. Only needed when the access token can read more than one account, which Reporter reports as error 214.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
4收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
apple-podcasts-mcp
面向 AI Agent 的 Apple Podcasts 所有者分析:播放次数、关注者数量和单集收听情况,通过 Apple Podcasts Connect Reporter 协议提供。只读。
这是一个 MCP 服务,提供 Apple 展示给节目所有者的分析数据:单集获得了多少次播放、听众听到了什么位置,以及关注者数量是否在变化。这些数据存储在 Apple Podcasts Connect 和 Reporter 服务中,不在 Apple 的公开目录 API 里。
这里的所有内容都尚未通过真实 Apple 账户验证。 本协议根据 Apple 的 Reporter 文档实现,并使用手动编写的固定数据进行测试。尚未通过实际网络请求验证此服务发送的请求或解析的响应。如果你用真实的供应商编号运行它,告知返回结果的问题反馈会非常有帮助。
使用此服务必须加入 Apple Podcasters Program。 Reporter 使用供应商编号识别你的身份,而该编号是在加入 Program 后建立的供应商关系中发放的。普通的免费 Podcasts Connect 账户没有此编号:其“账户”→“详细信息”页面显示的是账户 UUID,这是另一种标识符,在此处无法使用。加入计划需要支付年费,并提供法定实体、税务和银行信息。请参阅 Apple Podcasts 功能的可用性。
如果你尚未加入,就无需进行任何配置,这个服务也帮不了你——请直接在 Podcasts Connect 的“分析”部分查看数据。
只读。 Reporter 只读取数据。此服务无法更改节目、单集或账户。
此服务不提供什么
这不是 iTunes Search/公开目录 API。它不会按名称查找节目、读取公开排行榜、获取封面图片或返回评论和评分。我查看过的其他“Apple Podcasts” MCP 服务都封装了公开目录,无需凭据。此服务需要你的供应商编号和访问令牌,并以此换取你自己的收听数据。
它也不涵盖:
- 订阅和收入。 Reporter 提供
apSubscriptionsSales等接口。此服务不会封装这些接口。 - 你拥有 Podcasts Connect 账户之前的数据。 Reporter 报告的是 Apple 为你的供应商编号记录的数据。
- 今天的数据。 Apple 发布数据会延迟一到两天,因此日期范围默认截至两天前。
- 下载量。 Apple 报告的是播放次数和听众数,而不是下载量。如果你需要下载量,请使用托管平台或前缀分析来源,例如 op3-mcp。
工具
| 工具 | 返回内容 |
|---|---|
apple_podcasts_check_access | 令牌是否有效、可读取哪些供应商编号,以及 Apple 返回的令牌到期时间。不会返回收听数据。 |
apple_podcasts_summary | 指定日期范围内,按时段和合计显示节目的播放次数、独立听众数、参与听众数和关注者数。听众数统计的是设备,而非人数——请参阅指标含义。 |
apple_podcasts_episodes | 指定日期范围内各集的播放次数和听众数,按时段汇总并排序。 |
apple_podcasts_followers | 指定范围内各时段的关注者数值,以及整个时间窗口内的变化。 |
有意不提供“获取原始报告”工具。Reporter 每个日期返回一份报告,每份报告都包含每集一行;在非全球版本中,还会包含每个商店每集一行。一个月的数据就有数万行,原封不动地交给 Agent,只会让上下文窗口耗在制表符分隔的文本上。
每个工具都需要显式指定日期范围和上限:
max_periods限制单次工具调用发起的 Reporter 请求数,硬性上限为 31。Reporter 不支持范围查询——每个日期都需要一次 HTTP 往返——因此这是速率限制保护,而非形式要求。超过上限的范围会截断为最近的时段,并在响应中通过rangeTruncated说明。apple_podcasts_episodes中的limit将返回行数限制为 50。- 默认范围较短:Daily 为 7 天,Weekly 为 7 周,Monthly 为 6 个月。每个默认范围都设定为不超过默认的
max_periods(7),因此不指定日期时,调用会返回完整时间窗口,而不会截断。
指标含义
Apple 的数据并不代表人数。Podcasts Connect Analytics 汇总的是“来自独立设备的收听和观看完成率”(Apple),因此听众指的是设备。一个人同时使用手机和 CarPlay 主机,就可能被计为两个听众。
- 播放次数 — 某人按下节目播放键的次数。
- 独立听众 — 播放时长超过零秒的设备。
- 参与听众 — 播放单集时长至少达到 20 分钟或 40% 的设备。这是 Apple 用于衡量收听深度的门槛,不代表完成率;收听单集 40% 也不等于听完。
- 关注者 — 表示一个数值,而非变化量。为何这一项需要谨慎解读,请参阅关于列名。
设置
1. 获取供应商编号和访问令牌
两者都来自 Apple Podcasts 的 Reporter 端,而使用 Reporter 需要加入 Apple Podcasters Program——请参阅顶部的说明。免费的 Podcasts Connect 账户两者都没有。
已加入计划的账户可通过 Apple 的 Reporter 工具获取供应商编号和访问令牌,相关文档见 Reporter 用户指南。Reporter 的 generateToken 命令会签发访问令牌;viewToken 会显示当前令牌及其到期时间。
Apple 文档中有两项限制,值得注意:
- 每个 Apple Account 只能有一个有效令牌。 生成新令牌会立即使之前的令牌失效。如果此账户上的其他任何工具也在使用 Reporter——其他工具、同事,或你去年设置的仪表板——在这里生成令牌会悄无声息地破坏它;出现的故障与令牌过期完全相同。
- 令牌管理并非为自动化而设计。 Apple 声明,这些命令“并非用于自动化操作,访问可能会受到速率限制”,因此不要编写轮换脚本。
本节之前指向的
Settings页面并不存在。 早期版本的说明曾说,可以在 Podcasts Connect → Settings 下查找供应商编号并生成访问令牌。Podcasts Connect 没有 Settings 页面。其 Account 部分包含 People、API Keys 和 Details,但都没有供应商编号。这些说明依据 Apple 的文档编写,却从未对照产品核实。那里的 API Keys 页面是另一项功能,不能替代 Reporter 访问令牌:Apple 声明,API 密钥“允许你的托管服务提供商代表你向 Apple Podcasts 发布节目和单集,但他们无法访问你的收听分析数据。”生成 API 密钥不会给此 MCP 服务任何权限,而且创建后无法修改密钥以添加服务。
2. 构建
已发布到 npm。下面的配置片段使用 npx,首次运行时会自动获取;无需克隆。
git clone https://github.com/conorbronsdon/apple-podcasts-mcp.git
cd apple-podcasts-mcp
npm install
npm run build
3. 配置 MCP 客户端
Claude Code
添加到你的 .mcp.json:
{
"mcpServers": {
"apple-podcasts": {
"command": "npx",
"args": ["-y", "@conorbronsdon/apple-podcasts-mcp"],
"env": {
"APPLE_PODCASTS_ACCESS_TOKEN": "your-access-token",
"APPLE_PODCASTS_VENDOR_ID": "87654321"
}
}
}
}
Codex CLI
添加到 ~/.codex/config.toml:
[mcp_servers.apple-podcasts]
command = "npx"
args = ["-y", "@conorbronsdon/apple-podcasts-mcp"]
env = { APPLE_PODCASTS_ACCESS_TOKEN = "your-access-token", APPLE_PODCASTS_VENDOR_ID = "87654321" }
Claude Desktop
在 claude_desktop_config.json 中使用与 Claude Code 相同的配置片段。
MCP 服务在没有凭据的情况下也会启动,以便客户端列出其工具。之后调用工具时会失败,并提示缺少哪个变量。
如果你的令牌可以读取多个账户
APPLE_PODCASTS_ACCOUNT_ID 是可选项,大多数配置都不需要设置。Reporter 返回代码 214“此令牌可访问多个账户;请指定账户编号”时,请设置此变量——Reporter 不会替你选择账户,因此在指定账户前,每次调用都会失败。
"env": {
"APPLE_PODCASTS_ACCESS_TOKEN": "your-access-token",
"APPLE_PODCASTS_VENDOR_ID": "87654321",
"APPLE_PODCASTS_ACCOUNT_ID": "2011425"
}
它是环境变量,而不是工具参数,因为它属于凭据,而非问题的一部分:它不会因调用而变化;若将它放入每个工具的架构中,就会为一个几乎无人设置的参数浪费上下文。若只有一个账户,请将其留空——Reporter 会拒绝空账户字段,因此 MCP 服务会完全省略该字段,而不是发送空值。apple_podcasts_check_access 会回显正在使用的账户编号。
3. 验证
向你的助手询问:“检查我的 Apple Podcasts 访问权限。” 这会运行 apple_podcasts_check_access,验证令牌是否有效,并显示令牌是否可读取你的供应商编号——这两种故障从外部看起来完全相同。
每 180 天轮换令牌
Apple Reporter 访问令牌会在生成 180 天后过期。 这会导致你的配置失效,而且失效时不会有任何提示:服务会继续启动,工具也会继续列出,但每次调用都会开始失败。
令牌过期时,工具会返回:
Apple Reporter error (123) on Sales.getReport: Access token is expired. Reporter tokens
last 180 days. Generate a new one in Apple Podcasts Connect > Settings > Access Token and
update APPLE_PODCASTS_ACCESS_TOKEN.
轮换步骤:
- 按照 Reporter 用户指南,使用 Reporter 的
generateToken生成新令牌。 - 新令牌生成后,旧令牌会立即失效,因此请在能一次性更新配置时操作。
- 在所有设置过
APPLE_PODCASTS_ACCESS_TOKEN的位置替换令牌,然后重启 MCP 客户端,让它读取新的环境变量。
轮换影响整个账户,而非单个应用。 Apple 允许每个 Apple Account 只有一个有效令牌。账户上其他与 Reporter 通信的程序也会在你轮换令牌后立即开始失败,并返回此服务报告的同一错误代码 123。如果有多个程序需要访问 Reporter,它们必须共用一个令牌,并一起轮换。
设置时有两件事值得注意:
- 运行
apple_podcasts_check_access,并记录 Apple 返回的tokenExpires日期。并非每个账户都会从Sales.viewToken获得过期时间;如果没有,响应会说明这一点,你应自行记录日期。 - 设置一个第 170 天的日历提醒。轮换只需 30 秒;等到分析过程中才发现令牌已过期就太迟了。
过期(代码 123)和令牌被拒绝(代码 124)在这里属于两种不同的错误,因为修复方法不同:前者表示需要轮换,后者表示你粘贴错了令牌。
示例
你: Apple 上的节目上周表现如何?哪些单集带来了这些数据?
助手会运行两次调用。
使用 period: "Daily"、start: "2026-07-24"、end: "2026-07-30" 调用 apple_podcasts_summary:
{
"reportType": "apShowListeningWorldwide",
"period": "Daily",
"requestedRange": { "start": "20260724", "end": "20260730" },
"periodsReturned": 7,
"totals": { "plays": 8940, "uniqueListeners": 5620, "engagedListeners": 3810 },
"totalsNote": "Totals sum the flow metrics (plays, listeners, time listened) across periods. Followers is a level, not a flow, so it is reported per period in the series and is deliberately absent from totals.",
"series": [
{ "date": "20260724", "rows": 1, "metrics": { "plays": 1204, "followers": 9430 } },
{ "date": "20260725", "rows": 1, "metrics": { "plays": 1530, "followers": 9512 } }
],
"resolvedColumns": { "plays": "Plays", "followers": "Followers" }
}
然后在相同日期范围内调用 apple_podcasts_episodes,并设置 sort_by: "engagedListeners"、limit: 5:
{
"totalEpisodes": 43,
"returned": 5,
"sortedBy": "engagedListeners",
"episodes": [
{ "episodeId": "1000712346", "episodeName": "What evals actually measure",
"plays": 830, "uniqueListeners": 635, "engagedListeners": 530 }
]
}
engagedListeners 是值得关注的指标。播放次数统计开始播放的次数;互动听众统计收听时长达到 20 分钟或单集时长的 40% 的设备。如果某集播放次数领先、互动度却落后,说明人们点开了它,却没有听下去。
(以上数值仅作示例。列名取自你账户的报告,详见下一节。)
关于列名
Apple 没有公布播客收听报告的列布局,而且曾在不同报告版本之间重命名列。因此,此服务不会硬编码列名。每项指标都会通过别名表(src/tsv.ts)进行匹配,并且每个响应都会报告:
resolvedColumns— 每项指标在你的报告中实际匹配到的列。unmappedColumns— 报告中存在但未匹配到任何已知列的列。
如果 Apple 重命名了某列,apple_podcasts_summary 和 apple_podcasts_episodes 会在返回未映射列名的同时提供 schemaNote,而不是悄悄返回零值。如果你关心的指标出现在 unmappedColumns 中,请提交一个 issue,注明列名,以便将其加入别名表。
对关注者也需保持同样的谨慎。Apple 的关注者列既表示累计总数,也曾表示每个时段的数量。apple_podcasts_followers 会返回 resolvedColumn、change(最新值减去首个值)和 sumAcrossPeriods,并告知你在不同情况下应读取哪项,而不是替你猜测。
错误
Reporter 并非 REST。它会通过响应正文中的数字代码报告大多数失败,而且经常返回 HTTP 200,因此信任状态码的客户端会把错误封装解析成报告。此服务会检查响应正文。代码对应的类型化错误如下(src/errors.ts):
| 错误 | Reporter 代码 | 含义 |
|---|---|---|
TokenExpiredError | 123 | 180 天期限已到。请轮换令牌。 |
TokenInvalidError | 124、125、132、HTTP 401/403 | 令牌缺失、格式错误或遭到拒绝。 |
VendorError | 200、300 | 此令牌无法读取该供应商编号。请运行 apple_podcasts_check_access。 |
AccountError | 214、215 | 令牌关联了多个 Apple 账户,Reporter 无法自行选择;或者提供的账户编号有误。请设置 APPLE_PODCASTS_ACCOUNT_ID。 |
NoDataError | 209、211、213 | 请求有效,但该时间段没有报告。这很常见——报告会有延迟,流量较少的时间段也可能没有数据。 |
RateLimitError | 117、HTTP 429/503 | Apple 正在限流,或报告延迟。请缩小范围。 |
BadRequestError | 201–208 | 报告类型、日期类型或组合有误。 |
ReporterError | 其他任何情况 | 基类,也用于网络故障。 |
如果在范围中途发生 NoDataError,服务会处理而不是抛出:日期会记录在 missingPeriods 下,范围的其余部分仍会返回。如果整个范围都没有数据,服务会给出说明,而不是返回一页零值。
如果范围内完全没有 Reporter 日期,则会返回另一种响应。周报以该周结束的星期日作为日期,因此,周一到周五的周报范围中不包含任何报告日期,也不会向 Apple 发送请求。响应会对此作出说明,而不是把从未发出的请求归咎于 Apple 的发布延迟。
协议说明
Reporter 会发送一个 HTTP POST 请求,其中包含一个表单编码字段 jsonRequest,该字段存放一个包含令牌和带方括号命令的 JSON 文档:
POST https://reportingitc-reporter.apple.com/reportservice/sales/v1
Content-Type: application/x-www-form-urlencoded
jsonRequest={"accesstoken":"...","version":"2.2","mode":"Robot.XML",
"queryInput":"[p=Reporter.properties, Sales.getReport, 87654321,apShowListeningWorldwide,Summary,Daily,20260728]"}
版本 2.2 很重要:基于令牌的身份验证(generateToken)要求 Reporter 版本为 2.2 或更高,较旧的版本字符串会导致令牌遭到拒绝。成功获取的报告会以 gzip 压缩格式(Content-Type: application/a-gzip)返回,内容为制表符分隔文本,包含一行表头且不带引号。
设置 APPLE_PODCASTS_ACCOUNT_ID 后,account 字段会加入同一 JSON 文档。未设置时则会省略该字段:Reporter 会将空的 account 视为错误,而不是“无偏好”。
Apple 自带的客户端是一个 Java jar。此服务直接重新实现了线缆协议,因此依赖树中不包含 JVM。Apple 的参考文档:Reporter 用户指南。
开发
git clone https://github.com/conorbronsdon/apple-podcasts-mcp.git
cd apple-podcasts-mcp
npm install
npm run build
npm test
本地运行:
APPLE_PODCASTS_ACCESS_TOKEN=... APPLE_PODCASTS_VENDOR_ID=... npm start
测试会替换 fetch,并使用 src/__tests__/fixtures/ 中手工构建的测试数据运行。没有任何测试会访问 Apple。在将测试数据文件中的列名视为 Apple 的架构之前,请先阅读文件顶部的来源说明注释:这些测试数据固定了解析、聚合、日期和错误处理路径,这正是它们的用途。它们是根据 Apple 文档所述的响应格式编写的,并非从账户中捕获所得;移植此实现所依据的参考实现也不是从账户中捕获的。
发布
.github/workflows/publish.yml 会在版本号更新时使用 npm Trusted Publishing 发布。Trusted Publishing 需要在 npmjs.com 上针对每个包进行配置,因此首次发布必须手动完成(npm publish --access public),或使用细粒度访问令牌。在包创建且此仓库注册为可信发布者之前,工作流会运行并在发布步骤失败。工作流文件头部列出了相关步骤。
贡献
欢迎提交问题和拉取请求。以下三类内容尤其有帮助,按重要性排序:
- 任何来自真实账户的数据。 本服务解析的响应都尚未通过真实 Apple 数据验证——实现依据 Apple 的文档编写,测试则使用固定数据。如果你用真实供应商编号测试了它,请说明结果如何,无论是否正常。这是其他任何内容都无法弥补的缺口。
- 真实账户中的列名。 如果你关注的指标出现在
unmappedColumns中,请提供列名。无法从公开文档推导出这些信息。 - 本服务映射不准确的 Reporter 代码。 请附上代码和 Apple 的消息。
请遵守只读约定,并确保新增工具范围明确——必须指定范围和行数上限,不要输出原始数据。
关于
由 Conor Bronsdon 创建并维护。我主持 Chain of Thought 播客,内容涵盖 AI 基础设施、开发者工具,以及从业者实际如何使用这些工具。我创建这个项目,是因为 Apple 拥有对节目至关重要的收听数据,而获取这些数据唯一受支持的方式却是一个 Java jar 和一个电子表格。
配套工具:
- op3-mcp:OP3 下载分析数据——地理分布、应用和单集下载量。本工具涵盖播放量,下载量则由它提供。
- Transistor MCP:Transistor.fm 的官方 MCP 服务。提供单集、发布和分析功能。
- podcastindex-mcp:Podcast Index MCP 服务,可按人物或主题搜索、查看热门节目和 Feed 健康状况。
- podcast-benchmark:根据公开信号将你的节目与同类节目进行比较。
- ai-tools-for-creators:为以创意为生的人精选的 AI 技能和 MCP 服务列表。
更多信息请访问 chainofthought.show,或关注 X。
免责声明
这是一个独立的个人项目,与 Apple Inc. 无关,未获其赞助或认可。文中所有观点均为我个人观点。
许可证
Apache-2.0
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。