MCP server for Steam game library management, user data persistence, and game recommendations. Provides read-only library queries and write tools for user preferences, completion tracking, and memories.
Shelfbound demonstrates strong naming conventions (verb_noun pattern: get_, search_, record_, remember, delete_), comprehensive parameter descriptions, and well-documented output schemas. Tool descriptions are detailed and context-aware (e.g., get_library_summary explains 'scope' semantics; search_library clarifies what absence of results means). However, input schemas lack formal enum constraints for constrained parameters (status, rating, sort values are documented in text but not as JSON Schema enums), and error handling guidance is minimal. No tool annotations (readOnlyHint/destructiveHint) are visible in the code, despite clear risk classifications. Output schemas are inferred from return types rather than explicitly documented in descriptions.
Delete a stored memory by its id (ids come from get_remembered / get_game_user_data). Use when the user asks to forget something or corrects a saved fact.
Installed games the user likely hasn't started: never last-played, zero/unknown playtime, and not already marked finished/dropped/ignored/played-elsewhere. Good for 'what should I play next?'.
List the user's local Steam categories (collections) with how many games each contains. These are the user's OWN labels (e.g. 'Deck', 'Hold'); if a meaning is unclear, ask the user rather than guessing.
Get one observed game plus saved data and game-scoped memories by Steam app id or name. Returns null if not found; under 'installedOnly' or 'observedSubset' scope (see get_library_summary), null proves neither non-ownership nor lack of access.
Everything Shelfbound remembers about one game: status, rating, completion, aspects, and game-scoped memories.
Constrained parameters lack JSON Schema enum declarations. Status, rating, sort, and scope values are documented in text descriptions but not formalized as enums in input schemas. LLMs cannot parse text constraints reliably and may hallucinate invalid values.
No tool annotations visible in source code. Tools are classified by risk (READ_ONLY, WRITE, DESTRUCTIVE) in metadata but not exposed as MCP tool annotations (readOnlyHint, destructiveHint, idempotentHint). Agents cannot infer safety properties from tool definitions alone.
Output schemas not explicitly documented in tool descriptions. Return types are inferred from C# method signatures but not described in the tool description text. LLMs cannot plan downstream tool calls without knowing what fields to expect.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | 2026-07-28+ | v2 |
High-level overview of observed library facts: total/installed/categorized game counts, total size, total playtime (if available), libraries, and categories. Includes 'scope': 'installedOnly' is local installed presence; 'observedSubset' adds positive visibility-gated observations but absence still proves nothing; only 'fullLibrary' has an explicit completeness contract.
Check how set-up the user's taste profile is and what to ask about. If the profile is sparse (isSetUp=false, or few rated games / preferences), STRONGLY consider onboarding the user before recommending: ask about a few of the suggestedGamesToRate and their general preferences, then save with record_game_opinion / remember. Ask what any undefinedCategories mean and save with set_category_definition. Call this before giving recommendations.
Themed 'what should I play (or uninstall) next?' cards over the user's library, each with reasons: installed-but-unplayed (framed as 'play next on your Steam Deck' when the device is a Deck), paused games worth returning to, recently added but untouched, and games to uninstall to free space. Device-aware: only suggests Deck-specific play when the device actually is a Deck.
What Shelfbound remembers about the user: global preferences, category meanings, and memories (optionally filtered by scope). Recall this before recommending or comparing games.
Record the user's opinion of a game: a rating and/or liked/disliked aspects (e.g. 'dark themes'). Only on explicit statements; pass the user's own words as evidence.
Record where a game stands for the user. Only when the user explicitly says so (e.g. 'I finished it', 'mark this paused').
Save a durable fact the user explicitly stated (a preference, a note, a meaning). scope = global (taste), game (give appIdSubject), or category (give categorySubject). Pass the user's own words as evidence. Do NOT save guesses or inferences — only explicit statements or things the user asked you to remember.
Search/filter observed library facts AND the user's saved data. All parameters are optional and combine with AND. Returns games with categories, install state, size, playtime, and saved status/rating/completion/memories. If scope is 'installedOnly' or 'observedSubset' (see get_library_summary), no result does NOT mean the user does not own or have access to the game.
Record what one of the user's category/collection names means to them (e.g. 'Hold' = 'started but paused, want to return'). Only from explicit user statements.
Set how far the user has completed a game (0-100), and optionally whether they played/finished it on another platform.
Error handling and recovery guidance absent. No tool description explains what to do if a lookup fails, if scope limitations prevent finding a game, or how to handle partial results. Agents lack actionable next steps on failure.
Destructive operations (delete_memory) lack confirmation or dry-run support. No mention of undo capability or confirmation step before permanent deletion. Agents can accidentally erase user data without safeguards.