fix(agent-score): directive placement, markdown parity, MCP endpoints - #8099
Conversation
Fixes the three regressing checks in the Mintlify/afdocs agent-readiness
audit and adds guards so they stay fixed:
Content Discoverability (directive buried past 50% of the HTML):
- Move the hidden llms.txt directive to the first child of <body> in the
docs root layout; the sidebar markup previously pushed it to 30-88% of
the body. Now sits at 0-1% on every page.
Markdown Content Parity (pages failing at 52-90% missing):
- Restore heading markers in getLLMText output from the page toc —
fumadocs' processed markdown emits headings as bare "Text [#anchor]"
lines, so "## 1. Set up your project" degraded to a stripped list item
on the markdown side.
- Convert <details>/<summary> to a bold summary + dedented body; the
serialized 2-space indent broke the code fences inside.
- Wrap the OpenAPI explorer (APIPage) in data-markdown-ignore; the
interactive reference has no markdown equivalent and the .md already
carries the generated API summary.
- Unescape remark escapes (\_, \{, \}) outside code so prose like
snake_case matches the rendered HTML.
MCP Server Discoverable (no server at expected endpoints):
- New /docs/mcp route proxies MCP protocol traffic to mcp.prisma.io/mcp
(browser GETs redirect to the /mcp marketing page).
- Header-matched beforeFiles rewrites on the site route MCP traffic on
www.prisma.io/mcp to the real server; browsers still get the page.
Guards: lint-agent-ready now checks directive-first-in-body, heading
markers across all pages, <details> leakage, the APIPage parity wrapper,
and both MCP endpoints. Skill docs updated with the new invariants and
an afdocs reproduction playbook.
Verified with the afdocs CLI against a local production build: directive
+ parity + markdown-url + content-negotiation all pass on the 20 pages
that previously failed or warned (avg 1% missing, was avg 8%).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe change strengthens documentation HTML/Markdown parity checks, moves the hidden agent directive into the root layout, adds normalization for headings and details blocks, and introduces MCP proxy and rewrite routing with corresponding audit validation and documentation. ChangesAgent-readiness documentation flow
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Site
participant DocsMCP
participant MCPServer
Client->>Site: Send MCP request to /mcp
Site->>MCPServer: Rewrite matching protocol traffic
Client->>DocsMCP: Send request to /docs/mcp
DocsMCP->>MCPServer: Proxy supported MCP method
MCPServer-->>DocsMCP: Return streamed response
DocsMCP-->>Client: Return response or redirect
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
.claude/skills/docs-agent-ready/SKILL.md (1)
65-73: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low valueConsider pinning the
afdocsCLI version in reproduction commands.Static analysis flags the unpinned
npx afdocs check ...invocations as a supply-chain "rug pull" risk (a compromised/updated upstream package could silently change behavior for anyone reproducing the audit).-npx afdocs check https://www.prisma.io/docs --sampling deterministic -v +npx afdocs@<pinned-version> check https://www.prisma.io/docs --sampling deterministic -v🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.claude/skills/docs-agent-ready/SKILL.md around lines 65 - 73, Pin the afdocs CLI version in both reproduction commands under “Reproducing the audit” by using an explicit version with npx, keeping the existing arguments and audit behavior unchanged.Source: Linters/SAST tools
apps/docs/scripts/lint-agent-ready.ts (1)
466-479: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winMCP site-rewrite check passes with only 1 of the 3 required header-matched rewrites.
mcpRewriteCount === 0only fails if none of the/mcprewrite blocks exist; per the routing comment inapps/site/next.config.mjs, all three header conditions (accept: text/event-stream, content-type: application/json, mcp-session-id) are needed to cover the full MCP Streamable HTTP transport (GET stream, POST messages, DELETE teardown). A regression that drops 2 of the 3 rewrites would still pass this check.♻️ Proposed fix — require all three header-matched rewrites
- const mcpRewriteCount = ( - siteConfigSource.match(new RegExp(`source: "/mcp",\\s*\\n\\s*has:`, "g")) ?? [] - ).length; - if (mcpRewriteCount === 0 || !siteConfigSource.includes(`destination: "${MCP_URL}"`)) { + const requiredMcpHeaderKeys = ["accept", "content-type", "mcp-session-id"]; + const missingMcpHeaderRewrites = requiredMcpHeaderKeys.filter( + (key) => !new RegExp(`source: "/mcp",[\\s\\S]*?key: "${key}"`).test(siteConfigSource), + ); + if (missingMcpHeaderRewrites.length > 0 || !siteConfigSource.includes(`destination: "${MCP_URL}"`)) { mcpEndpointErrors.push( - `site: next.config.mjs is missing the header-matched /mcp rewrites to "${MCP_URL}"`, + `site: next.config.mjs is missing /mcp rewrite(s) for header key(s): ${missingMcpHeaderRewrites.join(", ")}`, );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/docs/scripts/lint-agent-ready.ts` around lines 466 - 479, Update the MCP rewrite validation in the site next.config.mjs check to require all three header-matched /mcp rewrites, replacing the current zero-count threshold with a count of three while preserving the destination URL validation and existing error reporting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/docs/src/app/layout.tsx`:
- Around line 114-137: Update the hidden directive div in the layout’s body
content to include aria-hidden="true", and remove its embedded link from
keyboard navigation with tabIndex={-1}. Preserve the existing markup, text,
styling, and first-child placement so the raw HTML/DOM byte-position audit
remains unchanged.
In `@apps/docs/src/app/mcp/route.ts`:
- Around line 46-47: Bound request-body buffering in the route handler around
the request.arrayBuffer() call: reject requests whose declared Content-Length
exceeds the configured maximum, and read the body through a bounded reader that
stops and rejects once the limit is exceeded, including chunked requests without
a declared length. Preserve undefined bodies for GET and HEAD requests and only
invoke fetch after validation completes.
- Around line 49-54: Add an AbortController-based timeout around the upstream
fetch in the MCP route, applying the signal to fetch so stalled connection or
header acquisition is aborted after the configured duration. Preserve
upstream.body streaming behavior for SSE responses and ensure the controller
lifecycle does not prematurely cancel an established stream.
---
Nitpick comments:
In @.claude/skills/docs-agent-ready/SKILL.md:
- Around line 65-73: Pin the afdocs CLI version in both reproduction commands
under “Reproducing the audit” by using an explicit version with npx, keeping the
existing arguments and audit behavior unchanged.
In `@apps/docs/scripts/lint-agent-ready.ts`:
- Around line 466-479: Update the MCP rewrite validation in the site
next.config.mjs check to require all three header-matched /mcp rewrites,
replacing the current zero-count threshold with a count of three while
preserving the destination URL validation and existing error reporting.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 232bb563-0a5c-4296-aacb-e289436e556b
📒 Files selected for processing (9)
.claude/skills/docs-agent-ready/SKILL.mdapps/docs/scripts/lint-agent-ready.tsapps/docs/src/app/(docs)/(default)/[[...slug]]/page.tsxapps/docs/src/app/layout.tsxapps/docs/src/app/mcp/route.tsapps/docs/src/components/api-page.tsxapps/docs/src/lib/get-llm-text.tsapps/docs/src/lib/llm-markdown.tsapps/site/next.config.mjs
- Hide the llms.txt directive from screen readers and the tab order
(aria-hidden + tabIndex={-1}); audits read raw HTML, not the a11y tree.
- Bound the /docs/mcp proxy: reject request bodies over 1 MiB (413, also
for chunked bodies without Content-Length) and abort the upstream fetch
if headers take more than 30s, while keeping SSE bodies streaming.
- lint-agent-ready now requires all three header-matched /mcp rewrites
(accept, content-type, mcp-session-id), not just one.
- Pin the afdocs version in the skill's reproduction commands.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/docs/scripts/lint-agent-ready.ts`:
- Around line 473-475: The missingMcpHeaderRewrites validation currently matches
source and header keys across different rewrite entries. Update this check to
isolate each individual rewrite object, then validate that the same entry
contains source "/mcp", the required header key, and its destination together;
preserve the existing missing-key reporting behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 15900ced-5e2f-4091-99da-9695259cebb6
📒 Files selected for processing (4)
.claude/skills/docs-agent-ready/SKILL.mdapps/docs/scripts/lint-agent-ready.tsapps/docs/src/app/layout.tsxapps/docs/src/app/mcp/route.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/docs/src/app/layout.tsx
- .claude/skills/docs-agent-ready/SKILL.md
The per-key regex could pair `source: "/mcp"` from one rewrite with a header key from a neighbouring entry (and ast-grep flagged the variable RegExp). Split the config into per-rewrite chunks at each `source:` and require the header key and MCP destination together in the same chunk, using static string matching. Verified the guard now fails when an entry is dropped or a destination is changed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/prisma/web into agent-score-directive-parity-mcp
|
@coderabbitai resolve All findings addressed:
|
|
✅ Action performedComments resolved and changes approved. |
TL;DR
The agent-readiness audit (afdocs) flags three things on www.prisma.io/docs. This PR fixes all three and adds CI guards so they stay fixed. Verified locally with the real audit CLI against a production build: all previously failing checks pass.
<body>in the docs layout (now at 0–1%).mdpipeline lost headings, broke fences in<details>, and the OpenAPI explorer has no markdown twin<details>;data-markdown-ignoreonAPIPage; unescape\_\{in prose/mcp<origin>/mcpwith an MCP initialize;/mcpis a marketing page/docs/mcpproxy route tomcp.prisma.io/mcp+ header-matched rewrites on site/mcp(browsers still get the page)Details
Directive. afdocs measures where the llms.txt link sits in the raw HTML body and warns when it's past 50%. It's now a visually-hidden,
aria-hiddenfirst child of<body>inapps/docs/src/app/layout.tsx, removed from the per-page component.Parity. afdocs extracts text segments from the HTML and checks each exists in the
.md. Three pipeline bugs made real content vanish from the markdown side:Text [#anchor]lines —getLLMTextnow restores##markers from the page toc, so every.mdhas real headings (this alone fixed ~7 warning pages with "1. Set up…" step headings).<details>bodies serialize 2-space indented, which un-fences the code blocks inside — newformatDetailstransform emits a bold summary + dedented body.data-markdown-ignore(the audit's sanctioned mechanism); the.mdkeeps the generated API summary.MCP.
/docs/mcpproxies MCP protocol traffic (POST / SSE GET / DELETE) to the real OAuth-gated server, preserving theWWW-Authenticatechallenge; plain browser GETs redirect to the/mcpmarketing page. On the site, three header-matchedbeforeFilesrewrites do the same forwww.prisma.io/mcp. Note: the server requires OAuth — if the checker insists on an unauthenticated tool list, a public no-auth server would be a separate product decision.Guards.
lint:agent-readygains checks for: directive-first-in-<body>, heading markers across all 621 pages,<details>leakage, theAPIPagewrapper, and both MCP endpoints. Thedocs-agent-readyskill documents the invariants and how to reproduce the audit (npx afdocs@0.18.7 check …).CodeRabbit review (all 5 findings addressed in 97c9b02):
aria-hiddenwithtabIndex={-1}— invisible to screen readers and the tab order/mcpheader rewrites, not just oneVerification
lint:agent-ready26 checks, 0 failures / 0 warnings;test:llm-markdown9/9; both apps typecheck.mdURLs + content negotiation 20/20/docs/mcpmanually probed: initialize → 401 +WWW-Authenticate(spec-compliant), 2 MiB body → 413, browser GET → 307After deploy:
npx afdocs@0.18.7 check https://www.prisma.io/docs --sampling deterministic -vto confirm the production score.🤖 Generated with Claude Code
Summary by CodeRabbit
llms.txt, including Markdown versions via.mdURLs./docs/mcpproxy and site-side/mcpheader-based routing for streaming and session traffic.<details>/<summary>reliably, and protect fenced/inline code for better HTML/Markdown parity.