kanka-mcp has clear verb-based naming (show_, list_, get_, create_, update_, delete_) and complete input schemas with types. However, descriptions are inconsistent in depth. Tool descriptions range from minimal (e.g., 'List all characters in a campaign') to verbose (create_character with 15-line field documentation). Parameter descriptions are present but generic, many lack format constraints, ranges, or examples of valid values. No output schema documentation. Error handling is absent: tools call raise_for_status() but provide no recovery guidance. No pagination support despite list_* tools. Security: API key is injected via environment variable (correct), but no permission checks or audit logging. Composition is reasonable, tools are single-purpose, but list_characters and list_locations lack limit/offset parameters, risking context window overflow.
Create a new character in a campaign. Fields: campaign_id: The ID of the campaign to add the character to name: The name of the character (required) title: The character's title (optional) type: The type or class of the character (optional) age: The age of the character (optional) sex: The sex/gender of the character (optional) pronouns: The pronouns of the character (optional) race_id: The ID of the race entity (optional) family_id: The ID of the family entity (optional) is_dead: Whether the character is dead (optional) image: URL or path to the character's image (optional) tags: Comma-separated list of tags (optional) entry: The character's entry/description (optional, must be HTML. If not HTML, it will be wrapped in <p> tags.) is_private: If the character is only visible to admin members (optional)
Create a new location in a campaign. Fields: campaign_id: The ID of the campaign to add the location to name: The name of the location (required) entry: The location's entry/description (optional, must be HTML. If not HTML, it will be wrapped in <p> tags.) type: Type of location (optional) location_id: The parent location id (optional) tags: Array of tag ids (optional) is_destroyed: If the location is destroyed (optional) is_private: If the location is only visible to admin members (optional)
Delete a character by ID.
Get a single character by ID.
No output schema documentation. LLMs cannot predict response structure, forcing them to guess which fields are available for downstream tool calls. create_character and update_character return response.json() but no schema is documented.
List tools (list_characters, list_locations) lack pagination (limit, offset, page_size). No result count returned. Large campaigns risk context window overflow and LLM reasoning degradation.
Error handling is minimal. Tools call raise_for_status() but provide no recovery guidance. LLMs receive raw HTTP errors with no actionable next steps (e.g., 'User not found. Try search_users() first.').
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 56 | 2026-07-28+ | v2 |
Get a single location by ID.
List all characters in a campaign.
List all locations in a campaign.
List all campaigns the user has access to. You may need to run this tool before running other tools to get the campaign ID.
Update an existing character. Fields: campaign_id: The ID of the campaign character_id: The ID of the character to update name: The name of the character (optional) title: The character's title (optional) type: The type or class of the character (optional) age: The age of the character (optional) sex: The sex/gender of the character (optional) pronouns: The pronouns of the character (optional) race_id: The ID of the race entity (optional) family_id: The ID of the family entity (optional) is_dead: Whether the character is dead (optional) image: URL or path to the character's image (optional) tags: Comma-separated list of tags (optional) entry: The character's entry/description (optional, must be HTML. If not HTML, it will be wrapped in <p> tags.) is_private: If the character is only visible to admin members (optional)
Destructive tool (delete_character) has minimal description ('Delete a character by ID.') and no confirmation/dry-run pattern. Agents can accidentally delete without safeguards.
Parameter descriptions lack format constraints and ranges. E.g., 'age' is a string with no guidance on valid formats (numeric, text, range). 'tags' in create_location is an array but no schema for array items. LLMs cannot validate input.