# Sts2 Compact Mcp

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

- **Type:** MCP server
- **Install:** `agentstack add mcp-chiang881-sts2-compact-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [chiang881](https://agentstack.voostack.com/s/chiang881)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [chiang881](https://github.com/chiang881)
- **Source:** https://github.com/chiang881/sts2-compact-mcp

## Install

```sh
agentstack add mcp-chiang881-sts2-compact-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# STS2 Compact MCP

[简体中文](README.zh-CN.md) | [Copy-paste AI installation prompt](INSTALL_PROMPT.zh-CN.md)

A token-efficient MCP proxy for
[Gennadiyev/STS2MCP](https://github.com/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](https://github.com/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](https://github.com/Gennadiyev/STS2MCP/releases/latest).
Copy these two release files into the game's `mods` directory:

```text
STS2_MCP.dll
STS2_MCP.json
```

On macOS, the default directory is:

```text
~/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:

```bash
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:

```bash
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](https://github.com/Gennadiyev/STS2MCP#1-install-the-mod).

### 2. Install this compact proxy

Install [uv](https://docs.astral.sh/uv/) and clone this repository:

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

Run the proxy:

```bash
uv run sts2-compact-mcp
```

Or directly from a checkout:

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

### 3. Configure the AI client

```json
{
  "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`

```text
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`

```text
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`

```text
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

```bash
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`.

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [chiang881](https://github.com/chiang881)
- **Source:** [chiang881/sts2-compact-mcp](https://github.com/chiang881/sts2-compact-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-chiang881-sts2-compact-mcp
- Seller: https://agentstack.voostack.com/s/chiang881
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
