Skip to main content
Skip to article

#MCP vs A2A: Which AI Agent Protocol for WhatsApp?

13 min read

You Don't Need to Choose—You Need Both

Picture this: You're building a WhatsApp customer support system with multiple specialized agents. Your support agent needs to look up inventory levels. Your calendar agent needs CRM access. Your payment agent needs transaction data.

Here's the question that stops most people: How do your agents get access to this data? And once they have it, how do they coordinate with each other?

Most developers assume they need one protocol to solve both problems. They're wrong.

The answer is simpler: MCP handles data access, A2A handles agent coordination. They're not competing—they're complementary layers in your multi-agent architecture. Get this distinction right, and building complex agent systems becomes dramatically simpler.

Let me show you exactly when to use each, how they work together, and the WhatsApp integration patterns that make this practical.

Protocol Quick Reference: What Each One Actually Does

Before we dive deep, here's the core distinction in one table:

AspectMCP (Model Context Protocol)A2A (Agent-to-Agent)
PurposeConnect AI models to data sourcesEnable agents to discover and communicate with each other
Developed byAnthropic (2025)Community-driven standard (2024-2025)
Transportstdio, HTTP, WebSocketWhatsApp, HTTP, WebSocket
AuthenticationServer-defined (OAuth, API keys)Bearer tokens, mutual TLS
Message formatJSON-RPC 2.0 (client→server)JSON-RPC 2.0 (peer-to-peer)
Use caseTool calling, RAG, context injectionMulti-agent workflows, agent coordination
AnalogyDatabase connector for AIMessaging bus for agents
StatefulNo (each tool call is independent)Yes (agents maintain conversation context)

Key insight: MCP is like a database connector — it gives your AI model access to tools, files, and data. A2A is like a messaging protocol — it lets agents talk to each other to coordinate complex workflows.

If your agent needs to search a knowledge base, that's MCP. If your agent needs to ask another agent for help, that's A2A.

When to Use MCP: Data Access Patterns

MCP shines when your AI model needs deterministic access to external systems. Think of it as the "tool-calling infrastructure" for your agents.

Use Case 1: RAG (Retrieval-Augmented Generation)

Your support agent needs to search your company knowledge base before answering customer questions. Without MCP, you'd have to hardcode database queries, API calls, and result formatting into your agent logic. With MCP, you expose a documents.search tool that your AI can call naturally.

Example scenario:

  • Customer asks: "What's your refund policy?"
  • Agent recognizes it needs external knowledge
  • Agent calls MCP tool: documents.search(query="refund policy", limit=3)
  • MCP server returns relevant policy documents
  • Agent synthesizes answer from retrieved context

Code example:

javascript
// MCP client implementation (simplified)
const mcp = new MCPClient({
  serverUrl: 'http://localhost:3000/mcp',
  transport: 'http'
});

// List available tools
const tools = await mcp.listTools();
console.log(tools);
// ["documents.search", "documents.retrieve", "crm.search_contact", ...]

// Call a tool
const result = await mcp.callTool({
  name: 'documents.search',
  arguments: { query: 'refund policy', limit: 3 }
});

console.log(result);
// {
//   documents: [
//     { title: "Refund Policy", content: "Customers can request..." },
//     { title: "Return Process", content: "To initiate a return..." },
//     { title: "Exchange Guidelines", content: "Items must be..." }
//   ]
// }

Why MCP is perfect here: The AI model doesn't need to know SQL syntax, your database schema, or how to connect to your knowledge base. It just calls a tool with natural parameters, and MCP handles the rest.

Use Case 2: CRM and Calendar Integration

Your sales agent needs to check if a lead already exists in your CRM before creating a duplicate record. Or your scheduling agent needs to find available appointment slots.

Example scenario:

  • Lead submits contact form via WhatsApp
  • Sales agent calls MCP tool: crm.search_contact(email="[email protected]")
  • If contact exists, update record; if not, create new
  • Agent calls MCP tool: crm.create_contact(name="John Doe", email=...)

Code example:

python
# Python MCP client for CRM integration
import asyncio
from mcp import Client

