MCP server providing access to Jellyfin media server and JellyStats activity/statistics data, enabling tools for browsing, searching, and analyzing media content and user activity
The server defines 16 tools with consistent verb-noun naming (get_*, search_*) and reasonable descriptions. However, all tools lack documented output schemas, the codebase shows tools return serde_json::Value or typed structs, but the MCP tool registration does not expose response schemas. Parameter descriptions are present but minimal (10-50 chars), below the 72-char baseline for production quality. All tools are read-only, limiting the severity of missing error handling for state changes. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are declared despite the risk profile being well-understood. The schema definitions are present for inputs but lack detail (no min/max constraints on numeric params, no enums for multi-choice fields like item_type). Composite tools like search_items accept item_type as a free string rather than an enum, inviting hallucinated invalid values.
Get all user activity from JellyStats including watch history, total plays, and last seen information
Get the episodes for a specific item from JellyStats. This includes all episodes related to the item.
Get all available genres from Jellyfin.
Get the play activity for a specific item from JellyStats. Allowing to know whether the user has played the item already or not.
Get items by a specific genre from Jellyfin. This includes items related to the specified genre.
Get items by a specific person from Jellyfin. This includes items related to the specified person.
Missing output schemas for all 16 tools. MCP registration shows input schemas but no documented response structure. LLMs cannot plan downstream operations or extract fields without knowing what the response contains.
item_type parameter in get_items_by_person, get_items_by_genre, and search_items is a free-form string. The Jellyfin implementation references ItemType enum (src/jellyfin/model.rs line shows 'pub enum ItemType' and 'item_type.as_str()'), but MCP schema exposes it as unconstrained string, inviting hallucinated values like 'MovieX' or 'Episodee'.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 50 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 44 | - | v1 |
Get the details for a specific item from Jellyfin. This includes detailed information about the item.
Get the details for a specific item from JellyStats. This includes detailed information about the item.
Get the recently added items from JellyStats. This includes the latest items added to the library.
Get similar items for a specific item from Jellyfin. This includes items similar to the specified item.
Get suggestions from Jellyfin. This includes suggested items based on the specified criteria.
Get the details for a specific user from JellyStats. This includes detailed information about the user.
Get the history of a specific user from JellyStats. This includes watch history, total plays, and last seen information.
Get the last played content for a specific user from JellyStats
Get all users from Jellyfin. This is used to match user_id and user name.
Search for items in Jellyfin. This includes items that match the specified search term and item type.
Pagination parameters (page, limit) lack constraints. No min/max specified. An LLM could pass limit=999999 or page=-1, causing backend errors. Rubric baseline: numeric params should declare 1 - 100 range or similar.
Parameter descriptions are consistently 10 - 65 characters, well below the rubric baseline of ~72 chars. E.g., get_item_activity's 'page' param describes as 'Optional page number for pagination (defaults to 1)', helpful, but does not state valid range or clarify pagination semantics (offset vs cursor).
Tool names 'get_jellystats_item_details' and 'get_jellyfin_item_details' both fetch item details from different backends. Names do not make the distinction obvious. An LLM could conflate them or choose wrong one, leading to missing data. E.g., 'get_item_details_from_jellystats' and 'get_item_details_from_jellyfin' would be clearer.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) declared in MCP schema. Although all tools are read-only (Risk: READ_ONLY in metadata), omitting the annotation means agents cannot reason about safety without parsing descriptions. Annotation format is optional but recommended for A-grade servers.
No error handling guidance in tool descriptions. If a user_id or item_id does not exist, tools will return empty results or HTTP errors. Descriptions do not explain what to do next (e.g., 'Call get_users() first to find a valid user_id'). Pattern: recovery-guide.