Ghost MCP Server

by MFYDev
Verified

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
GHOST_API_URLYesYour Ghost Admin API URL
GHOST_STAFF_API_KEYYesYour Ghost Staff API key

Schema

Prompts

Interactive templates invoked by user choice

NameDescription
search_blogPrompt template for searching blog posts
create_summaryCreate a prompt to summarize a blog post

Resources

Contextual data attached and managed by the client

NameDescription
blog://info

Tools

Functions exposed to the LLM to take actions

NameDescription
batchly_update_post

Update multiple blog posts that match the filter criteria.

Args: filter_criteria: Dictionary containing fields to filter posts by, example: { "status": "draft", "tag": "news", "featured": True } Supported filter fields: - status: Post status (draft, published, etc) - tag: Filter by tag name - author: Filter by author name - featured: Boolean to filter featured posts - visibility: Post visibility (public, members, paid) update_data: Dictionary containing the fields to update. The updated_at field is required. All fields supported by the Ghost API can be updated: - slug: Unique URL slug for the post - title: The title of the post - lexical: JSON string representing the post content in lexical format - html: HTML version of the post content - comment_id: Identifier for the comment thread - feature_image: URL to the post's feature image - feature_image_alt: Alternate text for the feature image - feature_image_caption: Caption for the feature image - featured: Boolean flag indicating if the post is featured - status: The publication status (e.g., published, draft) - visibility: Visibility setting (e.g., public, private) - created_at: Timestamp when the post was created - updated_at: Timestamp when the post was last updated (REQUIRED) - published_at: Timestamp when the post was published - custom_excerpt: Custom excerpt text for the post - codeinjection_head: Code to be injected into the head section - codeinjection_foot: Code to be injected into the footer section - custom_template: Custom template assigned to the post - canonical_url: The canonical URL for SEO purposes - tags: List of tag objects associated with the post - authors: List of author objects for the post - primary_author: The primary author object - primary_tag: The primary tag object - og_image: Open Graph image URL for social sharing - og_title: Open Graph title for social sharing - og_description: Open Graph description for social sharing - twitter_image: Twitter-specific image URL - twitter_title: Twitter-specific title - twitter_description: Twitter-specific description - meta_title: Meta title for SEO - meta_description: Meta description for SEO - email_only: Boolean flag indicating if the post is for email distribution only - newsletter: Dictionary containing newsletter configuration details - email: Dictionary containing email details related to the post Example: { "updated_at": "2025-02-11T22:54:40.000Z", "status": "published", "featured": True, "tags": [{"name": "news"}, {"name": "featured"}], "meta_title": "My Updated Title", "og_description": "New social sharing description" } ctx: Optional context for logging Returns: Formatted string containing summary of updated posts Raises: GhostError: If there is an error accessing the Ghost API or missing required fields
browse_tags

Get the list of tags from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of tags per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing tag information Raises: GhostError: If there is an error accessing the Ghost API
create_invite

Create a staff user invite in Ghost.

Args: role_id: ID of the role to assign to the invited user (required) email: Email address to send the invite to (required) ctx: Optional context for logging Returns: String representation of the created invite Raises: GhostError: If the Ghost API request fails ValueError: If required parameters are missing or invalid
create_member

Create a new member in Ghost.

Args: email: Member's email address (required) name: Member's name (optional) note: Notes about the member (optional) labels: List of labels to apply to the member. Each label should be a dict with 'name' and 'slug' (optional) newsletter_ids: List of newsletter IDs to subscribe the member to (optional) ctx: Optional context for logging Returns: String representation of the created member Raises: GhostError: If the Ghost API request fails ValueError: If required parameters are missing or invalid
create_newsletter

Create a new newsletter.

Args: name: Name of the newsletter (required) description: Newsletter description status: Newsletter status ("active" or "archived") subscribe_on_signup: Whether to subscribe new members automatically opt_in_existing: Whether to subscribe existing members sender_reply_to: Reply-to setting ("newsletter" or "support") show_header_icon: Whether to show header icon show_header_title: Whether to show header title show_header_name: Whether to show header name show_feature_image: Whether to show feature image title_font_category: Font category for titles title_alignment: Title alignment body_font_category: Font category for body text show_badge: Whether to show badge ctx: Optional context for logging Returns: Formatted string containing the created newsletter details
create_offer

