TL;DR: Machines find an agent or a server through cards — small files they read. Five seem prominent. Every spec lives in public git, so we read every version and drew them as one map, after Harry Beck's Underground diagram.
In Plain English
- Five cards. Five specs, all in public git.
- Eight choices. Every card picks a name field, an identity, a discovery path, a media type, an encoding, an extension point, a trust model and a versioning rule.
- One centre. The centre line is what most cards share. Distance is what only one card does.
First, the one that is not a card
We followed the MCP Registry closely, so start there. server.json is the Registry entry — how a server gets published, rather than a card a server serves at its own door. It is not on the map, and it is the piece faf-cli writes today:
faf cards --target registry
32,237 latest-version entries, counted page by page from the Registry API on 2026-09-15. Server Card Rev 1 borrowed its shape, which is where that line branches from.
Then the cards
Five. A2A Agent Card, MCP Server Card, AI Catalog, ARD and .fafa.
A2A reached Released v1.0 and joined AAIF at Growth Stage on 2026-08-27 — the one other specs point at when they need to describe an agent and would rather not invent a card. AI Catalog is moving fastest: MCP's own MCP Catalog is evolving into it, and the spec turned over #37 and #77 five weeks apart. ARD says Proposal. .fafa is ours.
They overlap, they disagree, and they are all in public git. So we read every version.
How to read it
Beck's 1933 diagram dropped geography and kept order. We did the same with time.
Time runs west to east. Each card is a line. Each station is a spec change, spaced by order, not by calendar. A ring marks the day two cards start or stop sharing a choice.
Two views. Protocol ↔ Envelope (the default): cards defined by one protocol sit above the centre, protocol-neutral envelopes below. Strict ↔ Loose: each card's required fields against the median.
The map as a band. The live version is interactive — hover a station, follow a tick to the spec at that commit, switch the view.
What it shows
- A2A opens alone. The map starts with A2A v0.2.0 in May 2025. Nothing to compare it with until MCP Server Card's first draft, SEP-2127, on January 21, 2026.
-
Twins. On June 25, 2026, AI Catalog merged #37 and #36. With ARD v0.9 already on
urn:air, the two met on the centre line. -
A step in. On July 20, MCP Server Card moved discovery to
/.well-known/ai-catalog.json. -
The split. On August 26, ARD v0.91 took its own
ard.json, JSON-LD and a trust manifest. The twins parted. AI Catalog moved that day with no spec change of its own. Distance is relative. -
Furthest out:
.fafa. The only card with an IANA-registered media type, and the only one written in YAML. Registering moved it one step further out. Different, not wrong.
How it's built
30 spec versions. 269 quotes, each checked against its line at its commit. Every station links to the spec at that commit, and every value links to the line it was quoted from — the register is public, so any figure here can be checked.
We make .fafa. So the rules came first, and .fafa landed where the rules put it.
The choice list is a judgement. A different list draws a different map. The quotes are public, so anyone can check it, or redraw it.
Some interesting facts
- A2A was alone for 245 days. The first card landed on 2025-05-21. There was nothing to compare it with until 2026-01-21.
-
Five cards, five different extension points. Of the eight choices we track,
extensionis the only one where no two cards agree. - A2A asks for eight required fields. AI Catalog asks for three.
- AI Catalog shipped eight versions in 141 days. A2A shipped six in 479.
Three ways to name a card
A media type is the label a machine reads before it opens the file.
None of these five specs requires one. They landed on three different answers.
A2A Agent Card and ARD name no media type.
AI Catalog uses application/ai-catalog+json. MCP Server Card uses application/mcp-server-card+json. Neither is registered.
.fafa uses application/vnd.fafa+yaml, registered with IANA on 2026-06-26.
Every value above links to the line it was quoted from.
What it cost us to keep up
The map carries our own lane too, because keeping up is the hard part and we have not always managed it.
AI Catalog merged #37 on June 25. We conformed on June 26 — one day.
AI Catalog merged #77 on July 30, moving extensions to a map. We answered in three days and used an array. It stayed wrong for forty-five, and working group parsers rejected the document the whole time.
Speed is not currency on its own. The check is.
Five, out of thirty-six
Five cards are drawn. We checked thirty-one more against one test: a public spec with git history, describing an agent or a server so machines can find it. Eight pass, seven are borderline, sixteen are out — each listed with the reason, on the page.
A card that does not make the map is not a lesser card. It is a card that answers a different question.
Get your pack
Seven answers describe an agent or a server: name, short name, domain, what it does, version, where it runs, what it can do. From those, faf-cli writes the .fafa and projects every card that has a place for it — correct to each spec, checked by each spec's own validator.
npx faf-cli@latest cards --target catalog,ard

Top comments (2)
The map makes an important interoperability problem visible: two cards can describe the same agent while disagreeing on identity, discovery, trust, and versioning. The risky part is projection—generating several formats from one source can look lossless even when a target has nowhere to express a field. I’d love to see
faf-cliemit a machine-readable loss report with the source field, target omission, and spec commit used for the conversion. Have you tried round-tripping a card through two formats to show which semantics survive and which cannot come back?No — not yet, not across two card specs. faf-cli's round-trip gates are all inside the FAF family (compile → decompile, Unicode through the wire format, CLI ↔ Rust parity on the binary), and the map was read out of each spec at its commit rather than converted. Projection does bite, though: our own .cursorrules exporter wrote
# Package Manager: npmand the importer read that line back as the project name — survived the write, came back wrong. Which is your point exactly, and it is why "this spec has no place for that field" and "this conversion dropped it" are two different artifacts.Good to see the map working. The next logical step is a surface where you run cards through and watch the diff — your loss report could sit right there. Thank you for your feedback.