{"name":"io.github.Happygallo/apple-ads","slug":"happygallo-apple-ads","title":null,"description":"Manage Apple Search Ads campaigns, keywords, budgets, and reports via API v5.","url":"https://mcp.market/server/happygallo-apple-ads","rating":null,"grade":"B","score":75,"certified":false,"status":"active","category":"search","tags":["search"],"presence":{"score":21,"stars":7,"forks":1,"downloads_week":70,"last_push_at":"2026-03-17T09:05:40.000Z","license":"MIT"},"uptime":null,"claimed":false,"transport":"npm","callable_via_gateway":false,"default_price_micros":0,"repository":"https://github.com/Happygallo/apple-ads-mcp","website":null,"version":"1.0.3","remotes":[],"packages":[{"registryType":"npm","identifier":"apple-ads-mcp","version":"1.0.3","transport":{"type":"stdio"},"environmentVariables":[{"description":"Apple Search Ads client ID (starts with SEARCHADS.)","isRequired":true,"format":"string","name":"ASA_CLIENT_ID"},{"description":"Apple Search Ads team ID (starts with SEARCHADS.)","isRequired":true,"format":"string","name":"ASA_TEAM_ID"},{"description":"Apple Search Ads key ID (UUID)","isRequired":true,"format":"string","name":"ASA_KEY_ID"},{"description":"Absolute path to your PKCS#8 private key file","isRequired":true,"format":"string","name":"ASA_PRIVATE_KEY_PATH"},{"description":"Organization ID (optional, use list_organizations to switch at runtime)","format":"string","name":"ASA_ORG_ID"}]}],"tools":[{"name":"add_negative_keywords","description":"Add negative keywords to block wasteful search terms from triggering your ads. Campaign-level negatives block across all ad groups; ad-group-level negatives only block within that ad group. Use get_search_term_report to identify high-spend/low-conversion terms to block.","write_action":false,"price_micros":0,"input_schema":null},{"name":"add_targeting_keywords","description":"Add new targeting keywords to an ad group. Keywords determine which App Store search queries trigger your ads. Match types: EXACT matches the exact query only (higher relevance, lower volume). BROAD matches related queries and synonyms (higher volume, may need negatives). Start with EXACT for proven terms and BROAD for discovery, then use get_search_term_report to refine.","write_action":false,"price_micros":0,"input_schema":null},{"name":"create_ad","description":"Create a new ad within an ad group. Requires a creativeId — use list_creatives to find available creatives, or create_creative to make a new one from a product page. Each ad group can have multiple ads with different creatives. Apple will automatically optimize delivery toward the best-performing creative. Defaults: status=ENABLED.","write_action":true,"price_micros":0,"input_schema":null},{"name":"create_ad_group","description":"Create a new ad group within a campaign. After creation, add targeting keywords (add_targeting_keywords) to start matching search queries. Optionally create ads with custom creatives (create_ad). Defaults: status=ENABLED, pricingModel=CPC, startTime=today. The defaultBidAmount is used for keywords that don't have an individual bid. Set cpaGoal to enable Apple's cost-per-acquisition optimization.","write_action":true,"price_micros":0,"input_schema":null},{"name":"create_budget_order","description":"Create a new budget order to authorize spending. Budget orders are the top-level billing entity — campaigns draw from them. Requires name, budget amount, and start date. The budget order must be approved before campaigns can spend against it.","write_action":true,"price_micros":0,"input_schema":null},{"name":"create_campaign","description":"Create a new Apple Search Ads campaign. After creation, you MUST create at least one ad group (create_ad_group) and add keywords (add_targeting_keywords) before the campaign can serve ads. Defaults applied: status=ENABLED, currency=USD, supplySource=APPSTORE_SEARCH_RESULTS. adChannelType and billingEvent are auto-set based on supply source (SEARCH/TAPS for search results, DISPLAY/IMPRESSIONS for s","write_action":true,"price_micros":0,"input_schema":null},{"name":"create_creative","description":"Create a new creative for use in ads. Creatives are based on App Store product pages. Use list_product_pages to find available product pages for the app, then provide the productPageId. After creation, use create_ad to attach the creative to an ad group. Each ad group can have multiple ads with different creatives for A/B testing.","write_action":true,"price_micros":0,"input_schema":null},{"name":"create_impression_share_report","description":"Create an async custom impression share report. Returns a report ID — poll with get_impression_share_report_by_id until status is COMPLETED. These reports provide detailed impression share data not available in standard keyword reports. Takes minutes to generate.","write_action":true,"price_micros":0,"input_schema":null},{"name":"delete_ad","description":"Permanently delete an ad. This action CANNOT be undone. The ad group must have at least one remaining ad, or it will stop serving. Consider pausing instead (update_ad with status=PAUSED).","write_action":true,"price_micros":0,"input_schema":null},{"name":"delete_ad_group","description":"Permanently delete an ad group and all its keywords and ads. This action CANNOT be undone. Consider pausing instead (update_ad_group with status=PAUSED) to preserve data.","write_action":true,"price_micros":0,"input_schema":null},{"name":"delete_campaign","description":"Permanently delete a campaign and all its child ad groups, keywords, and ads. This action CANNOT be undone. The campaign must be paused before deletion. Consider pausing instead if you might need the data later.","write_action":true,"price_micros":0,"input_schema":null},{"name":"delete_negative_keywords","description":"Permanently delete negative keywords in bulk. After deletion, ads may start showing for previously blocked search terms. Only delete if you're sure those terms are no longer wasteful.","write_action":true,"price_micros":0,"input_schema":null},{"name":"delete_targeting_keywords","description":"Permanently delete targeting keywords from an ad group in bulk. This CANNOT be undone — the keyword and its historical association are removed. Consider pausing instead (update_targeting_keywords with status=PAUSED) to preserve bid history.","write_action":true,"price_micros":0,"input_schema":null},{"name":"find_ad_rejection_reasons","description":"Find ad rejection reasons across your account, or get a specific rejection reason by ID. Use this when ads are not serving to understand why Apple rejected them and what to fix.","write_action":false,"price_micros":0,"input_schema":null},{"name":"find_app_assets","description":"Find app assets (screenshots, app previews, etc.) using filters. Useful for checking which visual assets are available before creating creatives. Filter by device class, orientation, or asset type using conditions.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_ad","description":"Get full details of a specific ad including its creative association, serving status, and any rejection reasons.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_ad_group","description":"Get full configuration of a specific ad group: bid settings, CPA goal, status, and scheduling. Use get_adgroup_report for performance metrics.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_ad_report","description":"Get performance metrics per ad variation within a campaign. Compare creative performance to identify which ad variations drive the best CPA and conversion rates. Use this to decide which creatives to scale and which to pause.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_adgroup_report","description":"Get performance metrics for ad groups within a campaign. Compare ad group performance to identify which targeting strategies work best. Returns impressions, taps, installs, spend, CPA, CPT per ad group. Drill down further with get_keyword_report.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_app_details","description":"Get detailed information about an app by Adam ID including app name, category, and store metadata. Set includeLocales=true to also fetch localized names and descriptions per language/region.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_app_eligibility","description":"Check if an app is eligible for Apple Search Ads in specific countries and supply sources. Shows eligibility state, device class, and minimum age per country. Use before creating a campaign to verify the app can run ads in target markets.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_budget_analysis","description":"Analyze budget utilization and efficiency across ALL campaigns. Shows spend vs budget, daily run rate, days until budget exhaustion, and cost per install. Use to identify under-spending campaigns (increase bids/keywords) and over-spending campaigns (reduce bids/budgets).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_budget_order","description":"Get full details of a specific budget order including budget amount, remaining balance, supply sources, and billing contacts.","write_action":true,"price_micros":0,"input_schema":null},{"name":"get_campaign_details","description":"Get full configuration of a specific campaign: targeting settings, budgets (total + daily), countries, supply sources, billing event, and status. Use get_campaign_report for performance metrics instead.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_campaign_report","description":"Get performance metrics for one or all campaigns over a date range. Returns impressions, taps, installs, spend, CPA, CPT, TTR, and conversion rates. Use for high-level performance analysis. For deeper analysis, drill down with get_adgroup_report or get_keyword_report.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_campaign_snapshot","description":"Get a comprehensive snapshot of a campaign in ONE call: campaign config, all ad groups, top keywords by spend, top search terms, and daily performance trends. Designed to give AI all the context needed for optimization analysis without multiple tool calls. Start here for any campaign health check or optimization task.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_creative","description":"Get full details of a specific creative including its associated app, type, state, and timestamps.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_geo_performance","description":"Get performance metrics broken down by country or region for a campaign. Shows impressions, taps, installs, spend, CPA per market. Use to identify which countries deliver the best ROI and where to increase/decrease investment or adjust geo targeting.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_impression_share_report_by_id","description":"Get an impression share report by ID. Poll until state=COMPLETED (typically 1-5 minutes). The report contains detailed impression share and rank data per keyword.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_keyword_report","description":"Get keyword-level performance metrics: impressions, taps, installs, spend, CPA, CPT, and conversion rate per keyword. Essential for bid optimization — identify high-CPA keywords to lower bids or pause, and high-converting keywords to increase bids. Also includes impression share data in the raw JSON (insights.impressionShare). Use get_search_term_report for the actual user queries that triggered e","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_me_details","description":"Get details about the currently authenticated API user including user ID and parent org ID. Useful for debugging authentication issues.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_negative_keyword","description":"Get details of a specific negative keyword by ID at the campaign or ad group level.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_product_page_by_id","description":"Get details of a specific product page by ID. Product pages are App Store page variations used to create custom creatives. Set includeLocales=true to also fetch locale-specific details (names, descriptions per language).","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_search_term_report","description":"Get actual user search queries that triggered your ads, with full performance metrics. THIS IS THE MOST VALUABLE TOOL for keyword optimization — reveals which search terms convert well (add as keywords), which waste money (add as negatives), and which keywords trigger irrelevant searches.","write_action":false,"price_micros":0,"input_schema":null},{"name":"get_targeting_keyword","description":"Get details of a specific targeting keyword: text, match type, bid amount, and status. Use get_keyword_report for performance metrics.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_ad_groups","description":"List or search ad groups. Provide campaignId to scope to one campaign, or omit to search across all campaigns (org-level). Supports filtering by conditions (e.g., status, defaultBidAmount) and sorting. Returns ad group ID, name, status, default bid, and CPA goal.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_ads","description":"List or search ads. Provide campaignId + adGroupId for a direct listing, campaignId alone to search within a campaign, or omit both for org-level search. Supports filtering and sorting. Returns ad ID, name, creative, status, and rejection reasons if any.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_budget_orders","description":"List all budget orders in the account. Budget orders define the overall spending authorization and billing relationship. Shows order name, budget, status (ACTIVE/INACTIVE/EXHAUSTED), and date range.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_campaigns","description":"List or search campaigns in the account. Returns campaign ID, name, status, budgets, countries, and supply sources. Use without parameters for a quick overview. Add conditions to filter (e.g., status=ENABLED) or sortBy to rank results. This is typically the first tool to call when exploring an account.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_creatives","description":"List or search creatives in the account. Creatives link product pages to ads — you need a creative before you can create_ad. Filter by adamId to find creatives for a specific app, or use conditions for advanced filtering.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_impression_share_reports","description":"List all custom impression share reports with their status (QUEUED, RUNNING, COMPLETED, FAILED). Use to find previously created reports.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_negative_keywords","description":"List negative keywords at campaign or ad group level. Negative keywords prevent your ads from showing for specific search terms. Use get_search_term_report to identify wasteful terms, then add_negative_keywords to block them. NOTE: The Apple Search Ads API does not support filter conditions on negative keyword endpoints — use sorting and client-side filtering instead.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_organizations","description":"List all organizations (campaign groups) you have access to. Shows org ID, name, currency, payment model, and your roles. Call this first to find the right org, then use switch_organization to set the active org for all subsequent API calls.","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_product_pages","description":"List all product pages for an app. Product pages are App Store page variations that can be used as creatives for custom product page ads. Shows which page is the default and each page's state (VISIBLE, etc.).","write_action":false,"price_micros":0,"input_schema":null},{"name":"list_targeting_keywords","description":"List or search targeting keywords in a campaign. Provide adGroupId for keywords in a specific ad group, or omit to search across all ad groups. Returns keyword text, match type, bid, and status. Use get_keyword_report for performance metrics instead.","write_action":false,"price_micros":0,"input_schema":null},{"name":"search_apps","description":"Search for apps eligible for Apple Search Ads campaigns by name or keyword. Returns app name, Adam ID (needed for create_campaign), and developer info. Set returnOwnedApps=true to only show apps you own.","write_action":false,"price_micros":0,"input_schema":null},{"name":"search_geolocations","description":"Search or look up geo locations for campaign geo targeting. Search by name (query) to find locations, or provide geoIds to look up specific locations by ID. Returns location display name, entity type (Country/AdminArea/Locality), and ID for use in ad group targeting.","write_action":false,"price_micros":0,"input_schema":null},{"name":"switch_organization","description":"Switch the active organization context. All subsequent API calls (campaigns, reports, etc.) will operate under this org. The switch persists across sessions. Use list_organizations to see available orgs and their IDs.","write_action":false,"price_micros":0,"input_schema":null},{"name":"update_ad","description":"Update an ad's name or status. Setting status to PAUSED stops delivery for this specific ad variation only; other ads in the same ad group continue serving.","write_action":true,"price_micros":0,"input_schema":null},{"name":"update_ad_group","description":"Update an ad group's configuration. Only provided fields are changed. Changing defaultBidAmount affects all keywords that don't have individual bids. Setting status to PAUSED stops delivery for this ad group only.","write_action":true,"price_micros":0,"input_schema":null},{"name":"update_budget_order","description":"Update an existing budget order. Can change name, budget amount, and end date. Increasing budget extends spending capacity; decreasing it may cause campaigns to pause if they've exceeded the new limit.","write_action":true,"price_micros":0,"input_schema":null},{"name":"update_campaign","description":"Update a campaign's configuration. Only provided fields are changed; omitted fields are left unchanged. Important: changing countriesOrRegions will clear existing geo targeting (ad-group-level locality/admin area targets). Budget changes take effect immediately. Setting status to PAUSED stops all ad delivery.","write_action":true,"price_micros":0,"input_schema":null},{"name":"update_negative_keywords","description":"Update negative keywords in bulk at the campaign or ad group level. Change status (ACTIVE/PAUSED), match type, or text. Pausing a negative keyword allows the previously blocked search term to trigger ads again.","write_action":true,"price_micros":0,"input_schema":null},{"name":"update_targeting_keywords","description":"Update targeting keywords in bulk — change status (ACTIVE/PAUSED) and/or bid amounts. Use to pause underperforming keywords or adjust bids based on get_keyword_report data. Pass an array of 1 for single-keyword updates. Bid changes take effect immediately and affect future auctions.","write_action":true,"price_micros":0,"input_schema":null}],"scan":{"score":75,"grade":"B","scanned_at":"2026-09-27T23:36:57.844Z","report":{"scannerVersion":"0.1.10","scannedAt":"2026-09-27T23:36:57.756Z","components":{"code":{"score":25,"max":25,"notes":["53 source files scanned"]},"reliability":{"score":-1,"max":20,"notes":["no gateway calls yet and no remote to probe"]},"poisoning":{"score":-1,"max":15,"notes":["tools not inspected (local package is not executed); not counted"]},"auth":{"score":12,"max":15,"notes":["local package, no credentials required"]},"maintenance":{"score":4,"max":15,"notes":["last push 195 days ago"]},"identity":{"score":8,"max":10,"notes":["registry namespace matches repository owner","GitHub account older than a year"]}},"findings":[],"inputs":{"packages":[{"registryType":"npm","identifier":"apple-ads-mcp","version":"1.0.3","found":true,"license":"MIT","hasInstallScripts":false,"dependencyCount":3,"publishedAt":"2026-03-17T09:06:10.048Z","repositoryUrl":"git+https://github.com/Happygallo/apple-ads-mcp.git","weeklyDownloads":70}],"repo":{"found":true,"owner":"Happygallo","repo":"apple-ads-mcp","archived":false,"pushedAt":"2026-03-17T09:05:40Z","stars":7,"forks":1,"openIssues":0,"ownerType":"User","ownerAvatarUrl":"https://avatars.githubusercontent.com/u/8990574?v=4","ownerCreatedAt":"2014-10-01T23:14:31Z","license":"MIT"},"icon":{"url":"https://avatars.githubusercontent.com/u/8990574?v=4&s=128","source":"github"},"presence":{"stars":7,"forks":1,"downloadsWeek":70,"license":"MIT","lastPushAt":"2026-03-17T09:05:40.000Z","score":21}}}},"grade_history":[],"reviews":[]}