Static source inference · medium confidence · evidence: structured output
No deprecated protocol patterns detected
Summary
The server provides 11 tools with consistent naming patterns (verb-first convention: get*, create*, update*, delete*, list*), but quality suffers from thin descriptions and incomplete output schema documentation. All tools have input schemas with typed parameters and descriptions, which is a positive baseline. However, descriptions are uniformly brief (15-30 chars typical), falling below the 50-200 char ideal for LLM reasoning. Output schemas are not documented anywhere in the source code, the API client returns responses, but the MCP tool definitions do not declare what fields agents should expect. Parameter descriptions are minimal ('Asset ID', 'Story name') without usage guidance or constraints. No pagination guidance is documented despite tools like listStories and getAssets accepting per_page/page parameters. Error handling is present in the API client but not surfaced to the MCP layer with recovery guidance.
Descriptions are critically brief (15-30 chars) vs. 50-200 char ideal. Examples: 'Get all assets from Storyblok', 'Get an asset from Storyblok', 'Create a new story in Storyblok'. These lack WHEN to use, prerequisites, or return value context.
Output schemas are not documented in the MCP tool registration. The API client returns responses (AssetResponse, StoryResponse types exist in types/storyblok.ts but are not visible in the provided code), but tools do not declare what fields agents should expect in the response. This prevents LLMs from planning downstream tool calls and forces them to guess at response structure.
Expand all tool descriptions to 80-150 chars minimum. Follow the pattern: 'What it does' + 'When to use it' + 'What it returns.' Example: 'Retrieve all assets in the space with pagination. Use this to discover available images/files before referencing them in stories. Returns an array of asset objects with id, name, filename, and url fields. Pagination supports up to 100 results per page.'
Document output schemas explicitly in each tool's registration. Add a 'returns' field or update description to include: 'Returns an array of {id: number, name: string, filename: string, url: string}' for getAssets. This prevents LLM guessing.
Add pagination guidance to listStories and getAssets: 'Use per_page (1-100, default 25) and page (starting at 1) for pagination. Include total_count in response for range awareness.' If Storyblok API doesn't support total_count, document what it returns instead.
Mark destructive tools (deleteAsset, deleteStory) with an explicit warning in the description: 'WARNING: This operation is irreversible. The asset/story will be permanently deleted.' Consider adding a require_confirmation pattern or dry_run boolean parameter.
Expand parameter descriptions to include format, constraints, and examples. Example for filter_query: 'Optional. Storyblok query string (e.g., 'slug=my-story' or 'is_published=true'). See Storyblok docs for syntax.' Example for content object: 'JSON object defining story content blocks. See getComponents first to learn available component types and their required fields.'
Pagination parameters (per_page, page) in getAssets and listStories lack guidance on limits, default values, and whether pagination is required. No documentation of total count or next_cursor support. agents may not know they need pagination or what max values are acceptable.
Destructive operations (deleteAsset, deleteStory) have no confirmation step, dry-run option, or explicit 'This operation is irreversible' warning in the description. LLMs should be warned of consequences before calling destructive tools.
Parameter descriptions are minimal and do not include format, range, or constraints. Examples: 'Asset ID', 'Story name', 'Filter query'. These do not explain valid formats (is filter_query a JSON string? URL-encoded? Free text?), ranges, or how to construct them.
Error responses in the API client (StoryblokError class in storyblok-api.ts) include status codes and details, but no recovery guidance. When an error occurs, the LLM receives no hint about what to do next (retry, ask user, use alternative tool, etc.). Error categorization (retryable vs fatal) is absent.
uploadAsset requires a public URL (fileUrl parameter), but the description does not mention URL format requirements, timeouts, file size limits, or supported MIME types. LLMs may pass invalid URLs without guidance.
createStory and updateStory accept a 'content' parameter as type 'object' with no schema or documentation of required/optional fields, structure, or component references. LLMs have no way to construct valid content payloads without trial and error.
Tool chaining is broken in several places: getStory and createStory return story data, but the next likely action (e.g., update the story, add content) requires a storyId. No documentation clarifies if the returned story object includes storyId or if a separate lookup is needed.
getStorycreateStory
Add error recovery guidance to API error handling. Catch StoryblokError and return messages like: 'Asset not found (ID: 123). Try listAssets() to find the correct ID.' or 'Unauthorized. Verify your SPACE_ID and ACCESS_TOKEN are correct.'
For uploadAsset, specify URL constraints: 'fileUrl must be a publicly accessible HTTP(S) URL pointing to an image or media file. Supported formats: JPEG, PNG, GIF, PDF, video files. Timeout: 30 seconds. Max file size: 100 MB (per Storyblok limits).'
Document the content object schema for createStory and updateStory. Either provide an enum of valid component types with required fields, or link to Storyblok component documentation. Example: 'content is a Blok array. Each Blok must have a _uid (string) and component (name matching one from getComponents). Additional fields depend on component schema.'
Add tool-chaining hints in descriptions. For createStory, append: 'The returned object includes storyId, name, slug, and status. Use storyId in updateStory, deleteStory, or getStory for subsequent operations.' This guides multi-step agent plans.
Validate required parameters and invalid values early, returning clear error messages. Example: 'storyId must be a number, got: "abc"' instead of a generic API error. Example: 'assetId 12345 not found. Available IDs range from 1 to 15670. Try listAssets() to search by name.'
Consider splitting finishUpload into the upload flow or combining uploadAsset + finishUpload into a single create_asset_from_url tool if finishUpload is always called after uploadAsset. The two-step flow is awkward for LLMs.
Add idempotency guidance. State which operations are safe to retry (GET operations always; POST/PUT operations depend on idempotency tokens). Example: 'If the network fails after calling createStory, you can safely retry with the same name and slug, it will return the existing story, not create a duplicate.'