Build-time integration for Astro projects that generates search indexes from site content for MCP-based search functionality.
Deploys a Cloudflare Worker with Durable Objects and R2 storage that provides MCP search tools for static websites, enabling full-text search with fuzzy matching across site content.
Generates search indexes from Hugo site content with TOML or YAML frontmatter for MCP-based search functionality.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Cloudflare MCP Server for Static Sitessearch my documentation for how to deploy a static site"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Cloudflare MCP Server for Static Sites
Turn your static website into an AI-accessible knowledge base. This project deploys a Cloudflare Worker that implements the Model Context Protocol (MCP). AI tools like Claude can then search and retrieve your content directly. You can read more about this approach in my blog post.
Cloudflare is well-suited for hosting remote MCP servers — its Workers platform handles the transport layer, and Durable Objects maintain persistent client sessions.
Why This Matters
AI assistants answer questions based on their training data, which may be outdated or incomplete. They can't search your website unless you give them a way to do so. This MCP server can be an AI-native bridge that allows these tools to get up-to-date information when they need it.
You might use this to:
Help users find answers in your documentation
Give AI assistants access to your blog's content
Let AI tools cite your articles with accurate, up-to-date information
How It Works
Prerequisites
Requirement | What It's For |
Hosts the Worker and R2 bucket. The free tier is sufficient. | |
Node.js 18+ or Bun | Runs the adapter that generates your search index. |
Deploys the Worker and manages R2. Installed via |
Quick Start
You can follow these steps manually or point an AI coding tool (Claude Code, Cursor, etc.) at this repo and ask it to set things up. Either way, you'll need a Cloudflare account and these details about your site:
Site name and domain (e.g., "My Blog" and "blog.example.com")
Content directory path to your markdown files
Tool prefix for MCP tool names (e.g., "myblog" →
search_myblog)MCP endpoint domain (e.g., "mcp.example.com")
1. Clone and Install
2. Configure
Edit wrangler.jsonc:
3. Create R2 Bucket
4. Generate and Upload Index
Pick an adapter for your site (see Adapters):
5. Deploy
Your MCP server is now running. Connect an MCP client to start searching.
CI/CD: The included GitHub Actions workflow (.github/workflows/deploy.yml) is set to manual trigger only. To deploy via GitHub Actions, go to Actions → Deploy → Run workflow. To enable auto-deploy on push, edit the workflow and add push: branches: [main] to the triggers.
MCP Client Setup
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
Claude Code
Cursor
Add to your Cursor mcp.json:
Other Clients
Use the mcp-remote package to connect via the /mcp endpoint (streamable HTTP, recommended) or /sse endpoint (SSE transport, legacy).
Available Tools
Tool | Description |
| Search by keywords. Returns titles, URLs, dates, and summaries. |
| Retrieve full content by URL path (e.g., |
| Get page count, generation date, and tool names. |
Threat Model
This MCP server is designed for public content only. Consider these security characteristics before deploying:
What's Exposed
Exposure | Mechanism |
All indexed content |
|
Content enumeration |
|
Site metadata |
|
Assumptions
Your content is already public. The indexed pages come from a public website. This server makes them AI-searchable, not newly public.
R2 is not the security boundary. While the R2 bucket is private, the Worker exposes its contents through MCP tools. Anyone with the endpoint URL can query all indexed content.
No authentication. The MCP server accepts connections from any client. There's no API key, OAuth, or access control.
Not Designed For
Private or internal documentation
Content requiring authentication or authorization
Partial access control (all-or-nothing visibility)
Recommendations
If you need access control, consider:
Cloudflare Access for authentication at the Worker level
A separate private deployment for internal content
Excluding sensitive pages from the search index
Adapters
An adapter generates the search index from your content. It scans your files, extracts frontmatter metadata, and outputs search-index.json.
Each adapter handles the specifics of a particular static site generator.
Generic (Markdown)
Works with any site that uses markdown files with YAML frontmatter.
See adapters/generic/README.md.
Astro
An Astro integration that generates the index at build time.
Hugo
A Node.js script that handles both TOML and YAML frontmatter.
Writing Your Own Adapter
If your static site generator isn't listed, you can write an adapter. It just needs to output JSON in the v3.0 format.
Your adapter should:
Find your content files (markdown, MDX, HTML, etc.)
Extract metadata from frontmatter (title, date, tags)
Extract body text for search
Map file paths to URLs
Write
search-index.json
Here's a template:
Validate your index:
Upload to R2:
Configuration
wrangler.jsonc
Field | Description |
| Worker name in Cloudflare dashboard |
| Your custom domain |
| R2 bucket name |
For testing, you can use a workers.dev subdomain instead of a custom domain:
Index Format
The search index follows the v3.0 schema:
Field | Required | Description |
| Yes | Schema version ("3.0") |
| Yes | ISO 8601 timestamp |
| Yes | Site name |
| Yes | Domain without protocol |
| No | Shown in MCP tool description |
| No | Tool name prefix (default: |
| Yes | Number of pages |
| Yes | Path starting with |
| Yes | Page title |
| No | Full text (recommended) |
Development
Note: This is a template repository. The bun run deploy command is for users who clone this template to deploy their own MCP server. To contribute to this template itself, use standard git workflows (git push).
Troubleshooting
"Search index not found in R2 bucket"
Check the bucket exists:
npx wrangler r2 bucket listCheck the file was uploaded:
npx wrangler r2 object list my-site-mcp-dataVerify the bucket name in
wrangler.jsoncmatches
MCP client won't connect
Use the
/mcpendpoint (recommended) or/ssefor legacy clientsVisit your worker URL in a browser — you should see JSON
Make sure the URL includes
https://
Search returns no results
Validate your index:
bun scripts/validate-index.ts ./search-index.jsonCheck that pages have
bodycontentTry broader search terms
Wrong tool names
Tool names come from toolPrefix in your search index. Regenerate and re-upload the index with the correct value.
Local development
You need a local copy of the search index:
Examples
Two sites using this approach:
REMnux Documentation
MCP server for REMnux, the Linux toolkit for malware analysis.
Repo: github.com/REMnux/remnux-docs-mcp-server
Lenny Zeltser's Website
MCP server for zeltser.com, covering malware analysis, incident response, and security leadership.
AI Agent Quick Reference
Key Files
File | Purpose |
| Worker entry point: MCP server setup, tool definitions, routing |
| Fuse.js search logic and index loading from R2 |
| Cloudflare deployment config (Worker name, R2 binding, routes) |
| Index generators for Astro, Hugo, and generic markdown sites |
| Validates search-index.json against the v3.0 schema |
Architecture
Adapters run at build time to generate
search-index.jsonThe Worker loads the index from R2 with 1-hour in-memory caching
Fuse.js provides fuzzy search across titles, abstracts, body text, and topics
Durable Objects manage persistent MCP client sessions
Common Dev Tasks
Security Notes
No authentication: any client with the endpoint URL can query all indexed content
Designed for public content only
R2 bucket is private but Worker exposes contents via MCP tools
Author
Lenny Zeltser: Builder of security products and programs. Teacher of those who run them.