Grav MCP Server: connect Claude.ai to your website in 30 minutes

โก In short
Connect Claude.ai to your Grav website in 30 minutes: a PHP plugin exposes 9 tools (read, create, update, delete pages, manage plugins) via JSON-RPC 2.0, a FastAPI proxy handles OAuth 2.1 authentication, and nginx bridges the internet to your server. Result: Claude can read and modify your site content directly from a conversation.
Code available on GitHub:
- ๐ Grav plugin: jmrGrav/grav-plugin-mcp-server
- ๐ OAuth proxy: jmrGrav/mcp-oauth-proxy
๐ง Why
Anthropic’s MCP (Model Context Protocol) allows Claude.ai to connect to external data sources via standardized tools. Until now, no MCP plugin existed for Grav CMS.
This homemade stack enables you to:
- Read and modify pages directly from Claude.ai without opening the Grav admin
- Automate bilingual content creation (FR + EN) in a single conversation
- Trigger actions on the site (clear cache, enable/disable plugins) by simple instruction
- Chain tools: create a page โ IndexNow + Google Indexing trigger automatically
๐ง What was done
๐๏ธ Global architecture
Claude.ai
โ
โ HTTPS (OAuth 2.1 + PKCE)
โผ
โโโโโโโโโโโโโโโโโ
โ Cloudflare โ WAF + Cache
โโโโโโโโโฌโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโ
โ nginx โ SSL termination
โ mcp.site.com โ location /mcp โ proxy
โโโโโโโโโฌโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโ
โ FastAPI proxy โ Port 8083
โ OAuth 2.1 โ Token validation
โ mcp-proxy โ SHA-256 hashing
โโโโโโโโโฌโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโ
โ Grav plugin โ Port 8090 (internal)
โ JSON-RPC 2.0 โ 9 MCP tools
โ PHP 8.3 โ
โโโโโโโโโโโโโโโโโ๐ฆ Components
| Component | Technology | Role |
|---|---|---|
grav-plugin-mcp-server | PHP 8.3 | Exposes MCP tools via JSON-RPC 2.0 |
mcp-oauth-proxy | FastAPI + Python | Handles OAuth 2.1, PKCE S256, tokens |
| nginx vhost | nginx | SSL reverse proxy, /mcp location |
| systemd unit | systemd | Hardened service for the proxy |
๐ Step 1 โ Install the Grav plugin
# Clone the plugin
git clone https://github.com/jmrGrav/grav-plugin-mcp-server.git \
/var/www/grav/user/plugins/mcp-server
# Permissions
sudo chown -R www-data:www-data /var/www/grav/user/plugins/mcp-server
# Clear Grav cache
cd /var/www/grav && sudo -u www-data php bin/grav clearcacheAdd the internal vhost to your nginx Grav config:
# Internal MCP vhost โ accessible only from the proxy
server {
listen 127.0.0.1:8090;
server_name localhost;
root /var/www/grav;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Block direct access to the PHP plugin
location ^~ /api/mcp {
return 444;
}
}๐ Step 2 โ Install the OAuth proxy
# Clone the proxy
git clone https://github.com/jmrGrav/mcp-oauth-proxy.git \
/opt/mcp-oauth-proxy
# Create dedicated user
sudo useradd -r -s /bin/false mcp-proxy
# Create Python virtual environment
cd /opt/mcp-oauth-proxy
python3 -m venv venv
venv/bin/pip install -r requirements.txt
# Configure secrets
sudo mkdir -p /etc/mcp-oauth-proxy
sudo cp secrets.env.example /etc/mcp-oauth-proxy/secrets.env
sudo nano /etc/mcp-oauth-proxy/secrets.env
# โ Fill in MCP_CLIENT_ID, MCP_CLIENT_SECRET, MCP_TOKEN_SECRET
# Install systemd service
sudo cp systemd/mcp-oauth-proxy.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now mcp-oauth-proxy
# Verify
sudo systemctl status mcp-oauth-proxy๐ Step 3 โ Configure nginx
# Copy the vhost template
sudo cp nginx/mcp-vhost.conf /etc/nginx/sites-available/mcp
# Update your-domain.com and SSL paths
sudo nano /etc/nginx/sites-available/mcp
# Enable the vhost
sudo ln -s /etc/nginx/sites-available/mcp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx๐ค Step 4 โ Connect Claude.ai
- Go to claude.ai โ Settings โ Connectors
- Click Add connector
- Enter the URL:
https://mcp.your-domain.com/mcp - Follow the OAuth flow โ authorize access
- The 9 tools appear in the connectors list โ
๐ ๏ธ The 9 available tools
| Tool | Description |
|---|---|
list_pages | List all pages with their routes and languages |
get_page | Read the Markdown content of a page |
create_page | Create a new page |
update_page | Update the content or title of a page |
delete_page | Delete a page |
clear_cache | Clear the Grav cache |
list_plugins | List installed plugins |
list_themes | List installed themes |
toggle_plugin | Enable or disable a plugin |
๐ Security
The proxy implements several layers of protection:
- OAuth 2.1 + PKCE S256 โ secure authentication flow compliant with RFC 9728
- SHA-256 token hashing โ tokens are never stored in plain text
- Atomic JSON writes โ no state file corruption
- Systemd hardening โ
NoNewPrivileges,ProtectSystem=strict,IPAddressDeny=any,MemoryDenyWriteExecute - nginx โ direct access to the PHP plugin blocked (
location ^~ /api/mcp { return 444; })
๐ Conclusion
This stack turns Grav CMS into an active context source for Claude.ai โ read, write, manage your site by simple conversation. The whole thing is reproducible on any nginx server with Python 3.11+, and the code is fully available on GitHub under the MIT license.
To go further:
- ๐ก Add more MCP tools: media management, user management, system configuration
- ๐ก Implement a per-tool permission system to restrict actions based on the OAuth token