Create a new offer in Ghost.

Args: name: Internal name for the offer (required) code: Shortcode for the offer (required) type: Either 'percent' or 'fixed' (required) cadence: Either 'month' or 'year' (required) amount: Discount amount - percentage or fixed value (required) tier_id: ID of the tier to apply offer to (required) duration: Either 'once', 'forever' or 'repeating' (required) display_title: Name displayed in the offer window (optional) display_description: Text displayed in the offer window (optional) currency: Required when type is 'fixed', must match tier's currency (optional) duration_in_months: Required when duration is 'repeating' (optional) ctx: Optional context for logging Returns: String representation of the created offer Raises: GhostError: If the Ghost API request fails ValueError: If required parameters are missing or invalid
create_post

Create a new blog post.

Args: post_data: Dictionary containing post data with required fields: - title: The title of the post - lexical: The lexical content as a JSON string Additional optional fields: - status: Post status ('draft' or 'published', defaults to 'draft') - tags: List of tags - authors: List of authors - feature_image: URL of featured image Example: { "title": "My test post", "lexical": "{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Hello World","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}" "status": "draft", } ctx: Optional context for logging Returns: Formatted string containing the created post details Raises: GhostError: If there is an error accessing the Ghost API or invalid post data
create_tag

Create a new tag.

Args: tag_data: Dictionary containing tag data with required fields: - name: The name of the tag Additional optional fields: - slug: URL slug for the tag - description: Description of the tag - feature_image: URL to the tag's feature image - visibility: Tag visibility ('public' or 'internal') - accent_color: CSS color hex value for the tag - meta_title: Meta title for SEO - meta_description: Meta description for SEO - canonical_url: The canonical URL - og_image: Open Graph image URL - og_title: Open Graph title - og_description: Open Graph description - twitter_image: Twitter card image URL - twitter_title: Twitter card title - twitter_description: Twitter card description - codeinjection_head: Code to inject in header - codeinjection_foot: Code to inject in footer Example: { "name": "Technology", "description": "Posts about technology", "visibility": "public" } ctx: Optional context for logging Returns: Formatted string containing the created tag details Raises: GhostError: If there is an error accessing the Ghost API or invalid tag data
create_tier

Create a new tier in Ghost.

Args: name: Name of the tier (required) monthly_price: Optional monthly price in cents (e.g. 500 for $5.00) yearly_price: Optional yearly price in cents (e.g. 5000 for $50.00) description: Optional description of the tier benefits: Optional list of benefits for the tier welcome_page_url: Optional URL for the welcome page visibility: Visibility of tier, either "public" or "none" (default: "public") currency: Currency for prices (default: "usd") ctx: Optional context for logging Returns: String representation of the created tier Raises: GhostError: If the Ghost API request fails
create_webhook

Create a new webhook in Ghost.

Args: event: Event to trigger the webhook (required) target_url: URL to send the webhook to (required) integration_id: ID of the integration (optional - only needed for user authentication) name: Name of the webhook (optional) secret: Secret for the webhook (optional) api_version: API version for the webhook (optional) ctx: Optional context for logging Returns: String representation of the created webhook Raises: GhostError: If the Ghost API request fails ValueError: If required parameters are missing or invalid
delete_post

Delete a blog post.

Args: post_id: The ID of the post to delete ctx: Optional context for logging Returns: Success message if post was deleted Raises: GhostError: If there is an error accessing the Ghost API or the post doesn't exist
delete_tag

Delete a tag.

Args: tag_id: The ID of the tag to delete ctx: Optional context for logging Returns: Success message if tag was deleted Raises: GhostError: If there is an error accessing the Ghost API or the tag doesn't exist
delete_user

Delete a user from Ghost.

