Ads Analytics MCP
Provides read access to Google Ads campaign performance data, including hourly breakdowns, search terms, keywords, and impression share metrics.
Provides read access to Meta Ads (Facebook/Instagram) campaign performance data, including hourly breakdowns, opportunity scores, auction rankings, and anomaly signals.
Provides read access to TikTok Ads campaign performance data, including hourly breakdowns, ad-level metrics with video engagement, and anomaly detection.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Ads Analytics MCPanalyze my Google Ads campaign performance for last week"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Ads Analytics MCP
An open-source Model Context Protocol (MCP) server that gives an AI assistant (Claude Desktop, Claude Code, or any MCP client) read access to campaign performance data from three ad platforms:
Google Ads
Meta Ads (Facebook / Instagram)
TikTok Ads
It exposes campaign, hourly, ad-level, and account-level insight tools. All data is fetched live from each platform's official API using credentials you supply. Nothing is bundled, cached to a database, or sent anywhere else.
On top of the raw tools, the repository ships a Claude intelligence layer: skills and subagents that turn those tools into opinionated, Spain-specific audits and recommendations (see The Claude intelligence layer).
No credentials are included in this repository. Copy the example files and fill in your own. See Configuration.
Table of contents
Related MCP server: ads-mcp-server
How it fits together
There are two distinct layers in this repo:
┌──────────────────────────────────────────────────────────────┐
│ Claude intelligence layer (.claude/) │
│ │
│ Skills Subagents References │
│ google-ads ──► audit-google ──► benchmarks-spain.md │
│ meta-ads ──► audit-meta compliance-eu-spain.md│
│ tiktok-ads ──► audit-tiktok platform-specs.md │
│ ads-budget-review ─► audit-budget │
│ ads-pacing-monitor business-analyst │
│ ads-strategy-plan │
│ ab-test-design │
│ competitor-teardown │
└───────────────────────────────┬──────────────────────────────┘
│ calls MCP tools
▼
┌──────────────────────────────────────────────────────────────┐
│ MCP server (src/ → dist/) │
│ │
│ tools/ ──► services/ ──► adapters/ ──► Platform APIs │
│ (16 read-only tools) Google / Meta / │
│ TikTok │
└──────────────────────────────────────────────────────────────┘The MCP server (
src/) is plain, provider-agnostic infrastructure: 16 read-only tools that any MCP client can call. It has no opinions. It returns normalized metrics.The Claude layer (
.claude/) is optional and Claude-specific. Skills are the entry points users trigger by phrase; they pull data with the tools and delegate deep work to subagents; subagents score against the reference benchmarks and write reports. You can run the server with no Claude layer at all and still use every tool.
Features
🔌 Live API access to Google Ads, Meta Marketing API, and TikTok Marketing API
📊 Campaign performance, hourly breakdowns, ad-level, search terms, keywords, impression share
🧠 Account-level insight tools: opportunity score, auction rankings, anomaly signals
👥 Multi-account: configure as many accounts as you like, one JSON file each
🔒 Secrets stay local.
.env+clients/*.jsonare git-ignored by default🤖 Optional Claude skills + subagents for Spain-specific audits and budget strategy
Available tools
All 16 tools are read-only. Every metric is normalized into a common shape (spend, impressions, clicks, CTR, CPC, CPM, conversions, CPA, conversion value, ROAS) before it leaves the server, so an agent sees the same vocabulary across platforms.
Tool | Platform | Description |
| n/a | List configured accounts and their platforms. Call this first to discover |
| Campaign metrics; | |
| Hour-of-day × day-of-week breakdown (dayparting) | |
| Search-terms report; surfaces | |
| Keyword performance + Quality Score distribution | |
| Impression share, split into budget-lost vs rank-lost | |
| Meta | Campaign metrics at campaign × day granularity |
| Meta | Hour-of-day × day-of-week breakdown (dayparting) |
| Meta | Account opportunity score (0–100) + recommendations queue |
| Meta | quality / engagement / conversion rankings + |
| Meta | Rolling-baseline Z-score anomaly detection per campaign × metric |
| TikTok | Campaign metrics at campaign × day granularity |
| TikTok | Hour-of-day × day-of-week breakdown (dayparting) |
| TikTok | Ad-level metrics + |
| TikTok | video_quality_score + engagement / conversion rankings |
| TikTok | Rolling-baseline Z-score anomaly detection per campaign × metric |
Requirements
Node.js >= 20
API access on each platform you want to use:
Google Ads: a Google Cloud OAuth app + a Google Ads API developer token
Meta: a Marketing API app and a (preferably long-lived System User) access token with
ads_readTikTok: a TikTok Marketing API app
Installation & build
git clone <your-fork-url>
cd ads-analytics-mcp
npm install # install dependencies
npm run build # compile TypeScript src/ → dist/npm run build runs tsc and emits the runnable server to dist/index.js. That compiled file is what every MCP client launches. Always rebuild after changing anything under src/.
Verify the build booted correctly (lists all tools over stdio without needing credentials):
npm start # node dist/index.js, should log "server connected via stdio"The server starts even with zero accounts configured (it just exposes list_clients returning an empty list). Credentials are only needed when you actually call a platform tool.
Configuration
Credentials are split in two:
App-level credentials →
.env(your OAuth apps / developer tokens)Account-level credentials →
clients/<id>.json(per-account IDs + tokens)
1. App-level .env
cp .env.example .envFill in your Google Ads OAuth app + developer token, and (if using TikTok) your TikTok app id/secret. See the comments in .env.example.
2. Account files
cp clients/_example.json clients/my-account.jsonEdit it with the account IDs and tokens for the platforms you use. Any platform block you omit is simply unavailable for that account. A minimal Google-only account:
{
"id": "my-account",
"name": "My Account",
"google_ads": {
"customer_id": "1234567890",
"refresh_token": "1//0e...",
"currency": "EUR"
}
}Add as many clients/*.json files as you have accounts. They are git-ignored (only _example.json is tracked). The id field is the client_id you pass to every tool.
Getting tokens
# Google Ads OAuth refresh token (uses GOOGLE_ADS_CLIENT_ID/SECRET from .env)
npm run auth:google
# TikTok access token (uses TIKTOK_APP_ID/SECRET from .env)
npm run auth:tiktokFor Meta, generate a long-lived System User token in Business Settings and paste it into your account file's meta_ads.access_token.
Connecting to an MCP client
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"ads-analytics": {
"command": "node",
"args": ["/absolute/path/to/ads-analytics-mcp/dist/index.js"]
}
}
}Claude Code
claude mcp add ads-analytics -- node /absolute/path/to/ads-analytics-mcp/dist/index.jsThen ask things like "List my accounts" or "Show last 30 days Google Ads campaign performance for my-account." When more than one account is configured, pass client_id (the account's id).
The Claude intelligence layer
Everything under .claude/ is an opinionated layer that sits on top of the raw tools. It is what turns "here are the numbers" into "here is what's wrong and what to do about it," tuned for Spanish (EU) advertisers. If you use a non-Claude MCP client, you can ignore this section. The tools work without it.
It has three parts: skills (entry points), subagents (deep workers), and references (the shared knowledge base they both cite).
Skills
Skills live in .claude/skills/<name>/SKILL.md. Each one activates on natural-language triggers, resolves inputs (client_id, date range), pulls data with the MCP tools, and either answers inline or hands off to a subagent for a full scored audit.
Per-platform skills (one entry point per channel):
Skill | Triggers on | Pulls these tools | Delegates to |
| "google ads", "Quality Score", "search terms waste", "PMax", "impression share" | the 5 |
|
| "meta ads", "facebook ads", "instagram ads", "pixel", "CAPI", "EMQ", "learning limited" | the 5 |
|
| "tiktok ads", "hook rate", "2s hold", "creative fatigue", "Smart Performance Campaign" | the 5 |
|
Cross-platform skills (work across all three channels at once):
Skill | Purpose |
| Strategic allocation. Applies the 70/20/10 rule, 3× Kill Rule, 20% Scaling Rule; produces a kill list and a scale list. Delegates to |
| Tactical mid-month spend pacing. Projects end-of-month spend at the current run rate and flags over/under-pacing campaigns. |
| Interactive kickoff plan for a new client: platform selection, campaign architecture, budget, creative, tracking, rollout roadmap. |
| Structured A/B-test design: hypothesis, sample-size calculator, duration estimate, platform-specific split-test setup. |
| Competitive landing-page analysis: positioning, messaging, objections, trust signals, CTA strategy. |
Subagents
Subagents live in .claude/agents/<name>.md. They are the deep workers a skill hands off to. Each runs a self-contained, scored audit and writes a Markdown report to ./reports/<client_id>/<date>-<platform>-audit/. The first line of every report is a machine-readable score line:
SCORE: <0-100>/100 GRADE: <A|B|C|D|F> CLIENT: <client_id> PLATFORM: <platform> PERIOD: <start>..<end>Agent | What it audits | Tools it pulls |
| Conversion tracking, wasted spend, structure, Quality Score, PMax, bidding | the 5 |
| Pixel/CAPI health, EMQ, learning state, auction competitiveness, anomalies | the 5 |
| Hook strength (2s/6s hold), creative performance, SPC, auction, anomalies | the 5 |
| Allocation, bidding strategy, scaling readiness, budget sufficiency | campaign + impression-share tools across all platforms |
| CMO-level synthesis: blended CPL/CPA/ROAS, where budget works vs is wasted | none directly; reads the other agents' reports |
business-analyst is the capstone: it does not call the platform tools itself. It consumes the reports written by the four audit agents and produces a unified cross-channel executive narrative with budget-reallocation recommendations.
Reference knowledge base
Both skills and agents are forbidden from inventing thresholds. They must cite these shared files in .claude/references/:
File | Contains |
| Spain (EUR) guidance ranges for CPC/CPM/CTR/CPA/ROAS per platform. ROAS and CPA always outweigh raw rate metrics. |
| GDPR / LOPDGDD / AEPD / Consent Mode v2, Meta EU Consent Policy, TikTok restricted categories. US privacy law is explicitly out of scope. |
| Creative dimensions, safe zones, and format-compliance specs (universal, not localized). |
This is why the audits are tuned for Spain: a campaign sitting below an average but with healthy ROAS is scored WARN, not FAIL, and US-specific rules (CCPA, ECPC-only logic, Offline Conversions API) are flagged as out-of-date or out-of-scope.
How skills, agents, and tools play together
A typical full request flows top-to-bottom through all three layers:
User: "Audit my TikTok account for client maganda, last 14 days"
│
▼
Skill tiktok-ads ── resolves client_id via list_clients
│ reads benchmarks-spain + compliance + platform-specs
│ decides: full audit → hand off
▼
Agent audit-tiktok ── parallel MCP calls:
│ get_tiktok_campaign_performance
│ get_tiktok_ad_performance (2s/6s hold)
│ get_tiktok_hourly_performance
│ get_tiktok_auction_rankings
│ get_tiktok_anomaly_signal
│ ── scores each check vs benchmarks-spain.md
▼
Tools get_tiktok_* ── services/ normalize → adapters/ → TikTok Marketing API
│
▼
Report ./reports/maganda/2026-06-28-tiktok-audit/TIKTOK-ADS-REPORT.md
SCORE: 72/100 GRADE: C CLIENT: maganda PLATFORM: tiktok_ads PERIOD: ...Run all three platform audits plus the budget review, then ask business-analyst to synthesize. It reads those four reports and produces the blended cross-channel view. A quick question ("what's my Meta CPA this week?") never leaves the skill: it pulls one tool and answers inline, no report written.
The contract between layers is deliberately thin: skills and agents only ever touch the platform through the 16 documented tool names. Add a new tool in src/tools/, rebuild, and reference it by name in a skill or agent. No other wiring required.
Development
npm run dev # tsx watch, hot-reloads src/ on save
npm run typecheck # tsc --noEmit, type-check without emitting
npm run build # compile to dist/
npm start # run the compiled server (node dist/index.js)Architecture
src/
index.ts entry point (stdio transport)
server.ts MCP server wiring (ListTools / CallTool)
config/ app-level config (env) + account registry (clients/*.json)
schemas/ zod schemas for inputs, normalized output, account config
tools/ MCP tool definitions + handlers (one file per platform area)
services/ per-platform orchestration + normalization
adapters/ the only layer that knows each platform's API shapes
utils/ dates, logging, metric math
.claude/
skills/ natural-language entry points (per-platform + cross-platform)
agents/ deep audit subagents + the cross-channel business-analyst
references/ Spain benchmarks, EU compliance, creative specsData flows tools → services → adapters → platform API on the way out, and the reverse, normalized, on the way back. adapters/ is the only layer that knows a platform's raw API shape; everything above it speaks the normalized vocabulary.
Security
Never commit
.envor realclients/*.jsonfiles, both are git-ignored.The repository ships only
*.exampleplaceholders.Tokens are read at runtime and used solely to call the official platform APIs.
All 16 tools are read-only. The server has no write path to any ad account.
License
Available Tools
16 toolsget_google_ads_campaign_performanceA
Retrieves Google Ads campaign performance metrics for a client. Returns normalized metrics: spend, impressions, clicks, CTR, CPC, CPM, conversions, CPA, conversion value, ROAS, plus bidding_strategy_type and channel_type. Default aggregation = 'campaign' (one row per campaign over the full period). Pass aggregation='campaign_day' for trend analysis or 'day' for account-level timeseries. Supports filtering by date range, campaign IDs, and campaign status. Use list_clients to see available client IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| statuses | No | Filter by campaign status. Returns all statuses if omitted. | |
| client_id | No | Client identifier. Required when multiple clients are configured. Use list_clients to see available IDs. | |
| aggregation | No | Row granularity. 'campaign' (default) = one row per campaign, totals over the full period. 'campaign_day' = one row per campaign × day (trend analysis). 'day' = one row per day rolled up across campaigns. | |
| campaign_ids | No | Filter to specific campaign IDs. Returns all campaigns if omitted. | |
| customer_ids | No | Override the client's default Google Ads account IDs. Useful for clients with multiple sub-accounts. | |
| date_range_end | No | End date in YYYY-MM-DD format. Defaults to today. | |
| date_range_start | No | Start date in YYYY-MM-DD format. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, so the description carries the burden. It discloses the row-granularity behavior of aggregation modes and that client_id is required when multiple clients exist, which is useful. But it doesn't state default date range behavior (the schema does), pagination, rate limits, or how many rows could be returned for high-cardinality 'day' queries.
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?
Front-loaded with purpose and metric list, then aggregation options, then filtering, then client lookup pointer. Every sentence earns its place and none repeat structured data verbatim.
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?
For a read tool with rich schema and no output schema, the description covers metrics returned, granularity, filtering, and dependency on list_clients. The absence of an output schema means the metric list in the description does useful work. Minor gap: no mention of date defaults or that customer_ids overrides default accounts (both in schema, so acceptable).
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%, so the schema already documents all 7 parameters including the enum. The description's mention of aggregation semantics and filtering matches the schema rather than extending it. Baseline 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?
Specific verb (retrieves) + resource (Google Ads campaign performance metrics) + the platform differentiator against the many sibling get_*_campaign_performance tools (Meta, TikTok). An agent can immediately distinguish this from get_meta_campaign_performance or get_tiktok_campaign_performance.
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 states when to use each aggregation ('campaign' default for totals, 'campaign_day' for trend analysis, 'day' for account-level timeseries) and points to list_clients for client IDs. However, it does not name when-not-to-use or point to sibling metric tools (search_terms, keywords, impression_share) that cover non-performance dimension analysis.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_google_ads_hourly_performanceA
Returns Google Ads performance broken down by hour-of-day (0–23) and day-of-week (MONDAY–SUNDAY) per campaign. Use for dayparting / ad-schedule analysis — identify when ads perform best and worst, inform ad_schedule bid adjustments. Metrics per bucket: impressions, clicks, spend, conversions, conversion_value, ctr, cpc, cpa, roas. Hours are in the advertiser's time zone as configured in Google Ads.
| Name | Required | Description | Default |
|---|---|---|---|
| client_id | No | Client identifier. Use list_clients to see available IDs. | |
| campaign_ids | No | Filter to specific campaign IDs. Returns all campaigns if omitted. | |
| customer_ids | No | Override the client's default Google Ads account IDs. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| date_range_start | No | YYYY-MM-DD. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the exact metric set returned per bucket and the important behavioral fact that hours are in the advertiser's Google Ads time zone. It omits read-only confirmation, row-volume/limits, and date-default behavior, but the timezone and metric disclosure is substantive.
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: the first front-loads the breakdown shape, the second gives usage and metric list. No filler, and the most distinctive information (hour/day buckets) leads.
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 exists, and the description compensates by enumerating the returned metrics and the bucket dimensions, which is exactly what an agent needs to interpret results. Missing only edge detail like empty-bucket behavior or row limits, which is minor for an aggregate report.
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%, so all five parameters are already documented in the schema (client_id, campaign_ids, customer_ids, date range defaults). The description adds only the timezone interpretation, which is bucket semantics rather than parameter semantics, so baseline 3 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?
States a specific verb (Returns) plus resource (Google Ads performance) and the exact breakdown axes (hour-of-day 0–23, day-of-week MONDAY–SUNDAY, per campaign). This cleanly separates it from get_google_ads_campaign_performance and the other non-hourly siblings.
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 names the use case (dayparting / ad-schedule analysis) and the downstream action it informs (ad_schedule bid adjustments). It does not name a competing sibling to route away from, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_google_ads_keywordsA
Retrieves keyword performance and Quality Score data from Google Ads. Returns quality_score_distribution summarising QS spread across the account. Quality Score 1–4 keywords are flagged for optimization — low QS raises CPC. Use min_impressions=100 to focus on keywords with enough data for reliable QS. Use list_clients to see available client IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max keywords to return, ranked by spend desc. Default 100. | |
| statuses | No | Filter by keyword status. | |
| client_id | No | Client identifier. Required when multiple clients are configured. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| customer_ids | No | Override the client's default Google Ads account IDs. | |
| date_range_end | No | End date (YYYY-MM-DD). Defaults to today. | |
| min_impressions | No | Minimum impressions to include a keyword. Use 100 for reliable QS data. | |
| date_range_start | No | Start date (YYYY-MM-DD). Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose non-obvious behavior: the account-level QS distribution summary, the 1-4 flagging rule, and the CPC consequence. It omits permissions/auth requirements, rate limits, and pagination behavior, which keeps it from a 5.
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?
Four sentences, front-loaded with purpose and then progressively more operational detail; little waste. The min_impressions advice mildly duplicates the schema text, which is the only 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?
For an 8-parameter read tool with no output schema and no annotations, the description covers purpose, output shape, and the key filter heuristic, and points at list_clients for the client_id prerequisite. It does not explain pagination/limit interaction or return ordering beyond what the schema states, leaving a small gap.
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%, so the schema already documents all 8 parameters including defaults and the min_impressions=100 recommendation. The description largely restates that same min_impressions guidance rather than adding format or interaction semantics, matching the baseline 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?
States a specific verb and resource ('Retrieves keyword performance and Quality Score data from Google Ads') and names the concrete artifact returned (quality_score_distribution). This is clearly distinguishable from siblings like get_google_ads_search_terms or get_google_ads_campaign_performance without opening any schema.
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?
Gives actionable usage context: 'Use min_impressions=100 to focus on keywords with enough data for reliable QS' and routes the agent to list_clients for client IDs. It stops short of explicitly stating when to choose this over the sibling search-terms or campaign-performance tools, so it lacks true alternatives/exclusions guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_google_ads_search_termsA
Retrieves search term performance data from Google Ads. Identifies wasted spend: terms with budget consumed but zero conversions. Returns total_spend, wasted_spend, and wasted_spend_pct at the response level. Use zero_conversions_only=true to focus exclusively on wasted spend. Use min_spend to filter out negligible terms. Use list_clients to see available client IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max search terms to return, ranked by spend desc. Default 100. | |
| client_id | No | Client identifier. Required when multiple clients are configured. | |
| min_spend | No | Minimum spend in account currency to include a term. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| customer_ids | No | Override the client's default Google Ads account IDs. | |
| date_range_end | No | End date (YYYY-MM-DD). Defaults to today. | |
| date_range_start | No | Start date (YYYY-MM-DD). Defaults to 30 days ago. | |
| zero_conversions_only | No | Return only terms with zero conversions (wasted spend). Default false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It helpfully defines wasted spend as terms with budget consumed but zero conversions and discloses the response-level fields (total_spend, wasted_spend, wasted_spend_pct), which partly compensates for the missing output schema. It says nothing about permissions, rate limits, or result volume behavior.
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?
Front-loaded with purpose, then readable guidance sentences. Efficient overall, though the min_spend and zero_conversions_only sentences largely duplicate schema text and could be trimmed.
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?
For an 8-parameter read tool with no annotations and no output schema, the description covers return aggregates and the key filtering flags, which is most of what an agent needs. Missing pieces are auth/client resolution details and pagination/limit behavior.
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%, so the schema already documents all 8 parameters, and the baseline is 3. The description restates zero_conversions_only and min_spend semantics that the schema already provides, adding no format or interaction detail beyond it.
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?
States a specific verb and resource ('Retrieves search term performance data from Google Ads') and frames the distinctive purpose (identifying wasted spend), which separates it from get_google_ads_keywords and the campaign-performance siblings. It does not explicitly name those siblings, so it stops short of a 5.
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?
Gives concrete invocation guidance: zero_conversions_only=true to focus exclusively on wasted spend, min_spend to filter negligible terms, and list_clients to discover client IDs. It lacks an explicit 'when not to use this vs get_google_ads_keywords' comparison, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_meta_anomaly_signalA
Detects daily anomalies in Meta campaign performance using a rolling-baseline Z-score model — equivalent in intent to Meta's MCP ads_insights_anomaly_signal but computed locally from /insights daily data (no new endpoint). For each campaign × metric (CTR, CPM, CPC, CPA, spend, conversions), evaluates the trailing days against a baseline of the prior baseline_days (default 14). Flags any day with |z| ≥ z_threshold (default 2.0). Severity: |z| ≥ 2× threshold = severe, ≥ 1.5× = moderate, otherwise mild. Direction: spike vs drop. Sorted severity → most-recent → |z|. Use to triage 'something changed yesterday' before doing a full audit.
| Name | Required | Description | Default |
|---|---|---|---|
| metrics | No | Subset of metrics to evaluate. Defaults to all six when omitted. | |
| client_id | No | Client identifier. | |
| z_threshold | No | Absolute Z-score threshold to flag a daily bucket. Default 2.0. Min 1, max 5. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| baseline_days | No | Rolling baseline window in days. Default 14. Min 7, max 60. | |
| ad_account_ids | No | Override the client's default Meta ad account IDs. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| date_range_start | No | YYYY-MM-DD. Defaults to baseline_days + 14 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the algorithm (rolling-baseline Z-score), the per-campaign-metric evaluation scope, severity banding (severe/moderate/mild based on multiples of threshold), direction (spike vs drop), and output ordering (severity → recency → |z|). It does not state auth requirements, rate limits, or computational cost, but the behavioral disclosure is unusually rich for an analysis tool.
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?
Front-loaded with the core purpose and carries dense technical detail in a few sentences. Every sentence contributes to understanding the algorithm or usage. Slightly long but justified by the complexity of the detection model; no obvious padding.
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?
For an analysis tool with 8 parameters, 100% schema coverage, no output schema, and no annotations, the description supplies the algorithmic context an agent needs to interpret results (what a flag means, severity levels, sorting). It does not describe the return format (list of anomalies with fields), which would help, but the core call-time context is complete.
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 the schema already documents all 8 parameters with defaults, ranges, and formats. The description adds semantic meaning by explaining what baseline_days and z_threshold do in the algorithm (trailing days vs prior baseline, flagging threshold), which is helpful context beyond the schema's terse descriptions. Baseline 3 is appropriate when the schema does the heavy lifting.
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?
States a specific verb+resource ('Detects daily anomalies in Meta campaign performance') and immediately distinguishes itself from the closest sibling by referencing Meta's MCP ads_insights_anomaly_signal and clarifying it is computed locally. An agent can differentiate this from get_meta_campaign_performance and get_tiktok_anomaly_signal without opening schemas.
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 states the use case at the end: 'Use to triage something changed yesterday before doing a full audit.' It also names the equivalent MCP tool, effectively routing the agent between local and remote anomaly detection. When-to-use is clear; when-not-to-use is implied by 'before doing a full audit.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_meta_auction_rankingsA
Returns Meta's three auction-ranking labels per ad: quality_ranking, engagement_rate_ranking, conversion_rate_ranking — each one of ABOVE_AVERAGE, AVERAGE, BELOW_AVERAGE_35/20/10, or UNKNOWN. Computes below_average_count (0–3) and sorts the worst offenders to the top — 2+ below-average rankings is a creative-refresh trigger. Filters out ads under min_impressions (default 1000) since Meta only assigns labels above that volume. Same data Meta's MCP ads_insights_auction_ranking_benchmarks exposes; runs against /act_/insights at level=ad.
| Name | Required | Description | Default |
|---|---|---|---|
| ad_ids | No | Filter to specific ad IDs. | |
| client_id | No | Client identifier. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| ad_account_ids | No | Override the client's default Meta ad account IDs. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| min_impressions | No | Drop ads below this impression threshold. Default 1000 — Meta does not assign labels under ~1000 impressions/week. | |
| date_range_start | No | YYYY-MM-DD. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, so the description carries the full burden and does well: it discloses the sort order (worst offenders to top), the below_average_count output, the default min_impressions threshold and why it exists (Meta never assigns labels under that volume), and the underlying endpoint (/act_<id>/insights at level=ad). It does not state auth requirements 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?
Dense but front-loaded: the return payload and label set come first, then the computation, then the sort rationale, then the filter. Every clause is informative; slightly long but not padded.
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?
For a 7-param read tool with 100% schema coverage and no output schema, the description explains the returned fields, the label semantics, the default threshold behavior, and the sort output. An agent has everything needed to call it correctly; only auth/permission context is absent.
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%, so the baseline is 3. The description reinforces the min_impressions default and its rationale and the meaning of the date range defaults (today, 30 days ago), adding minor value beyond the schema but not new syntax or constraints.
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?
States a specific verb and resource (returns Meta's three auction-ranking labels per ad) and enumerates the exact labels and value domains. An agent can distinguish this from siblings like get_meta_campaign_performance or get_tiktok_auction_rankings without opening the schema.
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?
Clearly establishes context: it filters out low-volume ads and surfaces worst offenders. It names the sibling Meta MCP tool (`ads_insights_auction_ranking_benchmarks`) for the same data, implying equivalence, but does not state when to prefer this tool over that one or over get_meta_campaign_performance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_meta_campaign_performanceA
Retrieves Meta (Facebook/Instagram) campaign performance metrics for a client. Returns normalized metrics: spend, impressions, clicks, reach, CTR, CPC, CPM, conversions, CPA, conversion value, ROAS. Supports filtering by date range, ad account IDs, campaign IDs, and campaign status. Data is returned at campaign × day granularity. Use list_clients to see available client IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| statuses | No | Filter by campaign status. Returns all statuses if omitted. | |
| client_id | No | Client identifier. Required when multiple clients are configured. Use list_clients to see available IDs. | |
| campaign_ids | No | Filter to specific campaign IDs. Returns all campaigns if omitted. | |
| ad_account_ids | No | Override the client's default Meta ad account IDs (format: act_XXXXXXXXX or plain ID). | |
| date_range_end | No | End date in YYYY-MM-DD format. Defaults to today. | |
| date_range_start | No | Start date in YYYY-MM-DD format. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears the full burden. It discloses the return granularity (campaign × day) and enumerates returned metrics, which is helpful. But it doesn't mention authentication needs, rate limits, pagination behavior, or what happens when client_id is omitted but multiple clients are configured (schema hints it's required then, but description is silent).
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?
Four sentences, each front-loaded and informative: purpose, return metrics, filtering, granularity, and a pointer to list_clients. No redundancy or filler.
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?
The description covers purpose, filters, and return granularity, but with no annotations and no output schema, it should do more to disclose behavioral traits like required permissions or default behaviors when parameters are omitted. It's adequate but not rich enough for a tool with six optional parameters.
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%, so the schema already documents all six parameters in detail. The description adds only a high-level overview of filters (date range, account/campaign IDs, status) without adding syntax, format details, or constraints beyond what the schema provides. Baseline 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?
States a clear verb (Retrieves) and specific resource (Meta campaign performance metrics) with explicit scope (Facebook/Instagram). It distinguishes itself from Google/TikTok siblings by platform, though it doesn't differentiate from get_meta_hourly_performance, which is a plausible confusion given the sibling list.
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?
It advises using list_clients to find client IDs and describes what filters are available, which implies usage. However, it gives no explicit guidance on when to use this tool versus get_meta_hourly_performance or get_meta_opportunity_score, leaving the agent to infer based on granularity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_meta_hourly_performanceA
Returns Meta Ads performance broken down by hour-of-day (0–23) and day-of-week (MONDAY–SUNDAY) per campaign. Use for dayparting / ad-set scheduling analysis — identify when ads perform best and worst in the advertiser's audience time zone. Metrics per bucket: impressions, clicks, spend, conversions (from client.meta_ads.conversion_action), conversion_value, ctr, cpc, cpa, roas. Day-of-week is derived client-side from the Meta insights date; hours are buckets from Meta's hourly_stats_aggregated_by_audience_time_zone breakdown.
| Name | Required | Description | Default |
|---|---|---|---|
| client_id | No | Client identifier. Use list_clients to see available IDs. | |
| campaign_ids | No | Filter to specific campaign IDs. Returns all campaigns if omitted. | |
| ad_account_ids | No | Override the client's default Meta ad account IDs. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| date_range_start | No | YYYY-MM-DD. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears full burden. It discloses the time-zone semantics (audience time zone) and how dimensions are derived (day-of-week client-side, hours from Meta's hourly_stats_aggregated_by_audience_time_zone), which is useful behavioral context. However, it omits the safety profile (read-only?), rate limits, and pagination behavior.
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 dense sentences with no filler. The purpose and use case are front-loaded, followed by metric and derivation details. Slightly long but every clause earns its place for a complex analytical tool.
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 exists, so the description correctly enumerates the returned metrics and their sources. It covers the analytical context and data derivation. Lacks explicit mention of the zero-required-parameter behavior (e.g., returns all campaigns if campaign_ids omitted, defaults for date range are in schema). Fairly complete but missing some operational details.
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%, so the schema already documents all five parameters. The description adds no additional meaning about parameter syntax or defaults beyond what the schema provides. Baseline 3 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?
States a specific verb and resource ('Returns Meta Ads performance broken down by hour-of-day and day-of-week per campaign'), distinguishing it explicitly from the sibling get_meta_campaign_performance, which lacks the dayparting dimension. The granularity (hour 0-23, MONDAY-SUNDAY) is unambiguous.
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?
Gives a clear use case ('Use for dayparting / ad-set scheduling analysis') and the analytical goal ('identify when ads perform best and worst'). Does not explicitly name the alternative (get_meta_campaign_performance) or state when not to use this tool, but the intended context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_meta_opportunity_scoreA
Returns Meta's account-level Opportunity Score (0–100) plus the active recommendations queue (consolidation, Advantage+, audience expansion, creative variants, etc.). Wraps the /act_/recommendations Marketing API edge — same data Meta's official MCP surfaces, but using the client's stored access token. Each recommendation is normalized: { recommendation_type, level, entity_id, title, description, estimated_lift, status }. Use to (a) score an account quickly, (b) feed concrete recommendations into a Meta audit, (c) prioritise the highest-lift fixes.
| Name | Required | Description | Default |
|---|---|---|---|
| client_id | No | Client identifier. Use list_clients to see available IDs. | |
| ad_account_ids | No | Override the client's default Meta ad account IDs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does well: it names the underlying Marketing API edge (/act_<id>/recommendations), discloses the auth model ('client's stored access token'), and describes the normalized return shape. It does not state whether the call is read-only or how large the recommendation queue can get, but for a read-style score endpoint the disclosure is above par.
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?
Front-loads what is returned, then the mechanics, then the use cases; no filler sentences. It is slightly dense with parenthetical detail, but every clause carries 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?
There is no output schema, and the description compensates by listing the normalized fields of each recommendation and the score range. It stops short of explaining how to interpret the 0–100 scale, empty queues, or partial-failure behavior, leaving a small gap for a two-parameter aggregation 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% — client_id points at list_clients in the schema and ad_account_ids documents its override behavior — so the schema does the heavy lifting. The description adds only the implicit link that the stored access token is resolved via the client, not new per-parameter semantics. Baseline 3 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?
States a specific verb and resource — Meta's account-level Opportunity Score plus the recommendations queue — and enumerates the recommendation categories covered. It is clearly distinguishable from the sibling performance/auction/anomaly tools, which return metrics rather than scores and recommendations.
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 enumerates three usage contexts: scoring an account quickly, feeding recommendations into a Meta audit, and prioritising high-lift fixes. Strong positive guidance, but it names no alternatives or when-not conditions (e.g., when to prefer the performance tools instead).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tiktok_ad_performanceA
Returns TikTok Ads performance at the ad level (campaign → ad group → ad). Includes the four core video-engagement signals: video_play_actions, video_watched_2s, video_watched_6s, average_video_play_per_user. video_watched_2s / impressions = hold rate (best proxy for hook strength on TikTok). 2s hold < 30% = creative-refresh signal.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of ad rows. Default 100, max 500. | |
| ad_ids | No | Filter to specific ad IDs. | |
| statuses | No | Filter by ad status. | |
| client_id | No | Client identifier. | |
| adgroup_ids | No | Filter to specific ad-group IDs. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| advertiser_ids | No | Override the client's default advertiser ID. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| date_range_start | No | YYYY-MM-DD. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It adds real value by naming the four video-engagement metrics and an interpretation rule, but says nothing about pagination behavior, return format, auth requirements, or rate limits for a 9-parameter list tool.
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?
Front-loads the core purpose then adds three tight metric-definition sentences. Dense and readable, though the metric list could be trimmed by an agent that already knows TikTok terminology.
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?
For a 9-parameter read tool with no annotations and no output schema, the description explains the return metrics but omits pagination limits (limit max 500 is in schema), default date behavior, and how it differs operationally from sibling performance tools. Adequate but with clear gaps.
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%, so all nine parameters (limit, ad_ids, statuses, client_id, date_range, etc.) are already documented in the schema. The description adds no per-parameter syntax or meaning beyond what the schema provides, so the baseline of 3 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?
States a specific verb and resource (returns TikTok Ads performance) and explicitly scopes it to the ad level with the campaign → ad group → ad hierarchy. Distinguishes it from sibling get_tiktok_campaign_performance by naming the ad grain.
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 implies performance-analysis usage and gives an interpretive heuristic (2s hold < 30% = creative-refresh signal), but never states when to use this tool versus get_tiktok_campaign_performance or get_tiktok_hourly_performance. No explicit when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tiktok_anomaly_signalA
Detects daily anomalies in TikTok campaign performance using the same rolling-baseline Z-score model as get_meta_anomaly_signal. For each campaign × metric (CTR, CPM, CPC, CPA, spend, conversions), evaluates trailing days against a baseline of the prior baseline_days (default 14). Flags any day with |z| ≥ z_threshold (default 2.0). Severity: |z| ≥ 2× threshold = severe, ≥ 1.5× = moderate, otherwise mild. Sorted severity → most-recent → |z|.
| Name | Required | Description | Default |
|---|---|---|---|
| metrics | No | Subset of metrics to evaluate. | |
| client_id | No | Client identifier. | |
| z_threshold | No | Absolute Z-score threshold to flag a daily bucket. Default 2.0. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| baseline_days | No | Rolling baseline window in days. Default 14. | |
| advertiser_ids | No | Override the client's default advertiser ID. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| date_range_start | No | YYYY-MM-DD. Defaults to baseline_days + 14 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the algorithm (rolling-baseline Z-score), the defaults (baseline_days=14, z_threshold=2.0), the severity tiering rules, and the result ordering (severity → most-recent → |z|). It omits auth/data-source constraints and any pagination or result-size behavior, so it stops short of a 5.
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?
Four dense sentences, fully front-loaded with purpose first, then model, then mechanics, then ordering. No filler and nothing repeated from structured fields.
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?
For an 8-param, no-annotation, no-output-schema tool, the description supplies the algorithm, defaults, severity logic, and sort order an agent needs to interpret results. It leaves the returned payload shape and data-source scope unspecified, which is the only meaningful gap.
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 is 3, but the description adds genuine derived meaning: severity tiers are computed relative to z_threshold, and date_range_start defaults to baseline_days + 14 days ago, a relationship not visible in the schema. It also enumerates the six evaluated metrics, reinforcing the schema enum.
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?
States a specific verb (detects), resource (daily anomalies in TikTok campaign performance), and the model used, and explicitly names the sibling it mirrors (get_meta_anomaly_signal). An agent can distinguish it from get_tiktok_campaign_performance and the meta sibling without opening any schema.
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 positions this as the TikTok counterpart to get_meta_anomaly_signal and describes the evaluation scope (campaign × metric), which implies when it applies. But it never states when to prefer it over get_tiktok_campaign_performance or get_tiktok_hourly_performance, nor any prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tiktok_auction_rankingsA
Returns per-ad TikTok ranking signals: video_quality_score (0–10), engagement_rate_ranking, conversion_rate_ranking — each one of ABOVE_AVERAGE / AVERAGE / BELOW_AVERAGE / UNKNOWN. Computes below_average_count (0–2) and sorts the worst offenders to the top — 1+ below-average rankings is a creative-refresh trigger on TikTok (the platform burns creatives faster than Meta). Filters out ads under min_impressions (default 1000). When a tier doesn't expose video_quality_score the field is null and the row still surfaces ranking labels.
| Name | Required | Description | Default |
|---|---|---|---|
| ad_ids | No | Filter to specific ad IDs. | |
| client_id | No | Client identifier. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| advertiser_ids | No | Override the client's default advertiser ID. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| min_impressions | No | Drop ads below this impression threshold. Default 1000. | |
| date_range_start | No | YYYY-MM-DD. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and does well: it discloses the sort order (worst offenders to top), a computed field (below_average_count), the impression filter and its default, and null-handling for tiers lacking video_quality_score. It omits auth requirements, pagination, and response envelope shape, keeping it short of a 5.
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 dense but well-packed sentences, front-loaded with the returned fields before behavior. Every sentence carries information, though the phrase about the platform burning creatives is slightly editorial.
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 no output schema and no annotations, the description adequately specifies the return fields, their value domains, the derived count, and sorting. It stops short of describing the overall result envelope or how multiple filter parameters combine, but covers what an agent needs to invoke it correctly.
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 the schema already documents all seven parameters and their defaults. The description only elaborates on min_impressions (its throttle purpose) and says nothing about ad_ids, campaign_ids, advertiser_ids, or the date range filters, so it adds little beyond baseline.
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?
States a specific verb (Returns) and resource (per-ad TikTok ranking signals) and enumerates the exact output fields: video_quality_score, engagement_rate_ranking, conversion_rate_ranking. An agent can distinguish this from get_tiktok_ad_performance and get_meta_auction_rankings purely from the description.
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?
Usage is implied through the statement that '1+ below-average rankings is a creative-refresh trigger on TikTok,' which signals the intended scenario. However, it never explicitly says when to choose this over siblings like get_tiktok_ad_performance or get_tiktok_campaign_performance, so the guidance remains inferential.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tiktok_campaign_performanceA
Retrieves TikTok Ads campaign performance metrics for a client. Returns normalized metrics: spend, impressions, clicks, CTR, CPC, CPM, conversions, CPA, conversion value, ROAS. Supports filtering by date range, advertiser IDs, campaign IDs, and campaign status. Data is returned at campaign × day granularity from the TikTok Marketing API /report/integrated/get/ endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| statuses | No | Filter by campaign status. | |
| client_id | No | Client identifier. Use list_clients to see available IDs. | |
| campaign_ids | No | Filter to specific campaign IDs. Returns all campaigns if omitted. | |
| advertiser_ids | No | Override the client's default TikTok advertiser ID. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| date_range_start | No | YYYY-MM-DD. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses data granularity (campaign × day) and the upstream endpoint (/report/integrated/get/), but omits pagination behavior, result limits, and whether client_id resolution requires a per-call lookup. Adds some value but leaves meaningful behavioral gaps for a data-retrieval tool.
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, front-loaded with purpose then return shape then capabilities; the metric enumeration is long but informative for an output-less schema. Little waste overall, though the API endpoint reference borders on internal detail.
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 exists, and the description compensates by naming the exact returned metrics and the row granularity. Filtering is covered, but pagination/row limits and behavior when client_id is omitted remain unstated, leaving a modest gap.
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%, so the schema already documents all six parameters including defaults and the list_clients pointer. The description merely paraphrases the same filter categories (date range, advertiser IDs, campaign IDs, status) without adding syntax, interaction, or precedence detail. Baseline 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?
States a specific verb (Retrieves) and resource (TikTok Ads campaign performance metrics) with the returned metric set enumerated. It also implies differentiation from siblings via the 'campaign × day granularity' note, though it never names the sibling tools it differs from (get_tiktok_hourly_performance, get_tiktok_ad_performance).
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?
It lists what can be filtered (date range, advertiser IDs, campaign IDs, status) but gives no explicit when-to-use guidance, no when-not-to-use, and no routing to alternative tools when a different granularity is needed. Usage is only implied by the description of capabilities.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tiktok_hourly_performanceA
Returns TikTok Ads performance broken down by hour-of-day (0–23) and day-of-week (MONDAY–SUNDAY) per campaign. Source: /report/integrated/get/ with stat_time_hour dimension. Hours are in the advertiser's account time zone. Use for dayparting / ad-schedule analysis. TikTok-specific peaks: lunch (12–14) and evening (19–23) in Spain.
| Name | Required | Description | Default |
|---|---|---|---|
| client_id | No | Client identifier. | |
| campaign_ids | No | Filter to specific campaign IDs. | |
| advertiser_ids | No | Override the client's default advertiser ID. | |
| date_range_end | No | YYYY-MM-DD. Defaults to today. | |
| date_range_start | No | YYYY-MM-DD. Defaults to 30 days ago. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry behavioral burden. It usefully discloses the underlying source endpoint, the stat_time_hour dimension, and—crucially—that hours are in the advertiser's account time zone. It does not cover permissions/auth needs, rate limits, or pagination. A meaningful addition beyond a bare description, but not a full behavioral profile for a no-annotation tool.
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 front-loaded sentences: what it returns, where it comes from, and when to use it. Efficient and well-organized. The Spain dayparting example is arguably extra but adds practical value; not wasteful overall.
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?
For a read-only reporting tool with no output schema, the description gives granularity, source endpoint, time-zone semantics, and usage context—enough for an agent to invoke it correctly. It lacks only auth/exclusion details, which is a minor gap given the structured fields present.
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%, so the schema already documents all five parameters. The description adds scope/context (per campaign, granularity) but no parameter-level syntax or defaults beyond what the schema provides. Baseline 3 is appropriate when the schema does the heavy lifting.
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 states a specific verb and resource ('Returns TikTok Ads performance') and pins down the exact granularity (hour-of-day 0–23 and day-of-week MONDAY–SUNDAY, per campaign). This clearly distinguishes it from the sibling get_tiktok_campaign_performance (daily/aggregate) and parallels get_meta_hourly_performance / get_google_ads_hourly_performance for other platforms.
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?
It gives explicit use context ('Use for dayparting / ad-schedule analysis') and cites TikTok-specific patterns, but does not state when NOT to use it or explicitly route to the alternative hourly tool for other platforms. The intent is clear, but the alternative-selection guidance is implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_clientsA
Lists all configured accounts available in this MCP server. For each account, shows the ID (used in other tools), name, and which platforms are configured (google_ads, meta_ads, tiktok_ads). Call this first when you need to know which client_id to pass to other tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose the return payload (ID, name, platforms), which is useful behavioral context, and 'Lists' implies a non-mutating read. But it says nothing about auth requirements, whether results are paginated, empty-state behavior, or caching/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 sentences, no filler, and the most important detail (call this first to get client_id) is placed at the end as the actionable takeaway after the payload description. Every sentence earns its place.
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?
For a parameterless discovery tool with no output schema, the description fully compensates by enumerating the returned fields and the platform enum values (google_ads, meta_ads, tiktok_ads). An agent has everything needed to call it and consume the result.
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?
With zero parameters, the baseline is 4. The description goes slightly beyond by explaining the meaning of the returned client_id ('used in other tools'), which is the key semantic an agent needs even though it isn't an input.
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?
States a specific verb and resource ('Lists all configured accounts available in this MCP server') and immediately clarifies the shape of what an account is (ID, name, platforms). An agent can distinguish it from the many per-platform performance siblings without opening any schema.
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?
Explicit routing instruction: 'Call this first when you need to know which client_id to pass to other tools.' That names both the trigger condition and the downstream dependency on sibling tools, which is exactly the guidance needed for a discovery tool.
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.
16 tool updates
v0.1.0- First observed
get_google_ads_campaign_performance - First observed
get_google_ads_hourly_performance - First observed
get_google_ads_impression_share - First observed
get_google_ads_keywords - First observed
get_google_ads_search_terms - First observed
get_meta_anomaly_signal - First observed
get_meta_auction_rankings - First observed
get_meta_campaign_performance - First observed
get_meta_hourly_performance - First observed
get_meta_opportunity_score - First observed
get_tiktok_ad_performance - First observed
get_tiktok_anomaly_signal - First observed
get_tiktok_auction_rankings - First observed
get_tiktok_campaign_performance - First observed
get_tiktok_hourly_performance - First observed
list_clients
TDQS
Scored across 16 tools
Each tool is scoped by a platform prefix (google_ads/meta/tiktok) plus a specific entity or metric, so even parallel tools like get_meta_hourly_performance and get_tiktok_hourly_performance or the two anomaly signals are clearly distinguishable by platform and purpose. There is no meaningful overlap where an agent could reasonably misselect.
All data tools follow the consistent get_{platform}_{metric_or_entity} pattern (e.g. get_google_ads_keywords, get_meta_auction_rankings, get_tiktok_anomaly_signal). The single discovery tool list_clients deviates slightly but is a natural, predictable exception with no competing convention.
16 tools sits at the upper edge of the ideal range, but the count is justified: three ad platforms each get parallel coverage of performance, hourly, and diagnostics. It is slightly heavy but every tool maps to a concrete analytical need rather than being filler.
The surface covers a strong analytics lifecycle across all three platforms: campaign performance, dayparting/hourly, auction rankings, anomaly detection, plus discovery. Minor asymmetries exist (Google Ads has no auction-rankings or anomaly tool, and Meta lacks ad-level performance), but these are workaroundable gaps rather than dead ends.
Maintenance
Related MCP Connectors
- mcp-serverOAuthco.flyweel
Access Google & Meta Ads data via AI. Analyse campaign performance in seconds.
Run Google Ads and Meta Ads from ChatGPT or Claude: audit wasted spend, create and manage campaigns.
- MCP AdsOAuthcom.mcp-ads
Run Google Ads, Meta Ads, GA4 and Search Console from chat: read, audit and launch campaigns.
Build, edit and sync Google, Microsoft, Reddit and Meta ad campaigns from your assistant.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to manage TikTok advertising campaigns through the TikTok Ads API. Supports campaign creation, performance analytics, audience management, creative operations, and custom reporting through natural language interactions.49MIT
- FlicenseBqualityCmaintenanceExposes Google Ads and Meta Marketing performance data, campaign settings, and change history to Claude (Cowork) for live daily-dashboard workflows.3-
- FlicenseNot gradedqualityDmaintenanceProvides read-only access to Meta Ads API, enabling campaign management, creative analysis, targeting research, and performance analytics via 39 tools.-
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to create, analyze, and optimize ad campaigns across Google Ads, Meta Ads, TikTok Ads, LinkedIn Ads, Amazon Ads, and ChatGPT Ads through natural language using 400+ tools.93MIT