Hugo MCP Server : connecter Claude.ai à un site Hugo statique

⚡ En bref
Connecter Claude.ai à un site Hugo hébergé dans une VM KVM en 30 minutes : un serveur FastAPI expose 6 outils MCP (lire, créer, modifier, supprimer des pages, rebuilder le site) via JSON-RPC 2.0, un proxy OAuth réutilise l’infrastructure existante, et chaque modification déclenche automatiquement un rebuild Hugo + une purge du cache Cloudflare.
Le code est disponible sur GitHub :
- 🔌 Serveur MCP Hugo : jmrGrav/hugo-mcp
- 🔐 Proxy OAuth : jmrGrav/mcp-oauth-proxy
🧠 Pourquoi
Le protocole MCP (Model Context Protocol) d’Anthropic permet à Claude.ai de se connecter à des sources de données externes via des outils standardisés. Contrairement à Grav CMS qui est dynamique (PHP), Hugo génère du HTML statique — ce qui rend la gestion de contenu via MCP encore plus puissante : chaque modification est compilée et déployée instantanément.
Ce stack maison permet de :
- Créer et modifier des pages Hugo directement depuis Claude.ai sans toucher aux fichiers manuellement
- Rebuilder le site automatiquement après chaque modification via
hugo --minify - Purger le cache Cloudflare de façon ciblée après chaque changement
- Gérer le contenu bilingue (FR + EN) en une seule conversation
🔧 Ce qui a été fait
🏗️ Architecture globale
Claude.ai
│
│ HTTPS (OAuth 2.1 + PKCE)
▼
┌───────────────┐
│ Cloudflare │ WAF + Cache
└───────┬───────┘
│
▼
┌───────────────┐
│ nginx │ SSL termination
│mcp-hugo.arleo │ location /mcp → proxy
└───────┬───────┘
│
▼
┌───────────────┐
│ FastAPI proxy │ Port 8084 (host NUC)
│ OAuth 2.1 │ Token validation
│ mcp-proxy │ SHA-256 hashing
└───────┬───────┘
│
▼
┌───────────────┐
│ hugo-mcp │ Port 8000 (VM KVM)
│ FastAPI │ 6 outils MCP
│ Python 3.12 │ 192.168.122.69
└───────┬───────┘
│
┌───────┴────────┐
▼ ▼
~/hugo-site/ deploy.sh → /var/www/hugo
content/*.md + purge Cloudflare📦 Composants
| Composant | Technologie | Rôle |
|---|---|---|
hugo-mcp | FastAPI + Python 3.12 | Expose les 6 outils MCP via JSON-RPC 2.0 |
mcp-oauth-proxy | FastAPI + Python | Gère OAuth 2.1, PKCE S256, tokens |
| nginx vhost | nginx | Reverse proxy SSL, location /mcp |
| deploy.sh | bash | Hugo rebuild + rsync vers /var/www/hugo |
| systemd units | systemd | Services hardenés VM + host |
🔌 Étape 1 — Installer hugo-mcp dans la VM
# Cloner le repo dans la VM
git clone https://github.com/jmrGrav/hugo-mcp.git ~/hugo-mcp
cd ~/hugo-mcp
# Créer l'environnement virtuel Python
sudo apt install -y python3.12-venv
python3 -m venv venv
venv/bin/pip install -r requirements.txt
# Générer le token MCP
MCP_TOKEN=$(openssl rand -hex 32)
# Configurer les secrets
cat > .env << EOF
MCP_TOKEN=$MCP_TOKEN
CF_TOKEN=<votre_token_cloudflare>
CF_ZONE_ID=<votre_zone_id>
EOF
# Installer le service systemd
sudo cp systemd/hugo-mcp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now hugo-mcp
# Vérifier
curl -s http://localhost:8000/health🔐 Étape 2 — Configurer le proxy OAuth sur le host
Le proxy OAuth réutilise mcp-oauth-proxy déjà installé pour Grav, comme une 2e instance indépendante sur le port 8084 :
# Créer les secrets pour Hugo MCP
sudo mkdir -p /etc/hugo-mcp
sudo tee /etc/hugo-mcp/secrets.env << EOF
HUGO_MCP_URL=http://192.168.122.69:8000
HUGO_MCP_TOKEN=$MCP_TOKEN
MCP_CLIENT_ID=hugo-mcp
MCP_CLIENT_SECRET=$(openssl rand -hex 32)
TOKEN_SECRET=$(openssl rand -hex 32)
PROXY_PORT=8084
PROXY_BASE_URL=https://mcp-hugo.votre-domaine.com
EOF
sudo chmod 600 /etc/hugo-mcp/secrets.env
# Ouvrir le port 8000 dans le firewall VM
# uniquement depuis le host NUC
sudo ufw allow from 192.168.122.1 to any port 8000 proto tcp
# Installer et démarrer le service proxy
sudo systemctl enable --now hugo-mcp-proxy🌐 Étape 3 — Configurer nginx
server {
listen 443 ssl http2;
server_name mcp-hugo.votre-domaine.com;
include snippets/ssl.conf;
location /mcp {
proxy_pass http://127.0.0.1:8084/mcp;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /.well-known/oauth-authorization-server {
proxy_pass http://127.0.0.1:8084/.well-known/oauth-authorization-server;
proxy_set_header Host $host;
}
location /oauth/ {
proxy_pass http://127.0.0.1:8084/oauth/;
proxy_set_header Host $host;
}
}🤝 Étape 4 — Connecter Claude.ai
- Aller sur claude.ai → Settings → Connectors
- Cliquer Add connector
- Entrer l’URL :
https://mcp-hugo.votre-domaine.com/mcp - Suivre le flux OAuth — autoriser l’accès
- Les 6 outils apparaissent dans la liste des connecteurs ✅
🛠️ Les 6 outils disponibles
| Outil | Description |
|---|---|
list_pages | Lister toutes les pages avec filtres par langue et section |
get_page | Lire le frontmatter et le contenu Markdown d’une page |
create_page | Créer une page + rebuild Hugo + purge CF ciblée |
update_page | Modifier une page + rebuild Hugo + purge CF ciblée |
delete_page | Supprimer une page + rebuild Hugo + purge CF totale |
build_site | Rebuild complet Hugo + déploiement + purge CF totale |
🔒 Sécurité
- OAuth 2.1 + PKCE S256 — flux d’authentification sécurisé conforme RFC 9728
- SHA-256 token hashing — les tokens ne sont jamais stockés en clair
- UFW — port 8000 de la VM ouvert uniquement depuis le host NUC (192.168.122.1)
- Systemd hardening —
NoNewPrivileges, service isolé dans la VM - Purge CF ciblée — seules les URLs modifiées sont purgées
🔄 Flux de modification d’une page
Claude.ai → create_page / update_page
│
▼
hugo-mcp écrit le .md
│
▼
deploy.sh : hugo --minify
│
▼
rsync public/ → /var/www/hugo/
│
▼
Cloudflare API : purge_cache (ciblée)
│
▼
Page visible en ~2 secondes🏁 Conclusion
Ce stack transforme Hugo en source de contexte active pour Claude.ai — créer, modifier, gérer le site statique par simple conversation, avec rebuild et purge cache automatiques. L’ensemble réutilise l’infrastructure OAuth déjà en place et est entièrement disponible sur GitHub sous licence MIT.
Pour aller plus loin :
- 💡 Ajouter un outil
list_assetspour gérer les images et fichiers statiques - 💡 Implémenter un webhook Git pour rebuilder automatiquement après un push
- 💡 Migrer le contenu de Grav vers Hugo en automatisant la conversion des frontmatter