Example Docs

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:

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

  1. Open /docs/getting-started/agent-ready-docs in the browser to see the full narrative.
  2. Open /docs/getting-started/agent-ready-docs.md to see the focused agent payload.
  3. Request /docs/getting-started/agent-ready-docs with Signature-Agent to get the same focused payload from the canonical URL.
  4. Use your own prompt cases to compare the human page output and the markdown agent payload.
  5. 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:

Feature Goal

The example app exposes two ways to read the same docs topic:

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.ts

Zero-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.

examples/next/next.config.ts
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:

packages/next/src/config.ts
function buildDocsMarkdownRewrites(entry: string) {
  return [
    {
      source: `/${entry}.md`,
      destination: "/api/docs?format=markdown",
    },
    {
      source: `/${entry}/:slug*.md`,
      destination: "/api/docs?format=markdown&path=:slug*",
    },
  ];
}
packages/fumadocs/src/docs-api.ts
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.

terminal
curl http://localhost:3000/docs/getting-started/agent-ready-docs \
  -H "Signature-Agent: https://chatgpt.com"
packages/next/src/config.ts
{
  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:

examples/next/app/api/docs/mcp/route.ts
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:

examples/next/docs.config.tsx
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.md

That 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

terminal
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.md

For MCP parity checks:

terminal
curl http://localhost:3000/api/docs?format=markdown\&path=getting-started/quickstart

Gotchas

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.