ChatGPT Ads MCP server
This MCP server lets you connect a ChatGPT Ads advertiser account to an MCP client to read campaign data and, optionally, prepare or apply ad-account changes.
Read account details, campaigns, ad groups, ads, creatives, and serving/review status.
Read performance insights, conversions, feeds, custom audiences, audit logs, spend limits, landing-page crawl evidence, and Bulk API jobs.
Search locations and inspect conversion settings, pixels, events, and feed products.
Access write schemas, write context, and mutation receipts/previews.
With writes enabled, create/update/pause/activate/archive campaigns, ad groups, and ads; upload images; manage conversion settings/pixels and feeds; and submit bulk jobs.
Writes preview by default, require explicit confirmation, and activation/spend changes require additional activation enablement.
Provides tools for interacting with the ChatGPT Ads (OpenAI Ads) Advertiser API, enabling reading and managing ad accounts, campaigns, ad groups, ads, creatives, insights, conversions, product feeds, custom audiences, audit logs, spend limits, and Bulk API jobs.
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., "@ChatGPT Ads MCP serverShow me last week's campaign performance and conversions."
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.
ChatGPT Ads MCP server
Bring your ChatGPT Ads account into your MCP client.
Read campaigns, performance and conversions, and prepare changes for the ad account your API key belongs to.
Watch the film · What's new · Install · Tool reference · Try hosted getmcpads