Args: user_id: ID of the user to delete (required) ctx: Optional context for logging Returns: Success message if deletion was successful Raises: GhostError: If the Ghost API request fails or if attempting to delete the Owner ValueError: If user_id is not provided
delete_webhook

Delete a webhook from Ghost.

Args: webhook_id: ID of the webhook to delete (required) ctx: Optional context for logging Returns: Success message if deletion was successful Raises: GhostError: If the Ghost API request fails ValueError: If webhook_id is not provided
get_auth_headers

Get authenticated headers for Ghost API requests.

Args: staff_api_key: API key in 'id:secret' format api_version: Ghost API version to use (default: v5.109) Returns: Dictionary of request headers including authorization and version Example: >>> headers = await get_auth_headers("1234:abcd5678") >>> headers { 'Authorization': 'Ghost eyJ0eXAiOiJKV1...', 'Accept-Version': 'v5.109' }
get_close_matches

Use SequenceMatcher to return list of the best "good enough" matches.

word is a sequence for which close matches are desired (typically a string). possibilities is a list of sequences against which to match word (typically a list of strings). Optional arg n (default 3) is the maximum number of close matches to return. n must be > 0. Optional arg cutoff (default 0.6) is a float in [0, 1]. Possibilities that don't score at least that similar to word are ignored. The best (no more than n) matches among the possibilities are returned in a list, sorted by similarity score, most similar first. >>> get_close_matches("appel", ["ape", "apple", "peach", "puppy"]) ['apple', 'ape'] >>> import keyword as _keyword >>> get_close_matches("wheel", _keyword.kwlist) ['while'] >>> get_close_matches("Apple", _keyword.kwlist) [] >>> get_close_matches("accept", _keyword.kwlist) ['except']
import_module

Import a module.

The 'package' argument is required when performing a relative import. It specifies the package to use as the anchor point from which to resolve the relative import to an absolute import.
list_members

Get the list of members from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of members per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing member information
list_newsletters

Get the list of newsletters from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of newsletters per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing newsletter information
list_offers

Get the list of offers from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of offers per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing offer information
list_posts

Get the list of posts from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of posts per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing post information Raises: GhostError: If there is an error accessing the Ghost API
list_roles

Get the list of roles from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of roles per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing role information
list_tiers

Get the list of tiers from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of tiers per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing tier information
list_users

Get the list of users from your Ghost blog.

Args: format: Output format - either "text" or "json" (default: "text") page: Page number for pagination (default: 1) limit: Number of users per page (default: 15) ctx: Optional context for logging Returns: Formatted string containing user information
make_ghost_request

Make an authenticated request to the Ghost API.

Args: endpoint: API endpoint to call (e.g. "posts" or "users") headers: Request headers from get_auth_headers() ctx: Optional context for logging (not used for resources) is_resource: Whether this request is for a resource http_method: HTTP method to use (GET, POST, PUT, or DELETE) json_data: Optional JSON data for POST/PUT requests Returns: Parsed JSON response from the Ghost API Raises: GhostError: For any Ghost API errors including: - Network connectivity issues - Invalid authentication - Rate limiting - Server errors ValueError: For invalid HTTP methods Example: >>> headers = await get_auth_headers("1234:abcd5678") >>> response = await make_ghost_request( ... "posts", ... headers, ... http_method=GET ... )
read_member

Get the details of a specific member.

Args: member_id: The ID of the member to retrieve ctx: Optional context for logging Returns: Formatted string containing the member details
read_newsletter

Get the details of a specific newsletter.

Args: newsletter_id: The ID of the newsletter to retrieve ctx: Optional context for logging Returns: Formatted string containing the newsletter details
read_offer

Get the details of a specific offer.

Args: offer_id: The ID of the offer to retrieve ctx: Optional context for logging Returns: Formatted string containing the offer details
read_post

Get the full content and metadata of a specific blog post.

Args: post_id: The ID of the post to retrieve ctx: Optional context for logging Returns: Formatted string containing all post details including: - Basic info (title, slug, status, etc) - Content in both HTML and Lexical formats - Feature image details - Meta fields (SEO, Open Graph, Twitter) - Authors and tags - Email settings - Timestamps Raises: GhostError: If there is an error accessing the Ghost API
read_tag

