Ghost MCP Server

by MFYDev
Verified
"""User-related MCP tools for Ghost API.""" import json from mcp.server.fastmcp import Context from ..api import make_ghost_request, get_auth_headers from ..config import STAFF_API_KEY from ..exceptions import GhostError async def list_users( format: str = "text", page: int = 1, limit: int = 15, ctx: Context = None ) -> str: """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 """ if ctx: ctx.info(f"Listing users (page {page}, limit {limit}, format {format})") try: if ctx: ctx.debug("Getting auth headers") headers = await get_auth_headers(STAFF_API_KEY) if ctx: ctx.debug(f"Making API request to /users/ with pagination") data = await make_ghost_request( f"users/?page={page}&limit={limit}&include=roles", headers, ctx ) if ctx: ctx.debug("Processing users list response") users = data.get("users", []) if not users: if ctx: ctx.info("No users found in response") return "No users found." if format.lower() == "json": if ctx: ctx.debug("Returning JSON format") return json.dumps(users, indent=2) formatted_users = [] for user in users: roles = [role.get('name') for role in user.get('roles', [])] formatted_user = f""" Name: {user.get('name', 'Unknown')} Email: {user.get('email', 'Unknown')} Roles: {', '.join(roles)} Status: {user.get('status', 'Unknown')} ID: {user.get('id', 'Unknown')} """ formatted_users.append(formatted_user) return "\n---\n".join(formatted_users) except GhostError as e: if ctx: ctx.error(f"Failed to list users: {str(e)}") return str(e) async def delete_user( user_id: str, ctx: Context = None ) -> str: """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 """ if not user_id: raise ValueError("user_id is required") if ctx: ctx.info(f"Attempting to delete user with ID: {user_id}") try: # First get the user to check if they are the Owner if ctx: ctx.debug("Getting user details to check role") headers = await get_auth_headers(STAFF_API_KEY) user_data = await make_ghost_request( f"users/{user_id}/", headers, ctx ) user = user_data.get("users", [{}])[0] roles = [role.get('name') for role in user.get('roles', [])] if 'Owner' in roles: error_msg = "Cannot delete the Owner user" if ctx: ctx.error(error_msg) raise GhostError(error_msg) # Proceed with deletion if ctx: ctx.debug(f"Making API request to delete user {user_id}") response = await make_ghost_request( f"users/{user_id}/", headers, ctx, http_method="DELETE" ) return f""" Successfully deleted user: Name: {user.get('name', 'Unknown')} Email: {user.get('email', 'Unknown')} """ except Exception as e: if ctx: ctx.error(f"Failed to delete user: {str(e)}") raise async def read_user(user_id: str, ctx: Context = None) -> str: """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 """ if ctx: ctx.info(f"Reading user details for ID: {user_id}") try: if ctx: ctx.debug("Getting auth headers") headers = await get_auth_headers(STAFF_API_KEY) if ctx: ctx.debug(f"Making API request to /users/{user_id}/") data = await make_ghost_request( f"users/{user_id}/?include=roles", headers, ctx ) if ctx: ctx.debug("Processing user data") user = data["users"][0] roles = [role.get('name') for role in user.get('roles', [])] return f""" Name: {user.get('name', 'Unknown')} Email: {user.get('email', 'Unknown')} Slug: {user.get('slug', 'Unknown')} Status: {user.get('status', 'Unknown')} Roles: {', '.join(roles)} Location: {user.get('location', 'Not specified')} Website: {user.get('website', 'None')} Bio: {user.get('bio', 'No bio')} Profile Image: {user.get('profile_image', 'None')} Cover Image: {user.get('cover_image', 'None')} Created: {user.get('created_at', 'Unknown')} Last Seen: {user.get('last_seen', 'Never')} """ except GhostError as e: return str(e)