道具Reference

Tools reference

59 tools, listed straight to the client — no router, no search step. Read tools run immediately; write tools return a proposal.

Each description below is the standard operating procedure the model reads: when to use the tool, when not to, what it returns and what to do when it is unsure. The risk badge and the cost line are added by the registry.

Cost is in tasks. 0 means the call is never billed.

Adako9

  • approve_proposaldestructive writefree

    Approve and execute a pending proposal

    Executes a pending proposal exactly once and reads the object back. Only call after the user has explicitly said yes to the specific proposal (quote its summary). Use when: the user's write policy is "inbox" and they approve in chat, or a client deferred a write. If the proposal expired or was already decided, returns an error — do not re-create it silently; tell the user.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "proposal_id": {
          "type": "string",
          "minLength": 8,
          "description": "Id from list_pending_proposals or the proposal_pending error"
        }
      },
      "required": [
        "proposal_id"
      ]
    }
  • explain_errorread-onlyfree

    Explain a platform error

    Translates a raw Google Ads / Meta / ChatGPT Ads error into a plain-language cause and a concrete fix, using Adako's rule table (no AI guessing). Use when: a tool returned platform_error, or the user pastes an error from the platform UI. Returns the best-matching rule; if none matches, says so — do not invent a cause.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "error_text": {
          "type": "string",
          "minLength": 3,
          "maxLength": 4000,
          "description": "The raw error message or JSON"
        },
        "platform": {
          "type": "string",
          "enum": [
            "google_ads",
            "meta_ads",
            "chatgpt_ads"
          ]
        }
      },
      "required": [
        "error_text"
      ]
    }
  • get_connections_statusread-onlyfree

    Connection health per platform

    Shows every platform login the user has connected, its token health (active / needs re-authorisation / revoked), and the active + primary ad accounts under it. Use when: a platform tool failed with not_connected or needs_reauth, or before the first platform call in a conversation. Returns links the user can open to fix a broken connection. Reads Adako's database only — no platform calls.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {}
    }
  • get_usage_statusread-onlyfree

    Plan and task usage

    Returns the user's plan, tasks used vs limit for the current period, when it resets, and the upgrade link. Use when: a tool returned quota_exceeded, or the user asks how many tasks they have left. Free; reads Adako's database only. A "task" is one billable tool call. System tools and resolvers are free.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {}
    }
  • list_connected_accountsread-onlyfree

    List ad accounts (active and inactive)

    Lists every ad account Adako knows for this user, with platform id, name, currency, timezone, and whether it is active (usable by tools) and primary (default). Use when: the user mentions an account by name and you need its id, or a tool returned account_ambiguous. Optional platform filter. Reads Adako's database only.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "platform": {
          "description": "Filter by platform",
          "type": "string",
          "enum": [
            "google_ads",
            "meta_ads",
            "chatgpt_ads"
          ]
        }
      }
    }
  • list_pending_proposalsread-onlyfree

    List proposals waiting for approval

    Lists writes that were proposed but not yet approved, with their preview and expiry (48 h). Use when: the user asks "what is waiting for my approval", or after a tool returned proposal_pending. Free.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {}
    }
  • reject_proposalwritefree

    Reject a pending proposal

    Marks a pending proposal as rejected so it will never execute. Store the user's reason when they give one (it improves future proposals). Use when: the user says no to a proposed change. Free.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "proposal_id": {
          "type": "string",
          "minLength": 8
        },
        "reason": {
          "type": "string",
          "maxLength": 500
        }
      },
      "required": [
        "proposal_id"
      ]
    }
  • start_hereread-onlyfree

    Start here — personalised next step

    Call this first in a new conversation, or whenever you are unsure what the user can do. Returns the real state of this user's Adako account: which ad platforms are connected, which account is primary, how many tasks remain, and three example prompts with their task cost. When not to use: you already know the connection state from an earlier call in this conversation. If nothing is connected, tell the user to open the connections link; do not attempt platform tools.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {}
    }
  • switch_primary_accountwritefree

    Set the primary ad account for a platform

    Makes one account the default for its platform so later tools need no account id. Changes Adako settings only; nothing on the ad platform changes, so no proposal is created. Use when: the user says "use account X from now on" or a tool returned account_ambiguous. The account must already be known to Adako (see list_connected_accounts).

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "platform": {
          "type": "string",
          "enum": [
            "google_ads",
            "meta_ads",
            "chatgpt_ads"
          ]
        },
        "account_id": {
          "type": "string",
          "minLength": 1,
          "description": "Platform account id as shown by list_connected_accounts"
        }
      },
      "required": [
        "platform",
        "account_id"
      ]
    }

