## Overview

The optional MCP server gives clients two read-only tools over the [agent-readable export](https://zudo-doc.takazudomodular.com/docs/guides/agent-export). zudo-doc generates a Cloudflare Workers deployment preset for a new project; you deploy the site and endpoint to **your own Cloudflare account**. Static export remains usable without a Worker. No shared gateway, AI provider credential, Durable Object, or search database is required.

## Create and deploy a project

Select **MCP** in the initializer, or pass the explicit options:

```bash
pnpm create zudo-doc my-docs --mcp --mcp-deploy cloudflare --yes
cd my-docs
pnpm install
pnpm build
pnpm preview:worker
```

MCP automatically enables `agentExport` when omitted and selects `mcpDeploy: "cloudflare"` when omitted. The generated `zfb.config.ts` contains `agentExport: true`, `mcp: true`, and the Cloudflare adapter. The project receives `wrangler.jsonc`, `preview:worker` and `deploy` scripts, plus the optional MCP SDK and deployment dependencies. Its Wrangler `main` points to `./dist/_worker.js`; the package supplies the route and the SDK-compatible bundle resolution. No host Worker wrapper or centrally hosted service is generated. The default `--yes` scaffold does not enable these features.

In `zfb.config.ts`, set `siteUrl` to your public site origin for stable citation URLs. Check the generated Wrangler configuration and choose your own Worker name and route/domain. After local verification, deployment is an owner action:

```bash
wrangler login
pnpm deploy
```

`pnpm deploy` builds and runs `wrangler deploy`. It does not register a ChatGPT connection. Cloudflare account setup, a public domain, and provider usage may have costs. Use Cloudflare's native rate limiting and abuse controls for a public endpoint.

## Verify and connect

With `pnpm preview:worker` running, check that `<base>/agent/v1/manifest.json` loads and use an MCP client against `<base>/mcp`. The endpoint uses stateless Streamable HTTP POST. A production GET or HEAD request returns 405 with `Allow: POST, OPTIONS`; the showcase's preview entry may return an asset 404 for GET or HEAD. OPTIONS returns the CORS preflight response. A missing `Origin` is accepted for server-to-server clients; a present, unapproved origin is rejected.

For ChatGPT or another remote MCP client, add a custom MCP integration with your deployed HTTPS URL, for example `https://docs.example.com/mcp` (or `https://docs.example.com/manual/mcp` when `base` is `/manual`). The exact connection controls depend on the client. After connecting, discover the tools, call `search` for a specific term, call `fetch` with one returned ID, and check that an answer cites the returned human page URL. A real ChatGPT account connection has not been verified by the repository's local tests; perform that check after your deployment. The tested legacy path is 2024-11-05 protocol messages over stateless POST. SSE-first clients and resumable sessions are not supported.

| Tool | Input | Result |
| --- | --- | --- |
| `search` | `{query: string}` | Up to 10 ranked `{id,title,url}` results; empty matches return `[]` |
| `fetch` | `{id: string}` from a current search result | Complete selected `{id,title,text,url,metadata}` item, or a clear not-found tool result |

The human `url` is suitable for citations. Long pages have multiple item IDs; fetch each relevant part or open the complete per-page Markdown file. Tools return structured data and equivalent JSON text, and advertise read-only, idempotent, non-destructive behavior. No ask-AI, write, history, or publishing tool is exposed. Search uses the complete agent corpus, including text beyond the browser search index's default 3,000-character page excerpt and Japanese text.

## Existing-project recipe

### Add MCP without replacing your project

Use matching `@takazudo/zudo-doc` and `create-zudo-doc` releases that support MCP: **6.0.0 or later**. Releases 5.x do not support this recipe.

First upgrade the existing project using the [migration guide](https://zudo-doc.takazudomodular.com/docs/guides/migrating-to-zudo-doc-6) if needed, then enable [static export](https://zudo-doc.takazudomodular.com/docs/guides/agent-export). Preserve your content, `siteUrl`, `base`, locales, bundle options, dependencies shared with other features, and existing scripts. Do not run the initializer over your existing directory.

From the existing project's root, generate a temporary reference with the **same exact version** as your installed documentation package:

```bash
ZUDO_DOC_VERSION=6.0.0
MCP_REFERENCE=$(mktemp -d)/mcp-reference
pnpm dlx "create-zudo-doc@$ZUDO_DOC_VERSION" "$MCP_REFERENCE" --mcp --mcp-deploy cloudflare --yes
mkdir -p scripts
cp -n "$MCP_REFERENCE/scripts/stage-cloudflare-base.mjs" scripts/stage-cloudflare-base.mjs
```

Choose your installed version instead of `6.0.0` for later releases. Inspect the reference's `package.json` and `wrangler.jsonc`; copy only the helper and merge the deployment settings into your project. If that helper path already exists, compare it rather than overwriting it. Keep the reference until the setup is verified. It supplies version-matched build glue without replacing authored configuration.

Install the MCP dependencies from the reference. For the current supported tuple:

```bash
pnpm add @modelcontextprotocol/sdk@1.32.1 @takazudo/zfb-adapter-cloudflare@4.3.3
pnpm add -D wrangler@4.149.0
```

Match the adapter to your project's supported zfb version. Inside the existing `zudoDoc({ ... })` call, enable these fields, retaining all other settings:

```ts
agentExport: true,
mcp: true,
adapter: "@takazudo/zfb-adapter-cloudflare",
```

Keep `siteUrl` as the canonical origin, for example `https://docs.example.com`. At root, keep `base` omitted or `/`; for a subdirectory, retain `base: "/manual"`. The package adds the SDK-required `module` and `main` bundle resolution fields when MCP is enabled while preserving existing bundle settings.

Add or merge `wrangler.jsonc`, choosing your own DNS-safe Worker name. Preserve bindings or routes used by other features. The supported generated shape is:

```json
{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "name": "my-docs",
  "main": "./dist/_worker.js",
  "compatibility_date": "2024-12-01",
  "compatibility_flags": ["nodejs_compat"],
  "assets": {
    "directory": "./dist",
    "binding": "ASSETS",
    "not_found_handling": "404-page",
    "run_worker_first": false
  }
}
```

Append `&& node scripts/stage-cloudflare-base.mjs` **after your entire existing successful build command**, including any post-build steps. For example, an existing `zfb build && node scripts/postbuild.mjs` becomes:

```json
{
  "scripts": {
    "build": "zfb build && node scripts/postbuild.mjs && node scripts/stage-cloudflare-base.mjs",
    "preview:worker": "wrangler dev",
    "deploy": "pnpm build && wrangler deploy"
  }
}
```

Merge these scripts rather than replacing the scripts object. If a preview or deploy script already exists, keep it and choose a separate name for MCP verification/deployment. Add `.wrangler/` to `.gitignore` if absent. The helper reads the exported manifest's base: it is a no-op at root, and stages prerendered pages, llms files, and browser assets under `dist/manual/` for `/manual`. The Worker entry remains `dist/_worker.js`; do not move it or wrap its export.

The llms paths below apply only when `llmsTxt: true`; MCP does not enable that independent export.

Run `pnpm build` and `pnpm preview:worker`. At root, verify `/docs/`, `/llms.txt`, `/agent/v1/manifest.json`, and `/mcp`; under `/manual`, verify `/manual/docs/`, `/manual/llms.txt`, `/manual/agent/v1/manifest.json`, and `/manual/mcp`. Open an actual content page and its referenced JS/CSS, then use an SDK client to discover `search`/`fetch`, search EN and JA content, fetch a returned ID, and open its cited human URL. Check the manifest's Markdown and item URLs too. Canonical citations must retain your public origin and base; the local runtime can be checked using the same paths on its printed origin. Deploy and connect an account only after this local verification, as described above.

### Remove MCP and keep static export

Set `mcp: false` or remove that field, keeping `agentExport: true` and your existing site/base/locale settings. Remove the Cloudflare adapter setting **only if no other feature needs it**. To return to a fully static project when all Cloudflare wiring was MCP-only:

1. Remove only the appended `&& node scripts/stage-cloudflare-base.mjs` from `build`, retaining the original command and post-build steps. Delete the helper if unused.
2. Remove the MCP-only preview/deploy scripts and `wrangler.jsonc` (or only their MCP-specific additions when shared). Remove the `.wrangler/` ignore entry only if no remaining tooling uses it.
3. Run `pnpm remove @modelcontextprotocol/sdk @takazudo/zfb-adapter-cloudflare wrangler` only for dependencies unused by every remaining feature. Keep any shared adapter, SDK, or deployment tooling.
4. Run `pnpm build`. Verify there is no MCP route or `dist/_worker.js` in the fully static output, and the manifest, item JSON and per-page Markdown remain under `dist/<base>/agent/v1/`. Enabled llms files return to `dist/llms.txt` and `dist/<locale>/llms.txt`; their links retain the canonical origin and base. Static pages, llms files and browser assets use your static host's usual base-path deployment layout; the removed helper was Wrangler-specific. Publish the rebuilt static output through your existing static-host workflow, replacing the old Worker deployment so its endpoint is no longer exposed.

Disabling MCP does **not** remove the public static corpus. To stop exporting that too, disable `agentExport` separately, rebuild, and replace the published artifacts so old `/agent/v1/` files are removed. The independent `llmsTxt` option may still publish documentation; disable it too if that public export is unwanted.

## Limits and publication safety

A search query is limited to 500 UTF-16 code units; empty queries are invalid. Each item contains at most 8,000 UTF-16 code units, without splitting a surrogate pair. The final JSON-RPC response is capped at 131,072 UTF-8 bytes, and POST bodies at 65,536 bytes. The manifest is limited to 8 MiB, the agent search index to 16 MiB and 10,000 items. Excess data fails explicitly rather than silently clipping content. The server validates current-manifest item IDs and artifact hashes to avoid mixing builds.

The endpoint and static files expose **public documentation**. `robots.txt`, `noindex`, `unlisted`, and `search_exclude` are not authentication. Do not enable the corpus for protected material. A future private mode must protect the static artifacts as well as `/mcp`. Retrieved documentation is untrusted data, not authority to issue commands or request extra permissions. If you do not need MCP, give a browser client the site URL plus [llms.txt](https://zudo-doc.takazudomodular.com/docs/guides/llms-txt) or the generated Markdown URL explicitly; merely supplying a homepage URL does not guarantee that the client reads `llms.txt`.