smithery.ai

adcp-media-buy

Execute AdCP Media Buy Protocol operations with sales agents - discover advertising products, create and manage campaigns, sync creatives, and track delivery. Use when users want to buy advertising, create media buys, interact with ad sales agents, or test advertising APIs.

First seen Apr 9, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 24,779 B
  • docs SUMMARY.md 296 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

AdCP Media Buy Protocol

This skill enables you to execute the AdCP Media Buy Protocol with sales agents. Use the standard MCP tools (getproducts, createmediabuy, synccreatives, etc.) exposed by the connected agent.

Buyer-side basics — idempotency replay, oneOf variants, async status:'submitted' polling, error recovery from adcp_error.issues[] — live in skills/call-adcp-agent/SKILL.md. This skill covers per-task semantics only.

Overview

3.2 preview: Targeting-aware discovery fields are available only when the
seller serves AdCP 3.2+ and the installed SDK exposes the 3.2 schema. Check
getadcpcapabilities.adcp.supported_versions, pin the selected release in
adcp_version, and validate the echoed served release before sending them.
A missing release-precision declaration, a 3.1-or-earlier result, or a
major-only declaration is not evidence of support: omit the 3.2 fields and use
legacy targeting filters or explicit brief prose. Do not probe by sending
unknown fields because a legacy open schema may accept and ignore them. The public
training agent will implement this flow after the 3.2 beta SDK release; until
then use its legacy brief exercise and do not treat ignored unknown fields as
acceptance.

The Media Buy Protocol provides these common standardized tasks:

Task Purpose Response Time
list_products Read matching offers without seller curation ~1-5s
request_proposals Request seller-authored draft plans ~60s or async
refine_proposals Revise drafts or finalize unchanged terms into inventory holds ~60s or async
decline_proposals Record terminal buyer disposition ~1-5s
accept_proposal Accept a finalized proposal into a MediaBuy Minutes-Days
get_products Use the 3.x compatibility facade for discovery and proposals ~60s
getadcpcapabilities See agent capabilities, supported protocols, and publisher properties ~1s
createmediabuy Create direct buys or use the 3.x proposal adapter Minutes-Days
updatemediabuy Modify campaigns Minutes-Days
getmediabuys Retrieve campaign state and status ~1-5s
sync_creatives Upload creative assets Minutes-Days
sync_catalogs Sync product feeds and catalogs Minutes-Days
list_creatives Query creative library ~1s
getmediabuy_delivery Get performance data ~60s
provideperformancefeedback Share outcomes with publishers ~1-5s

Typical Workflow

  1. Discover products: use listproducts, or requestproposals with a brief
  2. Verify the offer: inspect formats, pricing, forecast, overlaysupport, and any targetingresolution
  3. Negotiate and hold: revise a draft as needed, then finalize it without changing terms
  4. Accept or decline: call acceptproposal for the held snapshot or declineproposals when the buyer stops pursuing it
  5. Upload creatives: use sync_creatives to add creative assets
  6. Monitor delivery: use getmediabuy_delivery to track performance

Canonical formats (AdCP 3.2)

Products carry format_options[]: a list of ProductFormatDeclaration entries describing the creative shapes the product accepts. Each declaration carries:

  • formatkind — one of the 15 canonicals: image, html5, displaytag, imagecarousel, videohosted, videovast, audiohosted, audiovast, audiodaast, sponsoredplacement, nativeinfeed, responsivecreative, agentplacement, sellerrenderedstatefuldisplay, or coordinatedplacements; use custom only with formatshape and format_schema
  • params — per-canonical parameters narrowing the format (dimensions, durations, codecs, char limits, CTA enums)
  • Optional formatoptionid — disambiguates product options and identifies publisher-catalog declarations when paired with publisher_domain
  • Optional v1formatref: [{agent_url, id}] — array linking this v2 declaration to one or more v1 named formats (for dual emission during the v1↔v2 migration). Multi-size declarations should carry one ref per size
  • Optional seller_preference: "preferred" | "accepted" | "discouraged" — soft routing hint when a multi-format product has several options at the same price

Multi-format products. A flexible publisher slot is one product with N formatoptions entries — e.g., Pinnacle Media's homepage accepts image OR html5 OR displaytag at multiple sizes via three format_options, one per type. Buyer picks the creative type they ship.

