hugo-llms-mcp
by biccio
README.md
# Hugo MCP server
A generic **MCP (Model Context Protocol) server** for any Hugo blog, deployed on Cloudflare Workers.
It reads your blog's `llms.txt` and `llms-full.txt` files and exposes them as structured tools that AI assistants (Claude, Cursor, and others) can query to understand your content.
---
## How it works
```
Your Hugo blog Cloudflare Worker AI assistant
───────────────── ────────────────── ──────────────
/llms.txt ───► /mcp (MCP tools) ◄───► Claude / Cursor
/llms-full.txt ───► /llms.txt (proxy) etc.
/llms-full.txt (proxy)
```
The Worker fetches your blog's `llms.txt` and `llms-full.txt` at runtime (with an in-memory cache), and exposes three MCP tools:
| Tool | What it does |
|------|-------------|
| `get_blog_summary` | Returns the concise overview from `/llms.txt` |
| `get_blog_full_index` | Returns the full content index from `/llms-full.txt` |
| `search_content` | Searches for a keyword across the full index and returns matching paragraphs with context |
---
## Prerequisites
- A Hugo blog publicly accessible on the web
- `llms.txt` and `llms-full.txt` files in your Hugo `static/` folder (see [Step 1](#step-1--create-your-llmstxt-files))
- A [Cloudflare account](https://dash.cloudflare.com/sign-up) (free tier is enough)
- [Node.js](https://nodejs.org/) ≥ 18
- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) (`npm install -g wrangler`)
---
## Step 1 — Create your llms.txt files
`llms.txt` and `llms-full.txt` are plain-text files that describe your blog's content to language models. They live in your Hugo `static/` folder and are served automatically at `/llms.txt` and `/llms-full.txt`.
### Option A — Use the helper script
```bash
# Clone this repo
git clone https://github.com/your-username/hugo-llms-mcp.git
cd hugo-llms-mcp
# Edit the configuration at the top of the script
nano scripts/generate-llms.py
# Run it — outputs static/llms.txt and static/llms-full.txt
python3 scripts/generate-llms.py
```
Then copy the generated files to your Hugo site's `static/` folder, review and enrich them manually, and redeploy your site.
### Option B — Write them by hand
**`static/llms.txt`** (summary, ~50 lines):
```
# My Hugo Blog
> One-line tagline for your blog.
Author: Your Name
Site: https://your-hugo-blog.com
Language(s): English
## Description
Two or three sentences describing what the blog is about,
who the author is, and who it's for.
## Published content
- Post Title One (Month Year) — https://your-hugo-blog.com/posts/post-one/
- Post Title Two (Month Year) — https://your-hugo-blog.com/posts/post-two/
## Instructions for language models
- Content may be freely summarised with attribution and a link to the source.
- Short excerpts may be quoted for informational purposes.
- Reproduction of full articles is not permitted.
```
**`static/llms-full.txt`** (extended index, as long as needed):
```
# My Hugo Blog
# llms-full.txt — Extended index for language models
Site: https://your-hugo-blog.com
Author: Your Name
Generated: June 2026
---
## Author profile
A longer bio of the author.
---
## Content
---
### Post Title One
URL: https://your-hugo-blog.com/posts/post-one/
Date: January 2025
Description: A detailed summary of what this post covers,
key points made, people or places mentioned, and tone.
---
### Post Title Two
...
```
> **Tip:** The more detailed `llms-full.txt` is, the more useful the `search_content` tool becomes. Include summaries, key locations, episode descriptions, and any cross-references between posts.
### Verify the files are live
After deploying your Hugo site, check:
```
https://your-hugo-blog.com/llms.txt
https://your-hugo-blog.com/llms-full.txt
```
Both should return plain text. If they do, you're ready for Step 2.
---
## Step 2 — Configure the Worker
Clone this repo (if you haven't already) and edit `wrangler.toml`:
```toml
name = "my-blog-mcp" # becomes my-blog-mcp.<account>.workers.dev
[vars]
SITE_URL = "https://your-hugo-blog.com"
SITE_NAME = "My Hugo Blog"
CACHE_TTL_SEC = "3600" # cache TTL in seconds; 0 = always fetch fresh
```
---
## Step 3 — Deploy
```bash
# Install dependencies
npm install
# Log in to Cloudflare (once)
wrangler login
# Deploy
npm run deploy
```
Wrangler will print the Worker URL:
```
https://my-blog-mcp.<your-account>.workers.dev
```
---
## Step 4 — Verify
```bash
# Health check
curl https://my-blog-mcp.<your-account>.workers.dev/health
# List MCP tools
curl -s -X POST https://my-blog-mcp.<your-account>.workers.dev/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | python3 -m json.tool
# Search for a keyword
curl -s -X POST https://my-blog-mcp.<your-account>.workers.dev/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_content","arguments":{"query":"your keyword","max_results":3}}}' | python3 -m json.tool
```
---
## Step 5 — Connect to Claude
### Claude.ai
Settings → Connectors → Add MCP Server:
```
https://my-blog-mcp.<your-account>.workers.dev/mcp
```
### Claude Desktop
Install the `mcp-remote` bridge (needed because Claude Desktop doesn't yet support remote MCP natively):
```bash
npm install -g mcp-remote
```
Edit `claude_desktop_config.json`:
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"my-blog": {
"command": "npx",
"args": [
"mcp-remote",
"https://my-blog-mcp.<your-account>.workers.dev/mcp"
]
}
}
}
```
Restart Claude Desktop. The three tools will appear in the tool list.
### Cursor / other MCP clients
Use the Worker URL directly: `https://my-blog-mcp.<your-account>.workers.dev/mcp`
---
## Updating content
The Worker fetches content from your live site and caches it in memory for `CACHE_TTL_SEC` seconds (default: 1 hour). So when you publish new posts:
1. Update `llms.txt` and `llms-full.txt` in your Hugo `static/` folder.
2. Redeploy your Hugo site — the Worker will pick up the changes automatically within the cache TTL.
No need to redeploy the Worker itself unless you change `wrangler.toml` or `src/index.js`.
---
## Project structure
```
hugo-llms-mcp/
├── src/
│ └── index.js ← Cloudflare Worker (MCP server logic)
├── scripts/
│ └── generate-llms.py ← Helper to scaffold llms.txt files
├── wrangler.toml ← Cloudflare configuration (edit this)
├── package.json
├── .gitignore
├── LICENSE
└── README.md
```
---
## Cloudflare free tier limits
| Resource | Free limit |
|----------|-----------|
| Requests | 100,000 / day |
| CPU time | 10 ms / request |
| Memory | 128 MB |
| Script size | 1 MB (compressed) |
A typical blog MCP server uses well under all of these limits.
---
## Real-world example
This project was originally built for [ciclogravelista.com](https://ciclogravelista.com), a personal gravel cycling travel blog. The live MCP server is available at:
```
https://ciclogravelista-mcp.ciclogravelista.workers.dev/mcp
```
Source: [github.com/your-username/ciclogravelista-mcp](https://github.com/your-username/ciclogravelista-mcp)
---
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues