Testing AdCP via MCP
You can test AdCP tasks using the CLI tools or by chatting with Addie, the AgenticAdvertising.org assistant.Tool Call Patterns
Basic Tool Invocation
Tool Call with Filters
Tool Call with Application-Level Context
MCP Response Format
New in AdCP 1.6.0: All responses include unified status field. MCP responses use a flat structure where task-specific fields are at the top level alongside protocol fields:MCP-Specific Fields
- context_id: Session identifier that you must manually manage
- context: Opaque initiator-provided metadata echoed by agents
- status: Same values as A2A protocol for consistency
- Task-specific fields (e.g.,
products,media_buy_id,creatives) are at the top level, not wrapped in adataobject
Available Tools
All AdCP tasks are available as MCP tools:Protocol Tools
Media Buy Tools
Signals Tools
Async Operations via MCP Tasks
AdCP uses MCP Tasks for long-running operations over MCP. This removes the LLM from the polling path — the client handles task lifecycle at the protocol level, and the model only sees the final result. :::warning Client support is limited Most chat-based MCP clients (Claude Desktop, Cursor) do not yet support MCP Tasks. If your client doesn’t support task-augmented tool calls, use webhooks or polling viatasks/get instead — these work with any MCP client. See Async Operations and Push Notifications for transport-independent patterns.
MCP Tasks are the right choice when you control the MCP client (e.g., building your own orchestrator with @modelcontextprotocol/sdk) or when client support matures.
:::
SDK Implementation
If you use the@modelcontextprotocol/sdk package, MCP Tasks support requires minimal code. Pass an InMemoryTaskStore (or your own TaskStore implementation) to the Server constructor — the SDK auto-registers handlers for tasks/get, tasks/result, tasks/list, and tasks/cancel:
tools/call handler, check for the task field and use the store:
_meta injection for tasks/result responses. InMemoryTaskStore is non-persistent — for production, implement a TaskStore backed by your database.
If you use McpServer instead of Server, register task-capable tools with server.experimental.tasks.registerToolTask() — the higher-level API enforces this for tools that declare taskSupport.
:::warning Production task isolation
InMemoryTaskStore does not scope tasks by session — any client that knows a task ID can read, cancel, or list it. For production, implement a TaskStore that filters by sessionId on every operation. Also clamp client-provided TTL values server-side and enforce rate limits on task creation.
:::
Server Capabilities
AdCP MCP servers declaretasks in their capabilities:
Tool-Level Task Support
Each tool declares whether it supports task-augmented execution viaexecution.taskSupport:
| Tool | taskSupport | Rationale |
|---|---|---|
get_products | optional | Complex searches, HITL clarification |
create_media_buy | optional | External systems, approval workflows |
update_media_buy | optional | External system updates |
build_creative | optional | Human creative review, long production renders |
sync_creatives | optional | Asset processing and transcoding |
get_signals | optional | Complex audience discovery |
activate_signal | optional | Platform deployment |
sync_plans | optional | Governance plan processing |
check_governance | optional | External policy evaluation |
report_plan_outcome | optional | External system updates |
acquire_rights | optional | Approval workflows |
update_rights | optional | External updates |
get_rights | optional | External lookups |
get_adcp_capabilities | forbidden | Instant, static |
list_creative_formats | forbidden | Instant catalog lookup |
preview_creative | forbidden | Renders existing manifest |
list_creatives | forbidden | Session state lookup |
get_media_buys | forbidden | Session state lookup |
get_media_buy_delivery | forbidden | Session state lookup |
get_creative_delivery | forbidden | Session state lookup |
get_plan_audit_logs | forbidden | Session state lookup |
get_brand_identity | forbidden | Instant lookup |
taskSupport: "optional" can be called either way:
- Without
taskfield: Synchronous — returns the result directly - With
taskfield: Returns aCreateTaskResultimmediately; poll viatasks/get, retrieve the result viatasks/result
Invoking a Tool as a Task
Include thetask field in your tools/call request:
tasks/get (respecting pollInterval) until the task reaches a terminal state (completed, failed, or cancelled), then retrieves the CallToolResult via tasks/result. To abort a running task, send tasks/cancel with the taskId.
AdCP Status Mapping
AdCP uses a richer set of statuses than MCP Tasks. When serving over MCP, AdCP statuses map to MCP Task statuses:| AdCP Status | MCP Task Status | Notes |
|---|---|---|
working | working | Direct mapping |
submitted | working | Use statusMessage to indicate queued state |
input-required | input_required | Server moves task to input_required, sends elicitation via tasks/result |
completed | completed | Direct mapping |
failed | failed | Direct mapping |
rejected | failed | Use statusMessage for rejection reason |
canceled | cancelled | Spelling difference (AdCP uses American, MCP uses British) |
auth-required | input_required | Elicitation requests credentials |
Webhooks for Long-Lived Operations
MCP Tasks handles polling within the MCP session, but some AdCP operations outlive a single session (e.g., a media buy that takes 24 hours for publisher approval). For these, combine MCP Tasks withpush_notification_config:
Context Management (MCP-Specific)
Critical: MCP requires manual context management. You must passcontext_id to maintain conversation state.
Context Session Pattern
Usage Examples
Basic Session with Context
Async Operations with MCP Tasks
For tools withtaskSupport: "optional", pass the task option to use MCP Tasks:
task_type and operation_id are passed in the URL (e.g., /webhooks/adcp/create_media_buy/op_456). While the schema still supports these fields in the payload for backward compatibility, they are deprecated.
The result field contains the AdCP data payload. For completed/failed statuses, this is the full task response (e.g., create-media-buy-response.json). For other statuses, use the status-specific schemas (e.g., create-media-buy-async-response-working.json).
MCP Webhook Envelope Fields
Themcp-webhook-payload.json envelope includes:
Required fields:
task_id— Unique task identifier for correlationstatus— Current task status (completed, failed, working, input-required, etc.)timestamp— ISO 8601 timestamp when webhook was generated
domain— AdCP domain (“media-buy” or “signals”)context_id— Conversation/session identifiermessage— Human-readable context about the status change
task_type— Task name (e.g., “create_media_buy”, “sync_creatives”) - ⚠️ Deprecated: See URL-Based Routingoperation_id— Correlates a sequence of updates for the same operation - ⚠️ Deprecated: See URL-Based Routing
result— Task-specific AdCP payload (see Data Schema Validation below)
Webhook Trigger Rules
Webhooks are sent when all of these conditions are met:- Task type supports async (e.g.,
create_media_buy,sync_creatives,get_products) pushNotificationConfigis provided in the request- Task runs asynchronously — initial response is
workingorsubmitted
completed, failed, rejected), no webhook is sent—you already have the result.
Status changes that trigger webhooks:
working→ Progress update (task actively processing)input-required→ Human input neededcompleted→ Final result availablefailed→ Error details
Data Schema Validation
Theresult field in MCP webhooks uses status-specific schemas:
| Status | Schema | Contents |
|---|---|---|
completed | [task]-response.json | Full task response (success branch) |
failed | [task]-response.json | Full task response (error branch) |
working | [task]-async-response-working.json | Progress info (percentage, step) |
input-required | [task]-async-response-input-required.json | Requirements, approval data |
submitted | [task]-async-response-submitted.json | Acknowledgment (usually minimal) |
async-response-data.json
Webhook Handler Example
Task Management and Polling
Context Expiration Handling
Handling Async Operations
When a task returnsworking or submitted status, you need a way to receive the result. This applies whether or not your MCP client supports MCP Tasks — the patterns below work with any client.
| Approach | Best For | Trade-offs |
|---|---|---|
| Webhooks | Production systems, any task duration | Handles hours/days, but requires a public endpoint |
| Polling | Simple integrations, short tasks | Easy to implement, but inefficient for long waits |
| MCP Tasks | Custom clients using the MCP SDK | Protocol-native, but requires client support |
Option 1: Webhooks (recommended)
Configure a webhook URL and the server will POST the result when the operation completes. This is the right approach forsubmitted operations that are blocked on external dependencies (publisher approval, human review).
Option 2: Polling (backup)
Usetasks/get as a backup for submitted operations, or when you can’t expose a webhook endpoint:
Handling different statuses
Integration Example
MCP-Specific Considerations
Tool Discovery
AdCP Extension via MCP Server Card
Recommended: Use
get_adcp_capabilities for runtime capability discovery. The server card extension provides static metadata for tool catalogs and registries./.well-known/mcp.json (or /.well-known/server.json). AdCP-specific metadata goes in the _meta field using the adcontextprotocol.org namespace.
- Clients can discover AdCP capabilities without making test calls
- Declare which protocol domains you implement (media_buy, creative, signals)
- Declare which typed extensions you support (see Context & Sessions)
- Enable compatibility checks based on version
_meta field uses reverse DNS namespacing per the MCP server.json spec. AdCP servers should support both /.well-known/mcp.json and /.well-known/server.json locations.
Parameter Validation
Error Handling
AdCP errors are returned as tool-level responses withisError: true and the error in structuredContent.adcp_error. For the full extraction logic and JSON-RPC transport codes, see Transport Error Mapping.
Best Practices
- Use session wrapper for automatic context management
- Check status field before processing response data
- Handle context expiration gracefully with retries
- Reference Core Concepts for status handling patterns
- Validate parameters using MCP tool schemas when available
Next Steps
- Core Concepts: Read Task Lifecycle for status handling and workflows
- Task Reference: See Media Buy Tasks and Signals
- Protocol Comparison: Compare with A2A integration
- Examples: Find complete workflow examples in Core Concepts