Ghost MCP Server

by MFYDev
Verified
"""Main Ghost meta-tool that provides access to all Ghost functionality.""" import inspect from mcp.server.fastmcp import Context from typing import Any, Dict, Optional, List from .. import tools from ..exceptions import GhostError async def ghost( action: str, params: Optional[Dict[str, Any]] = None, ctx: Optional[Context] = None ) -> str: """Central Ghost tool that provides access to all Ghost CMS functionality. Args: action: The specific Ghost action to perform. Available actions: - Posts: list_posts, search_posts_by_title, read_post, create_post, update_post, delete_post, batchly_update_posts - Users: list_users, read_user, delete_user, list_roles - Members: list_members, read_member, create_member, update_member - Tags: browse_tags, read_tag, create_tag, update_tag, delete_tag - Tiers: list_tiers, read_tier, create_tier, update_tier - Offers: list_offers, read_offer, create_offer, update_offer - Newsletters: list_newsletters, read_newsletter, create_newsletter, update_newsletter - Webhooks: create_webhook, update_webhook, delete_webhook - Invites: create_invite params: Dictionary of parameters specific to the chosen action. Required parameters vary by action. ctx: Optional context for logging Returns: Response from the specified Ghost action Raises: GhostError: If there is an error processing the request """ if ctx: ctx.info(f"Ghost tool called with action: {action}, params: {params}") # Validate action if action not in tools._all_tools: valid_actions = ", ".join(tools._all_tools) return f"Invalid action '{action}'. Valid actions are: {valid_actions}" # Get the function for the specified action tool_func = getattr(tools, action) if not inspect.isfunction(tool_func): return f"Invalid action '{action}'. This is not a valid function." # Prepare parameters for the function call if params is None: params = {} # Add context to params if the function expects it sig = inspect.signature(tool_func) call_params = params.copy() if 'ctx' in sig.parameters: call_params['ctx'] = ctx try: # Call the function with the appropriate parameters result = await tool_func(**call_params) return result except GhostError as e: if ctx: ctx.error(f"Ghost tool error for action '{action}': {str(e)}") return f"Error executing '{action}': {str(e)}" except TypeError as e: # This usually happens when the wrong parameters are provided if ctx: ctx.error(f"Parameter error for action '{action}': {str(e)}") # Get the function parameters to provide better error messages params_info = [] for name, param in sig.parameters.items(): if name == 'ctx': continue param_type = param.annotation.__name__ if param.annotation != inspect.Parameter.empty else "any" default = f"(default: {param.default})" if param.default != inspect.Parameter.empty else "(required)" params_info.append(f"- {name}: {param_type} {default}") params_help = "\n".join(params_info) return f"Error: {str(e)}\n\nExpected parameters for '{action}':\n{params_help}" except Exception as e: if ctx: ctx.error(f"Unexpected error for action '{action}': {str(e)}") return f"Unexpected error executing '{action}': {str(e)}"