async def handle_new_lead(name, email, phone):
    # Connect to MCP server
    async with Client("http://crm-mcp-server:3000") as mcp:
        # Check if contact exists
        existing = await mcp.call_tool(
            "crm.search_contact",
            {"email": email}
        )

        if existing["contacts"]:
            # Update existing contact
            await mcp.call_tool(
                "crm.update_contact",
                {
                    "id": existing["contacts"][0]["id"],
                    "phone": phone,
                    "last_contact": "2026-02-11"
                }
            )
            return f"Updated existing contact: {existing['contacts'][0]['id']}"
        else:
            # Create new contact
            new_contact = await mcp.call_tool(
                "crm.create_contact",
                {
                    "name": name,
                    "email": email,
                    "phone": phone,
                    "source": "whatsapp"
                }
            )
            return f"Created new contact: {new_contact['id']}"

# Usage in webhook handler
result = await handle_new_lead("John Doe", "[email protected]", "+1234567890")
print(result)

Why MCP wins: Your AI agent doesn't need CRM-specific training. The MCP server handles authentication, rate limiting, and error handling. Your agent just calls tools with semantic parameters.

Use Case 3: File Access (Invoices, Contracts, PDFs)

Your accounting agent needs to read invoice PDFs to extract payment amounts and due dates.

Example scenario:

  • Customer asks: "What's the status of invoice #12345?"
  • Agent calls MCP tool: files.read(path="/invoices/12345.pdf")
  • MCP server returns parsed PDF content
  • Agent extracts amount, due date, payment status
  • Agent responds with precise information

MCP best practices:

  • Use for deterministic operations — Database queries, API calls, file reads where results are predictable
  • Server controls access — MCP server handles authentication, permissions, rate limiting
  • Stateless tool calls — Each call is independent; no session management needed
  • Type safety — Define tool schemas so AI knows what parameters to pass
  • Error handling — MCP server returns structured errors the AI can understand

When NOT to use MCP:

  • Agent-to-agent communication (use A2A)
  • Long-running workflows that span multiple agents (use A2A)
  • Peer-to-peer coordination without central data source (use A2A)

When to Use A2A: Agent Coordination Patterns

A2A excels when agents need to discover each other, negotiate capabilities, and exchange messages peer-to-peer. Think of it as the "inter-agent communication protocol."

Use Case 1: Multi-Agent Workflows (Handoffs and Escalation)

Your support agent can't answer a complex billing question, so it needs to escalate to a specialist agent — along with full conversation history.

Example scenario:

  • Customer: "Why was I charged twice for order #5678?"
  • Support agent searches knowledge base (via MCP) — no answer found
  • Support agent discovers billing agent via A2A: /.well-known/agent.json
  • Support agent calls A2A method: agent.escalate(conversation_history=...)
  • Billing agent handles inquiry, calls A2A to return result
  • Support agent relays answer to customer

Code example:

bash
# Step 1: Discover agent capabilities
curl https://billing-agent.example.com/.well-known/agent.json

# Response:
# {
#   "name": "Billing Specialist Agent",
#   "version": "1.0.0",
#   "capabilities": ["billing.escalate", "invoice.lookup", "refund.process"],
#   "rpc_endpoint": "/api/v2/a2a"
# }

# Step 2: Call agent method via A2A
curl -X POST https://billing-agent.example.com/api/v2/a2a \
  -H "Authorization: Bearer AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "billing.escalate",
    "params": {
      "customer_id": "cust_12345",
      "issue": "duplicate charge",
      "conversation_history": [
        {"role": "customer", "content": "Why was I charged twice?"},
        {"role": "agent", "content": "Let me check with billing..."}
      ]
    },
    "id": 1
  }'

# Response:
# {
#   "jsonrpc": "2.0",
#   "result": {
#     "status": "resolved",
#     "resolution": "Duplicate charge was a bank pending authorization...",
#     "refund_issued": false
#   },
#   "id": 1
# }

Why A2A is ideal: Agents are peers — no central orchestrator needed. The billing agent can be on a different server, owned by a different team, or even a third-party service. As long as it speaks A2A, coordination works.

Use Case 2: Agent Discovery and Capability Negotiation

Your payment agent needs to find an "invoice-generator" agent but doesn't know its URL or capabilities ahead of time.

Example scenario:

  • Payment received for order #7890
  • Payment agent needs to generate invoice
  • Agent queries service registry for agents with invoice.create capability
  • Discovers invoice-generator agent, checks its capabilities
  • Calls A2A method: invoice.create(order_id=7890, amount=99.99)
  • Invoice-generator returns PDF URL
  • Payment agent sends invoice to customer via WhatsApp

Code example:

