diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 4971cd4..7933bcd 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "realize-ads-api", - "version": "0.1.0", + "version": "0.2.0", "description": "Query Taboola Realize campaigns and pull performance reports through natural language — powered by the Realize remote MCP.", "author": { "name": "Taboola" diff --git a/CHANGELOG.md b/CHANGELOG.md index d196076..e837963 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,22 @@ All notable changes to this plugin will be documented here. Format loosely follo ## [Unreleased] +## [0.2.0] — 2026-05-13 + ### Added +- New `discovery` skill — read-only lookups for targeting / audience / publisher / conversion / time-zone / CTA-type catalogs. Wraps the upstream tools `search_geos`, `search_techno`, `search_audiences`, `search_lookalike_audiences`, `search_contextual_segments`, `search_publishers`, `search_conversion_rules`, `list_time_zones`, `list_cta_types`. - New `optimize-campaign` skill — data-driven diagnosis and recommendation loop grounded in Taboola's [official performance optimization guide](https://www.taboola.com/help/en/articles/3878108-how-to-improve-campaign-performance). Covers the 500–1000 click threshold, $50/day minimum spend rule, metric-combination prescription rules (CTR × CVR × CPA), and concrete UI-action recommendations with exact console paths. +- Agent Tool Reference now lists 18 read tools (up from 9), grouped: Accounts, Campaigns, Items, Discovery (targeting / audiences / publishers / conversion), Resources, Reports. +- `tests/test-scenarios.md` — five new scenarios (12–16) covering `search_audiences`, `search_geos` (DMA by country), `search_publishers`, `list_time_zones`, `list_cta_types`. ### Changed +- **Tool renames** to match upstream realize-mcp: `get_all_campaigns` → `list_campaigns`, `get_campaign_items` → `list_items`, `get_campaign_item` → `get_item`. Updated across the agent, the `campaigns` / `optimize-campaign` / `create-campaign` skills, and the test scenarios. - `create-campaign` skill rewritten with the exact setup flow from Taboola's [official setup guide](https://www.taboola.com/help/en/articles/10473049-setting-up-a-new-campaign): correct navigation (`Campaigns → +New → Campaign`), 5-value Marketing Objective enum, 3-value Bid Strategy enum with budget minimums (10× CPA for Maximize Conversions; 5× daily / 150× monthly for Enhanced CPC and Fixed Bid), 100–200 clicks/day rule for non-conversion campaigns, 3–10 ads per campaign recommendation, 7–10 day learning phase, 24–48 hour review cycle, and explicit guidance against narrowing targeting at launch. - Agent `realize-analyst`: added optimization-routing example and responsibility, and updated the create-campaign example to reflect the fuller setup flow. -- README: added `optimize-campaign` row to skills table and expanded natural-language examples with optimization and setup prompts. +- README: added `discovery` and `optimize-campaign` rows to the skills table, expanded natural-language examples with optimization, discovery, and setup prompts, and clarified the read-only scope. + +### Not in scope +- Upstream realize-mcp exposes write tools (campaign + native-item create/update). This plugin **intentionally does not enable writes** in this release — enabling them changes the plugin's safety posture and will be tracked in a separate issue/PR. Write-intent requests continue to route to the `create-campaign` UI walkthrough. ## [0.1.0] — 2026-04-24 diff --git a/CLAUDE.md b/CLAUDE.md index d529321..165337a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,14 +18,20 @@ This is a thin Claude Code plugin that wraps the [Realize remote MCP](https://gi └──────────┬──────────┘ │ ├──► accounts skill → search_accounts - ├──► campaigns skill → get_all_campaigns, get_campaign, ... + ├──► campaigns skill → list_campaigns, get_campaign, list_items, get_item + ├──► discovery skill → search_geos, search_techno, search_audiences, + │ search_lookalike_audiences, search_contextual_segments, + │ search_publishers, search_conversion_rules, + │ list_time_zones, list_cta_types ├──► reports skill → 4 report tools (CSV output) - └──► create-campaign skill → UI walkthrough (no MCP writes) + └──► create-campaign skill → UI walkthrough (no MCP writes enabled here) │ ▼ ┌────────────────────────────────────────┐ │ Realize MCP (https://mcp.realize.com) │ -│ OAuth 2.1, 11 tools at current rev │ +│ OAuth 2.1, 18 read tools wired here │ +│ (upstream also exposes 4 writes — │ +│ not enabled in this plugin revision) │ └────────────────────────────────────────┘ ``` diff --git a/README.md b/README.md index 10695f0..e35dd73 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Query Taboola **Realize** campaigns and pull performance reports through natural language, straight from Claude Code. Powered by the [Realize remote MCP](https://github.com/taboola/realize-mcp). -> **Scope today:** account discovery, campaign inspection, and performance reports. For actions the MCP does not yet expose as tools (e.g., creating or editing a campaign), the plugin walks you through the Realize console and then verifies the result via MCP. +> **Scope today:** account discovery, campaign + item inspection, targeting / audience / publisher / conversion-rule lookup, and performance reports — all read-only. This plugin does not enable write operations; for write-intent requests (creating, editing, pausing, duplicating), the plugin walks you through the Realize console and then verifies the result via MCP. ## Prerequisites @@ -22,7 +22,7 @@ Choose the path that matches how you consume Claude Code plugins: claude plugin i realize-ads-api ``` -That single command installs everything — the `realize-analyst` agent, the four skills, and the Realize MCP wiring. On the first tool call, Claude Code opens a browser for Taboola SSO to complete OAuth 2.1; after that you're ready to run prompts like *"List my Realize accounts"*. +That single command installs everything — the `realize-analyst` agent, the skills, and the Realize MCP wiring. On the first tool call, Claude Code opens a browser for Taboola SSO to complete OAuth 2.1; after that you're ready to run prompts like *"List my Realize accounts"*. > Requires the plugin to be registered with a Claude Code plugin marketplace your CLI has access to. See [Claude Code plugin docs](https://code.claude.com/docs/en/plugins) for the marketplace configuration specific to your Taboola distribution. @@ -85,9 +85,10 @@ For self-hosted HTTP mode and full local deployment details, see the [realize-mc |---|---| | [`accounts`](skills/accounts/SKILL.md) | Find Realize accounts and capture the `account_id` every other tool needs | | [`campaigns`](skills/campaigns/SKILL.md) | List and inspect campaigns and their creatives | +| [`discovery`](skills/discovery/SKILL.md) | Look up targeting metadata, audiences, publishers, conversion rules, time zones, and CTA types — resolves opaque IDs before campaign work | | [`reports`](skills/reports/SKILL.md) | Pull the four Realize performance reports and interpret the CSV output | | [`optimize-campaign`](skills/optimize-campaign/SKILL.md) | Diagnose underperforming campaigns against Taboola's official playbook (500–1000 clicks per item, $50/day minimum, 7–10 day learning phase) and prescribe concrete UI actions | -| [`create-campaign`](skills/create-campaign/SKILL.md) | Walk through the Realize console setup flow (exact Marketing Objective enum, Bid Strategy × budget minimums, learning-phase defaults) for actions not yet exposed as MCP tools, plus MCP verification afterward | +| [`create-campaign`](skills/create-campaign/SKILL.md) | Walk through the Realize console setup flow (exact Marketing Objective enum, Bid Strategy × budget minimums, learning-phase defaults) for write-intent actions, plus MCP verification afterward | The plugin also ships one agent, [`realize-analyst`](agents/realize-analyst.md), which routes natural-language questions to the right skill/tool and summarizes results in prose. @@ -107,6 +108,13 @@ The plugin also ships one agent, [`realize-analyst`](agents/realize-analyst.md), "Which sites are wasting my spend this month?" "My CPA doubled over the last two weeks. Help me diagnose." +# discovery (look up IDs / catalogs) +"What audiences are available for this account?" +"List all DMAs in the US." +"Show me publishers matching 'news' on this account." +"What time zones does Realize support?" +"What CTA button types exist for native items?" + # setup (UI walkthrough) "Create a new Online Purchases campaign with a $25 CPA target." "Walk me through launching a Leads campaign in the UK." diff --git a/agents/realize-analyst.md b/agents/realize-analyst.md index 7957f24..e41f211 100644 --- a/agents/realize-analyst.md +++ b/agents/realize-analyst.md @@ -14,7 +14,7 @@ You are a senior performance analyst for Taboola's **Realize** advertising platf User: "Show me my active campaigns." -You: Call `search_accounts` to resolve the user's account_id, confirm the selection if multiple match, then call `get_all_campaigns` and summarize status, spend, and count. +You: Call `search_accounts` to resolve the user's account_id, confirm the selection if multiple match, then call `list_campaigns` and summarize status, spend, and count. @@ -41,7 +41,7 @@ You: Check your Tool Reference — if no MCP tool currently exists for campaign 1. **Enforce the account-first workflow.** Every tool except `search_accounts` requires an `account_id`. Always resolve it first — do not accept a raw numeric ID typed by the user as the `account_id`. The returned `account_id` is an **opaque string** supplied by `search_accounts` (e.g., `advertiser_12345_prod`). Pass it through verbatim — do not reformat, re-case, or coerce it. -2. **Route intent to the right tool.** Map natural-language questions to the 11 MCP tools (see Tool Reference below). Prefer the narrowest tool that answers the question. +2. **Route intent to the right tool.** Map natural-language questions to the 18 MCP tools (see Tool Reference below). Prefer the narrowest tool that answers the question. For questions about what targeting / audience / publisher / conversion-rule IDs exist, route to the `discovery` skill. 3. **Propagate account_id through multi-step flows.** Cache it for the session; do not re-query unless the user switches accounts. @@ -57,16 +57,35 @@ You: Check your Tool Reference — if no MCP tool currently exists for campaign ## Tool Reference -All tools are exposed by the `realize-mcp` server as `mcp__realize-mcp__`. +All tools are exposed by the `realize-mcp` server as `mcp__realize-mcp__`. 18 read tools available over HTTP transport. ### Accounts - **`search_accounts(query, page=1, page_size=10)`** — Search accounts. `query` can be a numeric ID (routed server-side to an `id` lookup), free text (routed to `search_text`), or `"*"` to list all. `page_size` hard-capped at 10. Returns an opaque `account_id` string (e.g., `advertiser_12345_prod`) needed by every other tool. **Always call this first.** Empty/whitespace `query` raises `ToolInputError`. ### Campaigns -- **`get_all_campaigns(account_id)`** — List all campaigns for an account. **No pagination** — returns the full list in one call. +- **`list_campaigns(account_id)`** — List all campaigns for an account. **No pagination** — returns the full list in one call. - **`get_campaign(account_id, campaign_id)`** — Get a specific campaign's details. Both params required. -- **`get_campaign_items(account_id, campaign_id)`** — List all creatives/items for a campaign. **No pagination.** -- **`get_campaign_item(account_id, campaign_id, item_id)`** — Get a specific item's details. All three params required. + +### Items +- **`list_items(account_id, campaign_id)`** — List all creatives/items for a campaign. **No pagination.** +- **`get_item(account_id, campaign_id, item_id)`** — Get a specific item's details. All three params required. + +### Discovery — targeting metadata +- **`search_geos(dimension, country_code?)`** — Look up geo IDs. `dimension` ∈ {`countries`, `regions`, `dma`, `cities`, `postal_codes`}. `country_code` (ISO-2) is **required** when `dimension` is anything other than `countries`. Returns `{dimension, values: [{code, name}, ...]}`. +- **`search_techno(dimension, os_family?)`** — Look up OS / browser IDs. `dimension` ∈ {`operating_system_versions`, `browsers`}. `os_family` is **required** when `dimension=operating_system_versions`. + +### Discovery — audiences +- **`search_audiences(account_id, country_codes?, country_targeting_type?)`** — List Marketplace + My Audiences. `country_codes` is comma-separated ISO-2. `country_targeting_type` ∈ {`ALL`, `INCLUDE`, `EXCLUDE`}. +- **`search_lookalike_audiences(account_id, country_code?)`** — List lookalike audience rules. +- **`search_contextual_segments(account_id, country_codes?, country_targeting_type?)`** — List contextual segments. + +### Discovery — publishers and conversion +- **`search_publishers(account_id, query, publisher_ids?, page?, page_size?)`** — Search publishers. Pass `query="*"` to list all. `page_size` hard-capped at 50, default 10. Optional `publisher_ids` is an array of int IDs to look up directly. +- **`search_conversion_rules(account_id)`** — List configured conversion rules for the account. + +### Resources +- **`list_time_zones()`** — Return all valid IANA time zone names (e.g., `America/New_York`). No params. +- **`list_cta_types()`** — Return all valid `cta_type` enum values for native items. No params. ### Reports (CSV output) All report tools require `account_id`, `start_date`, `end_date` (ISO `YYYY-MM-DD`). `page` defaults to 1, `page_size` to 20, hard-capped at 100. @@ -77,7 +96,10 @@ All report tools require `account_id`, `start_date`, `end_date` (ISO `YYYY-MM-DD - **`get_campaign_site_day_breakdown_report`** — Per-site, per-day breakdown. Supports sort and `filters` (same shape as `get_campaign_breakdown_report`). ### Auth (stdio mode only — not available via remote) -- `get_auth_token`, `get_token_details` — Excluded from `streamable-http` transport. OAuth is handled automatically by the remote transport; you do not need these when the plugin is installed with the default remote wiring. +- `get_auth_token`, `get_token_details` — Excluded from HTTP transport. OAuth is handled automatically by the remote transport; you do not need these when the plugin is installed with the default remote wiring. + +### Out of scope in this plugin revision +This plugin **does not enable write operations**. For any write-intent request (create / edit / pause / duplicate a campaign or item), defer to the `create-campaign` skill (UI walkthrough). Do not invoke any tool not listed in the Tool Reference above, even if upstream surfaces additional ones. ## Technical Specifications @@ -102,7 +124,7 @@ When summarizing, cite `Total` so the user knows the scope of what was queried. **Response-size limits.** CSV output is capped at **25 KB of characters** and **1,000 rows per page**, whichever hits first. Truncation happens at row boundaries. On truncation, narrow the query (shorter date range, tighter `filters`, smaller `page_size`). -**Tool-existence boundary.** Only call tools listed in your Tool Reference above. If the user's intent requires a tool you don't see there (e.g., create/edit/pause/delete a campaign in the current MCP release), engage the `create-campaign` skill and walk them through the Realize UI. After the user says they've finished, offer to verify via `get_campaign` or `get_all_campaigns`. Upstream may add new tools over time — update your Tool Reference when the plugin is refreshed, and never guess at tools that aren't documented. +**Tool-existence boundary.** Only call tools listed in your Tool Reference above. If the user's intent requires any tool not listed there — including any write/edit operation — engage the `create-campaign` skill and walk them through the Realize UI. After the user says they've finished, offer to verify via `get_campaign` or `list_campaigns`. Upstream may add new tools over time — update your Tool Reference when the plugin is refreshed, and never guess at tools that aren't documented. **Error handling.** - Invalid `account_id` → re-run `search_accounts` and confirm selection with the user. diff --git a/docs/realize-best-practices-gap.md b/docs/realize-best-practices-gap.md index f20dc53..9a3aa96 100644 --- a/docs/realize-best-practices-gap.md +++ b/docs/realize-best-practices-gap.md @@ -32,16 +32,21 @@ This document serves three jobs, in order of size: ## Current MCP capability baseline -The MCP exposes **11 tools at the current release**, all read-only: +This plugin wires **18 read tools** from the upstream MCP, all read-only: | Area | Tools | |---|---| | Accounts | `search_accounts` | -| Campaigns | `get_all_campaigns`, `get_campaign`, `get_campaign_items`, `get_campaign_item` | +| Campaigns | `list_campaigns`, `get_campaign` | +| Items | `list_items`, `get_item` | +| Discovery — targeting | `search_geos`, `search_techno` | +| Discovery — audiences | `search_audiences`, `search_lookalike_audiences`, `search_contextual_segments` | +| Discovery — publishers / conversion | `search_publishers`, `search_conversion_rules` | +| Resources | `list_time_zones`, `list_cta_types` | | Reports (CSV) | `get_top_campaign_content_report`, `get_campaign_breakdown_report`, `get_campaign_history_report`, `get_campaign_site_day_breakdown_report` | | Auth (stdio only) | `get_auth_token`, `get_token_details` | -No create, update, delete, pause, conversion-tracking, audience, or configuration tools. +Write operations (campaign + item create/edit) are not enabled in this plugin revision — see Part 3 for the catalog of write capabilities still routed through the `create-campaign` UI walkthrough. --- @@ -61,7 +66,7 @@ No create, update, delete, pause, conversion-tracking, audience, or configuratio | Audience targeting (skip for new; use suppression) | `create-campaign` Step 7 | | 3–10 ads per campaign; "pre-qualify the click"; avoid generic CTAs | `create-campaign` Step 8 | | Dynamic Keyword Insertion mention | `create-campaign` Step 8 | -| Post-launch MCP verification via `get_campaign` + `get_campaign_items` | `create-campaign` Step 10 | +| Post-launch MCP verification via `get_campaign` + `list_items` | `create-campaign` Step 10 | ### From "How to Improve Campaign Performance" diff --git a/skills/campaigns/SKILL.md b/skills/campaigns/SKILL.md index 8679728..a4e9d83 100644 --- a/skills/campaigns/SKILL.md +++ b/skills/campaigns/SKILL.md @@ -16,27 +16,27 @@ Inspection of campaigns and their items (creatives) for a given account using th | Tool | Required params | Paginated? | |---|---|---| -| `mcp__realize-mcp__get_all_campaigns` | `account_id` | **No** — full list in one call | +| `mcp__realize-mcp__list_campaigns` | `account_id` | **No** — full list in one call | | `mcp__realize-mcp__get_campaign` | `account_id`, `campaign_id` | — | -| `mcp__realize-mcp__get_campaign_items` | `account_id`, `campaign_id` | **No** — full list in one call | -| `mcp__realize-mcp__get_campaign_item` | `account_id`, `campaign_id`, `item_id` | — | +| `mcp__realize-mcp__list_items` | `account_id`, `campaign_id` | **No** — full list in one call | +| `mcp__realize-mcp__get_item` | `account_id`, `campaign_id`, `item_id` | — | -None of these tools accept pagination or filter parameters. If a campaign has hundreds of items, they all come back in the single `get_campaign_items` call. Filter or summarize in post-processing rather than paginating. +None of these tools accept pagination or filter parameters. If a campaign has hundreds of items, they all come back in the single `list_items` call. Filter or summarize in post-processing rather than paginating. ## Typical flows **"List my active campaigns."** -1. `get_all_campaigns(account_id=...)` +1. `list_campaigns(account_id=...)` 2. Inspect the `status` field on each campaign and filter in memory to rows with an active/running status (the exact enum comes from the API response — e.g., `RUNNING`). Then summarize: count, combined spend, date range. **"What's the deal with campaign 98765?"** 1. `get_campaign(account_id=..., campaign_id=98765)` for configuration and status. -2. `get_campaign_items(account_id=..., campaign_id=98765)` for the creative list. +2. `list_items(account_id=..., campaign_id=98765)` for the creative list. 3. Summarize: objective, budget, targeting, creative count, any items flagged paused/rejected. **"Show me the creatives for my top-spending campaign."** 1. Combine with the `reports` skill: run `get_top_campaign_content_report`, pick the top campaign. -2. `get_campaign_items(account_id=..., campaign_id=)` and list creatives with IDs, names, status. +2. `list_items(account_id=..., campaign_id=)` and list creatives with IDs, names, status. ## Interpretation guidelines diff --git a/skills/create-campaign/SKILL.md b/skills/create-campaign/SKILL.md index f36f3b8..56179df 100644 --- a/skills/create-campaign/SKILL.md +++ b/skills/create-campaign/SKILL.md @@ -8,7 +8,7 @@ allowed-tools: ["Read", "AskUserQuestion"] This skill activates when the user asks for an action — campaign creation, editing, pausing, budget changes, creative swaps — that **no current MCP tool supports**. It walks the user through the equivalent steps in the **Realize console** using the setup flow as documented in Taboola's [official setup guide](https://www.taboola.com/help/en/articles/10473049-setting-up-a-new-campaign). -After the user says they've completed the UI flow, this skill hands back to the `realize-analyst` agent to verify the new state via the MCP tools that *do* exist (e.g., `get_campaign`, `get_all_campaigns`). +After the user says they've completed the UI flow, this skill hands back to the `realize-analyst` agent to verify the new state via the MCP tools that *do* exist (e.g., `get_campaign`, `list_campaigns`). When upstream adds new tools that cover an action this skill currently handles via UI, update the agent's Tool Reference and trim the affected walkthrough here in an explicit PR. @@ -123,7 +123,7 @@ Optional: Offer the user a verification step once the campaign is live: - Pull `get_campaign(account_id=..., campaign_id=...)` to confirm the fields match what they entered. -- Pull `get_campaign_items(account_id=..., campaign_id=...)` to confirm the ads are attached and live. +- Pull `list_items(account_id=..., campaign_id=...)` to confirm the ads are attached and live. - After **7–10 days** of data, hand off to `optimize-campaign` for the first performance review. Do not recommend optimizations before that — the algorithm is still in its learning phase. ## Editing an existing campaign @@ -152,7 +152,7 @@ Verify via `get_campaign` — the `status` field should reflect the change. Once the user confirms completion, call the `realize-analyst` agent (or route back to `campaigns` / `reports` skills) to: - Fetch the new/edited campaign via `get_campaign(account_id=..., campaign_id=...)` and read back the settings. Both params are required — never call `get_campaign` with only `campaign_id`. -- For pauses/resumes, confirm the `status` field in `get_campaign(account_id=..., campaign_id=...)` or list via `get_all_campaigns(account_id=...)`. +- For pauses/resumes, confirm the `status` field in `get_campaign(account_id=..., campaign_id=...)` or list via `list_campaigns(account_id=...)`. - For budget edits, echo the new `budget` / `daily_budget` field values. ## Gotchas diff --git a/skills/discovery/SKILL.md b/skills/discovery/SKILL.md new file mode 100644 index 0000000..280376f --- /dev/null +++ b/skills/discovery/SKILL.md @@ -0,0 +1,75 @@ +--- +name: discovery +description: Look up Realize targeting metadata, audiences, publishers, conversion rules, time zones, and CTA types. Use when the user asks "what X is available" or needs an opaque ID before going to the Realize console. Read-only — no campaign or item state is changed. +allowed-tools: ["Read", "Bash", "AskUserQuestion"] +--- + +# Discovery + +Resolve opaque IDs and enumerate the catalogs that Realize's targeting / audience / publisher / conversion settings draw from. This skill wraps the nine read-only "look it up" tools the MCP exposes, so the user does not have to guess country codes, audience IDs, publisher IDs, segment IDs, CTA enum values, or IANA time zone names. + +## When to use + +Trigger on any of: + +- "What countries / regions / DMAs / cities / postal codes can I target?" +- "What operating systems / browsers does Realize support?" +- "What audiences / lookalike audiences / contextual segments are available on account X?" +- "List publishers on account X" / "Find publishers matching " +- "What conversion rules are configured on account X?" +- "What time zones does Realize support?" +- "What CTA button types are available for native items?" +- Any campaign-console walkthrough where the user needs to paste an opaque ID rather than a display name. + +For pulling **performance numbers**, route to the `reports` skill instead. For campaign/item lookup, route to the `campaigns` skill. + +## Prerequisites + +- `account_id` resolved via the `accounts` skill is required for every tool below **except** `search_geos`, `search_techno`, `list_time_zones`, and `list_cta_types` (those are global catalogs). + +## Tools this skill wraps + +| Tool | Required params | Optional params | Returns | +|---|---|---|---| +| `mcp__realize-mcp__search_geos` | `dimension` ∈ {`countries`, `regions`, `dma`, `cities`, `postal_codes`} | `country_code` (ISO-2 — **required** when `dimension` ≠ `countries`) | `{dimension, values: [{code, name}, ...]}` | +| `mcp__realize-mcp__search_techno` | `dimension` ∈ {`operating_system_versions`, `browsers`} | `os_family` (**required** when `dimension=operating_system_versions`) | `{dimension, values: [...]}` | +| `mcp__realize-mcp__search_audiences` | `account_id` | `country_codes` (comma-separated ISO-2), `country_targeting_type` ∈ {`ALL`, `INCLUDE`, `EXCLUDE`} | Audience list with `audience_id`, `name`, ... | +| `mcp__realize-mcp__search_lookalike_audiences` | `account_id` | `country_code` (ISO-2) | Lookalike rules with `rule_id`, ... | +| `mcp__realize-mcp__search_contextual_segments` | `account_id` | `country_codes`, `country_targeting_type` | Segments with `segment_id`, ... | +| `mcp__realize-mcp__search_publishers` | `account_id`, `query` (use `"*"` for all) | `publisher_ids` (array of int), `page` (default 1), `page_size` (max **50**, default 10) | Paginated publisher list `{id, name, account_id, country, is_active}` | +| `mcp__realize-mcp__search_conversion_rules` | `account_id` | — | Conversion rules with `id`, ... | +| `mcp__realize-mcp__list_time_zones` | — | — | Array of IANA time zone names (e.g., `America/New_York`) | +| `mcp__realize-mcp__list_cta_types` | — | — | Array of valid `cta_type` enum values | + +## Examples + +- *"What DMAs are available in the US?"* → `search_geos(dimension="dma", country_code="US")`. +- *"List regions in Brazil."* → `search_geos(dimension="regions", country_code="BR")`. +- *"All Windows OS versions I can target?"* → `search_techno(dimension="operating_system_versions", os_family="Windows")`. +- *"Audiences on account advertiser_12345_prod for US/CA, include-mode."* → `search_audiences(account_id="advertiser_12345_prod", country_codes="US,CA", country_targeting_type="INCLUDE")`. +- *"Lookalike audiences for account X in Canada."* → `search_lookalike_audiences(account_id="...", country_code="CA")`. +- *"Contextual segments for account X."* → `search_contextual_segments(account_id="...")`. +- *"Publishers matching 'news' on account X."* → `search_publishers(account_id="...", query="news")`. +- *"All publishers on account X."* → `search_publishers(account_id="...", query="*")`. Paginate if needed — `page_size` is hard-capped at 50. +- *"Conversion rules on account X."* → `search_conversion_rules(account_id="...")`. +- *"What time zones does Realize accept?"* → `list_time_zones()`. +- *"What CTA button types exist?"* → `list_cta_types()`. + +## Workflow + +1. **Resolve `account_id` first** (if the tool requires it) via the `accounts` skill — see the [`accounts`](../accounts/SKILL.md) skill. +2. **Pick the narrowest tool** for the question. Don't pull all publishers when the user named one. +3. **Honor the dimension prerequisites:** + - `search_geos` with `dimension` in {`regions`, `dma`, `cities`, `postal_codes`} requires `country_code` — ask the user for it before calling, or default to the user's stated geo if obvious. + - `search_techno` with `dimension=operating_system_versions` requires `os_family` (e.g., `Windows`, `iOS`, `Android`, `macOS`). +4. **Summarize in prose, not raw JSON.** Pick the 3–5 most relevant rows, surface IDs alongside display names so the user can paste them downstream. If the list is long, offer to filter or paginate. +5. **Hand off the ID downstream.** When the user is mid-walkthrough in the `create-campaign` skill, return the opaque ID(s) and let the walkthrough continue. + +## Gotchas + +- **`country_code` is ISO-2, uppercase.** `US`, not `USA` or `us`. The MCP will reject other forms. +- **`search_publishers` `page_size` cap is 50**, not 100 — different from report tools. Default is 10. +- **`query="*"` lists all** publishers, but the result is still paginated — don't assume page 1 is the full set. +- **Audience country filters are passthrough.** `country_codes` and `country_targeting_type` are forwarded to the upstream API; verify the result actually narrowed by checking the row count. +- **Catalogs change.** Time zones and CTA types are versioned upstream — don't cache them across sessions; re-pull when starting a new campaign-creation flow. +- **Pass IDs verbatim downstream.** `audience_id`, `segment_id`, `rule_id`, and publisher `id` are opaque values returned by the API. Do not coerce to int, strip, or re-case them. diff --git a/skills/optimize-campaign/SKILL.md b/skills/optimize-campaign/SKILL.md index 7d0d564..e80b520 100644 --- a/skills/optimize-campaign/SKILL.md +++ b/skills/optimize-campaign/SKILL.md @@ -76,7 +76,7 @@ The MCP currently has no write tools, so every prescription is a **user action i - **Tighten targeting** — Campaigns → open the campaign → Location / Platform / Audiences. - **Isolate a top performer** — create a new campaign containing only the winning item(s) at an optimized CPC so you control its bid/budget independently. -After the user says they've made the change, offer to re-verify: pull `get_campaign` / `get_campaign_items` to confirm the new state, or re-run the relevant report after a data window (typically another 3–7 days). +After the user says they've made the change, offer to re-verify: pull `get_campaign` / `list_items` to confirm the new state, or re-run the relevant report after a data window (typically another 3–7 days). ## Prescription rules — quick reference diff --git a/tests/test-scenarios.md b/tests/test-scenarios.md index 525d136..48a9d40 100644 --- a/tests/test-scenarios.md +++ b/tests/test-scenarios.md @@ -43,7 +43,7 @@ Manual QA checklist. Run each scenario against a real Realize test account and c **Expected behavior:** 1. Claude reuses the cached `account_id` (does not re-run `search_accounts`). -2. Calls `get_all_campaigns(account_id=...)`. +2. Calls `list_campaigns(account_id=...)`. 3. Filters to running/active campaigns by inspecting the `status` field (exact enum from the API response) and summarizes: count, combined spend, names of top few. **Pass criteria:** No duplicate `search_accounts` call; summary is prose, not raw JSON dump. @@ -59,7 +59,7 @@ Manual QA checklist. Run each scenario against a real Realize test account and c **Expected behavior:** 1. `get_campaign(account_id=..., campaign_id=)`. -2. `get_campaign_items(account_id=..., campaign_id=)`. +2. `list_items(account_id=..., campaign_id=)`. 3. Summary includes: objective, budget, status, creative count, any paused/rejected items flagged. **Pass criteria:** Both tools are called; item-level status anomalies (if any) are surfaced. @@ -200,3 +200,79 @@ Manual QA checklist. Run each scenario against a real Realize test account and c 2. Claude does **not** fabricate a narrative. Says explicitly: "No records found for 2015 — either no campaigns ran in that window or the account is newer than that." **Pass criteria:** Empty-result honesty; no hallucinated data. + +--- + +## 12. Discovery — list audiences for an account + +**Prerequisite:** `account_id` resolved. + +**User prompt:** +> "What audiences are available for this account?" + +**Expected behavior:** +1. The `discovery` skill activates. +2. Calls `search_audiences(account_id=...)` (no country filter unless the user supplied one). +3. Summarizes top results in prose with `audience_id` alongside display name so they can be pasted into a campaign-creation flow. + +**Pass criteria:** `audience_id` values are surfaced verbatim (not coerced or re-cased); no `country_codes` filter is invented without the user asking for one. + +--- + +## 13. Discovery — DMAs in a country + +**User prompt:** +> "List all DMAs in the US." + +**Expected behavior:** +1. The `discovery` skill activates. +2. Recognizes that `search_geos(dimension="dma", ...)` requires `country_code`. +3. Calls `search_geos(dimension="dma", country_code="US")`. +4. Returns the DMA list with codes + names. + +**Pass criteria:** `country_code` is supplied as `US` (uppercase ISO-2), not `USA` or lowercase; tool is not called with `dimension="dma"` alone. + +--- + +## 14. Discovery — publisher search with query + +**Prerequisite:** `account_id` resolved. + +**User prompt:** +> "Show me publishers matching 'news' on this account." + +**Expected behavior:** +1. The `discovery` skill activates. +2. Calls `search_publishers(account_id=..., query="news")`. +3. Returns up to `page_size` (default 10, cap 50) publishers with `id`, `name`, `country`, `is_active`. +4. Offers pagination if the result is truncated. + +**Pass criteria:** `page_size` is not pushed above 50; `query="news"` is passed through verbatim (no wildcard injection). + +--- + +## 15. Discovery — list time zones + +**User prompt:** +> "What time zones does Realize support?" + +**Expected behavior:** +1. The `discovery` skill activates. +2. Calls `list_time_zones()` (no params). +3. Returns the IANA names. Claude offers to filter to a region if the list is long. + +**Pass criteria:** No `account_id` is sent (this is a global catalog); output is summarized, not dumped raw. + +--- + +## 16. Discovery — list CTA types + +**User prompt:** +> "What CTA button options are available for native items?" + +**Expected behavior:** +1. The `discovery` skill activates. +2. Calls `list_cta_types()` (no params). +3. Returns the enum values verbatim. + +**Pass criteria:** No `account_id` is sent; values are presented as the exact enum strings the user would paste into a campaign setup.