Get the full metadata of a specific tag.

Args: tag_id: The ID of the tag to retrieve ctx: Optional context for logging Returns: Formatted string containing all tag details Raises: GhostError: If there is an error accessing the Ghost API
read_tier

Get the details of a specific tier.

Args: tier_id: The ID of the tier to retrieve ctx: Optional context for logging Returns: Formatted string containing the tier details
read_user

Get the details of a specific user.

Args: user_id: The ID of the user to retrieve ctx: Optional context for logging Returns: Formatted string containing the user details
search_posts_by_title

Search for posts by title.

Args: query: The title or part of the title to search for exact: If True, only return exact matches (default: False) ctx: Optional context for logging Returns: Formatted string containing matching post information Raises: GhostError: If there is an error accessing the Ghost API
update_member

Update an existing member in Ghost.

Args: member_id: ID of the member to update (required) email: New email address for the member (optional) name: New name for the member (optional) note: New notes about the member (optional) labels: New list of labels. Each label should be a dict with 'name' and 'slug' (optional) newsletter_ids: New list of newsletter IDs to subscribe the member to (optional) ctx: Optional context for logging Returns: String representation of the updated member Raises: GhostError: If the Ghost API request fails ValueError: If no fields to update are provided
update_newsletter

Update an existing newsletter.

Args: newsletter_id: ID of the newsletter to update (required) name: New newsletter name description: New newsletter description sender_name: Name shown in email clients sender_email: Email address newsletters are sent from sender_reply_to: Reply-to setting ("newsletter" or "support") status: Newsletter status ("active" or "archived") subscribe_on_signup: Whether to subscribe new members automatically sort_order: Order in lists header_image: URL of header image show_header_icon: Whether to show header icon show_header_title: Whether to show header title show_header_name: Whether to show header name title_font_category: Font category for titles title_alignment: Title alignment show_feature_image: Whether to show feature image body_font_category: Font category for body text footer_content: Custom footer content show_badge: Whether to show badge ctx: Optional context for logging Returns: Formatted string containing the updated newsletter details
update_offer

Update an existing offer in Ghost.

Args: offer_id: ID of the offer to update (required) name: New internal name for the offer (optional) code: New shortcode for the offer (optional) display_title: New name displayed in the offer window (optional) display_description: New text displayed in the offer window (optional) ctx: Optional context for logging Returns: String representation of the updated offer Raises: GhostError: If the Ghost API request fails ValueError: If no fields to update are provided
update_post

Update a blog post with new data.

Args: post_id: The ID of the post to update update_data: Dictionary containing the updated data and updated_at timestamp. Note: 'updated_at' is required. If 'lexical' is provided, it must be a valid JSON string. The lexical content must be a properly escaped JSON string in this format: { "root": { "children": [ { "children": [ { "detail": 0, "format": 0, "mode": "normal", "style": "", "text": "Your content here", "type": "text", "version": 1 } ], "direction": "ltr", "format": "", "indent": 0, "type": "paragraph", "version": 1 } ], "direction": "ltr", "format": "", "indent": 0, "type": "root", "version": 1 } } Example usage: update_data = { "post_id": "67abcffb7f82ac000179d76f", "update_data": { "updated_at": "2025-02-11T22:54:40.000Z", "lexical": "{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Hello World","type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}" } } Updatable fields for a blog post: - slug: Unique URL slug for the post. - id: Identifier of the post. - uuid: Universally unique identifier for the post. - title: The title of the post. - lexical: JSON string representing the post content in lexical format. - html: HTML version of the post content. - comment_id: Identifier for the comment thread. - feature_image: URL to the post's feature image. - feature_image_alt: Alternate text for the feature image. - feature_image_caption: Caption for the feature image. - featured: Boolean flag indicating if the post is featured. - status: The publication status (e.g., published, draft). - visibility: Visibility setting (e.g., public, private). - created_at: Timestamp when the post was created. - updated_at: Timestamp when the post was last updated. - published_at: Timestamp when the post was published. - custom_excerpt: Custom excerpt text for the post. - codeinjection_head: Code to be injected into the head section. - codeinjection_foot: Code to be injected into the footer section. - custom_template: Custom template assigned to the post. - canonical_url: The canonical URL for SEO purposes. - tags: List of tag objects associated with the post. - authors: List of author objects for the post. - primary_author: The primary author object. - primary_tag: The primary tag object. - url: Direct URL link to the post. - excerpt: Short excerpt or summary of the post. - og_image: Open Graph image URL for social sharing. - og_title: Open Graph title for social sharing. - og_description: Open Graph description for social sharing. - twitter_image: Twitter-specific image URL. - twitter_title: Twitter-specific title. - twitter_description: Twitter-specific description. - meta_title: Meta title for SEO. - meta_description: Meta description for SEO. - email_only: Boolean flag indicating if the post is for email distribution only. - newsletter: Dictionary containing newsletter configuration details. - email: Dictionary containing email details related to the post. ctx: Optional context for logging Returns: Formatted string containing the updated post details Raises: GhostError: If there is an error accessing the Ghost API or missing required fields
update_tag

