API for agents

Everything here is public and read-only — no account, token, or client needed. Point an agent at /llms.txt for a plain-text index of the whole site.

Fetch a spec

EndpointReturns
GET /specs/{owner}/{name}.mdThe latest version's raw markdown (text/markdown)
GET /specs/{owner}/{name}/{version}.mdA specific version's raw markdown. Versions are immutable, so this is safe to cache.
GET /api/specs/{owner}/{name}Metadata as JSON: title, version, keywords, functions, types, test-vector counts
GET /api/specs/{owner}/{name}/versionsVersion history as JSON
curl https://canra.dev/specs/canra/json.md

Raw responses send Access-Control-Allow-Origin: *, so browser-based tools can fetch them too. A quarantined spec returns 451; an unknown spec or version returns 404.

Search

EndpointReturns
GET /api/search?q={query}&page={n}Matching specs as JSON, ranked; 20 per page

Index

EndpointReturns
GET /llms.txtPlain text: what Canra is, these endpoints, and every published spec with its raw URL

MCP server

Canra is also a remote Model Context Protocol server at https://canra.dev/mcp (Streamable HTTP, no auth). Tools: search_specs, get_spec, and get_test_vectors. In Claude Code:

claude mcp add --transport http canra https://canra.dev/mcp

In Cursor and other clients, add a server with URL https://canra.dev/mcp.

Command line

The @canra/cli package wraps these endpoints and adds publishing (Node 20+, no install needed):

npx @canra/cli search json
npx @canra/cli info canra/json

Rate limits

Anonymous requests are limited to 60 per minute per IP; requests with an API token get 1000 per minute. Over the limit you get 429 with a Retry-After header.

Spec format

A spec is markdown with TOML front-matter between +++ lines (name, version, title, and optional [api] functions/types). Test vectors are JSON Lines inside fenced test-vectors blocks — one case per line with id, function, input.args, and an expected result. See the publishing guide for the full format.

Publishing

Publishing needs an account and an API token (Account → API tokens): POST /api/specs with the raw markdown as the body and Authorization: Bearer {token}. Details are in the publishing guide.