mudko
← back

Docs

Once you generate the file bundle (via the free toolsor as a paid customer), here's how to wire it onto common hosts. The drop-in files take a scanner to Level 4 (found, readable, declared); Level 5 also needs a live /api/mcp — built into the WordPress-plugin and Cloudflare-Worker deliveries, or add one to a files deploy with the free Worker guide.

Where each file goes

Read this before you upload. The bundle has files in two places: inside .well-known/ and at the site root. Mixing them up is the #1 deploy failure.

🚨 DO NOT FLATTEN the archive

The .well-known/ folder is a literal directory required by IETF RFC 8615 — not a label, not optional. If you drag everything into one folder before uploading, your site will fail in subtle ways (extensionless files at root cause Apache 500s; agents probing /.well-known/ find nothing).

Preserve the directory structure exactly as it is in the ZIP.

Source → destination
THIS ZIP                                    YOUR WEB ROOT
─────────────────────────                   ─────────────────────────
.well-known/                                .well-known/                        ← KEEP this folder
├── agent-card.json              ━━━━━▶     ├── agent-card.json
├── api-catalog                  ━━━━━▶     ├── api-catalog
├── oauth-authorization-server   ━━━━━▶     ├── oauth-authorization-server
├── oauth-protected-resource     ━━━━━▶     ├── oauth-protected-resource
├── openid-configuration         ━━━━━▶     ├── openid-configuration
├── service-doc                  ━━━━━▶     ├── service-doc
├── mcp/                                    ├── mcp/
│   └── server-card.json         ━━━━━▶     │   └── server-card.json
└── agent-skills/                           └── agent-skills/
    ├── index.json               ━━━━━▶         ├── index.json
    └── <skill>/SKILL.md         ━━━━━▶         └── <skill>/SKILL.md
