From 18672a6977f3ddd5a366fead777a7ae524a93c89 Mon Sep 17 00:00:00 2001 From: Fanyang Meng Date: Tue, 11 Feb 2025 23:42:03 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Support=20creating=20invites?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/ghost_mcp/server.py | 1 + src/ghost_mcp/tools.py | 4 +- src/ghost_mcp/tools/__init__.py | 4 +- src/ghost_mcp/tools/invites.py | 75 +++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/ghost_mcp/tools/invites.py diff --git a/README.md b/README.md index 699aef3..7277a51 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ GHOST_API_URL=your_ghost_api_url GHOST_STAFF_API_KEY=your_staff_api_key npx @mod ### Users Management - `list_roles`: List all available roles +- `create_invite`: Create a new user invitation email and role_id - `list_users`: List all users with detailed role information - `read_user`: Get comprehensive details of a specific user diff --git a/src/ghost_mcp/server.py b/src/ghost_mcp/server.py index 8164888..399460d 100644 --- a/src/ghost_mcp/server.py +++ b/src/ghost_mcp/server.py @@ -66,6 +66,7 @@ def create_server() -> FastMCP: mcp.tool()(tools.create_newsletter) mcp.tool()(tools.update_newsletter) mcp.tool()(tools.list_roles) + mcp.tool()(tools.create_invite) # Register prompts @mcp.prompt() diff --git a/src/ghost_mcp/tools.py b/src/ghost_mcp/tools.py index b72b59f..603ca32 100644 --- a/src/ghost_mcp/tools.py +++ b/src/ghost_mcp/tools.py @@ -38,6 +38,7 @@ from .tools.newsletters import ( update_newsletter ) from .tools.roles import list_roles +from .tools.invites import create_invite __all__ = [ 'search_posts_by_title', @@ -63,5 +64,6 @@ __all__ = [ 'read_newsletter', 'create_newsletter', 'update_newsletter', - 'list_roles' + 'list_roles', + 'create_invite' ] diff --git a/src/ghost_mcp/tools/__init__.py b/src/ghost_mcp/tools/__init__.py index 631f635..432a146 100644 --- a/src/ghost_mcp/tools/__init__.py +++ b/src/ghost_mcp/tools/__init__.py @@ -7,6 +7,7 @@ from .tiers import list_tiers, read_tier, create_tier, update_tier from .offers import list_offers, read_offer, create_offer, update_offer from .newsletters import list_newsletters, read_newsletter, create_newsletter, update_newsletter from .roles import list_roles +from .invites import create_invite __all__ = [ 'search_posts_by_title', @@ -33,5 +34,6 @@ __all__ = [ 'read_newsletter', 'create_newsletter', 'update_newsletter', - 'list_roles' + 'list_roles', + 'create_invite' ] diff --git a/src/ghost_mcp/tools/invites.py b/src/ghost_mcp/tools/invites.py new file mode 100644 index 0000000..1f1a6e5 --- /dev/null +++ b/src/ghost_mcp/tools/invites.py @@ -0,0 +1,75 @@ +"""Invite-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 create_invite( + role_id: str, + email: str, + ctx: Context = None +) -> str: + """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 + """ + if not all([role_id, email]): + raise ValueError("Both role_id and email are required for creating an invite") + + if ctx: + ctx.info(f"Creating invite for email: {email} with role: {role_id}") + + # Construct invite data + invite_data = { + "invites": [{ + "role_id": role_id, + "email": email + }] + } + + try: + if ctx: + ctx.debug("Getting auth headers") + headers = await get_auth_headers(STAFF_API_KEY) + + if ctx: + ctx.debug("Making API request to create invite") + response = await make_ghost_request( + "invites/", + headers, + ctx, + http_method="POST", + json_data=invite_data + ) + + if ctx: + ctx.debug("Processing created invite response") + + invite = response.get("invites", [{}])[0] + + return f""" +Invite created successfully: +Email: {invite.get('email')} +Role ID: {invite.get('role_id')} +Status: {invite.get('status', 'sent')} +Created: {invite.get('created_at', 'Unknown')} +Expires: {invite.get('expires', 'Unknown')} +ID: {invite.get('id')} +""" + except Exception as e: + if ctx: + ctx.error(f"Failed to create invite: {str(e)}") + raise