Size flexibility. Display canonicals (image / html5 / displaytag) declare size in one of three modes: fixed (width+height), multi-size (sizes: [{w,h}] — mirrors OpenRTB banner.format[]), or responsive (minwidth/maxwidth/minheight/max_height). Modes are mutually exclusive.

Discovering publisher catalogs. Call GET https://agenticadvertising.org/api/registry/publisher?domain=<publisherdomain> for publisher-origin → AgenticAdvertising.org community-catalog → fail-closed resolution and provenance. Add &include=placements for provenance-labeled placement summaries with resolved canonical format options. The lookup's top-level formats[] remains a lossy display summary; fetch the returned raw registry or hosting URL when you need custom schema fields or other omitted declaration fields. Do not infer publisher authority from a seller's product catalog. Seller-specific deliverability comes from that seller's Product.formatoptions[].

Conversion tracking lives elsewhere. Pixel-firing, conversion events, and attribution belong on synceventsources / eventlog (campaign-scoped), NOT on creative format declarations. Sending pixelid in platform_extensions on a format is a category error.

Error codes specific to canonical formats. FORMATPROJECTIONFAILED, FORMATDECLARATIONDIVERGENT, FORMATDECLARATIONV1AMBIGUOUS, FORMATCAPABILITYUNRESOLVED, FORMATDECLARATIONV1LOSSYMULTISIZE — all non-fatal advisories surfaced via the response errors[] array. See static/schemas/source/enums/error-code.json for full recovery semantics.

See docs/creative/canonical-formats.mdx for the full vocabulary, narrowing rules, and worked examples.


Task Reference

get_products

Discover buyable product configurations. Choose each request surface by what it means:

  • brief: goals, context, semantic audience intent, preferences, and

requirements without a structured representation.

  • filters: hard offer filters such as metadata, dates, budget, availability,

commercial fit, and reporting support. They decide which products may be returned and apply in brief, wholesale, and refine.

  • targeting_overlay: exact delivery constraints known now. Use this for

countries, ages, placements, properties, collections, and other typed targeting so availability, price, and forecast already reflect them.

  • requiredoverlaysupport: targeting dimensions whose values will be chosen

independently on packages later. This requests capability, not one product per value.

Prefer a structured field whenever one exists. It uses fewer tokens, is applied by code, and avoids lossy inference. Explicit hard targeting written only in a brief is still binding; when a seller extracts a structured predicate from prose that materially affects eligibility, pricing, or forecasting, require one response-level confirmation in GetProductsResponse.targetingresolution.brieftargeting.

Request:

{
  "buying_mode": "brief",
  "brief": "Premium video for a developer-tool launch; prioritize engineering and open-source contexts",
  "brand": {
    "domain": "example.com"
  },
  "filters": {
    "channels": ["olv", "ctv"],
    "delivery_type": "guaranteed",
    "pricing_currencies": ["USD"]
  },
  "targeting_overlay": {
    "geo_countries": ["US"],
    "demographics": {
      "age": { "min": 18, "max": 44, "include_unknown": false }
    }
  },
  "required_overlay_support": {
    "geo_metros": { "systems": ["nielsen_dma"] }
  }
}

Key fields:

  • buying_mode (string): "brief", "wholesale", or "refine"
  • brief (string): Natural-language curation input; hard statements remain requirements
  • brand (object): Brand identity - { "domain": "acmecorp.com" }
  • filters (object, optional): Hard offer filters that decide which products may be returned
  • targeting_overlay (object, optional): Concrete targeting applied during discovery and carried into purchase
  • requiredoverlaysupport (object, optional): Dimensions the product must allow packages to select later

Response contains:

  • products: Array of matching products with productid, name, description, pricingoptions
  • Each product includes canonical format_options[] and targeting capabilities
  • overlay_support: binding product-scoped dimensions selectable later
  • targeting_resolution.modifications: sparse differences from the requested structured overlay; selecting the product accepts them
  • Response targetingresolution.brieftargeting: the seller's single structured interpretation of hard targeting inferred from prose
  • No targeting_resolution means exact acceptance of the structured overlay only; it does not prove how prose was interpreted

Treat productid as the opaque identity of this configured offer. Keep it within the same discovery/refinement context and purchase it before expiresat; do not assume it is a permanent cross-session ID.


createmediabuy

Create an advertising campaign from selected products.

Request:

{
  "brand": {
    "domain": "acme.com"
  },
  "packages": [
    {
      "product_id": "prod_configured_us_18_44",
      "pricing_option_id": "cpm-standard",
      "budget": 10000,
      "targeting_overlay": {
        "geo_metros": [
          { "system": "nielsen_dma", "values": ["501"] }
        ]
      }
    }
  ],
  "start_time": "asap",
  "end_time": "2024-03-31T23:59:59Z"
}

Key fields:

  • brand (object, required): Brand identity - { "domain": "acmecorp.com" }
  • packages (array, required): Products to purchase, each with:

- productid: From getproducts response - pricingoptionid: From product's pricingoptions - budget: Amount in dollars - bidprice: Required for auction pricing - targetingoverlay: Package targeting permitted by the selected product's overlaysupport; it composes with targeting already bound during discovery and must not silently broaden it - creative_ids or creatives: Creative assignments

  • start_time (string, required): "asap" or an ISO 8601 datetime (e.g., "2024-06-01T00:00:00Z")
  • end_time (string, required): ISO 8601 datetime

Response contains:

  • mediabuyid: The created campaign identifier
  • status: Current lifecycle state — pendingcreatives (no creatives assigned yet), pendingstart (waiting for flight date), or active (serving immediately)
  • packages: Created packages with their IDs

updatemediabuy

Modify an existing campaign.

Request:

{
  "idempotency_key": "update-mb-abc123-2024-04-pause",
  "media_buy_id": "mb_abc123",
  "updates": {
    "budget_change": 5000,
    "end_time": "2024-04-30T23:59:59Z",
    "status": "paused"
  }
}

Key fields:

  • mediabuyid (string, required): The campaign to update
  • updates (object): Changes to apply - budgetchange, endtime, status, targeting, etc.

sync_catalogs

Sync product catalogs, store locations, job postings, and other structured feeds to a seller account. Supports inline items or external feed URLs. When called without catalogs, returns existing catalogs (discovery mode).

Request:

{
  "account": {
    "account_id": "acct_123"
  },
  "catalogs": [
    {
      "catalog_id": "winter-collection",
      "name": "Winter 2025 Collection",
      "type": "product",
      "items": [
        {
          "id": "sku-001",
          "name": "Wool Coat",
          "price": 299.99,
          "currency": "USD"
        }
      ]
    }
  ]
}

Key fields:

  • account (object, required): Account that owns the catalogs — { account_id }
  • catalogs (array, optional): Catalog objects to sync. Omit for discovery mode.

- type (string, required): offering, product, inventory, store, promotion, hotel, flight, job, vehicle, realestate, education, destination, app - items (array): Inline catalog data (mutually exclusive with url) - url (string): External feed URL (mutually exclusive with items) - feedformat (string): googlemerchantcenter, facebookcatalog, shopify, linkedinjobs, custom

  • delete_missing (boolean, optional): Remove catalogs not in this sync (use with caution)
  • dry_run (boolean, optional): Preview changes without applying

sync_creatives

Upload and manage creative assets.

Request:

{
  "creatives": [
    {
      "creative_id": "hero_video_30s",
      "name": "Brand Hero Video",
      "format_kind": "video_hosted",
      "format_option_ref": {
        "scope": "product",
        "format_option_id": "video_30s"
      },
      "assets": {
        "video": {
          "url": "https://cdn.example.com/hero.mp4",
          "width": 1920,
          "height": 1080,
          "duration_ms": 30000
        }
      }
    }
  ],
  "assignments": {
    "hero_video_30s": ["pkg_001", "pkg_002"]
  }
}

Key fields:

  • creatives (array, required): Creative assets to sync

- creativeid: Your unique identifier - formatkind: Canonical format accepted by the selected product - formatoptionref: Product or publisher option when format_kind alone is ambiguous - assets: Asset content (video, image, html, etc.)

  • assignments (object, optional): Map creative_id to package IDs
  • dry_run (boolean): Preview changes without applying
  • delete_missing (boolean): Archive creatives not in this sync

list_creatives

Query the creative library with filtering.

Request:

{
  "filters": {
    "status": ["active"]
  },
  "limit": 20
}

getmediabuys

