Skip to main content
Glama
field_plugins.py7.6 kB
from typing import Any, Dict, Optional from httpx import AsyncClient from mcp.server.fastmcp import FastMCP from utils.api import get_management_headers, _handle_response, APIError def register_field_plugin_retrieval(mcp: FastMCP, client: AsyncClient) -> None: @mcp.tool() async def retrieve_field_plugins( context: str = "space", only_mine: Optional[int] = 1, page: Optional[int] = 1, per_page: Optional[int] = 25, search: Optional[str] = None ) -> Any: """ Retrieves multiple field plugins (field types) across different contexts. Args: context (str): 'space', 'org', or 'partner' only_mine (int): 1 = only plugins created by authenticated user page (int): pagination page number per_page (int): plugins per page (max 100) search (str): search filter for plugin name or slug """ try: url_map = { "space": "https://mapi.storyblok.com/v1/field_types/", "org": "https://mapi.storyblok.com/v1/org_field_types/", "partner": "https://mapi.storyblok.com/v1/partner_field_types/" } if context not in url_map: return {"isError": True, "content": [{"type": "text", "text": f"Context must be one of {list(url_map.keys())}"}]} params: dict[str, Any] = {} if only_mine is not None: params["only_mine"] = only_mine if page is not None: params["page"] = page if per_page is not None: params["per_page"] = per_page if search is not None: params["search"] = search resp = await client.get(url_map[context], headers=get_management_headers(), params=params) return _handle_response(resp, url_map[context]) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def retrieve_field_plugin( field_type_id: int, context: str = "space" ) -> Any: """ Retrieves a single field plugin by its ID in the specified context. Args: field_type_id (int): Numeric ID of the field plugin. context (str): 'space', 'org', or 'partner'. """ url_map = { "space": f"https://mapi.storyblok.com/v1/field_types/{field_type_id}", "org": f"https://mapi.storyblok.com/v1/org_field_types/{field_type_id}", "partner": f"https://mapi.storyblok.com/v1/partner_field_types/{field_type_id}", } if context not in url_map: return {"isError": True, "content": [{"type": "text", "text": "Context must be 'space', 'org', or 'partner'."}]} url = url_map[context] try: 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_field_plugin( name: str, body: str, compiled_body: str = "", context: str = "space" ) -> Any: """ Creates a new field plugin (field type) in the specified context. Args: name (str): Unique name for your plugin (e.g., 'my-geo-selector'). body (str): The uncompiled JavaScript source for the plugin. compiled_body (str): Required; empty string if developing locally. context (str): 'space', 'org', or 'partner'. """ try: url_map = { "space": "https://mapi.storyblok.com/v1/field_types/", "org": "https://mapi.storyblok.com/v1/org_field_types/", "partner": "https://mapi.storyblok.com/v1/partner_field_types/" } if context not in url_map: return {"isError": True, "content": [{"type": "text", "text": "Invalid context: choose 'space', 'org', or 'partner'."}]} payload = { "field_type": { "name": name, "body": body, "compiled_body": compiled_body } } resp = await client.post(url_map[context], json=payload, headers=get_management_headers()) return _handle_response(resp, url_map[context]) except APIError as e: return {"isError": True, "content": [{"type": "text", "text": str(e)}]} @mcp.tool() async def update_field_plugin( field_type_id: int, body: Optional[str] = None, compiled_body: Optional[str] = None, name: Optional[str] = None, options: Optional[Dict[str, Any]] = None, space_ids: Optional[list[int]] = None, context: str = "space" ) -> Any: """ Updates an existing field plugin in the specified context. Args: field_type_id: Numeric ID of the field plugin. body: Updated uncompiled JS source. compiled_body: Updated compiled JS source. name: Optional new name (must still be unique). options: Optional config options for the plugin. space_ids: Optional space assignment list. context: 'space', 'org', or 'partner'. """ url_map = { "space": f"https://mapi.storyblok.com/v1/field_types/{field_type_id}", "org": f"https://mapi.storyblok.com/v1/org_field_types/{field_type_id}", "partner": f"https://mapi.storyblok.com/v1/partner_field_types/{field_type_id}" } if context not in url_map: return {"isError": True, "content":[{"type":"text","text":"Invalid context: use 'space', 'org' or 'partner'."}]} payload: Dict[str, Any] = {"field_type": {}} if name is not None: payload["field_type"]["name"] = name if body is not None: payload["field_type"]["body"] = body if compiled_body is not None: payload["field_type"]["compiled_body"] = compiled_body if options is not None: payload["field_type"]["options"] = options if space_ids is not None: payload["field_type"]["space_ids"] = space_ids try: resp = await client.put( url_map[context], headers=get_management_headers(), json=payload ) return _handle_response(resp, url_map[context]) except APIError as e: return {"isError": True, "content": [{"type":"text","text":str(e)}]} @mcp.tool() async def delete_field_plugin(field_type_id: int) -> Any: """ Deletes a field plugin by its ID. Args: field_type_id (int): Numeric ID of the field plugin to delete. """ url = f"https://mapi.storyblok.com/v1/field_types/{field_type_id}" try: resp = await client.delete(url, headers=get_management_headers()) if resp.status_code == 204: return {"isError": False, "content": [{"type": "text", "text": "Field plugin deleted successfully."}]} else: return {"isError": True, "content": [{"type": "text", "text": f"Failed to delete field plugin. Status code: {resp.status_code}"}]} 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