Ghost MCP Server
by proars
README.md
# Ghost MCP Server




A TypeScript [MCP](https://modelcontextprotocol.io) server for managing Ghost CMS through AI clients over stdio: posts, pages, SEO, tags, members, newsletters, uploads and exports.
**58 tools:** 54 dedicated API tools, two SEO/tag shortcuts, a route search and a generic caller. The catalog covers **253 routes** from a pinned Ghost source snapshot; availability depends on your credentials, Ghost version and feature flags. See [GHOST_API.list](GHOST_API.list) for routes and sources.
## Quick start
Requires Node.js 20 or newer and access to a Ghost Admin API.
```bash
git clone https://github.com/proars/ghost-mcp-server.git
cd ghost-mcp-server
npm install
cp .env.example .env
```
Edit `.env`:
```dotenv
GHOST_API_URL=https://your-blog.com
GHOST_ADMIN_API_KEY=id:secret
```
Use the canonical **Admin domain**, including any site subdirectory, without `/ghost/api/admin`. For a local site, use an address such as `http://localhost:2368`.
Create a key in **Ghost Admin → Settings → Integrations → Add custom integration**. Copy the complete **Admin API Key** (`id:secret`), not the Content API key.
Configuration is loaded from the project-root `.env`, regardless of the launch directory. Existing environment variables take priority; if both required variables are set, the file is not read. Optional: `GHOST_MCP_ENV_FILE` selects another env file; `GHOST_MCP_SKIP_DOTENV=1` disables file loading.
## Connect your AI client
Replace `/ABSOLUTE/PATH/ghost-mcp-server` with your project path. These examples use the keys from `.env`; you can also supply them through your client's environment configuration.
**Claude Code:**
```bash
claude mcp add ghost -- npm --silent --prefix /ABSOLUTE/PATH/ghost-mcp-server start
```
**Claude Desktop / Cursor:**
```json
{
"mcpServers": {
"ghost-mcp-server": {
"command": "npm",
"args": ["--silent", "--prefix", "/ABSOLUTE/PATH/ghost-mcp-server", "start"]
}
}
}
```
For Claude Desktop on macOS, edit `~/Library/Application Support/Claude/claude_desktop_config.json`. For Cursor, use `~/.cursor/mcp.json` or your project's `.cursor/mcp.json`. Restart the client after configuration.
Other stdio MCP clients can use the same command. Keep `--silent`: npm's startup banner would otherwise enter the MCP protocol stream on stdout.
## Tools
| Resource | Tools |
|---|---|
| Posts | `get_posts`, `get_post`, `get_post_by_slug`, `create_post`, `update_post`, `delete_post`, `copy_post` |
| Pages | `get_pages`, `get_page`, `get_page_by_slug`, `create_page`, `update_page`, `delete_page`, `copy_page` |
| Tags | `get_tags`, `get_tag`, `get_tag_by_slug`, `create_tag`, `update_tag`, `delete_tag` |
| Tiers | `get_tiers`, `get_tier`, `create_tier`, `update_tier` |
| Newsletters | `get_newsletters`, `get_newsletter`, `create_newsletter`, `update_newsletter` |
| Offers | `get_offers`, `get_offer`, `create_offer`, `update_offer` |
| Members | `get_members`, `get_member`, `create_member`, `update_member` |
| Labels | `get_labels`, `create_label`, `update_label`, `delete_label` |
| Staff | `get_users`, `get_user`, `update_user`, `delete_user`, `get_roles`, `invite_user` |
| Images / themes | `upload_image`, `upload_theme`, `activate_theme` |
| Webhooks | `create_webhook`, `update_webhook`, `delete_webhook` |
| Site | `get_site`, `get_settings` |
| Shortcuts | `update_post_seo`, `update_post_tags` |
| Discovery / generic calls | `ghost_list_endpoints`, `ghost_api_request` |
### Calling conventions
- **Create/update:** pass record fields in `data`, with the record `id` as a separate argument. Post/page updates require `data.updated_at` from a fresh read; the SEO/tag shortcuts take `updated_at` directly.
- **Lists:** use `limit`, `page`, `filter`, `order`, `include` and `fields`. Posts/pages return compact fields and tags by default; single-record reads return full records.
- **Tags:** replacing tags replaces the entire set. Missing tags are created; an empty array removes all tags.
- **Publishing:** call `update_post` with `data.status="published"`, or `"scheduled"` plus a future `data.published_at`. Add `newsletter` (slug) and optionally `email_segment` to send email.
- **Images:** `upload_image` takes `file_path`, optional `purpose` (`image`, `profile_image`, `icon`) and `ref`.
For example, ask: "List my latest posts with their SEO titles" or "Create a draft from this HTML."
### Routes without dedicated tools
Use `ghost_list_endpoints` to search by `group`, `method`, `access` or `search`; `without_dedicated_tool=true` finds the other 199 routes. Entries show access requirements, feature flags and upload fields.
Call a route with `ghost_api_request`. Its `path` is relative to `/ghost/api/admin`; substitute actual IDs/slugs, without a query string.
```text
ghost_api_request method=GET path=/labels/slug/vip/
ghost_api_request method=POST path=/members/upload/ files={membersfile: "/Users/me/members.csv"}
ghost_api_request method=GET path=/posts/export/ save_to="/Users/me/posts.csv"
```
Pass JSON payloads in `body` using Ghost's expected structure, query parameters in `query`, and multipart files as `files={formField: "/absolute/path"}` with optional text `fields`.
For downloads, `save_to` must name a new file in an existing writable folder; trailing separators are rejected. Existing files are never overwritten. Set `save_to` on the **first call** of a POST/PUT/DELETE that returns a file—repeating a mutation to retrieve its response can repeat its effect.
## Access and compatibility
| Class | Routes | Requirement |
|---|---:|---|
| `I` / `PUBLIC` | 125 | Integration-key allowlist or public access; handler permissions still apply. |
| `U` | 116 | A staff user's access token with the required role, or a user session. |
| `SESSION` | 3 | User cookie session; integration keys and staff tokens are blocked. |
| `FLOW` | 9 | Login/recovery/setup flows with their own authentication requirements. |
For staff-token access, put the token from the user's Ghost Admin profile into `GHOST_ADMIN_API_KEY`. Its permissions follow the user's role. Staff tokens cannot call `DELETE /db/`, `PUT /users/owner/` or `POST /authentication/reset/`.
The server does not implement cookie sessions, login or 2FA. The catalog includes these routes for discovery, not as supported authentication flows.
Requests send `Accept-Version: v5.0`. The catalog is a snapshot of Ghost's `main` branch and includes newer or experimental routes that may return 404 on your installation. The public Content API is not included.
## Safety and limits
- Keep keys in `.env` or your client's environment; never commit them. Enable manual approval for destructive tools, including all `update_*`/`delete_*` tools, `activate_theme`, `upload_theme` and `ghost_api_request`.
- If a mutation fails after dispatch, check Ghost before retrying: it may already have completed. Use read tools to inspect a truncated response's result.
- Redirects are never followed. Configure the canonical Admin URL; after a mutation receives a redirect, check its result before sending another request.
- Local file paths must be absolute. Hidden path components are refused both as written and after symlink resolution; uploads require regular files. Downloads are reserved before dispatch with owner-only permissions.
- File checks are not a general sandbox: they do not protect sensitive files with visible names or defend against a local process rewriting directory components during a call. Treat site content as untrusted and review upload requests.
- Uploads and downloads are buffered in memory. HTTP requests time out after 120 seconds; tool responses over 100,000 characters are truncated.
## Development
```bash
npm run typecheck # tsc --noEmit
npm test # regression tests with synthetic credentials and a local fake Ghost server
npm run catalog # regenerate src/catalog.ts from GHOST_API.list
npm run build # compile to dist/
npm start # run over stdio (requires configuration)
```
Tests check catalog/tool consistency, request construction, file safety, redirects, retry guidance and configuration isolation. They do not establish compatibility with a live Ghost instance.
Edit `GHOST_API.list` to change routes, then regenerate the catalog and run tests. See [AGENTS.md](AGENTS.md) for architecture and contribution rules. Server logs belong on stderr; stdout is reserved for MCP.
## License
[MIT](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues