MCP vs A2A vs Agentic Resource Discovery: what AI developers need to know
MCP connects agents to tools, A2A connects agents to other agents, and ARD helps agents find and verify both. What each does, their status in 2026 and how they fit.
Updated 15 min read

In this article
MCP, A2A and Agentic Resource Discovery (ARD) are not three competing standards. Each answers a different question. MCP is how your agent uses a tool or reads data. A2A is how your agent hands a task to another agent, usually one run by someone else. ARD is how an agent finds a tool or agent it has never seen and checks who publishes it. Most teams need MCP now, A2A when they work with agents outside their own codebase, and ARD only once they publish or consume capabilities at scale. This guide explains each one as it stands in October 2026, shows how they connect, and includes a tested discovery client.
Tested with: Node.js 24.19.0 (built-in fetch, no dependencies), against the ARD v0.91 proposal (26 August 2026), A2A specification 1.0 and MCP specification revision 2026-07-28.
The short version
| MCP | A2A | ARD | |
|---|---|---|---|
| Connects | An AI application to tools, resources and prompts | One agent to another agent | An agent or developer to a catalogue or registry of capabilities |
| Core objects | Tools, resources, prompts | Agent Card, tasks, messages, artifacts | Catalogue entries with a urn:air: identifier |
| Where you find it | Client configuration; server cards are a draft proposal | /.well-known/agent-card.json | /.well-known/ard.json or a registry's POST /search |
| Status | Revision 2026-07-28 | 1.0 (March 2026), 1.0.1 (May 2026) | v0.91, status "Proposal" |
| Governance | Agentic AI Foundation (Linux Foundation) | Agentic AI Foundation since August 2026 | Apache 2.0 spec from Google, Microsoft, Hugging Face and partners |

