Skip to main content
Glama
assets.py8.14 kB
import json from typing import Optional, Dict, Any, Literal, List from httpx import AsyncClient from mcp.server.fastmcp import FastMCP from utils.api import ( build_management_url, get_management_headers, _handle_response, create_pagination_params, add_optional_params, APIError, ) from datetime import datetime def register_assets(mcp: FastMCP, client: AsyncClient) -> None: @mcp.tool() async def fetch_assets( page: Optional[int] = 1, per_page: Optional[int] = 25, search: Optional[str] = None, folder_id: Optional[int] = None, sort_by: Optional[Literal[ "created_at:asc", "created_at:desc", "updated_at:asc", "updated_at:desc", "short_filename:asc", "short_filename:desc" ]] = None, is_private: Optional[bool] = None, by_alt: Optional[str] = None, by_title: Optional[str] = None, by_copyright: Optional[str] = None, with_tags: Optional[str] = None ) -> Any: """ Retrieve multiple assets from Storyblok Management API. """ try: params = create_pagination_params(page, per_page) add_optional_params(params, { "search": search, "in_folder": folder_id, "sort_by": sort_by, "is_private": "1" if is_private else None, "by_alt": by_alt, "by_title": by_title, "by_copyright": by_copyright, "with_tags": with_tags, }) url = build_management_url("/assets") 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 get_asset(id: str) -> Any: """Gets a specific asset by ID.""" try: url = build_management_url(f"/assets/{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 delete_asset(id: str) -> Any: """Deletes an asset from Storyblok.""" try: url = build_management_url(f"/assets/{id}") resp = await client.delete(url, headers=get_management_headers()) _handle_response(resp, url) return {"content": [{"type": "text", "text": f"Asset {id} has been successfully deleted."}]} except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def update_asset( asset_id: int, asset_folder_id: Optional[int] = None, internal_tag_ids: Optional[List[int]] = None, locked: Optional[bool] = None, is_private: Optional[bool] = None, publish_at: Optional[datetime] = None, expire_at: Optional[datetime] = None, focus: Optional[str] = None, alt: Optional[str] = None, title: Optional[str] = None, source: Optional[str] = None, copyright: Optional[str] = None, meta_data: Optional[Dict[str, Any]] = None ) -> Any: """ Update an existing asset’s metadata or settings. """ try: payload: Dict[str, Any] = {} # Core fields for field, value in [ ("asset_folder_id", asset_folder_id), ("internal_tag_ids", internal_tag_ids), ("locked", locked), ("is_private", is_private), ("publish_at", publish_at.isoformat() if publish_at else None), ("expire_at", expire_at.isoformat() if expire_at else None), ("focus", focus), ]: if value is not None: payload[field] = value # Metadata fields md: Dict[str, Any] = meta_data or {} for field, value in [ ("alt", alt), ("title", title), ("source", source), ("copyright", copyright), ]: if value is not None and field not in md: md[field] = value if md: payload["meta_data"] = md url = build_management_url(f"/assets/{asset_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_multiple_assets( ids: List[int] ) -> Any: """ Deletes multiple assets by numeric IDs using the Storyblok Management API. """ if not ids: return {"isError": True, "content": [{"type": "text", "text": "ids list cannot be empty"}]} try: payload = {"ids": ids} url = build_management_url("/assets/bulk_destroy") 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 bulk_move_assets( ids: List[int], asset_folder_id: int ) -> Any: """ Move multiple assets to a specified folder. """ if not ids: return {"isError": True, "content": [{"type": "text", "text": "ids list cannot be empty"}]} if not isinstance(asset_folder_id, int): return {"isError": True, "content": [{"type": "text", "text": "asset_folder_id must be an integer"}]} try: payload = { "ids": ids, "asset_folder_id": asset_folder_id } url = build_management_url("/assets/bulk_update") 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 bulk_restore_assets( ids: List[int] ) -> Any: """ Restores multiple previously deleted assets """ if not ids: return {"isError": True, "content": [{"type": "text", "text": "ids list cannot be empty"}]} try: payload = {"ids": ids} url = build_management_url("/assets/bulk_restore") 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 init_asset_upload(filename: str, size: int, content_type: str) -> Any: """Initializes asset upload and returns signed S3 upload URL.""" try: url = build_management_url("/assets") payload = {"filename": filename, "size": size, "content_type": content_type} 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 complete_asset_upload(asset_id: str) -> Any: """Completes the asset upload process after S3 upload.""" try: url = build_management_url(f"/assets/{asset_id}/finish_upload") resp = await client.post(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