MCP server for VK Ads (ads.vk.com / myTarget) API — manage campaigns, ad groups, banners, and fetch statistics via Claude and other MCP clients.
18 tools with consistent naming (verb_noun pattern) and reasonable descriptions (avg ~120 chars). All tools have input schemas with typed parameters. However, critical gaps: (1) descriptions lack actionable context for LLM selection, most are 1-2 sentences without WHEN/WHY guidance; (2) no output schemas documented, LLMs cannot plan downstream calls; (3) enum constraints missing for status/entity/metrics params (free-form strings invite hallucination); (4) error handling returns raw API payloads without recovery guidance; (5) write tools lack confirmation/dry-run patterns despite destructive capability. Naming is strong (auth_check, list_campaigns, set_campaign_status), but parameter descriptions are sparse (e.g., 'campaign payload' vs 'name (string, 1-100 chars), objective (enum: awareness|traffic|conversions), budget_limit_day (int, 100-1000000 RUB)').
Verify credentials and API reachability. Returns current user info if token is valid, otherwise an error payload.
Create a new campaign. `payload` follows VK Ads Campaign schema (name, objective, budget_limit, budget_limit_day, package_id, targetings, etc.). See target.vk.ru docs.
Get a single ad group by ID.
Get a single banner by ID.
Get a single campaign by ID.
Daily statistics. Args: entity: one of `campaigns`, `ad_groups`, `banners`, `users`. ids: comma-separated entity IDs (e.g. "123,456"). date_from: YYYY-MM-DD. date_to: YYYY-MM-DD. metrics: optional metric group (e.g. `base`, `video`, `uniques`, `all`).
No output schemas documented. LLMs cannot infer response structure, forcing them to guess field names for downstream tool calls. E.g., list_campaigns returns what fields? Does it include campaign_id, name, status, budget? Without documented output, agents cannot chain tools reliably.
Enum constraints missing for status, entity, and metrics parameters. 'status' in list_campaigns accepts free-form string (description says 'active, blocked, deleted, etc.' but no enum). LLMs hallucinate invalid values like 'paused', 'inactive', 'archived'. Same for entity in statistics tools ('campaigns, ad_groups, banners, users' should be enum, not string).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
Summary (aggregated) statistics for the period. Args mirror `get_statistics_day`.
List ad groups, optionally filtered by campaign_id.
List banners (individual ads).
List advertising campaigns. Args: limit: max items (default 50, max 250). offset: pagination offset. status: filter by status (active, blocked, deleted, etc.). fields: comma-separated field list to return.
List available ad packages (ad formats / placements).
List remarketing audiences.
Search geo regions for targeting (cities, regions).
Set campaign status. Allowed: `active`, `blocked` (pause), `deleted`.
Update an ad group.
Update a banner (status, urls, creatives references, etc.).
Update a campaign (PATCH-style; send only changed fields).
Upload a static image to VK Ads content storage. `source_path_or_url` is a local file path OR a public URL. Returns the content object (id, url, dimensions) to reference from a banner.
Descriptions lack actionable context. Most are 1-2 sentences (e.g., 'Get a single campaign by ID.' is 28 chars). No WHEN/WHY guidance for LLM selection. E.g., get_campaign vs list_campaigns, when should an LLM choose one over the other? Descriptions should explain: 'Use when you have a specific campaign_id; use list_campaigns to discover IDs by name or status.'
Write tools (create_campaign, update_campaign, update_ad_group, update_banner, upload_image) lack confirmation/dry-run patterns. Agents can accidentally delete campaigns or overwrite banners. No recovery guidance in error responses. E.g., set_campaign_status to 'deleted' is irreversible, should require explicit confirmation or offer a restore tool.
Error responses return raw API payloads (_wrap_error returns status, url, detail) without recovery guidance. LLMs cannot act on bare error codes. E.g., a 400 error should say 'Invalid campaign_id: must be a positive integer. Use list_campaigns() to find valid IDs.' Current: {'error': True, 'status': 400, 'detail': {...}} tells agent nothing.