> ## Documentation Index
> Fetch the complete documentation index at: https://agenticadvertisingorg-snap-format-preview-links.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Protocol Comparison

> MCP vs A2A for AdCP: side-by-side comparison of transport formats, async handling, status systems, and when to use each protocol for advertising agent integration.

Both MCP and A2A provide identical AdCP capabilities using the same unified status system. They differ only in transport format and async handling.

## Quick Comparison

| Aspect              | MCP                                                                                 | A2A                                                           |
| ------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| **Request Style**   | Tool calls                                                                          | Task messages                                                 |
| **Response Style**  | Direct JSON                                                                         | Artifacts                                                     |
| **Status System**   | Unified status field                                                                | Unified status field                                          |
| **Async Handling**  | AdCP status payloads over tool calls; optional MCP Tasks wrapper                    | AdCP status payloads in A2A artifacts; optional SSE streaming |
| **Webhooks**        | `push_notification_config` in tool args                                             | Native PushNotificationConfig                                 |
| **Task Management** | AdCP `task_id` via webhooks or AdCP polling (`get_task_status`, legacy `tasks/get`) | AdCP `task_id` via webhooks or AdCP polling                   |
| **Context**         | Manual (pass context\_id)                                                           | Automatic (protocol-managed)                                  |
| **Best For**        | Claude, AI assistants                                                               | Agent workflows                                               |

## Unified Status System

Both protocols use the same status field with consistent values.

### Status Handling (Both Protocols)

Every response includes a status field that tells you exactly what to do:

```json theme={null}
{
  "status": "input-required",    // Same values for both protocols
  "message": "Need your budget", // Same human explanation
  // ... protocol-specific formatting below
}
```

| Status           | What It Means                | Your Action                                         |
| ---------------- | ---------------------------- | --------------------------------------------------- |
| `completed`      | Task finished                | Process data, show success                          |
| `input-required` | Need user input              | Read message, prompt user, follow up                |
| `working`        | Processing (\< 120s)         | Wait for the open call/stream result; show progress |
| `submitted`      | Long-running (hours to days) | Provide webhook or poll less frequently             |
| `failed`         | Error occurred               | Show error, handle gracefully                       |
| `auth-required`  | Need auth                    | Prompt for credentials                              |

See [Task Lifecycle](/docs/building/by-layer/L3/task-lifecycle) for complete status handling guide.

## Transport Format Differences

Same status and data, different packaging:

### MCP Response Format

```json theme={null}
{
  "status": "input-required",
  "message": "I need your budget and target audience",
  "context_id": "ctx-123",
  "products": [],
  "suggestions": ["budget", "audience"]
}
```

### A2A Response Format

```json theme={null}
{
  "status": "input-required",
  "contextId": "ctx-123",
  "artifacts": [{
    "artifactId": "artifact-product-discovery-xyz",
    "name": "product_discovery",
    "parts": [
      {
        "kind": "text",
        "text": "I need your budget and target audience"
      },
      {
        "kind": "data",
        "data": {
          "products": [],
          "suggestions": ["budget", "audience"]
        }
      }
    ]
  }]
}
```

## Async Operation Differences

Both protocols carry the same AdCP status progression:
`submitted` → `working` → `completed`/`failed`

The progression above is AdCP application state. MCP Tasks and A2A task state are transport mechanics that can deliver an AdCP payload, but they are not a replacement for AdCP task polling or reconciliation.

### MCP Task-Augmented Call (Transport Wrapper)

```javascript theme={null}
// Task-augmented tool call — returns CreateTaskResult immediately
const createResult = await mcp.callTool({
  name: "create_media_buy",
  arguments: {
    buyer_ref: "acme_q1",
    packages: [...],
    push_notification_config: {  // Optional: webhook for session-outliving ops
      url: "https://buyer.com/webhooks/adcp/create_media_buy/op_123",
      authentication: { schemes: ["HMAC-SHA256"], credentials: "secret" }
    }
  },
  task: { ttl: 86400000 }  // Request task-augmented execution
});
// createResult.task = { taskId: "task-456", status: "working", pollInterval: 5000 }

// Client polls via MCP Tasks protocol (outside the LLM loop)
const status = await mcp.getTask({ taskId: "task-456" });
// status = { taskId: "task-456", status: "completed", ... }

// Retrieve the actual CallToolResult, then inspect the AdCP payload inside it
const result = await mcp.getTaskResult({ taskId: "task-456" });
// result = { content: [...], isError: false }

const adcpResponse = result.structuredContent;
if (adcpResponse.status === "submitted") {
  // The MCP task delivered the AdCP response; the media-buy workflow is still open.
  await adcp.call("get_task_status", {
    task_id: adcpResponse.task_id,
    include_result: true
  });
}
```

### A2A Async Pattern

```javascript theme={null}
// Initial response carries an AdCP payload inside A2A task/artifact transport
{
  "status": "submitted",
  "task_id": "adcp-task-456",
  "contextId": "ctx-123",
  "estimatedCompletionTime": "2025-01-23T10:00:00Z"
}

// Real-time updates via SSE
const events = new EventSource(`/tasks/${response.taskId}/events`);
events.onmessage = (event) => {
  const update = JSON.parse(event.data);
  console.log(`Status: ${update.status}, Message: ${update.message}`);
};

// Native webhook support
await a2a.send({
  message: { /* skill invocation */ },
  push_notification_config: {
    webhook_url: "https://buyer.com/webhooks",
    authentication: {
      schemes: ["Bearer"],
      credentials: "secret_token_min_32_chars"
    }
  }
});
```

## Context Management

### MCP: Manual Context

```javascript theme={null}
let contextId = null;

async function callAdcp(request) {
  if (contextId) {
    request.context_id = contextId;
  }

  const response = await mcp.call('get_products', request);
  contextId = response.context_id; // Save for next call

  return response;
}
```

### A2A: Automatic Context

```javascript theme={null}
// A2A manages context automatically
const response1 = await a2a.send({ message: "Find video products" });
const response2 = await a2a.send({
  contextId: response1.contextId, // Optional - A2A tracks this
  message: "Focus on premium inventory"
});
```

## Clarification Handling

Both protocols use the same `status: "input-required"` pattern:

```javascript theme={null}
// Works for both MCP and A2A
function handleResponse(response) {
  if (response.status === 'input-required') {
    const info = promptUser(response.message);
    return sendFollowUp(response.context_id, info);
  }

  if (response.status === 'completed') {
    return processResults(response);
  }
}
```

## Error Handling

Both use `status: "failed"` with same error structure:

```json theme={null}
{
  "status": "failed",
  "message": "Insufficient inventory for your targeting criteria",
  "context_id": "ctx-123",
  "error_code": "insufficient_inventory",
  "suggestions": ["Expand targeting", "Increase CPM"]
}
```

## Choosing a Protocol

### Choose MCP if you're using:

* Claude Desktop or Claude Code
* MCP-compatible AI assistants
* Simple tool-based integrations
* Direct JSON responses

### Choose A2A if you're using:

* Google AI agents or Agent Engine
* Multi-modal workflows (text + files)
* Real-time streaming updates
* Artifact-based data handling

### Both protocols provide:

* Same AdCP tasks and capabilities
* Unified status system for clear client logic
* Context management for conversations
* Async operation support
* Human-in-the-loop workflows
* Error handling and recovery

## Next Steps

* **MCP Guide**: See [MCP Guide](/docs/building/by-layer/L0/mcp-guide) for tool calls and context management
* **A2A Guide**: See [A2A Guide](/docs/building/by-layer/L0/a2a-guide) for artifacts and streaming
* **Both protocols**: Provide the same capabilities with unified status handling
