AppStore MCP Server
Servidor MCP (Rust, rmcp) que expõe a API Apple App Store Connect — apps, compras dentro do app, assinaturas, preços, versões/metadados, TestFlight, provisionamento e uploads de assets, além de ferramentas genéricas JSON:API.
Documentação
appstore-mcp
Um servidor MCP, escrito em Rust, que expõe a API do Apple App Store Connect para agentes de IA. Ele cobre todo o ciclo de vida do produto — apps e metadados, compras dentro do app, assinaturas e suas ofertas, preços e disponibilidade, versões da App Store, envio para análise da App Store, TestFlight, provisionamento e assinatura, uploads de assets, compras promovidas, avaliações de clientes, lançamento faseado, usuários e acesso, eventos no app, Xcode Cloud e relatórios de análise — em 114 ferramentas, e pode alcançar qualquer outro endpoint do App Store Connect por meio de duas ferramentas genéricas JSON:API.
Construído sobre o SDK oficial rmcp via stdio.
📖 Referência completa de ferramentas → docs/TOOLS.md — a finalidade e os parâmetros de cada ferramenta.
Cada ferramenta é rotulada com anotações MCP, para que um cliente possa distinguir list_apps
de remove_user. Você pode servir apenas os domínios que precisa (ASC_TOOLS) ou apenas
as ferramentas que não podem gravar (ASC_READ_ONLY) — veja
Escolhendo quais ferramentas servir.
Design: cobertura híbrida
A API do App Store Connect tem centenas de endpoints, mas é uniformemente JSON:API. Em vez de uma ferramenta por endpoint, este servidor é híbrido:
- Ferramentas selecionadas (112) para os fluxos de trabalho comuns, de várias etapas ou propensos a erros — apps e metadados, compras dentro do app, assinaturas e ofertas, versões, preços, disponibilidade, envio para análise da App Store, TestFlight, provisionamento, uploads de assets, compras promovidas, avaliações de clientes, lançamento faseado, usuários, eventos no app, Xcode Cloud, relatórios de análise e páginas de produto personalizadas.
- Duas ferramentas genéricas de escape —
appstore_requesteappstore_list— que podem chamar qualquer endpoint com documentos JSON:API brutos.
Ferramentas
| Grupo | Ferramentas |
|---|---|
| Genéricas | appstore_request, appstore_list |
| Apps e metadados | list_apps, get_app, update_app, list_app_infos, update_app_info, set_age_rating, create_app_info_localization, update_app_info_localization |
| Compras dentro do app (v2) | list_in_app_purchases, create_in_app_purchase, update_in_app_purchase, delete_in_app_purchase, create_iap_localization, set_iap_price_schedule, upload_iap_review_screenshot |
| Assinaturas | list_subscription_groups, create_subscription_group, create_subscription, update_subscription, create_subscription_localization, set_subscription_price |
| Versões e metadados | list_app_store_versions, create_app_store_version, create_version_localization, update_version_localization |
| Envio para análise da App Store | create_review_submission, add_review_submission_item, submit_review_submission, list_review_submissions, submit_in_app_purchase, set_app_review_detail, create_app_encryption_declaration, assign_build_encryption_declaration |
| Preços | list_territories, list_iap_price_points, list_subscription_price_points |
| Disponibilidade | set_iap_availability, set_subscription_availability, set_app_availability |
| TestFlight | list_builds, list_beta_groups, create_beta_group, add_beta_tester, submit_build_for_beta_review, set_build_test_notes, set_build_beta_detail, set_beta_app_review_detail, expire_build, add_build_to_beta_group |
| Provisionamento e assinatura | list_bundle_ids, create_bundle_id, enable_bundle_id_capability, disable_bundle_id_capability, list_certificates, create_certificate, list_devices, register_device, list_profiles, create_profile |
| Assets | upload_app_screenshot, upload_app_preview, create_screenshot_set, create_preview_set, delete_screenshot_set, delete_preview_set, reorder_screenshots |
| Ofertas de assinatura | create_introductory_offer, create_promotional_offer, create_winback_offer, list_winback_offers |
| Códigos de oferta | create_offer_code, generate_one_time_use_codes, create_custom_offer_code, list_offer_codes |
| Compras promovidas | create_promoted_purchase, update_promoted_purchase, set_promoted_purchase_order, list_promoted_purchases |
| Avaliações de clientes | list_customer_reviews, respond_to_review, delete_review_response |
| Lançamento faseado | start_phased_release, update_phased_release |
| Usuários e acesso | list_users, invite_user, update_user, remove_user |
| Eventos no app | create_app_event, create_app_event_localization, upload_app_event_screenshot |
| Xcode Cloud | list_ci_products, list_ci_workflows, start_ci_build, get_ci_build_run, list_ci_build_actions |
| Relatórios de análise | request_analytics_report, list_analytics_reports, list_analytics_report_instances, list_analytics_report_segments, download_analytics_segment |
| Páginas de produto personalizadas | list_custom_product_pages, get_custom_product_page, create_custom_product_page, update_custom_product_page, delete_custom_product_page, list_custom_product_page_versions, create_custom_product_page_version, list_custom_product_page_localizations, create_custom_product_page_localization, update_custom_product_page_localization, create_cpp_screenshot_set, create_cpp_preview_set |
Consulte docs/TOOLS.md para a descrição e os parâmetros de cada ferramenta. As imagens
de páginas de produto personalizadas são enviadas com as ferramentas existentes upload_app_screenshot / upload_app_preview.
Instalação
Binários pré-compilados para macOS (universal), Linux (x86-64) e Windows (x86-64) são anexados a cada Release do GitHub. Escolha o canal para o seu cliente; todos precisam de credenciais (veja Credenciais).
Claude Desktop — pacote de um clique
Baixe appstore-mcp.mcpb da versão mais recente e abra-o com o Claude Desktop
(Configurações → Extensões → Instalar Extensão…, ou arraste o arquivo para a janela).
Ele solicita seu Issuer ID, Key ID e arquivo de chave .p8. O pacote inclui
os binários das três plataformas e seleciona o correto automaticamente.
Claude Code — marketplace de plugins
/plugin marketplace add forgeopslabs/appstore-mcp
/plugin install appstore-mcp@forgeopslabs
O plugin executa o binário appstore-mcp do seu PATH, então instale-o primeiro —
baixe o binário para o seu sistema operacional na versão mais recente
e coloque-o no seu PATH, ou cargo install --git https://github.com/forgeopslabs/appstore-mcp.
Defina ASC_ISSUER_ID, ASC_KEY_ID e ASC_PRIVATE_KEY_PATH no ambiente a partir do qual você inicia
o Claude Code.
Codex
O Codex configura servidores MCP diretamente (sem marketplace). Com appstore-mcp no seu PATH:
codex mcp add appstore \
--env ASC_ISSUER_ID=... --env ASC_KEY_ID=... \
--env ASC_PRIVATE_KEY_PATH=/path/AuthKey_XXXXXX.p8 \
-- appstore-mcp
ou em ~/.codex/config.toml:
[mcp_servers.appstore]
command = "appstore-mcp"
args = []
env = { ASC_ISSUER_ID = "...", ASC_KEY_ID = "...", ASC_PRIVATE_KEY_PATH = "/path/AuthKey_XXXXXX.p8" }
MCP Registry
Publicado como io.github.forgeopslabs/appstore-mcp (metadados em
server.json) para que qualquer cliente compatível com MCP possa descobri-lo.
A partir do código-fonte
cargo build --release # -> target/release/appstore-mcp
Credenciais
Gere uma Team Key no App Store Connect → Usuários e Acesso → Integrações →
API do App Store Connect e baixe o arquivo .p8. Em seguida, defina:
| Variável | Obrigatória | Descrição |
|---|---|---|
ASC_ISSUER_ID | ✅ | UUID do emissor mostrado acima da tabela de chaves. |
ASC_KEY_ID | ✅ | O Key ID da chave da API. |
ASC_PRIVATE_KEY | um de | Conteúdo PEM inline do .p8. |
ASC_PRIVATE_KEY_PATH | um de | Caminho para o arquivo .p8 baixado. |
ASC_BASE_URL | opcional | Substitui a origem da API. |
ASC_LOG | opcional | Filtro de log (para stderr). Padrão info. |
Consulte .env.example. O servidor autentica cada solicitação com um
JWT ES256 de curta duração assinado pela sua chave (armazenado em cache e renovado automaticamente).
O servidor inicia mesmo sem credenciais para que um cliente possa listar suas ferramentas; as chamadas de ferramentas então retornam um erro de configuração acionável até que as credenciais sejam definidas.
Escolhendo quais ferramentas servir
Cem definições de ferramentas custam contexto em cada sessão, e um cliente que vê uma lista plana não consegue distinguir uma leitura de uma exclusão. Dois controles resolvem isso:
| Variável | Padrão | Descrição |
|---|---|---|
ASC_TOOLS | todos | Grupos de ferramentas separados por vírgula para servir, ou o preset core. |
ASC_READ_ONLY | 0 | Serve apenas ferramentas que não podem modificar a conta. |
ASC_TOOL_DISCOVERY | 0 | Expõe apenas search_tools, get_tool_details e call_discovered_tool; as ferramentas de domínio filtradas permanecem disponíveis por meio da descoberta. |
ASC_TOOLS=core # 41 tools: generic, apps, versions, assets, testflight, submission
ASC_TOOLS=testflight,provisioning # just what a build-distribution agent needs
ASC_READ_ONLY=1 # 35 read-only tools; writes are withheld entirely
ASC_TOOL_DISCOVERY=1 # 3 visible tools; discover domain tools on demand
Grupos: generic, apps, iap, subscriptions, versions, pricing,
availability, submission, testflight, provisioning, assets, offers,
offer-codes, promotions, reviews, users, events, xcode-cloud,
analytics, custom-product-pages — além de all e core. Um nome não reconhecido
gera um aviso no stderr e não serve nada, em vez de silenciosamente voltar a servir
tudo.
No modo somente leitura, appstore_request é mantido, mas recusa qualquer método diferente de
GET, para que a saída de escape ainda alcance endpoints sem uma ferramenta selecionada sem
se tornar uma forma de contornar a restrição.
Cada ferramenta servida anuncia anotações MCP (readOnlyHint, destructiveHint,
idempotentHint), que os clientes usam para decidir o que precisa de confirmação. Nove ferramentas
são marcadas como destrutivas: as sete ferramentas delete_*/remove_*, expire_build,
disable_bundle_id_capability e appstore_request (que podem alcançar qualquer
endpoint DELETE).
Modo de descoberta. Pesquise por tarefa, inspecione o esquema completo de entrada
e as anotações de segurança de uma ferramenta correspondente e, em seguida, passe seu nome e argumentos exatos para
call_discovered_tool. ASC_TOOLS e ASC_READ_ONLY filtram o catálogo
privado antes da pesquisa ou execução. Chamadas diretas a nomes de ferramentas ocultas falham.
Isso é descoberta no lado do servidor: os esquemas inspecionados aparecem nos resultados das ferramentas, não como
novas ferramentas MCP de primeira classe injetadas pelo host.
A ferramenta de execução genérica é marcada como destrutiva sempre que as gravações estão habilitadas;
os hosts não podem aplicar regras de aprovação distintas a cada ferramenta oculta. Inspecione a
ferramenta subjacente e aprove as gravações antes de chamá-la. O modo padrão preserva
a superfície de ferramentas anotadas individualmente existente.
Ajustes
Os padrões são escolhidos para que uma chamada de ferramenta não trave e uma única resposta não sobrecarregue o contexto de um agente. Todos são opcionais.
| Variável | Padrão | Descrição |
|---|---|---|
ASC_TIMEOUT_SECS | 60 | Tempo limite de toda a solicitação. 0 desativa. |
ASC_CONNECT_TIMEOUT_SECS | 10 | Tempo limite de conexão. 0 desativa. |
ASC_TRANSFER_TIMEOUT_SECS | 300 | Tempo limite para uploads de assets e downloads de relatórios. |
ASC_MAX_RETRIES | 3 | Tentativas após a primeira tentativa. 0 desativa. |
ASC_MAX_RESPONSE_BYTES | 60000 | Limite de tamanho do resultado da ferramenta. 0 desativa. |
ASC_COMPACT_RESPONSES | 1 | Remove links JSON:API redundantes das respostas. |
Tentativas. Um 429 é reproduzido para qualquer método, pois a Apple rejeitou a solicitação
sem aplicá-la. Um 5xx ou um tempo limite no meio da solicitação é reproduzido apenas para
GET/PATCH/PUT/DELETE — nunca POST, que poderia criar um
recurso duplicado (e a Apple reserva permanentemente identificadores como um ID
de produto). O backoff é exponencial com jitter e respeita Retry-After.
Formatação de resposta. Os resultados são serializados de forma compacta — JSON indentado medido
1,72× os bytes para conteúdo idêntico, então o mesmo orçamento agora carrega cerca de 40%
mais dos dados que você solicitou. Links self por recurso e relacionamentos
apenas com link são removidos: nenhum conteúdo endereçável é perdido, e links.next
sobrevive para paginação. Se uma resposta ainda exceder o orçamento, included é
removido primeiro, depois os itens data finais, e o resultado carrega uma chave _truncated
informando o que foi omitido e como restringir a consulta. Observe que seguir
links.next após um corte pularia os itens removidos — solicite novamente com um
limit menor.
Build e execução
cargo build --release
ASC_ISSUER_ID=... ASC_KEY_ID=... ASC_PRIVATE_KEY_PATH=/path/AuthKey_XXX.p8 \
./target/release/appstore-mcp
O servidor fala MCP via stdio. Os logs vão para stderr; o stdout é o canal do protocolo.
Uso com um cliente MCP
Exemplo de configuração de cliente (por exemplo, o mcpServers do Claude Desktop):
{
"mcpServers": {
"appstore": {
"command": "/absolute/path/to/appstore-mcp/target/release/appstore-mcp",
"env": {
"ASC_ISSUER_ID": "00000000-0000-0000-0000-000000000000",
"ASC_KEY_ID": "ABCD123456",
"ASC_PRIVATE_KEY_PATH": "/absolute/path/to/AuthKey_ABCD123456.p8"
}
}
}
}
Inspecionar com o MCP Inspector
npx @modelcontextprotocol/inspector ./target/release/appstore-mcp
Notas de uso
- IDs são opacos. Liste/obtenha primeiro para resolver IDs de app, IAP, assinatura, conjunto e ponto de preço, depois passe-os para as ferramentas de criação/atualização.
- Precificação exige um ponto de preço. Use
list_iap_price_points/list_subscription_price_pointspara obter oidparaset_iap_price_schedule/set_subscription_price. - Uploads de assets (
upload_*) usam um caminho de arquivo local e executam o fluxo completo de reserva → upload em partes → commit MD5 em uma única chamada. O arquivo é transmitido em fluxo, então o pico de memória é uma parte, não o tamanho do asset, e uma parte que falha é tentada novamente isoladamente. Capturas de tela/prévias exigem umappScreenshotSet/appPreviewSetexistente; crie-os com as ferramentas genéricas se necessário. - Paginação.
appstore_listretorna uma página por padrão. Passemax_pages(até 20) para seguirlinks.nexte mesclar as páginas em um único resultado —meta.hasMoreinforma se ainda há algo restante. - Dados de análise.
request_analytics_report→list_analytics_reports→list_analytics_report_instances→list_analytics_report_segmentsfornece uma URL de segmento pré-assinada;download_analytics_segmenta busca, descompacta com gunzip e retorna as linhas como JSON. A Apple pode levar até 48 horas para gerar o primeiro relatório para uma nova solicitação. - Qualquer coisa não listada é acessível via
appstore_request(método bruto + caminho + corpo JSON:API) ouappstore_list(GET paginado). Exemplo:appstore_request { "method": "GET", "path": "/v1/apps/123/customerReviews" }. - Não coberto: endpoints de relatórios de vendas/financeiro retornam TSV compactado com gzip (não JSON:API) e estão fora do escopo dessas ferramentas.
Limitações (impostas pela Apple)
- Você não pode criar um app via API. O recurso
appspermite apenas GET e UPDATE —POST /v1/appsretorna403 FORBIDDEN_ERROR. Crie o registro do app no site do App Store Connect (Apps → ➕ → Novo App); você pode pré-criar seu bundle ID comcreate_bundle_id. Todas as outras ferramentas operam em um app existente. - O
productIdde uma compra dentro do app excluída é permanentemente reservado pela Apple e não pode ser reutilizado.
Desenvolvimento
cargo test # 200+ tests, no network or credentials needed
cargo clippy --all-targets -- -D warnings
cargo fmt --check
Os testes vêm em três camadas: testes unitários puros para construtores de corpo de solicitação, decisões de
repetição e modelagem de resposta; testes wiremock
que dirigem o cliente HTTP real contra uma API simulada (repetições, timeouts,
paginação, o protocolo de upload em três etapas, downloads de segmento); e
tests/tool_surface.rs, que afirma as invariantes do que um cliente realmente
vê — nomes únicos, descrições reais, esquemas de objetos, anotações corretas e
que ASC_TOOLS/ASC_READ_ONLY retêm exatamente o que afirmam.
A versão mínima suportada do Rust é 1.88, verificada por seu próprio job de CI.
Regenere a referência de ferramentas após adicionar/alterar ferramentas (precisa do binário de lançamento; nenhuma credencial necessária):
cargo build --release && python3 scripts/gen_tools_doc.py # rewrites docs/TOOLS.md
Testes de integração ao vivo
scripts/integration_test.py dirige o servidor compilado contra a API real.
Somente leitura por padrão; --write adiciona um ciclo de vida de IAP autolimpante.
cargo build --release
# Credentials via env (ASC_ISSUER_ID/ASC_KEY_ID/ASC_PRIVATE_KEY_PATH) or local
# appstore-connect.txt + AuthKey_*.p8 in the repo root (both gitignored).
python3 scripts/integration_test.py --app <APP_ID> # read-only sweep
python3 scripts/integration_test.py --app <APP_ID> --write # + write lifecycle
Licença
MIT