关于 app-store-connect-mcp
app-store-connect-mcp 面向管理 Apple 应用的团队,提供 App Store Connect 和 App Store Server API 的 MCP 接口。它结合端点搜索、分级读写、敏感写入确认及 StoreKit 2 签名验证。
主要功能
- 01搜索并查看 API 操作说明
- 02分离读取与写入工具
- 03敏感写入要求确认
- 04组合常见的多步 API 流程
- 05验证 StoreKit 2 签名
- 06提供资源和斜杠命令工作流
适用场景
- 01检查应用发布准备情况
- 02查看或调整应用定价
- 03上传 App Store 截图
- 04获取分析与订阅数据
MCP 相关
此服务通过 MCP 工具、资源和工作流开放 Apple API 操作。MCP 客户端可搜索端点并执行读取或写入;高风险写入可要求操作人员确认。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @abd3lraouf/app-store-connect-mcpASC_KEY密钥keychain:<service> (recommended), or a path to your AuthKey .p8ASC_ISSUER_IDIssuer ID. Not needed if stored in the keychain envelope.ASC_KEY_ID密钥API key ID. Not needed if stored in the keychain envelope.ASC_BUNDLE_IDRequired for App Store Server API calls and to verify Apple's signatures.ASC_APP_APPLE_IDNumeric Apple ID. Apple requires it to verify Production signatures.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
13收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
App Store Connect MCP 服务
让 Claude 使用你的 App Store Connect 账户,而不把定价权限交给它。 一个覆盖 App Store Connect API 和 App Store Server API (StoreKit 2)的 MCP 服务——通过 13 个工具提供 1,293 项操作,适用于 Claude Code、Claude Desktop、 Cursor 以及任何支持模型上下文协议的产品。
1,293 operations · 13 tools · key never on disk · Apple signatures verified
flowchart LR
A["Claude<br/>Cursor · any MCP client"] -->|"search · call · write"| B["app-store-connect-mcp<br/>13 tools"]
B --> C{"risk tier"}
C -->|"READ · 811 ops"| D["Apple<br/>App Store Connect API"]
C -->|"WRITE · 482 ops"| E["ask a human first"]
E -->|approved| D
E -->|declined| F["nothing is sent"]
B --> G["App Store Server API<br/>StoreKit 2 · signatures verified"]
style E fill:#ffe8b3,stroke:#c98a00,color:#000
style F fill:#ffd6d6,stroke:#c00,color:#000
style D fill:#d6f5d6,stroke:#2a2,color:#000
style G fill:#d6f5d6,stroke:#2a2,color:#000
别安装这个
真的。消磨下午时光有更便宜的方式,以下几类人现在就该关掉这个标签页:
你想要一个只管办事的 Agent。 它会停下来,在更改价格、删除内容或更改账户访问权限前征求同意——而且问的是你,不是它自己。如果你觉得这很碍事,确实如此。这就是它的设计。
你想让每个端点都成为独立工具。 有些服务会注册 890 个工具。你的服务还没回答一个问题,光工具定义就会占用六位数的上下文。这个服务只注册 11 个工具,其余操作通过搜索查找。
tool definitions loaded into context, before you ask anything
one tool per endpoint ███████████████████████████████████ >100k tokens
this server ▌ ~1k tokens
你用的是 Windows 或 Linux,却想用 Keychain。 Keychain 存储仅支持 macOS。其他系统可以使用文件路径,但这个工具最适合 macOS 环境。
你想让它帮你撰写 App Store 文案。 它会获取你的评论和本地化内容,但不会凭空编写营销文案并发布,也没有任何选项可以让它这么做。
你打算将它用于商业产品。 请先阅读许可协议。内部使用免费,但转售不行。
还在继续看?那接下来的内容大概适合你。
它拒绝做的事
这里大部分工程工作都用在克制上,因此从这里开始最坦诚。
它不会运行生成的代码。 覆盖庞大 API 的优雅方式,是让模型编写 JavaScript,再在沙箱中 eval。Node 的 vm 不是沙箱——它自己的文档也这么说——而任何传入的宿主对象都会通过原型链泄露整个运行环境:
spec.constructor.constructor('return process.env.HOME')() // → /Users/you
这是对一个真实上线的 MCP 服务沙箱的复现,它会返回你的主目录。15 秒超时也无济于事:它只限制同步代码,因此 async 循环会永远运行。此服务分发的是参数,而不是代码。覆盖范围相同,令牌成本相同,没有任何东西可供逃逸。
它不会让写入操作伪装成读取操作。 读取和写入是独立的工具。asc_write 携带 _meta["anthropic/requiresUserInteraction"],Claude Code 即使在 bypassPermissions 模式下也会遵守。模型无法花言巧语绕过它;只有操作人员可以通过使用 --no-confirm 启动服务来做到这一点——这会同时移除标志、提示和令牌,适用于无人值守的运行。
它不会替你决定定价意图。 preserve_current_price 是必填参数,没有默认值。Apple 将其默认设为 false——这意味着现有订阅者会被转移到新价格。将其设为必填,可以让这个决定明确呈现出来,供人查看。
它不会为了回答一个问题而创建持续义务。 获取分析数据需要报告请求,而 accessType: ONGOING 是你账户上的持续义务,不是查询。该工具会读取报告;不会悄悄创建报告。
它不会假装已清理你的评价。 客户评价由陌生人撰写,并会原样进入模型的上下文。包含评价内容的结果会首先附上说明,指出这些内容是需要报告的数据,而不是要遵循的指令。它有意不筛除注入短语——攻击者会不断迭代这种对抗游戏,而通过这类筛选会让人误以为它能提供实际上无法保证的安全性。
它不会在未检查的情况下告诉你签名没问题。 请见下文。
安装
Claude Code,一行命令:
claude mcp add --scope user app-store-connect \
--env ASC_KEY=keychain:my-asc-key \
--env ASC_BUNDLE_ID=com.example.app \
--env ASC_APP_APPLE_ID=1234567890 \
-- npx -y @abd3lraouf/app-store-connect-mcp
无需克隆或构建。或者,如果你想先阅读源码,也可以从源码安装:
git clone https://github.com/abd3lraouf-studios/app-store-connect-mcp
cd app-store-connect-mcp && npm install && npm run build
或者,适用于 Claude Desktop、Cursor 等:
{
"mcpServers": {
"app-store-connect": {
"command": "npx",
"args": ["-y", "@abd3lraouf/app-store-connect-mcp"],
"env": {
"ASC_KEY": "keychain:my-asc-key",
"ASC_BUNDLE_ID": "com.example.app",
"ASC_APP_APPLE_ID": "1234567890"
}
}
}
}
然后询问它 “检查 App Store Connect 连接”——这会运行 asc_status,通过一个轻量级请求验证你的凭据,并在有任何缺失时准确告诉你缺少什么。
你的密钥应存放在 Keychain 中
Apple 只允许你下载 .p8 一次。磁盘上的明文副本就是一份可能泄露的副本。
ASC_KEY=keychain:my-asc-key # recommended
ASC_KEY=/path/to/AuthKey.p8 # works, but plaintext
ASC_PRIVATE_KEY='-----BEGIN…' # discouraged: ps -E exposes it
将其存储为 base64 JSON,让标识符与密钥材料一同保存——这样 ASC_KEY_ID 就不会与它所标识的密钥不同步;这种不匹配只会以含糊的 401 错误显现:
security add-generic-password -s my-asc-key -a api -w "$(
jq -nc --arg i "$ISSUER" --arg k "$KEYID" --arg p "$(cat AuthKey.p8)" \
'{issuerID:$i,keyID:$k,privateKeyPEM:$p}' | base64
)"
十三种工具
五种核心工具,涵盖所有操作:
| 工具 | |
|---|---|
asc_status | 凭据、连通性、剩余速率限制额度。出现任何故障时,先运行此工具——它能区分是密钥错误还是请求错误。 |
asc_search_endpoints | 按关键词、方法、标签或风险等级搜索两个 API 中的 1,293 个操作。 |
asc_describe_endpoint | 参数、包含真实字段名称的请求体架构、风险等级。 |
asc_call | **读取。**路径和查询参数、分页,支持两个 API。 |
asc_write | **所有会更改数据的操作。**需确认,支持 dry_run。 |
八种复合工具,用于原始 API 无法通过单次调用完成的链式操作。仅仅省去一次请求的工具不会纳入——它们需要永远跟上 Apple 的变化,而且并未提供 asc_call 不具备的功能:
| 工具 | 合并的操作 |
|---|---|
asc_pricing_get | 将约 175 次查询合并为少数几次,适用于订阅和一次性购买。币种属于销售地区,而非价格行,所以手动读取价格会得到含糊的数字。 |
asc_pricing_set | 相同的操作链,再加上写入,并明确要求做出订阅者决策。 |
asc_preflight_version | 六种资源 → GO / NO-GO,每个缺项都会标明可修复它的操作。 |
asc_listing_screenshots | 每个地区一个请求 → 四次,通过 included 实现。 |
asc_upload_screenshot | Apple 的预留 → 按偏移量 PUT → 使用 MD5 提交的流程,跨越两个主机。 |
asc_upload_iap_screenshot | 为应用内购买的审核截图执行相同流程——这是导致 IAP 一直处于 MISSING_METADATA 状态的那个字段。 |
asc_availability_set | 每个销售地区执行一次 PATCH(最多 175 次;Apple 没有批量端点),然后重新读取每个地区,并报告哪些操作未生效。 |
asc_analytics_report | 五个步骤 → 签名 URL → gunzip → 数据行,并拼接所有分段。 |
为什么 asc_upload_screenshot 无法通过一次 API 调用完成
Apple 的资源流程跨越两个主机,最后还要校验校验和;如果校验和有误,流程会静默失败——上传会一直停在 AWAITING_UPLOAD,看起来就像什么也没发生。uploadOperations 在 Apple 的 OpenAPI 文档中仅作为 fields[] 枚举中的一个值出现,因此 Agent 读取规范时,虽然能看到这个字段,但仍无法知道必须对它执行操作。
sequenceDiagram
participant M as Claude
participant S as this server
participant A as App Store Connect
participant U as Apple asset host
M->>S: asc_upload_screenshot(set, file)
S->>A: POST /v1/appScreenshots (fileName, fileSize)
A-->>S: id + uploadOperations[]
loop each byte range
S->>U: PUT bytes at offset, Apple's headers
Note over S,U: pre-signed URL — no bearer token sent
end
S->>A: PATCH uploaded=true + MD5 checksum
A-->>S: assetDeliveryState
S-->>M: state, and how to clean up if it failed
此外,还有四种资源(@asc:cookbook、@asc:enums、@asc:risk、@asc:sources)和通过斜杠命令调用的四个工作流:
/mcp__asc__release-readiness、pricing-audit、review-triage、
testflight-status。
写入安全
HTTP 方法并不能很好地代表操作后果。PATCH /v1/subscriptionPrices
和 PATCH /v1/appInfos/{id} 都是写入操作;只有其中一个会改变客户的
收费金额,而且重复执行都无法撤销。因此,每项操作都有一个等级(数量
统计自 App Store Connect;StoreKit 2 另增加 14 个读取操作和 16 个写入操作):
| 等级 | 数量 | |
|---|---|---|
READ | 797 | 不会产生更改。 |
WRITE | 238 | 会更改数据。 |
REVENUE | 61 | 定价、订阅、权益。 |
DESTRUCTIVE | 132 | 删除操作。 |
RELEASE | 12 | 构建、提交、发布内容。 |
ACCESS | 12 | 谁可以访问账户。 |
INFRASTRUCTURE | 11 | 证书、标识符、回调 URL。 |
flowchart TD
A["asc_write called"] --> B{"--read-only?"}
B -->|yes| Z["blocked"]
B -->|no| N{"--no-confirm?"}
N -->|yes| S["send it"]
N -->|no| C{"risk tier"}
C -->|"WRITE"| S["send it"]
C -->|"REVENUE · DESTRUCTIVE<br/>INFRASTRUCTURE · ACCESS · RELEASE"| D{"client supports<br/>elicitation?"}
D -->|yes| E["ask the person<br/>method · path · body · tier"]
D -->|no| F["issue a token<br/>hash-bound to this exact request"]
E -->|accepted| S
E -->|declined| Z
F --> G["caller repeats the call<br/>with the token"]
G --> S
style Z fill:#ffd6d6,stroke:#c00,color:#000
style E fill:#ffe8b3,stroke:#c98a00,color:#000
style F fill:#ffe8b3,stroke:#c98a00,color:#000
style S fill:#d6f5d6,stroke:#2a2,color:#000
等级最低的五类操作会在运行前询问确认。如果你的客户端支持征询, 它会直接向你询问,并显示方法、路径、请求体和等级。否则,它会发放一个 确认令牌,该令牌通过哈希绑定到确切的操作、路径、查询参数和请求体—— 因此,为低风险调用获取的令牌不能用于高风险调用。声称支持征询却未能 完成征询的客户端会回退处理,而不会直接放行。
--read-only block every write --confirm confirm every write
--no-confirm never confirm (default) confirm the five tiers above
dry_run: true report the exact request without sending it (a parameter of asc_write)
--no-confirm 是无人值守模式,而且是完全无人值守:不会弹出征询提示,
不会要求确认令牌,写入工具也不再声明
requiresUserInteraction,因此 Claude Code 也不会因此暂停。否则,无人值守运行
就会拿到无法回应的确认请求。
签名验证
解码 JWS 能告诉你字节内容是什么。验证则能告诉你这些内容确实由 Apple 签署。在这里,这一区别比大多数场景都重要,因为这些载荷是判断 “此人是否为付费订阅者?”的证据——而解码后未经验证的交易,恰恰就是伪造 交易的样子。
每个签名字段都会根据 Apple Root CA - G3 进行检查;该证书随附在
certs/ 中,因此网络故障不会导致验证被关闭。证书链验证、过期检查、吊销检查
以及 Bundle 和环境检查都交由 Apple 自己的库处理,因为这些环节正是看似合理的
实现会接受恶意输入的地方。
验证结果按字段分别给出,而不是按响应整体给出——在两百条历史记录中 出现一个错误签名,才是需要关注的情况:
"signedTransactionInfo_decoded": { "productId": "premium.monthly" },
"signedTransactionInfo_verification": { "verified": true }
无法运行验证时,载荷仍会解码,且每个字段都会说明这一情况。 保持沉默才是危险的结果。
对比
| 方案 | 保留的优势 | 不足之处 | |
|---|---|---|---|
| 手动封装的工具 | 每个端点对应一个工具 | 参数有类型,易于发现 | 70–900 个工具定义、超过 100k 个 token;Apple 一发布新版本就会过时 |
| Code Mode | 模型编写 JS,服务端通过 eval 执行 | 两个工具、约 1k 个 token、全面覆盖 | 在持有签名密钥的进程中运行生成的代码 |
| 元工具 | search → 使用参数进行 call | 同样节省上下文,不执行代码 | — |
该致谢时就致谢:这里有几个想法改编自阅读 erayendes/app-store-connect-mcp 和 TrialAndErrorAI/appstore-connect-mcp 时获得的启发。没有复制代码。Heimdall 尤其是这个领域中开发最完善的服务; 如果你需要 890 个按配置文件整理的类型化工具,请改用它——它很好, 只是采用了不同的权衡。
验证依据
声明很容易。以下内容都可以核查:
378 tests · 90% line coverage · offline, no credentials, runs on every PR
- 签名验证的两个方向。 一个拒绝所有内容的验证器看起来和正确的验证器一样可靠,因此,生成一条包含验证器要求的两个 Apple OID 的证书链,可以证明它会走接受路径;而伪造、篡改、错误 Bundle 和错误环境的负载都会被拒绝。
- 协议版本是实测得出的,而非想当然。 Claude Code 2.1.235 协商使用 MCP
2025-11-25,并声明了elicitation——我们让它连接到探测服务并记录了结果。这就是此处继续使用 SDK v1 的原因:v2 软件包实现的是 2026-07-28,该版本用 MRTR 取代了 elicitation,而正是 elicitation 让asc_write能够询问用户。 - **使用 MSW,而非 nock,**进行 HTTP 模拟——
nock会修补node:http,而 Node 的全局fetch使用 undici,完全绕过它。因此它实际上什么也拦截不到,而且不会发出任何提示。 - 有一项测试会启动真实二进制文件,并断言每一行标准输出都能解析为 JSON,因为只要多出一条
console.log,就会破坏 JSON-RPC 通道,而任何进程内测试框架都无法发现这一问题。
npm test # 378 tests, offline
npm run verify # 14 read-only checks against the live APIs
npm run fetch:specs # re-download both API descriptions from Apple
紧跟 Apple 的更新
覆盖范围取决于 Apple 的规范,而不是有人来得及封装多少个端点。
- App Store Connect——1,263 个操作,规范 v4.4.1。Apple 发布了 OpenAPI 文档;我们会下载并编译成精简索引(360KB,而原始规范为 3.3MB)。
- App Store Server——30 个操作。Apple 没有为此发布 OpenAPI 文档,因此我们会从 Apple 自己的客户端库中解析端点集合,并固定在指定的发布标签上;每次运行
verify时,都会将其与此仓库的目录进行差异比较。 - 枚举表均由生成器生成,共 90 张。其他地方广为转载的一份指南列出了 Apple 并不存在的
eventState值,还漏掉了两个实际存在的值;通过生成枚举表,这里就不可能出现这种问题。 - 每周运行的任务会重新获取这两者;如果 Apple 有所变更,就会创建一个分支。
传输方式
node dist/index.js # stdio (default)
node dist/index.js --transport http --http-token "$(openssl rand -hex 32)"
HTTP 仅绑定到回环地址,没有 Bearer 令牌就拒绝启动。它还会验证 Host 和 Origin:否则,浏览器页面可以将绑定到回环地址的服务视为同源并访问它,而仅凭令牌无法防御这种情况。
Docker 使用 distroless 镜像构建,并以非 root 用户运行。注意,stdio 需要使用 docker run -i,且不得加上 -t——TTY 会破坏 JSON-RPC 流。
技能
服务可以回答问题,但无法阻止模型从正确答案中得出错误结论——例如,由于地区写成了 US 而不是 USA,结果列表为空;把三十条记录中的一页当作整个账户;或者对销售一次性购买项目的应用声称“没有订阅”。这些情况都没有错误可捕获,因为响应状态是 200。
这类判断封装成了 Claude Code 技能:
npx -p @abd3lraouf/app-store-connect-mcp asc-mcp-skill
它会安装到 ~/.claude/skills/app-store-connect(使用 --scope project 可安装到 ./.claude/skills;使用 --link 可通过符号链接关联一个检出目录,使编辑实时生效)。它不会向 settings.json 添加任何内容。
该技能列出的是在得出结论之前要执行的检查,而非 API 导览。凡是可以推导出来的内容,它都不会手动复制——没有枚举表,也没有端点列表;并且有一项测试会断言,其中的每个工具名称、资源 URI、提示词和枚举形态的值,都仍可追溯到 src/ 或 Apple 的规范。
失败记录
如今,失败只存在于对话记录中的工具结果里。对话结束后,Apple 的 x-request-id——Apple 支持团队会索要的唯一值——也会随之消失,模型尝试过哪些操作却未能找到所需内容的证据同样如此。
现在,两部分都会写入 failures.jsonl:服务会记录自己的 HTTP、网络和被吞掉的失败,技能则记录服务看不到的失败,也就是以 200 状态码返回的解读失败。
npm run triage # what keeps failing, and what the cookbook never warned about
写入位置依次如下:如果设置了 ASC_FAILURE_LOG_DIR,则写入该目录(不会再写入其他位置——显式指定的目标却悄悄变成另一个位置,还不如没有目标);否则写入此软件包的工作检出目录,即包含 src/ 和 .git/ 的目录,而 npm pack 不会发布这两个目录;否则写入已安装技能自身的目录;最后写入 ~/.claude。
如果机器上既没有检出目录,也没有已安装的技能,除非 ASC_FAILURE_LOG=1 明确启用,否则不会写入任何内容。ASC_FAILURE_LOG=0 会在所有位置禁用日志记录。
绝不会写入的内容:请求头或请求正文——只记录正文的键名,因为 appStoreReviewDetails 的纯文本正文中包含有效的 demoAccountPassword。响应内容会精简为 Apple 的错误对象。预签名资源 URL 会记录为主机名,因为签名位于路径中。JWT、Bearer 令牌、PEM 区块和电子邮件地址的本地部分会作为第二道防线进行脱敏。
记录会通过 O_APPEND 描述符以单次、有大小限制的写入追加,因此服务和技能可以共用一个文件,无需加锁。这项保证依赖 POSIX,在 NFS 上不成立——请将 ASC_FAILURE_LOG_DIR 指向本地磁盘。
已知限制
坦诚说明这些限制,因为你迟早会发现它们:
- 风险级别是根据方法和路径进行模式匹配的,这种方式刻意保持谨慎,但仍是启发式判断。执行写入前,请先阅读
asc_describe_endpoint。 - 钥匙串存储仅适用于 macOS。 在其他系统上,请使用权限受限的文件路径。
--no-confirm会禁用所有关卡——令牌、征询和requiresUserInteraction标志。此选项供 CI 和无人值守的 Agent 使用;只要有人在场,就不适合作为默认设置。--no-online-checks会跳过 OCSP 检查,这意味着会接受已撤销的证书。- 失败日志的无锁追加依赖
O_APPEND的原子性,而网络文件系统不保证这一点。npm run triage会跳过被截断的行,而不是报错,但网络挂载可能导致记录丢失。 - 签名的接受路径已通过替换信任锚进行验证,而非使用 Apple 的信任锚——要获得真正由 Apple 签名的负载,需要真实的客户交易。证书链逻辑使用的是 Apple 自己的库。
发布
更新版本号、合并,完成。两个注册表都使用工作流自身的 OIDC 身份进行身份验证,因此无需轮换令牌,也无需记住标签:
npm run release:version patch # or minor, major, or an exact version
git commit -am "Release v1.0.1" && git push
CI 会检测尚未发布到 npm 的版本,运行完整的检查门禁,然后发布到 npm 和 MCP Registry、为提交打标签,并创建 GitHub Release。触发条件是版本号而非标签,因此任务具有幂等性——重新运行不会发布任何内容。
许可证
Business Source License 1.1。可免费用于内部使用、评估和开发;若要将其作为托管或嵌入式服务提供给第三方,或将其重新分发到商业产品中,则需要获得许可。该许可证将于 2030-08-19 转为 Apache-2.0。
此处随附的 Apple OpenAPI 描述和根证书遵循 Apple 的条款,而非本许可证——请参阅 NOTICE。
Apple、App Store、App Store Connect、StoreKit 和 TestFlight 是 Apple Inc. 的商标。本项目与 Apple 无关。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。