Skip to main content
Glama

Storyblok MCP Server

by ArjunCodess
storyblok.ts72 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import axios from "axios"; import { CDN_BASE, MANAGEMENT_BASE, MANAGEMENT_TOKEN, PUBLIC_TOKEN, SPACES_BASE, buildURL, getHeaders, toQuery } from "./utils.js"; import { generateText, generateObject } from 'ai'; import { google } from '@ai-sdk/google'; export function storyblok(server: McpServer) { server.tool('ping', {}, async () => { try { await axios.get(`${CDN_BASE}/spaces/${process.env.STORYBLOK_SPACE_ID}?token=${PUBLIC_TOKEN}`); return { content: [{ type: 'text', text: 'Server is running and Storyblok API is reachable.' }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_stories', { page: z.number().optional(), per_page: z.number().optional(), starts_with: z.string().optional(), by_slugs: z.string().optional(), excluding_slugs: z.string().optional(), sort_by: z.string().optional(), search_term: z.string().optional() }, async (params) => { try { const q = toQuery({ ...params, token: PUBLIC_TOKEN }); const res = await axios.get(`${CDN_BASE}/stories${q}`); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_story', { id: z.string() }, async ({ id }) => { try { const q = toQuery({ token: PUBLIC_TOKEN }); const res = await axios.get(`${CDN_BASE}/stories/${id}${q}`); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_story', { name: z.string(), slug: z.string(), content: z.record(z.unknown()), parent_id: z.number().optional(), group_id: z.string().optional(), alternates: z.array(z.unknown()).optional(), is_folder: z.boolean().optional(), is_startpage: z.boolean().optional(), tag_list: z.array(z.string()).optional(), published: z.boolean().optional(), sort_by_date: z.string().optional(), default_root: z.string().optional(), disble_fe_editor: z.boolean().optional(), meta_data: z.unknown().optional(), pinned: z.boolean().optional(), position: z.number().optional(), path: z.string().optional(), publish_at: z.string().optional(), expire_at: z.string().optional(), is_scheduled: z.boolean().optional(), scheduled_dates: z.string().optional(), favourite_for_user_ids: z.array(z.number()).optional() }, async (params) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'stories'), { story: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_story', { id: z.string(), name: z.string().optional(), slug: z.string().optional(), content: z.record(z.unknown()).optional(), parent_id: z.number().optional(), group_id: z.string().optional(), alternates: z.array(z.unknown()).optional(), is_folder: z.boolean().optional(), is_startpage: z.boolean().optional(), tag_list: z.array(z.string()).optional(), published: z.boolean().optional(), sort_by_date: z.string().optional(), default_root: z.string().optional(), disble_fe_editor: z.boolean().optional(), meta_data: z.unknown().optional(), pinned: z.boolean().optional(), position: z.number().optional(), path: z.string().optional(), publish_at: z.string().optional(), expire_at: z.string().optional(), is_scheduled: z.boolean().optional(), scheduled_dates: z.string().optional(), favourite_for_user_ids: z.array(z.number()).optional() }, async ({ id, ...params }) => { try { const res = await axios.put(buildURL(MANAGEMENT_BASE, `stories/${id}`), { story: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_story', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `stories/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Story ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('publish_story', { id: z.string() }, async ({ id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `stories/${id}/publish`), {}, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('unpublish_story', { id: z.string() }, async ({ id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `stories/${id}/unpublish`), {}, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_story_versions', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `stories/${id}/versions`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('restore_story', { id: z.string(), version_id: z.string() }, async ({ id, version_id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `stories/${id}/restore/${version_id}`), {}, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('import_story', { id: z.string(), story: z.record(z.unknown()), lang_code: z.string().optional(), import_lang: z.boolean().optional() }, async ({ id, story, lang_code, import_lang }) => { try { const params = []; if (lang_code) params.push(`lang_code=${encodeURIComponent(lang_code)}`); if (import_lang !== undefined) params.push(`import_lang=${import_lang}`); const query = params.length ? `?${params.join('&')}` : ''; const res = await axios.put( buildURL(MANAGEMENT_BASE, `stories/${id}/import${query}`), { story }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_tags', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'tags'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_tag', { name: z.string() }, async ({ name }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'tags'), { name }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_tag_and_add_to_story', { name: z.string(), story_id: z.string() }, async ({ name, story_id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'tags'), { name, story_id }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_tag', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `tags/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Tag ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_releases', { page: z.number().optional(), per_page: z.number().optional() }, async ({ page = 1, per_page = 25 }) => { try { const q = toQuery({ page, per_page }); const res = await axios.get(buildURL(MANAGEMENT_BASE, `releases${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_release', { name: z.string(), publish_at: z.string().optional(), branches_to_deploy: z.array(z.number()).optional(), timezone: z.string().optional(), users_to_notify_ids: z.array(z.number()).optional() }, async ({ name, publish_at, branches_to_deploy, timezone, users_to_notify_ids }) => { try { const body: any = { name }; if (publish_at) body.release_at = publish_at; // Changed to release_at as per API docs if (branches_to_deploy) body.branches_to_deploy = branches_to_deploy; if (timezone) body.timezone = timezone; if (users_to_notify_ids) body.users_to_notify_ids = users_to_notify_ids; const res = await axios.post(buildURL(MANAGEMENT_BASE, 'releases'), { release: body }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('add_story_to_release', { release_id: z.string(), story_id: z.string() }, async ({ release_id, story_id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `releases/${release_id}/stories`), { story_id }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('publish_release', { release_id: z.string() }, async ({ release_id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `releases/${release_id}/publish`), {}, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_release', { release_id: z.string(), name: z.string().optional(), release_at: z.string().optional(), branches_to_deploy: z.array(z.number()).optional(), timezone: z.string().optional(), users_to_notify_ids: z.array(z.number()).optional(), do_release: z.boolean().optional() }, async ({ release_id, name, release_at, branches_to_deploy, timezone, users_to_notify_ids, do_release }) => { try { const releaseData: any = {}; if (name) releaseData.name = name; if (release_at) releaseData.release_at = release_at; if (branches_to_deploy) releaseData.branches_to_deploy = branches_to_deploy; if (timezone) releaseData.timezone = timezone; if (users_to_notify_ids) releaseData.users_to_notify_ids = users_to_notify_ids; const requestData: any = { release: releaseData }; if (do_release !== undefined) requestData.do_release = do_release; const res = await axios.put( buildURL(MANAGEMENT_BASE, `releases/${release_id}`), requestData, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_release', { release_id: z.string() }, async ({ release_id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `releases/${release_id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Release ${release_id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_assets', { page: z.number().optional(), per_page: z.number().optional(), search: z.string().optional(), folder_id: z.number().optional() }, async ({ page = 1, per_page = 25, search, folder_id }) => { try { const q = toQuery({ page, per_page, search, folder_id }); const res = await axios.get(buildURL(MANAGEMENT_BASE, `assets${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_asset', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `assets/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_asset', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `assets/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Asset ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('init_asset_upload', { filename: z.string(), size: z.number(), content_type: z.string() }, async ({ filename, size, content_type }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'assets'), { filename, size, content_type }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('complete_asset_upload', { asset_id: z.string() }, async ({ asset_id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `assets/${asset_id}/finish_upload`), {}, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_asset_folders', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'asset_folders'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_asset_folder', { name: z.string(), parent_id: z.union([z.number(), z.string()]).optional() }, async ({ name, parent_id }) => { try { const folderData: any = { name }; if (parent_id !== undefined) folderData.parent_id = parent_id; const res = await axios.post(buildURL(MANAGEMENT_BASE, 'asset_folders'), { asset_folder: folderData }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_asset_folder', { id: z.string(), name: z.string() }, async ({ id, name }) => { try { const res = await axios.put(buildURL(MANAGEMENT_BASE, `asset_folders/${id}`), { asset_folder: { name } }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_asset_folder', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `asset_folders/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Asset folder ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_components', { component_summary: z.boolean().optional(), include_schema_details: z.boolean().optional(), filter_by_name: z.string().optional() }, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'components'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_component', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `components/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_component', { name: z.string(), display_name: z.string().optional(), schema: z.record(z.unknown()), is_root: z.boolean().optional(), is_nestable: z.boolean().optional() }, async ({ name, display_name, schema, is_root = false, is_nestable = true }) => { try { const componentData = { component: { name, display_name: display_name || name, schema, is_root, is_nestable } }; const res = await axios.post(buildURL(MANAGEMENT_BASE, 'components'), componentData, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_component', { id: z.string(), name: z.string().optional(), display_name: z.string().optional(), schema: z.record(z.unknown()).optional(), is_root: z.boolean().optional(), is_nestable: z.boolean().optional() }, async ({ id, name, display_name, schema, is_root, is_nestable }) => { try { const updateData: any = {}; if (name !== undefined) updateData.name = name; if (display_name !== undefined) updateData.display_name = display_name; if (schema !== undefined) updateData.schema = schema; if (is_root !== undefined) updateData.is_root = is_root; if (is_nestable !== undefined) updateData.is_nestable = is_nestable; const res = await axios.put(buildURL(MANAGEMENT_BASE, `components/${id}`), { component: updateData }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_component', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `components/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Component ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('search_stories', { starts_with: z.string().optional(), by_uuids: z.string().optional(), by_slugs: z.string().optional(), excluding_slugs: z.string().optional(), with_tag: z.string().optional(), is_startpage: z.boolean().optional(), sort_by: z.string().optional(), search_term: z.string().optional(), page: z.number().optional(), per_page: z.number().optional() }, async (params) => { try { const q = toQuery({ ...params, token: PUBLIC_TOKEN }); const res = await axios.get(`${CDN_BASE}/stories${q}`); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_story_by_slug', { slug: z.string() }, async ({ slug }) => { try { const q = toQuery({ token: PUBLIC_TOKEN }); const res = await axios.get(`${CDN_BASE}/stories/${slug}${q}`); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_folders', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'stories?is_folder=true'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_datasources', { page: z.number().optional(), per_page: z.number().optional() }, async ({ page = 1, per_page = 25 }) => { try { const q = toQuery({ page, per_page }); const res = await axios.get(buildURL(MANAGEMENT_BASE, `datasources${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_datasource', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `datasources/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_datasource', { name: z.string(), slug: z.string(), dimensions_attributes: z.array( z.object({ name: z.string(), entry_value: z.string() }) ).optional() }, async (params) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'datasources'), { datasource: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_datasource', { id: z.string(), name: z.string().optional(), slug: z.string().optional(), dimensions_attributes: z.array( z.object({ name: z.string(), entry_value: z.string() }) ).optional() }, async ({ id, ...params }) => { try { const res = await axios.put(buildURL(MANAGEMENT_BASE, `datasources/${id}`), { datasource: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_datasource', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `datasources/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Datasource ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_datasource_entries', { datasource_id: z.string(), page: z.number().optional(), per_page: z.number().optional() }, async ({ datasource_id, page = 1, per_page = 25 }) => { try { const q = toQuery({ page, per_page }); const res = await axios.get(buildURL(MANAGEMENT_BASE, `datasources/${datasource_id}/entries${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_datasource_entry', { entry_id: z.string() }, async ({ entry_id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `datasource_entries/${entry_id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_datasource_entry', { datasource_id: z.string(), name: z.string(), value: z.string(), dimension_values: z.record(z.string()).optional() }, async ({ datasource_id, name, value, dimension_values }) => { try { const entryData: any = { name, value, datasource_id }; if (dimension_values) entryData.dimension_values = dimension_values; const res = await axios.post(buildURL(MANAGEMENT_BASE, 'datasource_entries'), { datasource_entry: entryData }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_datasource_entry', { entry_id: z.string(), name: z.string().optional(), value: z.string().optional(), dimension_value: z.string().optional(), dimension_id: z.number().optional() }, async ({ entry_id, name, value, dimension_value, dimension_id }) => { try { const entryData: any = {}; if (name !== undefined) entryData.name = name; if (value !== undefined) entryData.value = value; if (dimension_value !== undefined) entryData.dimension_value = dimension_value; const payload: any = { datasource_entry: entryData }; if (dimension_id !== undefined) payload.dimension_id = dimension_id; const res = await axios.put(buildURL(MANAGEMENT_BASE, `datasource_entries/${entry_id}`), payload, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_datasource_entry', { entry_id: z.string() }, async ({ entry_id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `datasource_entries/${entry_id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Datasource entry ${entry_id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('generate_alt', { asset_id: z.string() }, async ({ asset_id }) => { try { const assetRes = await axios.get(buildURL(MANAGEMENT_BASE, `assets/${asset_id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); const asset = assetRes.data; if (!asset || !asset.filename) { return { isError: true, content: [{ type: 'text', text: 'Asset not found or missing filename.' }] }; } const imageRes = await axios.get(asset.filename, { responseType: 'arraybuffer' }); const imageBuffer = Buffer.from(imageRes.data); const { text: alt } = await generateText({ model: google('gemini-2.0-flash'), messages: [ { role: 'user', content: [ { type: 'text', text: 'Describe this image for visually impaired users. Be concise and accurate.' }, { type: 'image', image: imageBuffer, mimeType: imageRes.headers['content-type'] || 'image/jpeg' } ] } ] }); await axios.put(buildURL(MANAGEMENT_BASE, `assets/${asset_id}`), { meta_data: { alt } }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify({ asset: { id: asset_id, alt } }) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('generate_meta', { story_id: z.string() }, async ({ story_id }) => { try { const q = toQuery({ token: PUBLIC_TOKEN }); const storyRes = await axios.get(`${CDN_BASE}/stories/${story_id}${q}`); const story = storyRes.data.story; if (!story || !story.content) { return { isError: true, content: [{ type: 'text', text: 'Story not found.' }] }; } const text = JSON.stringify(story.content); const prompt = `Write an SEO title (max 60 chars) and meta description (max 155 chars) for this content.\nContent: ${text}\nReturn as JSON: {\"meta_title\": string, \"meta_description\": string}`; const { object } = await generateObject({ model: google('gemini-2.0-flash'), schema: z.object({ meta_title: z.string(), meta_description: z.string() }), prompt }); await axios.put(buildURL(MANAGEMENT_BASE, `stories/${story_id}`), { story: { content: { ...story.content, meta_title: object.meta_title, meta_description: object.meta_description } } }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify({ meta_title: object.meta_title, meta_description: object.meta_description }) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('auto_tag_story', { story_id: z.string() }, async ({ story_id }) => { try { const q = toQuery({ token: PUBLIC_TOKEN }); const storyRes = await axios.get(`${CDN_BASE}/stories/${story_id}${q}`); const story = storyRes.data.story; if (!story || !story.content) { return { isError: true, content: [{ type: 'text', text: 'Story not found.' }] }; } const text = JSON.stringify(story.content); const prompt = `List 8 keywords summarizing this article. Return as a JSON array of strings.`; const { object } = await generateObject({ model: google('gemini-2.0-flash'), schema: z.array(z.string()), prompt: `${prompt}\nContent: ${text}` }); const tags: string[] = object; const tagsRes = await axios.get(buildURL(MANAGEMENT_BASE, 'tags'), { headers: getHeaders(MANAGEMENT_TOKEN) }); const existingTags = (tagsRes.data?.tags || []).map((t: any) => t.name); for (const tag of tags) { if (!existingTags.includes(tag)) { await axios.post(buildURL(MANAGEMENT_BASE, 'tags'), { name: tag }, { headers: getHeaders(MANAGEMENT_TOKEN) }); } } await axios.put(buildURL(MANAGEMENT_BASE, `stories/${story_id}`), { story: { tag_list: tags } }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify({ tags }) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('translate_story', { story_id: z.string(), lang: z.string() }, async ({ story_id, lang }) => { try { const res = await axios.put( buildURL(MANAGEMENT_BASE, `stories/${story_id}/ai_translate`), { lang, code: lang, overwrite: false }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_access_tokens', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'api_keys'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_access_token', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `api_keys/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_access_token', { access: z.enum(['public', 'private']), name: z.string().optional(), min_cache: z.number().optional(), story_ids: z.array(z.number()).optional(), branch_id: z.number().optional() }, async (params) => { try { const api_key: any = { access: params.access }; if (params.name !== undefined) api_key.name = params.name; if (params.min_cache !== undefined) api_key.min_cache = params.min_cache; if (params.story_ids !== undefined) api_key.story_ids = params.story_ids; if (params.branch_id !== undefined) api_key.branch_id = params.branch_id; const res = await axios.post(buildURL(MANAGEMENT_BASE, 'api_keys'), { api_key }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_access_token', { id: z.string(), access: z.enum(['public', 'private']).optional(), name: z.string().optional(), min_cache: z.number().optional(), story_ids: z.array(z.number()).optional(), branch_id: z.number().optional() }, async ({ id, ...params }) => { try { const api_key: any = {}; if (params.access !== undefined) api_key.access = params.access; if (params.name !== undefined) api_key.name = params.name; if (params.min_cache !== undefined) api_key.min_cache = params.min_cache; if (params.story_ids !== undefined) api_key.story_ids = params.story_ids; if (params.branch_id !== undefined) api_key.branch_id = params.branch_id; const res = await axios.put(buildURL(MANAGEMENT_BASE, `api_keys/${id}`), { api_key }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_access_token', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `api_keys/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Access token ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_story_schedulings', { page: z.number().optional(), per_page: z.number().optional(), story_id: z.number().optional(), language: z.string().optional(), sort_by: z.string().optional() }, async (params) => { try { const q = toQuery(params); const res = await axios.get(buildURL(MANAGEMENT_BASE, `story_schedulings${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_story_scheduling', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `story_schedulings/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_story_scheduling', { story_id: z.number(), publish_at: z.string(), language: z.string().optional() }, async (params) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'story_schedulings'), { story_scheduling: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_story_scheduling', { id: z.string(), publish_at: z.string().optional(), language: z.string().optional() }, async ({ id, ...params }) => { try { const res = await axios.put(buildURL(MANAGEMENT_BASE, `story_schedulings/${id}`), { story_scheduling: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_story_scheduling', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `story_schedulings/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Story scheduling ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_presets', { page: z.number().optional(), per_page: z.number().optional() }, async ({ page = 1, per_page = 25 }) => { try { const q = toQuery({ page, per_page }); const res = await axios.get(buildURL(MANAGEMENT_BASE, `presets${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_preset', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `presets/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_preset', { name: z.string(), preset: z.record(z.unknown()), component_id: z.number(), image: z.string().optional(), color: z.string().optional(), icon: z.string().optional(), description: z.string().optional() }, async (params) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'presets'), { preset: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_preset', { id: z.string(), name: z.string().optional(), preset: z.record(z.unknown()).optional(), component_id: z.number().optional(), image: z.string().optional(), color: z.string().optional(), icon: z.string().optional(), description: z.string().optional() }, async ({ id, ...params }) => { try { const res = await axios.put(buildURL(MANAGEMENT_BASE, `presets/${id}`), { preset: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_preset', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `presets/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Preset ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_webhooks', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'webhook_endpoints'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_webhook', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `webhook_endpoints/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_webhook', { name: z.string(), endpoint: z.string(), actions: z.array(z.string()), secret: z.string().optional(), activated: z.boolean().optional() }, async (params) => { try { const res = await axios.post( buildURL(MANAGEMENT_BASE, 'webhook_endpoints'), { webhook_endpoint: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_webhook', { id: z.string(), name: z.string().optional(), endpoint: z.string().optional(), actions: z.array(z.string()).optional(), secret: z.string().optional(), activated: z.boolean().optional() }, async ({ id, ...params }) => { try { const res = await axios.put( buildURL(MANAGEMENT_BASE, `webhook_endpoints/${id}`), { webhook_endpoint: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_webhook', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `webhook_endpoints/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Webhook ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_component_folders', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'component_groups'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_component_folder', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `component_groups/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_component_folder', { name: z.string(), parent_id: z.union([z.string(), z.number()]).optional() }, async (params) => { try { const res = await axios.post( buildURL(MANAGEMENT_BASE, 'component_groups'), { component_group: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_component_folder', { id: z.string(), name: z.string(), parent_id: z.union([z.string(), z.number()]).optional() }, async ({ id, ...params }) => { try { const res = await axios.put( buildURL(MANAGEMENT_BASE, `component_groups/${id}`), { component_group: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_component_folder', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `component_groups/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Component folder ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_space', {}, async () => { try { const res = await axios.get(MANAGEMENT_BASE, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_spaces', { page: z.number().optional(), per_page: z.number().optional() }, async ({ page = 1, per_page = 25 }) => { try { const q = toQuery({ page, per_page }); const res = await axios.get(`${SPACES_BASE}${q}`, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_space', { name: z.string(), domain: z.string().optional(), owner_id: z.number().optional(), story_published_hook: z.string().optional(), environments: z.array(z.object({ name: z.string(), location: z.string() })).optional(), billing_address: z.object({ tax_number: z.string().optional(), order_number: z.string().optional(), company: z.string().optional(), email: z.string().optional(), name: z.string().optional(), address_city: z.string().optional(), address_country: z.string().optional(), address_iso_country: z.string().optional(), address_line1: z.string().optional(), address_zip: z.string().optional() }).optional(), options: z.object({ branch_deployed_hook: z.string().optional(), s3_bucket: z.string().optional(), aws_arn: z.string().optional(), backup_frequency: z.string().optional(), languages: z.array(z.object({ code: z.string(), name: z.string() })).optional(), }).optional() }, async (params) => { try { const res = await axios.post(SPACES_BASE, { space: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_space', { space_id: z.string(), name: z.string().optional(), domain: z.string().optional(), uniq_domain: z.string().optional(), owner_id: z.number().optional(), story_published_hook: z.string().optional(), environments: z.array(z.object({ name: z.string(), location: z.string() })).optional(), parent_id: z.number().optional(), searchblok_id: z.number().optional(), duplicatable: z.boolean().optional(), billing_address: z.object({ tax_number: z.string().optional(), order_number: z.string().optional(), company: z.string().optional(), email: z.string().optional(), name: z.string().optional(), address_city: z.string().optional(), address_country: z.string().optional(), address_iso_country: z.string().optional(), address_line1: z.string().optional(), address_zip: z.string().optional() }).optional(), routes: z.array(z.string()).optional(), default_root: z.string().optional(), has_pending_tasks: z.boolean().optional(), ai_translation_disabled: z.boolean().optional(), options: z.object({ branch_deployed_hook: z.string().optional(), s3_bucket: z.string().optional(), aws_arn: z.string().optional(), backup_frequency: z.string().optional(), languages: z.array(z.object({ code: z.string(), name: z.string() })).optional(), }).optional() }, async ({ space_id, ...params }) => { try { const res = await axios.put(buildURL(SPACES_BASE, space_id), { space: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_space', { space_id: z.string() }, async ({ space_id }) => { try { await axios.delete(buildURL(SPACES_BASE, space_id), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Space ${space_id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('duplicate_space', { space_id: z.string(), name: z.string(), duplicate_content: z.boolean().optional(), create_components: z.boolean().optional() }, async ({ space_id, name, duplicate_content = true, create_components = true }) => { try { const res = await axios.post(buildURL(SPACES_BASE, `${space_id}/duplicate`), { duplicate: { name, duplicate_content, create_components } }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('backup_space', { space_id: z.string(), }, async ({ space_id }) => { try { const res = await axios.post(buildURL(SPACES_BASE, `${space_id}/backup`), {}, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_space_roles', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'space_roles'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_space_role', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `space_roles/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_space_role', { role: z.string(), subtitle: z.string().optional(), permissions: z.array(z.string()).optional(), field_permissions: z.array(z.string()).optional(), readonly_field_permissions: z.array(z.string()).optional(), allowed_paths: z.array(z.number()).optional(), datasource_ids: z.array(z.number()).optional(), component_ids: z.array(z.number()).optional(), branch_ids: z.array(z.number()).optional(), allowed_languages: z.array(z.string()).optional(), asset_folder_ids: z.array(z.number()).optional() }, async (params) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'space_roles'), { space_role: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_space_role', { id: z.string(), role: z.string().optional(), subtitle: z.string().optional(), permissions: z.array(z.string()).optional(), field_permissions: z.array(z.string()).optional(), readonly_field_permissions: z.array(z.string()).optional(), allowed_paths: z.array(z.number()).optional(), datasource_ids: z.array(z.number()).optional(), component_ids: z.array(z.number()).optional(), branch_ids: z.array(z.number()).optional(), allowed_languages: z.array(z.string()).optional(), asset_folder_ids: z.array(z.number()).optional() }, async ({ id, ...params }) => { try { const res = await axios.put(buildURL(MANAGEMENT_BASE, `space_roles/${id}`), { space_role: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_space_role', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `space_roles/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Space role ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_workflows', { page: z.number().optional(), per_page: z.number().optional() }, async (params) => { try { const q = toQuery(params); const res = await axios.get(buildURL(MANAGEMENT_BASE, `workflows${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_workflow', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `workflows/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_workflow', { name: z.string(), content_types: z.array(z.string()) }, async (params) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, 'workflows'), { workflow: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_workflow', { id: z.string(), name: z.string().optional(), content_types: z.array(z.string()).optional() }, async ({ id, ...params }) => { try { const res = await axios.put(buildURL(MANAGEMENT_BASE, `workflows/${id}`), { workflow: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('duplicate_workflow', { id: z.string(), name: z.string(), content_types: z.array(z.string()) }, async ({ id, ...params }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `workflows/${id}/duplicate`), { workflow: params }, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_workflow', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `workflows/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Workflow ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_workflow_stages', {}, async () => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, 'workflow_stages'), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_workflow_stage', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `workflow_stages/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_workflow_stage', { name: z.string(), color: z.string().optional(), position: z.number().optional(), is_default: z.boolean().optional(), allow_publish: z.boolean().optional(), allow_all_users: z.boolean().optional(), allow_all_stages: z.boolean().optional(), allow_admin_publish: z.boolean().optional(), allow_admin_change: z.boolean().optional(), allow_editor_change: z.boolean().optional(), user_ids: z.array(z.number()).optional(), space_role_ids: z.array(z.number()).optional(), workflow_stage_ids: z.array(z.number()).optional(), after_publish_id: z.number().optional(), workflow_id: z.number().optional() }, async (params) => { try { const res = await axios.post( buildURL(MANAGEMENT_BASE, 'workflow_stages'), { workflow_stage: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_workflow_stage', { id: z.string(), name: z.string().optional(), color: z.string().optional(), position: z.number().optional(), is_default: z.boolean().optional(), allow_publish: z.boolean().optional(), allow_all_users: z.boolean().optional(), allow_all_stages: z.boolean().optional(), allow_admin_publish: z.boolean().optional(), allow_admin_change: z.boolean().optional(), allow_editor_change: z.boolean().optional(), user_ids: z.array(z.number()).optional(), space_role_ids: z.array(z.number()).optional(), workflow_stage_ids: z.array(z.number()).optional(), after_publish_id: z.number().optional(), workflow_id: z.number().optional() }, async ({ id, ...params }) => { try { const res = await axios.put( buildURL(MANAGEMENT_BASE, `workflow_stages/${id}`), { workflow_stage: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_workflow_stage', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `workflow_stages/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Workflow stage ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_workflow_stage_changes', { with_story: z.string().optional() }, async ({ with_story }) => { try { const q = with_story ? `?with_story=${with_story}` : ''; const res = await axios.get(buildURL(MANAGEMENT_BASE, `workflow_stage_changes${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_workflow_stage_change', { workflow_stage_id: z.number(), story_id: z.number() }, async ({ workflow_stage_id, story_id }) => { try { const res = await axios.post( buildURL(MANAGEMENT_BASE, 'workflow_stage_changes'), { workflow_stage_change: { workflow_stage_id, story_id } }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_workflow_stage_change', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `workflow_stage_changes/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_branches', { page: z.number().optional(), per_page: z.number().optional() }, async (params) => { try { const q = toQuery(params); const res = await axios.get(buildURL(MANAGEMENT_BASE, `branches${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_branch', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `branches/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_branch', { name: z.string(), source_id: z.number().nullable().optional(), url: z.string().optional(), position: z.number().optional() }, async (params) => { try { const res = await axios.post( buildURL(MANAGEMENT_BASE, 'branches'), { branch: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('update_branch', { id: z.string(), name: z.string().optional(), source_id: z.number().nullable().optional(), url: z.string().optional(), position: z.number().optional() }, async ({ id, ...params }) => { try { const res = await axios.put( buildURL(MANAGEMENT_BASE, `branches/${id}`), { branch: params }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('delete_branch', { id: z.string() }, async ({ id }) => { try { await axios.delete(buildURL(MANAGEMENT_BASE, `branches/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: `Branch ${id} has been successfully deleted.` }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('deploy_branch', { id: z.string() }, async ({ id }) => { try { const res = await axios.post(buildURL(MANAGEMENT_BASE, `branches/${id}/deploy`), {}, { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_branch_stories', { id: z.string(), page: z.number().optional(), per_page: z.number().optional(), sort_by: z.string().optional() }, async ({ id, ...params }) => { try { const q = toQuery(params); const res = await axios.get(buildURL(MANAGEMENT_BASE, `branches/${id}/stories${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('compare_branches', { source_id: z.string(), target_id: z.string(), page: z.number().optional(), per_page: z.number().optional() }, async ({ source_id, target_id, ...params }) => { try { const q = toQuery({ ...params, source: source_id, target: target_id }); const res = await axios.get(buildURL(MANAGEMENT_BASE, `branches/compare${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('copy_stories_between_branches', { source_branch_id: z.string(), target_branch_id: z.string(), story_ids: z.array(z.number()) }, async ({ source_branch_id, target_branch_id, story_ids }) => { try { const res = await axios.post( buildURL(MANAGEMENT_BASE, `branches/${target_branch_id}/stories/copy`), { source_branch_id, story_ids }, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('fetch_branch_deployments', { page: z.number().optional(), per_page: z.number().optional() }, async ({ page = 1, per_page = 25 }) => { try { const q = toQuery({ page, per_page }); const res = await axios.get(buildURL(MANAGEMENT_BASE, `deployments${q}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('create_branch_deployment', { branch_id: z.number(), release_uuids: z.array(z.string()).optional() }, async ({ branch_id, release_uuids }) => { try { const payload: any = { branch_id }; if (release_uuids && release_uuids.length > 0) { payload.release_uuids = release_uuids; } const res = await axios.post( buildURL(MANAGEMENT_BASE, 'deployments'), payload, { headers: getHeaders(MANAGEMENT_TOKEN) } ); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); server.tool('get_branch_deployment', { id: z.string() }, async ({ id }) => { try { const res = await axios.get(buildURL(MANAGEMENT_BASE, `deployments/${id}`), { headers: getHeaders(MANAGEMENT_TOKEN) }); return { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] }; } catch (error: any) { return { isError: true, content: [{ type: 'text', text: `Error: ${error.message}` }] }; } }); }

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/ArjunCodess/storyblok-mcp'

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