AIR (Artificial Intelligence Ranking), by airanks, is AI optimization made visible — a 0–10 score showing how visible a domain is inside AI-generated answers (ChatGPT and friends): how often it's cited, how it's referenced, how discoverable it is when an AI does retrieval. Check any site's AI Rank at airanks.net, or carry the signal in your browser with the airanks toolbar.
This repo is the universal toolkit for teaching any AI agent — Claude Desktop, Claude Code, Codex, Cursor, Cline, Hermes, or any other MCP client — how to speak AIR, instead of hand-writing N bespoke per-platform integrations. 🔌➡️🤖
- Why one toolkit instead of many skills
- Architecture
- The three ways an agent can use AIR
- Quick start
- Shared authentication
- Request flow
- Claude skill
- Repo layout
- Related airanks repos
- License
Every harness has its own way of granting an agent a new capability — an MCP config here, a skill file there, a plugin manifest somewhere else. Hand-writing an integration per platform means the AIR contract (auth, endpoints, polling, hostname rules) drifts out of sync every time one of them changes 😵. This repo teaches the contract once and gives each harness the smallest possible pointer into it:
| File | What it's for |
|---|---|
📜 AGENTS.md |
The full machine-readable contract — endpoints, auth resolution, hostname normalization, worked examples. Point any agent (or system prompt) at this file and it knows how to use AIR, full stop. |
🛠️ SETUP.md |
Copy-paste MCP config for Claude Desktop, Claude Code, Codex, Cursor, Cline, and any generic MCP client — plus a shell/HTTP fallback for harnesses with no MCP support. |
🎯 skills/airanks/SKILL.md |
A small Claude skill that fires when someone asks about a site's AI rank/AI visibility, and routes the call the same way. |
None of these duplicate logic. They're thin pointers into one authoritative contract — the
same one the reference air CLI and the
airanks-net/mcp-server implement, documented in full at
API-CONTRACT.md. 🎣 One rod, three lines, same fish.
flowchart TB
subgraph Harnesses["🤖 Agent harnesses"]
CD["Claude Desktop"]
CC["Claude Code"]
CX["Codex"]
CU["Cursor"]
CL["Cline"]
OTHER["...any MCP client"]
end
subgraph Toolkit["📦 agent-toolkit (this repo)"]
AGENTS["AGENTS.md<br/>the contract"]
SETUP["SETUP.md<br/>per-harness config"]
SKILL["skills/airanks/SKILL.md<br/>Claude skill"]
end
MCP["🔌 @airanks-net/mcp-server<br/>(npx)"]
CLI["⌨️ air-cli"]
API["🌐 airanks.net/api/v1"]
CD --> SETUP
CC --> SETUP
CX --> SETUP
CU --> SETUP
CL --> SETUP
OTHER --> SETUP
CC -.->|"or copies"| SKILL
SKILL --> AGENTS
SETUP --> MCP
AGENTS --> CLI
AGENTS --> API
MCP --> API
CLI --> API
API --> AIR[("🏆 AIR score<br/>0–10")]
style Toolkit fill:#1a1a2e,color:#fff,stroke:#7b7bff
style API fill:#0aa,color:#fff
Every path — MCP tool call, CLI shell-out, or raw HTTP — terminates at the same
https://airanks.net/api/v1 endpoints and shares the same auth. Nothing here is a separate
data source; it's the same AIR number the toolbar shows. 🪞
Recommended path first — fall back only if a given harness can't do it:
| Path | When to use it | Where |
|---|---|---|
| 🔌 MCP | Your harness supports MCP servers (most modern ones do) | SETUP.md |
⌨️ air CLI |
Shell access, no MCP wiring | npm install -g air-cli, then air <domain> |
| 🌐 REST API | Neither of the above — build your own call | AGENTS.md |
All three resolve auth identically and read the same GET /v1/domains/{host} and
GET /v1/search?q= endpoints against https://airanks.net/api/v1.
{
"mcpServers": {
"airanks": { "command": "npx", "args": ["-y", "@airanks-net/mcp-server"] }
}
}Drop that into your harness's MCP config (exact file/command per harness in
SETUP.md) and restart it. Add AIR_API_KEY to the env block to authenticate;
anonymous works too, just rate-limited harder. 🐢
npm install -g air-cli
air example.com # AIR score + AI-crawler/llms.txt signals
air "best crm software" # search domains, brands, phrasesRead https://raw.githubusercontent.com/airanks-net/agent-toolkit/main/AGENTS.md
and use AIR to check example.com's AI rank.
📄 What's in AGENTS.md (click to expand)
- Full REST contract for
GET /v1/domains/{host}andGET /v1/search?q= - Auth resolution order (below)
- Hostname normalization rules (lowercase, strip
www., when to search instead of look up) - Hydration/polling rules for a domain's first-ever lookup
429/ rate-limit handling- Worked request/response examples
One login works across every AIR client. Resolved in this order — identical whether you're
the MCP server, the air CLI, or hand-rolled REST:
flowchart LR
A["Request needs auth?"] --> B{"AIR_API_KEY<br/>env set?"}
B -->|yes| K1["✅ Use it — every request,<br/>no exceptions"]
B -->|no| C{"~/.config/air/auth.json<br/>exists?"}
C -->|yes| K2["✅ Use saved token<br/>(written by `air login`,<br/>host-matched)"]
C -->|no| K3["👤 Anonymous<br/>(works, rate-limited harder)"]
style K1 fill:#0aa,color:#fff
style K2 fill:#0aa,color:#fff
style K3 fill:#666,color:#fff
AIR_API_KEYenv var, if set — attaches to every request, no exceptions. Best for CI or a sandboxed agent run.~/.config/air/auth.json(mode0600) — written once byair loginin any client (CLI, MCP server, toolbar). Shape:{"token", "host", "user": {"name","email"}, "expires_at", "created_at"}. A file-sourced token only attaches to requests whose host matches the savedhost.- Anonymous — no token needed. Works, just rate-limited harder. 🐌
Header either way: Authorization: Bearer <token>. An agent never needs to implement the PKCE
browser login itself — that's air login's job.
sequenceDiagram
autonumber
participant Agent as 🤖 Agent
participant Client as MCP / CLI / REST
participant API as airanks.net/api/v1
Agent->>Client: "what's example.com's AI rank?"
Client->>Client: resolve auth (env → auth.json → anon)
Client->>API: GET /v1/domains/example.com
alt first-ever lookup
API-->>Client: 200, ai_files.status = "pending"
loop poll every ~15-20s, up to ~3 min
Client->>API: GET /v1/domains/example.com
end
API-->>Client: 200, score ready
else already tracked
API-->>Client: 200, { air_score, tracked, ... }
end
Client-->>Agent: AIR score + signals
A 429 carries a Retry-After header — sleep that long and retry once, never hot-loop it. A
pending first-lookup score is a placeholder 0, never report it as a real measured score.
If you're on Claude Code or Claude Desktop and just want the trigger without wiring MCP yourself, copy the skill in:
cp -r agent-toolkit/skills/airanks ~/.claude/skills/It fires on "what's my AI rank", "am I AI-optimized", "check this domain's AI visibility", and routes MCP → CLI → REST in that order, same as everything else in this toolkit.
agent-toolkit/
├── README.md this file
├── AGENTS.md the contract — point any agent here
├── SETUP.md copy-paste MCP config per harness
├── LICENSE MIT
└── skills/airanks/
└── SKILL.md SKILL.md for Claude Code / Claude Desktop
| Repo | What it is |
|---|---|
| 🏆 airanks.net | The AIR rankings platform |
| 🧰 airanks.net/toolbar | Browser toolbar — AI optimization signal, live |
📗 ../API-CONTRACT.md |
Full API + auth contract (edge cases, PKCE flow, exit codes) |
⌨️ ../node-cli |
Reference air CLI (Node) |
🔌 ../mcp-server |
@airanks-net/mcp-server — the MCP server every config above points to |
MIT — see LICENSE.
Made for agents, by agents' humans. Wire it once, AIR everywhere. 🌬️