javascript
// Agent discovery and dynamic invocation
async function generateInvoice(orderId, amount) {
  // Query service registry for invoice agents
  const registry = await fetch('https://registry.example.com/agents?capability=invoice.create');
  const agents = await registry.json();

  if (agents.length === 0) {
    throw new Error('No invoice generation agents available');
  }

  // Use first available agent
  const invoiceAgent = agents[0];

  // Check capabilities
  const wellKnown = await fetch(`${invoiceAgent.url}/.well-known/agent.json`);
  const capabilities = await wellKnown.json();

  if (!capabilities.capabilities.includes('invoice.create')) {
    throw new Error('Agent does not support invoice.create');
  }

  // Call A2A method
  const response = await fetch(`${invoiceAgent.url}${capabilities.rpc_endpoint}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.AGENT_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      jsonrpc: '2.0',
      method: 'invoice.create',
      params: { order_id: orderId, amount: amount, currency: 'USD' },
      id: Date.now()
    })
  });

  const result = await response.json();
  return result.result.pdf_url;
}

// Usage
const pdfUrl = await generateInvoice(7890, 99.99);
console.log(`Invoice generated: ${pdfUrl}`);

Why A2A wins: No hardcoded URLs. Agents can be added, removed, or replaced without changing your code. Capability negotiation prevents calling methods that don't exist.

Use Case 3: Asynchronous Agent Collaboration

Your lead qualification agent scores a lead as "hot," then notifies your sales agent to follow up — all without blocking or waiting for confirmation.

Example scenario:

  • Lead fills out contact form on website
  • Lead qualification agent analyzes responses, scores lead as 8/10
  • Agent calls A2A: sales_agent.notify_hot_lead(lead_id=123, score=8)
  • Sales agent receives notification, starts outreach workflow
  • Sales agent updates CRM (via MCP), notifies marketing agent for nurture campaign

A2A best practices:

  • Use for agent-to-agent coordination — Not for model-to-data access
  • Implement timeout handling — Agents may be offline or slow to respond
  • Version capabilities — Agents evolve over time; version your methods
  • Include conversation context — A2A messages should carry enough context for the receiving agent to act
  • Peer authentication — Use bearer tokens or mutual TLS to verify agent identity

When NOT to use A2A:

  • Fetching data from databases (use MCP)
  • Tool calling within a single agent (use MCP)
  • Synchronous data retrieval (use MCP)

How MCP and A2A Work Together

Here's where the magic happens. Most real-world agent systems need both protocols working in harmony.

Architecture pattern (described):

text
Customer sends WhatsApp message
  ↓
MoltFlow receives webhook → Routes to Support Agent
  ↓
Support Agent needs product data
  ↓ [MCP] Query inventory database via MCP tool
  ↓ Result: Product out of stock
  ↓
Support Agent needs specialist help
  ↓ [A2A] Escalate to Logistics Agent via A2A
  ↓
Logistics Agent needs supplier ETA data
  ↓ [MCP] Call supplier API via MCP tool
  ↓ Result: Restocking in 3 days
  ↓
Logistics Agent responds to Support Agent
  ↓ [A2A] Return resolution via A2A
  ↓
Support Agent synthesizes response
  ↓
MoltFlow sends message to customer

Real-world example: E-commerce order inquiry

Let's trace a complete interaction through both protocols:

  1. Customer asks: "Where's my order #12345?"
  2. Support agent uses MCP to query order database:
    javascript
    const order = await mcp.callTool('orders.search', { id: 12345 });
    // Result: { status: 'shipped', tracking: 'TRK789', carrier: 'FedEx' }
  3. Order shows "shipped" — agent uses MCP to query shipping API:
    javascript
    const tracking = await mcp.callTool('shipping.track', {
      tracking_number: 'TRK789',
      carrier: 'FedEx'
    });
    // Result: { status: 'delayed', estimated_delivery: '2026-02-15' }
  4. Shipping delayed — agent uses A2A to notify logistics agent:
    javascript
    const escalation = await a2a.call({
      agent: 'logistics-agent',
      method: 'escalate',
      params: { order_id: 12345, issue: 'delayed_shipment', tracking: 'TRK789' }
    });
    // Result: { resolution: 'Carrier weather delay, offering 20% discount code' }
  5. Logistics agent resolves — calls A2A callback to support agent with resolution
  6. Support agent responds to customer: "Your order is delayed due to weather. Estimated delivery: Feb 15. Here's a 20% discount code for your next order: SORRY20"

Integration pattern with MoltFlow:

MoltFlow provides the infrastructure glue that makes this work:

  • Webhooks trigger agent workflows — Inbound WhatsApp messages start the flow
  • Agents use MCP for data access (RAG, CRM, file systems, databases)
  • Agents use A2A for peer coordination (handoffs, escalations, notifications)
  • MoltFlow exposes both interfaces — MCP server interface (future feature) and A2A endpoint (already available at /api/v2/a2a)

Setting Up MCP + A2A in MoltFlow

Let's make this practical. Here's how to configure both protocols with MoltFlow.

MCP Setup (Illustrative — Future Feature)

bash
# Configure MCP server in MoltFlow
curl -X POST https://apiv2.waiflow.app/api/v2/mcp/servers \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "company-knowledge-base",
    "transport": "http",
    "url": "http://internal-mcp-server:3000/mcp",
    "tools": ["documents.search", "documents.retrieve", "crm.search_contact"]
  }'

What this does: Registers an MCP server that exposes knowledge base and CRM tools. Your MoltFlow agents can now call these tools naturally.

A2A Setup (Already Available)

MoltFlow already exposes an A2A endpoint. Here's how to use it:

Discovery endpoint:

bash
curl https://apiv2.waiflow.app/.well-known/agent.json

A2A RPC endpoint:

bash
curl -X POST https://apiv2.waiflow.app/api/v2/a2a \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "message.send",
    "params": {
      "session_name": "support-bot",
      "chatId": "[email protected]",
      "text": "Agent handoff complete"
    },
    "id": 1
  }'

Response:

json
{
  "jsonrpc": "2.0",
  "result": {
    "message_id": "wamid.HBgNMTIzNDU2Nzg5MAA=",
    "status": "sent"
  },
  "id": 1
}

Combined Example: Webhook Handler Using Both Protocols

javascript
// Express webhook handler combining MCP + A2A
import express from 'express';
import { MCPClient } from '@modelcontextprotocol/sdk';
import { A2AClient } from '@a2a-protocol/client';

const app = express();
app.use(express.json());

const mcp = new MCPClient({ serverUrl: 'http://localhost:3000/mcp' });
const a2a = new A2AClient({ baseUrl: 'https://apiv2.waiflow.app' });

app.post('/webhook/moltflow', async (req, res) => {
  const { event, message, from } = req.body;

  if (event !== 'message.received') {
    return res.json({ success: true });
  }

  try {
    // Step 1: Use MCP to search knowledge base
    const kbResults = await mcp.callTool({
      name: 'documents.search',
      arguments: { query: message.text, limit: 3 }
    });

    if (kbResults.documents && kbResults.documents.length > 0) {
      // Step 2: Generate response using KB context
      const response = await generateResponse(message.text, kbResults.documents);

      // Step 3: Send via A2A
      await a2a.call({
        method: 'message.send',
        params: {
          session_name: 'support-bot',
          chatId: from,
          text: response
        }
      });
    } else {
      // Step 4: No KB results → escalate to specialist via A2A
      await a2a.call({
        agent: 'specialist-support',
        method: 'handle_escalation',
        params: {
          customer: from,
          message: message.text,
          context: 'no_kb_results'
        }
      });
    }

    res.json({ success: true });
  } catch (error) {
    console.error('Error handling webhook:', error);
    res.status(500).json({ error: error.message });
  }
});

async function generateResponse(query, documents) {
  // Use AI model to synthesize response from retrieved documents
  // (implementation depends on your AI provider)
  return `Based on our documentation: ${documents[0].content.substring(0, 200)}...`;
}

app.listen(3000, () => console.log('Webhook handler running on port 3000'));

What this demonstrates:

  • MCP for knowledge base search (data access)
  • A2A for sending messages and escalating to specialists (agent coordination)
  • Both protocols working together in a single workflow
  • Error handling for both protocol calls

What's Next?

You now understand the core distinction between MCP and A2A:

  • MCP connects your AI models to data sources (databases, APIs, files)
  • A2A connects your agents to each other (discovery, coordination, workflows)
  • Use both for robust multi-agent systems that can access data AND coordinate complex tasks

MoltFlow is the only WhatsApp platform with native A2A protocol support, giving you the infrastructure to build sophisticated agent systems.

Continue learning:

Ready to implement both protocols? Follow our step-by-step guide: REST API Quick Start

MoltFlow supports A2A protocol out of the box—start coordinating agents today.

> Try MoltFlow Free — 100 messages/month

$ curl https://molt.waiflow.app/pricing

bash-5.2$ echo "End of post."_