HYPD AI - OpenAI Ads
Provides read-only access to the OpenAI Ads API, enabling listing and retrieval of ad accounts, campaigns, ad groups, ads, and performance insights.
openai-ads-mcp
A Model Context Protocol (MCP) server for the OpenAI Ads (Advertiser) API. It lets MCP-compatible clients — Claude Desktop, Cursor, VS Code, and others — read your OpenAI Ads campaigns, ad groups, ads, and performance insights through natural language.
Read-only. This first release only reads data — it never creates, edits, or pauses anything and never spends budget. Write actions are on the roadmap.
Unofficial. This is a community project and is not affiliated with or endorsed by OpenAI. See the disclaimer.
Overview
The OpenAI Ads API exposes an advertiser's account, campaigns, ad groups, ads, and reporting. This server wraps the read endpoints of that API as MCP tools so an AI assistant can answer questions like:
"Is my OpenAI Ads API key working? What account is it tied to?"
"List my active campaigns and their budgets."
"Show spend, clicks, and CTR for campaign
cmp_123over the last 30 days, by day.""Which ads in ad group
adg_456are still pending review?"
Related MCP server: Ads MCP
Features
11 read-only tools covering the account, campaigns, ad groups, ads, and insights at every level.
Faithful responses — the API's JSON is returned as-is, so nothing is lost in translation.
Clear errors — HTTP status and the API error body are surfaced to the model instead of being swallowed.
Micros-aware — every tool description explains the micros convention so the assistant can present human-readable currency.
Cursor pagination passthrough (
limit,order,after,before).Zero-install via
npx—npx -y @hypd-ai/openai-ads-mcp, no clone or build.
Tools
Tool | What it does |
| Fetch the ad account for the configured key. Great as a connectivity check. |
| List campaigns (objective, budget, country targeting). |
| Fetch a single campaign by ID. |
| List ad groups, optionally filtered by campaign. |
| Fetch a single ad group by ID (bidding config, context hints). |
| List ads, optionally filtered by ad group. |
| Fetch a single ad by ID (creative + review status). |
| Performance insights for the whole account. |
| Performance insights for one campaign. |
| Performance insights for one ad group. |
| Performance insights for one ad. |
Insights tools accept since/until (YYYY-MM-DD) for the reporting window, plus time_granularity (daily/none), aggregation_level, fields, sort, filters, limit (1–10000), and after/before cursors.
Prerequisites
Node.js 20 or newer.
An OpenAI Ads API key. Create an Ads account at ads.openai.com (currently US-only), then issue a key from Settings → ads.openai.com/settings. See the quickstart and authentication docs. Each key is scoped to a single ad account.
Installation & configuration
MCP clients launch the server as a subprocess and pass your API key via an environment variable.
Published on npm as
@hypd-ai/openai-ads-mcp—npxfetches it for you, so there's nothing to clone or build. To run the latest unreleasedmaininstead, replace@hypd-ai/openai-ads-mcpwithgithub:HYPD-AI/openai-ads-mcp(its first launch builds from source — see Running from source).
Add the snippet for your client below.
Claude Desktop
Edit your claude_desktop_config.json:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"openai-ads": {
"command": "npx",
"args": ["-y", "@hypd-ai/openai-ads-mcp"],
"env": {
"OPENAI_ADS_API_KEY": "your-openai-ads-api-key"
}
}
}
}Restart Claude Desktop, then ask: "Use the openai-ads tools to look up my ad account."
Cursor
Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project):
{
"mcpServers": {
"openai-ads": {
"command": "npx",
"args": ["-y", "@hypd-ai/openai-ads-mcp"],
"env": {
"OPENAI_ADS_API_KEY": "your-openai-ads-api-key"
}
}
}
}VS Code
Add to .vscode/mcp.json. VS Code can prompt for the key and store it as a secret via inputs:
{
"inputs": [
{
"type": "promptString",
"id": "openai_ads_api_key",
"description": "OpenAI Ads API key",
"password": true
}
],
"servers": {
"openai-ads": {
"command": "npx",
"args": ["-y", "@hypd-ai/openai-ads-mcp"],
"env": {
"OPENAI_ADS_API_KEY": "${input:openai_ads_api_key}"
}
}
}
}Other MCP clients
Any client that speaks MCP over stdio works. Run npx -y @hypd-ai/openai-ads-mcp (or node /path/to/dist/index.js) with OPENAI_ADS_API_KEY set in the environment.
Configuration
Variable | Required | Default | Description |
| Yes | — | Your OpenAI Ads API key, sent as a Bearer token. |
| No |
| Override the API base URL (useful for testing or a proxy). |
See .env.example.
A note on "micros"
Fields whose names end in _micros — for example a campaign's lifetime_spend_limit_micros or an ad group's max_bid_micros — are expressed in micros:
1,000,000 micros = 1 unit of the account's currency (e.g. $1.00 = 1,000,000 micros)So a lifetime_spend_limit_micros of 25000000 is $25.00. Divide a _micros value by 1,000,000 to display a human amount, or multiply by 1,000,000 to convert the other way.
Insights metrics are not micros. Reporting values like
spend,cpc, andcpmare already in the account's currency as decimals (e.g.spend: 42.75means $42.75).
Read-only by design
This release registers only read (GET) tools — and each one is annotated with the MCP readOnlyHint, so well-behaved clients know it cannot mutate state. There is no tool here that can create, edit, pause, or delete anything, and nothing that can spend budget. Write actions will arrive as a deliberate, separately reviewed step (see Roadmap).
Running from source
git clone https://github.com/hypd-ai/openai-ads-mcp.git
cd openai-ads-mcp
npm install
npm run buildThen point your MCP client at the built entry file:
{
"mcpServers": {
"openai-ads": {
"command": "node",
"args": ["/absolute/path/to/openai-ads-mcp/dist/index.js"],
"env": {
"OPENAI_ADS_API_KEY": "your-openai-ads-api-key"
}
}
}
}Try it with the MCP Inspector
OPENAI_ADS_API_KEY=your-key npx @modelcontextprotocol/inspector node dist/index.jsDevelopment
npm install # install dependencies
npm run dev # rebuild on change (tsup --watch)
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm run format # prettier --write
npm test # vitest
npm run build # bundle to dist/Project layout:
src/
index.ts # bin entry: load config, build server, connect stdio
server.ts # buildServer(): McpServer + register all tools
client.ts # OpenAIAdsClient: auth, URL building, errors
config.ts # environment parsing & validation
schemas.ts # shared zod shapes (pagination, insights) + micros note
tools/ # one file per resource (account, campaigns, ad-groups, ads, insights)
test/ # vitest specs (config, client, in-memory server)How tools map to the API
All endpoints are under the base URL (default https://api.ads.openai.com/v1).
Tool | Method | Endpoint |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Roadmap
✍️ Write actions — create & update (via
POST) campaigns, ad groups, and ads, plus the dedicated state transitions (POST .../activate,.../pause,.../archive). The HTTP client already supportsPOST; these will be gated behind an explicit opt-in, since they change delivery and spend.🖼️ Creative uploads —
POST /upload(JSONimage_urlormultipart/form-data) to attach images to ad creatives.🌍 Campaign targeting — country include/exclude (
targeting.locations.countries).📈 Conversions API support.
🌐 Remote/HTTP transport for hosted deployments.
📦 Published npm release so
npx -y openai-ads-mcpworks out of the box.
Contributing
Contributions are welcome! Please read CONTRIBUTING.md. In short: open an issue to discuss substantial changes, keep npm run lint && npm run typecheck && npm test green, and add tests for new behavior.
Disclaimer
This is an unofficial, community-built project. It is not affiliated with, endorsed by, or sponsored by OpenAI. "OpenAI" and related names and logos are trademarks of OpenAI. Your use of the OpenAI Ads API through this tool is subject to OpenAI's terms and policies. The tool is provided "as is", without warranty of any kind — see the license.
License
MIT © HYPD AI
Available Tools
11 toolsget_account_insightsGet ad account insightsARead-only
Retrieve performance insights aggregated across the entire ad account. Returns a list response (data[] with first_id/last_id/has_more for paging). Each row carries id, start_time, end_time, plus the projected fields such as impressions, clicks, spend, ctr, cpc, cpm, readable_time, campaign_name, ad_group_name, and ad_name. Combine aggregation_level, sort, and limit to rank entities (e.g. the top ad by clicks). Monetary metrics (spend, cpc, cpm) are in the account's currency as decimal values, not micros.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | Start date of the reporting window (inclusive), YYYY-MM-DD. Combined with `until` into a date_range time filter. | |
| until | No | End date of the reporting window (inclusive), YYYY-MM-DD. Combined with `since` into a date_range time filter. | |
| time_granularity | No | Aggregation bucket size: 'daily' for one row per day, or 'none' for a single aggregated row over the whole window. | |
| aggregation_level | No | Scope each row is aggregated to (e.g. 'ad' to break results out per ad even when querying a campaign). Combine with `sort` + `limit` to rank entities. | |
| fields | No | Fields to project in each row, e.g. ['ad_id','ad_name','campaign_name','readable_time','impressions','clicks','spend','ctr','cpc','cpm']. | |
| sort | No | Sort expressions applied in order, e.g. [{ "field": "clicks", "direction": "desc" }] to rank by most clicks. | |
| filters | No | Advanced filter expressions, passed through to the API as-is. | |
| limit | No | Maximum number of rows to return (1-10000). | |
| after | No | Pagination cursor: pass `last_id` from a previous page to fetch the next page. | |
| before | No | Pagination cursor: pass `first_id` from a previous page to fetch the previous page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are readOnlyHint and openWorldHint. The description adds value beyond annotations by detailing the list response format with paging (first_id, last_id, has_more), mentioning monetary metrics are decimal (not micros) in account currency, and listing typical fields. No contradiction.
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 detailed but well-structured: front-loads purpose, then response format, then usage hint. Each sentence adds value, though slightly verbose. It efficiently communicates key 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?
Given no output schema, the description thoroughly explains return format (paging, fields, currency), parameter combinations, and filtering. Covers all 10 parameters with practical guidance, making it complete for effective tool usage.
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 has 100% coverage with descriptions for all 10 parameters. The description adds extra context by explaining the combined use of aggregation_level, sort, and limit for ranking, and clarifies monetary metric format (decimal vs micros), providing value beyond 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 retrieves performance insights aggregated across the entire ad account, distinguishing from sibling tools like get_campaign_insights by specifying 'across the entire ad account'. It also details the response structure and available fields.
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 explains how to combine aggregation_level, sort, and limit to rank entities (e.g., top ad by clicks), and mentions paging. It implies when to use this tool for account-level analysis, but does not explicitly state when not to use it or directly contrast with siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_adGet adARead-only
Fetch a single ad by its ID, including its creative and review status.
| Name | Required | Description | Default |
|---|---|---|---|
| ad_id | Yes | The ID of the ad to fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint and openWorldHint. Description adds useful context: ad includes creative and review status. No contradictions. Adds value beyond 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?
Single sentence, front-loaded with purpose, no extraneous words. Highly efficient.
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 one required parameter, no output schema, but annotations cover read-only and open-world. Description explains return content (creative, review status). Adequately complete for a simple fetch 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?
Schema covers 100% of parameters; ad_id is self-explanatory. Description does not add parameter-level detail but mentions what is returned (creative, review status), which is helpful but not about parameter semantics.
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 verb ('Fetch'), resource ('a single ad'), and scope ('including its creative and review status'). Distinguishes from siblings like list_ads (multiple ads) and get_ad_insights (analytics).
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?
Does not explicitly state when to use this tool versus alternatives like list_ads or get_ad_insights. Usage is implied from the name and description (fetching a single ad by ID), but no clear guidance on when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ad_accountGet ad accountARead-only
Fetch the ad account associated with the configured API key. Use this as a connectivity check to confirm the key is valid, and to read account-level details such as name, currency, status, and timezone. Each API key is scoped to a single ad account.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true; the description adds context that it is a connectivity check, returns specific fields (name, currency, status, timezone), and explains key-account scoping, exceeding what annotations alone provide.
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 three sentences, each adding value: purpose, usage guidance with specific returned details, and scoping constraint. 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 zero parameters and no output schema, the description fully covers what the tool does, when to use it, and what to expect. The name and sibling tools provide additional context.
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, and schema coverage is 100%. The description adds no parameter detail because none are needed; baseline 4 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 clearly states the tool fetches the ad account associated with the API key, specifies it is for connectivity checks and reading account-level details, and distinguishes from siblings (e.g., get_account_insights) by focusing on the account itself rather than insights.
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 recommends using it as a connectivity check and to read account details, and notes the API key scoping, but does not mention when not to use it or explicitly name alternatives, though siblings are listed separately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ad_groupGet ad groupARead-only
Fetch a single ad group by its ID, including its status, bidding configuration, and context hints. Monetary values are expressed in micros: 1,000,000 micros = 1 unit of the account's currency (for example, $1.00 = 1,000,000 micros). Divide any *_micros value by 1,000,000 to show a human-readable amount, and multiply by 1,000,000 to convert a currency amount into micros.
| Name | Required | Description | Default |
|---|---|---|---|
| ad_group_id | Yes | The ID of the ad group to fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint and openWorldHint. Description adds value by listing returned data (status, bidding, context) and explaining micros conversion. No contradictions.
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, no fluff. First sentence states purpose and contents, second adds essential micros detail. Efficient and well-structured.
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 what the tool returns and a key formatting detail. Lacks error handling or rate limits, but for a simple read tool with annotations, it is fairly 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 description covers the single parameter (ad_group_id). Description only reinforces 'by its ID'. With 100% schema coverage, baseline 3 is appropriate; minimal added value.
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?
Clearly states 'Fetch a single ad group by its ID' with specific fields (status, bidding configuration, context hints). Differentiates from sibling tools like list_ad_groups (list vs single) and get_ad_group_insights (different resource).
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?
Implies usage when you have an ad_group_id, but does not explicitly mention when not to use it or compare with alternatives. Sibling tools exist but no guidance on selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ad_group_insightsGet ad group insightsARead-only
Retrieve performance insights for a single ad group. Returns a list response (data[] with first_id/last_id/has_more for paging). Each row carries id, start_time, end_time, plus the projected fields such as impressions, clicks, spend, ctr, cpc, cpm, readable_time, campaign_name, ad_group_name, and ad_name. Combine aggregation_level, sort, and limit to rank entities (e.g. the top ad by clicks). Monetary metrics (spend, cpc, cpm) are in the account's currency as decimal values, not micros.
| Name | Required | Description | Default |
|---|---|---|---|
| ad_group_id | Yes | The ID of the ad group to report on. | |
| since | No | Start date of the reporting window (inclusive), YYYY-MM-DD. Combined with `until` into a date_range time filter. | |
| until | No | End date of the reporting window (inclusive), YYYY-MM-DD. Combined with `since` into a date_range time filter. | |
| time_granularity | No | Aggregation bucket size: 'daily' for one row per day, or 'none' for a single aggregated row over the whole window. | |
| aggregation_level | No | Scope each row is aggregated to (e.g. 'ad' to break results out per ad even when querying a campaign). Combine with `sort` + `limit` to rank entities. | |
| fields | No | Fields to project in each row, e.g. ['ad_id','ad_name','campaign_name','readable_time','impressions','clicks','spend','ctr','cpc','cpm']. | |
| sort | No | Sort expressions applied in order, e.g. [{ "field": "clicks", "direction": "desc" }] to rank by most clicks. | |
| filters | No | Advanced filter expressions, passed through to the API as-is. | |
| limit | No | Maximum number of rows to return (1-10000). | |
| after | No | Pagination cursor: pass `last_id` from a previous page to fetch the next page. | |
| before | No | Pagination cursor: pass `first_id` from a previous page to fetch the previous page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds value beyond annotations by explaining the return structure (list with paging) and that monetary metrics are in account currency as decimals, not micros. Annotations already declare readOnlyHint=true, so the description enhances transparency without contradiction.
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 concise paragraph with no redundant information. Every sentence adds value: purpose, return structure, field list, usage hints, and formatting edge cases. It is well-organized and front-loaded.
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 11 parameters, full schema coverage, and no output schema, the description covers the key aspects: return shape, paging, parameter combinations, and monetary formatting. It does not document error cases or prerequisites but is sufficient for a read-only 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%, but the description provides additional context on how to combine aggregation_level, sort, and limit for ranking, and clarifies monetary metric formatting. This goes above and beyond the parameter descriptions, adding meaningful guidance.
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 retrieves performance insights for a single ad group, specifying the verb 'Retrieve' and the resource 'performance insights for a single ad group'. It differentiates from siblings by focusing on ad_group level, not campaign or ad level.
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 usage for querying a single ad group's insights, but does not explicitly state when to use this tool versus alternatives like get_ad_insights or get_campaign_insights. It provides some guidance on combining parameters (aggregation_level, sort, limit) but lacks explicit when-not or exclusionary context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ad_insightsGet ad insightsARead-only
Retrieve performance insights for a single ad. Returns a list response (data[] with first_id/last_id/has_more for paging). Each row carries id, start_time, end_time, plus the projected fields such as impressions, clicks, spend, ctr, cpc, cpm, readable_time, campaign_name, ad_group_name, and ad_name. Combine aggregation_level, sort, and limit to rank entities (e.g. the top ad by clicks). Monetary metrics (spend, cpc, cpm) are in the account's currency as decimal values, not micros.
| Name | Required | Description | Default |
|---|---|---|---|
| ad_id | Yes | The ID of the ad to report on. | |
| since | No | Start date of the reporting window (inclusive), YYYY-MM-DD. Combined with `until` into a date_range time filter. | |
| until | No | End date of the reporting window (inclusive), YYYY-MM-DD. Combined with `since` into a date_range time filter. | |
| time_granularity | No | Aggregation bucket size: 'daily' for one row per day, or 'none' for a single aggregated row over the whole window. | |
| aggregation_level | No | Scope each row is aggregated to (e.g. 'ad' to break results out per ad even when querying a campaign). Combine with `sort` + `limit` to rank entities. | |
| fields | No | Fields to project in each row, e.g. ['ad_id','ad_name','campaign_name','readable_time','impressions','clicks','spend','ctr','cpc','cpm']. | |
| sort | No | Sort expressions applied in order, e.g. [{ "field": "clicks", "direction": "desc" }] to rank by most clicks. | |
| filters | No | Advanced filter expressions, passed through to the API as-is. | |
| limit | No | Maximum number of rows to return (1-10000). | |
| after | No | Pagination cursor: pass `last_id` from a previous page to fetch the next page. | |
| before | No | Pagination cursor: pass `first_id` from a previous page to fetch the previous page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint, openWorldHint) indicate it's a safe, non-destructive operation. The description adds value by detailing pagination (first_id/last_id/has_more) and emphasizing that monetary metrics are in account currency as decimals, not micros, which is beyond the 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?
The description is concise (one paragraph, ~100 words) and front-loaded with the main purpose. Every sentence adds value: output structure, paging, fields, ranking usage, and currency note. 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 11 parameters and no output schema, the description adequately explains the output format and paging. It mentions key fields that can be projected but omits full detail; however, the complexity is well-covered for a read-only insights 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%, baselined at 3. The description adds meaning by explaining how to combine aggregation_level, sort, and limit to rank entities, and clarifies monetary metric format, going beyond the parameter descriptions.
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 retrieves performance insights for a single ad, specifies the output as a list with paging, and lists projected fields. It uses a specific verb and resource, and the name distinguishes it from sibling tools like get_ad or get_campaign_insights.
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 usage for querying ad performance with aggregation, sort, and limit, but it does not explicitly state when to use this tool versus alternatives or provide exclusion criteria. The guidance is implicit rather than direct.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_campaignGet campaignARead-only
Fetch a single campaign by its ID, including its objective, status, budget, and targeting. Monetary values are expressed in micros: 1,000,000 micros = 1 unit of the account's currency (for example, $1.00 = 1,000,000 micros). Divide any *_micros value by 1,000,000 to show a human-readable amount, and multiply by 1,000,000 to convert a currency amount into micros.
| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The ID of the campaign to fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, indicating a safe read. The description adds behavioral details about the return fields and the micros conversion, which is valuable for the agent.
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: first states purpose and scope, second explains a critical monetary conversion detail. No wasted words, front-loaded.
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 sufficiently explains returned fields and micros handling. It is complete for a simple fetch operation, though error cases are omitted.
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 description adds minimal extra meaning beyond the campaign_id parameter. It does mention the returned fields, which provides context for what the parameter operation yields.
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 tool's purpose is clearly stated: fetching a single campaign by ID, including specific fields. This distinguishes it from sibling tools like list_campaigns (multiple campaigns) and get_campaign_insights (insights).
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: use when you need a campaign by ID. However, there is no explicit guidance on when not to use or alternatives, such as recommending list_campaigns for multiple campaigns.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_campaign_insightsGet campaign insightsARead-only
Retrieve performance insights for a single campaign. Returns a list response (data[] with first_id/last_id/has_more for paging). Each row carries id, start_time, end_time, plus the projected fields such as impressions, clicks, spend, ctr, cpc, cpm, readable_time, campaign_name, ad_group_name, and ad_name. Combine aggregation_level, sort, and limit to rank entities (e.g. the top ad by clicks). Monetary metrics (spend, cpc, cpm) are in the account's currency as decimal values, not micros.
| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The ID of the campaign to report on. | |
| since | No | Start date of the reporting window (inclusive), YYYY-MM-DD. Combined with `until` into a date_range time filter. | |
| until | No | End date of the reporting window (inclusive), YYYY-MM-DD. Combined with `since` into a date_range time filter. | |
| time_granularity | No | Aggregation bucket size: 'daily' for one row per day, or 'none' for a single aggregated row over the whole window. | |
| aggregation_level | No | Scope each row is aggregated to (e.g. 'ad' to break results out per ad even when querying a campaign). Combine with `sort` + `limit` to rank entities. | |
| fields | No | Fields to project in each row, e.g. ['ad_id','ad_name','campaign_name','readable_time','impressions','clicks','spend','ctr','cpc','cpm']. | |
| sort | No | Sort expressions applied in order, e.g. [{ "field": "clicks", "direction": "desc" }] to rank by most clicks. | |
| filters | No | Advanced filter expressions, passed through to the API as-is. | |
| limit | No | Maximum number of rows to return (1-10000). | |
| after | No | Pagination cursor: pass `last_id` from a previous page to fetch the next page. | |
| before | No | Pagination cursor: pass `first_id` from a previous page to fetch the previous page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are readOnlyHint=true and openWorldHint=true. The description adds valuable context: pagination details (first_id/last_id/has_more), monetary unit clarification (decimal, not micros), and the ability to rank entities. No contradiction with 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?
A single paragraph of four sentences, front-loaded with the primary purpose. It could be slightly more concise by omitting the list of fields, but overall it is efficient and readable.
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 11 parameters, no output schema, and the complexity of pagination and sorting, the description covers the key behavioral aspects: response structure, paging, currency format, and entity ranking. Lacks details on error conditions or advanced filtering, but is 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?
Schema description coverage is 100%, so baseline is 3. The description provides some additional meaning (e.g., decimal currency, paging fields) but does not significantly augment individual parameter descriptions beyond what the schema already provides.
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?
Clearly states 'Retrieve performance insights for a single campaign' – a specific verb and resource, and distinguishes from siblings that target different scopes (e.g., get_account_insights, get_ad_insights).
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?
Implies usage for campaign-level performance insights but does not explicitly compare to sibling tools or state when not to use it. No exclusions or alternatives are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_ad_groupsList ad groupsARead-only
List ad groups within a campaign (campaign_id is required). Ad groups belong to a campaign and hold the bidding configuration and context hints. Supports cursor pagination (order, after/before; the response includes first_id, last_id, and has_more). Monetary values are expressed in micros: 1,000,000 micros = 1 unit of the account's currency (for example, $1.00 = 1,000,000 micros). Divide any *_micros value by 1,000,000 to show a human-readable amount, and multiply by 1,000,000 to convert a currency amount into micros.
| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | Parent campaign ID. Required — ad groups are listed within a campaign. | |
| limit | No | Maximum number of objects to return per page (1-500). Uses the API default if omitted. | |
| order | No | Sort by creation time: 'asc' for oldest-first, 'desc' for newest-first. | |
| after | No | Pagination cursor. Pass the `last_id` from the previous page to fetch the next page. | |
| before | No | Pagination cursor. Pass the `first_id` from the previous page to fetch the previous page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint and openWorldHint, but description adds significant behavioral context: pagination support (cursor-based with `after`/`before`, `first_id`, `last_id`, `has_more`) and monetary micros conversion. No contradictions.
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?
Extremely concise and well-structured. Front-loads purpose, then adds necessary context in logical order. 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?
Covers key aspects: required campaign_id, pagination, micros conversion. With 5 parameters and no output schema, a bit more on response structure could be helpful, but current info is adequate.
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 baseline is 3. Description adds value by explaining pagination mechanisms and micros handling, which are not fully captured in parameter descriptions.
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?
Clearly states the tool lists ad groups within a campaign, requiring `campaign_id`. Distinguishes from sibling tools like `get_ad_group` (single fetch) and `list_ads` (different resource).
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 context: lists ad groups for a campaign, with pagination details. Lacks explicit when-not-to-use or alternatives, but the context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_adsList adsARead-only
List ads within an ad group (ad_group_id is required). Each ad holds a creative (title, body, target URL, image) and a review_status (in_review, approved, or rejected). Supports cursor pagination (order, after/before; the response includes first_id, last_id, and has_more).
| Name | Required | Description | Default |
|---|---|---|---|
| ad_group_id | Yes | Parent ad group ID. Required — ads are listed within an ad group. | |
| limit | No | Maximum number of objects to return per page (1-500). Uses the API default if omitted. | |
| order | No | Sort by creation time: 'asc' for oldest-first, 'desc' for newest-first. | |
| after | No | Pagination cursor. Pass the `last_id` from the previous page to fetch the next page. | |
| before | No | Pagination cursor. Pass the `first_id` from the previous page to fetch the previous page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint, openWorldHint), the description discloses cursor pagination behavior (order, after/before, first_id, last_id, has_more) and the review_status field, adding useful behavioral context.
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 two sentences with no wasted words. The first sentence states the action and requirement, and the second adds details about content and pagination, front-loading key 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?
The description explains the pagination mechanism and mentions ad fields, but without an output schema, it could be more explicit about the full response structure. It is mostly complete given the annotations and schema coverage.
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 parameters. The description adds context about ad content (creative fields, review_status) but does not significantly enhance parameter semantics beyond what the schema provides.
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 ads within an ad group, specifying the required parameter ad_group_id. It distinguishes from sibling tools like get_ad (single ad) and list_ad_groups (list groups).
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 indicates that ad_group_id is required and ads are listed within that group, which implies when to use this tool. However, it does not explicitly state when not to use it or mention alternatives like get_ad for a single ad.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_campaignsList campaignsARead-only
List campaigns in the ad account. Campaigns are the top-level objects that define the objective, budget, and country targeting. Supports cursor pagination; the response includes first_id, last_id, and has_more. Monetary values are expressed in micros: 1,000,000 micros = 1 unit of the account's currency (for example, $1.00 = 1,000,000 micros). Divide any *_micros value by 1,000,000 to show a human-readable amount, and multiply by 1,000,000 to convert a currency amount into micros.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of objects to return per page (1-500). Uses the API default if omitted. | |
| order | No | Sort by creation time: 'asc' for oldest-first, 'desc' for newest-first. | |
| after | No | Pagination cursor. Pass the `last_id` from the previous page to fetch the next page. | |
| before | No | Pagination cursor. Pass the `first_id` from the previous page to fetch the previous page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare `readOnlyHint: true` and `openWorldHint: true`. The description adds significant behavioral details: cursor pagination with `first_id`, `last_id`, and `has_more`, plus monetary micros conversion explanation. No contradiction with 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?
The description is compact (4 sentences), front-loaded with purpose, and each sentence adds value without repetition or fluff.
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 moderate complexity, no required parameters, and no output schema, the description covers key behavioral aspects (pagination, monetary units) adequately. It could mention the return format is a list of campaign objects, but that is implied by context.
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% with descriptions for all parameters. The description does not add parameter-specific details beyond the schema, but provides general context about pagination and micros that aids understanding. 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?
The description clearly states 'List campaigns in the ad account' and explains that campaigns are top-level objects defining objective, budget, and country targeting. This distinguishes it from sibling tools like `get_campaign` (single campaign) and `list_ad_groups` (different resource).
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 context that campaigns are top-level, implying use for listing all campaigns. It does not explicitly mention when not to use or suggest alternatives, but the context is clear enough.
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.
11 tool updates
v0.1.3- First observed
get_account_insights - First observed
get_ad - First observed
get_ad_account - First observed
get_ad_group - First observed
get_ad_group_insights - First observed
get_ad_insights - First observed
get_campaign - First observed
get_campaign_insights - First observed
list_ad_groups - First observed
list_ads - First observed
list_campaigns
TDQS
Scored across 11 tools
Each tool targets a distinct entity or scope (account, campaign, ad group, ad) with clear separation between get, list, and insights operations. No overlaps or ambiguity between tool purposes.
All tool names follow a consistent verb_noun pattern: get_<singular_entity> or list_<plural_entity> and get_<entity>_insights. The naming is predictable and uniform across the entire set.
With 11 tools covering account, campaign, ad group, and ad entities plus their insights, the count is well-scoped for an ad platform's read surface. No redundant or missing core tools.
The tool set is entirely read-only, lacking any create, update, or delete operations. This is a critical gap for an ad management platform, as agents cannot perform any mutations. Significant missing functionality for typical ad workflows.
Maintenance
Related MCP Connectors
Run Google Ads and Meta Ads from ChatGPT or Claude: audit wasted spend, create and manage campaigns.
Create, launch, and manage Meta + Google ads from Claude and ChatGPT.
Run Google, Meta, Microsoft, TikTok and LinkedIn Ads from Claude or ChatGPT. Writes need approval.
OpenAI Ads MCP for ChatGPT Ads campaigns, creatives, audiences, insights, and conversions.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables users to analyze, manage, and optimize digital advertising campaigns through natural language conversations in Claude, offering performance insights, interactive visualizations, and campaign management for platforms like Amazon Ads.4-
- 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

PaidSync MCP Serverofficial
AlicenseNot gradedqualityFmaintenanceConnects Google Ads, Meta Ads, and LinkedIn Ads to AI assistants, enabling natural language ad campaign management, reporting, and optimization across platforms.MIT- AlicenseAqualityAmaintenanceTri-channel AdsAgent plugin (Meta, Google Ads, TikTok): hosted OAuth MCP at adsagent.md plus agent skills for insights, templates, and prepare/confirm writes. Install via adsagents/adsagent-ai-skills. Meta MCP: https://adsagent.md/mcp/v2. Registry: md.adsagent/meta-mcp.43MIT