The film shows hosted getmcpads with sample data. Its MCP Apps, from creative galleries and alerts to Google Sheets exports and bulk launches, belong to the hosted product. This repository provides the standalone native API tools.
30 read tools · 28 write tools, disabled by default.
Run locally with your own Advertiser API key and a client that supports stdio MCP, such as Claude Desktop, Claude Code or Cursor. Your requests go directly to the ChatGPT Ads API. For managed connections, including supported ChatGPT setups, use the hosted option.
What's new
v1.0.1: Zod 4 security update · October 26, 2026
Update
zodto 4.6.7. Every Zod release before 4.6.6 is covered by the high-severity advisory GHSA-mrhx-c7xc-m3w5: validating an oversized constrained collection can exhaust memory, and no Zod 3 release carries the fix.npm audit --omit=devreports no vulnerability again.Keep the Zod 3 validation behaviour. A parameter default is still validated and completed before use, so an omitted object must still supply its required fields.
Keep each parameter's own description when the parameter is optional or has a default. Zod 4 stores a description on the wrapped schema only, so the shared fallback description could otherwise replace it.
Tool names, parameters and descriptions published over MCP are unchanged.
server-card.jsonis regenerated with Zod 4's JSON Schema output, which spells some constraints differently.
Earlier releases
Version | Date | Highlights |
1.0.0 | October 23, 2026 | First standalone release |
Source synchronization: SOURCE_SYNC.md.
Upgrade notes
Requires Node.js 22.23.4 or later on the 22 line, 24.22.1 or later on the 24 line, or 26.12.1 or later. These releases carry the October 2026 security fixes, and the server prints a warning on stderr when started on an older runtime. CI covers Node 22, 24 and 26. Writes remain optional and require explicit confirmation. Hosted creative integrations and MCP Apps UI are outside this release.
Related MCP server: OpenAI Ads MCP
Install this release
This is a GitHub source release. npm and MCP Registry versions are published separately. The commands below select this exact version; unpinned npx examples later in this document select the version currently available on npm.
git clone --branch v1.0.1 --depth 1 https://github.com/get-mcp-ads/chatgpt-ads-mcp-server.git
cd chatgpt-ads-mcp-server
npm ci
npm run buildConfigure your MCP client to run node with the absolute path to dist/cli.js and the environment variables documented below. With the npm package, a client configuration looks like this:
{
"mcpServers": {
"chatgpt-ads": {
"command": "npx",
"args": ["-y", "@getmcpads/chatgpt-ads-mcp-server"],
"env": {
"OPENAI_ADS_API_KEY": "your-advertiser-api-key",
"OPENAI_ADS_ACCOUNT_ID": "adacct_your_account"
}
}
}
}Run npm run doctor to check the configuration without contacting ChatGPT Ads, then call openai_ads_get_account first.
Managed connection. Use ChatGPT Ads with hosted getmcpads. Connect your account, select the data your assistant may access and use the hosted MCP connection. See the site for current features and plans.
Configuration
Provide these environment variables through the client's secret configuration:
Variable | Purpose |
| Required. An Advertiser API key created on the Settings page of Ads Manager. Each key is scoped to one ad account. This is not an OpenAI Platform API key. |
| Required. The |
| Defaults to |
| Defaults to |
You need an ad account in Ads Manager and an Advertiser API key, as described in OpenAI's Advertiser API overview. Some features are enabled per account: the Bulk API is in limited preview, and API partners need pixel management and conversion-optimized bidding enabled for each client account, as described in API Partner Setup. The server returns the native access error when a feature is not enabled. API use is governed by OpenAI's Advertising Terms, which require you to keep API keys confidential.
This package reads a key from the environment. It runs no browser sign-in and writes nothing to disk. To rotate the key, create a new one in Ads Manager, update the variable and restart the server.
Safety and coverage
Writes preview by default. A call without confirm returns the change, the native state it was checked against and a confirmationToken. After the person approves the exact preview, repeat the identical call with confirm: true and that token. Use one requestId UUID per logical change; creations send it as the native Idempotency-Key, which OpenAI uses to avoid creating a duplicate when the same creation is sent again.
Before applying, the server reads the native state again and refuses the write if it changed since the preview. After applying, it reads campaigns, ad groups, ads and feed products back and reports whether the change is confirmed.
Campaigns, ad groups and ads are created paused. Activation is refused unless OPENAI_ADS_ENABLE_ACTIVATION=true, and previews that can start delivery carry activationMaySpend: true.
A write whose outcome is uncertain is recorded as UNKNOWN and never resubmitted. Read the receipt with openai_ads_get_mutation and the native state before deciding anything else. Previews and receipts live in memory and a restart forgets them.
Account checks run before every request. Unknown arguments are rejected, and nested request bodies are validated against the pinned native schemas.
Requests go only to api.ads.openai.com with a 30 second timeout and an 8 MiB response bound. Redirects are refused. The key is removed from any provider text, and only validation errors return native messages. The API allows 600 requests per minute per endpoint and 1,200 overall; a throttled request returns RATE_LIMITED without a retry.
Budgets and bids use integer micros of the account currency (1,000,000 is one unit). Reported spend, CPC and CPM use major units, CTR and conversion rates are fractions, and missing values stay null. Product feed prices use minor units (7999 is USD 79.99).
This server exposes a reviewed subset of the API. It leaves out API key provisioning, billing and spend limit changes, account administration, partner account creation, custom audience creation and membership uploads, lead sync webhooks and SFTP credentials. New upstream endpoints are not exposed automatically.
Use tools/list or server-card.json for exact schemas, openai_ads_get_write_schema for nested request fields, and the official API reference for provider details.
Hosted option
getmcpads for ChatGPT Ads manages the hosted connection and account selection. Hosted and source releases can differ. Contact: hello@getmcpads.com.
Development
npm run typecheck
npm run lint
npm run build
npm test
npm run catalogAll tests run offline with synthetic responses. No live account is read or changed. To refresh the pinned schemas, save the official OpenAPI document and run node scripts/generate-contracts.mjs <path> <date>.
Tools
Every tool is listed below. See server-card.json for complete parameter and output schemas. Every tool takes adAccountId, the account in OPENAI_ADS_ACCOUNT_ID.
Tool | Purpose |
| Read the account's name, currency, time zone, status and brand review, and verify that the key belongs to it. |
| List one page of campaigns. |
| Read one campaign with its budget, schedule and targeting. |
| List one page of the ad groups of a campaign. |
| Read one ad group with its bidding, context hints and product set. |
| List one page of the ads of an ad group, with creative metadata and review status. |
| Read one ad with its creative and review status. |
| List chat card creatives with their file IDs and signed image links, refreshing expired links. |
| Read performance by account, campaign, ad group or ad, with one optional country, device or platform breakdown and attribution settings. |
| Search country, region and market location IDs for geographic targeting. |
| List recorded changes to campaigns, ad groups and ads. |
| Read the account's spend limit windows. |
| Read the landing page crawl evidence for an ad's submitted version. |
| List conversion event settings, the goals a campaign can use. |
| List conversion pixels and connected pixel IDs. |
| List recent sampled conversion events, to check that a pixel or server integration sends data. |
| Read attributed conversion totals or daily values, optionally by country or device. |
| List product feeds, optionally with product counts. |
| List recent product feed uploads and their results. |
| Read a feed's display and organic-listing settings. |
| List feed products that match ad group product filters. |
| List custom audiences. |
| Read one custom audience and its matched count. |
| List the accepted operations of a custom audience. |
| Read the state of one custom audience operation. |
| Read the status of a Bulk API job. |
| Read one page of a Bulk API job's operation outcomes. |
| Read the pinned native request definitions, upload and bulk limits, and the exclusions. |
| Read the account, conversion settings and feeds before proposing a campaign, with the supported bid combinations. |
| Read a write preview or receipt held by this server process. |
Disabled by default. Calls preview unless explicitly confirmed. Check the configuration and exact schema before use.
Tool | Purpose |
| Create a paused campaign with its objective, budget, schedule and targeting. |
| Update campaign settings such as budget, schedule or targeting. |
| Pause a campaign. |
| Activate a campaign. Can spend budget; requires |
| Archive a campaign. |
| Create a paused ad group with its bidding, context hints and product set. |
| Update ad group settings such as bidding or context hints. |
| Pause an ad group. |
| Activate an ad group. Can spend budget; requires |
| Archive an ad group. |
| Create a paused ad with a chat card or product template creative, which enters review. |
| Update an ad's name or creative. A creative edit starts a new review. |
| Pause an ad. |
| Activate an ad. Can spend budget; requires |
| Archive an ad. |
| Create a temporary preview of an existing ad. |
| Rename a campaign. The name is the only field that changes. |
| Rename an ad group. The name is the only field that changes. |
| Rename an ad. The name is the only field that changes. |
| Upload PNG, JPEG or WebP bytes of at least 640 x 640 and return a file ID for a chat card. |
| Have OpenAI import a public HTTPS image and return a file ID. |
| Create a conversion event setting for a standard or custom event. |
| Create a conversion pixel. |
| Create a product feed. |
| Update a feed's display name and organic-listing settings. |
| Update the title, price or availability of up to 500 existing product variants. |
| Archive a product feed. |
| Submit a Bulk API job of up to 1,000 operations, validation only by default. |
Resource | Content |
| Account scope, write flow, units, rate limits, supported metrics, levels, breakdowns and attribution options. |
License
Apache License 2.0. See NOTICE.
More from getmcpads
Meta Ads · Google Ads · Google Analytics 4 · Google Search Console · TikTok Ads · Pinterest Ads · X Ads
Maintained by Emmanuel at getmcpads. Questions: hello@getmcpads.com.
Available Tools
30 toolsopenai_ads_get_accountopenai ads get accountARead-onlyIdempotent
Read the configured ChatGPT Ads account: name, currency, time zone, status and brand review. Also verifies that the API key belongs to OPENAI_ADS_ACCOUNT_ID. Run it first.
| Name | Required | Description | Default |
|---|---|---|---|
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive. The description adds that the call validates API key ownership and refuses a mismatched account ID, which is useful context beyond the safety hints, though it doesn't mention rate limits or error shapes.
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 compact sentences, front-loaded with the core read action and followed by the verification behavior. Nothing redundant or 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?
With an output schema available, the description needn't explain return structure; it summarizes returned fields and the key verification behavior. Combined with annotations and a fully documented single parameter, an agent has everything needed to call 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 adAccountId pattern and refusal-on-mismatch semantics are already documented in the schema. The description reinforces the single-account scoping but adds no format or syntax details beyond that 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 and resource ('Read the configured ChatGPT Ads account') and enumerates what is returned (name, currency, time zone, status, brand review). An agent can distinguish it from the many sibling get_* tools that fetch campaigns, insights, or settings.
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?
'Run it first' gives explicit ordering guidance, and the note about verifying the API key against OPENAI_ADS_ACCOUNT_ID clarifies its role as a preliminary validation call. It does not name exclusions or alternatives, but the sequencing instruction is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_adopenai ads get adARead-onlyIdempotent
Read one ad with its creative and review status. No preview or change is requested.
| Name | Required | Description | Default |
|---|---|---|---|
| adId | Yes | Native ad ID (ad_) in the configured account. | |
| include | No | Add serving_issues to receive native reasons why this entity cannot serve. A paused state is intentional, not an issue. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds value by specifying the returned content (creative and review status) and explicitly ruling out preview, which is not captured by 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?
Two compact sentences with zero filler, front-loading the core action and then the exclusion. Every phrase 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?
Given full schema coverage and a present output schema, the description provides enough to call this tool correctly: it states the read-only nature, the resource, and the returned fields. It could be slightly richer by naming the list alternative, but nothing essential is missing.
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%, and all three parameters are well documented in the schema, including the account scoping and the optional serving_issues include. The description adds no parameter-level meaning beyond what the schema provides, so the 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 ("Read one ad") and what it returns ("creative and review status"), which distinguishes it from the plural list sibling openai_ads_get_ads. It stops short of naming that sibling explicitly, so the differentiation is implied rather than stated.
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?
"No preview or change is requested" signals this is a pure read and rules out mutation or preview workflows, which is useful context. However, it never says when to choose this over openai_ads_get_ads or openai_ads_list_ad_creatives, nor does it mention prerequisites beyond what the schema already documents.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_ad_groupopenai ads get ad groupARead-onlyIdempotent
Read one ad group with its native bidding, context hints and product set.
| Name | Required | Description | Default |
|---|---|---|---|
| include | No | Add serving_issues to receive native reasons why this entity cannot serve. A paused state is intentional, not an issue. | |
| adGroupId | Yes | Native ad group ID (adgrp_) in the configured account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is fully covered. The description adds a small amount of value by naming the returned aspects, but says nothing about permissions, errors, or cost beyond what annotations 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?
A single front-loaded sentence with no filler; the resource and the returned content are stated immediately.
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 simple read-by-ID tool with an output schema, full annotation coverage and 100% documented parameters, the description covers the essentials. It could be slightly stronger by naming the list sibling or the serving_issues include option, but nothing critical is missing.
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%, including the include=serving_issues option and the account-scoping constraint, so the schema does the heavy lifting and baseline 3 applies. The description contributes no additional parameter semantics (it never mentions include or the ID formats).
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 ('Read one ad group') and names the payload it returns (native bidding, context hints, product set). The singular 'one ad group' implicitly contrasts with the get_ad_groups list sibling, though it never names it explicitly.
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 when-to-use is only implied by the tool name and singular scope: fetch a single ad group by its adgrp_ ID rather than listing. There is no explicit statement of when to choose this over get_ad_groups or get_campaign, and no prerequisites are mentioned beyond what the schema already says about the scoped account.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_ad_groupsopenai ads get ad groupsARead-onlyIdempotent
List one page of ad groups in a campaign. Native ad group IDs start with adgrp_. Follow last_id only when has_more is true.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Return only entities whose name matches this text, 3 to 1,000 characters. | |
| after | No | Next-page cursor: the previous page's last_id, only when has_more is true. | |
| limit | No | Page size, 1 to 500. Defaults to 100. | |
| order | No | Sort by creation time. Defaults to desc, newest first. | desc |
| before | No | Previous-page cursor: a first_id returned by a later page. | |
| include | No | Add serving_issues to receive native reasons why this entity cannot serve. A paused state is intentional, not an issue. | |
| campaignId | Yes | Native campaign ID (cmpn_) in the configured account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld and non-destructive, so safety is covered. The description adds behavior annotations don't: results are returned one page at a time, IDs carry the adgrp_ prefix, and cursors should only be followed when has_more is true. It stops short of noting default page size or rate limits, which the schema covers anyway.
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 short sentences, front-loaded with the action and scope, then the two facts an agent needs (ID format, cursor rule). No filler or repetition of schema content.
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 an output schema present and full annotation coverage, the description does not need to explain return values. It covers pagination behavior, which is the main complexity for an 8-parameter listing tool. Only the absence of any filtering or sorting hint keeps it from being fully 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 coverage is 100%, so every parameter including after, before, limit and order is already documented. The description's mention of last_id and has_more adds useful ties between response fields and the after cursor but nothing beyond that. Baseline 3 applies where 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?
Uses a specific verb and resource with scope: "List one page of ad groups in a campaign." That clearly separates it from the singular openai_ads_get_ad_group sibling, though it never names the sibling explicitly. Purpose is unambiguous but differentiation is left implicit.
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 sentence "Follow last_id only when has_more is true" gives real usage guidance for pagination, which is the main way this tool gets misused. However, it says nothing about when to choose this lister versus openai_ads_get_ad_group or how it relates to openai_ads_get_ads; tool-selection guidance is only implied by the plural/scoped naming.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_adsopenai ads get adsARead-onlyIdempotent
List one page of ads in an ad group with native creative metadata and review status. Follow last_id only when has_more is true.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Return only entities whose name matches this text, 3 to 1,000 characters. | |
| after | No | Next-page cursor: the previous page's last_id, only when has_more is true. | |
| limit | No | Page size, 1 to 500. Defaults to 100. | |
| order | No | Sort by creation time. Defaults to desc, newest first. | desc |
| before | No | Previous-page cursor: a first_id returned by a later page. | |
| include | No | Add serving_issues to receive native reasons why this entity cannot serve. A paused state is intentional, not an issue. | |
| adGroupId | Yes | Native ad group ID (adgrp_) in the configured account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world). The description adds real behavioral context: results arrive as a single page and cursors should only be followed when has_more is true. It stops short of stating anything about filtering behavior, the account-scoping constraint, or the effect of include=serving_issues, which the schema carries alone.
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 short sentences, zero waste, and the primary operation is stated before the pagination caveat. 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?
With an output schema present, the description needn't explain return fields, and the pagination contract is stated. What's missing is a note on the account scoping constraint or how the include parameter changes the response, but those are already covered in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every one of the eight parameters is already documented, and the baseline of 3 applies. The description mentions cursor semantics but refers to 'last_id' (a response field) rather than the 'after' parameter name, so it adds little usable meaning beyond the schema and risks a naming mismatch.
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 ('List one page of ads in an ad group') plus the content returned (native creative metadata and review status). This clearly separates it from openai_ads_get_ad, which fetches a single ad, but it doesn't name that sibling or contrast the two explicitly.
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 pagination rule ('Follow last_id only when has_more is true') gives clear guidance for paging, which is implied usage. But there is no statement of when to prefer this over openai_ads_get_ad or a creative-listing tool, and nothing about exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_audience_operationopenai ads get audience operationARead-onlyIdempotent
Read the lifecycle state of one custom audience operation. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. | |
| operation_id | Yes | Exact native operation_id. The entity must belong to the configured ad account. | |
| custom_audience_id | Yes | Exact native custom_audience_id. The entity must belong to the configured ad account. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so safety is fully covered. The description adds only 'Native fields and pagination are preserved', a partial note on output fidelity that is largely redundant with the existing output schema. It says nothing about rate limits, eventual consistency of operation state, or what a terminal vs in-progress state looks like.
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 short sentences with the purpose front-loaded; no filler. The final cross-reference sentence is slightly off-target for a read-only tool, but it is brief and does not obscure the main statement.
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 an output schema present the description need not explain return values, and rich annotations carry the safety profile, so the remaining job is purpose plus scoping and both are stated. What is missing is whether the returned lifecycle state can be polled to completion and how it relates to the list-level sibling, which would matter for an operations-status 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% and all three required parameters are documented in the schema, including the account-scoping constraint ('another ID is refused'). The description contributes nothing about operation_id or custom_audience_id, 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?
The description gives a specific verb and resource ('Read the lifecycle state of one custom audience operation'), and the word 'one' plus 'lifecycle state' distinguishes it from the plural sibling openai_ads_get_audience_operations. An agent can pick the right tool without opening either 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?
Usage is only implied by the singular scope; there is no explicit instruction on when to call this versus openai_ads_get_audience_operations (polling an in-flight op) or openai_ads_get_mutation. The one routing hint given ('see openai_ads_get_write_schema for nested request fields') points at write-side schema, which does not help an agent decide when to read an operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_audience_operationsopenai ads get audience operationsBRead-onlyIdempotent
List the accepted operations of a custom audience. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. | |
| custom_audience_id | Yes | Exact native custom_audience_id. The entity must belong to the configured ad account. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds that operation records are returned in native shape with native pagination preserved, which is genuinely useful since a custom-audience operations endpoint could otherwise be assumed to be normalized. It says nothing about volume, ordering, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and resource. Nothing is padded, though the write-schema pointer is only loosely connected to a read tool and could have been traded for sibling routing.
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?
Output schema is present so return values need not be described, and pagination plus native field preservation are disclosed. With 100% schema coverage and clear annotations, the remaining gap is only the missing contrast with the singular get_audience_operation sibling.
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 adAccountId scoping, the required custom_audience_id, and the limit/cursor query object are already fully documented. The description adds no parameter-level meaning beyond the schema, so the 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: list the accepted operations of a named custom audience. An agent can tell it is a per-audience read. It stops short of distinguishing itself from the singular sibling openai_ads_get_audience_operation, which is the main confusion risk.
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?
There is no guidance on when to use this versus openai_ads_get_audience_operation or openai_ads_get_custom_audience, and no prerequisites or exclusions. The only cross-reference points at openai_ads_get_write_schema for payload shapes, which is about content rather than when to call this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_audit_logsopenai ads get audit logsARead-onlyIdempotent
List recorded changes to the account's campaigns, ad groups and ads, optionally filtered by entity, actor or time. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld, so safety is covered. The description adds that native fields and pagination are preserved (one page per call), which is useful context, but says nothing about retention window or volume of results. The trailing reference to openai_ads_get_write_schema is confusing on a read-only log tool and adds no behavioral clarity.
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 short sentences, front-loaded with the resource and scope. The final sentence about write schema is the only weak link — it points at a mutation tool from a read tool and slightly dilutes focus.
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?
An output schema exists, annotations are rich, and the parameter schema is fully documented, so the description only needs to establish scope and pagination — which it does. The odd write-schema redirect is the sole incompleteness.
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 eleven query fields are already documented, including the nested roll-up semantics for campaign_id and ad_group_id and the actor_id caveat. The description only restates the filter axes at a higher level, so it sits at the 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 and resource — 'List recorded changes to the account's campaigns, ad groups and ads' — which is unmistakably distinct from the get_campaigns/get_ads retrieval siblings. An agent can tell this is the audit-history tool 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?
It names the filter dimensions (entity, actor, time) which implies when to reach for it, but gives no explicit when-not or alternative routing. The pointer to openai_ads_get_write_schema is a cross-reference for related fields rather than a usage rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_bulk_jobopenai ads get bulk jobARead-onlyIdempotent
Read one Bulk API job (limited preview, enabled per account). Only completed, partially_failed and failed are terminal. A completed job still requires reading every operation result and the native entities.
| Name | Required | Description | Default |
|---|---|---|---|
| jobId | Yes | Native bulk job ID, blkmtnjob_ followed by its identifier, returned when the job was submitted. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the safety annotations, the description explicitly details complex behavioral requirements, such as the job states that are terminal. It also enforces a critical next step: even for a completed job, the agent must read every operation result.
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 uses two highly dense, well-structured sentences. Both sentences carry maximum information with no wasted words, front-loading constraints and critical operational steps.
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 that handling bulk API jobs involves state management and subsequent action, the description is entirely complete. It informs the agent about the status lifecycle and the mandatory follow-up step of reading operation results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Since schema coverage is 100%, the description focuses on providing the operational context and lifecycle of the bulk job, rather than redundant parameter explanations. This semantic focus adds significant value beyond the structural 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 purpose is immediately clear: to 'Read one Bulk API job'. It is specifically scoped to a limited preview feature enabled per account, which differentiates it from generic job fetching tools.
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?
While it does not specify the exact workflow (when to call it), it provides essential usage context by defining the terminal states of a job (completed, partially_failed, failed). This tells the agent when the tool will be effective.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_bulk_job_operationsopenai ads get bulk job operationsARead-onlyIdempotent
Read one page of Bulk API operation outcomes: created, updated, validated, failed or skipped. Pass the last operation_id as after only when has_more is true. A partial failure never rolls back earlier operations; do not resubmit an uncertain job.
| Name | Required | Description | Default |
|---|---|---|---|
| jobId | Yes | Native bulk job ID, blkmtnjob_ followed by its identifier, returned when the job was submitted. | |
| query | No | Page size from 1 to 100 and, for later pages, the last operation_id of the previous page as after. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description instead adds semantics the annotations cannot: partial failures do not roll back earlier operations, paging is gated on has_more, and an uncertain job should not be resubmitted. That's substantive context beyond structured fields, though it doesn't address consistency/latency of the operation log.
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 tight sentences: what it returns, how to page, and how to interpret/handle failure. The paging contract is front-loaded right after the purpose, and no sentence is 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?
An output schema exists, so return-shape explanation is unnecessary, and the description covers the two things that matter for a paginated read of an async job: cursor gating and partial-failure semantics. It stops just short of stating where has_more lives or whether operations are available before the job finishes.
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 3 would be the floor, but the description adds real meaning the schema lacks: the cursor must be the last operation_id and is only valid when has_more is true. That conditional is not present in the 'after' property definition, so the prose genuinely compensates.
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 names a specific verb and resource ('Read one page of Bulk API operation outcomes') and even enumerates the outcome types (created, updated, validated, failed, skipped), which is far more than a restatement of the title. It doesn't explicitly contrast itself with the sibling openai_ads_get_bulk_job, so the boundary between 'job status' and 'job operation outcomes' must be inferred from naming.
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 one concrete operational rule — pass the last operation_id as after only when has_more is true — plus a caution not to resubmit an uncertain job. What's missing is when to reach for this tool versus openai_ads_get_bulk_job or openai_ads_get_mutation; usage is implied by the paging instruction rather than stated as a selection rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_campaignopenai ads get campaignBRead-onlyIdempotent
Read one campaign with its native status, budget, schedule and targeting.
| Name | Required | Description | Default |
|---|---|---|---|
| include | No | Add serving_issues to receive native reasons why this entity cannot serve. A paused state is intentional, not an issue. | |
| campaignId | Yes | Native campaign ID (cmpn_) in the configured account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds only that fields returned are the "native" ones, without disclosing anything beyond annotations such as the account-scoping refusal or serving-issues behavior (which live in the schema). Given rich annotations, this adds little.
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 front-loaded sentence with no filler; every clause contributes to the purpose. It is efficient, though somewhat terse given the available schema detail it could reference.
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 an output schema present, rich annotations, and full schema coverage, the description need not explain return values or parameter formats. It is adequate for a simple single-resource read, with only marginal room for added guidance about native-field nuances.
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 campaignId, adAccountId and the include flag are all fully documented in the schema, including the serving_issues semantics and the account-scoping restriction. The description adds no parameter detail beyond what the schema already states, meeting 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 ("Read one campaign") and enumerates the data returned (native status, budget, schedule, targeting), which implicitly separates it from the plural get_campaigns sibling. It stops short of naming the sibling explicitly, so it is clear but not maximally differentiating.
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 "one campaign" framing implies the single-object use case versus the list tool, but there is no explicit when-to-use, when-not, or prerequisite guidance. Usage is inferable from context rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_campaignsopenai ads get campaignsARead-onlyIdempotent
List one page of campaigns in the account. Follow last_id only when has_more is true. Budget amounts use integer account-currency micros.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Return only entities whose name matches this text, 3 to 1,000 characters. | |
| after | No | Next-page cursor: the previous page's last_id, only when has_more is true. | |
| limit | No | Page size, 1 to 500. Defaults to 100. | |
| order | No | Sort by creation time. Defaults to desc, newest first. | desc |
| before | No | Previous-page cursor: a first_id returned by a later page. | |
| include | No | Add serving_issues to receive native reasons why this entity cannot serve. A paused state is intentional, not an issue. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, open-world behavior, so the bar is lower. The description still adds real value by disclosing that results are paged one page at a time and that budget values are integer micros in account currency, which prevents a common misread of returned numbers.
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 short sentences, front-loaded with the verb and scope, then pagination rule, then unit convention. Nothing is padded or repeated from the schema.
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 an output schema present, return values need not be explained, and the description covers pagination and unit conventions. It leaves unmentioned the filtering and sorting capabilities the schema exposes, but nothing required for a correct call is missing.
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 every input including the 'after' cursor, limit, order and include. The description reinforces the cursor contract by referring to last_id/has_more, but adds no new meaning for name, limit, order, before or include, 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 and resource ('List one page of campaigns in the account'), and 'one page' implicitly contrasts with the singular openai_ads_get_campaign sibling. It stops short of naming the sibling or noting that this returns summary-level campaign objects.
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 pagination rule ('Follow last_id only when has_more is true') gives operative guidance for continuation, but there is no explicit statement of when to reach for this list tool versus openai_ads_get_campaign or openai_ads_get_insights.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_conversion_eventsopenai ads get conversion eventsARead-onlyIdempotent
List recent sampled conversion events, for checking that a pixel or server integration sends data. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, non-destructive, open-world call. The description adds useful behavior beyond that: results are 'recent' and 'sampled,' and native fields plus pagination are preserved, which matters for interpreting the response.
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 short sentences, front-loads the core action and purpose, and includes only relevant operational details. The cross-reference to openai_ads_get_write_schema is compact and does not bury the main point.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the input schema is fully described, the description covers the key remaining gaps: purpose, sampling behavior, and pagination. An agent has enough information to decide when and how to call this 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%, and the nested query object documents pid and limit thoroughly. The description adds little parameter-level meaning beyond pointing to openai_ads_get_write_schema for nested request fields, so the schema remains the primary source.
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: 'List recent sampled conversion events.' It also names the concrete diagnostic purpose, checking that a pixel or server integration sends data, which distinguishes it from siblings such as conversion insights, conversion settings, and conversion pixels.
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 a clear use case, checking pixel/server integration delivery, but does not explicitly say when to prefer conversion insights or conversion pixels instead. The context is strong enough for most selection decisions, though no exclusions or alternatives are spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_conversion_insightsopenai ads get conversion insightsARead-onlyIdempotent
Read attributed conversion totals or daily values, optionally by country or device and with event details. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Exact pinned native JSON request body. Nested configuration objects replace their previous contents, so send the complete intended configuration. Money uses integer account-currency micros. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description contributes 'Native fields and pagination are preserved', which usefully signals no result reshaping and paged output, but says nothing about rate limits, result size, or how the pinned native body interacts with reconciliation beyond what the schema states.
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 short sentences, front-loaded with the core read capability, with no filler. The closing pointer to the write schema is slightly tangential for a read tool but is compact and does not bury the main content.
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?
An output schema exists, so return-shape explanation is unnecessary, and the nested body semantics are documented in-schema. Given a nested-object read tool with annotations, the description covers scope, optional dimensions, and pagination adequately; only the sibling differentiation is thin.
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 adAccountId scoping, include/event_names dependency, breakdown, and granularity. The description restates the breakdown and event-detail options without adding syntax, defaults, or constraints beyond the schema, 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 and resource ('Read attributed conversion totals or daily values') plus the supported breakdowns (country/device) and the optional event-detail expansion. It doesn't explicitly contrast itself with the sibling openai_ads_get_insights or openai_ads_get_conversion_events, so the boundary with those tools is left to inference.
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 breakdown and include options imply when this tool is appropriate, but there is no explicit 'use this instead of X when Y' guidance against the many sibling read tools. The only routing pointer is to openai_ads_get_write_schema for nested request fields, which addresses schema discovery rather than tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_conversion_pixelsopenai ads get conversion pixelsBRead-onlyIdempotent
List the account's conversion pixels and connected pixel IDs. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds that native fields and pagination are preserved, a useful note about response shape, but says nothing further about page size, ordering, or how many pixels a typical account returns. With annotations carrying the safety burden, a 3 is appropriate.
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 short sentences with the purpose front-loaded. The trailing write-schema pointer is the one sentence that does not clearly earn its place for a read tool, though it is brief.
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?
An output schema exists and annotations cover safety, so the core is complete enough to call. However, the description never explains how the returned pixel IDs relate to conversion_events or conversion_settings, and its only external pointer targets the mutation schema, leaving the agent without relational context for a tool that sits in a crowded conversion-related namespace.
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% — adAccountId's pattern and account-scoping constraint are fully documented in the schema, as are the query paging parameters. The description adds no parameter-level meaning, so the baseline 3 applies; the cross-reference to openai_ads_get_write_schema does not clarify the read parameters.
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 — list the account's conversion pixels plus connected pixel IDs — which an agent can distinguish from conversion_events or conversion_settings siblings by name. It stops short of explicitly contrasting with those siblings, but the resource 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?
There is no guidance on when to choose this over openai_ads_get_conversion_events or openai_ads_get_conversion_settings, which cover adjacent concepts. The only routing hint points to openai_ads_get_write_schema, a write-oriented sibling, for nested request fields — a confusing pointer for a read-only listing tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_conversion_settingsopenai ads get conversion settingsARead-onlyIdempotent
List the account's conversion event settings, the goals a campaign can use. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, and openWorld, so the safety profile is covered. The description adds that native fields and pagination are preserved, which is mild context, but the closing pointer to openai_ads_get_write_schema is confusing for a read-only tool and adds no behavioral clarity.
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 compact sentences with the purpose front-loaded and no filler. The trailing write-schema reference is arguably noise for a listing tool, which keeps it just short of a 5.
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?
An output schema exists and annotations fully describe the safety profile, and the schema documents both parameters. Given that richness, the description supplies exactly the remaining piece — what the resource is and that pagination/native fields are retained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters (adAccountId, query) are fully documented in the schema, so the description carries little burden. It adds no syntax or scoping detail beyond the schema, and the mention of 'nested request fields' is misleading for a GET tool whose nested object is just a query block.
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: 'List the account's conversion event settings', and adds the purpose ('the goals a campaign can use'). It is reasonably distinguishable from get_conversion_events, though the description never explicitly contrasts the two 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?
The 'goals a campaign can use' phrasing implies the use case, but there is no explicit when-to-use guidance, no prerequisites, and no stated alternative for retrieving actual conversion event data versus settings. Usage is only inferable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_custom_audienceopenai ads get custom audienceARead-onlyIdempotent
Read one custom audience and its matched count. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. | |
| custom_audience_id | Yes | Exact native custom_audience_id. The entity must belong to the configured ad account. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds beyond that: it discloses that native fields and pagination are preserved, and that a matched count is returned — useful behavioral context the annotations don't carry.
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 short sentences with the resource and its payload front-loaded; no wasted clauses. The trailing write-schema pointer is arguably dispensable for a read tool but is brief and does not bloat the definition.
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?
Output schema exists and schema coverage is 100%, so return shape needn't be explained; the description still covers pagination and matched-count return. The only weakness is the misdirected reference to a write schema, which is not needed to call this read tool 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 description coverage is 100% and all three parameters (including the nested query.matched_count_granularity) are documented in the schema itself. The description's mention of 'matched count' loosely maps to the granularity param but adds no syntax or format detail 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+resource: 'Read one custom audience and its matched count.' The word 'one' implicitly separates it from the sibling openai_ads_get_custom_audiences (list), though the sibling is never named explicitly. An agent can tell what it fetches, but the singular/plural distinction must be inferred from a single word.
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 only implied by 'Read one' — no explicit when-to-use, when-not, or alternative named. The one cross-reference ('See openai_ads_get_write_schema for nested request fields') points at a write-schema tool, which is not an obvious alternative for a read operation and adds little routing value.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_custom_audiencesopenai ads get custom audiencesBRead-onlyIdempotent
List the account's custom audiences. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. "Native fields and pagination are preserved" adds some behavioral context about pass-through results and paging, but it is vague about page size, cursor semantics, and the fact that each call returns only one page (that detail appears only in the schema).
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 first two sentences are tight and front-loaded. The third sentence, "See openai_ads_get_write_schema for nested request fields," is a stock cross-reference that is poorly targeted for a read/list operation and spends a full sentence on tangential 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?
An output schema exists, so return values need not be described, and the adAccountId scoping is handled in the schema. However, for a paginated tool exposing eight query filters (intended_use, custom_audience_ids, policy_revision, etc.), the description says nothing about filtering capability, leaving the agent to discover it from the schema alone.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the nested query object is fully documented in the schema, so the baseline is 3. The description only gestures at pagination and defers filter semantics to another tool, adding little beyond what the schema already states.
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?
"List the account's custom audiences" gives a specific verb (list) and resource, which clearly separates it from the singular openai_ads_get_custom_audience in the sibling set. It stops short of naming that sibling explicitly, so the plural-vs-singular distinction is left for the agent to infer from the names.
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 only implied: the word "List" suggests enumeration versus the single-record getter, and the closing pointer redirects to openai_ads_get_write_schema rather than to a competing read tool. There is no explicit statement of when to prefer this over openai_ads_get_custom_audience or when to page instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_feed_productsopenai ads get feed productsBRead-onlyIdempotent
List products in a feed that match ad group product filters. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | Exact pinned native JSON request body. Nested configuration objects replace their previous contents, so send the complete intended configuration. Money uses integer account-currency micros. | |
| feed_id | Yes | Exact native feed_id. The entity must belong to the configured ad account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is fully covered elsewhere. The description adds only that 'native fields and pagination are preserved' — a useful but thin note on response shaping, with no mention of the filter semantics (e.g., that product filters come from the ad group) or 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 short sentences, front-loaded with the verb and resource, with no filler. The final cross-reference sentence is terse but arguably misdirects toward a write-schema tool, which slightly weakens an otherwise clean structure.
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?
An output schema exists, so return values need not be explained, and the fully-described schema covers all three parameters including the nested body. What remains missing — guidance on choosing this tool over the other feed-related siblings — is a usage gap rather than a completeness gap at the schema level.
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 explains adAccountId scoping, feed_id ownership, and the body's complete-configuration semantics including micros currency. The description adds nothing beyond pointing at another tool for 'nested request fields', so the 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 ('List products in a feed') plus the scoping condition ('that match ad group product filters'), which distinguishes it from sibling listing tools like openai_ads_get_feeds or openai_ads_get_feed_settings. It does not explicitly name those siblings as alternatives, keeping it 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?
There is no statement of when to use this tool versus openai_ads_get_feeds, openai_ads_get_feed_uploads, or openai_ads_get_feed_settings, and no prerequisites or exclusions. The only routing hint ('See openai_ads_get_write_schema for nested request fields') points at a write-schema tool for what is described as a read/list operation, which is confusing rather than directive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_feedsopenai ads get feedsBRead-onlyIdempotent
List the account's product feeds, optionally with product counts. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, so safety behavior is covered. The description adds that native fields and pagination are preserved, which tells the agent to expect pass-through upstream shapes rather than normalized ones. It says nothing about rate limits, page sizes, or whether counts are expensive to compute.
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 short sentences, front-loaded with the core action, no filler. The final sentence is the weakest link and could be dropped or corrected without loss.
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?
An output schema exists, so return values need not be explained, and parameter coverage is complete in the schema. What is missing is the piece an agent actually needs for selection: how this differs from get_feed_products/get_feed_uploads, and why a read tool would defer nested request detail to a write-schema 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%, so the baseline is 3. The description does hint at the 'include: product_count' option and the pagination parameters, but adds no syntax or constraints beyond what the schema already documents (limit 1-500, after/before cursors, adacct_ ID scoping).
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: 'List the account's product feeds', with an optional enrichment (product counts). It is clearly a feeds listing, not uploads or settings, though it does not explicitly name the neighboring feed tools (get_feed_uploads, get_feed_settings, get_feed_products) to sharpen the boundary.
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?
No guidance on when to use this vs get_feed_products or get_feed_uploads, both of which overlap semantically with 'feeds'. The only routing hint, 'See openai_ads_get_write_schema for nested request fields', points at a write-schema tool for what is a read-only list operation, which is more likely to confuse than help.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_feed_settingsopenai ads get feed settingsARead-onlyIdempotent
Read a feed's display and organic-listing settings. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| feed_id | Yes | Exact native feed_id. The entity must belong to the configured ad account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the safety profile is covered. The description adds useful context beyond the annotations: raw native fields are preserved and pagination is maintained, which tells the agent what shape the response will take.
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 short sentences, no filler, and the core read action is front-loaded. The trailing pointer to the write schema is a little questionable in a read context, but the description is tight 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?
An output schema exists, so return values needn't be described, and both required parameters are covered by rich schema descriptions. The description supplies the essential behavior (raw native fields and pagination preserved) and a cross-reference, leaving only minor gaps around when to prefer this over sibling read tools.
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 both required parameters (feed_id and adAccountId) are fully documented in the schema, including the adacct_ pattern and account scoping. The description adds no parameter-level detail, which is acceptable given the schema does the work, 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 ('Read') and resource ('a feed's display and organic-listing settings'), which is distinguishable from list tools like openai_ads_get_feeds and related item tools like openai_ads_get_feed_products. The exact nature of 'display and organic-listing settings' remains slightly abstract, but the scope is clear enough to choose the tool.
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 only implied: the verb 'Read' plus the resource suggests fetching settings for a known feed, and the pointer to openai_ads_get_write_schema hints at related workflows. There is no explicit 'use this when…' or exclusion against siblings such as openai_ads_get_feeds or openai_ads_get_feed_products, and referring to a write schema in a read tool is confusing rather than helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_feed_uploadsopenai ads get feed uploadsARead-onlyIdempotent
List recent product feed uploads and their processing results. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare this is a safe, read-only, idempotent operation. The description complements this by adding functional context that the results include processing status, which is critical for the user's understanding of the return value.
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 brief, uses active language, and organizes the information logically: what it does, how it paginates, and where to find advanced request details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the excellent structured data (annotations and 100% schema coverage), the description successfully fills the gaps by addressing specific operational behaviors like pagination preservation and the scope of the results.
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%, satisfying the minimum requirement (score 3). The description adds semantic value by detailing the scope of the data returned—'processing results'—which gives the parameters a higher operational meaning.
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 resource being acted upon ('product feed uploads') and the action ('List') while specifying the inclusion of 'processing results.' This precisely distinguishes it from sibling tools like openai_ads_get_feeds or openai_ads_get_ad_creatives.
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 provides practical usage context by stating that 'native fields and pagination are preserved.' It also guides the user to a specific sibling tool (openai_ads_get_write_schema) for complex nested request definitions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_insightsopenai ads get insightsARead-onlyIdempotent
Read performance by account, campaign, ad group or ad over inclusive account-local dates. One optional country, device or platform breakdown supports delivery metrics only; use openai_ads_get_conversion_insights for conversions by country or device. Attribution defaults to 30-day click, 1-day view and ad_event_time. CTR and CVR are fractions; money uses major units of the account currency. Pages are followed up to maxRows and truncation is explicit.
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | Aggregation level: ad_account, campaign, ad_group or ad. Defaults to campaign. | campaign |
| since | Yes | First day of the report, YYYY-MM-DD, in the account's time zone. Inclusive. | |
| until | Yes | Last day of the report, YYYY-MM-DD, in the account's time zone. Inclusive. At most 365 days after since. | |
| maxRows | No | Maximum rows to collect across pages, 1 to 10,000. truncated is true when more rows exist. | |
| metrics | No | Native metrics to return. Defaults to spend, impressions and clicks. | |
| breakdown | No | One delivery breakdown per request: country, device or platform. Supports impressions, clicks, spend, ctr, cpc and cpm. Omit for entity totals. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. | |
| attribution | No | Report attribution only: attribution_window_days 7, 14 or 30, view_through_attribution_window_days 0 or 1, attribution_time_basis ad_event_time or conversion_time. Campaign goals are unchanged. | |
| timeGranularity | No | daily returns one row per day; none returns period totals. | daily |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/non-destructive/idempotent, but the description adds genuinely new behavior: pagination is followed up to maxRows with explicit truncation, attribution defaults to 30-day click and 1-day view on ad_event_time, CTR/CVR are fractions, and money is in major units of account currency. These conventions prevent real misinterpretation of results.
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, front-loaded with the read scope and followed by exclusions, semantics, and pagination. No filler, though some clauses (attribution defaults, unit conventions) are compressed into a very jargon-heavy run-on that takes a careful read.
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 9 parameters, nested attribution, and an output schema present, the description covers everything the schema does not carry: cross-metric/breakdown compatibility, unit conventions, attribution default semantics, and pagination/truncation behavior. Nothing needed for a correct call is missing.
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 baseline is 3. The description does add some meaning beyond the schema (breakdown restricted to delivery metrics, attribution defaults, inclusive date range), but it mostly summarizes defaults already documented per-parameter rather than deepening them.
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: 'Read performance' at four named aggregation levels over inclusive account-local dates. It immediately distinguishes itself from openai_ads_get_conversion_insights by naming that sibling and its domain, so an agent can route correctly without opening either 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 rule: use openai_ads_get_conversion_insights for conversions by country or device. It also states the in-tool constraint that a single breakdown supports delivery metrics only, which tells the agent when not to combine breakdown with conversion metrics.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_landing_page_crawlopenai ads get landing page crawlARead-onlyIdempotent
Read the saved landing page crawl evidence for an ad's submitted version. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| ad_id | Yes | Exact native ad_id. The entity must belong to the configured ad account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds that native fields and pagination are preserved, which is useful behavioral context, but says nothing about rate limits or response shape beyond that.
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 short sentences, front-loaded with the core action. The final reference to openai_ads_get_write_schema for 'nested request fields' is slightly odd for a read-only tool and may not earn its place, but overall the text is tight.
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?
An output schema exists, so return values need not be described, and annotations cover safety. The description supplies the essential scope ('saved crawl evidence for an ad's submitted version') and pagination note; only the write_schema pointer is confusing, but nothing critical is missing.
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 both parameters (ad_id, adAccountId) are fully documented in the schema, including the account-scoping constraint. The description adds no parameter-level meaning beyond what the schema already provides, 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 and resource: reading saved landing page crawl evidence for an ad's submitted version. This is clearly distinguishable from the many get_* siblings which fetch ads, campaigns, insights, etc. It stops short of explaining what 'submitted version' means, which leaves some ambiguity.
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 context (retrieving crawl evidence for a specific ad) but gives no explicit when-to-use/when-not guidance or alternatives among siblings. The cross-reference to openai_ads_get_write_schema is presented without a condition that selects it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_mutationopenai ads get mutationARead-onlyIdempotent
Read a write preview or receipt held by this server process: its state, the native state it was approved against and the result. Receipts live in memory and a restart forgets them. Never resubmit a write whose state is UNKNOWN or APPLYING.
| Name | Required | Description | Default |
|---|---|---|---|
| mutationId | Yes | The confirmationToken or mutationId returned by a write preview or receipt. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing durability ('Receipts live in memory and a restart forgets them') and the specific state semantics that matter operationally (UNKNOWN/APPLYING must not be resubmitted). The readOnly/idempotent hints are already in the annotations, so this added context is exactly the kind that earns credit.
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 what the tool reads, then the durability caveat, then the operational warning. Every sentence carries information an agent would otherwise have to discover by failure.
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 an output schema present it is fair not to enumerate the returned structure, and the description still summarizes it plus the memory volatility caveat. What it omits is how the enumerated states relate to each other (what to do after APPLYING resolves), leaving a small but real gap for a status-polling tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters carry their own descriptions, so the baseline is 3. The description adds a little meaning by tying 'preview' and 'receipt' to the two possible identifiers, but it gives no format or lookup details beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Read a write preview or receipt held by this server process,' and enumerates the payload (state, approved-against native state, result). Among the many get_* siblings it is unmistakably the only mutation/receipt reader, though it never names a sibling explicitly.
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?
Context for use is clear: this is how you check on a preview or receipt you already hold, and 'Never resubmit a write whose state is UNKNOWN or APPLYING' gives a concrete decision rule for the polling loop. It stops short of naming alternatives such as openai_ads_get_bulk_job or openai_ads_get_write_context, so the routing is not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_spend_limitsopenai ads get spend limitsARead-onlyIdempotent
Read the account's spend limit windows and daily recurrence rules. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds that native fields and pagination are preserved, a modest note on return shape, but says nothing about account-scoping refusals or rate limits beyond what the schema already states.
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 short sentences with the purpose front-loaded and no redundancy. The trailing pointer to openai_ads_get_write_schema ('nested request fields') is boilerplate that doesn't apply to a read tool with a flat one-field schema, costing a little precision.
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?
An output schema exists, so return values need not be explained, and annotations cover safety. However, the 'pagination is preserved' claim is unverifiable in a schema with no pagination parameters, and the write-schema reference is a misdirection — enough gaps to keep this at minimum-viable.
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?
Only one parameter and schema coverage is 100% — the adAccountId pattern and the API-key scoping/refusal behavior are fully documented in the schema itself. The description adds no parameter-level meaning beyond that, which matches the baseline-3 expectation.
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 ('Read') and a specific resource ('the account's spend limit windows and daily recurrence rules'), which no sibling tool covers. An agent can distinguish it from openai_ads_get_account or openai_ads_get_insights 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?
The purpose implies when it applies (fetching spend limits), but there is no explicit when/when-not guidance and no alternative named. The only cross-reference points at openai_ads_get_write_schema, which is a write-path helper unrelated to this read-only tool, so it doesn't route the agent usefully.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_write_contextopenai ads get write contextARead-onlyIdempotent
Read the account, its conversion settings and its product feeds before proposing a campaign. Lists the native objective, billing and bid strategy combinations and the missing prerequisites. It grants no eligibility and creates nothing.
| Name | Required | Description | Default |
|---|---|---|---|
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the description is not carrying the safety burden alone — yet it still adds real behavioral context: the tool aggregates several resources and surfaces 'missing prerequisites'. The explicit disclaimer "grants no eligibility and creates nothing" usefully preempts an agent misreading the composite read as an entitlement check.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences: the trigger and scope come first, then what is returned, then the negative capability disclaimer. No filler and nothing that could be cut without losing meaning.
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 an output schema present, return values need not be spelled out, and annotations cover the safety profile; the description supplies the one thing they cannot — when in the workflow to call it. The only gap is that it does not relate itself to the adjacent write-schema/pre-write sibling, leaving the agent to infer that pairing.
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?
Single parameter with 100% schema description coverage, including the adacct_ pattern and the API-key scoping rule. The description adds nothing about adAccountId, so the baseline of 3 for fully-documented schemas 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 (read) and a specific composite resource (account, conversion settings, product feeds) plus the two things it returns: valid objective/billing/bid-strategy combinations and missing prerequisites. It is distinguishable from single-resource siblings like get_account or get_feeds by being an aggregating pre-flight read, although it never names those siblings explicitly.
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?
"before proposing a campaign" gives a clear trigger condition, and "creates nothing" sets the boundary against write tools. No alternatives or exclusions are named (e.g. when to call get_conversion_settings alone instead), so it stops just short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_get_write_schemaopenai ads get write schemaARead-onlyIdempotent
Read the pinned native request definitions, paths and parameters of every operation, the upload and bulk limits, and what this server leaves out. Schema support does not imply that the account is eligible for a feature.
| Name | Required | Description | Default |
|---|---|---|---|
| toolName | No | Optional tool name, such as openai_ads_create_campaign, to return only that operation. Omit for all. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, non-destructive operation. The description adds meaningful scope details: it returns paths, parameters, limits, and explicitly documents what the server leaves out, plus a caveat about feature eligibility. It stops short of describing return structure, but an output schema exists.
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 and front-loads the core action and returned content. The eligibility caveat is worth including, though the sentence is somewhat dense and could be split for faster scanning.
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 a fully described input schema, an output schema, and rich annotations, the description supplies the remaining necessary context: returned content categories, limits, omissions, and an eligibility caveat. An agent has enough information to decide whether to call it and what to expect.
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 both parameters are already fully documented in the input schema. The description adds no additional meaning about adAccountId or the optional toolName filter, which is acceptable given the high schema coverage 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?
The description uses a specific verb ('Read') and clearly identifies the resource: pinned native request definitions, paths, parameters, upload/bulk limits, and omissions. It is more specific than the title and differentiates at a high level from typical data-fetching siblings, though it does not explicitly contrast with close metadata siblings like openai_ads_get_write_context.
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 this is for looking up write-operation schemas and limits, but it gives no explicit when-to-use guidance, prerequisites, or comparison to alternatives such as openai_ads_get_write_context. The caveat that schema support does not imply account eligibility is useful context but not usage routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_list_ad_creativesopenai ads list ad creativesARead-onlyIdempotent
List chat card creatives of the account or of one ad group, 20 ads per page, or read up to 60 exact adIds. Each item has the native file_id, signed image_url, title, body, destination and review status. An expired image link is refreshed with one ad read. Follow nextCursor when hasMore.
| Name | Required | Description | Default |
|---|---|---|---|
| adIds | No | Up to 60 exact ad IDs to read. Cannot be combined with adGroupId or after. | |
| after | No | The nextCursor of the previous page, only when hasMore is true. | |
| limit | No | Ads per page, 1 to 20. Defaults to 20. | |
| adGroupId | No | Optional ad group (adgrp_) to list. Omit to list ads across the account. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld, so the safety profile is covered and the description spends its budget on real behavior: 20 items per page, a 60-id batch ceiling, sequential paging via nextCursor/hasMore, and the fact that an expired signed image_url is refreshed by a single ad read. That last detail is non-obvious side-effect disclosure an agent would otherwise not know.
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 densely packed sentences, front-loaded with the core listing scope, and each one carries actionable information about paging, return fields, or link refresh. The enumeration of return fields is marginally redundant given an output schema exists, but it is compact enough not to waste space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present the description needn't document return shape, and it still adds pagination termination rules and the batch-read mode that the schema alone would not make obvious. Account scoping is left to the schema's adAccountId text, so the description is complete but not exhaustive for a 5-parameter listing tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3; the description goes further by tying pagination to concrete values ("20 ads per page") and by explaining that after should be followed from nextCursor when hasMore is true, plus the 60-id cap on adIds. It adds page-size and paging-loop semantics beyond the field-level schema text.
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 plus resource ("List chat card creatives") and enumerates the three access modes: account-wide, one ad group, or up to 60 exact adIds. An agent immediately knows the scope and shape of the call. It does not explicitly distinguish itself from the sibling openai_ads_get_ads / openai_ads_get_ad, which is the only thing keeping it from 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?
"List ... of the account or of one ad group, ... or read up to 60 exact adIds" clearly frames the mutually exclusive invocation modes, and the schema reinforces that adIds cannot combine with adGroupId or after. There is no explicit when-not guidance or named alternative among the large set of sibling listing tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openai_ads_search_locationsopenai ads search locationsARead-onlyIdempotent
Search country, region and market location IDs for campaign geographic targeting. Native fields and pagination are preserved. See openai_ads_get_write_schema for nested request fields.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Documented native query parameters. Each call reads one page unless the tool says otherwise. | |
| adAccountId | Yes | The adacct_ ID configured in OPENAI_ADS_ACCOUNT_ID. The API key is scoped to this one account; another ID is refused. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes | Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructive:false, so the safety profile is covered. 'Native fields and pagination are preserved' is the only added behavioral claim and is too vague to act on – it hints at raw-API passthrough and paging without saying what paging looks like or how large result sets are handled.
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 short sentences with the search action front-loaded and no padding. The write-schema cross-reference is the one sentence that does not clearly earn its place on a read-only location search.
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 an output schema and full annotation coverage, little else is required; the description names the resource and the filtering domain. The odd reference to get_write_schema slightly muddies rather than completes the picture, and query-matching semantics remain unstated.
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%, and the adAccountId entry already explains the adacct_ scoping and refusal behavior. The description adds nothing about the nested query object — how `q` matches (prefix vs substring, case sensitivity) or what `limit` defaults to — so it sits at the 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 (search) plus a precise resource (country, region and market location IDs) and the reason for it (campaign geographic targeting). That is enough to separate it from every get_*-style sibling, though it never explicitly says 'use this instead of X'.
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 'for campaign geographic targeting' clause implies when the tool applies, but there is no explicit when-not, no prerequisites, and no named alternative. The closing pointer to openai_ads_get_write_schema is a cross-reference, not usage routing, and is puzzling on a read-only lookup 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.
30 tool updates
- Changed
openai_ads_get_account1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_ad1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_ad_group1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_ad_groups1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_ads1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_audience_operation1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_audience_operations1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_audit_logs4 fields changed- added
Input schema / properties / query / properties / order / anyOfAdded value: +[ + { + "const": "asc", + "type": "string" + }, + { + "const": "desc", + "type": "string" + } +] - removed
Input schema / properties / query / properties / order / enumRemoved value: -[ - "asc", - "desc" -] - removed
Input schema / properties / query / properties / order / typeRemoved value: -"string" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_bulk_job1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_bulk_job_operations1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_campaign1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_campaigns1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_conversion_events2 fields changed- changed
Input schema / requiredPrevious value: -[ - "adAccountId", - "query" -]New value: +[ + "adAccountId" +] - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_conversion_insights12 fields changed- added
Input schema / properties / body / properties / attribution_time_basis / anyOfAdded value: +[ + { + "const": "conversion_time", + "type": "string" + }, + { + "const": "ad_event_time", + "type": "string" + } +] - removed
Input schema / properties / body / properties / attribution_time_basis / enumRemoved value: -[ - "conversion_time", - "ad_event_time" -] - removed
Input schema / properties / body / properties / attribution_time_basis / typeRemoved value: -"string" - changed
Input schema / properties / body / properties / attribution_window_days / anyOfPrevious value: -[ - { - "enum": [ - 7, - 14, - 30 - ], - "type": "number" - }, - { - "type": "null" - } -]New value: +[ + { + "anyOf": [ + { + "const": 7, + "type": "number" + }, + { + "const": 14, + "type": "number" + }, + { + "const": 30, + "type": "number" + } + ] + }, + { + "type": "null" + } +] - added
Input schema / properties / body / properties / breakdown / anyOfAdded value: +[ + { + "const": "device", + "type": "string" + }, + { + "const": "country", + "type": "string" + } +] - removed
Input schema / properties / body / properties / breakdown / enumRemoved value: -[ - "device", - "country" -] - removed
Input schema / properties / body / properties / breakdown / typeRemoved value: -"string" - added
Input schema / properties / body / properties / time_granularity / anyOfAdded value: +[ + { + "const": "none", + "type": "string" + }, + { + "const": "daily", + "type": "string" + } +] - removed
Input schema / properties / body / properties / time_granularity / enumRemoved value: -[ - "none", - "daily" -] - removed
Input schema / properties / body / properties / time_granularity / typeRemoved value: -"string" - changed
Input schema / properties / body / properties / view_through_attribution_window_days / anyOfPrevious value: -[ - { - "enum": [ - 0, - 1 - ], - "type": "number" - }, - { - "type": "null" - } -]New value: +[ + { + "anyOf": [ + { + "const": 0, + "type": "number" + }, + { + "const": 1, + "type": "number" + } + ] + }, + { + "type": "null" + } +] - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_conversion_pixels4 fields changed- added
Input schema / properties / query / properties / order / anyOfAdded value: +[ + { + "const": "asc", + "type": "string" + }, + { + "const": "desc", + "type": "string" + } +] - removed
Input schema / properties / query / properties / order / enumRemoved value: -[ - "asc", - "desc" -] - removed
Input schema / properties / query / properties / order / typeRemoved value: -"string" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_conversion_settings4 fields changed- added
Input schema / properties / query / properties / order / anyOfAdded value: +[ + { + "const": "asc", + "type": "string" + }, + { + "const": "desc", + "type": "string" + } +] - removed
Input schema / properties / query / properties / order / enumRemoved value: -[ - "asc", - "desc" -] - removed
Input schema / properties / query / properties / order / typeRemoved value: -"string" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_custom_audience1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_custom_audiences7 fields changed- added
Input schema / properties / query / properties / intended_use / anyOfAdded value: +[ + { + "const": "inclusion", + "type": "string" + }, + { + "const": "exclusion", + "type": "string" + }, + { + "const": "bid_multiplier", + "type": "string" + } +] - removed
Input schema / properties / query / properties / intended_use / enumRemoved value: -[ - "inclusion", - "exclusion", - "bid_multiplier" -] - removed
Input schema / properties / query / properties / intended_use / typeRemoved value: -"string" - added
Input schema / properties / query / properties / order / anyOfAdded value: +[ + { + "const": "asc", + "type": "string" + }, + { + "const": "desc", + "type": "string" + } +] - removed
Input schema / properties / query / properties / order / enumRemoved value: -[ - "asc", - "desc" -] - removed
Input schema / properties / query / properties / order / typeRemoved value: -"string" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_feed_products4 fields changed- added
Input schema / properties / body / properties / filters / items / properties / operator / anyOfAdded value: +[ + { + "const": "in", + "type": "string" + }, + { + "const": "not_in", + "type": "string" + }, + { + "const": "gt", + "type": "string" + }, + { + "const": "gte", + "type": "string" + }, + { + "const": "lt", + "type": "string" + }, + { + "const": "lte", + "type": "string" + }, + { + "const": "contains", + "type": "string" + }, + { + "const": "not_contains", + "type": "string" + }, + { + "const": "starts_with", + "type": "string" + } +] - removed
Input schema / properties / body / properties / filters / items / properties / operator / enumRemoved value: -[ - "in", - "not_in", - "gt", - "gte", - "lt", - "lte", - "contains", - "not_contains", - "starts_with" -] - removed
Input schema / properties / body / properties / filters / items / properties / operator / typeRemoved value: -"string" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_feed_settings1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_feed_uploads1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_feeds1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_insights10 fields changed- added
Input schema / properties / attribution / properties / attribution_window_days / anyOfAdded value: +[ + { + "const": 7, + "type": "number" + }, + { + "const": 14, + "type": "number" + }, + { + "const": 30, + "type": "number" + } +] - removed
Input schema / properties / attribution / properties / attribution_window_days / enumRemoved value: -[ - 7, - 14, - 30 -] - removed
Input schema / properties / attribution / properties / attribution_window_days / typeRemoved value: -"number" - added
Input schema / properties / attribution / properties / view_through_attribution_window_days / anyOfAdded value: +[ + { + "const": 0, + "type": "number" + }, + { + "const": 1, + "type": "number" + } +] - removed
Input schema / properties / attribution / properties / view_through_attribution_window_days / enumRemoved value: -[ - 0, - 1 -] - removed
Input schema / properties / attribution / properties / view_through_attribution_window_days / typeRemoved value: -"number" - removed
Input schema / properties / until / $refRemoved value: -"#/properties/since" - added
Input schema / properties / until / patternAdded value: +"^\\d{4}-\\d{2}-\\d{2}$" - added
Input schema / properties / until / typeAdded value: +"string" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_landing_page_crawl1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_mutation2 fields changed- added
Input schema / properties / mutationId / patternAdded value: +"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_spend_limits1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_write_context1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_get_write_schema3 fields changed- added
Input schema / properties / toolName / formatAdded value: +"starts_with" - changed
Input schema / properties / toolName / patternPrevious value: -"^openai\\_ads\\_"New value: +"^openai_ads_.*" - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_list_ad_creatives1 field changed- changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
- Changed
openai_ads_search_locations2 fields changed- changed
Input schema / requiredPrevious value: -[ - "adAccountId", - "query" -]New value: +[ + "adAccountId" +] - changed
Output schema / properties / result / anyOfPrevious value: -[ - { - "additionalProperties": true, - "properties": {}, - "type": "object" - }, - { - "items": {}, - "type": "array" - }, - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } +]
30 tool updates
v1.0.0- First observed
openai_ads_get_account - First observed
openai_ads_get_ad - First observed
openai_ads_get_ad_group - First observed
openai_ads_get_ad_groups - First observed
openai_ads_get_ads - First observed
openai_ads_get_audience_operation - First observed
openai_ads_get_audience_operations - First observed
openai_ads_get_audit_logs - First observed
openai_ads_get_bulk_job - First observed
openai_ads_get_bulk_job_operations - First observed
openai_ads_get_campaign - First observed
openai_ads_get_campaigns - First observed
openai_ads_get_conversion_events - First observed
openai_ads_get_conversion_insights - First observed
openai_ads_get_conversion_pixels - First observed
openai_ads_get_conversion_settings - First observed
openai_ads_get_custom_audience - First observed
openai_ads_get_custom_audiences - First observed
openai_ads_get_feed_products - First observed
openai_ads_get_feed_settings - First observed
openai_ads_get_feed_uploads - First observed
openai_ads_get_feeds - First observed
openai_ads_get_insights - First observed
openai_ads_get_landing_page_crawl - First observed
openai_ads_get_mutation - First observed
openai_ads_get_spend_limits - First observed
openai_ads_get_write_context - First observed
openai_ads_get_write_schema - First observed
openai_ads_list_ad_creatives - First observed
openai_ads_search_locations
TDQS
Scored across 30 tools
Each tool targets a distinct resource or report (campaigns vs ad groups vs ads vs feeds vs audiences vs bulk jobs), and the insights vs conversion_insights split is explicitly documented. The main friction is the large set of near-neighbor tools (get_custom_audiences / get_custom_audience / get_audience_operations / get_audience_operation, and get_write_schema / get_write_context / get_mutation) where an agent must read carefully, plus get_* names that sometimes list and sometimes read one entity.
All names share the openai_ads_ prefix and a verb_noun shape, so the set is predictable. However the verb usage is loose: get_ is used for both list operations (get_campaigns, get_ads, get_feeds) and single-entity reads, while list_ and search_ appear only once each, which weakens the pattern's signal.
30 tools is heavy for a single MCP server and sits above the comfortable 15-tool band, even though the domain (campaigns, creatives, conversions, feeds, audiences, audit, bulk) is genuinely broad. Several read-only sub-resources (audience operations, feed uploads, feed settings, landing page crawl) could reasonably be folded into parent tools to slim the surface.
Read coverage is deep and coherent across the ad lifecycle, including diagnostics and bulk job result inspection. But the surface is read-heavy: get_write_schema, get_write_context and get_mutation reference write previews and receipts while no tool actually submits a mutation, leaving a dangling step in the advertised lifecycle and no create/update/delete operations.
Maintenance
Related MCP Connectors
OpenAI Ads MCP for ChatGPT Ads campaigns, creatives, audiences, insights, and conversions.
Manage Google Ads from ChatGPT, Claude or any MCP client. Sign in with OAuth or use an API key.
Ads MCP for Meta, Google Ads, TikTok, Snapchat and LinkedIn: stage launches and manage campaigns.
Google Ads MCP: reports, search terms, negatives, budgets, campaigns. Approval on every write.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables management of OpenAI Ads campaigns, ad groups, ads, and insights through MCP, with approval-gated live mutations for safe write operations.128 npmMIT
- AlicenseBqualityDmaintenanceTyped MCP server for OpenAI Ads and ChatGPT Ads via the Advertiser API. Supports account, campaign, ad group, ad, creative, audience, insight, and conversion tools with readonly mode and guarded writes.124MIT
- FlicenseNot gradedqualityCmaintenanceEnables management of Google Ads accounts via MCP, providing read and write tools for campaigns, ad groups, keywords, assets, and more, with support for reporting and mutations.-
- AlicenseBqualityCmaintenanceEnables managing ChatGPT Advertiser campaigns from MCP-capable agents, including campaign creation, creative uploads, audience management, conversions setup, and insights retrieval.8924 npmMIT