Google Ads23

  • google_add_keywordswrite1 task

    Add keywords to a Google Ads ad group

    Adds keywords to one existing ad group, with an optional max CPC per keyword. Keywords that already exist in that ad group with the same match type are skipped rather than duplicated, and the result says which ones were skipped. Use when: the user has agreed on specific keywords, usually after google_research_keywords or google_analyze_search_terms. Do not use when: you would be guessing the terms, or when the campaign only accepts broad match — some newer campaign types reject exact and phrase keywords outright, and Google will refuse the whole batch with a broad-match-only error. If that happens, tell the user rather than retrying with different match types. Write keyword text plainly: no quotation marks for phrase and no square brackets for exact — the match type is a separate field. Bids are decimals in the account currency and are ignored by campaigns using automated bidding. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "ad_group_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Ad group id as returned by google_get_campaign_structure."
        },
        "keywords": {
          "minItems": 1,
          "maxItems": 100,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80,
                "description": "Keyword text without match-type punctuation (no quotes or brackets)."
              },
              "match_type": {
                "type": "string",
                "enum": [
                  "EXACT",
                  "PHRASE",
                  "BROAD"
                ]
              },
              "cpc_bid": {
                "description": "Optional max CPC, decimal in the account currency.",
                "type": "number",
                "exclusiveMinimum": 0
              }
            },
            "required": [
              "text",
              "match_type"
            ]
          },
          "description": "Keywords to add to this ad group."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "ad_group_id",
        "keywords"
      ]
    }
  • google_add_negative_keywordswrite1 task

    Add campaign-level negative keywords

    Blocks queries from triggering ads anywhere in one campaign. Negatives that already exist are skipped, and the result lists them. Use when: google_analyze_search_terms found wasted queries and the user has approved the list. Do not use when: the term also appears in queries that converted — blocking it costs real conversions. Show the user the list and get an explicit yes first. Match types work differently for negatives than for normal keywords: a broad negative blocks queries containing all of its words in any order, a phrase negative blocks queries containing the words in that order, and an exact negative blocks only that precise query. Negatives never expand to synonyms or close variants, so plurals and misspellings need their own entries. Adding a negative is reversible with google_remove_negative_keywords, but removal is permanent, so prefer adding fewer, well-understood negatives. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        },
        "keywords": {
          "minItems": 1,
          "maxItems": 200,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "match_type": {
                "type": "string",
                "enum": [
                  "EXACT",
                  "PHRASE",
                  "BROAD"
                ]
              }
            },
            "required": [
              "text",
              "match_type"
            ]
          },
          "description": "Negative keywords to add at campaign level."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "campaign_id",
        "keywords"
      ]
    }
  • google_analyze_search_termsread-only1 task

    Analyse Google Ads search terms and suggest negatives

    Reads the actual queries people typed before an ad showed, then sorts them into three buckets: converting (at least one conversion), wasted (spend above the threshold with no conversions) and new (not yet added as a keyword or a negative). It also proposes negative keywords with a match type and says why each was chosen. Use when: the user asks where their budget is going, wants negative keyword ideas, or wants to find keywords worth adding. Do not use when: the user means the keywords they bid on rather than the queries that matched them (google_get_keyword_performance). Suggestions are proposals only — nothing is added. To apply them call google_add_negative_keywords, and show the user the list first. Search term data lags roughly a day and Google hides low-volume queries, so the numbers here will not add up exactly to campaign spend. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "description": "Limit to one campaign.",
          "type": "string",
          "pattern": "^[0-9]+$"
        },
        "date_range": {
          "description": "Preset range. Alternatively pass start_date and end_date (YYYY-MM-DD). Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the period (YYYY-MM-DD). Use with end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the period (YYYY-MM-DD). Use with start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "wasted_threshold": {
          "description": "Minimum spend (decimal, account currency) before a zero-conversion term counts as wasted. Default 10.",
          "type": "number",
          "minimum": 0
        },
        "limit": {
          "description": "How many terms to pull, by spend (default 200).",
          "type": "integer",
          "minimum": 10,
          "maximum": 500
        }
      }
    }
  • google_analyze_wasted_spendread-only1 task

    Find Google Ads spend with nothing to show for it

    Finds keywords, and the campaigns they sit in, that spent real money over the period and recorded zero conversions. The rule is deliberately conservative so it never flags something that simply has not had a chance yet: a keyword must have spent at least the threshold (never below 20 in the account currency), must have zero conversions, and its campaign must have been running for more than 14 days. Anything newer is in its learning period and is excluded and counted separately. Use when: the user asks where money is being wasted, wants to cut costs, or asks for a spend audit. Do not use when: conversion tracking may be missing entirely — check google_list_conversion_actions first, because zero conversions everywhere usually means broken tracking rather than bad keywords. Returns candidates only. Pausing anything is a separate, explicit step the user must approve. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "date_range": {
          "description": "Preset range. Alternatively pass start_date and end_date (YYYY-MM-DD). Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the period (YYYY-MM-DD). Use with end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the period (YYYY-MM-DD). Use with start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "min_spend": {
          "description": "Minimum spend (decimal, account currency) for a keyword to count. Raised to 20 if lower. Default 20.",
          "type": "number",
          "minimum": 0
        },
        "limit": {
          "description": "How many keyword rows to scan, by spend (default 300).",
          "type": "integer",
          "minimum": 10,
          "maximum": 500
        }
      }
    }
  • google_create_search_campaignwrite1 task

    Create a Google Ads Search campaign (paused)

    Creates a complete Search campaign in one atomic operation: daily budget, campaign, location and language targeting, ad groups, keywords, one responsive search ad per ad group and optional campaign-level negatives. Either everything is created or nothing is. Everything is created PAUSED — the campaign, its ad groups and its ads — so no money can be spent until the user turns it on in the Google Ads interface. Say this explicitly when you report the result. Use when: the user has agreed on a structure (budget, locations, ad groups, keywords, ad copy) and wants it built. Do not use when: anything is still undecided. Resolve place names with google_resolve_locations first (free text is rejected), check ad copy with google_validate_ad_copy, and confirm the daily budget in the account currency. Call this once per campaign: on an error, read what exists with google_list_campaigns rather than retrying. The preview runs Google's own dry run (validateOnly), so policy and structural rejections surface before anything is created. Search partners are off unless include_search_partners is true. Budgets and bids are decimals in the account currency, never micros; ids are strings. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "description": "Campaign name. Must not already exist in the account."
        },
        "daily_budget": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Average daily budget as a decimal in the account currency (for example 50 for $50/day). Never micros."
        },
        "bidding_strategy": {
          "type": "string",
          "enum": [
            "MAXIMIZE_CLICKS",
            "MAXIMIZE_CONVERSIONS",
            "TARGET_CPA",
            "TARGET_ROAS",
            "MANUAL_CPC"
          ],
          "description": "How Google should bid. TARGET_CPA needs target_cpa; TARGET_ROAS needs target_roas."
        },
        "target_cpa": {
          "description": "Target cost per conversion, decimal in the account currency.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "target_roas": {
          "description": "Target return on ad spend as a ratio, e.g. 4 for 400%.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "location_ids": {
          "minItems": 1,
          "maxItems": 50,
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "description": "Geo target constant ids from google_resolve_locations. Place names are rejected."
        },
        "language_ids": {
          "description": "Language constant ids, e.g. [\"1000\"] for English.",
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[0-9]+$"
          }
        },
        "include_search_partners": {
          "description": "Show on Google Search partner sites too. Default false: partner traffic converts differently and is hard to segment.",
          "type": "boolean"
        },
        "start_date": {
          "description": "First day the campaign may run (YYYY-MM-DD).",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day the campaign may run (YYYY-MM-DD).",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "ad_groups": {
          "minItems": 1,
          "maxItems": 10,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "Ad group name, unique within the campaign."
              },
              "default_bid": {
                "description": "Default max CPC for the ad group, decimal in the account currency.",
                "type": "number",
                "exclusiveMinimum": 0
              },
              "keywords": {
                "minItems": 1,
                "maxItems": 200,
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 80,
                      "description": "Keyword text, without match-type punctuation."
                    },
                    "match_type": {
                      "type": "string",
                      "enum": [
                        "EXACT",
                        "PHRASE",
                        "BROAD"
                      ],
                      "description": "EXACT, PHRASE or BROAD."
                    },
                    "cpc_bid": {
                      "description": "Optional max CPC for this keyword, decimal in the account currency.",
                      "type": "number",
                      "exclusiveMinimum": 0
                    }
                  },
                  "required": [
                    "text",
                    "match_type"
                  ]
                },
                "description": "Keywords for this ad group."
              },
              "headlines": {
                "minItems": 3,
                "maxItems": 15,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Between 3 and 15 headlines, each at most 30 characters."
              },
              "descriptions": {
                "minItems": 2,
                "maxItems": 4,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Between 2 and 4 descriptions, each at most 90 characters."
              },
              "path1": {
                "description": "First display path segment.",
                "type": "string",
                "maxLength": 15
              },
              "path2": {
                "description": "Second display path segment; needs path1.",
                "type": "string",
                "maxLength": 15
              },
              "final_url": {
                "type": "string",
                "format": "uri",
                "description": "Landing page for this ad group, including https://."
              }
            },
            "required": [
              "name",
              "keywords",
              "headlines",
              "descriptions",
              "final_url"
            ]
          },
          "description": "One to ten ad groups, each with keywords and one responsive search ad."
        },
        "negative_keywords": {
          "description": "Campaign-level negative keywords applied to every ad group.",
          "maxItems": 100,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string",
                "minLength": 1,
                "maxLength": 80
              },
              "match_type": {
                "type": "string",
                "enum": [
                  "EXACT",
                  "PHRASE",
                  "BROAD"
                ]
              }
            },
            "required": [
              "text",
              "match_type"
            ]
          }
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "campaign_name",
        "daily_budget",
        "bidding_strategy",
        "location_ids",
        "ad_groups"
      ]
    }
  • google_get_ad_group_performanceread-only1 task

    Google Ads ad group performance

    Reports spend, clicks, CTR, conversions, CPA and ROAS per ad group for a period, optionally inside one campaign, ordered by spend. Use when: a campaign looks off and you need to see which ad group is responsible, or the user asks about a specific ad group. Do not use when: the question is about individual keywords (google_get_keyword_performance) or about the whole campaign (google_get_campaign_performance). Pass either date_range or start_date + end_date, never both. Money is a decimal in the account currency; ad group ids are strings. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "description": "Limit to one campaign. Omit to see every ad group in the account.",
          "type": "string",
          "pattern": "^[0-9]+$"
        },
        "date_range": {
          "description": "Preset range. Alternatively pass start_date and end_date (YYYY-MM-DD). Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the period (YYYY-MM-DD). Use with end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the period (YYYY-MM-DD). Use with start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "limit": {
          "description": "Maximum ad groups (default 50, by spend).",
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      }
    }
  • google_get_campaign_performanceread-only1 task

    Google Ads campaign performance with period-over-period change

    Reports spend, impressions, clicks, CTR, conversions, conversion value, CPA and ROAS per campaign for a period, plus the change against the immediately preceding period of the same length. Use when: the user asks how campaigns performed, whether results improved, or what a campaign costs per conversion. Do not use when: the user wants to know what exists rather than how it performed (google_list_campaigns), or wants search-query detail (google_analyze_search_terms). Pass either date_range (a preset) or start_date + end_date, never both. Periods are calendar days in the account's own timezone. Money is a decimal in the account currency. CPA is blank when there were no conversions and ROAS is blank when there was no spend — say so rather than printing zero. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "date_range": {
          "description": "Preset range. Alternatively pass start_date and end_date (YYYY-MM-DD). Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the period (YYYY-MM-DD). Use with end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the period (YYYY-MM-DD). Use with start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "campaign_ids": {
          "description": "Limit the report to these campaign ids.",
          "maxItems": 50,
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[0-9]+$"
          }
        },
        "limit": {
          "description": "Maximum campaigns to return (default 50).",
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        }
      }
    }
  • google_get_campaign_structureread-only1 task

    Google Ads campaign contents (ad groups, keywords, ads)

    Returns the inside of one campaign: its ad groups, the keywords in each (text, match type, state, quality score) and the responsive search ads (headlines, descriptions, display paths, final URL). Use when: you need ad group or keyword ids before changing anything, or the user asks what a campaign is actually targeting or saying. Do not use when: the user asks about performance numbers (use the performance tools) or about which search queries triggered ads (use google_analyze_search_terms). Paginated by ad group. When has_more is true, call again with page_token set to the returned value and merge the pages before answering; never present a partial structure as complete. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        },
        "page_size": {
          "description": "Ad groups per page (default 5, max 20).",
          "type": "integer",
          "minimum": 1,
          "maximum": 20
        },
        "page_token": {
          "description": "Cursor from the previous call. Omit for the first page.",
          "type": "string"
        },
        "include": {
          "description": "Trim the response: summary lists ad groups only.",
          "type": "string",
          "enum": [
            "all",
            "keywords",
            "ads",
            "summary"
          ]
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • google_get_campaign_targetingread-only1 task

    Google Ads campaign targeting

    Shows who and where a campaign is targeting: locations (with the resolved place names and any exclusions), languages, ad schedule, device bid adjustments and attached audiences. Use when: the user asks who is being targeted, why an ad shows in the wrong place, or before changing targeting so you can describe what exists today. Do not use when: the user asks about keywords — those are targeting too but live in google_get_campaign_structure. Location and language ids returned here are the same constant ids the write tools accept, so you can quote them directly. Nothing is changed by this call. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • google_get_keyword_performanceread-only1 task

    Google Ads keyword performance (top spenders)

    Reports the highest-spending keywords for a period with match type, state, quality score, clicks, conversions, CPA and ROAS. Use when: the user asks which keywords work, which are expensive, or you need keyword ids and current bids before changing them. Do not use when: the user asks about the actual search queries people typed — those are search terms, not keywords (google_analyze_search_terms). Returns the top N by spend, so a keyword missing from the list simply spent less than the ones shown. Pass either date_range or start_date + end_date, never both. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "description": "Limit to one campaign.",
          "type": "string",
          "pattern": "^[0-9]+$"
        },
        "ad_group_id": {
          "description": "Limit to one ad group.",
          "type": "string",
          "pattern": "^[0-9]+$"
        },
        "date_range": {
          "description": "Preset range. Alternatively pass start_date and end_date (YYYY-MM-DD). Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the period (YYYY-MM-DD). Use with end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the period (YYYY-MM-DD). Use with start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "limit": {
          "description": "How many keywords by spend (default 25).",
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      }
    }
  • google_list_campaignsread-only1 task

    List Google Ads campaigns

    Lists the campaigns in a Google Ads account with their state, campaign type, bidding strategy, daily budget (shared or not) and last-30-day spend, clicks and conversions. Use when: you need campaign ids for any other tool, or the user asks what campaigns exist, what they cost or which are running. Do not use when: the user wants performance over a specific period (use google_get_campaign_performance) or the contents of one campaign (use google_get_campaign_structure). Returns one row per campaign, most expensive first. Budgets are decimals in the account currency; a "shared" budget is used by more than one campaign, so changing it affects all of them. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "status": {
          "description": "Campaign state to include. Defaults to everything except removed campaigns.",
          "type": "string",
          "enum": [
            "ENABLED",
            "PAUSED",
            "REMOVED",
            "ALL"
          ]
        },
        "campaign_type": {
          "description": "Campaign type to include. Defaults to all types.",
          "type": "string",
          "enum": [
            "SEARCH",
            "PERFORMANCE_MAX",
            "DISPLAY",
            "SHOPPING",
            "VIDEO",
            "DEMAND_GEN",
            "ALL"
          ]
        },
        "limit": {
          "description": "Maximum campaigns to return (default 100).",
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      }
    }
  • google_list_conversion_actionsread-only1 task

    Google Ads conversion actions

    Lists the conversion actions set up on the account: name, state, category, how each one counts (every conversion or one per click), whether it is included in the "Conversions" column, and the click-through lookback window. Use when: conversion numbers look wrong or absent, before recommending a conversion-based bidding strategy, or when the user asks what is being tracked. Do not use when: the user wants conversion counts per campaign (use google_get_campaign_performance). Read this before blaming keywords for zero conversions: if no action is enabled and primary for a goal, the account cannot report conversions at all, and Smart Bidding on conversions will not work. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        }
      }
    }
  • google_pause_ad_groupdestructive write1 task

    Pause a Google Ads ad group

    Stops one ad group inside a campaign from serving, leaving the rest of the campaign running. Use when: one ad group is clearly the problem and the user wants only that part stopped. Do not use when: the whole campaign should stop (google_pause_campaign) or when only some keywords are at fault (google_update_keyword). Nothing is deleted; the ad group can be resumed at any time. Its budget belongs to the campaign, so pausing an ad group frees that spend for the other ad groups rather than saving it. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "ad_group_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Ad group id as returned by google_get_campaign_structure."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "ad_group_id"
      ]
    }
  • google_pause_campaigndestructive write1 task

    Pause a Google Ads campaign

    Stops a live campaign from serving. Spend stops as soon as Google applies the change; nothing is deleted and google_resume_campaign puts it back exactly as it was. Use when: the user has clearly said to stop a specific campaign, and you have shown them what it is currently spending. Do not use when: the user only wants to reduce spend (change the budget instead), or when the campaign is already paused — check google_list_campaigns first. Pausing is never a way to delete something. Smart Bidding strategies lose learning while paused, so a long pause can mean a slower ramp when it is resumed; mention this for conversion-based campaigns. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • google_remove_negative_keywordsdestructive write1 task

    Remove campaign negative keywords (permanent)

    Deletes negative keywords from a campaign so those queries can trigger ads again. This is the only tool in Adako that removes anything, and the removal is permanent: a removed criterion cannot be restored, only re-added as a new one. Use when: the user has confirmed that a specific negative is blocking traffic they want, and you have shown them the exact list by name. Do not use when: the user asked to "turn off", "stop" or "pause" something — that is never a removal. Negatives cannot be paused; if the user is unsure, leave them in place. Requires confirm_delete: true. Ask the user first, in plain words, naming every negative that will be deleted. Ids that are not negatives on this campaign are reported back rather than silently ignored. Removing a negative widens matching immediately, which can increase spend. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        },
        "keyword_ids": {
          "minItems": 1,
          "maxItems": 100,
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "description": "Criterion ids of the campaign negatives to remove, from google_get_campaign_targeting."
        },
        "confirm_delete": {
          "description": "Must be true to remove anything. Ask the user first.",
          "type": "boolean"
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "campaign_id",
        "keyword_ids"
      ]
    }
  • google_research_keywordsread-only1 task

    Google Ads keyword ideas with volume and bid ranges

    Asks Google Keyword Planner for keyword ideas from seed terms or a landing page, and returns average monthly searches, competition and the top-of-page bid range for each. Use when: planning a new campaign, expanding an existing one, or checking whether a term has any real search volume. Do not use when: the user wants the performance of keywords they already run (google_get_keyword_performance) or the queries that triggered their ads (google_analyze_search_terms). Volumes are broad averages Google rounds heavily, and bid ranges are estimates, not what you will pay. Keyword Planner needs at least Basic API access; on a lower access level this returns access_level_insufficient — say so plainly and suggest planning from search-term data instead. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "seed_keywords": {
          "description": "Starting terms. Give either these, a page_url, or both.",
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          }
        },
        "page_url": {
          "description": "A landing page Google should read for ideas.",
          "type": "string",
          "format": "uri"
        },
        "location_ids": {
          "description": "Geo target constant ids from google_resolve_locations. Volumes are for these places.",
          "maxItems": 10,
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[0-9]+$"
          }
        },
        "language_id": {
          "description": "Language constant id, e.g. 1000 for English.",
          "type": "string",
          "pattern": "^[0-9]+$"
        },
        "include_search_partners": {
          "description": "Include the Search Network partners in the volume estimate. Default false.",
          "type": "boolean"
        },
        "limit": {
          "description": "Maximum ideas to return (default 50).",
          "type": "integer",
          "minimum": 5,
          "maximum": 200
        }
      }
    }
  • google_resolve_locationsread-onlyfree

    Turn place names into Google location ids

    Converts place names ("Berlin", "California", "United Kingdom") into the numeric geo target constant ids the write tools require. Free text never reaches a campaign: every location a campaign targets must come from this tool. Use when: the user names a place and you are about to create or change a campaign's targeting. Do not use when: you already have numeric ids from google_get_campaign_targeting — pass those straight through. If a name matches more than one place the tool refuses to choose and returns the candidates with their canonical names and country codes; show them to the user and ask which one they mean. A name that matches nothing is reported as unresolved, never silently dropped. This call is free and changes nothing. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "locations": {
          "minItems": 1,
          "maxItems": 10,
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "description": "Place names or numeric geo target constant ids. Ids are verified rather than searched."
        },
        "country_code": {
          "description": "Two-letter country code to disambiguate names that exist in several countries, e.g. \"GB\".",
          "type": "string",
          "minLength": 2,
          "maxLength": 2
        }
      },
      "required": [
        "locations"
      ]
    }
  • google_resume_ad_groupwrite1 task

    Resume a paused Google Ads ad group

    Turns a paused ad group back on. Use when: the user asked to restart a specific ad group. Do not use when: its campaign is paused — the ad group will still show nothing, and the user probably means google_resume_campaign. Check the campaign state and say so. The ad group resumes with the keywords, bids and ads it already had; nothing is recreated. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "ad_group_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Ad group id as returned by google_get_campaign_structure."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "ad_group_id"
      ]
    }
  • google_resume_campaignwrite1 task

    Resume a paused Google Ads campaign

    Turns a paused campaign back on. It resumes against its existing daily budget and bidding strategy. Use when: the user has asked to restart a specific campaign. Do not use when: the campaign was paused because of a problem that is still unresolved (broken landing page, disapproved ads, exhausted budget) — check first and say what you found. Money starts moving again immediately, so confirm the daily budget with the user before resuming. Automated bidding may need a few days to re-learn. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • google_update_campaigndestructive write1 task

    Update Google Ads campaign settings

    Changes a campaign's name, on/off state, end date or Search-partner setting. Only the fields you pass are touched; everything else is left alone. Use when: the user asked for one of these specific changes and named the campaign. Do not use when: the user only wants to pause or resume — google_pause_campaign and google_resume_campaign say exactly that and are easier to audit. Do not use it to change budgets (google_update_campaign_budget). Search partners default to off for a reason: that inventory sits on other search sites, cannot be excluded site by site, and usually performs differently from Google Search. Turning it on is a real change in where ads appear, so say so. Setting an end date stops delivery at the end of that day in the account timezone. The preview shows the exact before/after for every field. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        },
        "name": {
          "description": "New campaign name.",
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "status": {
          "description": "Turn the campaign on or off.",
          "type": "string",
          "enum": [
            "ENABLED",
            "PAUSED"
          ]
        },
        "end_date": {
          "description": "Last day the campaign may run (YYYY-MM-DD).",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "remove_end_date": {
          "description": "Set true to let the campaign run indefinitely.",
          "type": "boolean"
        },
        "include_search_partners": {
          "description": "Show on Google Search partner sites. Off is the safer default: partner traffic cannot be excluded per site and often converts worse.",
          "type": "boolean"
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • google_update_campaign_budgetdestructive write1 task

    Change a Google Ads campaign daily budget

    Changes the average daily budget attached to one campaign. The amount is a decimal in the account currency; Adako converts it for Google. Before changing anything the tool reads the budget and detects whether it is a *shared* budget. A shared budget is used by several campaigns at once, so raising or lowering it changes all of them. When that is the case the call is refused until you have listed the affected campaigns to the user and they agree — then call again with confirm_shared_budget: true. Use when: the user has stated a new daily amount. Do not use when: the campaign uses a portfolio bidding strategy that manages spend centrally, or the user only wants a temporary change — say what will happen instead. Google may spend up to twice the daily budget on a single day and balances it across the month, so the monthly figure is roughly the daily amount times 30.4. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Campaign id as returned by google_list_campaigns."
        },
        "daily_budget": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "New average daily budget as a decimal in the account currency (for example 75 for $75/day). Never micros."
        },
        "confirm_shared_budget": {
          "description": "Set true only after telling the user which other campaigns share this budget and getting their agreement.",
          "type": "boolean"
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "campaign_id",
        "daily_budget"
      ]
    }
  • google_update_keyworddestructive write1 task

    Change a keyword bid or state

    Pauses, re-enables or re-bids one keyword. Use when: a specific keyword is over- or under-spending and the user has agreed what to do about it. Do not use when: you want to change the keyword text or its match type — neither can be edited after creation. Add a new keyword with google_add_keywords and pause the old one instead, and say that is what you are doing. Bids are decimals in the account currency. A max CPC is ignored while the campaign uses an automated bidding strategy, so check the strategy with google_list_campaigns before promising the bid will take effect. Pausing a keyword stops it matching; it is not deleted and can be re-enabled at any time. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "customer_id": {
          "description": "Google Ads customer id (10 digits, dashes optional). Omit to use the primary account; list_connected_accounts shows the valid ids.",
          "type": "string"
        },
        "ad_group_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Ad group id as returned by google_get_campaign_structure."
        },
        "keyword_id": {
          "type": "string",
          "pattern": "^[0-9]+$",
          "description": "Criterion id of the keyword, from google_get_campaign_structure or google_get_keyword_performance."
        },
        "status": {
          "description": "Turn the keyword on or off.",
          "type": "string",
          "enum": [
            "ENABLED",
            "PAUSED"
          ]
        },
        "cpc_bid": {
          "description": "New max CPC as a decimal in the account currency.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        }
      },
      "required": [
        "ad_group_id",
        "keyword_id"
      ]
    }
  • google_validate_ad_copyread-onlyfree

    Check responsive search ad copy against the RSA limits

    Checks headlines, descriptions and display paths against the responsive search ad rules before anything is sent to Google: at most 15 headlines of 30 characters, at most 4 descriptions of 90, display paths of 15, at least 3 headlines and 2 descriptions, no duplicates, no shouting in capitals and no repeated or excessive punctuation. Use when: you have drafted ad copy, or the user pasted copy and wants to know whether it will be accepted. Do not use when: the question is about policy topics (medical claims, trademarks) — this tool only checks format and style, not eligibility. Runs entirely inside Adako: no Google call, no cost, no connection required. Fix every error before calling google_create_search_campaign, which applies exactly the same rules and will refuse the whole campaign otherwise. Warnings are advice, not blockers. If you are unsure which account, campaign or period the user means, ask them — do not guess ids or dates.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "headlines": {
          "maxItems": 30,
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Headline texts, in the order you would submit them."
        },
        "descriptions": {
          "maxItems": 10,
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Description texts."
        },
        "path1": {
          "description": "First display path segment shown after the domain.",
          "type": "string"
        },
        "path2": {
          "description": "Second display path segment. Only valid with path1.",
          "type": "string"
        },
        "final_url": {
          "description": "Landing page URL, including https://.",
          "type": "string"
        }
      },
      "required": [
        "headlines",
        "descriptions"
      ]
    }

