MCP server bridge for Slay the Spire 2. Connects to the STS2_MCP mod's HTTP server and exposes game actions as MCP tools for Claude Desktop / Claude Code.
The server exposes 40 tools for Slay the Spire 2 game automation. Tool naming follows verb_noun patterns well (get_game_state, play_card, end_turn). Descriptions are present for all 40 tools and range from 50-400+ characters, with most falling in the 100-250 range, adequate but not optimized for LLM selection. Input schemas are consistently defined with JSON Schema types and descriptions for all parameters. However, there are significant gaps: (1) Output schemas are not documented, responses are opaque JSON/markdown strings with no structured field definitions, (2) Error handling lacks recovery guidance, tools return raw HTTP errors or generic messages without actionable next steps, (3) No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk levels in the provided data, (4) Parameters lack enums for constrained values (e.g., format in get_game_state accepts only 'markdown' or 'json' but is a free string), (5) Some descriptions are verbose and include implementation details rather than focusing on LLM selection criteria. Composition is reasonable, tools are mostly single-responsibility, though some game-state query tools (get_game_state, get_profile, get_compendium) overlap slightly in scope. The server handles async HTTP communication cleanly via httpx with proper error classification (ConnectError vs HTTPStatusError), but error messages lack guidance for recovery (e.g., 'Cannot connect' does not suggest waiting for mod startup or checking port).
Advance a dialogue or event text (for events with multi-step narration).
Place a bid on a treasure relic in multiplayer treasure rooms.
Cancel a bundle selection.
Cancel a card selection.
Choose an option during an event. Only valid when the game state contains an "event" section.
Choose a node on the map to travel to. Only valid on the map screen.
Choose an option at a rest site (upgrade, rest, smith, etc.).
Claim a reward after combat.
Output schemas are entirely undocumented. Tools return opaque text (markdown or JSON strings) with no structured field definitions, forcing LLMs to parse freeform output and hindering downstream tool composition and data extraction.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are completely absent despite clear risk levels in the metadata (DELETE_PROFILE is DESTRUCTIVE, play_card is WRITE, get_game_state is READ_ONLY). LLMs cannot infer safe retry boundaries or understand side effect scope.
Constrained parameters lack enum declarations. 'format' in get_game_state accepts only 'markdown' or 'json' but is defined as a free string; 'item_type' in search_wiki should be an enum ('all', 'card', 'relic') but is not. LLMs will hallucinate invalid values.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | 2026-07-28+ | v2 |
Claim a treasure relic from a treasure room.
Confirm a combat card selection.
Select a card for deck building or similar combat card selection screens.
Confirm a bundle selection.
Confirm a card selection.
Click a cell in the Crystal Sphere event grid.
Proceed from the Crystal Sphere event.
Set the active tool in the Crystal Sphere event.
Delete an inactive profile slot. The active profile cannot be deleted through this tool. Switch away first if you intend to remove a slot after backing up any data you need.
Discard a potion from your potion slots.
End your turn in combat. Only valid during the play phase (your turn).
End your turn in multiplayer combat. Signals that you are ready for the next round.
Get the active profile's Compendium-shaped progress summary. Mirrors the visible Compendium cards: Card Library, Relic Collection, Potion Lab, Bestiary, Character Stats, and Run History. This is a profile-level view, so it is useful at the main menu as well as during a run. Card/relic/potion rules text is still supplied by game state when those objects are visible in run-specific contexts.
Get the current Slay the Spire 2 game state. Returns the full game state including player stats, hand, enemies, potions, etc. The state_type field indicates the current screen (combat, map, event, shop, fake_merchant, etc.).
Get the current profile's persistent progress summary. Includes character stats, discovered content, achievements, epochs, and global run totals for the active profile.
List the three profile slots and identify the active slot. The has_data field indicates whether a slot currently has progress data.
Select a visible menu option. Use with state_type "menu" or "game_over". Covers main-menu navigation, singleplayer / multiplayer submenus, multiplayer host & join lobbies, multiplayer load lobby (resume saved co-op run), character select for SP and MP (with `unready` once readied in MP), profile switching, timeline controls, tutorial prompts, blocking popups, and game-over main-menu return. Multiplayer flow tips: - On menu_screen "multiplayer_join", use refresh / back / join_<index> / join_<player_id> (e.g. "join_0" or "join_76561198000000000"). - On menu_screen "multiplayer_load_lobby", use confirm (or embark) to ready up; the run resumes once everyone is connected and ready. - On menu_screen "character_select" while in MP, the state includes a `lobby` block with the roster, ready states, and ascension; "unready" becomes available after you confirm/embark.
Play a card from your hand in combat. Target resolution: - If the card is self-targeted or not targeted, 'target' is ignored. - If the card requires a single target (e.g., Strike to a chosen enemy), pass 'target' with the entity_id of that enemy. - If the card is AoE (affects all enemies), 'target' is ignored.
Proceed through blocking screens (combats, rewards, etc.).
Search discovered card and relic wiki entries for the active profile. Uses fuzzy matching over profile-unlocked content only, so agents can ask for a card or relic by approximate name without receiving the entire game catalog. Card results include both base and upgraded variants when the card can be upgraded.
Select a bundle during bundle selection screens.
Select a card during card selection screens (e.g., deck building, card rewards).
Select a card from a card reward screen.
Select a relic from a relic reward screen.
Purchase an item from a shop.
Skip a card reward (when available).
Skip a relic selection (when available).
Switch to a profile slot through the game's profile UI. Use an empty slot to create or enter a fresh profile for testing. This cannot be used while a run is in progress.
Undo an end turn submission in multiplayer combat to continue playing cards.
Use a potion from your potion slots.
Vote for an event option in multiplayer (when event voting is active).
Vote for a map node in multiplayer (when map voting is active).
Error handling provides no recovery guidance. _handle_error() returns raw messages like 'Error: Cannot connect to STS2_MCP mod...' without suggesting next steps (wait for startup, check port, retry). LLMs cannot self-correct from failures.
Short, uninformative descriptions on action tools. end_turn, use_potion, discard_potion, claim_reward, skip_card_reward, proceed have descriptions under 50 characters with minimal context for LLM selection. At 40 chars, 'proceed through blocking screens' does not explain when to use it vs claim_reward.
No pagination or result limits documented for discovery tools. search_wiki defaults limit=10 and clamps it 'to a bounded maximum', but the maximum is not specified. get_profile, get_compendium, list_profiles return unbounded responses with no field to indicate truncation or next_cursor.
Overlapping tool semantics. get_game_state returns 'the full game state'; get_profile and get_compendium also return persistent data. The distinction in use cases is not clearly documented. LLMs may choose the wrong tool.
Parameter descriptions lack format and range specifications. 'option' in menu_select is described as 'Option ID from the current menu state's options list' but does not clarify format (alphanumeric string, integer, UUID, enum). 'seed' in menu_select says 'Standard mode rejects seeds' but does not specify valid seed format.