Skip to main content
Glama
README.md
# EU5 Advisor

[![License: AGPL v3](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](LICENSE)
![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)
![MCP](https://img.shields.io/badge/MCP-server-8A2BE2)

Ask an AI about your **Europa Universalis V** save game.

> "Where is my economy leaking?"
> *"42% of your available tax is not being collected.
> 14 of your 19 locations have no road to the capital, and those are exactly the ones
> with the lowest control. Hoorn alone is losing 6.6."*

Every number comes out of your own save file. Every building name, good and law comes
out of your own game installation. Nothing about EU5 is hardcoded in this project, so
the answers keep matching whatever patch you are playing.

## Status

Early alpha. Reading and advising only: it never modifies your saves.

## How it works

```
your save.eu5
      │
      ├─ rakaly            decodes the packed binary save
      ├─ pyeu5             resolves names through your game's own files
      │
      ▼
  snapshot.sqlite          a few MB, built once per save
      │
      ▼
  MCP server ──────────────► Claude
```

Decoding a mid-game save costs a couple of minutes and around 2.4 GB of memory, which
is not something you want sitting next to a running game. So that work happens once in
a throwaway process, and everything after it is answered from a small database in
milliseconds.

## What it will not do

- **It will not guess.** If a value is not in your save, the tools return `null` with a
  reason instead of a plausible-looking number.
- **It will not pretend to read a save it cannot decode.** When the game patches ahead
  of rakaly, you get a clear message saying so.
- **It will not encode game rules.** Thresholds used to rank problems are labelled as
  judgement calls; the measurements underneath them are read from the save.
- **It will not explain a mechanic from memory.** Rules are looked up, not recalled, and
  every rule comes back with the source it came from.

## Where the rules come from

Numbers are only half of an answer. Asked what raises control, the honest reply needs
three different kinds of fact, and they live in three different places:

| Source | What only it knows | Example |
|---|---|---|
| Your save | your actual numbers | Hoorn sits at 21% control and loses 6.6 tax a month |
| Your install | what your patch contains | a paved road grants +5 proximity; Paradox's own `readme.txt` says proximity is the "reduction of the distance to capital effect" |
| The [EU5 wiki](https://eu5.paradoxwikis.com) | engine logic that is in no readable file | +0.75% max control per proximity point |

That third row is the reason an assistant starts inventing things: the conversion from
proximity to control appears nowhere on your disk. So `explain_mechanic` fetches it,
cites it with a revision number, and then **checks it** by regressing control against
proximity across your own locations and comparing the measured slope to the wiki's
figure. On the reference save those two land within 10% of each other. When they do not,
the answer says so instead of picking one.

Wiki content is fetched at run time under CC BY-SA 3.0, cached in your own cache
directory and never bundled. Turn it off with `EU5_WIKI=off` or the installer checkbox;
rules that then cannot be verified are reported as unverified rather than guessed.

## Install

### Claude Desktop extension bundle (recommended)

Download `eu5-advisor.mcpb` from the [releases page](https://github.com/Neilbenji/eu5-advisor/releases/latest), then:

1. Open Claude Desktop and go to **Settings → Extensions**
2. **Drag the `.mcpb` file onto that window**, or use the install-from-file button there
3. Leave the settings fields empty, it finds your game and saves on its own

> Double-clicking the file does nothing. Windows has no file association for `.mcpb`,
> so it has to be dragged onto the Extensions window. That is a Claude Desktop
> limitation, not something this project can register around.

There is nothing else to install: no Python, no manual dependencies. It fetches what
it needs on first use. The settings dialog has fields for the game folder, the save
folder and whether to consult the wiki, but you only need them if autodetection fails
or you want to work offline.

Build it yourself from a checkout with:

```sh
npx @anthropic-ai/mcpb pack . dist/eu5-advisor.mcpb
```

### From a checkout

For development, register the working tree instead so `git pull` is the whole update:

```sh
uv run eu5-advisor install      # register with Claude Desktop and verify it works
uv run eu5-advisor status       # show what is registered and where
uv run eu5-advisor uninstall    # remove it again
```

`install` resolves dependencies, detects your game and saves, **starts the server and
completes a real MCP handshake before changing anything**, then registers itself in
`claude_desktop_config.json`. It backs the file up first, touches only its own entry,
and leaves your other MCP servers and preferences alone. If verification fails, your
configuration is not modified at all.

Restart Claude Desktop afterwards.

### Claude Code

```sh
claude mcp add eu5-advisor -- uv run --directory /path/to/eu5-advisor server.py
```

### Development

```sh
uv sync
uv run eu5-advisor doctor      # shows what it detected
uv run eu5-advisor index       # indexes your newest save
uv run --extra dev pytest
```

`doctor` finds your installation via Steam (including libraries on other drives), GOG,
or the `EU5_GAME_PATH` environment variable.

To build the installer:

```sh
uv run python bundle/make_icon.py
npx @anthropic-ai/mcpb validate manifest.json
npx @anthropic-ai/mcpb pack . dist/eu5-advisor.mcpb
```

### Which install route to use

| | `.mcpb` bundle | `eu5-advisor install` |
|---|---|---|
| Needs a checkout | no | yes |
| Update procedure | drop in the new bundle | `git pull` |
| Runs from | Claude Desktop's own copy | your working tree |
| Verifies before installing | no | yes |

The bundle is what to hand to a player. Use the checkout route while developing: the
bundle runs from a copy under `Claude Extensions/`, so edits to this repo have no
effect until it is repacked and reinstalled.

## Tools

| Tool | Answers |
|---|---|
| `list_saves` | Which saves exist, newest first |
| `load_save` | Pick one to work with (defaults to newest) |
| `country_overview` | Treasury, income, stability, laws, estates, research |
| `economy_breakdown` | Income, expenses, trade, loans, uncollected tax |
| `locations_table` | Every location with control, development and its tax gap |
| `find_problems` | Ranked list of what is going wrong, with the numbers behind it |
| `build_plan` | Which building where, what it returns, what it costs |
| `strategic_review` | The full assessment: standing, bottleneck, options, ordered plan |
| `explain_mechanic` | How a rule works, from all four sources, and whether they agree |
| `wiki_search` / `wiki_page` | The EU5 wiki, with revision and licence attached |
| `buildings_report` | Profit and upkeep per building type |
| `market_report` | Which goods are oversupplied or scarce |
| `diplomacy_overview` | Rivals, relations, neighbours |
| `compare_saves` | What changed between two saves |

## Licence

AGPL-3.0-or-later, inherited from [pyeu5](https://codeberg.org/Galla/pyeu5).

## Credits

- [rakaly](https://github.com/rakaly/cli) and [pdx-tools](https://github.com/pdx-tools/pdx-tools)
  by Nick Babcock, decodes the save format.
- [pyeu5](https://codeberg.org/Galla/pyeu5) by Adrian Chaves, save model and game-file parsing.

This project downloads rakaly's official release binary at runtime. It does not bundle
or reproduce rakaly's binary token table, which is deliberately not public.

## Author

Built by Kevin Luijken. I build AI integrations and MCP servers for products and teams; if you want Claude or another assistant connected to your own data, get in touch via [GitHub](https://github.com/Neilbenji).