Agent-Ready Docs
This page is intentionally written for human readers. It explains how the Next example app serves a single docs topic in two different forms:
/docs/getting-started/agent-ready-docsfor human HTML/docs/getting-started/agent-ready-docs.mdfor the page's directagent.md/docs/getting-started/agent-ready-docswithSignature-Agentfor automatic markdown
Because this folder includes a sibling agent.md, the .md route returns that file. For pages
without agent.md, the same .md route and header-based markdown response fall back to the normal
page markdown.
What To Open
- Open
/docs/getting-started/agent-ready-docsin the browser to see the full narrative. - Open
/docs/getting-started/agent-ready-docs.mdto see the focused agent payload. - Request
/docs/getting-started/agent-ready-docswithSignature-Agentto get the same focused payload from the canonical URL. - Use your own prompt cases to compare the human page output and the markdown agent payload.
- Compare how much broader explanation humans get versus how much narrower implementation detail an agent gets.
Why It Matters
This is the simplest version of the pattern you wanted:
- one folder
- one
page.mdx - one
agent.md - two audience-specific experiences from the same slug
Feature Goal
The example app exposes two ways to read the same docs topic:
/docs/<slug>for human HTML pages/docs/<slug>.mdfor machine-readable markdown/docs/<slug>withSignature-Agentfor agents that read canonical URLs
When a page folder has an agent.md, the .md route and Signature-Agent response should return
that file. When it does not, both markdown entry points should fall back to the normal page
markdown.
That fallback comes from the same docs source lookup used by the shared page reader, so pages
without agent.md do not need any extra configuration.
Files Involved
The key files for this flow are:
examples/next/next.config.ts
examples/next/app/api/docs/mcp/route.ts
examples/next/app/docs/getting-started/agent-ready-docs/page.mdx
examples/next/app/docs/getting-started/agent-ready-docs/agent.md
examples/next/docs.config.tsx
packages/docs/src/agent.ts
packages/next/src/config.ts
packages/next/src/api.tsZero-Config Layer
The public .md URL now comes from withDocs() itself. Apps do not need to add their own
rewrites or a custom markdown catch-all route.
export default withDocs({
distDir: process.env.NODE_ENV === "production" && !process.env.VERCEL ? ".next-build" : ".next",
turbopack: {
root: repoRoot,
},
});Built-In Markdown Route
withDocs() wires the public .md URLs into the existing /api/docs handler. The public rewrite
lands on /api/docs with format=markdown, so the shared docs API accepts both direct markdown
queries and rewritten page URLs like /docs/getting-started/agent-ready-docs.md:
function buildDocsMarkdownRewrites(entry: string) {
return [
{
source: `/${entry}.md`,
destination: "/api/docs?format=markdown",
},
{
source: `/${entry}/:slug*.md`,
destination: "/api/docs?format=markdown&path=:slug*",
},
];
}const markdownRequest = resolveMarkdownRequest(entry, url);
if (markdownRequest) {
const requestedPath = markdownRequest.requestedPath;
const document = await getMarkdownDocument(ctx, requestedPath);
if (!document) return new Response("Not Found", { status: 404 });
return new Response(document, {
headers: { "Content-Type": "text/markdown; charset=utf-8" },
});
}Signature-Agent Auto-Rewrite
Some agents fetch the canonical page URL and identify themselves with Signature-Agent instead of
sending Accept: text/markdown. withDocs() handles that case automatically: the normal HTML URL
continues to work for browsers, while requests with the header are rewritten to the existing
/api/docs handler with format=markdown.
curl http://localhost:3000/docs/getting-started/agent-ready-docs \
-H "Signature-Agent: https://chatgpt.com"{
source: `/${entry}/:slug*`,
has: [{ type: "header", key: "signature-agent" }],
destination: "/api/docs?format=markdown&path=:slug*",
}No docs config flag is required. The header only changes docs page responses under the configured
entry route, so unrelated pages are not hijacked. No extra API wrapper is generated; the existing
app/api/docs/route.ts remains the single docs API entry point.
MCP Route
The example app also exposes the standard MCP surface:
import docsConfig from "@/docs.config";
import { createDocsMCPAPI } from "@farming-labs/next/api";
export const { GET, POST, DELETE } = createDocsMCPAPI(docsConfig);When agent.md exists, the .md route returns that file. MCP remains available for tool-based
access and parity checks, but the HTTP .md route is the simple public contract.
MCP Code Examples
The MCP server also exposes get_code_examples. It scans fenced code blocks from the raw markdown
source and returns parsed metadata without changing the rendered code block UI.
Use metadata on examples that agents should treat as implementation-ready:
```ts title="docs.config.ts" framework="nextjs" packageManager="pnpm" runnable
import { defineDocs } from "@farming-labs/docs";
export default defineDocs({
entry: "docs",
});
```An MCP client can request only matching examples:
{
"name": "get_code_examples",
"arguments": {
"path": "getting-started/quickstart",
"framework": "nextjs",
"packageManager": "pnpm",
"runnable": true
}
}The get_code_examples response is JSON, so agents do not need to scrape rendered HTML:
{
"examples": [
{
"language": "ts",
"title": "docs.config.ts",
"framework": "nextjs",
"packageManager": "pnpm",
"runnable": true,
"page": {
"url": "/docs/getting-started/quickstart"
},
"code": "import { defineDocs } from \"@farming-labs/docs\";\\n..."
}
]
}The MCP server also exposes list_docs for structured discovery before reading page bodies:
{
"name": "list_docs",
"arguments": {
"section": "getting-started"
}
}The response includes matching page summaries plus a section tree:
{
"section": "getting-started",
"resultCount": 1,
"sectionCount": 1,
"pages": [
{
"slug": "getting-started/quickstart",
"url": "/docs/getting-started/quickstart",
"title": "Quickstart"
}
],
"sections": [
{
"slug": "getting-started",
"title": "Getting Started",
"pageCount": 1
}
]
}The MCP server also exposes get_config_schema for agents that need to edit docs.config.ts
without guessing option names or defaults:
{
"name": "get_config_schema",
"arguments": {
"option": "mcp.tools.getConfigSchema"
}
}Use query instead of option when the agent only knows the feature area, such as llms or
page actions.
A filtered get_config_schema response includes the matching option metadata:
{
"schemaVersion": 1,
"configFile": "docs.config.ts",
"filters": {
"option": "mcp.tools.getConfigSchema"
},
"resultCount": 1,
"options": [
{
"path": "mcp.tools.getConfigSchema",
"name": "getConfigSchema",
"type": "boolean",
"default": true,
"description": "Expose the get_config_schema tool."
}
]
}Docs Config
The example app does not need any MCP flag. withDocs() picks up the default MCP surface
automatically, so the markdown route and MCP can both be exercised without extra config:
export default defineDocs({
entry: "docs",
ordering: "numeric",
pageActions: {
copyMarkdown: { enabled: true },
},
});Folder Convention
For this exact showcase, the folder is intentionally minimal:
app/docs/getting-started/agent-ready-docs/
page.mdx
agent.mdThat is the whole pattern.
Request Flow
When a request comes in for /docs/getting-started/agent-ready-docs.md, withDocs() handles the
rewrite automatically into the existing /api/docs handler. The shared docs API accepts either the
explicit format=markdown&path=... query produced by the rewrite or a direct .md pathname in
adapters that pass the public URL through, then resolves the requested slug and checks whether the
page has agentRawContent.
When a request comes in for /docs/getting-started/agent-ready-docs with Signature-Agent,
withDocs() rewrites it into the existing /api/docs handler with format=markdown and the
current docs slug as path. The same generated app/api/docs/route.ts handles search, markdown,
llms.txt, skill, sitemap, feedback, and agent discovery formats.
Because this page has a sibling agent.md, the response becomes the raw contents of that file. If
another page does not have agent.md, the same route falls back to the normal page markdown.
Useful Commands
curl http://localhost:3000/docs/getting-started/agent-ready-docs
curl http://localhost:3000/docs/getting-started/agent-ready-docs.md
curl http://localhost:3000/docs/getting-started/agent-ready-docs \
-H "Signature-Agent: https://chatgpt.com"
curl http://localhost:3000/docs/getting-started/quickstart.mdFor MCP parity checks:
curl http://localhost:3000/api/docs?format=markdown\&path=getting-started/quickstartGotchas
- In the Next example,
contentDirshould default toapp/${entry}when the config does not set it explicitly. - The
.mdroute is automatic in Next when you usewithDocs(). Signature-Agentis automatic in Next when you usewithDocs()and does not require adocs.configoption.agent.mdshould stay hidden from normal docs discovery and sidebar generation.- When
agent.mdexists, it overrides the normal markdown for that slug.
Why This Page Exists
This page is intentionally richer and more explanatory than the agent override. It is meant to show
that you can keep all the human context you want in page.mdx while still serving a tight
implementation-oriented document to agents from the exact same folder.