aapl-ads-mcp
The aapl-ads-mcp server connects AI assistants to the Apple Search Ads API v5, enabling read-only querying of ASA account data through natural language.
Health Check (
health) — Verify the MCP server is running without requiring ASA authentication.List Organizations (
list_orgs) — Verify credentials and discover accessible orgs, including ID, name, currency, timezone, and role.List Campaigns (
list_campaigns) — Enumerate campaigns with metadata (id, name, status, budget, country, channel type); filter by status (ENABLED, PAUSED, DELETED) and paginate.List Ad Groups (
list_ad_groups) — List ad groups within a campaign, including default bid and automated keyword opt-in settings.List Keywords (
list_keywords) — Retrieve targeting keywords for an ad group, including text, match type (BROAD/EXACT), bid amount, and status.Campaign Performance Report (
get_campaign_report) — Fetch campaign-level metrics (impressions, taps, TTR, spend, avgCPT, avgCPM, installs, CPI) with configurable date range and granularity (HOURLY/DAILY/WEEKLY/MONTHLY).Ad Group Performance Report (
get_ad_group_report) — Fetch ad group-level metrics broken down by country/region, with configurable date range and granularity.Keyword Performance Report (
get_keyword_report) — Fetch per-keyword metrics (impressions, taps, TTR, spend, CPI, installs) for a specific ad group, with configurable date range and granularity.Search Terms Report (
get_search_terms_report) — Retrieve actual user search queries that triggered ads, with performance metrics per term — ideal for keyword discovery and negative keyword identification (aggregate totals only, no granularity breakdown).
All tools default to the last 30 days, support pagination, and require ASA API credentials. No write operations are supported.
Integrates with Apple Search Ads API v5 to query campaigns, ad groups, keywords, and performance reports.
aapl-ads-mcp
An MCP server that connects Claude (and any MCP-compatible client) to Apple Search Ads API v5.
What is this
MCP (Model Context Protocol) is an open standard that lets AI assistants call external tools. This server implements the MCP stdio transport and exposes 9 read-only tools that query your Apple Search Ads account — campaigns, ad groups, keywords, and performance reports.
You install it once, point Claude Desktop at it, and then ask questions in plain English: "Which keywords drove the most installs last month?" or "Show me campaigns with zero impressions this week."
Related MCP server: tiktok-ads-mcp
Why
The official ASA dashboards are good for humans but not for ad-hoc analysis or automated reporting. Existing MCP alternatives are either SaaS (you hand over your keys) or unmaintained. This is a self-hosted, open-source option you control.
Features
list_orgs — verify authentication, list accessible organizations
list_campaigns — enumerate campaigns, optionally filter by status
list_ad_groups — ad groups for a given campaign
list_keywords — targeting keywords with bid amounts and match type
get_campaign_report — impressions, taps, installs, spend, CPI, TTR by campaign
get_ad_group_report — same metrics broken down by ad group
get_keyword_report — per-keyword performance with weekly/daily/monthly granularity
get_search_terms_report — the real search queries that triggered your ads (most useful for discovery)
All tools default to the last 30 days. Reports support HOURLY, DAILY,
WEEKLY, and MONTHLY granularity.
Limitations
Read-only by design. No write operations (create, update, pause) in this release.
Requires Apple Search Ads Campaign Management API access. You need to create an API user in your ASA account and generate an ES256 key pair.
Aggregate install metrics work without app-side integration.
tapInstalls,viewInstalls, and related fields in ASA reports are populated by Apple Search Ads directly and do not require any SDK in your app. AdServices / AdAttributionKitis only needed if you want to attribute installs to specific campaigns from inside your app (e.g. for onboarding personalization).Single organization. The org ID is fixed in the config. Multi-org switching is not implemented.
Setup
1. Generate an ES256 key pair
Use the modern genpkey command — it produces PKCS#8 format directly, which is what this server requires. The older ecparam -genkey produces SEC1 format and will cause a startup error.
# Generate private key (PKCS#8)
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out private-key.pem
# Derive public key
openssl pkey -in private-key.pem -pubout -out public-key.pemVerify the private key starts with -----BEGIN PRIVATE KEY----- (not -----BEGIN EC PRIVATE KEY-----). If it starts with the EC variant, convert it:
openssl pkcs8 -topk8 -nocrypt -in ec-key.pem -out private-key.pemStore private-key.pem outside the repository root if possible (e.g. ~/.ssh/asa-private-key.pem).
2. Create an API user in Apple Search Ads
Go to ASA → Account Settings → User Management
Click Create User, choose role API Account Read Only for read-only usage (recommended for this server). API Campaign Manager is also fine and adds write permissions if you plan to extend the server with write tools later.
Go to the API tab, click Create Client
Upload
public-key.pemCopy
client_id,team_id, andkey_idfrom the confirmation screenFind your
org_idin Account Settings → Overview
3. Clone and build
git clone https://github.com/andrealufino/aapl-ads-mcp.git
cd aapl-ads-mcp
npm install
npm run build4. Configure Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"aapl-ads": {
"command": "node","args": ["/absolute/path/to/aapl-ads-mcp/dist/index.js"], "env": { "ASA_CLIENT_ID": "SEARCHADS.your-client-id-here",
"ASA_TEAM_ID": "SEARCHADS.your-team-id-here",
"ASA_KEY_ID": "your-key-id-here",
"ASA_ORG_ID": "12345678",
"ASA_PRIVATE_KEY_PATH": "/absolute/path/to/private-key.pem"
} }
} }
**Note:** `ASA_PRIVATE_KEY_PATH` must be an absolute path. Tilde (`~`) is not
expanded by Node.js — use the full path.
For container or cloud deployments where mounting a file is impractical, set
`ASA_PRIVATE_KEY` to the inline PEM contents instead (newlines preserved). If
both are set, `ASA_PRIVATE_KEY` wins.
Restart Claude Desktop. Ask "run health check" to verify the server is
connected.
## Usage examples
These are natural-language prompts that work with Claude Desktop once the server
is running:List my Apple Ads campaigns
Show me the last 30 days of campaign performanceWhich keywords drove installs in my Brand campaign last week?What search terms triggered my ads in the past month? Focus on ones
with impressions but no installs.Compare weekly spend across all campaigns for Q1 2025Show ad groups in campaign 1234567890 with their bid amountsDevelopment
npm run build # compile TypeScript
npm test # run test suite (Vitest)
npm run typecheck # type-check without emitting
npm run lint # Biome lint
npm run format # Biome format (write)MCP Inspector
To debug tool calls interactively without Claude Desktop:
npx @modelcontextprotocol/inspector node dist/index.jsSet the env vars in the Inspector UI before connecting.
Pre-commit hooks
Install lefthook hooks locally after cloning:
npx lefthook installThis sets up:
gitleaks protect --staged— blocks commits that contain secretsBiome lint check on staged
.tsfilesTypeScript type check
Contributing
See docs/ARCHITECTURE.md for technical details: auth
flow, HTTP client design, tool pattern, report schema quirks, and ASA v5
lessons learned during development.
Bug reports and pull requests welcome.
Security
Never commit
.envor*.pemfiles — both are in.gitignoreKeep
private-key.pemoutside the repository rootThe access token is held in memory only, never written to disk
If you suspect a key has been exposed, rotate it in ASA → Account Settings → API
License
MIT — see LICENSE.
Available Tools
9 toolsget_ad_group_reportA
Fetch performance metrics for ad groups within a specific Apple Search Ads campaign: impressions, taps, TTR, spend, CPI, installs (tap-through and view-through), and install rate. Requires ASA authentication; read-only. Use get_campaign_report for a campaign-level summary, or get_keyword_report for keyword-level detail. Results are grouped by country/region and include grand totals. Defaults to the last 30 days with WEEKLY granularity.
| Name | Required | Description | Default |
|---|---|---|---|
| endDate | No | End of the reporting period (YYYY-MM-DD). Defaults to today. | |
| startDate | No | Start of the reporting period (YYYY-MM-DD). Defaults to 30 days ago. | |
| adGroupIds | No | Restrict results to these ad group IDs. Omit to include all ad groups in the campaign. | |
| campaignId | Yes | ID of the campaign to report on. Obtain from list_campaigns. | |
| granularity | No | Time granularity for the breakdown rows: HOURLY, DAILY, WEEKLY, or MONTHLY. Defaults to WEEKLY. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. Describes read-only nature, grouping by country/region, grand totals, and default time range/granularity. However, does not cover potential error behaviors or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three well-structured sentences, front-loaded with core purpose, no redundant information. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, description lists the metrics returned. Covers key behavioral aspects and parameter defaults. Could include more on error handling or pagination, but adequate for a report tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, baseline 3. Description adds context beyond schema: e.g., 'Obtain from list_campaigns' for campaignId, defaults for startDate/endDate/granularity, and meaning of adGroupIds absence.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it fetches ad group performance metrics for a specific ASA campaign, listing specific metrics (impressions, taps, etc.). It distinguishes from siblings by naming get_campaign_report and get_keyword_report.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use this tool vs. alternatives ('Use get_campaign_report for a campaign-level summary, or get_keyword_report for keyword-level detail.'). Also mentions authentication requirements and defaults.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_campaign_reportA
Fetch performance metrics for Apple Search Ads campaigns: impressions, taps, tap-through rate (TTR), localSpend, avgCPT, avgCPM, tapInstalls, viewInstalls, totalInstalls, new downloads, redownloads, CPI, and install rate. Requires ASA authentication; read-only. Use get_ad_group_report or get_keyword_report for deeper breakdowns. Results are grouped by country/region and include grand totals. Defaults to the last 30 days with WEEKLY granularity.
| Name | Required | Description | Default |
|---|---|---|---|
| startDate | No | Start of the reporting period (YYYY-MM-DD). Defaults to 30 days ago. | |
| endDate | No | End of the reporting period (YYYY-MM-DD). Defaults to today. | |
| granularity | No | Time granularity for the breakdown rows: HOURLY, DAILY, WEEKLY, or MONTHLY. Defaults to WEEKLY. | |
| campaignIds | No | Restrict results to these campaign IDs. Omit to include all campaigns in the org. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It mentions authentication requirements and read-only nature. It also describes grouping and grand totals. Could be more explicit about return format, but sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (4 sentences), well-structured, and front-loaded with the main action. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description explains what metrics are returned, grouping, defaults, and authentication. It is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline 3. Description adds value by specifying defaults (last 30 days, WEEKLY granularity) and mentioning grouping by country/region, which is not in schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it fetches performance metrics for Apple Search Ads campaigns, listing specific metrics. It distinguishes itself from siblings by mentioning get_ad_group_report and get_keyword_report for deeper breakdowns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use alternatives ('Use get_ad_group_report or get_keyword_report for deeper breakdowns') and provides default behavior (last 30 days, WEEKLY granularity).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_keyword_reportA
Fetch performance metrics for targeting keywords in a specific Apple Search Ads ad group: impressions, taps, TTR, spend, CPI, installs, and install rate broken down per keyword. Requires ASA authentication; read-only. Use get_search_terms_report to see the actual user queries that triggered these keywords. Results are grouped by country/region and include grand totals. Defaults to the last 30 days with WEEKLY granularity.
| Name | Required | Description | Default |
|---|---|---|---|
| startDate | No | Start of the reporting period (YYYY-MM-DD). Defaults to 30 days ago. | |
| endDate | No | End of the reporting period (YYYY-MM-DD). Defaults to today. | |
| granularity | No | Time granularity for the breakdown rows: HOURLY, DAILY, WEEKLY, or MONTHLY. Defaults to WEEKLY. | |
| campaignId | Yes | ID of the campaign containing the ad group. Obtain from list_campaigns. | |
| adGroupId | Yes | ID of the ad group to report on. Obtain from list_ad_groups. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It states read-only, authentication requirement, results grouping by country/region, inclusion of grand totals, and default time range/granularity. Lacks details on rate limits or error behavior but is sufficient for typical use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences that front-load the purpose and provide necessary context without unnecessary detail. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, but description lists expected metrics, grouping, defaults, and authentication. It references sibling tools for obtaining required IDs. Could be improved by mentioning pagination or data limits, but overall complete for a reporting tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with each parameter having a clear description. The description does not add additional parameter-level meaning beyond what the schema already provides, so baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states 'Fetch performance metrics for targeting keywords' and lists specific metrics (impressions, taps, TTR, etc.). It clearly differentiates from the sibling tool get_search_terms_report by stating that tool shows actual user queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use the alternative tool ('Use get_search_terms_report to see the actual user queries') and mentions prerequisites ('Requires ASA authentication; read-only'). Also indicates default parameters.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_search_terms_reportA
Fetch the actual user search queries that triggered Apple Search Ads impressions, along with performance metrics per search term. Requires ASA authentication; read-only. Most useful for keyword discovery (finding new terms to add) and negation (finding irrelevant queries to exclude). Does not support granularity breakdown — returns aggregate totals per search term. Use get_keyword_report to see metrics for your configured targeting keywords instead. Defaults to the last 30 days.
| Name | Required | Description | Default |
|---|---|---|---|
| startDate | No | Start of the reporting period (YYYY-MM-DD). Defaults to 30 days ago. | |
| endDate | No | End of the reporting period (YYYY-MM-DD). Defaults to today. | |
| granularity | No | Ignored for this report — the ASA API does not support granularity on search terms reports. | |
| campaignId | Yes | ID of the campaign containing the ad group. Obtain from list_campaigns. | |
| adGroupId | Yes | ID of the ad group to report on. Obtain from list_ad_groups. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses read-only nature, authentication requirement, that granularity is not supported, and aggregate totals are returned. However, lacks details on error handling, rate limits, or specific performance metrics returned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences, each serving a purpose. Front-loaded with main action, then usage, then limitations. No redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, usage, behavior, and limitations. Lacks specifics on return format or metrics, but given no output schema, the description is reasonably complete for a report tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and description adds value by explaining defaults for startDate/endDate, that granularity is ignored, and how to obtain campaignId and adGroupId (via list_campaigns and list_ad_groups).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description specifies the verb 'Fetch' and resource 'actual user search queries... along with performance metrics per search term'. It clearly distinguishes from sibling tool get_keyword_report by stating the difference between search terms and configured targeting keywords.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use scenarios: 'keyword discovery' and 'negation'. Explicitly directs to use get_keyword_report for targeting keywords. Also notes that granularity is ignored and defaults to 30 days.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
healthA
Check if the aapl-ads-mcp server is running and reachable. Use this to verify the MCP connection before making API calls. No ASA authentication is required — returns server name, version, and current timestamp.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It describes return values and non-destructive nature. Lacks error handling details but sufficient for a simple health check.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with front-loaded purpose. No wasted words; every sentence adds necessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With zero parameters and no output schema, the description fully covers purpose, usage, and return expectations. No gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so description adds value by clarifying expected output and usage context. Baseline 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks if the server is running and reachable, with specific return values (server name, version, timestamp). It distinctly differs from sibling tools that focus on data retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises to use before making API calls, and notes no authentication required. Could strengthen by mentioning not to use for data operations, but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_ad_groupsA
List ad groups within a specific Apple Search Ads campaign. Requires ASA authentication; read-only. Returns ad group metadata (id, name, status, default bid, automated keyword opt-in) but not performance metrics — use get_ad_group_report for metrics. Supports pagination via limit/offset; default limit 20, max 1000.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | ID of the campaign whose ad groups to list. Obtain from list_campaigns. | |
| limit | No | Max ad groups to return (1–1000). Defaults to 20. | |
| offset | No | Zero-based page offset for pagination. Defaults to 0. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses read-only nature, describes return content (metadata fields) and what is not returned (performance metrics), providing full behavioral context without annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences, front-loaded with purpose, no redundant information, efficient use of text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite lacking output schema, the description covers authentication, return content, limitations, pagination, and alternative tools, making it fully contextual for a list operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Since schema covers 100% of parameters with descriptions, the description adds useful context like obtaining campaignId from list_campaigns, slightly exceeding the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists ad groups within a specific Apple Search Ads campaign, distinguishing it from siblings like get_ad_group_report for performance metrics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Specifies read-only operation, pagination details (limit/offset defaults and max), and directs to get_ad_group_report for performance metrics, but does not explicitly exclude other sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_campaignsA
List all campaigns in the configured Apple Search Ads organization. Requires ASA authentication; read-only. Returns campaign metadata (id, name, status, budget, country, channel type) but not performance metrics — use get_campaign_report for metrics. Optionally filter by status. Supports pagination via limit/offset; default limit 20, max 1000.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter results to campaigns with this status. Omit to return all statuses. | |
| limit | No | Max campaigns to return (1–1000). Defaults to 20. | |
| offset | No | Zero-based page offset for pagination. Defaults to 0. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses read-only nature, authentication requirement, returned fields, pagination behavior with default and max limit, and explicitly states what is not returned (performance metrics).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with all critical information front-loaded; no unnecessary words, efficient use of space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Fully describes return value (fields listed), excludes performance metrics, notes authentication, and covers pagination details. No missing information for a list tool without output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 100% coverage with descriptions; the description reiterates filter and pagination options but does not add new semantic meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool lists campaigns in the Apple Search Ads organization, specifies the resource and scope, and distinguishes from sibling tool get_campaign_report by noting it returns metadata not performance metrics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear guidance on when to use this tool (for campaign metadata) and when to use an alternative (get_campaign_report for metrics), along with optional filtering and pagination details.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_keywordsA
List targeting keywords for a specific Apple Search Ads ad group. Requires ASA authentication; read-only. Returns keyword metadata (text, match type BROAD/EXACT, bid amount, status) but not performance metrics — use get_keyword_report for metrics. Supports pagination via limit/offset; default limit 20, max 1000.
| Name | Required | Description | Default |
|---|---|---|---|
| campaignId | Yes | ID of the campaign that contains the ad group. Obtain from list_campaigns. | |
| adGroupId | Yes | ID of the ad group whose keywords to list. Obtain from list_ad_groups. | |
| limit | No | Max keywords to return (1–1000). Defaults to 20. | |
| offset | No | Zero-based page offset for pagination. Defaults to 0. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosure. It states the tool is read-only, requires ASA authentication, returns keyword metadata (text, match type, bid amount, status), and supports pagination with default and maximum limits. However, it does not cover possible error conditions or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured paragraph that front-loads the purpose, then covers constraints, alternatives, and pagination details. Every sentence adds essential information with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of annotations and output schema, the description covers the main functional aspects: purpose, return content, authentication, pagination, and differentiation from related tools. It could have mentioned the response structure or error handling, but it is fairly complete for a listing tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All parameters are described in the input schema with full coverage. The description adds value by explaining authentication requirements and pagination defaults, though it does not provide additional semantic depth beyond what the schema already offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists targeting keywords for a specific Apple Search Ads ad group, using specific verbs and identifying the resource. It distinguishes itself from sibling tools like get_keyword_report.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: it is read-only, requires ASA authentication, and explicitly mentions that performance metrics should be retrieved using get_keyword_report. It also explains pagination limits, giving good guidance on when to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_orgsA
List all Apple Search Ads organizations accessible with the configured credentials. Requires ASA authentication. Use this to verify credentials are valid and to discover available org IDs before calling other tools. Returns org ID, name, currency, timezone, payment model, and assigned role names.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden. It mentions authentication requirement ('Requires ASA authentication') and lists return fields, but does not disclose potential limitations (e.g., rate limits, error handling, pagination). Adequate but not exceptional.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each necessary and front-loaded: purpose, usage guidance, return data. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters, no output schema, and a simple list operation, the description covers all needed information: what it does, authentication, usage timing, and return fields. Completely sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist (baseline 4). The description adds value by detailing what the return data includes (org ID, name, currency, timezone, payment model, assigned role names), which is beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List' and resource 'organizations' within the context of Apple Search Ads. It distinguishes itself from sibling tools like list_campaigns by specifying 'organizations' and includes the qualifier 'accessible with configured credentials'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent when to use this tool: 'Use this to verify credentials are valid and to discover available org IDs before calling other tools.' This is excellent guidance for workflow sequencing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v1.0.0- First observed
get_ad_group_report - First observed
get_campaign_report - First observed
get_keyword_report - First observed
get_search_terms_report - First observed
health - First observed
list_ad_groups - First observed
list_campaigns - First observed
list_keywords - First observed
list_orgs
TDQS
Scored across 9 tools
Each tool targets a distinct entity and action: list_* for enumerating hierarchy levels, get_*_report for metrics at each level, get_search_terms_report for search queries, and health for server status. No two tools could be confused for the same task.
Most tools follow the list_ or get_*_report pattern clearly separating metadata enumeration from report retrieval. The single deviation is 'health', which is a noun rather than a verb-prefixed action (e.g., check_health), making the pattern slightly inconsistent.
Nine tools is well-scoped for a read-only Apple Search Ads data access server: four list tools for entity hierarchy, four report tools for metrics breakdowns, and a health check. Each tool serves a distinct need without redundancy.
The read-only surface covers the full object hierarchy (org → campaign → ad group → keyword) with list operations and corresponding report endpoints, including search terms. However, the complete absence of write operations (no create/update/delete for campaigns or keywords) could be a gap if management tasks are expected, though it appears intentionally read-only.
Maintenance
Related MCP Connectors
Manage Apple Ads campaigns and reporting in chat.
Google Ads analysis and operations — read performance, manage keywords, bids, and campaigns.
Apple Search Ads MCP: campaign analytics, bid management, and attribution tracking.
Read-only access to your Reporting Ninja marketing and analytics data across 20+ ad platforms.
Related MCP Servers
- AlicenseBqualityDmaintenanceMCP server exposing the full Apple Ads (Search Ads) Campaign Management API v5 — 74 typed tools7420 npm11MIT
- AlicenseBqualityDmaintenanceProvides read-only access to TikTok advertising data, including campaigns, ad groups, ads, and performance reports through the TikTok Business API.642MIT
- FlicenseNot gradedqualityDmaintenanceRead-only access to Reddit Ads API v3 for listing ad accounts, campaigns, ad groups, ads, and generating performance reports with OAuth2 authentication.-
- AlicenseNot gradedqualityCmaintenanceMCP server for Apple Search Ads API v5 that enables natural language management of campaigns, keywords, budgets, creatives, and performance reporting. Supports 54 tools for campaign management, keyword optimization, search term analysis, and more.75 npm7MIT