Retrieve media buy state: status, valid_actions, creative approvals, pending formats, and optional delivery snapshots or revision history.

Request:

{
  "media_buy_ids": ["mb_abc123"],
  "include_snapshot": true,
  "include_history": 5
}

Key fields:

  • mediabuyids (array, optional): Specific media buy IDs to retrieve
  • account (object, optional): Filter to a specific account
  • statusfilter (string or array, optional): Filter by status — pendingcreatives, pending_start, active, paused, completed, rejected, canceled. Defaults to ["active"] when no IDs provided.
  • include_snapshot (boolean, optional): Include near-real-time delivery snapshots per package
  • include_history (integer, optional): Include the last N revision history entries per media buy

Response contains:

  • mediabuys: Array with mediabuyid, status, validactions, packages, creative approval state
  • Optional snapshot per package (impressions, spend, pacing)
  • Optional history entries (revision, timestamp, actor, action, summary)

Relationship-scoped indicators

Before querying indicators, read getadcpcapabilities.mediabuy.supportedindicator_types. Indicators may appear at three levels:

  • buy: getmediabuys.mediabuys[] (budgetconstrained)
  • package: packages[] (creativediversitylow, audiencesaturation, inventoryshortfallforecast, pacingrisk, budget_constrained)
  • assignment: creativeapprovals[] and the matching listcreatives.assignments.assignedpackages[] (creativefatigue, creativequalityopportunity)

indicators omitted means unknown. A present array requires indicatortypesevaluated and indicatorsasof; empty means clear only for those named types and coverage. scope narrows an assertion; indicatorsevaluatedscope declares partial publisher/placement coverage. Creative-library sellers advertise listcreatives in relationshipnotifications.projectiontasks; those sellers include mediabuyid, approval state, and any approvalscopes on every reverse assignment row. Every seller repairs through getmediabuys.

For portfolio discovery, call listcreatives with filters.indicatortypes, includeassignments: true, assignmentprojection: "matching", a bounded assignmentlimit, fields: ["creativeid", "assignments"], and cursor pagination. The seller still returns the released required creative envelope; fields limits optional payload. Check assignmentstruncated; use getmediabuys for complete repair. Key evaluated state by seller + mediabuyid + packageid + creative_id + type + normalized placement scope.

Never clear from filtered disappearance or failure. Reread directly without indicator_types; clear only a named evaluated type in covered scope from a strictly newer snapshot. Equal-timestamp conflicts are no-ops. Direct assignment deletion retires its keys.

Indicator polling through getmediabuys does not require webhooks. Sellers may additionally declare indicators.changed and may independently declare creative.assignmentchanged; creative-library sellers may advertise the bounded listcreatives reverse projection. Subscriptions are prospective, so establish a complete getmediabuys baseline after activation by enumerating known IDs or requesting every media-buy status and exhausting pagination, without indicatortypes. Verify, dedupe, and reread getmediabuys; webhook payloads are invalidations, not state. Timestamp-only reevaluation does not fire, while material in-place creative updates invalidate prior assignment evaluations. Root warnings[] on completed buyproducts, acceptproposal, or controlmediabuy calls are immediate receipts; createmediabuy and updatemedia_buy facades mirror them. Inventory and pacing warning codes require the matching advertised durable indicator type.


provideperformancefeedback

Submit one compact optimizer-ready assertion. Measurement agents call a buyer-controlled orchestrator gateway; the orchestrator authenticates and normalizes provider output, then calls each seller under the buyer's identity. Measurement providers do not receive seller-account grants.

Request:

{
  "idempotency_key": "feedback-mb-abc123-2025-01-final",
  "media_buy_id": "mb_abc123",
  "measurement_period": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-31T23:59:59Z"
  },
  "performance_index": 1.2,
  "baseline": "campaign_target",
  "metric": {
    "scope": "standard",
    "metric_id": "conversions"
  },
  "producer": { "domain": "pinnacle-measurement.example" },
  "methodology": "deterministic_attribution",
  "final": true
}

