A Docusaurus plugin that exposes an MCP (Model Context Protocol) server endpoint, allowing AI agents like Claude, Cursor, and other MCP-compatible tools to search and retrieve your documentation.
npm install docusaurus-plugin-mcp-server// docusaurus.config.js
module.exports = {
plugins: [
[
'docusaurus-plugin-mcp-server',
{
server: {
name: 'my-docs',
version: '1.0.0',
},
},
],
],
};Choose your deployment platform:
Vercel
Create api/mcp.js:
import { createVercelHandler } from 'docusaurus-plugin-mcp-server/adapters';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export default createVercelHandler({
docsPath: path.join(__dirname, '../build/mcp/docs.json'),
indexPath: path.join(__dirname, '../build/mcp/search-index.json'),
name: 'my-docs',
baseUrl: 'https://docs.example.com',
});Add to vercel.json:
{
"functions": {
"api/mcp.js": {
"includeFiles": "build/mcp/**"
}
},
"rewrites": [
{ "source": "/mcp", "destination": "/api/mcp" }
]
}Netlify
Create netlify/functions/mcp.js:
import { createNetlifyHandler } from 'docusaurus-plugin-mcp-server/adapters';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export const handler = createNetlifyHandler({
docsPath: path.join(__dirname, '../../build/mcp/docs.json'),
indexPath: path.join(__dirname, '../../build/mcp/search-index.json'),
name: 'my-docs',
baseUrl: 'https://docs.example.com',
});Add to netlify.toml:
[build]
publish = "build"
[functions]
directory = "netlify/functions"
included_files = ["build/mcp/**"]
[[redirects]]
from = "/mcp"
to = "/.netlify/functions/mcp"
status = 200Cloudflare Workers
Cloudflare Workers can't access the filesystem, so you need to import the data directly:
import { createCloudflareHandler } from 'docusaurus-plugin-mcp-server/adapters';
import docs from '../build/mcp/docs.json';
import searchIndex from '../build/mcp/search-index.json';
export default {
fetch: createCloudflareHandler({
docs,
searchIndexData: searchIndex,
name: 'my-docs',
baseUrl: 'https://docs.example.com',
}),
};npm run build
# Deploy to your platformClaude Code:
claude mcp add --transport http my-docs https://docs.example.com/mcpCursor / VS Code:
{
"mcpServers": {
"my-docs": {
"url": "https://docs.example.com/mcp"
}
}
}Add a dropdown button to your docs site so users can easily install the MCP server in their AI tool:
import { McpInstallButton } from 'docusaurus-plugin-mcp-server/theme';
function NavbarItems() {
return (
<McpInstallButton
serverUrl="https://docs.example.com/mcp"
serverName="my-docs"
/>
);
}The button shows a dropdown with copy-to-clipboard configurations for all supported MCP clients.
| Light Mode | Dark Mode |
|---|---|
![]() |
![]() |
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
serverUrl |
string |
required | Your MCP server endpoint URL |
serverName |
string |
required | Name for the MCP server |
label |
string |
(none) | Button label. If omitted, shows only the MCP icon |
headerText |
string |
"Choose your AI tool:" |
Text shown at the top of the dropdown |
className |
string |
"" |
Optional CSS class |
clients |
ClientId[] |
All HTTP-capable | Which clients to show |
The server exposes two tools for AI agents:
Search across documentation with relevance ranking. Returns matching documents with URLs, snippets, and relevance scores.
{
"name": "docs_search",
"arguments": {
"query": "authentication",
"limit": 5
}
}| Parameter | Type | Default | Description |
|---|---|---|---|
query |
string |
required | Search query |
limit |
number |
5 |
Max results (1-20) |
Response includes:
- Full URL for each result (use with
docs_fetch) - Title and relevance score
- Snippet of matching content
- Matching headings
Retrieve full page content as markdown. Use this after searching to get the complete content of a specific page.
{
"name": "docs_fetch",
"arguments": {
"url": "https://docs.example.com/docs/authentication"
}
}| Parameter | Type | Description |
|---|---|---|
url |
string |
Full URL of the page (from search results) |
Response includes:
- Page title and description
- Table of contents with anchor links
- Full markdown content
| Option | Type | Default | Description |
|---|---|---|---|
outputDir |
string |
'mcp' |
Output directory for MCP artifacts (relative to build dir) |
contentSelectors |
string[] |
['article', 'main', ...] |
CSS selectors for finding content |
excludeSelectors |
string[] |
['nav', 'header', ...] |
CSS selectors for elements to remove |
minContentLength |
number |
50 |
Minimum content length to consider a page valid |
server.name |
string |
'docs-mcp-server' |
Name of the MCP server |
server.version |
string |
'1.0.0' |
Version of the MCP server |
excludeRoutes |
string[] |
['/404*', '/search*'] |
Routes to exclude (glob patterns) |
Content selectors (in priority order):
['article', 'main', '.main-wrapper', '[role="main"]']Exclude selectors:
['nav', 'header', 'footer', 'aside', '[role="navigation"]', '[role="banner"]', '[role="contentinfo"]']For the runtime adapters:
| Option | Type | Required | Description |
|---|---|---|---|
docsPath |
string |
Yes* | Path to docs.json |
indexPath |
string |
Yes* | Path to search-index.json |
docs |
object |
Yes* | Pre-loaded docs (Cloudflare) |
searchIndexData |
object |
Yes* | Pre-loaded search index (Cloudflare) |
name |
string |
Yes | Server name |
version |
string |
No | Server version |
baseUrl |
string |
No | Base URL for full page URLs in responses |
*Use either file paths (Node.js) or pre-loaded data (Workers).
After running npm run build, use the included CLI to verify the MCP output:
npx docusaurus-mcp-verifyThis checks that:
- All required files exist (
docs.json,search-index.json,manifest.json) - Document structure is valid
- The MCP server can initialize and load the content
You can specify a custom build directory:
npx docusaurus-mcp-verify ./custom-buildExample output:
π MCP Build Verification
==================================================
Build directory: /path/to/your/project/build
π Checking build output...
β Found 42 documents
β All required files present
β File structure valid
π Testing MCP server...
β Server initialized with 42 documents
β
All checks passed!
The easiest way to test your MCP server is with the official MCP Inspector:
npx @modelcontextprotocol/inspectorThis opens a visual interface where you can:
- Connect to your server URL
- Browse available tools
- Execute tool calls interactively
- View responses in a formatted display
Alternatively, test with curl:
# List available tools
curl -X POST https://docs.example.com/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Search documentation
curl -X POST https://docs.example.com/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":2,
"method":"tools/call",
"params":{
"name":"docs_search",
"arguments":{"query":"getting started"}
}
}'flowchart LR
subgraph Build["Build Time"]
A[Docusaurus Build] --> B[postBuild Hook]
B --> C[Extract Content]
C --> D[Build Search Index]
D --> E[Write Artifacts]
end
subgraph Artifacts["build/mcp/"]
F[docs.json]
G[search-index.json]
H[manifest.json]
end
subgraph Runtime["Runtime"]
I[Serverless Function]
J[MCP Server]
end
subgraph Clients["AI Agents"]
K[Claude]
L[Cursor]
M[Other MCP Clients]
end
E --> F & G & H
F & G --> I
I --> J
K & L & M <-->|MCP Protocol| J
The plugin operates in two phases:
Build Time: During docusaurus build, the plugin's postBuild hook processes all rendered HTML pages, extracts content, converts to markdown, builds a FlexSearch index, and outputs artifacts to build/mcp/.
Runtime: A serverless function loads the pre-built artifacts and handles MCP JSON-RPC requests from AI agents. The server is stateless and fast since all indexing happens at build time.
- Full-text Search - FlexSearch-powered search with relevance ranking
- Page Retrieval - Get complete page content as clean markdown
- Platform Adapters - Pre-built adapters for Vercel, Netlify, and Cloudflare Workers
- CORS Support - All adapters include CORS headers for browser-based clients
- Build-time Processing - Extracts content from rendered HTML, capturing React component output
- Zero Runtime Docusaurus Dependency - The MCP server runs independently
Run a local HTTP server for testing:
// mcp-server.mjs
import http from 'http';
import { McpDocsServer } from 'docusaurus-plugin-mcp-server';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const server = new McpDocsServer({
docsPath: path.join(__dirname, 'build/mcp/docs.json'),
indexPath: path.join(__dirname, 'build/mcp/search-index.json'),
name: 'my-docs',
baseUrl: 'http://localhost:3000',
});
http.createServer(async (req, res) => {
if (req.method === 'OPTIONS') {
res.writeHead(204, {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
});
res.end();
return;
}
if (req.method !== 'POST') {
res.writeHead(405);
res.end();
return;
}
await server.handleHttpRequest(req, res);
}).listen(3456, () => {
console.log('MCP server at http://localhost:3456');
});Connect Claude Code:
claude mcp add --transport http my-docs http://localhost:3456import {
// Docusaurus plugin (default export)
mcpServerPlugin,
// MCP Server class
McpDocsServer,
// Tool definitions
docsSearchTool,
docsFetchTool,
// Utilities
htmlToMarkdown,
extractContent,
extractHeadingsFromMarkdown,
buildSearchIndex,
// Provider types (for custom implementations)
loadIndexer,
loadSearchProvider,
FlexSearchIndexer,
FlexSearchProvider,
// Default options
DEFAULT_OPTIONS,
} from 'docusaurus-plugin-mcp-server';import {
createVercelHandler,
createNetlifyHandler,
createCloudflareHandler,
generateAdapterFiles,
} from 'docusaurus-plugin-mcp-server/adapters';import {
McpInstallButton,
type McpInstallButtonProps,
} from 'docusaurus-plugin-mcp-server/theme';- Node.js >= 20
- Docusaurus 3.x
MIT

