Ghost MCP Server
Multi-tenant MCP server that provides Ghost CMS tools to Claude Code runners.
Architecture
A single ghost-mcp container serves all 3 Ghost instances. Each instance is accessed via a unique token in the URL path. The MCP server routes requests to the correct Ghost instance based on this token.
graph LR
rc4["runner-cam4"] -->|"cam4 token"| gmcp["ghost-mcp<br>:3002"]
rc4m["runner-cam4models"] -->|"cam4models token"| gmcp
rc4p["runner-cam4pays"] -->|"cam4pays token"| gmcp
gmcp -->|"Admin API"| cam4["ghost-cam4"]
gmcp -->|"Admin API"| cam4m["ghost-cam4models"]
gmcp -->|"Admin API"| cam4p["ghost-cam4pays"]
Endpoints
| URL | Purpose |
|---|---|
http://ghost-mcp:3002/<token> |
MCP endpoint (internal, per-instance) |
https://mcp.casper.camlab.dev/<token> |
MCP endpoint (external, via Caddy) |
https://mcp.casper.camlab.dev/status |
Health/status endpoint |
Environment Variables
Defined in /opt/camlab/.env, passed to the container:
GHOST_INSTANCES=cam4,cam4models,cam4pays
# Per instance (repeat for each):
GHOST_CAM4_MCP_TOKEN=<hex-token>
GHOST_CAM4_ADMIN_URL=http://ghost-cam4:2368
GHOST_CAM4_ADMIN_API_KEY=<ghost-admin-key>
GHOST_CAM4_CONTENT_URL=http://ghost-cam4:2368
GHOST_CAM4_CONTENT_API_KEY=<ghost-content-key>
MCP Tokens
Each blog has a unique MCP token (generated with openssl rand -hex 16). The token:
- Is used in the URL path to route to the correct Ghost instance
- Is configured in the runner's .mcp.json file
- Must match between .env and the runner config
Token locations:
- Server: /opt/camlab/.env → GHOST_<SLUG>_MCP_TOKEN
- Runner: /opt/camlab/runners/<slug>/claude-config/.mcp.json → ghost.url
Available Tools (24 total — 8 per instance)
The MCP server exposes these Ghost Admin API tools:
| Tool | Description |
|---|---|
| ghost_create_post | Create a new blog post |
| ghost_update_post | Update an existing post |
| ghost_get_post | Get a post by ID or slug |
| ghost_list_posts | List posts with filters |
| ghost_delete_post | Delete a post |
| ghost_upload_image | Upload an image to Ghost |
| ghost_list_tags | List all tags |
| ghost_create_tag | Create a new tag |
Adding a New Instance
- Add env vars to
.env(token, admin URL, API keys) - Add slug to
GHOST_INSTANCESlist - Restart:
docker compose restart ghost-mcp - Verify:
curl -X POST http://localhost:3002/<new-token> -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Troubleshooting
# Check status
curl https://mcp.casper.camlab.dev/status
# View logs
docker compose logs --tail 50 ghost-mcp
# Test a specific instance
curl -X POST http://localhost:3002/<token> \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Restart
docker compose restart ghost-mcp