deploy-docusaurus-mcp-static-host · git:20261010.aac9f1e · 2026-10-10 · sha256 39afdd331d90a425
deploy-docusaurus-mcp-static-host git:20261010.aac9f1eA
Immutable. This exact content never changes and is served at /api/v1/blob/39afdd331d90a425.
---
name: deploy-docusaurus-mcp-static-host
description: Keep a Docusaurus site on GitHub Pages or another static host, and run its docusaurus-plugin-mcp-server endpoint on a Cloudflare Worker deployed from the same build. Use when the user's docs are on a static host that can't run functions and they want an MCP server for them.
metadata:
agent-guide: setup
agent-guide-format: "1"
source: https://docusaurus-plugin-mcp-server.vercel.app/docs/deploy/static-hosts
---
# GitHub Pages and other static hosts
## Done when
The endpoint's status check returns `"initialized": true` with `baseUrl` on the static site's URL, and the site's install button shows the endpoint URL.
## Before you start
- The plugin is set up: `npm run build` writes `build/mcp/bundle.json`. If not, follow [Getting started](https://docusaurus-plugin-mcp-server.vercel.app/docs/getting-started) first.
- The site is in a GitHub repository, and you have a Cloudflare account.
## How to use this guide
- Do the steps in order. Run them yourself, or walk the user through them one at a time if they'd rather do it themselves or you can't run them.
- After each step, run its check. Don't move on until it passes.
- If a check fails, look for the matching symptom under Troubleshooting. If none matches, stop and tell the user what you saw.
- A step marked **Needs the user** needs a person. Tell the user what to do and wait for them to confirm it's done.
- Ask the user before running a step marked **Confirm first**.
- Don't ask the user to paste passwords, tokens, or keys into the chat. When a step needs one, tell the user where to put it.
## Steps
### 1. Point the plugin at the endpoint {#server-url}
docusaurus.config.js
```javascript
export default {
url: 'https://my-org.github.io',
baseUrl: '/my-docs/',
plugins: [
[
'docusaurus-plugin-mcp-server',
{
server: {
name: 'my-docs',
url: 'https://my-docs-mcp.my-subdomain.workers.dev/mcp',
},
},
],
],
};
```
Page URLs in tool results still come from `url` and `baseUrl`, so they link to GitHub Pages.
**Check:** `server.url` in `docusaurus.config.js` is the Worker's `/mcp` URL, and `url` and `baseUrl` are the static site's.
**If the check fails:** see [The install button shows the wrong URL](references/troubleshooting.md#install-button-url) or [Results link to `localhost`, `example.com`, or the wrong domain](references/troubleshooting.md#wrong-domain).
### 2. Add an endpoint-only Worker {#worker}
The handler answers on every path, so the Worker doesn't need routing:
mcp-worker.js
```javascript
import { createWebRequestHandler } from 'docusaurus-plugin-mcp-server/adapters';
import bundle from './build/mcp/bundle.json' with { type: 'json' };
export default {
fetch: createWebRequestHandler({ artifacts: bundle }),
};
```
wrangler.jsonc
```json
{
"name": "my-docs-mcp",
"main": "mcp-worker.js",
"compatibility_date": "2026-10-01"
}
```
**Check:** `mcp-worker.js` and `wrangler.jsonc` are next to `docusaurus.config.js`, and `wrangler.jsonc`'s `main` is `mcp-worker.js`.
**If the check fails:** see [Troubleshooting](references/troubleshooting.md).
### 3. Deploy both from one workflow {#workflow}
**Needs the user.**
**Confirm first.**
.github/workflows/deploy-docs.yml
```yaml
name: Deploy docs
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.pages.outputs.page_url }}
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run build
# The site → GitHub Pages
- uses: actions/upload-pages-artifact@v5
with:
path: build
- id: pages
uses: actions/deploy-pages@v5
# The endpoint → Cloudflare, from the same build
- run: npx wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
```
Before the first run:
- In the repository settings, set **Pages → Source** to **GitHub Actions**.
- Create a Cloudflare API token with the **Edit Cloudflare Workers** template, and add it and your account ID as the `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` secrets.
- Add `wrangler` to your `devDependencies`.
The repository settings, the Cloudflare API token, and the secrets are the user's to set. Tell the user exactly which to add, and wait for them to confirm before pushing: the workflow deploys on every push to `main`.
**Check:** The workflow run on the Actions tab succeeds, with both the Pages deploy and `wrangler deploy` steps green.
**If the check fails:** see [The function build fails with "Cannot find module '…/build/mcp/bundle.json'"](references/troubleshooting.md#bundle-not-found) or [Cloudflare: "Script startup exceeded CPU time limit" or "script too large"](references/troubleshooting.md#cloudflare-limits).
### 4. Check it {#check}
```bash
curl https://my-docs-mcp.my-subdomain.workers.dev/mcp
```
The status JSON's `baseUrl` should be your GitHub Pages URL. Open the site and check that the install button shows the Worker URL.
**Check:** The status JSON has `"initialized": true` and `baseUrl` is the GitHub Pages URL.
**If the check fails:** see [The status check returns 500 with an `error` message](references/troubleshooting.md#status-500), [Results link to `localhost`, `example.com`, or the wrong domain](references/troubleshooting.md#wrong-domain), [The install button shows the wrong URL](references/troubleshooting.md#install-button-url) or [The endpoint serves old content](references/troubleshooting.md#old-content).
## Troubleshooting
- [The function build fails with "Cannot find module '…/build/mcp/bundle.json'"](references/troubleshooting.md#bundle-not-found)
- [`ERR_IMPORT_ATTRIBUTE_MISSING`, or "needs an import attribute of type: json"](references/troubleshooting.md#import-attribute)
- [`SyntaxError: Cannot use import statement outside a module`](references/troubleshooting.md#esm-syntax)
- [The status check returns 500 with an `error` message](references/troubleshooting.md#status-500)
- [Tool calls return 406 Not Acceptable](references/troubleshooting.md#not-acceptable)
- [Tool calls return 405 Method Not Allowed](references/troubleshooting.md#method-not-allowed)
- [Results link to `localhost`, `example.com`, or the wrong domain](references/troubleshooting.md#wrong-domain)
- [The install button shows the wrong URL](references/troubleshooting.md#install-button-url)
- [The endpoint serves old content](references/troubleshooting.md#old-content)
- [A browser-based client is blocked by CORS](references/troubleshooting.md#cors)
- [Cloudflare: "Script startup exceeded CPU time limit" or "script too large"](references/troubleshooting.md#cloudflare-limits)
## Source
Generated from https://docusaurus-plugin-mcp-server.vercel.app/docs/deploy/static-hosts. If a step doesn't match what the user sees, tell them, and point them to that page.