earn a blue link a human clicks. you optimized to place tenth, then third, then first, in a page of ten results.
five files / one worker / vcn #35 / your site is on the agent map by 10pm
MCP SERVER CARDS APPEAR ON FEWER THAN 15 SITES ON EARTH.
Everyone is building agents. Almost nobody has put up a sign telling those agents what they offer. The whole demand side is here. The supply side of discovery is nearly empty.
cf-readiness (Cloudflare agent-readiness study, April 2026). that empty space is the opportunity. one file tonight and your site is rare company.
SITES SHIP RULES FOR OLD CRAWLERS. ALMOST NONE SHIP FOR AGENTS.
cf-readiness. the 1990s crawler got a welcome mat. the 2026 agent gets a locked door with no sign on it.
YOU SPENT A DECADE GETTING RANKED. NOW THE JOB IS GETTING RECOMMENDED.
GEO is generative engine optimization. optimize to be recommended and cited inside an AI answer, not ranked by a search engine. the agent reads, decides, and names a source.
shopify-geo (The GEO Playbook, 2026). same goal as SEO, a new reader. the well-known files are how you introduce yourself to it.
THE ANSWER ENGINE IS ALREADY HALF THE TRAFFIC.
If a third of your readers are now models, you need a page written for a model to find.
shopify-geo. the audience already shifted. the question is whether your site speaks to the new half.
THE AGENT DOES NOT BROWSE LIKE YOU. IT FETCHES KNOWN PATHS.
An AI crawler reads the server-returned HTML only. It does not run your JavaScript. Whatever a client-side framework paints after load is invisible to it.
So it does not click around. It requests a handful of known locations and reads what comes back as plain text.
First thing to check tonight: is robots.txt silently blocking the AI crawlers you actually want? Many sites block the readers they hope will cite them.
# what the agent actually does
GET /robots.txt
GET /.well-known/agent-card.json
GET /.well-known/mcp.json
GET /.well-known/ai-agent.json
GET /llms.txt
# reads the raw response. no
# browser. no JS. just text at
# a known address.
shopify-geo. you are not designing a page for an eye. you are answering a fetch at a fixed path. that is the whole shift.
THERE IS ALREADY A KNOWN PLACE TO LEAVE A NOTE. IT IS NOT NEW.
/.well-known/ is a standard registry for known URIs, defined by RFC 8615. A fixed directory at the root of any domain. The idea is the entire point: a known location, so a client needs no negotiation to find it.
rfc8615. the same mechanism behind security.txt, ACME, and OpenID discovery. agents just got added to the list of who looks there.
THE PROMISE.
you walk out tonight with five well-known files, live on a domain you own, and a score that proves it.
not a slide you watched. a domain you can scan. now the map of what we ship.
FOUR FILES UNDER /.well-known/. ONE AT THE ROOT.
Hold one rule above all: ai-agent.json lives under /.well-known/. llms.txt lives at the root. Swap them and both go dark.
a2a-spec / mcp-2127 / aiia-spec / rfc9728 / llmstxt. one preview slide each, next. then we hand-roll all five.
agent-card.json · THREE FIELDS AND IT IS CALLABLE.
A2A v1.0.0. The agent's business card.
A2A reached v1.0.0 in March 2026 and was donated to the Linux Foundation. The three-field minimum is callable: name, description, and an endpoint. The spec's recommended home is exactly this path.
// the 3-field minimum
{
"name": "My Service",
"description":
"What this agent does,
in one plain line.",
"url": "https://my.example/a2a"
}
a2a-spec (A2A Protocol v1.0.0). we build the full card in Segment 1. this is the shape to hold in your head.
mcp.json · THE CARD FEWER THAN 15 SITES SHIP.
MCP server discovery over HTTP.
SEP-2127 (PR #2127, "MCP Server Cards"). Draft, but ship-stable, and already validated by Shopify and Smithery. It advertises transport, URL, and tools so an agent finds your server without a config file.
● the file that puts you in the top ~0.01%
// advertise your MCP server
{
"transport": "http",
"url": "https://my.example/mcp",
"tools": [
{"name": "search"}
]
}
mcp-2127. the SEP's precise path is /.well-known/mcp/server-card.json. mcp.json is the widely-shipped short form. we ship both in Segment 2.
ai-agent.json · THE ONE THE SCANNER ACTUALLY CHECKS.
The Aiia working group manifest.
Required: name and description. Optional: protocols, endpoints, auth, contacts. It is already wired into Cloudflare's isitagentready scanner, so shipping it moves your score directly.
● ship this and the number goes up tonight
// required: name + description
{
"name": "My Service",
"description":
"Plain English. What you do
and who you are for."
}
aiia-spec (Aiia working group, 2026-03-28). two required fields. the most score per line of any file tonight.
oauth-protected-resource · IT SAYS WHERE, NOT HOW.
RFC 9728. The auth handshake target.
Both MCP and A2A piggyback on this. It says where to authenticate. It does not mint tokens. Two load-bearing fields: the resource and its authorization_servers.
// point at your auth server
{
"resource":
"https://my.example",
"authorization_servers": [
"https://auth.my.example"
]
}
rfc9728 (OAuth 2.0 Protected Resource Metadata). the one file with no .json suffix. we wire the handshake in Segment 4. do not roll your own.
llms.txt · AT THE ROOT. NOT UNDER WELL-KNOWN.
Jeremy Howard's markdown sitemap.
A curated markdown map of your site, for a model to read. It lives at the top level, not under /.well-known/. This is the single most common mix-up of the night.
honest caveat: major crawlers do not fetch it yet. ship it anyway, the cost is near zero. (more in Segment 5.)
# My Service
> One line on what this is.
## Docs
- [Quickstart](/docs/start.md)
- [API](/docs/api.md)
llmstxt (Jeremy Howard, 2024-09-03). markdown, not JSON. the only file of the five that lives at the root. hold that.
THE SCANNER RUNS 21 CHECKS IN FOUR CATEGORIES.
cf-readiness (isitagentready.com). 21 checks, four categories. the files you ship tonight light up Discoverability, OAuth discovery, and the MCP Card.
NO SITE SCORED ABOVE 70. ONE REASON LEADS THE LIST.
cf-readiness. the #1 reason no site scored above 70: a div where a button belongs. the agent reads roles, not your CSS. ship the files first, then earn the rest of the score here.
HUGE DEMAND. A NEARLY EMPTY SHELF.
anthropic-mcp / cf-readiness. millions of agents looking. fewer than fifteen front doors. you build a front door tonight.
WHAT YOU WALK OUT WITH.
a thing that runs, not a thing you watched. with cards on fewer than 15 sites, that puts you in rare company.
THE NEXT THREE HOURS.
Frontier Tower Floor 9. ask out loud the moment you are stuck. a site that scans live in the room beats a clean one you only watched.
BRING THREE THINGS. THE WORKER DOES THE REST.
THE AGENT CARD.
Enough context. agent-card.json, three fields, on your domain. Open your terminal and the file for File 1.
The agent's business card.
agent-card.json is the front of the house. An agent lands on your domain, looks in one known place, and reads who you are and where to talk to you. This is A2A, version 1.0.0, donated to the Linux Foundation in March 2026. Three fields make it callable. We write those three first, then the trap that makes it leak.
● file 1 · the three that make it callable
{
"name": "Acme Concierge",
"description": "Books and reschedules Acme appointments.",
"url": "https://acme.com/a2a",
"version": "1.0.0",
"capabilities": { "streaming": false },
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "book",
"name": "Book appointment",
"description": "Reserve an open slot.",
"tags": ["scheduling"]
}
]
}
A2A v1.0.0, March 2026, donated to the Linux Foundation. [a2a-spec]
One known address. One quiet default.
Hand code the card with no auth field and it defaults to public. If that agent touches tenant data, you just published an open door. Set auth on day one.
"securitySchemes": { "oauth": { "type": "oauth2" } }recommended location is exactly /.well-known/agent-card.json. the public default is the most common mistake. [a2a-spec][dossier]
One curl, and the card answers.
# fetch the card any agent would read
curl -s https://acme.com/.well-known/agent-card.json
# what comes back
{
"name": "Acme Concierge",
"description": "Books and reschedules Acme appointments.",
"url": "https://acme.com/a2a"
}
If that returns JSON, your card is discoverable. The agent now knows your name, what you do, and the one URL to start a conversation. curl is the whole test. No SDK, no client.
three fields is a callable card. [a2a-spec]
Where your tools live.
The card says who you are. mcp.json says what you can do. It points an agent at your MCP server and lists the tools waiting there. This is SEP-2127, the HTTP discovery story for the MCP servers from last month's build. Draft, but ship stable. Shopify and Smithery already validate it.
● file 2 · the shape
{
"schema_version": "2025-06-18",
"name": "acme-mcp",
"description": "Acme tools for agents.",
"transport": "streamable-http",
"url": "https://acme.com/mcp",
"tools": [
{ "name": "search_orders",
"description": "Find orders by email." }
]
}
- transportstreamable-http. the production transport from VCN #34.
- urlthe /mcp endpoint the agent will actually call.
- toolsa name and a description per tool. discovery before connect.
SEP-2127, MCP Server Cards over HTTP. [mcp-2127]
Draft on paper. Shipping in production.
Shopify
Validates the well-known MCP discovery file across its commerce surface.
Smithery
The MCP registry uses the same shape to index servers for agents.
The SEP's precise path is /.well-known/mcp/server-card.json. The widely shipped short form is /.well-known/mcp.json. Ship the short form, and know the long form exists so a stricter scanner does not surprise you.
SEP-2127, validated by Shopify and Smithery. [mcp-2127]
The file the scanner reads.
ai-agent.json is the Aiia working group's manifest. It is plain and short. Two fields are required. The reason it earns its own segment: it is already wired into Cloudflare's isitagentready scanner, so shipping it moves the score you will run live tonight.
● file 3 · two required, the rest optional
{
"name": "Acme",
"description": "What Acme's agent does, in one line.",
"protocols": ["a2a", "mcp"],
"endpoints": {
"a2a": "https://acme.com/a2a",
"mcp": "https://acme.com/mcp"
},
"auth": { "type": "oauth2" },
"contacts": ["agent@acme.com"]
}
Aiia ai-agent.json, working group spec 2026-03-28. [aiia-spec]
Ship this file. Watch the number move.
Cloudflare's isitagentready.com already checks for ai-agent.json by name. The other files matter for real agents. This one also moves the legible score on the gauge we run before and after tonight. Cheapest point on the board.
already wired into the isitagentready scanner. [aiia-spec][cf-readiness]
They overlap. You ship both anyway.
A2A's card. Indexes into the A2A ecosystem and its catalogs. Richer skills model.
Aiia's manifest. Indexes into a different registry, and into the scanner.
Same facts, two registries. The cost to ship both is about fifty lines of JSON. There is no reason to pick. Write both, point them at the same endpoints, move on.
they overlap but index into different registries; ~50 lines to ship both. [dossier]
The handshake everyone shares.
oauth-protected-resource is the auth target. It is RFC 9728, and the thing that makes it worth one file: both MCP and A2A piggyback on it. One file answers the auth question for every protocol you speak. It says where to authenticate. It never mints a token.
● file 4 · two fields carry the weight
{
"resource": "https://acme.com",
"authorization_servers": [
"https://auth.acme.com"
],
"bearer_methods_supported": ["header"],
"scopes_supported": ["read", "write"]
}
RFC 9728, OAuth 2.0 Protected Resource Metadata. [rfc9728]
A 401 is not a dead end. It is a map.
the 401 then well-known then token then retry loop. [rfc9728]
You write the pointer. You do not write the auth server.
The one well-known file. A pointer at authorization_servers. That is your whole job here.
Token issuance, rotation, DPoP, token exchange. SharkAuth does OAuth 2.1, RFC 8693, and DPoP in one Go binary.
Auth is where you get owned. Do not roll your own. Point at a managed identity provider, ship the pointer file, and let the hard parts live where people audit them.
SharkAuth: open source OAuth 2.1 / RFC 8693 / DPoP for agents. [sharkauth]
The map in plain markdown.
llms.txt is Jeremy Howard's idea: a markdown sitemap that tells a model what is on your site and where to read more. It is the friendliest of the five, just headings and links. One catch you cannot miss: it lives at the root, not under well-known. We write the file, then the trap.
● file 5 · headings and links, that is all
# Acme
> One line summary of the site.
## Docs
- [Quickstart](https://acme.com/docs/quickstart): get running in 5 minutes
## API
- [Reference](https://acme.com/api): endpoints and auth
llms.txt format; the Anthropic docs template is a working reference. [llmstxt][anthropic-llmstxt]
If you remember one path rule tonight, it is this one.
Four files live under well-known. llms.txt does not. It sits at the site root. Put it in the wrong place and it goes dark.
llms.txt is top level; ai-agent.json is under well-known. mixing them up is the most common error. [dossier]
Astro shipped llms.txt, then pulled it.
In May 2026 Astro removed its llms.txt. The lesson is not "skip the file." It is that an llms.txt auto generated from build output, with no human looking at it, drifts stale and starts pointing at the wrong pages. A stale map is a negative signal, worse than none.
Astro removed its llms.txt, 2026-05-04; auto generation without curation can turn it negative. [astro-walkback]
One Cloudflare Worker routes every path.
const FILES = {
"/.well-known/agent-card.json": agentCard,
"/.well-known/mcp.json": mcpCard,
"/.well-known/ai-agent.json": aiAgent,
"/.well-known/oauth-protected-resource": oauthMeta,
"/llms.txt": llmsTxt
};
export default {
async fetch(req) {
const path = new URL(req.url).pathname;
const body = FILES[path];
if (!body) return new Response("not found", { status: 404 });
const type = path.endsWith(".txt") ? "text/plain" : "application/json";
return new Response(body, { headers: { "content-type": type } });
}
};
One handler. A path map. JSON for the four under /.well-known/, plain text for /llms.txt at the root. Deploy once, all five answer. CORS comes next, and it is not optional.
one Worker fetch handler routes paths to the right file and content type. [self]
No CORS, and browser agents fail silently.
A browser based agent sends a preflight before it reads your well-known files. Miss the header and the fetch dies with no useful error, just a dead client and a clean server log. Add one header to every well-known response.
Access-Control-Allow-Origin: *
It bites in prod, not in your terminal, because curl does not preflight and a browser does. Set it on day one, on every path, and the whole browser agent population can read you.
missing Access-Control-Allow-Origin on well-known makes browser agents fail silently. [dossier]
Five files. All live.
- PASSagent-card.json who you are, with auth set
- PASSmcp.json the tools, pointed at your /mcp
- PASSai-agent.json the manifest the scanner reads
- PASSoauth-protected-resource where to authenticate
- PASSllms.txt at the root, curated by hand
- PASSone Worker serving all five, with CORS
You shipped the signage. Now we point a scanner at it and watch the map light up.
next: the scan, the before and after, the score. [cf-readiness]
SHIP
Now you
get scanned.
Five files are written. The only question left is whether an agent can actually see them. There is a public scanner that tells you, out loud, in a number.
isitagentready.com
files written DONE deploy next scan twice read the climb
Run it first. Read the dark map.
Point the scanner at your domain before you deploy anything. Most sites come back low. You are looking at a map with one beacon lit, if that.
low
21 checks across 4 categories. With no well-known files, the Capabilities row is dark, and that is most of what the agent was looking for. This is the supply gap, on your own domain.
One Worker. All five routes live.
One deploy puts every file at its known address. The agent does not care what served them. It cares that the URL returns 200 with CORS.
wrangler deploy
Uploaded well-known-worker
Published well-known-worker
https://your-domain.com
Routes:
/.well-known/agent-card.json
/.well-known/mcp.json
/.well-known/ai-agent.json
/.well-known/oauth-protected-resource
/llms.txt
The Worker is just transport. Steel-grey plumbing. The files are the signal. This is the moment the dark map gets a light put on it.
Run it again. Watch the number move.
Same domain. Same scanner. Five text files later, the Capabilities row lights up and the score climbs in real time. This is the legible "this matters" moment.
low->high
The accessibility tree caps everyone, so nobody is at 100. But the move off the floor is yours, live, in front of the room. Files that took twenty minutes, score that climbs in twenty seconds.
Highest score takes the poster home.
Everyone scans their own domain. We read the room's numbers off one screen. The climb is private. The leaderboard is not.
Tonight's high score wins the VCN poster.
The point is not the prize. The point is that "agent-ready" is now a number you can move on purpose.
21 checks. 4 categories. No one at 100.
The scanner is not arbitrary. It is four buckets, and tonight you filled most of one of them.
Discoverability
robots, sitemap, link headers. Where you point.
Content
markdown content negotiation. What a model can read cleanly.
Bot Access
Content Signals, AI rules, Web Bot Auth. Who you let in.
Capabilities
Skills, API Catalog, OAuth discovery,
MCP Card, WebMCP. What you can do.
The Capabilities tail is the long one. Skills, an MCP Card, WebMCP tools. Most of the room's score climb tonight lives right here, and almost no site on earth has filled it.
Five ways the files pass green and still go dark.
- LOCATIONwrong path.
llms.txtis top-level.ai-agent.jsonis under/.well-known/. Mix them up and both go dark. - CORSno Access-Control-Allow-Origin. Browser-side agents fail silently on every
/.well-known/*route without it. - AUTHdefaults to public. Hand-coding
agent-card.jsonwith noauthopens a tenant-data agent to the world. Setoauth2day one. - SAASstatic behind per-tenant. Static well-known files break under tenant-per-domain SaaS. Serve dynamically with cache headers.
- A11Ythe accessibility tree. The #1 reason no site scored above 70. The agent reads the tree, not your CSS.
What the agent sees when you ship nothing.
GET /.well-known/agent-card.json 404
GET /.well-known/mcp.json 404
GET /.well-known/ai-agent.json 404
GET /.well-known/oauth-protected-resource 404
GET /llms.txt 404
agent capabilities found: none
markdown content found: none
the scanner returns: a dark map
96%of the top 200,000 domains are NOT agent-ready (only 4% declare AI preferences).
Your site renders fine for a human. To the agent, it is empty.
Cloudflare agent-readiness study, April 2026. 78% ship robots.txt, 4% declare AI prefs, 3.9% do markdown negotiation, MCP Server Cards on fewer than 15 sites.
The #1 finding. It is not in your CSS.
A div is invisible.
A button is a control.
What the agent sees
<div onClick={submit}>
Buy
</div>
a11y tree: generic text "Buy"
What the agent can use
<button onClick={submit}>
Buy
</button>
a11y tree: button "Buy"
This single substitution is why no site scored above 70. The agent navigates the accessibility tree. A styled div with a click handler looks like a button to a human and like nothing to an agent.
FRONTIER
discovery -> identity
-> trust -> payments.
Tonight you built the discovery layer. A flat file at a known address that says "I exist." The next three layers are where this series goes, and they all stack on top of the file you just shipped.
Discovery is one axis across four protocols.
The survey of agent interoperability lines up MCP, ACP, A2A, and ANP. Discovery shows up in all of them. Tonight's flat file is the plaintext end of a spectrum.
- MCP
- ACP
- A2A
- ANP
ANP is the decentralized end. It uses did:wba identifiers and a JSON-LD Agent Description published at /.well-known/agent-descriptions. Same idea as your ai-agent.json, signed and resolvable instead of plaintext.
Ehtesham et al., A survey of agent interoperability protocols, arXiv 2505.02279.
Above the flat file: a directory.
A file on your domain says "I exist" to anyone who already knows to look. A registry makes you findable when they do not. AGNTCY is one such plane.
content-addressed
agent records as OCI artifacts, addressed by hash.
DHT-distributed
no single host. A federated discovery plane.
Sigstore-signed
records are signed, so a puller can verify provenance.
It is the federated layer above the file you shipped. The well-known file is your front door. The directory is the phone book.
The AGNTCY Agent Directory Service, arXiv 2509.18787.
Identity, then trust.
Discovery answers "do you exist." The next two questions are "who are you" and "are you safe to deal with." That is identity, then trust.
Identity
DIDs and verifiable credentials. NANDA's AgentFacts is a machine-readable identity-plus-reputation template a registry can validate.
Trust
a binary trust registry. GenGEO gives a yes-or-no eligibility signal before any transaction.
Discovery says "I exist." Trust says "I am safe to pay."
Garzon, AI Agents with DIDs and Verifiable Credentials, arXiv 2511.02841. GenGEO trust registry.
And then agents pay each other.
discovery -> identity -> trust -> payments
A2A's agent card is enterprise-shaped and assumes a catalog is up. The research move is to anchor those cards on a ledger and settle with x402 micropayments. Discovery flows into a tamper-evident registry, and the registry flows into payment.
Vaziry et al., Towards Multi-Agent Economies: A2A with ledger-anchored identities and x402, arXiv 2507.19550.
The receipt. What you walk out with.
You walked in with a site that renders. You walk out with a site an agent can see.
- [ ok ]five files live at their known addresses, 200 with CORS.
- [ ok ]a Worker you wrote serving all five routes from one deploy.
- [ ok ]a score, twice the before and the after, measured out loud.
Measurably, that is the top ~1% of the agentic web.
One more thing.
This deck is itself on the map.
GET /.well-known/agent-card.json this deck's card
GET /.well-known/ai-agent.json wired to the scanner
GET /.well-known/mcp.json
GET /.well-known/oauth-protected-resource
GET /llms.txt
navigator.modelContext.registerTool("next_slide")
navigator.modelContext.registerTool("goto_slide")
navigator.modelContext.registerTool("submit_feedback")
It ships all five well-known files and registers three live WebMCP tools. An agent in this room, in a WebMCP browser, could advance these slides and send feedback without touching the keyboard.
Do not take our word for it. Scan this deck on isitagentready. It practices what it teaches.
Tonight was discovery. The series walks the stack.
Vibe Coding Nights runs weekly at Frontier Tower. The agentic web, one layer at a time.
- tonight#35 Well-Known discovery, the five files, /.well-known
- Jun 10#36 Crosstalk A2A, agents talking to each other
- later#37 Payments x402 micropayments, agents that pay
- later#38 Observability reading model state before each action
Every event is on Luma. Get the weekly intel in THE SIGNAL, Immersive Commons' AI dispatch. Both links on the handout.
Go light up
your map.
Hosted by Rayyan Zahid, Michalis Vasileiadis, Eric Mockler, and Devinder Sodhi.
Vibe Coding Nights #35 · Well-Known · Frontier Tower Floor 9.
Licensed CC BY-SA 4.0. Take it, fork it, run your own. Now go ship five files.