NaviGravity presents a moderately well-structured MCP server for Navidrome music curation with 17 tools. Strengths: all tools have descriptions (most 50-150 chars), most input parameters are typed and include descriptions, and tool names follow verb_noun conventions appropriately. Schema definitions are visible for all tools and include enums, minimums, maximums where applicable. Weaknesses: output schemas are not documented anywhere in the source, LLMs cannot predict what fields each tool returns, forcing them to guess downstream field names and types for chaining. Error handling is absent, no indication of how failures are communicated, what's retryable, or how to recover. Parameter descriptions lack constraint details (e.g., 'limit' fields say 'default 20, max 500' but no explanation of why or consequences). No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear READ_ONLY vs WRITE distinctions. Some tools accept ambiguous or overloaded parameters (e.g., 'playlist_id' and 'playlist_name' in get_playlist should clarify precedence). Logging infrastructure is present and JSON-formatted, but no audit trail tie-back to tool invocations per the pattern:audit-trail baseline.
Add songs to a playlist by ID.
Analyze a playlist and return quality metrics (diversity, repetition, coverage).
Verify connection to Navidrome and retrieve server info.
Create a new playlist with an optional set of song IDs.
Get detailed info and all songs for an album.
Get detailed info and top songs for an artist.
Retrieve all songs from a playlist by ID or name.
No output schemas documented. Tools return JSON but LLMs cannot predict field names, types, or nesting. Forces guessing on downstream field references (e.g., does get_song_details return 'song_id' or 'id'? 'play_count' or 'playCount'?). This violates the pattern:response-shaper requirement and causes downstream tool chaining failures.
No error handling documented. Tools fail silently or with bare exceptions. No guidance on retryability, user-fixable vs fatal errors, or recovery steps. Violates pattern:recovery-guide and pattern:error-classification.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 51 | <=2025-11-25 | v2 |
Return a list of songs selected by smart criteria (mode + optional filters).
Get detailed metadata for a song by ID.
List all albums in the library.
List all artists in the library.
List all playlists.
Rate a song (1-5 stars) by ID.
Scrobble (log play) of a song.
Search for songs by title, artist, album, or any text.
Star (favorite) a song by ID.
Unstar a song by ID.
No tool annotations despite clear semantic distinctions. All WRITE tools (star_song, rate_song, create_playlist, etc.) lack destructiveHint=true. All READ_ONLY tools lack readOnlyHint=true. Prevents MCP clients from surfacing safety warnings and idempotence metadata.
get_playlist accepts both 'playlist_id' and 'playlist_name', parameter precedence is undocumented. Description should explicitly state 'If both provided, playlist_id takes precedence.' Violates pattern:constrained-input.
Parameter descriptions lack actionable constraints. E.g., 'limit' parameters say 'max 500' but do not explain: why 500? What happens if you exceed it? Are results paginated? What's the recommended limit? Violates pattern:tool-description baseline of 50-200 char descriptions with clear WHAT/WHEN/HOW guidance.
No audit trail integration. Logging logs tool execution but does not tie it back to a user/agent identity, request ID, or permission scope. Violates pattern:audit-trail requirement.
Credentials (NAVIDROME_URL, NAVIDROME_USER, NAVIDROME_PASS) are injected via .env file, which is correct (pattern:secret-injection), but the source code loads them at module level without explicit validation. If .env is missing, a ValueError is raised but does not indicate which specific env var is missing. Error message should list all required vars: 'Missing NAVIDROME_URL, NAVIDROME_USER, and/or NAVIDROME_PASS.'