MCP and A2A in Marketing Software: Who Shipped What, When — and How to Wire It Up

T
Tanel Taluri
Jul 13, 2026 18 min read 11 views
MCP and A2A in Marketing Software: Who Shipped What, When — and How to Wire It Up

Two years ago, connecting an AI model to your CRM meant writing a bespoke integration. Today there are two open protocols doing that job, and almost every serious marketing platform has picked at least one of them.

MCP (Model Context Protocol) connects an agent downward to tools and data. A2A (Agent2Agent) connects agents sideways to each other. They are not competitors — a working stack usually runs both.

This post does two things: it gives you the dated adoption timeline for marketing software, and then it gets into the wire protocol — the JSON-RPC calls, the transports, the auth handshake and the discovery documents you actually need to implement against.


Part 1 — The timeline: who shipped, and when

The protocols themselves

Date Event
25 Nov 2024 Anthropic announces MCP as an open standard
9 Apr 2025 Google announces A2A at Cloud Next
23 Jun 2025 Google donates A2A to the Linux Foundation
30 Jul 2025 A2A v0.3.0 — the version most tutorials still describe
9 Dec 2025 Anthropic donates MCP to the Agentic AI Foundation (Linux Foundation), co-founded with Block and OpenAI
25 Nov 2025 MCP spec revision 2025-11-25 — the biggest change set since launch: async tasks, server-side agent loops, richer elicitation, Client ID Metadata Documents
12 Mar 2026 A2A v1.0 — first stable major version. Breaking changes throughout
28 Jul 2026 Next MCP spec revision due — the release candidate is locked, but 2025-11-25 is still the current stable spec

Neither protocol is a vendor project anymore. Both sit under the Linux Foundation, which is the single biggest reason procurement teams stopped blocking them.

Marketing software: the MCP adoption wave

The pattern is consistent. Local server first (an npm or pip package you run on your own machine), then a remote server (an HTTPS endpoint with OAuth), then write access. Most vendors are somewhere in the middle of that path.