Update a tag with new data.

Args: tag_id: The ID of the tag to update update_data: Dictionary containing the updated data. Fields that can be updated: - name: The name of the tag - slug: URL slug for the tag - description: Description of the tag - feature_image: URL to the tag's feature image - visibility: Tag visibility ('public' or 'internal') - accent_color: CSS color hex value for the tag - meta_title: Meta title for SEO - meta_description: Meta description for SEO - canonical_url: The canonical URL - og_image: Open Graph image URL - og_title: Open Graph title - og_description: Open Graph description - twitter_image: Twitter card image URL - twitter_title: Twitter card title - twitter_description: Twitter card description - codeinjection_head: Code to inject in header - codeinjection_foot: Code to inject in footer Example: { "name": "Updated Name", "description": "Updated description" } ctx: Optional context for logging Returns: Formatted string containing the updated tag details Raises: GhostError: If there is an error accessing the Ghost API
update_tier

Update an existing tier in Ghost.

Args: tier_id: ID of the tier to update (required) name: New name for the tier description: New description for the tier monthly_price: New monthly price in cents (e.g. 500 for $5.00) yearly_price: New yearly price in cents (e.g. 5000 for $50.00) benefits: New list of benefits for the tier welcome_page_url: New URL for the welcome page visibility: New visibility setting ("public" or "none") currency: New currency for prices active: New active status ctx: Optional context for logging Returns: String representation of the updated tier Raises: GhostError: If the Ghost API request fails
update_user

Update an existing user in Ghost.

Args: user_id: ID of the user to update (required) name: User's full name (optional) slug: User's slug (optional) email: User's email address (optional) profile_image: URL for profile image (optional) cover_image: URL for cover image (optional) bio: User's bio (optional) website: User's website URL (optional) location: User's location (optional) facebook: Facebook username (optional) twitter: Twitter username (optional) meta_title: Meta title for SEO (optional) meta_description: Meta description for SEO (optional) accessibility: Accessibility settings (optional) comment_notifications: Enable comment notifications (optional) free_member_signup_notification: Enable free member signup notifications (optional) paid_subscription_started_notification: Enable paid subscription started notifications (optional) paid_subscription_canceled_notification: Enable paid subscription canceled notifications (optional) mention_notifications: Enable mention notifications (optional) milestone_notifications: Enable milestone notifications (optional) ctx: Optional context for logging Returns: String representation of the updated user Raises: GhostError: If the Ghost API request fails ValueError: If no fields to update are provided
update_webhook

Update an existing webhook in Ghost.

Args: webhook_id: ID of the webhook to update (required) event: New event to trigger the webhook (optional) target_url: New URL to send the webhook to (optional) name: New name of the webhook (optional) api_version: New API version for the webhook (optional) ctx: Optional context for logging Returns: String representation of the updated webhook Raises: GhostError: If the Ghost API request fails ValueError: If no fields to update are provided or if the event is invalid