STS2MCP: letting an assistant play a deckbuilding game
Full agentic runs for Slay the Spire 2. A mod that exposes in-game state, and the MCP server for the mod.
At a glance
- What is it?
- STS2MCP is a mod that opens a local interface onto a running game, so that an AI assistant can see the board and take turns. The interesting engineering is not the interface but the restraint: the parts of the game's state that a player would want are exposed, and the parts that would fill the context window are not, and the readme explains the limit in terms of what an agent can actually use.
- Who is it for?
- STS2MCP fits a developer who wants to watch an assistant play, or to build on the game's state as a research platform for agents. It does not fit somebody who wants a stable integration with a released game.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 86 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the project is
The project describes itself as an experimental research project to fully automate runs of a deckbuilding game, and it is two things: a mod for the game and a server that speaks the protocol assistants use to call tools.
The mod exposes the game state and the available actions over a REST interface on the local machine, and the server wraps that interface so that an assistant can drive it. So the assistant does not see the screen; it sees a description of the board, and it issues the same actions a player would.
That division is the whole design. The mod runs inside the game, where the real state is, and the server runs outside it, where the assistant is. The server is a separate program, written in Python, and the mod is a plugin for the game, written in a compiled language. The two meet at a local HTTP endpoint, and the readme says the server accepts options for the host and the port if the defaults do not suit.
The scope is wider than the name suggests. The readme lists single player and multiplayer, and then a long list of menu and lobby features: switching between profiles, character selection in both single and multiplayer roles with an optional seed, hosting a multiplayer game, joining through a friend invitation or through a local join, loading a lobby so that a saved co-op run can be resumed, dismissing the game-over screen, handling the tutorial popup, and controlling whether a timeline is visible.
That list is the interesting part, because it tells you what an agent needs in order to play well. Playing a card is the easy part. Noticing that the tutorial has popped up over the deck selection screen, or that the game-over screen is waiting, is the part that makes a session work at all, and the fact that the mod handles it means the author has run this a lot.
And there are two warnings, both prominent. The first is that the mod lets external programs read and control the game through a local interface, and that you should use it at your own risk on runs you care less about. The second is that multiplayer support is in beta, that most problems people encounter with the mod installed are caused by the mod rather than the game, and that you should disable the mod and confirm the problem persists before reporting it to the game's developers.
That second warning is unusually considerate, and it is the kind of thing a mod author writes after a week of confusing bug reports.
Installing it, and the one file people miss
The install is four steps and two files.
You download the latest release, copy the assembly and the manifest file into the game's mods directory, launch the game, and enable mods in the settings. The enable step shows a consent dialog the first time, and once you accept it the mod starts an HTTP server on a local port automatically. There is no configuration step and no launcher.
The platform note is worth its own paragraph, because it saves the reader a guess. The released assembly is platform-agnostic, so the same two files work on Windows, on Linux and on macOS, and there are no separate builds to choose between.
Which shifts the problem to the mods directory, and on macOS that is inside the application bundle rather than next to the executable. The readme gives the default Steam path, then the manual route of showing the package contents, going into the directory and creating a mods folder, and then a terminal route for the people who would rather not click through three windows of a file browser.
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 "$MODS_DIR/"
cp STS2_MCP.json "$MODS_DIR/"The two copy commands are the detail that matters, because the two files have different jobs and the manifest is the one people forget. The assembly is the code; the manifest tells the game that it exists, what it is called and what it does, and the mod will not appear in the list without it.
And the step after that is the one with a diagnostic value, because it distinguishes two very different failures. The server is running if the request returns a small JSON object naming the mod and its version. If the request is refused, the readme says the mod is not loaded, and the thing to check is the settings, not the code.
Two ways to wire it up, and one flag that saves sessions
The readme offers a choice of two integrations, in a table, and the left column is the one that needs no installation at all.
If you prefer a skill, you tell the assistant to read the raw documentation files in the repository and sit back. If you prefer the model context protocol server, you need a recent Python and a fast package manager, and the server has to be registered with the client.
The server is started with a single command that points at the server's own directory, and the readme explains what that command does: the package manager reads the project's own configuration file, creates an isolated environment, and installs the pinned dependencies from the lock file, and later runs reuse that environment immediately.
uv run --directory /path/to/STS2_MCP/mcp python server.py --helpThat is a good choice of invocation, because it removes the need to create a virtual environment by hand and guarantees the versions the server was tested with, and the lock file is in the repository, so the pinning is real rather than aspirational.
Registration is then a small JSON object with the command and its arguments, and the readme gives the exact shape for the two clients that matter, and says that other agents should have similar options. There is also a note about the client needing to be restarted after the configuration changes, which is the kind of step that is easy to miss and produces a confusing failure.
Two operational details in this section are worth keeping.
The first is a tip about the path to the package manager on macOS: use the absolute path in the command field, because a program launched from a graphical interface may not inherit the shell's path, and the server will therefore never start. That is one of those failures that looks like a bug in the server and is actually a difference in how the two programs were launched.
The second is the proxy flag. The server uses a common HTTP library, and that library picks up proxy settings from the environment by default, which causes connection trouble when the server runs inside a container. The flag disables that behaviour, so the server talks to the game directly.
And the verification step is the one that makes the whole thing diagnosable: ask the assistant to call the state function, and with the game running it should return the current state. That is a test that exercises the mod, the local server and the client in one step, and it is the correct first thing to try.
The profile layer, and the idea of durable context
The interesting endpoints are the ones that are not about the current room.
The interface separates profile-level progress from the live state of a run. One endpoint returns the active profile's persistent summary: what has been discovered, the achievements, the epochs, the per-character totals and the global run totals. Another groups that progress into the same high-level sections the game itself uses in its compendium, with the card library, the relic collection, the potion lab, the bestiary, the character statistics and the run history. A third lists the profile slots and which one is active, and a fourth switches or deletes a profile through the game's own user interface rather than behind its back.
Why this exists is stated in the readme, and it is a point about agent design rather than about the game. The compendium call is intended for agents that need durable context outside the current room or the current run. It works from the main menu, it includes a block describing the current run while one is in progress, and it summarises the saved run files for the active profile.
And then the detail that shows the author has thought about failure modes: the run history in the response is capped at the twenty most recent files, so that a long-lived profile does not create unbounded tool output.
That cap is the whole design principle in one number. An assistant's context is finite and its cost is per token, so a tool that returns everything is a tool that eventually breaks the session. So the tool returns the recent ones and the rest is on disk.
The same reasoning shows up in the wiki search, and the readme says so explicitly. The search never returns the whole catalogue: the mod first filters to the card and relic identifiers the active profile has actually discovered, and only then returns the best fuzzy matches. So the assistant is told about the twenty cards this profile has seen, not about the thousand in the game. The results are limited to ten by default and the limit can be raised, and the card results include the base and upgraded variants where both exist, because an agent that knows about a card but not its upgraded form will make a bad upgrade decision.
The model context server exposes the same set as tools, and the readme gives the names, so the two interfaces are the same interface in two shapes.
The multiplayer work, and what the release names say
The release history is short and its names are unusually informative, because they name the feature rather than the version.
One release adds menu navigation and multiplayer hosting. The one before it is a release candidate with a name that refers to a specific item in the game, and the one before that is described as a multiplayer consistency pass.
A consistency pass is a term that means something specific here. In a networked game, both players must see the same state, and the mod that exposes that state has to be careful about when it reads it and when it acts. A consistency pass is the work of making the mod's reads agree with the game's own state, so that an agent looking at the board sees what a human would see, and so that two players in a co-op run do not see different boards because of when the mod sampled them.
That is the hard part of the whole project, and it is worth naming as such. Exposing a state interface is easy. Exposing one that stays consistent across a networked session is the work, and it is why the readme's multiplayer warning exists at all.
The multiplayer feature list is also where the project's ambition shows. Hosting, joining through a friend invitation, joining locally, loading a lobby to resume a saved co-op run, an optional seed on character selection, dismissing the game-over screen, handling the tutorial popup, and toggling a timeline element. Each of those is a small thing that an agent would otherwise get stuck on, and the fact that they are implemented is the difference between a demo and something that can play a session end to end.
And the multiplayer warning is the honest counterpart to that. The support is in beta, the readme says to expect bugs, and it says that any problem encountered with the mod installed is very likely caused by the mod rather than by the game, and asks you to disable the mod and confirm the problem persists before reporting it to the game's developers. That is a mod author protecting a game studio's issue tracker from their own bugs, and it is the sort of courtesy that makes a mod welcome rather than a nuisance.
The repository, and the shape of the code
The top level of the repository is a mod, a server, and the paperwork of a project, and the file names describe the decomposition of the mod itself.
There is a main file for the mod, and then a set of files named after what they do: one for the actions the assistant can take, one for the compendium data, one for formatting, one for helpers, two for the multiplayer side, one for profiles, one for the settings screen, one for building the state description, and one for the wiki lookups. The state builder having its own file is the interesting one, because that is the component that decides what the assistant is shown, and it is the file you would edit to change what the model can see.
There is the project file and the solution file for the mod, a build script for Windows, a manifest file that the game reads to know the mod exists, and a directory for the documentation with the raw files that the skill-based integration reads.
And there is a directory for the server, which holds the Python project with its own configuration and its own lock file. The separation is complete: the mod has a build system in one language, the server has a package manager configuration in another, and the only thing they share is a local HTTP interface and a document format.
The governance files are worth a mention. There is a code of conduct, a contribution guide, a licence, an editor settings file, and a file instructing coding assistants, a sign that a project has decided how it wants automated contributions handled rather than leaving it to chance.
And the developer section is short: the build needs a recent software development kit for the compiled language and the base game, and the build script takes the game directory either as an argument or through an environment variable set once.
# Pass game path directly:
.\build.ps1 -GameDir "D:\SteamLibrary\steamapps\common\Slay the Spire 2"The comment says the second option is to set it once and forget it, which is the difference between a build step you run every time and one you configure once. For a project whose whole point is producing a mod you drop into a game directory, that is the only build step most users will ever need, and making it a single environment variable is the difference between a smooth first run and a support question.
Editorial conclusion
STS2MCP fits a developer who wants to watch an assistant play, or to build on the game's state as a research platform for agents. It does not fit somebody who wants a stable integration with a released game. Verify first that the game version you have is the one the mod was tested against, because the readme names a specific build and the mod reaches into the game's internals, that the multiplayer support is what you think it is, because the readme calls it beta and attributes most reported problems to the mod rather than to the game, and that you are willing to use it on runs you care less about, which is what the readme's own warning says.
Frequently asked questions
What does the STS2MCP project do?
It is a mod for a deckbuilding game that exposes the running game's state and available actions over a local REST interface, together with a server that exposes that interface to an AI assistant over the model context protocol. It supports single player and co-op, and it handles the game's menus, profile switching, character selection and lobbies as well as the play itself.
How do I install the STS2MCP mod?
Download the latest release, copy the assembly and its manifest file into the game's mods directory, launch the game and enable mods in the settings, accepting the consent dialog that appears on first launch. The mod then starts its local HTTP server automatically. The released files are platform-agnostic, so the same two files work on Windows, Linux and macOS, and on macOS the mods directory is inside the application bundle.
How do I check that the STS2MCP server is running?
Request the server's local address and look for a small JSON object naming the mod and its version. A refused connection means the mod is not loaded, and the thing to check is the mod list in the game's settings rather than anything in the code. To check the whole chain, ask the assistant to call the state function with the game running.
Why does the STS2MCP server limit the wiki search results?
Because the search never returns the whole catalogue. The mod first filters to the card and relic identifiers the active profile has actually discovered, and only then returns the best fuzzy matches, with ten by default. A long-lived profile must not fill the assistant's context with entries it never needed, and the run history in the profile summary is capped for the same reason.
Is the STS2MCP multiplayer support ready for use?
Not according to its own readme, which calls it beta and says to expect bugs, warns that problems seen with the mod installed are very likely caused by the mod rather than the game, and asks you to disable the mod and confirm the problem persists before reporting it to the game's developers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gennadiyev-sts2mcp)Was this useful?