Table of contents
Docusaurus serves anything in static/ as-is, so the MCP server card needs one file and no plugin. This guide covers check P2 on Docusaurus. I built a site on Docusaurus 3.10.2 and ran the dev server and the production server, and the dev server hides the one mistake that matters.
The card is the JSON document that tells an agent where your MCP server lives. Its schema is still a draft, so read Publish an MCP Server Card So Agents Can Find Your Tools for the fields. This post is only the Docusaurus mechanics for check P2, which AIScan grades.
Quick summary
| If you want... | Do this | Time |
|---|---|---|
| The card live on Docusaurus | Create static/.well-known/mcp/server-card.json and rebuild | 5 min |
To keep the card outside static/ | Add the folder to staticDirectories in the config | 5 min |
| To host on GitHub Pages | Also add an empty static/.nojekyll | 1 min |
| To test it honestly | Use docusaurus serve, never docusaurus start | 2 min |
Check first: run npx aiscan-cli yoursite.com and read check P2 in the Capabilities group.
Put the card in static/
Docusaurus copies the static/ directory into build/ unchanged, and the static assets docs describe that folder as the place for files served at the site root. A dot-prefixed folder is copied like any other. Create:
static/.well-known/mcp/server-card.json
{
"serverInfo": { "name": "example-mcp", "version": "1.0.0" },
"description": "Search the example catalog",
"transport": { "type": "streamable-http", "url": "https://example.com/mcp" },
"tools": [{ "name": "search", "description": "Search the catalog" }]
}
Replace the example values with your real server name, endpoint and tools. The field names follow the shape in AIScan's own P2 guidance and are a convention, not a ratified schema. Run npm run build. On 3.10.2 the output contained build/.well-known/mcp/server-card.json with no config change.
Do not put the card in src/pages/. That folder is for React and Markdown pages that become HTML routes, not for raw JSON files.
Keep it in a different folder
If your team keeps generated files out of static/, point Docusaurus at a second directory. The docs show staticDirectories: ['public', 'static'] in docusaurus.config.js:
export default {
title: 'My site',
staticDirectories: ['public', 'static'],
};
I put a card in public/.well-known/mcp/ and built. It landed at build/.well-known/mcp/server-card.json. Setting the option replaces the default list, so keep 'static' in it or your existing images and robots.txt disappear from the build.
GitHub Pages needs one more file
The Docusaurus docs warn that GitHub Pages runs published files through Jekyll, and that Jekyll discards files that begin with _. They recommend an empty .nojekyll file in your static directory. Add it now: static/.nojekyll. I did not deploy to GitHub Pages, so I cannot tell you what Jekyll does to a .well-known folder on your repository. After any Pages deploy, request the live URL instead of trusting the build folder.
Test with serve, not start
The two local servers disagree about missing files. I ran both against the same site:
| Request | docusaurus start (port 3112) | docusaurus serve (port 3111) |
|---|---|---|
/.well-known/mcp/server-card.json | 200, application/json | 200, application/json; charset=utf-8 |
/.well-known/mcp/server-carb.json (typo) | 200 | 404 |
/.well-known/mcp/server-card | 200, text/html | 404 |
The dev server answers an unknown path with the site's HTML shell and a 200, so a misspelled folder looks fine until you read the body. The production server returns a real 404. Build first, then check with npm run serve.
Verify the card
Run AIScan first:
npx aiscan-cli yoursite.com
Find P2 · MCP Server Card in the Capabilities group. It should pass. By hand, one request does the same job:
curl -si https://yoursite.com/.well-known/mcp/server-card.json
Expected output, trimmed:
HTTP/2 200
content-type: application/json
{"serverInfo":{"name":"example-mcp","version":"1.0.0"},...
Docusaurus sets no headers in a static build. The content-type your visitors see comes from the host in front of build/, and I did not test any host. Run the request on the domain agents will use.
When the card still fails
- 404 at the right path. The folder is
static/well-known/without the leading dot, or the build ran before you added the file. Listbuild/.well-known/mcp/. - 200 but the body is HTML. Your host rewrites unknown paths to
index.html, the same thingdocusaurus startdoes. Checkcontent-typeand the first bytes, never only the status. - The card is missing after you set
staticDirectories. The file sits in a folder you did not list, or you dropped'static'from the array. - It works locally and 404s on GitHub Pages. Add
static/.nojekyll, redeploy and request the live URL.
Where to go next
Run npx aiscan-cli yoursite.com, confirm check P2, then browse the other fixes in the AIScan guides. The capabilities checks reference lists P1 to P4 and E2. If you also need llms.txt on Docusaurus, the llms.txt guide for Docusaurus covers it, and the Docusaurus setup guide covers the wider checklist. The Hugo version of this guide covers the same check on another static generator.
Frequently asked questions
Where does the MCP server card go in a Docusaurus project?
Put it at static/.well-known/mcp/server-card.json. Docusaurus copies static/ into build/ unchanged, so the file is served at /.well-known/mcp/server-card.json.
Does Docusaurus copy a folder that starts with a dot?
Yes. On Docusaurus 3.10.2 a static/.well-known folder was copied to build/.well-known with no configuration.
Do I need a plugin to publish an MCP server card on Docusaurus?
No. The card is a plain JSON file, so the static directory is enough. No plugin and no config change is needed.
Can I keep the card outside the static folder?
Yes. Add another folder to staticDirectories in docusaurus.config.js, for example ['public', 'static']. Keep 'static' in the list, because setting the option replaces the default.
Why does the card return 200 locally but the scan fails?
Check the body. The docusaurus start dev server returns the HTML shell with a 200 for unknown paths, so a typo in the folder name still looks like success. Build and test with docusaurus serve, which returns a real 404.
Why is the card a 404 on my deployed Docusaurus site?
Look for a missing leading dot (well-known instead of .well-known), a build that ran before you added the file, or a host that does not publish dot folders. List build/.well-known/mcp/ first, then request the live URL.
Why does the card work locally and 404 on GitHub Pages?
GitHub Pages runs published files through Jekyll, which the Docusaurus docs say discards files that begin with an underscore. Add an empty static/.nojekyll file as the docs recommend, redeploy, and request the live URL.
What content-type should the Docusaurus card return?
application/json. A static Docusaurus build sets no headers itself, so the type comes from your host. Run curl -si on the live URL and read the content-type line.
Related guides
How to return a real 404 with a recoverable body on Docusaurus
Docusaurus builds a real 404.html for you, and then the place you test it hides it. Run npm start, type a madeup URL and you get a friendly page with a 200 status. The production build behaves…
UCP profiles: Shopify serves one, most other stores don't
Shopify stores answer on /.wellknown/ucp. Almost nobody else does. We checked 238 commerceactive sites in the AIScan corpus on 10 October 2026: 12 of 17 Shopify catalogue stores pass check M1 the…
How to publish /.well-known/mcp/server-card.json on Hugo
Hugo has two ways to put an MCP server card at /.wellknown/mcp/servercard.json, and one of them can build cleanly while writing the file to the wrong place. This guide covers the card for check P2 on…
How to Test Whether an AI Agent Can Complete a Task on Your Site
Finding an MCP endpoint is the easy half. The half that matters is whether an agent can finish a job with it: ask a question, get an answer it can parse, and act on it. A server can answer tools/list…