Tool First shipped Where it is now (Jul 2026)
Shopify (Dev MCP) 31 Mar 2025 GA. Storefront MCP followed 21 May 2025; Catalog MCP opened to all developers in the Winter '26 Edition. Both migrated to the Universal Commerce Protocol (UCP) in Apr 2026 — the old Storefront cart tools were deprecated, legacy support ended 15 Jun 2026
Zapier MCP 4 Apr 2025 Remote, de-facto GA — the fastest way to reach 8,000+ apps
Ahrefs 28 Apr 2025 (@ahrefs/mcp) Remote server at api.ahrefs.com/mcp; the local repo was archived Feb 2026
HubSpot 6 May 2025 (local beta) Remote MCP GA 13 Apr 2026 at mcp.hubspot.com. Read and write on CRM objects and engagements — but marketing content (campaigns, landing pages, blog posts) stays read-only
Salesforce 23 Jun 2025 (Agentforce 3) Salesforce-hosted MCP servers GA 29 Apr 2026; Marketing Cloud Engagement MCP GA Jun 2026. Agentforce also acts as an MCP client
Google Analytics (GA4) 22 Jul 2025 Official, local only, read-only, Apache-2.0
Klaviyo 2025 GA of its enhanced MCP server 20 Aug 2025 — among the first martech MCP servers to reach GA. mcp.klaviyo.com/mcp
Braze 12 Aug 2025 Still beta, still read-only
Mixpanel 29 Aug 2025 Remote, beta
Semrush 10 Sep 2025 GA at mcp.semrush.com, requires an API subscription
Slack 1 Oct 2025 GA 17 Feb 2026 at mcp.slack.com
Google Ads 7 Oct 2025 Official, open-source, self-hosted. Read-only in the initial release — Google's wording, and it still holds
Amplitude 21 Oct 2025 Remote, public
Asana ~May 2025 V2 GA 4 Feb 2026
Adobe (Express, AEM, Analytics/CJA) Sep 2025 → Mar 2026 Express Dev MCP stable 16 Mar 2026; AEM + Analytics remote servers live
Meta Ads 29 Apr 2026 "Ads AI Connectors" open beta at mcp.facebook.com/ads — genuine read and write (campaign creation and editing, catalog management). The first major ad platform to ship write access at launch
Mailchimp 28 May 2026 Official Intuit connector for Claude and ChatGPT, following the Feb 2026 Intuit–Anthropic partnership. US, CA, UK, AU
SharksAPI.AI (that's us) 2026 Not another tool with an MCP server bolted on — an AI marketing platform built agent-first. One MCP endpoint (/mcp/{botType}) and one A2A v1.0 endpoint expose 520+ tools across 131+ integrations: GA4, Search Console, Google Ads, Meta Ads, WordPress, LinkedIn, Pipedrive and the rest of the stack above, behind a single OAuth token. Ships a signed Agent Card

And the notable gaps, because they tell you as much as the launches:

  • Google Search Console has no official MCP server. Everything you see — mcp-gsc, mcp-server-gsc and friends — is community-built. For the single most important free data source in SEO, that is a striking hole.
  • Shopify has no first-party Admin MCP. The admin story is Sidekick extensions.
  • Zendesk built an MCP client, not a server — it wants to consume your tools, not expose its own.
  • Most ad-platform MCPs are read-only by design. Google Ads, GA4 and Braze all shipped read-only first. Meta is the outlier, and that is a deliberate bet.

A2A adoption: a different crowd entirely

Here is the thing most posts get wrong. A2A adoption in marketing is not the same list.

  • Salesforce — A2A shipped with Agentforce 3 (23 Jun 2025). AgentExchange supports MCP and A2A natively.
  • ServiceNow — A2A endpoints out of the box via AI Agent Fabric.
  • SAP — Joule's A2A toolkit went bidirectional in Joule Studio 2.0.
  • Adobe — Agent Orchestrator (GA Sep 2025) is explicitly built on MCP + A2A.
  • SharksAPI.AI (disclosure: this is our platform) — A2A v1.0 at /a2a, MCP at /mcp/{botType}, and a signed Agent Card (JWS ES256, verifiable against /.well-known/jwks.json). The rare mid-market martech platform that ships both.
  • Not present: HubSpot, Klaviyo, Braze, Semrush, Ahrefs, Shopify.

The split is clean: A2A is an enterprise-suite story. MCP is the everyone-else story. If you are a mid-market marketing team, you will consume A2A far more often than you will publish it — and you will publish MCP servers long before you publish an Agent Card.

As of April 2026 the Linux Foundation counted 150+ organisations supporting A2A, with SDKs in five languages.


Part 2 — MCP, technically

The shape of it

MCP is JSON-RPC 2.0 with a defined vocabulary. A host (Claude, ChatGPT, Cursor, your own agent runtime) spawns one client per server, and each client holds a 1:1 stateful session.

Servers expose three primitives:

  • Tools — model-invoked functions (get_campaign_metrics, update_bid)
  • Resources — application-controlled context, addressed by URI (ga4://property/123/report/weekly)
  • Prompts — user-selected templates

Clients can expose three back to the server:

  • Sampling — the server asks the host to run an LLM completion
  • Elicitation — the server asks the user a question mid-tool-call
  • Roots — filesystem or URI boundaries the server is allowed to touch

Most marketing MCP servers only implement tools. That is fine, and it is the reason "MCP is just a wrapper around your REST API" is a half-truth — it is a self-describing, capability-negotiated, auth-aware wrapper, which is the part that matters.

Transports

There are exactly two you need to care about:

  1. stdio — the server is a subprocess. Newline-delimited JSON-RPC over stdin/stdout. This is how the GA4 and Google Ads servers run.
  2. Streamable HTTP — a single HTTP endpoint that accepts POST for requests and can upgrade to Server-Sent Events for server→client streaming. This replaced the old HTTP+SSE dual-endpoint transport. Every remote server (HubSpot, Semrush, Klaviyo, Slack) uses this.

The handshake

// → client to server
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": { "sampling": {}, "elicitation": {} },
    "clientInfo": { "name": "sharksapi-agent", "version": "2.4.0" }
  }
}
// ← server to client
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-11-25",
    "capabilities": { "tools": { "listChanged": true }, "resources": {} },
    "serverInfo": { "name": "semrush", "version": "2.1.0" }
  }
}

Then notifications/initialized, then discovery:

{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }

The server returns each tool with a JSON Schema for its inputs. That schema is what the model reads. If your description field is vague, the model will call the tool wrongly — tool descriptions are prompt engineering, not documentation.

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "domain_organic_search_keywords",
    "arguments": {
      "domain": "example.ee",
      "database": "ee",
      "limit": 100,
      "sort_by": "traffic_desc"
    }
  }
}

The result comes back as typed content blocks (text, image, resource) plus an optional structuredContent object validated against the tool's outputSchema. Always read structuredContent if it is present — parsing the human-readable text block is how integrations break on the next release.

Authorization — the part everyone gets wrong

