MCP Servers

A collection of Model Context Protocol servers, templates, tools and more.

S
Sts2 Compact MCP

Token-efficient MCP proxy for Slay the Spire 2 via Gennadiyev/STS2MCP

Created 6/8/2026
Updated about 4 hours ago
Repository documentation and setup instructions

STS2 Compact MCP

简体中文 | Copy-paste AI installation prompt

A token-efficient MCP proxy for Gennadiyev/STS2MCP.

It leaves the game mod and its REST API unchanged. Instead of exposing 64 verbose MCP tools, this proxy exposes three:

  • observe: compact, delta, or full game state
  • act: every game action through one stable interface
  • inspect: full map, wiki, profile, and other details on demand

Project scope

This repository contains only the external Python MCP proxy. Development and issue reports should be directed according to the component involved:

| Component | Repository | What it owns | | --- | --- | --- | | Game mod and REST API | Gennadiyev/STS2MCP | STS2_MCP.dll, STS2_MCP.json, game integration, port 15526, raw state and actions | | Compact MCP proxy | This repository | token reduction, delta state, definition cache, deterministic automation, three-tool MCP interface |

Changes in this repository do not rebuild, replace, or patch the game DLL. Install and update the game mod from the upstream project. Modify this project when changing model-facing output, token usage, caching, automatic Continue or reward handling, or MCP client behavior.

Why

The upstream MCP is intentionally descriptive and complete. That is useful for general clients, but expensive for autonomous runs:

  • 64 tool schemas are loaded into model context
  • full map data is repeated on every map observation
  • card text, relic text, pile contents, and keyword definitions repeat often
  • an action and the following state read normally require separate calls

This proxy keeps interactive fields such as card indices, targets, legal options, and current card text, while removing repeated glossary and static metadata from the default response.

Measured against STS2MCP v0.4.0 in this repository:

| MCP surface | Tools | Serialized tool schema | | --- | ---: | ---: | | Upstream | 64 | 41,988 bytes | | Compact proxy v0.3 | 3 | 1,906 bytes |

That is a 95.5% reduction before game state is exchanged. The tool list remains intentionally fixed and is serialized in a stable order, so clients can reuse the same prompt prefix across turns.

Automatic deterministic actions

The proxy now removes transitions that do not need model judgment:

  • clicks main-menu continue
  • advances Ancient dialogue
  • clicks an event's sole unlocked Continue/Proceed option
  • collects gold
  • collects a potion when a slot is free
  • opens card rewards, but never chooses a card
  • proceeds after all automatically collectable rewards are gone
  • proceeds after a chosen rest-site or treasure action completes
  • proceeds after a completed Crystal Sphere or defeated fake merchant

Safety boundaries:

  • it never ends a combat turn
  • it never chooses a card, relic, map node, shop purchase, rest action, or event branch
  • it stops when potion slots are full
  • it emits a short alert when exactly three potions are held
  • it leaves non-requested reward types, including relic rewards, for the model
  • leaving a shop or skipping an unused rest site remains a model decision

Requirements

  • Python 3.11+
  • uv
  • Slay the Spire 2 running with STS2MCP enabled
  • STS2MCP REST server available at http://localhost:15526

Installation

1. Install the upstream game mod

Download the latest STS2MCP release. Copy these two release files into the game's mods directory:

STS2_MCP.dll
STS2_MCP.json

On macOS, the default directory is:

~/Library/Application Support/Steam/steamapps/common/Slay the Spire 2/
  SlayTheSpire2.app/Contents/MacOS/mods/

You can create it and copy the files from Terminal:

GAME_DIR="$HOME/Library/Application Support/Steam/steamapps/common/Slay the Spire 2"
MODS_DIR="$GAME_DIR/SlayTheSpire2.app/Contents/MacOS/mods"
mkdir -p "$MODS_DIR"
cp STS2_MCP.dll STS2_MCP.json "$MODS_DIR/"

Launch the game, open Settings -> Mods, enable STS2MCP, and accept the first-launch consent dialog. Verify the upstream REST server:

curl -s http://localhost:15526/

A JSON response with "status":"ok" means the game-side mod is ready. For Windows, Linux, source builds, and current compatibility notes, follow the upstream installation guide.

2. Install this compact proxy

Install uv and clone this repository:

brew install uv
git clone https://github.com/chiang881/sts2-compact-mcp.git
cd sts2-compact-mcp
uv sync

Run the proxy:

uv run sts2-compact-mcp

Or directly from a checkout:

uv run --directory /absolute/path/to/sts2-compact-mcp sts2-compact-mcp

3. Configure the AI client

