| name | docs-agent-ready |
| description | Use when adding a new docs section or product area, editing llms.ts / the llms.txt or llms/[...slug] / llms-full.txt routes / get-llm-text / skill.md / .well-known endpoints, or working on the "agent score", "llms.txt", or anything "agent-ready" in the docs and site apps. Explains the invariants the Mintlify agent-readiness audit measures and how to hold them. |
| metadata | {"author":"Prisma","version":"2026.7.24"} |
Docs agent-readiness
Keep Prisma's docs machine-readable so the Mintlify agent-score audit does not silently regress as content is added. The score measures whether AI agents can discover and fetch the docs: a working llms.txt index, per-page Markdown, a discoverable skill, and MCP discovery. The guard apps/docs/scripts/lint-agent-ready.ts (run pnpm --filter docs lint:agent-ready) enforces the invariants below on every PR via .github/workflows/links.yml.
Invariants
- Root
llms.txt < 50k bytes (warn at 35k). It links to per-area section indexes, not every page.
- Each section index < 50k bytes (warn at 40k). Over budget means split the section.
- Every page is reachable — each
filterPagesForLLMsIndex page appears in a section file or the root "Other pages" list. The guard asserts against the generated content, not just membership.
- Directives in HTML + Markdown — every page's Markdown (
getLLMText) starts with the hidden llms.txt directive blockquote; the HTML keeps a hidden directive as the first child of <body> in the root layout (apps/docs/src/app/layout.tsx), NOT inside the page component. Audits measure the directive's byte position in the body and warn when it sits past 50%, which is where it lands if rendered after the sidebar markup.
- HTML/Markdown parity via
data-markdown-ignore on human-only chrome so the Markdown mirrors the page. The OpenAPI explorer (APIPage wrapper in src/components/api-page.tsx) carries data-markdown-ignore because the interactive reference has no markdown equivalent — the .md serves the generated API summary instead.
- Markdown keeps real headings — fumadocs' processed output emits headings as bare
Text [#anchor] lines; getLLMText restores ## markers from the page toc (restoreHeadingMarkers in llm-markdown.ts). Without them, parity checkers strip list-like heading text ("## 1. Set up …") and agents see prose instead of structure.
<details> blocks are converted to a bold summary line + dedented body (formatDetails in llm-markdown.ts); serialized <details> children are 2-space indented, which silently breaks the code fences inside for markdown consumers.
llms-full.txt excludes legacy /orm/v6 and the Accelerate/Optimize products (getLLMsFullPages).
- Skill + MCP endpoints live at BOTH roots:
www.prisma.io (apps/site) and /docs (apps/docs).
File map
| Endpoint | Generated by |
|---|
/docs/llms.txt | apps/docs/src/app/llms.txt/route.ts → buildLLMsIndexContent (llms.ts) |
/docs/llms/<slug>.txt | apps/docs/src/app/llms/[...slug]/route.ts → buildLLMsSectionContent (llms.ts) |
/docs/llms-full.txt | apps/docs/src/app/llms-full.txt/route.ts → getLLMsFullPages (llms.ts) + getLLMText |
/docs/<page>.md | apps/docs/src/lib/get-llm-text.ts (getLLMText) |
/docs/skill.md | apps/docs/src/app/skill.md/route.ts → apps/docs/src/lib/agent-skill.ts |
/docs/.well-known/mcp[.json] | apps/docs/src/lib/mcp-discovery.ts |
/skill.md, /.well-known/agent-skills/* | apps/site/src/lib/agent-skills.ts (buildSkillMarkdown) |
/.well-known/mcp* (site) | apps/site/src/lib/agent-skills.ts (buildMcpDiscovery, server cards) |
/docs/mcp (MCP proxy) | apps/docs/src/app/mcp/route.ts → proxies protocol traffic to mcp.prisma.io/mcp |
/mcp (site, MCP traffic) | header-matched beforeFiles rewrites in apps/site/next.config.mjs (browser GETs still get the marketing page) |
The route handlers are thin wrappers: shared builders in llms.ts are the single source of truth, so the guard measures exactly what the routes serve.
Playbooks
(a) Adding a new docs area. Add an entry to llmsSections in apps/docs/src/lib/llms.ts with prefixes (and excludePrefixes if a sub-tree belongs elsewhere). Run pnpm --filter docs lint:agent-ready. A "Catch-all creep" warning (> 25 pages in root "Other pages") means a new docs area needs its own section here.
(b) Section over budget. When a section fails/warns on size, split it into two sections in llmsSections (narrower prefixes, or carve a sub-tree out with a new slug). Re-run the guard.
(c) Changing page chrome. The hidden llms.txt directive lives in apps/docs/src/app/layout.tsx as the first child of <body> — keep it there (before <Banner), never move it into the page component where the sidebar markup would push it past 50% of the HTML. In [[...slug]]/page.tsx, put data-markdown-ignore on any human-only chrome (banners, nav, badges) so it stays out of the parity comparison. New interactive/human-only MDX components should get data-markdown-ignore on their wrapper plus a markdown fallback in normalizeProcessedMarkdown (llm-markdown.ts), following APIPage/formatApiPage.
(d) Changing the CLI workflow or MCP tools in docs content: update the skill copy in apps/site/src/lib/agent-skills.ts AND apps/docs/src/lib/agent-skill.ts — they quote real commands and tool names. Keep them in sync with the Prisma Postgres quickstart and content/docs/ai/tools/mcp-server.mdx. The commonQueries links in llms.ts must point to existing pages (the guard fails on stale links).
(e) Verification.
pnpm --filter docs lint:agent-ready
pnpm --filter docs test:llm-markdown
pnpm --filter docs types:check
curl -s https://www.prisma.io/docs/llms.txt | head
curl -s https://www.prisma.io/docs/skill.md | head
curl -s https://www.prisma.io/.well-known/mcp
The guard prints a size table with per-file headroom so reviewers see how close each file is to its budget.
(f) Reproducing the audit. The audit is the afdocs npm CLI (https://afdocs.dev). To reproduce a report locally:
npx afdocs@0.18.7 check https://www.prisma.io/docs --sampling deterministic -v
npx afdocs@0.18.7 check https://www.prisma.io/docs \
--checks markdown-url-support,content-negotiation,markdown-content-parity \
--sampling deterministic --format json -v
Audit gotchas encoded in the invariants above: the HTML directive check needs an <a href*="/llms.txt"> within the first 10% of the (nav/script/style-stripped) <body> on sampled pages and warns when every match sits past 50%; the parity check compares HTML text segments against the .md, strips data-markdown-ignore elements from the HTML side, and only treats a fenced code block as protected when the fence starts at column 0 — which is why <details> bodies must be dedented and headings must keep their # markers. The separate "MCP Server Discoverable" check probes <origin>/mcp with an MCP initialize request (discovery documents alone do not count), which is what the /docs/mcp proxy route and the site /mcp rewrites are for.