mirror of
https://github.com/jlengrand/ghost-mcp.git
synced 2026-03-10 00:11:21 +00:00
✨ Support update users
This commit is contained in:
@@ -82,6 +82,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
|
||||
- `update_user`: Update an existing user's information **(Please note: Ghost has not implemented the ability to update user roles via the API even though they include it in the API documentation)**
|
||||
- `list_users`: List all users with detailed role information
|
||||
- `read_user`: Get comprehensive details of a specific user
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ async def get_auth_headers(staff_api_key: str) -> Dict[str, str]:
|
||||
token = await generate_token(staff_api_key)
|
||||
return {
|
||||
"Authorization": f"Ghost {token}",
|
||||
"Accept-Version": "v5"
|
||||
"Accept-Version": "v5.109"
|
||||
}
|
||||
|
||||
async def make_ghost_request(
|
||||
|
||||
@@ -49,6 +49,7 @@ def create_server() -> FastMCP:
|
||||
mcp.tool()(tools.delete_post)
|
||||
mcp.tool()(tools.list_users)
|
||||
mcp.tool()(tools.read_user)
|
||||
mcp.tool()(tools.update_user)
|
||||
mcp.tool()(tools.list_members)
|
||||
mcp.tool()(tools.read_member)
|
||||
mcp.tool()(tools.create_member)
|
||||
|
||||
@@ -11,7 +11,8 @@ from .tools.posts import (
|
||||
)
|
||||
from .tools.users import (
|
||||
list_users,
|
||||
read_user
|
||||
read_user,
|
||||
update_user
|
||||
)
|
||||
from .tools.members import (
|
||||
list_members,
|
||||
@@ -49,6 +50,7 @@ __all__ = [
|
||||
'delete_post',
|
||||
'list_users',
|
||||
'read_user',
|
||||
'update_user',
|
||||
'list_members',
|
||||
'read_member',
|
||||
'create_member',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Ghost MCP tools package."""
|
||||
|
||||
from .posts import search_posts_by_title, list_posts, read_post, create_post, update_post, delete_post
|
||||
from .users import list_users, read_user
|
||||
from .users import list_users, read_user, update_user
|
||||
from .members import list_members, read_member, create_member, update_member
|
||||
from .tiers import list_tiers, read_tier, create_tier, update_tier
|
||||
from .offers import list_offers, read_offer, create_offer, update_offer
|
||||
@@ -18,6 +18,7 @@ __all__ = [
|
||||
'delete_post',
|
||||
'list_users',
|
||||
'read_user',
|
||||
'update_user',
|
||||
'list_members',
|
||||
'read_member',
|
||||
'create_member',
|
||||
|
||||
@@ -72,6 +72,149 @@ ID: {user.get('id', 'Unknown')}
|
||||
ctx.error(f"Failed to list users: {str(e)}")
|
||||
return str(e)
|
||||
|
||||
async def update_user(
|
||||
user_id: str,
|
||||
name: str = None,
|
||||
slug: str = None,
|
||||
email: str = None,
|
||||
profile_image: str = None,
|
||||
cover_image: str = None,
|
||||
bio: str = None,
|
||||
website: str = None,
|
||||
location: str = None,
|
||||
facebook: str = None,
|
||||
twitter: str = None,
|
||||
meta_title: str = None,
|
||||
meta_description: str = None,
|
||||
accessibility: str = None,
|
||||
comment_notifications: bool = None,
|
||||
free_member_signup_notification: bool = None,
|
||||
paid_subscription_started_notification: bool = None,
|
||||
paid_subscription_canceled_notification: bool = None,
|
||||
mention_notifications: bool = None,
|
||||
milestone_notifications: bool = None,
|
||||
ctx: Context = None
|
||||
) -> str:
|
||||
"""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
|
||||
"""
|
||||
# Check if at least one field to update is provided
|
||||
update_fields = {
|
||||
'name': name,
|
||||
'slug': slug,
|
||||
'email': email,
|
||||
'profile_image': profile_image,
|
||||
'cover_image': cover_image,
|
||||
'bio': bio,
|
||||
'website': website,
|
||||
'location': location,
|
||||
'facebook': facebook,
|
||||
'twitter': twitter,
|
||||
'meta_title': meta_title,
|
||||
'meta_description': meta_description,
|
||||
'accessibility': accessibility,
|
||||
'comment_notifications': comment_notifications,
|
||||
'free_member_signup_notification': free_member_signup_notification,
|
||||
'paid_subscription_started_notification': paid_subscription_started_notification,
|
||||
'paid_subscription_canceled_notification': paid_subscription_canceled_notification,
|
||||
'mention_notifications': mention_notifications,
|
||||
'milestone_notifications': milestone_notifications
|
||||
}
|
||||
|
||||
if not any(v is not None for v in update_fields.values()):
|
||||
raise ValueError("At least one field must be provided to update")
|
||||
|
||||
if ctx:
|
||||
ctx.info(f"Updating user with ID: {user_id}")
|
||||
|
||||
# Construct update data with only provided fields
|
||||
update_data = {"users": [{}]}
|
||||
user_updates = update_data["users"][0]
|
||||
|
||||
for field, value in update_fields.items():
|
||||
if value is not None:
|
||||
user_updates[field] = value
|
||||
|
||||
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 update user {user_id}")
|
||||
response = await make_ghost_request(
|
||||
f"users/{user_id}/",
|
||||
headers,
|
||||
ctx,
|
||||
http_method="PUT",
|
||||
json_data=update_data
|
||||
)
|
||||
|
||||
if ctx:
|
||||
ctx.debug("Processing updated user response")
|
||||
|
||||
user = response.get("users", [{}])[0]
|
||||
roles = [role.get('name') for role in user.get('roles', [])]
|
||||
|
||||
return f"""
|
||||
User updated successfully:
|
||||
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')}
|
||||
Facebook: {user.get('facebook', 'None')}
|
||||
Twitter: {user.get('twitter', 'None')}
|
||||
Created: {user.get('created_at', 'Unknown')}
|
||||
Updated: {user.get('updated_at', 'Unknown')}
|
||||
Last Seen: {user.get('last_seen', 'Never')}
|
||||
Notifications:
|
||||
- Comments: {user.get('comment_notifications', False)}
|
||||
- Free Member Signup: {user.get('free_member_signup_notification', False)}
|
||||
- Paid Subscription Started: {user.get('paid_subscription_started_notification', False)}
|
||||
- Paid Subscription Canceled: {user.get('paid_subscription_canceled_notification', False)}
|
||||
- Mentions: {user.get('mention_notifications', False)}
|
||||
- Milestones: {user.get('milestone_notifications', False)}
|
||||
"""
|
||||
except Exception as e:
|
||||
if ctx:
|
||||
ctx.error(f"Failed to update user: {str(e)}")
|
||||
raise
|
||||
|
||||
async def read_user(user_id: str, ctx: Context = None) -> str:
|
||||
"""Get the details of a specific user.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user