Skip to main content
Glama
discussions.py9.65 kB
from typing import Any, Dict, List, Optional from httpx import AsyncClient from mcp.server.fastmcp import FastMCP from utils.api import build_management_url, get_management_headers, _handle_response, APIError def register_discussions(mcp: FastMCP, client: AsyncClient) -> None: @mcp.tool() async def retrieve_multiple_discussions( story_id: int, per_page: Optional[int] = 25, page: Optional[int] = 1, by_status: Optional[str] = None ) -> Any: """ Retrieves multiple discussions for a specific story in a Storyblok space. - story_id: Numeric ID of the story. - per_page: Number of discussions per page (default: 25, max: 100). - page: Page number to retrieve (default: 1). - by_status: Filter discussions by status (e.g., 'unsolved', 'solved'). """ try: params = { "per_page": per_page, "page": page, "by_status": by_status } url = build_management_url(f"/stories/{story_id}/discussions") resp = await client.get(url, params=params, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def retrieve_specific_discussion( discussion_id: int ) -> Any: """ Retrieves a specific discussion by its ID in a Storyblok space. - discussion_id: Numeric ID of the discussion. """ try: url = build_management_url(f"/discussions/{discussion_id}") resp = await client.get(url, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def retrieve_idea_discussions_comments( discussion_uuid: str ) -> Any: """ Retrieves comments for a specific idea discussion in a Storyblok space. - discussion_uuid: UUID of the discussion in the idea. """ try: url = build_management_url(f"/discussions/{discussion_uuid}/comments") resp = await client.get(url, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def create_discussion( story_id: int, title: str, fieldname: str, block_uid: str, component: str, lang: str, message_json: List[Dict[str, Any]] ) -> Any: """ Creates a new discussion for a story via the Storyblok Management API. Required: - story_id: ID of the story - title: Title of the discussion field - fieldname: Technical name of the discussion field - block_uid: ID of the discussion block - component: Component/block name this discussion belongs to - lang: Language code (e.g., "default", "en") - message_json: Array of message objects [{"type": "text", "text": "...", "attrs": {...}}, ...] """ try: payload = { "discussion": { "title": title, "fieldname": fieldname, "block_uid": block_uid, "component": component, "lang": lang, "comment": { "message_json": message_json } } } url = build_management_url(f"/stories/{story_id}/discussions") resp = await client.post(url, json=payload, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def retrieve_my_discussions( page: Optional[int] = 1, per_page: Optional[int] = 25, by_status: Optional[str] = None ) -> Any: """ Retrieves discussions you're involved in within a Storyblok space. - space_id: Numeric ID of the space. - page: Page number (default 1). - per_page: Items per page (default 25, max 100). - by_status: Filter discussions by status ('unsolved' or 'solved'). """ try: params = { "page": page, "per_page": per_page } if by_status is not None: params["by_status"] = by_status url = build_management_url(f"/mentioned_discussions/me") resp = await client.get(url, params=params, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def resolve_discussion( discussion_id: int, solved_at: str ) -> Any: """ Marks a discussion as resolved via the Storyblok Management API. - discussion_id: Numeric ID of the discussion. - solved_at: Timestamp when the discussion is resolved (ISO 8601 format). """ try: payload = { "discussion": { "solved_at": solved_at } } url = build_management_url(f"/discussions/{discussion_id}") resp = await client.put(url, json=payload, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def retrieve_multiple_comments( discussion_id: int ) -> Any: """ Retrieves all comments from a specific discussion via the Storyblok Management API. - discussion_id: Numeric ID of the discussion. """ try: url = build_management_url(f"/discussions/{discussion_id}/comments") resp = await client.get(url, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def create_comment( discussion_id: int, message_json: List[Dict[str, Any]], message: Optional[str] = None ) -> Any: """ Adds a comment to a discussion via the Storyblok Management API. - discussion_id: Numeric ID of the discussion. - message_json: Required array of message objects. Each must include "type", "text", and "attrs". - message: Optional plain-text field (can be null or string). """ try: payload = { "comment": { "message_json": message_json } } # Include optional `message` field if message is not None: payload["comment"]["message"] = message url = build_management_url(f"/discussions/{discussion_id}/comments") resp = await client.post(url, json=payload, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def update_comment( discussion_id: int, comment_id: int, message_json: List[Dict[str, Any]], message: Optional[str] = None ) -> Any: """ Updates a comment in a discussion via the Storyblok Management API. Required: - discussion_id: Numeric ID of the discussion. - comment_id: Numeric ID of the comment. Payload: - message_json: Required. Array of message objects, each with keys "type", "text", "attrs". - message: Optional string or null. """ try: payload = { "comment": { "message_json": message_json } } # Include optional message field when provided if message is not None: payload["comment"]["message"] = message url = build_management_url( f"/discussions/{discussion_id}/comments/{comment_id}" ) resp = await client.put(url, json=payload, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def delete_comment( discussion_id: int, comment_id: int ) -> Any: """ Deletes a comment from a discussion via the Storyblok Management API. - discussion_id: Numeric ID of the discussion. - comment_id: Numeric ID of the comment. """ try: url = build_management_url( f"/discussions/{discussion_id}/comments/{comment_id}" ) resp = await client.delete(url, headers=get_management_headers()) return _handle_response(resp, url) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Kiran1689/storyblok-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server