Meta Ads17

  • meta_analyze_wasted_spendread-only1 task

    Find Meta spend that bought nothing

    Finds ad sets that spent money and produced no results in the window, and ad sets whose cost per result is far above the account's own average. Everything still in the learning phase is listed separately and explicitly excluded from the "pause it" recommendation. Use when: the user asks where their Meta budget is leaking, or before any budget reallocation. Do not use as a pause list without reading the rule it prints — an ad set with no results may simply be new, or may be on an objective that records no conversions at all. Returns three groups: wasted (spend above the threshold, zero results), expensive (cost per result more than the multiplier above the account average), and learning (spending but not yet out of the learning phase — leave these alone). The rule is stated in the output so the user can disagree with it. If nothing crosses the threshold, say the account looks clean rather than inventing a finding.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "date_range": {
          "description": "Preset reporting window. The \"last N days\" windows end yesterday so no partial day is mixed in. Alternatively pass start_date and end_date. Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the reporting window, YYYY-MM-DD. Requires end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the reporting window, YYYY-MM-DD, inclusive. Requires start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Restrict the analysis to one campaign."
        },
        "min_spend": {
          "description": "Minimum spend (decimal, account currency) before an ad set counts as wasteful. Default: 1% of the window total, floor 10.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "cost_multiplier": {
          "description": "How many times the account average cost per result counts as \"expensive\". Default 2.",
          "type": "number",
          "minimum": 1.1,
          "maximum": 10
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_create_image_campaignwrite3 tasks

    Create a paused Meta image campaign

    Builds a complete single-image campaign: campaign, one ad set, the image upload, the creative and one ad. Every object is created PAUSED, so nothing spends until the user turns it on in Ads Manager. Use when: the user has agreed on objective, budget, audience, image and copy. Gather those first — resolve locations and interests with meta_search_targeting, the Page with meta_list_pages, the pixel with meta_list_pixels, and check the image with meta_validate_creative_url. Do not use to add another ad or audience to something that already exists; this always creates a new campaign, and calling it twice for the same brief creates two campaigns that both spend. Do not pass free text for locations or interests — only ids from the resolver tools are accepted. Returns the four new ids and reads the statuses back so you can confirm everything is paused. Refuses to start when: the account has no promotable Page; the account has several Pages and none was chosen; a sales or leads objective has no pixel; or an EU/EEA country is targeted without dsa_beneficiary and dsa_payor. Ask the user for the missing piece rather than substituting a value.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "campaign_name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "description": "Name shown in Ads Manager. Say what it sells and to whom."
        },
        "objective": {
          "type": "string",
          "enum": [
            "OUTCOME_AWARENESS",
            "OUTCOME_TRAFFIC",
            "OUTCOME_ENGAGEMENT",
            "OUTCOME_LEADS",
            "OUTCOME_SALES",
            "OUTCOME_APP_PROMOTION"
          ],
          "description": "What Meta should optimise the campaign for. OUTCOME_SALES and OUTCOME_LEADS need a pixel; OUTCOME_TRAFFIC, OUTCOME_ENGAGEMENT and OUTCOME_AWARENESS do not."
        },
        "daily_budget": {
          "description": "Daily budget as a decimal in the account currency (25 means 25 dollars, not 2500 cents). One of daily_budget or lifetime_budget is required.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "lifetime_budget": {
          "description": "Total budget for the whole flight, decimal in the account currency. Requires end_time.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "start_time": {
          "description": "When delivery may start, YYYY-MM-DD or an ISO timestamp. Defaults to immediately after the user activates it.",
          "type": "string"
        },
        "end_time": {
          "description": "When delivery must stop, YYYY-MM-DD or an ISO timestamp. Required with lifetime_budget.",
          "type": "string"
        },
        "optimization_goal": {
          "description": "Override what the ad set optimises for. Leave empty to use the objective default.",
          "type": "string"
        },
        "billing_event": {
          "description": "What Meta charges for. Leave empty to use IMPRESSIONS.",
          "type": "string"
        },
        "pixel_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Pixel that records the conversion. Required for sales and leads objectives; get it from meta_list_pixels."
        },
        "conversion_event": {
          "description": "The pixel event to optimise for. Defaults to PURCHASE for sales, LEAD for leads.",
          "type": "string",
          "enum": [
            "PURCHASE",
            "LEAD",
            "COMPLETE_REGISTRATION",
            "ADD_TO_CART",
            "INITIATED_CHECKOUT",
            "ADD_PAYMENT_INFO",
            "SUBSCRIBE",
            "START_TRIAL",
            "SUBMIT_APPLICATION",
            "CONTACT",
            "SCHEDULE",
            "SEARCH",
            "CONTENT_VIEW",
            "DONATE",
            "FIND_LOCATION"
          ]
        },
        "countries": {
          "description": "Two-letter country codes from meta_search_targeting.",
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          }
        },
        "region_keys": {
          "description": "Region keys from meta_search_targeting (never region names).",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "city_keys": {
          "description": "City keys from meta_search_targeting (never city names).",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "age_min": {
          "description": "Youngest age to target. Minimum 18.",
          "type": "integer",
          "minimum": 18,
          "maximum": 65
        },
        "age_max": {
          "description": "Oldest age to target. 65 means 65 and over.",
          "type": "integer",
          "minimum": 18,
          "maximum": 65
        },
        "genders": {
          "description": "Restrict by gender. Defaults to all — narrow only when the user asks.",
          "type": "string",
          "enum": [
            "all",
            "men",
            "women"
          ]
        },
        "interest_ids": {
          "description": "Interest ids from meta_search_targeting. Never free text.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "behavior_ids": {
          "description": "Behaviour ids from meta_search_targeting. Never free text.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "custom_audience_ids": {
          "description": "Custom audience ids from meta_list_custom_audiences.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "excluded_custom_audience_ids": {
          "description": "Custom audiences to exclude, e.g. existing customers.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "advantage_audience": {
          "description": "Let Meta deliver beyond the listed interests. Defaults to off so the targeting the user asked for is the targeting they get.",
          "type": "boolean"
        },
        "dsa_beneficiary": {
          "description": "Who benefits from the ad. Required whenever an EU or EEA country is targeted.",
          "type": "string",
          "maxLength": 512
        },
        "dsa_payor": {
          "description": "Who pays for the ad. Required whenever an EU or EEA country is targeted.",
          "type": "string",
          "maxLength": 512
        },
        "special_ad_categories": {
          "description": "Declare a restricted category (housing, employment, credit, politics, gambling, financial products). Leave empty unless the ad genuinely falls into one — a wrong declaration limits delivery, a missing one breaks Meta policy.",
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "EMPLOYMENT",
              "HOUSING",
              "CREDIT",
              "ISSUES_ELECTIONS_POLITICS",
              "ONLINE_GAMBLING_AND_GAMING",
              "FINANCIAL_PRODUCTS_SERVICES"
            ]
          }
        },
        "facebook_page_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Page the ad runs from, from meta_list_pages. Required when the account has more than one Page."
        },
        "instagram_account_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Instagram account to run the ad from, from meta_list_pages."
        },
        "image_url": {
          "type": "string",
          "format": "uri",
          "description": "Public HTTPS URL of the image. Check it with meta_validate_creative_url first."
        },
        "primary_text": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2200,
          "description": "Main ad copy. About 125 characters show before \"See more\"."
        },
        "headline": {
          "description": "Headline under the image. About 40 characters show.",
          "type": "string",
          "maxLength": 255
        },
        "description": {
          "description": "Description line. About 30 characters show, and only on some placements.",
          "type": "string",
          "maxLength": 255
        },
        "landing_page_url": {
          "type": "string",
          "format": "uri",
          "description": "Where the ad sends people. Must be HTTPS."
        },
        "call_to_action": {
          "description": "Button label. Defaults to LEARN_MORE.",
          "type": "string",
          "enum": [
            "LEARN_MORE",
            "SHOP_NOW",
            "SIGN_UP",
            "SUBSCRIBE",
            "DOWNLOAD",
            "BOOK_NOW",
            "GET_QUOTE",
            "CONTACT_US",
            "APPLY_NOW",
            "GET_OFFER",
            "ORDER_NOW",
            "SEE_MORE",
            "GET_STARTED",
            "BUY_NOW",
            "DONATE_NOW",
            "NO_BUTTON"
          ]
        },
        "ad_set_name": {
          "description": "Ad set name. Defaults to the campaign name plus a suffix.",
          "type": "string",
          "maxLength": 200
        },
        "ad_name": {
          "description": "Ad name. Defaults to the campaign name plus a suffix.",
          "type": "string",
          "maxLength": 200
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "campaign_name",
        "objective",
        "image_url",
        "primary_text",
        "landing_page_url"
      ]
    }
  • meta_get_ad_performanceread-only1 task

    Meta ad performance

    Ad-level results joined with the creative behind each ad (creative name and thumbnail), plus the previous-period comparison. Use when: choosing which creative to keep, refresh or turn off, or when the user asks which ad is working. Do not use to compare audiences — that is meta_get_adset_performance with a breakdown. Returns frequency alongside CTR: a rising frequency with a falling CTR is the usual signature of creative fatigue, and is worth saying out loud when the numbers show it. Scope with ad_set_id or campaign_id; ad-level reporting across a whole account is slow and rarely what the user means.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "date_range": {
          "description": "Preset reporting window. The \"last N days\" windows end yesterday so no partial day is mixed in. Alternatively pass start_date and end_date. Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the reporting window, YYYY-MM-DD. Requires end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the reporting window, YYYY-MM-DD, inclusive. Requires start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Only ads in this campaign."
        },
        "ad_set_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Only ads in this ad set."
        },
        "limit": {
          "description": "Maximum ads (default 20, ordered by spend).",
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_get_adset_performanceread-only1 task

    Meta ad set performance

    Ad-set level results with the objective's own KPI and a previous-period comparison, optionally split by a breakdown (age and gender, publisher platform and position, device, or country). Use when: one campaign is under- or over-performing and you need to know which audience or placement is responsible. Do not use with a breakdown to judge overall performance — breakdown rows do not sum to the campaign total for every metric, and some metrics are unavailable when a breakdown is applied. Returns each ad set's spend, results, cost per result and ROAS where the objective supports it. If the user asks "why is this campaign expensive", run this with the placement breakdown before recommending anything.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "date_range": {
          "description": "Preset reporting window. The \"last N days\" windows end yesterday so no partial day is mixed in. Alternatively pass start_date and end_date. Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the reporting window, YYYY-MM-DD. Requires end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the reporting window, YYYY-MM-DD, inclusive. Requires start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Only ad sets in this campaign."
        },
        "ad_set_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Report on a single ad set."
        },
        "breakdown": {
          "description": "Split each ad set by this dimension. Omit for a plain ad set table.",
          "type": "string",
          "enum": [
            "age,gender",
            "publisher_platform,platform_position",
            "device_platform",
            "country"
          ]
        },
        "limit": {
          "description": "Maximum rows (default 25, ordered by spend).",
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_get_campaign_performanceread-only1 task

    Meta campaign performance

    Campaign-level results for a window, next to the same-length window before it, with the KPI each campaign's objective is actually judged on: purchases and purchase ROAS for sales, leads and cost per lead for lead generation, link clicks and CPC for traffic, reach and CPM for awareness, engagements for engagement, installs for app promotion. Use when: the user asks how Meta is doing, which campaigns are worth more budget, or what changed week over week. Do not use to inspect settings (meta_list_campaigns) or to find waste inside an ad set (meta_analyze_wasted_spend). Returns "not applicable" rather than a blank or a zero for ROAS on objectives that record no revenue — never present a missing ROAS as a bad ROAS. If the user's date wording is vague ("recently", "lately"), ask which window they mean instead of picking one.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "date_range": {
          "description": "Preset reporting window. The \"last N days\" windows end yesterday so no partial day is mixed in. Alternatively pass start_date and end_date. Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the reporting window, YYYY-MM-DD. Requires end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the reporting window, YYYY-MM-DD, inclusive. Requires start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Report on a single campaign."
        },
        "limit": {
          "description": "Maximum campaigns in the table (default 25, ordered by spend).",
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_list_ad_setsread-only1 task

    List Meta ad sets

    Lists ad sets with budget, optimisation goal, billing event, a one-line targeting summary, schedule and learning-phase state. Use when: you need ad set ids, want to know what an ad set optimises for before changing its budget, or need to know whether it is still learning. Do not use for results — pair it with meta_get_adset_performance. Returns learning stage: an ad set in LEARNING has not yet had enough conversions for stable delivery, so budget or targeting edits restart the phase. Say so before recommending a change. Pass campaign_id to scope the list; without it you get every ad set in the account.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Only ad sets in this campaign."
        },
        "status": {
          "description": "Comma-separated effective_status filter, e.g. \"ACTIVE\".",
          "type": "string"
        },
        "limit": {
          "description": "Maximum ad sets to return (default 100).",
          "type": "integer",
          "minimum": 1,
          "maximum": 500
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_list_adsread-only1 task

    List Meta ads

    Lists individual ads with delivery status, the creative behind each one and a preview link the user can open. Use when: you need ad ids to pause or compare specific ads, or the user asks what creative is live. Do not use to judge creative quality — get the numbers from meta_get_ad_performance first. Returns effective_status, which is where you see review problems: DISAPPROVED or PENDING_REVIEW explain zero delivery far more often than budget does. Scope with ad_set_id or campaign_id; without either you get the whole account.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "ad_set_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Only ads in this ad set."
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Only ads in this campaign."
        },
        "status": {
          "description": "Comma-separated effective_status filter, e.g. \"ACTIVE,PAUSED\".",
          "type": "string"
        },
        "limit": {
          "description": "Maximum ads to return (default 100).",
          "type": "integer",
          "minimum": 1,
          "maximum": 500
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_list_campaignsread-only1 task

    List Meta campaigns

    Lists the campaigns in a Meta ad account with objective, delivery status, budget (as a decimal in the account currency), bid strategy and any Advantage+ state the account exposes. Use when: you need campaign ids before reading performance or changing anything, or the user asks what is running. Do not use to compare results — that is meta_get_campaign_performance; this call returns configuration only, no spend or conversions. Returns one row per campaign plus the campaign id you must pass to other tools. Budgets set at campaign level mean the campaign uses campaign budget optimisation and its ad sets have no budgets of their own. If unsure which account: call list_connected_accounts first rather than guessing an id.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "status": {
          "description": "Comma-separated effective_status filter, e.g. \"ACTIVE\" or \"ACTIVE,PAUSED\". Omit for everything except deleted campaigns.",
          "type": "string"
        },
        "objective": {
          "description": "Filter to one objective, e.g. OUTCOME_SALES.",
          "type": "string"
        },
        "limit": {
          "description": "Maximum campaigns to return (default 100).",
          "type": "integer",
          "minimum": 1,
          "maximum": 500
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_list_custom_audiencesread-only1 task

    List Meta custom and lookalike audiences

    Lists the saved custom and lookalike audiences on the ad account with their type, approximate size and whether Meta considers them usable right now. Use when: planning retargeting or exclusions, or when the user refers to an audience by name and you need its id. Do not assume an audience is usable because it exists — Meta refuses to deliver to audiences below roughly a thousand people, and the delivery status says so. Returns each audience id plus its subtype (website, customer list, engagement, lookalike), which decides whether it makes sense as a target or only as an exclusion. If an audience is too small, say so and suggest broadening rather than launching against it.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_list_pagesread-only1 task

    List promotable Facebook Pages

    Lists the Facebook Pages this ad account may advertise from, with any Instagram account linked to each one. Use when: creating an ad (every ad needs a Page), or when a creation attempt failed because no Page was given. Do not guess a Page id from a Page name in a URL — a Page the user administers is not necessarily one this ad account can promote. Returns the Page id for facebook_page_id and the Instagram account id for instagram_account_id. When more than one Page comes back, ask the user which one to advertise from; do not choose for them. If the list is empty the user must add a Page to the ad account's Business portfolio before any ad can be created.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_list_pixelsread-only1 task

    List Meta pixels

    Lists the pixels on the ad account with the time each one last received an event, and the standard events it has recently recorded where Meta exposes them. Use when: setting up a sales or leads campaign — those objectives cannot optimise without a pixel and an event — or when diagnosing why conversions are not being recorded. Do not treat a pixel that exists as a pixel that works: a pixel with no recent fire time will not deliver conversions no matter what the campaign says. Returns the pixel id needed by meta_create_image_campaign and the event names that are safe to optimise for. If no pixel has fired recently, tell the user that a conversion campaign will not optimise and suggest a traffic objective instead.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • meta_pause_entitydestructive write1 task

    Pause a Meta campaign, ad set or ad

    Stops delivery on one campaign, ad set or ad by setting its status to PAUSED. Spend stops; nothing is deleted, and the object can be resumed later with meta_resume_entity. Use when: the user has explicitly asked to stop something, and you have shown them what it is currently spending. Do not pause an ad set that is still in the learning phase on the strength of a few days of data — say so and let the user decide. Do not use this as a way to delete: pausing keeps the object, its history and its learning. Returns the status and effective status read back from Meta, which is how you confirm the pause actually applied — a campaign can report PAUSED while its parent is what really stopped delivery.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "entity_type": {
          "type": "string",
          "enum": [
            "campaign",
            "adset",
            "ad"
          ],
          "description": "What the id refers to: campaign, adset or ad."
        },
        "entity_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Id of the campaign, ad set or ad."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "entity_type",
        "entity_id"
      ]
    }
  • meta_resume_entitywrite1 task

    Resume a Meta campaign, ad set or ad

    Sets one campaign, ad set or ad back to ACTIVE so it can deliver again. Real money starts being spent as soon as Meta approves delivery. Use when: the user has reviewed something paused — often a campaign this server created — and wants it live. Do not resume an object without telling the user its budget first: resuming a campaign resumes its whole structure and the daily budget applies from that moment. Returns both status and effective_status. A resumed ad set whose campaign is still paused reports ACTIVE but will not deliver — check the effective status before telling the user it is live.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "entity_type": {
          "type": "string",
          "enum": [
            "campaign",
            "adset",
            "ad"
          ],
          "description": "What the id refers to: campaign, adset or ad."
        },
        "entity_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "Id of the campaign, ad set or ad."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "entity_type",
        "entity_id"
      ]
    }
  • meta_search_targetingread-onlyfree

    Look up Meta targeting ids

    Turns a plain-language audience description into the ids Meta's write endpoints require: interest ids, behaviour ids, and location keys for countries, regions, cities, postcodes and media markets. Use when: the user describes an audience in words ("women in Berlin interested in yoga") and before any campaign creation. meta_create_image_campaign only accepts ids, never free text. Do not use to check how an existing audience is performing (meta_get_adset_performance) or to list saved audiences (meta_list_custom_audiences). Returns the id or location key plus the estimated audience size where Meta provides one. Search one concept at a time; broad queries return loosely related suggestions. If several results look plausible, show the user the options with their sizes and let them choose. Do not pick one silently.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "search_type": {
          "type": "string",
          "enum": [
            "interest",
            "behavior",
            "location"
          ],
          "description": "interest = hobbies, topics, brands; behavior = purchase and device behaviours; location = places."
        },
        "query": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "description": "What to search for, e.g. \"yoga\", \"frequent travellers\", \"Berlin\"."
        },
        "location_types": {
          "description": "For search_type=location: which kinds of place to return. Defaults to country, region and city.",
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "country",
              "region",
              "city",
              "zip",
              "geo_market"
            ]
          }
        },
        "limit": {
          "description": "Maximum results (default 15).",
          "type": "integer",
          "minimum": 1,
          "maximum": 50
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "search_type",
        "query"
      ]
    }
  • meta_update_adset_budgetdestructive write1 task

    Change a Meta ad set budget

    Changes the daily or lifetime budget of one ad set. The preview shows the current and new amounts as decimals in the account currency and the percentage change, so the user approves a real number rather than a raw platform value. Use when: the user has decided to scale an ad set up or down and named the ad set and the amount. Do not use on an ad set whose campaign holds the budget — campaign budget optimisation means Meta manages ad set budgets and this call will be rejected. Change the campaign instead. Do not change the budget of an ad set that is still learning unless the user accepts that learning restarts: a large change resets what Meta has learned and delivery gets worse before it gets better. Returns the ad set read back from Meta after the change so the new budget is confirmed, not assumed. Amounts are decimals in the account currency. For currencies Meta treats as whole units (yen, won, forint and similar) the conversion is handled here — never send minor units.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "ad_set_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "The ad set to re-budget, from meta_list_ad_sets."
        },
        "daily_budget": {
          "description": "New daily budget, decimal in the account currency.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "lifetime_budget": {
          "description": "New lifetime budget, decimal in the account currency. The ad set must already have an end date.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "ad_set_id"
      ]
    }
  • meta_update_campaignwrite1 task

    Edit a Meta campaign

    Changes a campaign's name, status or lifetime spend cap. The spend cap is a hard ceiling on everything the campaign will ever spend, expressed as a decimal in the account currency. Use when: renaming for clarity, or putting a hard ceiling on a campaign the user wants to bound. Do not use to pause or resume — meta_pause_entity and meta_resume_entity exist so the risk of the change is stated correctly to the user. Do not set a spend cap below what the campaign has already spent: Meta stops delivery immediately and the campaign cannot be revived by lowering it further. Returns the campaign read back from Meta. At least one of name, status or spend_cap must be given.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[0-9]+$",
          "description": "The campaign to edit."
        },
        "name": {
          "description": "New campaign name.",
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "status": {
          "description": "New status. Prefer meta_pause_entity / meta_resume_entity, which explain the risk properly.",
          "type": "string",
          "enum": [
            "ACTIVE",
            "PAUSED"
          ]
        },
        "spend_cap": {
          "description": "Lifetime spend ceiling as a decimal in the account currency. Meta enforces a minimum of roughly 100 in most currencies.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • meta_validate_creative_urlread-onlyfree

    Check an image URL and ad copy before building an ad

    Fetches a public image URL and reports whether it is reachable, what type and size it is, and its pixel dimensions, then checks any ad copy against Meta's length guidance. Use when: the user supplies an image URL or ad text, always before meta_create_image_campaign. A URL that Meta cannot fetch fails the campaign halfway through creation, after the campaign and ad set already exist. Do not use for landing page quality or policy review — this checks that the file exists and fits the format, nothing about its content. Returns dimensions when the file is a PNG or JPEG, plus warnings for anything Meta is likely to reject or crop: too small, wrong aspect ratio, unsupported type, or copy that will be truncated in the feed. Costs nothing and calls no ad platform, so run it as often as needed.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "image_url": {
          "description": "Public HTTPS URL of the image the ad will use.",
          "type": "string",
          "format": "uri"
        },
        "primary_text": {
          "description": "The main ad copy, checked against the 125-character guidance.",
          "type": "string"
        },
        "headline": {
          "description": "Headline, checked against the 40-character guidance.",
          "type": "string"
        },
        "description": {
          "description": "Description line, checked against the 30-character guidance.",
          "type": "string"
        },
        "landing_page_url": {
          "description": "Destination URL, checked for reachability and HTTPS.",
          "type": "string",
          "format": "uri"
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }

ChatGPT Ads10

  • chatgpt_geo_lookupread-onlyfree

    Find ChatGPT Ads location ids

    Turns a place name into the location ids the platform targets by. "Berlin", "California", "Japan" go in; ids, canonical names and location types come out. Use when: the user names any place the ad should run in, always before chatgpt_launch_ad. The launch tool accepts ids only and refuses anything that looks like a name. Do not guess an id, reuse one from another ad platform, or pass a place name straight into a write — a wrong id spends real money in the wrong country and the platform will not warn you. Returns every match with its type and country code, so you can tell one Springfield from another. Types include country, region, city and dma (a US media market covering several cities, which is often what a metro name resolves to). If several matches look plausible, show them and ask the user which one they mean rather than taking the first. Costs nothing, so resolve every place the user mentions, one place per call.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "query": {
          "type": "string",
          "minLength": 1,
          "maxLength": 80,
          "description": "The place name to look up, as the user said it. One place per call."
        },
        "limit": {
          "description": "Maximum matches to return (default 10).",
          "type": "integer",
          "minimum": 1,
          "maximum": 100
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "query"
      ]
    }
  • chatgpt_get_accountread-onlyfree

    Show the connected ChatGPT Ads account

    Reads the advertiser account the stored key belongs to: id, name, website, currency, timezone, account status and the platform's review verdict on the account. This is the same call the key was verified with when the user connected it. Use when: starting work on this platform, confirming which account you are about to change, or checking whether a failing call is an access problem rather than a data problem. Run it before any write if you are not certain which account the key points at. Do not use it to see what is running — that is chatgpt_list_campaigns. Do not use it to test a key the user pasted into chat: keys are only ever stored through the Connections page and are never passed to a tool. Returns the account currency and timezone. Every budget and every spend figure on this platform is a decimal in that currency, and every reporting window is resolved in that timezone. If the account review status is not "approved", nothing will deliver no matter what is created — say so before building anything. Costs nothing, so run it whenever the answer would otherwise be a guess. If it fails with a reauth error the key was rotated or revoked and the user must paste a new one.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • chatgpt_get_performanceread-only1 task

    Read ChatGPT Ads performance

    Reports impressions, clicks, spend, conversions and the ratios derived from them (CTR, CPC, CPM, CPA, ROAS) for a window, broken down by campaign, ad group or ad — and compares every number with the equally long period immediately before it. Use when: the user asks how anything is doing, whether something is working, or what changed. Scope it with campaign_id, ad_group_id or ad_id; without any of them it reports the whole account. Do not use it to find out what exists — that is chatgpt_list_campaigns — and do not read a single day and call it a trend: this platform's daily numbers are noisy at small budgets, so prefer last_7_days or longer before recommending a change. Do not compare a partial day with a whole one. The "last N days" windows deliberately end yesterday for that reason. Returns spend as a decimal in the account currency and a percentage change per metric against the previous period. A dash in the change column means the previous period was zero, not that nothing changed. ROAS is only meaningful where the account reports attributed revenue; where it does not, it comes back empty rather than as zero. If the numbers are all zero, check chatgpt_list_ads for a review verdict and chatgpt_list_campaigns for a serving issue before concluding the ads are simply performing badly.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "level": {
          "description": "How to break the numbers down: account (one total), campaign, ad_group or ad. Defaults to campaign.",
          "type": "string",
          "enum": [
            "account",
            "campaign",
            "ad_group",
            "ad"
          ]
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "Only this campaign."
        },
        "ad_group_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "Only this ad group."
        },
        "ad_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "Only this ad."
        },
        "date_range": {
          "description": "Preset reporting window. The \"last N days\" windows end yesterday so no partial day is mixed in. Alternatively pass start_date and end_date. Never both.",
          "type": "string",
          "enum": [
            "today",
            "yesterday",
            "last_7_days",
            "last_14_days",
            "last_30_days",
            "this_month",
            "last_month"
          ]
        },
        "start_date": {
          "description": "First day of the reporting window, YYYY-MM-DD. Requires end_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of the reporting window, YYYY-MM-DD, inclusive. Requires start_date.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "compare_previous": {
          "description": "Compare with the equally long period before the window. On by default; costs no extra call.",
          "type": "boolean"
        },
        "limit": {
          "description": "Maximum rows in the breakdown (default 25, by spend).",
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • chatgpt_launch_adwrite8 tasks

    Launch a ChatGPT Ads chat card ad

    Builds a complete, paused campaign on ChatGPT Ads: campaign, ad group, image upload and one chat card ad. Nothing delivers and nothing spends until the user activates it with chatgpt_resume_campaign. Use when: the user has given a budget, a destination, ad copy and a square image, and has decided to launch. Resolve every place they named with chatgpt_geo_lookup first — this tool takes location ids and refuses names. Do not call it twice for the same brief. If a step fails, the error lists what already exists; finish or remove that rather than starting again, or you will create a second campaign spending a second budget. Do not invent copy, a budget, a destination or a location the user did not give. If any of those is missing, ask. The card limits are hard: the title must be 3–50 characters, the body at most 100, and the image must be square. All three are checked before anything is created, so a rejection here costs nothing. Returns the ids of the four objects created and reads all of them back so their paused state is confirmed rather than assumed. Budgets are decimals in the account currency.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "campaign_name": {
          "type": "string",
          "minLength": 3,
          "maxLength": 1000,
          "description": "Name shown in Ads Manager. Say what it sells and to whom."
        },
        "lifetime_budget": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Hard ceiling on everything this campaign will ever spend, as a decimal in the account currency (100 means one hundred, not 10000). Required by the platform."
        },
        "daily_budget": {
          "description": "Optional daily pacing limit, decimal in the account currency. Cannot exceed the lifetime ceiling.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "objective": {
          "description": "What the platform optimises for: reach, clicks or conversions. Defaults to clicks. Conversions also needs conversion_event_setting_id.",
          "type": "string",
          "enum": [
            "reach",
            "clicks",
            "conversions"
          ]
        },
        "conversion_event_setting_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "The conversion event to optimise for. Required when objective is conversions."
        },
        "geo_location_ids": {
          "description": "Location ids from chatgpt_geo_lookup. Ids only — a place name here is refused. Omit to let the platform choose where it runs.",
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        "ad_group_name": {
          "description": "Ad group name. Defaults to the campaign name with a suffix.",
          "type": "string",
          "minLength": 3,
          "maxLength": 1000
        },
        "context_hints": {
          "description": "Short free-text hints about the audience or context the ad suits. This platform has no keywords; these are the nearest thing.",
          "maxItems": 20,
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          }
        },
        "max_bid": {
          "description": "Fixed maximum bid as a decimal in the account currency. Leave it out for automatic bidding, which is the right default for a first launch.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "title": {
          "type": "string",
          "description": "Chat card headline, 3–50 characters. This is the line people read first."
        },
        "body": {
          "type": "string",
          "description": "Chat card body copy, at most 100 characters. Put the offer in the first half."
        },
        "target_url": {
          "type": "string",
          "format": "uri",
          "description": "Where a click goes. Must be https and reachable without a login."
        },
        "image_url": {
          "type": "string",
          "format": "uri",
          "description": "Public https URL of the card image. It must be square; the bytes are downloaded and checked here before anything is created."
        },
        "start_date": {
          "description": "When delivery may start, YYYY-MM-DD. Defaults to whenever the user activates it.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "end_date": {
          "description": "Last day of delivery, YYYY-MM-DD, inclusive.",
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "campaign_name",
        "lifetime_budget",
        "title",
        "body",
        "target_url",
        "image_url"
      ]
    }
  • chatgpt_list_ad_groupsread-only1 task

    List ChatGPT Ads ad groups

    Lists ad groups with status, bidding configuration (what the account is billed on, the strategy, and any fixed maximum bid as a decimal in the account currency), the free-text context hints that steer where the ads appear, and any serving issue. Use when: you need ad group ids, or want to know how an ad group bids before changing anything above it. Do not use for results — pair it with chatgpt_get_performance at ad-group level. Returns the bidding strategy, which is where "why is this not spending" often lives: an ad group with a fixed bid far below the market simply never wins. An ad group with no strategy and no maximum bid is on automatic bidding, which is the default this server creates. Note that geo and audience targeting are set on the **campaign** on this platform, not here — read chatgpt_list_campaigns for where an ad group is allowed to run. Pass campaign_id to scope the list.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "Only ad groups in this campaign."
        },
        "status": {
          "description": "Only objects in this state. Statuses are lowercase on this platform. Defaults to all except archived.",
          "type": "string",
          "enum": [
            "active",
            "paused",
            "archived",
            "all"
          ]
        },
        "limit": {
          "description": "Maximum rows to return (default 100).",
          "type": "integer",
          "minimum": 1,
          "maximum": 500
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • chatgpt_list_adsread-only1 task

    List ChatGPT Ads ads

    Lists individual ads with their status, the chat card behind each one (title, body, destination) and — most usefully — the platform's review verdict and reason. Use when: you need ad ids, or the user asks what creative is live, or an ad is not delivering and you need to know whether review is the reason. Do not use to judge creative quality — get the numbers from chatgpt_get_performance first, then look at the copy. Returns review_status: an ad that is in_review is not delivering yet, and one that is rejected never will until the copy or destination changes. The rejection reason is the single most useful field on this platform, so quote it to the user verbatim rather than paraphrasing. Pass ad_group_id to scope the list; without it you get every ad in the account.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "ad_group_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "Only ads in this ad group."
        },
        "status": {
          "description": "Only objects in this state. Statuses are lowercase on this platform. Defaults to all except archived.",
          "type": "string",
          "enum": [
            "active",
            "paused",
            "archived",
            "all"
          ]
        },
        "limit": {
          "description": "Maximum rows to return (default 100).",
          "type": "integer",
          "minimum": 1,
          "maximum": 500
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • chatgpt_list_campaignsread-only1 task

    List ChatGPT Ads campaigns

    Lists the campaigns in the advertiser account with status, objective, what the platform bids towards, the lifetime and daily spend limits as decimals in the account currency, the schedule, where they are allowed to run, and any serving issue the platform reports. Use when: you need campaign ids before reading performance or changing anything, or the user asks what is running. Do not use to compare results — that is chatgpt_get_performance; this returns configuration only, with no spend or clicks in it. Returns one row per campaign plus the id every other tool needs. Serving issues are the fastest explanation for a campaign that exists but delivers nothing: an exhausted budget, a missing payment method or an unapproved account will all show up here rather than in the numbers. Archived campaigns are hidden unless you ask for them, because archiving is irreversible on this platform and an archived campaign is never the answer to "what is running".

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "status": {
          "description": "Only objects in this state. Statuses are lowercase on this platform. Defaults to all except archived.",
          "type": "string",
          "enum": [
            "active",
            "paused",
            "archived",
            "all"
          ]
        },
        "name": {
          "description": "Only campaigns whose name matches this text, as the platform matches it.",
          "type": "string"
        },
        "limit": {
          "description": "Maximum rows to return (default 100).",
          "type": "integer",
          "minimum": 1,
          "maximum": 500
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      }
    }
  • chatgpt_pause_campaigndestructive write1 task

    Pause a ChatGPT Ads campaign

    Stops delivery on one campaign by setting it to paused. Spend stops; nothing is deleted, every ad group and ad underneath keeps its configuration and history, and the campaign can be started again with chatgpt_resume_campaign. Use when: the user has explicitly asked to stop something, and you have shown them what it is currently spending. Do not pause on the strength of a day or two of data — this platform's daily numbers are noisy at small budgets. Show the user last_7_days from chatgpt_get_performance and let them decide. Do not use this as a way to delete. Pausing is reversible; archiving is not, and no tool here archives anything. Returns the campaign read back from the platform, which is how you confirm the pause actually applied rather than reporting an intention as a fact.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "The campaign to act on, from chatgpt_list_campaigns."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • chatgpt_resume_campaignwrite1 task

    Resume a ChatGPT Ads campaign

    Sets one campaign back to active so it can deliver again. Real money starts being spent as soon as the platform approves delivery. Use when: the user has reviewed something paused — often a campaign this server created — and wants it live. Do not resume without telling the user the spend limits first: resuming restarts the whole structure underneath, and the daily limit applies from that moment. Do not assume "active" means "delivering". Check the read-back: an unapproved account, an unapproved ad or a serving issue will keep an active campaign at zero, and the serving issues in the read-back say which. Returns the campaign read back from the platform, including its spend limits and any serving issue.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "The campaign to act on, from chatgpt_list_campaigns."
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "campaign_id"
      ]
    }
  • chatgpt_update_campaignwrite1 task

    Edit a ChatGPT Ads campaign

    Changes a campaign's name, status or spend limits. Both limits are decimals in the account currency: the lifetime limit is a hard ceiling on everything the campaign will ever spend, the daily limit paces it. Use when: renaming for clarity, or the user has decided to scale a campaign up or down and named the amount. Do not use it to pause or resume — chatgpt_pause_campaign and chatgpt_resume_campaign exist so the risk of that change is stated correctly to the user before they approve it. Do not lower the lifetime ceiling below what the campaign has already spent: delivery stops at once and lowering it further cannot revive it. Check spend with chatgpt_get_performance first. Returns the campaign read back from the platform after the change, so the new values are confirmed rather than assumed. At least one of name, status, lifetime_budget or daily_budget must be given. If the user says "increase the budget" without a number, ask which limit and how much. Never pick an amount for them.

    Input schema
    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "ad_account_id": {
          "description": "ChatGPT Ads advertiser account id. One advertiser key belongs to one account, so this is only needed when the user has connected more than one key. Omit it to use the primary account.",
          "type": "string"
        },
        "campaign_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "description": "The campaign to edit."
        },
        "name": {
          "description": "New campaign name.",
          "type": "string",
          "minLength": 3,
          "maxLength": 1000
        },
        "status": {
          "description": "New status. Prefer chatgpt_pause_campaign / chatgpt_resume_campaign, which explain the risk properly.",
          "type": "string",
          "enum": [
            "active",
            "paused"
          ]
        },
        "lifetime_budget": {
          "description": "Hard ceiling on total spend, decimal in the account currency (25 means twenty-five, not 2500).",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "daily_budget": {
          "description": "Daily pacing limit, decimal in the account currency. Cannot exceed the lifetime ceiling.",
          "type": "number",
          "exclusiveMinimum": 0
        },
        "idempotency_key": {
          "description": "Optional caller-supplied key; identical keys never execute twice.",
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "raw_data": {
          "description": "Return compact JSON only (no markdown). Use when you will compute on the result.",
          "type": "boolean"
        }
      },
      "required": [
        "campaign_id"
      ]
    }