{
  "mcpServers": {
    "sts2-compact": {
      "command": "/opt/homebrew/bin/uv",
      "args": [
        "run",
        "--directory",
        "/absolute/path/to/sts2-compact-mcp",
        "sts2-compact-mcp"
      ]
    }
  }
}

Disable the original sts2 MCP entry when using this proxy so the client does not load both sets of tool schemas. Keep the upstream game mod enabled: only its verbose Python MCP server is replaced by this compact proxy.

Restart the AI client after changing its MCP configuration. The game must be running with the upstream mod enabled whenever the proxy is used.

Tools

observe

observe(mode="delta", multiplayer=false)

Modes:

  • delta: only changes since the previous observation
  • compact: complete current screen in compact form
  • full: untouched upstream JSON for debugging

The first delta observation returns a complete compact state.

act

act(
  action="play_card",
  args={"card_index": 0, "target": "JAW_WORM_0"},
  revision=12
)

act accepts upstream raw action names and familiar aliases such as combat_play_card, map_choose_node, and rewards_pick_card. Legacy argument names such as node_index, reward_index, and option_index are translated automatically. An mp_ action prefix automatically selects the multiplayer endpoint.

After an action, the proxy waits for animation or enemy-turn transitions and returns the next meaningful decision state. Successful upstream acknowledgments and automatic clicks are omitted from the response. Supplying revision protects against acting on stale card or reward indices.

Stable card, potion, relic, and status metadata is emitted in a top-level defs dictionary only when first encountered or when it changes. This includes names, card types, rarity, targets, and rules text. Subsequent states refer to the item by ID while retaining dynamic fields such as index, cost, legality, upgrade state, and counters.

inspect

inspect(kind="map")
inspect(kind="wiki", query="Bash")
inspect(kind="profile")
inspect(kind="compendium")
inspect(kind="state")
inspect(kind="metrics")

Use inspect(kind="state") as the escape hatch for the full original state. inspect(kind="metrics") reports cumulative MCP result bytes and a rough token estimate. It is opt-in and is never attached to normal gameplay output. The MCP process cannot see provider-side cached_tokens, model output tokens, or the host application's complete conversation prompt.

What the model receives

The proxy does not build the model prompt. The host application combines its instructions, conversation history, the three MCP tool schemas, and each MCP result. This proxy controls only the tool schemas and tool results.

At each meaningful decision:

  • combat sends the complete current hand because playing a card shifts indices
  • draw, discard, and exhaust piles are grouped by card ID and count
  • card reward and selection screens send every current candidate
  • map state sends only the current position and immediately reachable nodes
  • descriptions and other stable item metadata use lazy defs
  • an act result already contains the next decision state, so an immediate follow-up observe is unnecessary

It does not send the entire deck on every turn. Full upstream state is returned only by an explicit observe(mode="full") or inspect(kind="state").

Prompt-cache behavior

Provider prompt caching depends on an exact shared prefix. This project helps by keeping the tool set fixed, sorting JSON object keys deterministically, and moving repeated definitions into an ID cache. Dynamic game state remains at the end of the conversation as tool results.

The MCP server cannot set the host's provider cache key or read its exact cache hit count. Inspect the API response usage or provider dashboard for authoritative cached_tokens; use inspect(kind="metrics") only for the MCP result portion.

In a representative four-card combat sample, compared with v0.2:

| Payload | v0.2 | v0.3 | | --- | ---: | ---: | | First encounter, including definitions | 1,095 bytes | 1,026 bytes | | Repeated state after definition cache hit | 957 bytes | 601 bytes |

The repeated state was about 37% smaller. Actual savings depend on hand size, duplicate cards, statuses, potions, and how often definitions recur.

Suggested agent policy

  1. Start with observe("compact").
  2. Pass the latest rev to every act.
  3. Use the state returned by act; do not immediately call observe again.
  4. Use observe("delta") after external UI changes.
  5. Use inspect only when a decision needs information omitted from compact state.
  6. Do not call reward-claim or continue actions unless the proxy stopped because a real choice remains.

Compatibility

The proxy does not modify STS2MCP, the game DLL, save data, action names, card indices, or target IDs. The original server can remain installed and is still available for clients that require all 64 legacy tools.

Development

uv sync --extra dev
uv run pytest

The test suite includes deterministic reward collection, full-potion-slot handling, hardwired Continue behavior, stale-state protection, and an explicit guard against automatic end_turn.

Quick Setup
Installation guide for this server

Install Package (if required)

uvx sts2-compact-mcp

Cursor configuration (mcp.json)

{ "mcpServers": { "chiang881-sts2-compact-mcp": { "command": "uvx", "args": [ "sts2-compact-mcp" ] } } }