For remote servers, MCP defines the server as an OAuth 2.1 Resource Server. It does not issue tokens; it validates them. The flow:

  1. Client calls the MCP endpoint with no token → server returns 401 with a WWW-Authenticate header pointing at its Protected Resource Metadata (RFC 9728):
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"
  1. Client fetches that document, learns which authorization server to talk to.
  2. Client discovers the auth server's endpoints (OAuth 2.0 AS metadata or OIDC — the 2025-11-25 spec requires at least one).
  3. Client runs Authorization Code + PKCE, and — critically — includes an RFC 8707 resource indicator so the issued token is audience-bound to this MCP server only.
  4. Client retries with Authorization: Bearer ….

That resource indicator is not optional pedantry. Without audience binding, a token minted for one MCP server can be replayed against another — the exact class of confused-deputy bug that produced several one-click account-takeover write-ups in 2025. If you are building a server, reject tokens whose audience is not you.

Where vendors deviate: Semrush accepts OAuth or a static key via Authorization: Apikey YOUR_KEY for clients that cannot do OAuth. Convenient; strictly worse. Prefer OAuth where you have the choice.

Connecting a marketing stack — a real config

{
  "mcpServers": {
    "hubspot": {
      "type": "http",
      "url": "https://mcp.hubspot.com"
    },
    "semrush": {
      "type": "http",
      "url": "https://mcp.semrush.com/v2/mcp"
    },
    "klaviyo": {
      "type": "http",
      "url": "https://mcp.klaviyo.com/mcp?company=acme-retail"
    },
    "ahrefs": {
      "type": "http",
      "url": "https://api.ahrefs.com/mcp"
    },
    "ga4": {
      "command": "pipx",
      "args": ["run", "--spec", "google-analytics-mcp", "ga4-mcp-server"],
      "env": { "GOOGLE_APPLICATION_CREDENTIALS": "/secrets/ga4-sa.json" }
    }
  }
}

Or, from the CLI:

claude mcp add --transport http hubspot https://mcp.hubspot.com
claude mcp add --transport http semrush https://mcp.semrush.com/v2/mcp

The remote ones will open a browser for OAuth on first use. The local one uses a service-account key file, because Google's GA4 server predates the remote-MCP pattern.

One hard-won warning: every tool from every connected server lands in the model's context window. Five marketing MCP servers can easily mean 150+ tool definitions and tens of thousands of tokens before the user has typed anything. Scope aggressively — enable the servers a given agent actually needs, not your whole stack. This is the single most common cause of "the agent got dumber after we added integrations".

Writing your own server

Three tools, cleanly described, beats forty auto-generated ones:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("acme-ads")

@mcp.tool()
def campaign_performance(campaign_id: str, days: int = 30) -> dict:
    """Return spend, impressions, clicks, conversions and ROAS for one campaign
    over the last N days. Use this before recommending any budget change."""
    return acme_api.get(f"/campaigns/{campaign_id}/stats", days=days)

if __name__ == "__main__":
    mcp.run(transport="stdio")

The docstring is the tool description the model sees. Write it as an instruction to the model, including when not to call it.


Part 3 — A2A, technically (and what changed in v1.0)

MCP gives an agent hands. A2A gives it colleagues. Where MCP calls a function, A2A delegates a task to another opaque agent — one you do not control, whose internal tools and prompts you cannot see, and which may take minutes or hours to answer.

Discovery: the Agent Card

Every A2A agent publishes a JSON document at:

https://agent.example.com/.well-known/agent-card.json
{
  "name": "SharksAPI SEO Agent",
  "description": "Audits technical SEO, tracks rankings and drafts optimisation tasks.",
  "provider": { "organization": "SharksAPI.AI", "url": "https://sharksapi.ai" },
  "version": "2.1.0",
  "supportedInterfaces": [
    {
      "url": "https://api.sharksapi.ai/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    },
    {
      "url": "https://api.sharksapi.ai/a2a/grpc",
      "protocolBinding": "GRPC",
      "protocolVersion": "1.0"
    }
  ],
  "capabilities": {
    "streaming": true,
    "pushNotifications": true,
    "extendedAgentCard": true
  },
  "securitySchemes": {
    "oauth2": {
      "type": "oauth2",
      "flows": {
        "clientCredentials": {
          "tokenUrl": "https://sharksapi.ai/oauth/token",
          "scopes": { "seo:read": "Read audits", "seo:write": "Create tasks" }
        }
      }
    }
  },
  "security": [{ "oauth2": ["seo:read"] }],
  "defaultInputModes": ["text/plain", "application/json"],
  "defaultOutputModes": ["text/plain", "application/json"],
  "skills": [
    {
      "id": "technical-audit",
      "name": "Technical SEO audit",
      "description": "Crawls a domain and returns prioritised technical issues.",
      "tags": ["seo", "audit", "crawl"],
      "examples": ["Audit example.ee and list the top 10 crawl blockers"]
    }
  ]
}

Cards can be signed — v1.0 formalises this as JWS (RFC 7515) over an RFC 8785 canonicalisation of the card. If you are going to let an agent delegate money-spending work to another agent, verify the signature.

The v0.3 → v1.0 breaking changes

If you built against A2A in 2025, this list is your migration plan:

v0.3.0 v1.0
message/send SendMessage
message/stream SendStreamingMessage
tasks/get GetTask
tasks/cancel CancelTask
tasks/resubscribe SubscribeToTask
agent/getAuthenticatedExtendedCard GetExtendedAgentCard
ListTasks (new, cursor-paginated)
preferredTransport + additionalInterfaces supportedInterfaces[]
protocolVersion on the card per-interface protocolVersion
kind discriminator fields removed — discriminate on JSON member names
kebab-case enums (input-required) SCREAMING_SNAKE_CASE (TASK_STATE_INPUT_REQUIRED)
compound IDs (tasks/{id}/…) flat UUIDs
POST /v1/message:send POST /message:send (no /v1 prefix)
implicit + password OAuth flows removed; Device Code (RFC 8628) added; pkce_required added

Also new in v1.0: a tenant field on every request (multi-tenancy without URL gymnastics), and a mandatory version header:

POST /a2a HTTP/1.1
Host: api.sharksapi.ai
A2A-Version: 1.0
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

An empty A2A-Version header is interpreted as 0.3. If you forget it, you silently get old semantics. Send it.

Delegating a task

{
  "jsonrpc": "2.0",
  "id": "req-01",
  "method": "SendMessage",
  "params": {
    "message": {
      "role": "user",
      "messageId": "c1f9a2e0-6b34-4f1a-9a7e-2f0d3b8c4a11",
      "parts": [
        { "text": "Audit example.ee and return the top 10 crawl blockers." }
      ]
    },
    "configuration": {
      "returnImmediately": true,
      "acceptedOutputModes": ["application/json"]
    }
  }
}

With returnImmediately: true you get a Task back straight away, in TASK_STATE_SUBMITTED or TASK_STATE_WORKING, and you then poll GetTask, open a SubscribeToTask SSE stream, or register a webhook via CreateTaskPushNotificationConfig. With it unset (the default), the call blocks until the task reaches a terminal or interrupted state.

Task lifecycle

TASK_STATE_SUBMITTED
        ↓
TASK_STATE_WORKING ⇄ TASK_STATE_INPUT_REQUIRED   (interrupted — needs a human or more data)
        │           ⇄ TASK_STATE_AUTH_REQUIRED    (interrupted — needs credentials)
        ↓
TASK_STATE_COMPLETED | TASK_STATE_FAILED | TASK_STATE_CANCELED | TASK_STATE_REJECTED
                                (all terminal)

Terminal tasks reject further messages with UnsupportedOperationError. Streams close when a terminal state is reached. TASK_STATE_REJECTED is the agent saying "I won't do this" — which is a legitimate, and underused, answer.

Outputs come back as Artifacts (the deliverable) rather than Messages (the conversation). That distinction is deliberate: the artifact is what you store; the messages are how you got there.


MCP vs A2A: which one, when

MCP A2A
Connects agent → tools & data agent → agent
The other side is a function you call a peer you delegate to
Unit of work tool call (fast, synchronous) task (long-running, stateful)
Discovery tools/list after initialize /.well-known/agent-card.json
Transport stdio, Streamable HTTP JSON-RPC, gRPC, HTTP+JSON/REST
Auth OAuth 2.1 RS + RFC 9728 + RFC 8707 OAuth 2.x / mTLS declared in the card
Governance Agentic AI Foundation (LF) Linux Foundation
Martech adoption broad — HubSpot, Semrush, Klaviyo, Ahrefs, Shopify, Meta narrow — Salesforce, SAP, ServiceNow, Adobe

The rule of thumb: if the other side is a capability you fully control the semantics of, use MCP. If it is an actor with its own judgement, its own model and its own runtime, use A2A. A marketing agent that reads Semrush over MCP, decides on a content brief, and hands that brief to a separate copywriting agent over A2A is the canonical shape.

We go deeper on the trade-offs in MCP vs REST vs GraphQL and the A2A Protocol Deep Dive.


Security: five things to fix before you go live

  1. Audience-bind every token. RFC 8707 resource indicators, and servers that reject tokens issued for anyone else. This is the whole ballgame.
  2. Treat tool output as untrusted input. A campaign name, a support ticket, a product description — any of them can carry a prompt injection. Data returned by a tool must never be executed as an instruction.
  3. Read-only until proven otherwise. There is a reason Google Ads, GA4 and Braze all shipped read-only first. Write scopes (HubSpot, Meta Ads) need a human approval gate on anything that spends money.
  4. Verify Agent Card signatures before delegating over A2A, and pin the provider.
  5. Scope tool exposure per agent. Not per organisation. See the context-window warning above — this is a quality issue as much as a security one.

What to do this quarter

  • Audit what you already have. If you use HubSpot, Semrush, Klaviyo, Shopify or Slack, you have official MCP servers sitting unused. Cost of connecting: minutes.
  • Fill the gaps with your own servers. Search Console still has no first-party option, and neither does most of your internal data — a 100-line FastMCP wrapper around an API you already call is a weekend's work.
  • Do not write an Agent Card yet unless you sell an agent. Consume A2A; publish MCP.
  • Pin your spec versions. MCP's next revision lands 28 July 2026. A2A v1.0 broke almost everything from v0.3. Version negotiation is not decoration.

SharksAPI.AI exposes 520+ MCP tools across 131+ integrations, with OAuth 2.0 client-credentials agent self-registration, an A2A v1.0 endpoint, and a signed Agent Card you can verify before you trust it. If you would rather not maintain twelve MCP servers yourself, see how agent access works.


FAQ

What is the difference between MCP and an API?
An API is a contract for developers; MCP is a contract for models. The endpoints may be identical, but MCP adds runtime capability discovery (tools/list), machine-readable JSON Schema for every input and output, a standard OAuth 2.1 authorization flow, and a session lifecycle. You are not replacing your REST API — you are putting a self-describing, model-legible surface in front of it.

Which marketing tools have an official MCP server?
As of July 2026: HubSpot, Salesforce (including Marketing Cloud Engagement), Semrush, Ahrefs, Klaviyo, Braze, Shopify, Google Analytics 4, Google Ads, Meta Ads, Mailchimp, Slack, Asana, Amplitude, Mixpanel, Canva, Figma, Adobe (Express/AEM/Analytics), Stripe, Zapier, Make, n8n and Notion. Google Search Console notably does not — every GSC server you will find is community-built.

Is A2A a replacement for MCP?
No, and they were never competing. A2A explicitly positions MCP as complementary: MCP is how an agent reaches its tools, A2A is how agents reach each other. Google's own AP2 payments protocol is built as an extension of both.

What version of A2A should I build against?
v1.0 (released 12 March 2026, patch v1.0.1 in May 2026). Anything describing message/send, preferredTransport or kebab-case task states is documenting v0.3 and is now out of date. Always send the A2A-Version: 1.0 header — an empty header is interpreted as 0.3.

Can an AI agent change my ad campaigns?
Only if you let it. Most ad-platform MCP servers — Google Ads, GA4, Braze — shipped deliberately read-only. Meta's Ads AI Connectors (open beta since 29 April 2026) are the notable exception, with real write access to campaigns and catalogs, and HubSpot's remote server added CRM write scopes at GA in April 2026. Anything that spends money should sit behind a human approval step regardless of what the protocol permits.

Where does the .well-known Agent Card live?
At https://your-domain/.well-known/agent-card.json. In A2A v1.0 the card lists supportedInterfaces[], each with its own url, protocolBinding (JSONRPC, GRPC or HTTP+JSON) and protocolVersion — the old top-level preferredTransport and protocolVersion fields are gone.


Sources: Anthropic — Introducing MCP · MCP joins the Agentic AI Foundation · MCP Specification 2025-11-25 — Authorization · MCP 2026-07-28 Release Candidate · A2A Specification v1.0 · A2A — What's New in v1.0 · A2A GitHub releases · Linux Foundation — A2A project launch · HubSpot — Remote MCP server is now GA · Salesforce — Hosted MCP servers now GA · Semrush MCP docs · Klaviyo MCP server · Ahrefs MCP docs · Google Analytics MCP · Google Ads MCP server · Meta Ads AI Connectors · Shopify — UCP Cart MCP changelog · Intuit Mailchimp — AI and data integrations

Related Posts