Key fields:

  • idempotency_key (string, required): Stable key for this logical assertion; retries reuse the same key and payload
  • mediabuyid (string, required): Publisher's media buy identifier
  • measurement_period (object, required): Time period with start and end (ISO 8601)
  • performance_index (number, required): Normalized score — 1.0 equals baseline, lower underperforms, higher outperforms. Use observed/baseline for higher-is-better ratios and baseline/observed for lower-is-better ratios such as CPA.
  • baseline (string, required for compact-contract producers): campaigntarget, controlgroup, sellerhistory, buyerportfolio, market_benchmark, or other
  • package_id (string, optional): Specific package for package-level feedback
  • creative_id (string, optional): Specific creative for creative-level feedback
  • metric (object, optional): Standard/vendor metric identity; preferred over deprecated metric_type
  • producer (BrandRef, conditionally required): Measurement provider that produced the analysis; required when methodology or methodology_version is present. The orchestrator verifies it against provider identity before preserving it on seller submissions
  • methodology, methodology_version (string, optional): Provider-scoped open identifiers
  • study_ref (string, optional): Opaque correlation reference, never an experiment-execution instruction
  • evidence / evidence_ref (optional): Small inline summary and provider-hosted detail
  • final, asof, supersedesfeedback_id (optional): Maturation and immutable revision fields

Sellers declaring mediabuy.performancefeedback also list measurement.core in top-level experimentalfeatures and return feedbackid. When reportsapplicationstatus is true, inspect applicationstatus: accepted is not an application claim; applied means the signal entered optimizer inputs; notapplied includes a reason. Do not confuse this with the response envelope's task status.

Do not send raw measurement datasets through this task or through reportusage. In the first gateway tier the provider reads delivery through the orchestrator's getmediabuydelivery task and returns only the compact decision signal through provideperformancefeedback.


getmediabuy_delivery

Retrieve performance metrics for a campaign.

Request:

{
  "media_buy_id": "mb_abc123",
  "granularity": "daily",
  "date_range": {
    "start": "2024-01-01",
    "end": "2024-01-31"
  }
}

Response contains:

  • delivery: Aggregated metrics (impressions, spend, clicks, etc.)
  • by_package: Breakdown by package
  • timeseries: Data points over time if granularity specified

Key Concepts

Brand identity

Brand context is provided by domain reference:

{
  "brand": {
    "domain": "acmecorp.com"
  }
}

The agent resolves the domain to retrieve the brand's identity (name, colors, guidelines, etc.) from its brand.json file.

Canonical format options

Products declare their closed accepted set directly:

{
  "format_option_id": "display_image_300x250",
  "format_kind": "image",
  "params": { "width": 300, "height": 250 }
}

Buyers select the option with formatoptionrefs[] on the package and submit a manifest using formatkind plus formatoption_ref. Compound named format IDs are deprecated in 3.2.

Pricing Options

Products include pricing_options array. Each option has:

  • pricingoptionid: Use this in createmediabuy
  • pricing_model: "cpm", "cpm-auction", "flat-fee", etc.
  • price: Base price (for fixed pricing)
  • floor: Minimum bid (for auction)

For auction pricing, include bid_price in your package.

Asynchronous Operations

Operations like createmediabuy and sync_creatives may require human approval. The response includes:

  • status: "pending" - Operation awaiting approval
  • task_id - For tracking async progress

Poll or use webhooks to check completion status.


Error Handling

Common error patterns:

  • 400 Bad Request: Invalid parameters - check required fields
  • 401 Unauthorized: Invalid or missing authentication token
  • 404 Not Found: Invalid productid, mediabuyid, or creativeid
  • 422 Validation Error: Schema validation failure - check field types

Error responses include:

{
  "errors": [
    {
      "code": "VALIDATION_ERROR",
      "message": "budget must be greater than 0",
      "field": "packages[0].budget"
    }
  ]
}

Testing Mode

Use sandbox mode for testing without real transactions. Sandbox is account-level — once a request references a sandbox account, the entire request is treated as sandbox with no real platform calls or spend.

Check whether the agent supports sandbox via getadcpcapabilities:

{
  "account": {
    "sandbox": true
  }
}

To enter sandbox mode, set sandbox: true on the account reference:

{
  "account": {
    "brand": { "domain": "acme-corp.com" },
    "operator": "acme-corp.com",
    "sandbox": true
  }
}

Some sync tasks (synccreatives, synccatalogs) also support a dryrun parameter that previews changes without applying them. This is orthogonal to sandbox — you can use dryrun in both sandbox and production accounts.

See Sandbox mode for full details.