webmcp.js                        ━━━━━▶     webmcp.js                           ← root, NOT in .well-known/
robots.txt                       ━━━━━▶     robots.txt                          ← root, OVERWRITES existing
llms.txt                         ━━━━━▶     llms.txt                            ← root
Where is "web root" on your host?
  • Vercel / Next.js: apps/web/public/ (or public/)
  • Netlify / Cloudflare Pages: public/ in your repo
  • Astro / SvelteKit / Eleventy: public/ (or static/)
  • cPanel shared hosting: public_html/ (or public_html/<addon-domain>/ if it's an addon domain)
  • WordPress: simplest is our one-click WordPress plugin delivery (serves the whole surface + a live /api/mcp → Level 5). To place these raw files by hand instead, drop them in the same folder as index.php via FTP (not the plugin upload UI — that mangles directory structure)
  • GitHub Pages / static / S3 / R2: alongside index.html

Common mistakes

Read this before you deploy. These are the failures we see most often.

1. Uploading only the .well-known/ folder

The kit bundle has files at two levels: .well-known/* AND root-level files (webmcp.js, robots.txt,llms.txt). Many users upload just the folder via FTP and miss the rest.

Symptom:Scanner shows agent-card pass but webmcp-bridge + llms-txt fail. Stuck at L1 because the host's default robots.txt is still being served.

Fix: Upload every file in the bundle preserving the directory structure. If you used the ZIP, extract it and upload all top-level entries.

2. Not adding the <script> tag

/webmcp.jsonly registers tools when the page loads it. The kit can't edit your HTML for you.

Fix: Add this line inside <head> on every page (or the shared template):

<script src="/webmcp.js"></script>
3. Default robots.txt not overwritten

Shared hosts (cPanel, GoDaddy, Bluehost) ship a default robots.txt with rules for MSNBot, Slurp, Teoma, etc. — circa 2010 search engines. Without overwriting, your AI-crawler permissions read as failing and you stay at L1.

Fix: Upload the kit's robots.txt directly to your site root (public_html/robots.txt on cPanel) and overwrite the existing one. Confirm with: curl https://yoursite.com/robots.txt | grep Content-Signal.

4. /api/mcp is declared but not implemented

Your mcp/server-card.json declareshttps://yoursite.com/api/mcp as a JSON-RPC endpoint. If nothing is actually running there, agents that try to call your MCP server hit 500 (or 404 on most hosts) and the live-endpoint check fails.

Two fixes:

  • Free: deploy the Cloudflare Worker template— bind it to /api/mcp/* on your domain. Five-minute job.
  • Or the WordPress-plugin / Cloudflare-Worker delivery (included in the flat $450 package) ships a live /api/mcp for you — nothing to hand-wire.

Once /api/mcp is live (or via the WordPress-plugin / Cloudflare-Worker deliveries, which ship it), it answers a suite of default tools automatically. To add your own, see Craft your own MCP tool.

5. Apache returns 500 instead of 404 for missing files

Many shared hosts have a broken .htaccessthat 500s when a file is missing. Scanners interpret 500 as “endpoint broken” rather than “not implemented”, dragging your level down on optional checks.

Fix: Add to public_html/.htaccess:

ErrorDocument 404 /404.html

Then create a minimal /404.html. This routes all unknown paths through a proper 404 instead of a 500.

6. Markdown content negotiation (Apache one-liner for L3)

The L3 (“Agent-Readable”) check requires that requests with Accept: text/markdown get markdown back. Static /index.md files alone don't pass this — your server has to honor the header.

Fix (Apache + .htaccess):

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_ACCEPT} text/markdown
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^$ /index.md [L,T=text/markdown]
  RewriteRule ^([^.]+)$ /$1.md [L,T=text/markdown]
</IfModule>

You also need actual markdown siblings (/index.md, optionally one per page). The kit doesn't generate them — write a one-line summary and you're done.

Verify: curl -H "Accept: text/markdown" https://yoursite.com/ should return markdown, not HTML.

What gets generated

  • .well-known/agent-card.json — A2A 0.3 agent card
  • .well-known/mcp/server-card.json — MCP 2025-06-18 server card
  • .well-known/api-catalog + oauth-* + openid-configuration — RFC 9727 + OAuth discovery
  • .well-known/agent-skills/ — skills index + per-tool SKILL.md
  • /webmcp.js — in-page WebMCP bridge
  • /robots.txt + /llms.txt
Vercel + Next.js (App Router)
Easiest
  1. Drop the generated files into apps/web/public/ (or your repo's public/).
  2. Add a sitemap: apps/<app>/src/app/sitemap.ts (Next.js generates /sitemap.xml).
  3. Add the Link header to every response via next.config.ts headers().
  4. Add a markdown sibling: src/app/index.md/route.ts returns text/markdown.
// next.config.ts
async headers() {
  return [{
    source: "/:path*",
    headers: [{
      key: "Link",
      value: '</.well-known/api-catalog>; rel="api-catalog"',
    }],
  }];
}
Netlify
  1. Place generated files under public/.well-known/ — Netlify serves the contents of public/ at /.
  2. Add a _headers file to set the Link header.
  3. Add a netlify.toml redirect for the markdown sibling if you don't have one.
# public/_headers
/*
  Link: </.well-known/api-catalog>; rel="api-catalog"
Cloudflare Pages
  1. Files under public/ are served at /. Place .well-known/ there.
  2. Add a _headers file (same syntax as Netlify).
  3. For markdown negotiation, add a Cloudflare Worker that responds to /*.md with the markdown variant.
# public/_headers
/*
  Link: </.well-known/api-catalog>; rel="api-catalog"
Static host (GitHub Pages, S3, etc.)
  1. Upload .well-known/ alongside index.html.
  2. Most static hosts cannot set Link headers — set them via your CDN (CloudFront, Fastly) instead, or add a meta-equiv tag in index.html: <meta http-equiv="Link" content="</.well-known/api-catalog>; rel=\"api-catalog\"">.
cPanel / Apache
  1. Upload .well-known/ to public_html/.
  2. Add the Link header in .htaccess.
# .htaccess
Header set Link "</.well-known/api-catalog>; rel=\"api-catalog\""

Verify

After deploying, run a scan against your domain:

curl 'https://mudko.com/api/scan?url=https://yoursite.com'

Or use the UI scanner. Target for drop-in files: Level 4. Level 5 also needs a live /api/mcp — the WordPress-plugin and Cloudflare-Worker deliveries ship one built in.