VCN #35 / Well-Known / the companion cheat sheet

The five files. Copy, paste, ship.

Everything an agent needs to find you, in five short files plus one Worker. Real, minimal, valid. Swap acme.com for your domain and deploy. ASCII safe, so it survives any terminal.

back to the deck ->
file 1 / 5

agent-card.json

A2A v1.0.0

Who you are. The three load bearing fields are name, description, and an endpoint. Set auth on day one or it defaults to public.

/.well-known/agent-card.json
{
  "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"],
  "securitySchemes": { "oauth": { "type": "oauth2" } },
  "skills": [
    {
      "id": "book",
      "name": "Book appointment",
      "description": "Reserve an open slot.",
      "tags": ["scheduling"]
    }
  ]
}
file 2 / 5

mcp.json

SEP-2127

Where your tools live. Points an agent at your MCP server. The strict SEP path is /.well-known/mcp/server-card.json; the short form below is what ships in the wild.

/.well-known/mcp.json
{
  "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." }
  ]
}
file 3 / 5

ai-agent.json

Aiia, 2026-03-28

The file the scanner reads. Only name and description are required. It is wired into isitagentready, so it moves the score directly.

/.well-known/ai-agent.json
{
  "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"]
}
file 4 / 5

oauth-protected-resource

RFC 9728

Where to authenticate. Both MCP and A2A piggyback on it. resource is what you protect; authorization_servers is where to get a token. It points, it does not mint.

/.well-known/oauth-protected-resource
{
  "resource": "https://acme.com",
  "authorization_servers": ["https://auth.acme.com"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["read", "write"]
}
file 5 / 5

llms.txt

llmstxt.org

Top level, NOT under well-known. A markdown map of your site. Curate it by hand. An auto generated, stale map is a negative signal.

/llms.txt (site root)
# 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
deploy

One Worker serves all five

Cloudflare

A path map and a fetch handler. JSON for the four under well-known, plain text for llms.txt at the root. Access-Control-Allow-Origin is not optional: without it, browser agents fail silently.

worker.js
// paste your five file bodies as strings up here:
//   agentCard, mcpCard, aiAgent, oauthMeta, llmsTxt

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,
        "access-control-allow-origin": "*"
      }
    });
  }
};

The four traps