Apple Ads MCP
apple-search-ads-mcp
Un servidor del Protocolo de Contexto de Modelos (MCP) que envuelve la API completa de gestión de campañas de Apple Search Ads (ahora Apple Ads) v5. 74 herramientas tipadas, mapeo 1:1 a cada endpoint documentado de la v5: campañas, grupos de anuncios, anuncios, creatividades, páginas de producto personalizadas, palabras clave, palabras clave negativas, informes, informes de cuota de impresiones, órdenes de presupuesto, ACLs, búsqueda geo/app, metadatos de apps, auditorías de motivos de rechazo, además de un passthrough directo para cualquier endpoint futuro.
Ciclo de vida de la API: Apple Ads (Search Ads) v5 es la API de producción actual. La v5 dejará de estar disponible el 26 de enero de 2027 en favor de la nueva "Apple Ads Platform API" que llegará en el verano de 2026. Este servidor apunta a la v5.0 → v5.5.
Instalación rápida
git clone https://github.com/AppVisionOS/apple-search-ads-mcp.git
cd apple-search-ads-mcp
npm install
npm run buildLuego regístralo con Claude Code en una línea:
claude mcp add apple-search-ads --scope user \
-e ASA_CLIENT_ID=SEARCHADS.xxxx \
-e ASA_TEAM_ID=SEARCHADS.xxxx \
-e ASA_KEY_ID=xxxx \
-e ASA_PRIVATE_KEY_PATH=/absolute/path/to/asa-private.p8 \
-e ASA_ORG_ID=1234567 \
-- node $(pwd)/dist/index.jsConfiguración
1. Obtener credenciales de API
La interfaz de usuario de Apple Ads divide las credenciales en dos pantallas. La pestaña API dentro de la Configuración de la cuenta solo gestiona el acceso para proveedores de servicios externos; para tu propio acceso programático, el flujo pasa primero por Gestión de usuarios.
a) Invitar a un usuario de API
En app-ads.apple.com → Configuración de la cuenta → Gestión de usuarios → Invitar usuario:
Correo electrónico: cualquier dirección que controles (puede ser la tuya; Apple requiere un Apple ID separado para el usuario de la API)
Rol: elige uno con permisos de API (p. ej., API Account Manager)
Envía la invitación y luego acéptala desde la bandeja de entrada invitada
b) Generar el par de claves localmente
Mientras se procesa la invitación, genera un par de claves ES256 en tu máquina. Asegúrate de que sea PKCS#8; los ejemplos .p8 de Apple y la salida antigua de openssl ecparam no son PKCS#8 y jose no puede cargarlos.
# CORRECT — produces PKCS#8 (-----BEGIN PRIVATE KEY-----)
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out asa-private.p8
openssl ec -in asa-private.p8 -pubout -out asa-public.pem
# If you already produced traditional EC (-----BEGIN EC PRIVATE KEY-----), convert it:
# openssl pkcs8 -topk8 -nocrypt -in asa-private.p8 -out asa-private-pkcs8.p8Guarda asa-private.p8 en un lugar seguro (p. ej., ~/.apple-search-ads/, chmod 600). Solo pegarás la mitad pública en Apple.
c) Generar el cliente de API
Cierra sesión y vuelve a iniciarla como el usuario de API invitado (no la cuenta de administrador). Ve a Configuración de la cuenta → API. Verás una pantalla de Credenciales de cliente con un área de texto para la Clave pública; esto solo aparece para los usuarios que tienen el rol de API.
Pega el contenido de
asa-public.pem(con los marcadores-----BEGIN PUBLIC KEY-----/-----END PUBLIC KEY-----).Haz clic en Generar cliente de API.
Copia los tres valores que te muestra Apple: ID de cliente, ID de equipo, ID de clave; estos no vuelven a aparecer más tarde.
2. Instalación
npm install
npm run build3. Configuración
Copia .env.example a .env y rellénalo, o pasa las variables de entorno a través de tu cliente MCP.
ASA_CLIENT_ID=SEARCHADS.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ASA_TEAM_ID=SEARCHADS.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ASA_KEY_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ASA_PRIVATE_KEY_PATH=/absolute/path/to/private-key.p8
ASA_ORG_ID=1234567 # optional default; can be overridden per callASA_PRIVATE_KEY (contenido PEM en línea, con escapes \n si se inyecta vía JSON) es compatible como alternativa a ASA_PRIVATE_KEY_PATH.
4. Conectar a tu cliente MCP
{
"mcpServers": {
"apple-search-ads": {
"command": "node",
"args": ["/absolute/path/to/apple-search-ads-mcp/dist/index.js"],
"env": {
"ASA_CLIENT_ID": "SEARCHADS.xxxx...",
"ASA_TEAM_ID": "SEARCHADS.xxxx...",
"ASA_KEY_ID": "xxxx...",
"ASA_PRIVATE_KEY_PATH": "/absolute/path/to/private-key.p8",
"ASA_ORG_ID": "1234567"
}
}
}
}Autenticación
El servidor maneja el flujo de credenciales de cliente OAuth 2.0 con una aserción de cliente JWT ES256:
Firma un JWT con tu clave privada
.p8(encabezado:kid=ID de clave,alg=ES256; carga útil:iss=ID de equipo,sub=ID de cliente,aud=https://appleid.apple.com).Haz un POST a
https://appleid.apple.com/auth/oauth2/tokencongrant_type=client_credentialsyscope=searchadsorg.Usa el token de acceso de 1 hora devuelto con
Authorization: Bearer …yX-AP-Context: orgId=…en cada llamada a la API.
El token se almacena en caché en memoria hasta unos 30 segundos antes de su vencimiento, por lo que firmas una aserción e intercambias un token por hora. En caso de 401, el servidor fuerza la actualización y reintenta una vez. En caso de 429/5xx, espera (respetando Retry-After) hasta 3 veces.
Inventario de herramientas (74 herramientas)
Cuenta y acceso (2)
org_acls, me_user: llama sin un contexto de organización para descubrir qué puede hacer tu token.
Descubrimiento (3)
search_apps, search_geo, geo_lookup
Metadatos de apps (6)
apps_get, apps_locale_details, apps_eligibilities_find, apps_assets_find, creative_app_preview_devices, countries_or_regions_list
Páginas de producto personalizadas (3)
cpp_list, cpp_get, cpp_locale_details
Campañas (6)
campaigns_create, campaigns_get, campaigns_list, campaigns_find, campaigns_update, campaigns_delete
Grupos de anuncios (7)
adgroups_create, adgroups_get, adgroups_list, adgroups_find_in_campaign, adgroups_find_org_wide, adgroups_update, adgroups_delete
Creatividades (4)
creatives_create, creatives_list, creatives_get, creatives_find: las creatividades envuelven una referencia a una Página de producto personalizada, Página de producto predeterminada o Conjunto de creatividades. Los anuncios se vinculan a las creatividades mediante creativeId.
Anuncios (7)
ads_create, ads_get, ads_list, ads_find_in_campaign, ads_find_org_wide, ads_update, ads_delete
Palabras clave de segmentación (7)
targeting_keywords_create, targeting_keywords_get, targeting_keywords_list, targeting_keywords_find, targeting_keywords_update, targeting_keywords_delete (en lote), targeting_keywords_delete_single
Palabras clave negativas: alcance de grupo de anuncios (6)
adgroup_negative_keywords_create, adgroup_negative_keywords_get, adgroup_negative_keywords_list, adgroup_negative_keywords_find, adgroup_negative_keywords_update, adgroup_negative_keywords_delete
Palabras clave negativas: alcance de campaña (6)
campaign_negative_keywords_create, campaign_negative_keywords_get, campaign_negative_keywords_list, campaign_negative_keywords_find, campaign_negative_keywords_update, campaign_negative_keywords_delete
Informes (7)
Herramienta | Endpoint |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Todos aceptan startTime, endTime, granularity opcional (HOURLY/DAILY/WEEKLY/MONTHLY), groupBy opcional (adminArea / ageRange / countryCode / countryOrRegion / deviceClass / gender / locality), selector, returnRowTotals, returnGrandTotals, returnRecordsWithNoMetrics, timeZone (UTC | ORTZ).
Informes de cuota de impresiones (3): asíncronos
custom_reports_create → devuelve reportId. Consulta con custom_reports_get hasta que state=COMPLETED. Lista con custom_reports_list.
Órdenes de presupuesto (4): solo cuentas LOC
budget_orders_create, budget_orders_get, budget_orders_list, budget_orders_update. La v5 no tiene eliminación para órdenes de presupuesto.
Auditoría de motivos de rechazo (2)
product_page_reasons_find, product_page_reasons_get: inspección de solo lectura de por qué los revisores de Apple rechazaron las creatividades.
Puerta de escape (1)
apple_search_ads_request: llama a cualquier ruta con cualquier método. La autenticación y el contexto de la organización se siguen manejando por ti.
Selectores
Las herramientas *_find aceptan la gramática de selectores de Apple:
{
"conditions": [
{ "field": "status", "operator": "EQUALS", "values": ["ENABLED"] },
{ "field": "countriesOrRegions", "operator": "CONTAINS_ANY", "values": ["US", "GB"] }
],
"fields": ["id", "name", "status"],
"orderBy": [{ "field": "name", "sortOrder": "ASCENDING" }],
"pagination": { "limit": 100, "offset": 0 }
}Operadores: EQUALS, NOT_EQUALS, CONTAINS, STARTS_WITH, ENDS_WITH, GREATER_THAN, LESS_THAN, IN, NOT_IN, CONTAINS_ALL, CONTAINS_ANY, BETWEEN. values es siempre una matriz.
Ejemplo de extremo a extremo
Un flujo de trabajo que puedes realizar completamente a través de Claude:
org_acls→ elige elorgId.search_appspara tu app → obtén eladamId.campaigns_createcon ese adamId, presupuesto diario, segmentación en EE. UU.,adChannelType=SEARCH,supplySources=["APPSTORE_SEARCH_RESULTS"],billingEvent=TAPS.adgroups_createdentro de la campaña condefaultBidAmount={amount:"1.00",currency:"USD"}ypricingModel=CPC.targeting_keywords_createcon un lote de filas{text, matchType, bidAmount}.cpp_list→ elige un productPageId →creatives_createcontype=CUSTOM_PRODUCT_PAGEpara crear un creativeId →ads_createpara vincularlo al grupo de anuncios.Espera unos días.
reports_campaignspara resultados generales, luegoreports_search_terms_in_campaignpara obtener nuevas palabras clave / negativas.custom_reports_createpara cuota de impresiones / cuota de voz en tus búsquedas principales.
Notas sobre la superficie conocida (peculiaridades de la v5)
No hay CRUD de conjuntos de creatividades heredados. Apple lo eliminó en la v5; crea una fila en
creativesen su lugar y haz referencia a ella desdeads.creativeId.No hay endpoint de categorías de apps. Usa
apps_gety leeprimaryGenre/secondaryGenre.No hay segmentación geográfica por código postal. Las entidades geográficas en la v5 son solo Country / AdminArea / Locality.
No hay búsqueda en toda la organización para palabras clave o búsqueda de palabras clave con alcance de grupo de anuncios. Apple limita la búsqueda de palabras clave de segmentación al nivel de campaña (
/campaigns/{id}/adgroups/targetingkeywords/find) y las agrupa en todos los grupos de anuncios; filtra poradGroupIden el selector para restringir.No hay DELETE en órdenes de presupuesto. Actualízalas, no las elimines.
Las audiencias, la previsión y los eventos de conversión NO están en la v5; esos residen en APIs de Apple separadas (AdServices Attribution, etc.).
Desarrollo local
npm run dev # tsc --watch
npm run typecheck # one-shot type check
npm run build # compile to dist/Usa apple_search_ads_request para depurar cualquier endpoint directamente; devuelve el sobre sin procesar para que puedas ver la forma exacta de la respuesta que devolvió Apple.
Maintenance
Latest Blog Posts
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/AppVisionOS/apple-search-ads-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server