I Shipped Agentic Resource Discovery on This Site (And a Client Found Me)
Google and 10 others shipped Agentic Resource Discovery. I added an ai-catalog.json to this site, validated it against the official tool, and a reference client discovered my capabilities. Here is the build and the Cloudflare catch.
On 17 June 2026, Google and 10 other companies published Agentic Resource Discovery, a spec for how AI agents find tools, agents, and APIs across the web.
Within 2 days I had it running on this site.
Then I pointed the official Hugging Face client at my domain, and it read my own capabilities straight back to me.
It works.
The catch is what happens when a slightly different client tries the same fetch, and Cloudflare decides it does not like the look of it.
Here is the whole build, the proof it runs, and the part nobody is talking about yet.
ARD in a minute, and why it is not your api-catalog
Agentic Resource Discovery has 2 halves.
You publish a static ai-catalog.json at a well-known path. It lists what your site offers an agent, an MCP server, an A2A agent, an API, even a nested catalog, and points at each one. Then registries crawl those catalogs and answer natural-language queries, so an agent can ask “who can do X” and get a ranked answer.
The first half is a file you write. The second half is the agentic web’s version of a search engine, and it is the genuinely new part. The draft has 11 companies behind it, including Microsoft, GitHub, Hugging Face, Nvidia and Salesforce, on a Linux Foundation data model. That spread is why this one is worth taking seriously.
The first thing to clear up, because the names are one letter apart and everyone is about to mix them up.
api-catalog (RFC 9727) | ai-catalog.json (ARD) | |
|---|---|---|
| Lists | Your public APIs | Tools, skills, MCP servers, A2A agents, sub-catalogs |
| Standard | IETF | Google and 10 others, Linux Foundation model |
| Discovery | A static list you publish | A static list plus registries that crawl and rank everyone |
| Identity | None | Domain ownership as the trust root |
I already serve an api-catalog on this site, and it stays exactly where it is. ARD is not a rename of it. It is the layer above, and the two sit side by side.
Why this site was a soft target
ARD only matters if your catalog points at something real. Most content sites have nothing to list, so their ai-catalog.json would be an empty shelf.
This site is not one of them. From the agent-ready build it already serves an A2A agent card at /.well-known/agent.json and an MCP server card at /.well-known/mcp/server-card.json, both live, both pointing at the WebMCP endpoint at /mcp/. ARD’s entire job is to advertise exactly those. So my catalog points at working capabilities, which is the difference between a demo and a real one.
The file
Here is the catalog, trimmed to 2 of its 3 entries. The full version is live at /.well-known/ai-catalog.json.
{
"specVersion": "1.0",
"host": {
"displayName": "Suganthan Mohanadasan",
"identifier": "did:web:suganthan.com",
"documentationUrl": "https://suganthan.com/mcp/"
},
"entries": [
{
"identifier": "urn:ai:suganthan.com:agent:blog-agent",
"displayName": "Suganthan Blog Agent",
"type": "application/a2a-agent-card+json",
"url": "https://suganthan.com/.well-known/agent.json",
"description": "A2A agent card for searching, retrieving, and reading my blog posts and notes on SEO, AI SEO, and the agentic web.",
"capabilities": ["search_posts", "list_posts", "get_post", "get_site_info"],
"representativeQueries": [
"find an agent that can search an SEO blog",
"what has this site published about the agentic web"
],
"version": "0.1.0"
},
{
"identifier": "urn:ai:suganthan.com:server:blog-mcp",
"displayName": "Suganthan's MCP Server",
"type": "application/mcp-server-card+json",
"url": "https://suganthan.com/.well-known/mcp/server-card.json",
"description": "MCP server with tools to search posts, list posts, fetch a post by slug, and read site and author info.",
"representativeQueries": [
"find an MCP server that can search a blog about SEO",
"get the full text of an SEO blog post by slug"
],
"version": "1.0.0"
}
]
}
Here are 2 details that I missed and wasted a lot of my time.
specVersion is "1.0", not 0.9. The spec document is at v0.9 draft, but the schema pins the wire-format version to 1.0, and validation fails on anything else. Read the schema, do not infer the version from the spec’s own heading.
Every identifier is a URN matching a strict pattern, urn:ai:<publisher>:<namespace>:<name>, where the publisher segment has to be your domain. The representativeQueries are not decoration. They are the text a registry embeds to match natural-language searches, so they are worth writing as the questions a real person would type.
The 4 ways to advertise it
The spec defines 4 discovery methods. I shipped 3 of them plus an HTTP Link header, and skipped the fourth.
The well-known file is the main one. On top of that, a directive in robots.txt:
Agentmap: https://suganthan.com/.well-known/ai-catalog.json
A link in every page head:
<link rel="ai-catalog" href="/.well-known/ai-catalog.json">
And the same pointer as an HTTP Link header, served from Cloudflare’s _headers next to the api-catalog one that was already there:
Link: </.well-known/ai-catalog.json>; rel="ai-catalog"
The one I skipped is DNS. ARD lets you publish Service Binding records so an agent can find your catalog from a DNS lookup alone, no HTTP needed. It’s clever, but it meant touching DNS for a draft spec, and I was not ready to do that for a file that already has 3 other front doors.
did:web, because identity is the whole point
ARD’s trust model is domain ownership. If a catalog lives at suganthan.com, the claim is that whoever controls that domain controls the catalog. To make that concrete I set the host identifier to did:web:suganthan.com and shipped a did.json so the identifier actually resolves rather than dangling.
The heavy version of this, the signed trustManifest with SPIFFE identities and compliance attestations, is the optional enterprise layer. I did not ship it, because for a personal site, serving the document from the domain itself is the proof. That is the entire appeal of did:web. The domain is the root of trust, and you already own it.
Does it validate? Yes
I ran 2 checks. First, the file against the official JSON Schema, Draft 2020-12, which passed with no errors. Then the official conformance tool from the spec repo, run against the live file:
=== Validating Manifest: /.well-known/ai-catalog.json ===
✓ Manifest parsed successfully as valid JSON.
✓ Strict JSON Schema validation passed.
• Found 3 entries to validate.
Entry: Suganthan Blog Agent
✓ Valid URN format. Publisher: 'suganthan.com', Name: 'blog-agent'.
✓ Correct Value-or-Reference delivery format (using url).
...
=== Conformance Validation Summary ===
CONFORMANCE STATUS: PASS
Validated with 0 critical specification errors and 1 warnings.
The one warning is worth keeping rather than hiding. My third entry is the site’s OpenAPI spec, and its media type, application/vnd.oai.openapi+json, is not one of ARD’s standard discovery types. ARD recognises MCP servers, A2A agents, nested catalogs and registries as first-class. A raw REST API rides along and gets flagged as non-standard. That tells you something true about the spec. It’s built agent-protocol first, not API first. I left the entry in because the API is real, and a warning is honest where a deletion would be tidy.
Does a client actually find me? Also yes
This is the moment ARD stops being a PDF. I installed the Hugging Face reference client and pointed its navigate command, which does automatic catalog discovery, at my live domain:
hf-discover navigate https://suganthan.com "find an MCP server that can search an SEO blog"
It fetched my catalog and handed back my own capabilities:
{
"discovered": [
{ "kind": "catalog",
"url": "https://suganthan.com/.well-known/ai-catalog.json",
"status": "ok" }
],
"results": [
{ "identifier": "urn:ai:suganthan.com:agent:blog-agent",
"displayName": "Suganthan Blog Agent",
"type": "application/a2a-agent-card+json", "score": 50 },
{ "identifier": "urn:ai:suganthan.com:server:blog-mcp",
"displayName": "Suganthan's MCP Server",
"type": "application/mcp-server-card+json", "score": 50 }
]
}
To check it was matching rather than just dumping the file, I asked it something my site cannot do, “transcribe audio to text”. It dropped the agent and the API and returned only the MCP server, the closest of a bad set. So there is real selection happening, not a blind echo.
A third-party client, run cold against my domain, discovered and understood what this site can do for an agent. That is the spec working end to end.
The catch: Cloudflare blocked the validator
Now for the part that bites. The first time I ran that conformance tool against the live URL, it did not validate anything. It got a flat 403.
The file was fine. curl pulls it down with a 200 all day. The tool was getting blocked because of who it said it was. It fetches with Python’s standard library, whose user-agent is Python-urllib, and Cloudflare’s managed bot rules treat that as a bad actor and turn it away at the edge before it ever reaches the file.
I tested the same URL as a series of different clients:
| Client user-agent | Response |
|---|---|
Python-urllib/3.11 (the conformance tool) | 403 |
Browser (Mozilla/5.0) | 200 |
ClaudeBot, GPTBot | 200 |
curl, empty user-agent, the Hugging Face client | 200 |
Read that table again.
The named AI crawlers walk straight in. A blank user-agent walks in. The official conformance tool for the spec you are implementing does not. Same file, different doorman.
That is the gap between publishing a catalog and having it be discoverable. Shipping the file is necessary and nowhere near sufficient. If you sit behind Cloudflare, or any WAF with managed bot rules, a registry crawling you with a stock HTTP library can be turned away while you sit there thinking you are live. The fix is to allowlist your /.well-known/ paths for these clients, or to lean on the fact that the real registries identify themselves properly. The Hugging Face client got through because it sends its own user-agent. The reference validator did not, because nobody changed the default. Check this yourself, because it is the step everyone will skip.
The limitation
What I have proved is the publisher half and the client half. My catalog is valid, it is discoverable, and a real client pointed at my domain reads it correctly.
What I have not proved is the headline the spec is selling, that a registry indexes the open web and an agent finds me cold, never having heard of this site. To be fair, that machinery is only 2 days old. Hugging Face’s hosted registry only indexes its own Spaces, and no public registry is crawling the open web yet.
So the federated-search half is a promise, not yet a demo.
The upside is that the catalog is already sitting there for the day a public registry starts crawling. Watch this space.
Should you ship this yet?
If your site does not expose an MCP server, an A2A agent, or an API, your ai-catalog.json is an empty shelf. Skip it, and revisit when you have something to list.
If you do expose any of those, and more sites will, it’s a 20-minute job that costs nothing and gets you in front of the registries before they arrive. The order that worked for me → Serve a valid ai-catalog.json -> point every entry at a real capability → run the conformance tool until it passes -> advertise the file more than one way, and then, if you are behind a WAF, confirm a plain HTTP client can actually fetch it.
That last check is the one that separates a catalog that exists from one that works.
This is the next layer on top of making your site agent-ready and shipping WebMCP.
The protocols keep stacking. The good news is that each one is a small file, and most of the work is deciding whether you needed it at all.
Just only small problem.
Want your site built to be found by AI agents, not just crawled by them?
If you want help applying this on your own site, my agency Snippet Digital takes on this kind of work. Send an enquiry and I will be in touch.
Work with me
Norwegian entrepreneur with 20+ years in SEO. Co-founder of Keyword Insights and Snippet Digital. Based in Dubai.