MCP: your agent and its tools
The Model Context Protocol standardises the connection between an AI application (the host and its client) and a server that exposes tools, resources and prompts. When a support assistant looks up an order in your database or creates a ticket in your help desk, that call is the job MCP was built for. The current revision, dated 2026-07-28, removed the initialize handshake and protocol-level sessions and added server/discover; we covered that change in MCP 2026-07-28 explained, so it is not repeated here.
What matters for this comparison is the shape of the relationship. MCP assumes your application chose to connect to the server: someone configured it, approved it and decided which tools the model may call. The server does not plan or own a goal. It executes one well-defined operation and returns a result. That is why MCP works best inside a trust boundary you control, and why the hard problems are approval and least privilege, covered in MCP security in 2026.
MCP does not have a finished answer to discovery. Server cards, static JSON documents describing a server before you connect, are being developed as SEP-2127 and are still a proposal, with the well-known path not yet fixed. Treat any /.well-known/mcp/... path you see in tools as provisional.
A2A: handing a task to another agent
Agent2Agent (A2A) covers a different relationship: two agents, each with its own model, tools and policies, often run by different companies. One agent delegates a task, and the other works on it, perhaps for minutes, asks for more input, and returns artifacts. Google launched A2A in April 2025 and donated it to the Linux Foundation in June 2025. Version 1.0.0 was tagged in March 2026 and 1.0.1 in May 2026. On 17 August 2026 the Agentic AI Foundation announced that A2A had joined it as a hosted project, alongside MCP, goose, AGENTS.md and agentgateway. The AAIF is hosted by the Linux Foundation, so "A2A is a Linux Foundation project" is accurate, with the detail that its home is now the AAIF.
The pieces you will meet in A2A 1.0:
- Agent Card, published at
https://{domain}/.well-known/agent-card.json. Required fields includename,description,version,supportedInterfaces,capabilities,defaultInputModes,defaultOutputModesandskills. Cards may be signed with JSON Web Signature, using RFC 8785 canonicalisation. - Protocol bindings: JSON-RPC, gRPC and HTTP+JSON, which must be functionally equivalent.
- Operations such as
SendMessage,SendStreamingMessage,GetTask,ListTasks,CancelTaskandSubscribeToTask. - Task states including
TASK_STATE_WORKING,TASK_STATE_INPUT_REQUIRED,TASK_STATE_AUTH_REQUIREDand the terminalCOMPLETED,FAILED,CANCELEDandREJECTED. - Authentication declared in the card through
securitySchemes: API key, HTTP auth, OAuth 2.0, OpenID Connect or mutual TLS. A2A does not invent its own identity system.
Here is a minimal Agent Card for an invoice-checking agent. Field names follow the 1.0 protobuf definition in JSON form:
{
"name": "Invoice Triage Agent",
"description": "Checks supplier invoices against purchase orders and flags mismatches for a human to approve.",
"version": "1.2.0",
"provider": { "organization": "Example Ltd", "url": "https://example.com" },
"supportedInterfaces": [
{ "url": "https://agents.example.com/a2a/v1", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" }
],
"capabilities": { "streaming": true, "pushNotifications": false },
"securitySchemes": {
"bearer": { "httpAuthSecurityScheme": { "scheme": "Bearer", "bearerFormat": "JWT" } }
},
"securityRequirements": [{ "schemes": { "bearer": { "list": [] } } }],
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["application/json"],
"skills": [
{
"id": "triage-invoice",
"name": "Triage a supplier invoice",
"description": "Compares an invoice with its purchase order and returns matched, mismatched or needs-review.",
"tags": ["finance", "invoices"],
"examples": ["Check invoice INV-2291 against PO-7710"]
}
]
}A JSON-RPC call to that agent then looks like this. The A2A-Version header lets the server reject versions it does not support with a VersionNotSupportedError:
POST /a2a/v1 HTTP/1.1
Host: agents.example.com
Authorization: Bearer <token from your identity provider>
A2A-Version: 1.0
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "SendMessage",
"params": {
"message": {
"role": "ROLE_USER",
"messageId": "6f1c2a90-4d1e-4c55-9a51-0b7f4c1d2e33",
"parts": [{ "text": "Check invoice INV-2291 against PO-7710" }]
}
}
}The difference from MCP is ownership of the work. With MCP your model decides each step and the server executes it. With A2A the remote agent decides how to do the task, and you only see its messages, status and artifacts. That opacity is deliberate, since the other party's prompts and tools are its business, and it is also why A2A needs stronger contracts: authentication, task limits and a clear statement of what the remote agent is allowed to do on your behalf.
ARD: finding and checking capabilities
Agentic Resource Discovery is the newest of the three. Google announced it on 17 June 2026, the same day as Microsoft's post, which lists Cisco, Databricks, GitHub, GoDaddy, Google, Hugging Face, Nvidia, Salesforce, ServiceNow and Snowflake as partners. The specification is Apache 2.0, version v0.91, status "Proposal", dated 26 August 2026, with authors from Google, Microsoft and Hugging Face. It builds on the data model of the Linux Foundation's AI Catalog Working Group. ARD itself is not, at the time of writing, a project of the AAIF or the Linux Foundation, and it is not a final standard.
ARD does not execute anything. It describes where an MCP server, A2A agent, skill or API lives, who publishes it, and how to reach it, then "steps out of the way" so the client connects with the resource's own protocol. Its main parts:
- A catalogue file at
/.well-known/ard.jsonwith anentriesarray. The earlier name,/.well-known/ai-catalog.json, is now the predecessor path, and v0.91 tells publishers to move toard.json. Some June coverage still shows the old name. - Entries with a required
identifierin the formurn:air:<publisher>:<namespace>:<name>, where the publisher is a fully qualified domain name, plusdisplayName, a mediatypesuch asapplication/a2a-agent-card+jsonorapplication/mcp-server-card+json, and exactly one ofurlordata. Two to fiverepresentativeQueriesare recommended. - Registries that crawl catalogues and expose
POST /search(required),POST /exploreandGET /agents(optional). Search can federate across registries inauto,referralsornonemode. - Trust: domain ownership is the root of identity. If an entry carries
trustManifest.identity, that trust domain must align with the publisher in the URN, which is ARD's defence against namespace squatting. ARD does not define signatures itself; it defers to the trust framework the manifest names.
GitHub's Agent Finder for Copilot and Hugging Face's Discover Tool were announced as early implementations. A catalogue for the example company above is short:
{
"entries": [
{
"identifier": "urn:air:example.com:finance:invoice-triage",
"displayName": "Invoice Triage Agent",
"type": "application/a2a-agent-card+json",
"url": "https://agents.example.com/.well-known/agent-card.json",
"description": "Checks supplier invoices against purchase orders and flags mismatches.",
"capabilities": ["InvoiceTriage"],
"representativeQueries": [
"check this supplier invoice against its purchase order",
"which invoices from last week do not match a PO"
],
"trustManifest": { "identity": "example.com" }
},
{
"identifier": "urn:air:example.com:catalogue:product-search",
"displayName": "Product Catalogue MCP Server",
"type": "application/mcp-server-card+json",
"url": "https://api.example.com/mcp/server-card",
"capabilities": ["ProductSearch"],
"representativeQueries": [
"find products under 50 dollars in the garden category",
"is SKU 4471 in stock"
]
}
]
}A tested discovery client
To see how the pieces connect, we wrote a small client that fetches an ARD catalogue, applies the rules above, and then checks the A2A Agent Card that one entry points to. It has no dependencies. We served a test catalogue from a local Node.js server on 127.0.0.1:4710, with the two valid entries shown above plus two deliberately broken ones: a partner entry whose trustManifest.identity names a different domain from its URN publisher, and an old entry with no URN and no url.
// Fetch an ARD catalogue, check each entry, then fetch and check an A2A Agent Card.
// Usage: node discover.mjs <origin> [claimed-domain]
const origin = process.argv[2] ?? 'https://example.com';
const domain = process.argv[3] ?? new URL(origin).hostname; // the domain we believe we are talking to
const URN = /^urn:air:([a-z0-9.-]+\.[a-z]{2,}):([a-z0-9-]+):([a-z0-9-]+)$/i;
const KNOWN_TYPES = new Set(['application/a2a-agent-card+json', 'application/mcp-server-card+json']);
async function getJson(url) {
const res = await fetch(url, { headers: { accept: 'application/json' }, signal: AbortSignal.timeout(5000), redirect: 'error' });
if (!res.ok) throw new Error(`${url} -> HTTP ${res.status}`);
return res.json();
}
export function checkEntry(entry, domain) {
const problems = [];
for (const field of ['identifier', 'displayName', 'type']) if (!entry[field]) problems.push(`missing ${field}`);
if (('url' in entry) === ('data' in entry)) problems.push('needs exactly one of url or data');
const urn = URN.exec(entry.identifier ?? '');
if (!urn) problems.push('identifier is not urn:air:<publisher>:<namespace>:<name>');
const publisher = urn?.[1].toLowerCase();
if (publisher && entry.trustManifest?.identity && entry.trustManifest.identity.toLowerCase() !== publisher)
problems.push(`trustManifest.identity ${entry.trustManifest.identity} does not match publisher ${publisher}`);
const n = entry.representativeQueries?.length ?? 0;
const warnings = n < 2 || n > 5 ? [`${n} representativeQueries (spec suggests 2 to 5)`] : [];
if (entry.type && !KNOWN_TYPES.has(entry.type)) warnings.push(`unknown type ${entry.type}`);
if (publisher && publisher !== domain && !publisher.endsWith(`.${domain}`))
warnings.push(`published by ${publisher}, not ${domain}: verify it separately`);
return { ok: problems.length === 0, problems, warnings };
}
export function checkAgentCard(card) {
const required = ['name', 'description', 'version', 'supportedInterfaces', 'capabilities', 'defaultInputModes', 'defaultOutputModes', 'skills'];
const problems = required.filter((f) => card[f] === undefined).map((f) => `missing ${f}`);
for (const i of card.supportedInterfaces ?? []) {
if (!['JSONRPC', 'GRPC', 'HTTP+JSON'].includes(i.protocolBinding)) problems.push(`unexpected binding ${i.protocolBinding}`);
if (i.url?.startsWith('http:')) problems.push(`plain HTTP interface ${i.url}`);
}
if (!card.securitySchemes || Object.keys(card.securitySchemes).length === 0) problems.push('no securitySchemes declared');
return problems;
}
const catalogue = await getJson(new URL('/.well-known/ard.json', origin));
console.log(`ARD catalogue from ${origin} (claimed domain ${domain}): ${catalogue.entries?.length ?? 0} entries\n`);
const usable = [];
for (const entry of catalogue.entries ?? []) {
const { ok, problems, warnings } = checkEntry(entry, domain);
console.log(`${ok ? 'OK ' : 'SKIP'} ${entry.displayName ?? '(no name)'} [${entry.type ?? '?'}]`);
for (const p of problems) console.log(` error: ${p}`);
for (const w of warnings) console.log(` warn: ${w}`);
if (ok) usable.push(entry);
}
// In production you would fetch entry.url; locally we read the card from the test server.
const card = await getJson(new URL('/.well-known/agent-card.json', origin));
const cardProblems = checkAgentCard(card);
console.log(`\nA2A Agent Card "${card.name}" v${card.version}: ${cardProblems.length ? cardProblems.join('; ') : 'valid'}`);
console.log(` interfaces: ${card.supportedInterfaces.map((i) => `${i.protocolBinding} ${i.url} (A2A ${i.protocolVersion})`).join(', ')}`);
console.log(` skills: ${card.skills.map((s) => s.id).join(', ')}`);
console.log(`\n${usable.length} of ${catalogue.entries.length} entries usable; connect with each artefact's own protocol and auth.`);Running node discover.mjs http://127.0.0.1:4710 example.com skipped both broken entries for the right reasons and accepted the Agent Card:

Two details in the code are deliberate. First, a catalogue on example.com may list a resource published by another domain. ARD does not forbid that, so the client warns instead of rejecting, and you verify the other publisher separately. Second, the client refuses redirects and uses a five-second timeout, because a discovery client fetches URLs that strangers control.
How they fit together in one flow
Take an accounts-payable agent at a retailer. It needs to check supplier invoices, and one supplier offers an invoice-reconciliation agent.
- Find (ARD). The agent, or more often the developer building it, searches a registry for "reconcile supplier invoice against PO" and gets back an entry for
urn:air:example.com:finance:invoice-triage. The client checks the publisher domain and any trust manifest before going further. - Delegate (A2A). It fetches the Agent Card, authenticates with the scheme the card declares, and sends a
SendMessagewith the invoice. The remote agent works on the task and may move toTASK_STATE_INPUT_REQUIREDif a PO number is missing. - Act (MCP). When the result comes back, your agent uses its own MCP servers to update your ERP, post a note in your help desk or create an approval request. The remote agent never touches those systems.
Each layer has a narrow job. Discovery tells you what exists and who stands behind it. A2A moves work between parties that do not share code. MCP gives your own agent hands inside your own systems.
When to use each, and when not to
Use MCP when
- Your agent needs to call your own APIs, databases or SaaS accounts.
- You want the same tools available in several AI clients (an IDE assistant, a chat app, your own agent).
Do not use MCP to wrap another company's autonomous agent as if it were a tool. You lose task state, progress and the ability to answer its follow-up questions properly.
Use A2A when
- The other side is an agent with its own reasoning and long-running work, especially one run by a partner or supplier.
- You need task lifecycle, streaming updates and push notifications across organisational boundaries.
Do not use A2A between components of your own application. Inside one codebase a function call, a queue or an MCP tool is simpler, cheaper and easier to debug. Two agents in the same process do not need a network protocol.
Use ARD when
- You publish agents or MCP servers that other organisations should be able to find, or you run an internal registry for many teams.
- Your agent has too many possible tools to load into its context, and search is the better selection method.
Do not let an agent discover and connect to arbitrary resources at runtime without a human or a policy approving the publisher first. A search hit is not an endorsement: the spec states that a registry's relevance score "MUST NOT be interpreted as a trust, compliance, or safety judgment". For most small teams in 2026, a hand-curated allowlist beats open discovery.
Security: what each layer does and does not give you
The three protocols divide security work, and the gaps between them are where problems occur.
- ARD gives you identity, not safety. A valid URN and a matching domain prove who published an entry. They say nothing about whether the agent behind it is competent, honest or secure. Keep an allowlist of publishers and re-check catalogues on a schedule, since a domain can change hands.
- A2A gives you authenticated delegation, not trustworthy output. Everything a remote agent returns is untrusted input to your model, exactly like a web page. Text in an artifact can carry instructions aimed at your agent. The patterns in our prompt injection design guide apply, especially keeping untrusted content away from tools that can send data out.
- Signed Agent Cards help with tampering, not intent. Verify signatures where they are present, but a signed card from a careless publisher is still a careless publisher.
- MCP gives you the most control and the most risk. It is where your credentials and data live. Scope tokens per server, require approval for writes, and log every tool call.
- Never pass your users' tokens through. When you delegate a task over A2A, authenticate as your service with the scopes the remote agent needs for that task, not with an end user's session.
Connecting your systems to partner agents is where a design mistake turns into a data leak, so it is worth a second opinion. Our API development and integration work includes publishing and consuming MCP servers and A2A endpoints with scoped authentication and audit logs.

