AI と LLM
Fumadocs に AI 機能を組み込みます。
LLM向けドキュメント
LLMやAIエージェント向けに、ドキュメントをMarkdown形式で提供します。
npx @fumadocs/cli feature llmsこれにより、docs コレクションで処理済みの Markdown が有効になり、lib/source.ts に docsLlms が追加されて、以下のファイルが配信されます。手動でセットアップする場合に備えて、生成されるファイルを以下に記載しています。
docsLlms
llms() は、ドキュメントを LLM 向けにレンダリングします。renderPage は、生のファイル内容ではなく処理済みのドキュメントをもとに、1 つのページを Markdown に変換します。
import { llms } from 'fumadocs-core/source';
export const docsLlms = llms(source, {
renderPage: async (page) => `# ${page.data.title} (${page.url})
${await page.data.getText('processed')}`,
});
| メソッド | 出力 |
|---|---|
index(lang?) | ページツリーから構築される llms.txt インデックス |
page(page) | renderPage でレンダリングした 1 つのページ |
full(lang?) | renderPage でレンダリングした全ページを結合したもの |
files() | エージェント向けファイルのパス |
serve(path) | 指定したパスにあるファイルのレスポンス |
renderPage は必須です
コンテンツソースが Markdown をどのように公開しているかを Fumadocs 側では判断できないため、page()、full()、files()、serve() は
renderPage を渡した場合にのみ利用できます。
renderPage はページの処理済み Markdown を読み取るため、includeProcessedMarkdown を有効にしてください。
import { defineConfig } from 'astro/config';
import fumadocs from '@fumadocs/astro';
export default defineConfig({
integrations: [
fumadocs({
includeProcessedMarkdown: true,
}),
],
});MDX コンポーネントは、Markdown 形式を定義していない限り、JSX 構文のまま出力されます。
@fumadocs/local-md のようなランタイムのコンテンツソースは、リクエスト時に解決されます。その getSource を渡すと、CLI が同じファイルを生成します。
export const docsLlms = llms(getSource, {
renderPage: (page) => `# ${page.data.title} (${page.url})
${page.data.content}`,
});getSource を使用する場合、index() と indexNode() は文字列ではなく Promise を返します。
ファイル
CLIは、AIエージェント向けに次のファイルを配信します。
/llms.txt: ドキュメントのインデックスです。各ページのMarkdownへのリンクが含まれます。/llms-full.txt: 全ページのコンテンツです。<page>.md: 各ページのMarkdownです (例:/docs/ui.md) 。/のページは/index.mdになります。<section>/llms-full.txt: セクションのコンテンツです (例:/docs/ui/llms-full.txt) 。
下書きなどのページをこれらのファイルから除外するには、filter を指定します。除外したページも llms.txt には引き続き掲載され、HTMLページへのリンクになります。
export const docsLlms = llms(source, {
filter: (page) => page.slugs[0] !== 'drafts',
renderPage: async (page) => `# ${page.data.title}\n\n${await page.data.getText('processed')}`,
});これらのファイルでは、renderUrl はリンク先のファイルのパス (ページの .md ファイルなど) を受け取ります。
ページの HTML を読み取るエージェントは、<head> 内のリンクからそのページの Markdown を見つけます:
<link rel="alternate" type="text/markdown" href="/docs/ui.md" />セクション
セクションとは、独自の llms-full.txt を持つページツリー内のフォルダーです。これにより、エージェントは大規模なドキュメントを部分ごとに読み込めます。デフォルトでは、すべてのルートフォルダーがセクションになります。llms.txt では、各フォルダーの行がそのセクションの llms-full.txt へのリンクになります。
セクションとするフォルダーを指定するには、section を渡します。この関数はフォルダーを受け取り、そのフォルダーをセクションとするかどうかを返します。
export const docsLlms = llms(source, {
// index ページを持つすべてのフォルダー
section: (folder) => folder.index !== undefined,
renderPage: async (page) => `# ${page.data.title}\n\n${await page.data.getText('processed')}`,
});大規模なサイトでは、セクションを折りたたむと llms.txt を短く保てます。折りたたんだセクションは、llms.txt ではそのセクション専用の <section>/llms.txt への1つのリンクとして記載され、セクション内のページはそのファイルに一覧表示されます。
export const docsLlms = llms(source, {
section: (folder) => (folder.root ? { collapse: true } : false),
renderPage: async (page) => `# ${page.data.title}\n\n${await page.data.getText('processed')}`,
});セクションのファイルは、そのフォルダーのインデックスページの URL 配下で配信されます。インデックスページがないフォルダーでは、代わりに配下のページの URL ディレクトリが使われます。フォルダーグループのように 2 つのフォルダーが同じ URL を共有する場合は、asPath を渡すと、一方を別のパスで配信できます (例:{ asPath: '/docs/guides' }) 。
ルート
files() はファイルのパスを列挙し、serve(path) は指定したパスのファイルをレスポンスとして返します。そのため、各ルートはリクエストパスを serve() に渡すだけで済みます。
1つのエンドポイントで、すべてのファイルをそれぞれのパスにプリレンダリングします:
import type { APIRoute, GetStaticPaths } from 'astro';
import { docsLlms } from '@/lib/source';
export const prerender = true;
export const getStaticPaths = (async () => {
const paths: { params: { path: string } }[] = [];
for (const path of await docsLlms.files()) paths.push({ params: { path: decodeURI(path.slice(1)) } });
return paths;
}) satisfies GetStaticPaths;
export const GET: APIRoute = async ({ params }) => (await docsLlms.serve(`/${params.path}`))!;
serve() はファイルが存在しないパスに対して undefined を返すため、ミドルウェアはリクエストを後続の処理に渡せます。hideLocale: 'always' を指定した場合は URL にロケールが含まれないため、言語を serve() の第2引数、および files() の第1引数として渡してください。
静的出力
エンドポイントは、アダプターの有無にかかわらずプリレンダリングされます。
Accept
ドキュメントページでは、Accept ヘッダーに応じて Markdown を返すことはできません。Astro のミドルウェアはリクエスト時にレンダリングされるページでしか実行されず、ドキュメントページはプリレンダリングされるためです。
ページアクション
ページアクションを使うと、読者はページの Markdown をコピーしたり、AI アプリでページを開いたりできます。ページアクションは、ページの .md ファイルを読み込みます。

docs ページから React アイランドに Markdown の URL を渡し、アイランド内でレンダリングしてください。
<Docs
client:load
markdownUrl={`${page.url}.md`}
githubUrl={`https://github.com/${owner}/${repo}/blob/main/content/docs/${encodeURI(page.path)}`}
>
<Content />
</Docs>MCP サーバー
MCP サーバーを通じてドキュメントをAIエージェントに公開できます。ページの一覧表示・検索・読み取りを行うツールも提供されます。
npx @fumadocs/cli feature mcp上記の LLM ルート に加えて、Streamable HTTP トランスポートを使用する /api/mcp ルートを作成します。
ツールは fumadocs-core/mcp によって提供されます。
import type { APIRoute } from 'astro';
import { createMcpHandler, McpServer } from '@modelcontextprotocol/server';
import { registerSearchTool, registerSourceTools } from 'fumadocs-core/mcp';
import { createFromSource } from 'fumadocs-core/search/server';
import { docsLlms, source } from '@/lib/source';
const handler = createMcpHandler(() => {
const mcp = new McpServer(
{
name: 'docs',
version: '1.0.0',
},
// the tools never change, a stream to watch them would hold a serverless function open
{ capabilities: { tools: { listChanged: false } } },
);
registerSourceTools(mcp, source, docsLlms);
registerSearchTool(mcp, createFromSource(source));
return mcp;
});
export const prerender = false;
export const GET: APIRoute = async ({ request }) => handler.fetch(request);
export const POST: APIRoute = async ({ request }) => handler.fetch(request);
export const DELETE: APIRoute = async ({ request }) => handler.fetch(request);
このルートはリクエストごとにレンダリングされるため、プロジェクトに アダプター を導入する必要があります。
エージェントを接続するには、次のようにします。
{
"mcpServers": {
"docs": { "url": "https://your-site.com/api/mcp" }
}
}WebMCP
実験的機能
WebMCP は策定初期段階の Web 標準で、Chrome 149 以降で
#enable-webmcp-testing フラグを有効にするか、オリジントライアルを通じて利用できます。API は今後
変更される可能性があります。
前述の MCP サーバーがサイトに接続してくるエージェント向けであるのに対し、WebMCP は読者が閲覧しているページ上で、ブラウザに組み込まれた AIエージェント にツールを公開します。
npx @fumadocs/cli feature webmcpLLM ルートをベースにした WebMCP コンポーネントが作成されます。これを <RootProvider /> の内側でレンダリングしてください。
search_docsは検索 API ルートにクエリを送信します。fetchClientは他のクライアントに置き換えることもできます。read_pageは、/docs/page.mdからページの Markdown を取得します。
AIに質問

Fumadocs CLI を使用して、AI チャットダイアログをインストールできます。
npx @fumadocs/cli add ai/openrouterVercel AI SDK を使用して OpenRouter 向けに自動で設定され、AI 用の /search ツールも含まれます。
/api/chat ルートを更新すれば、他のモデルも使用できます。
Fumadocs は AI モデルを提供していません。モデルはご自身で用意してください。
AI モデルには、上記で生成した llms-full.txt ファイルを利用できます。また、サードパーティのソリューションと組み合わせれば、より多様な情報ソースを活用することもできます。
Docs レイアウトは、aiChat オプションをもとにチャットをレンダリングします。このオプションはクライアントの状態を受け取るため、レイアウト用のクライアントコンポーネントを作成し、元のレイアウトの代わりに使用してください。
'use client';
// Notebook、Glass、Spacious レイアウトも使用できます
import { DocsLayout as Layout, type DocsLayoutProps } from 'fumadocs-ui/layouts/docs';
// インストールしたコンポーネント
import { AIChat, AIChatPanel, useAIChat } from './search';
export function DocsLayout(props: DocsLayoutProps) {
return (
<AIChat>
<ChatLayout {...props} />
</AIChat>
);
}
function ChatLayout(props: DocsLayoutProps) {
const { open, setOpen } = useAIChat();
return (
<Layout
{...props}
aiChat={{ open, onOpenChange: setOpen, panel: <AIChatPanel />, trigger: true }}
/>
);
}How is this guide?
最終更新日