Common mistakes
- Treating the three as alternatives. Teams ask "MCP or A2A?" when the honest answer is usually MCP inside, A2A across boundaries, and ARD only at scale.
- Building on the old ARD file name. New catalogues should use
/.well-known/ard.json. Readai-catalog.jsononly as a fallback. - Hard-coding draft paths. MCP server cards and ARD are both pre-1.0 drafts. Put paths and media types in configuration, not code.
- Trusting search ranking. A high
scoremeans relevant, nothing more. - Using A2A 0.3-era examples. Much published sample code predates 1.0. Method names such as
message/sendcome from older versions; 1.0 usesSendMessage, and the Agent Card moved tosupportedInterfaces. - Skipping version negotiation. Send
A2A-Versionand handleVersionNotSupportedError, rather than assuming every partner runs the same release.
What to do next
If you are starting out, build MCP servers for your own systems first and get approval and logging right. Add A2A when a partner or supplier offers an agent you need to work with, and treat its output as untrusted. Publish an ard.json when you have capabilities that outsiders should find, but keep it out of any runtime path that connects automatically until the specification passes its proposal stage.
Need your APIs exposed safely to AI agents, or a partner's agent connected to your systems? Cloudsoft Zone builds API and agent integrations with scoped access, approval steps and audit trails.
Frequently asked questions
Is A2A a replacement for MCP?
No. MCP connects an AI application to tools and data it controls. A2A lets one agent delegate a task to another agent with its own reasoning, often at another company. Many systems use both: A2A between organisations, MCP inside each one.
Who publishes Agentic Resource Discovery?
ARD was announced on 17 June 2026 by Google and Microsoft with partners including Cisco, Databricks, GitHub, GoDaddy, Hugging Face, Nvidia, Salesforce, ServiceNow and Snowflake. The specification is Apache 2.0 licensed, at version v0.91 with status "Proposal" (26 August 2026), and builds on the Linux Foundation AI Catalog Working Group data model.
Is A2A part of the Linux Foundation?
Yes. Google donated A2A to the Linux Foundation in June 2025, and on 17 August 2026 it joined the Agentic AI Foundation, the Linux Foundation-hosted home that also hosts MCP.
Where do I publish an ARD catalogue?
At
/.well-known/ard.jsonon your domain, with anentriesarray. The older/.well-known/ai-catalog.jsonpath is treated as a predecessor that consumers may read but publishers should move away from.Does ARD make a discovered agent safe to use?
No. ARD ties an entry to the domain that published it and lets registries rank results by relevance. It does not judge quality or safety, and the spec says scores must not be read as trust ratings. Approve publishers yourself and treat everything a remote agent returns as untrusted input.
Your next customer could start right here.
Introduce your tool, product or business to readers exploring technology.
Explore placements and request a private quote
Sources
- ARD Specification v0.91 — AgenticResourceDiscovery.org, 2026-08-26
- Announcing the Agentic Resource Discovery specification — Google Developers Blog, 2026-06-17
- Introducing the Agentic Resource Discovery specification — Microsoft, 2026-06-17
- A2A Protocol Specification (latest, 1.0) — A2A Project
- A2A joins the Agentic AI Foundation — Agentic AI Foundation, 2026-08-17
- A2A releases (v1.0.0, v1.0.1) — A2A Project on GitHub, 2026-05-28
- MCP specification 2026-07-28: key changes — Model Context Protocol, 2026-07-28
- SEP-2127: MCP Server Cards — Model Context Protocol
Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.
Comments
No comments yet. Be the first to join the conversation.
Leave a comment
Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.
More from Cloudsoft Zone

Architecture guideAI and Automation
How to build a safe AI content pipeline with human fact review
An architecture for AI-assisted publishing where people stay responsible: untrusted source snapshots, claim checking with citations, a review queue AI cannot skip, labels and rollback.
By Cloudsoft Zone

TutorialNode.js
How to test a Node.js API with the built-in test runner (node:test)
Write, run, mock and measure coverage for a small Node.js HTTP API using only node:test and node:assert. Covers port-0 servers, fetch(), spies, t.mock.method(), fake dates and coverage thresholds.
By Cloudsoft Zone

TutorialNode.js
Node.js streams in practice: pipeline(), backpressure and async generators
Process files of any size in Node.js with flat memory use. A hands-on guide to stream/promises pipeline(), backpressure, async generator transforms, AbortSignal timeouts and streaming downloads over HTTP.
By Cloudsoft Zone
