Skip to main content
Glama

CivMCP

MCP server that lets an AI read your Civilization VI game and coach you. See PLAN.md for the architecture and phase history.

Description

CivMCP is a read-only MCP server for Sid Meier's Civilization VI (Aspyr Mac 1.4.6). It feeds an AI client — Claude Code, or any other MCP host — three kinds of truth about the game:

  1. Rules from the cached gameplay database (DebugGameplay.sqlite): techs, civics, units, districts, adjacency, eurekas.

  2. History from engine CSVs (Player_Stats, combat, diplomacy, boosts), archived so they survive the game wiping Logs/ on launch.

  3. Live state over the FireTuner socket (127.0.0.1:4318): cities, units, diplomacy, threats, tiles around a city.

A coaching layer on top of that records per-turn snapshots, compares you to speed- and difficulty-scaled pace targets, and turns the gap into advice.

You play every move. The model explains, prioritizes, and points at mistakes. It does not found cities, set production, or end the turn. That is the opposite of civ6-mcp, which plays the game; we reuse some of its read-only Lua (MIT) and nothing that mutates state.

Goals

  • Teach, don't autopilot. After a session you should know why a Campus wants mountains, why a second city is late, or why 4 science/turn has been flat — not just which button to press.

  • Cite the real game. Advice must come from this save's yields, queues, and logs, not from the model's memory of Civ VI.

  • Stay honest about pace. Marathon turn 30 is not standard turn 30. Benchmarks scale by game speed and difficulty so the coach does not invent a crisis.

  • Work on this Mac. Aspyr Apple Silicon has no Lua.log and no io in the sandbox. Live data goes through FireTuner; history goes through archived CSVs.

  • Keep it read-only. No RequestOperation, no deal-making, no “the AI takes your turn.” If a Lua snippet looks like a mutation, it is rejected.

  • Get better from real games. Keep findings that changed a decision; drop the rest. Snapshot history exists so later advice can say “science unchanged for 15 turns.”

Success looks like: you ask “what should I build in my capital and why?” and the answer names the actual queue, yields, and available districts; or “how has my science compared to the AI?” and you get a table from the logs.

Start the server

You need uv (Python 3.12 is installed per-project) and a Civ VI install that has been launched at least once so Logs/ and Cache/ exist.

cd ~/Projects/CivMCP
uv sync

One-shot checks (no MCP client)

uv run civmcp-smoke          # FireTuner: needs Civ VI running, a game loaded, EnableTuner 1
uv run python -m unittest discover -s tests -v
uv run mcp dev src/civmcp/__init__.py   # MCP inspector UI

uv run civmcp is the stdio MCP server. Do not run it by hand in a normal terminal and type at it — an MCP client must spawn it.

Register with Claude Code (this machine)

Already done once as:

claude mcp add civmcp -- uv run --directory ~/Projects/CivMCP civmcp

After you pull new tools/prompts, restart the MCP server (quit/reload Claude Code, or /mcp) so the client picks up the new list.

Other MCP clients

Point the client at stdio:

{
  "mcpServers": {
    "civmcp": {
      "command": "uv",
      "args": ["run", "--directory", "/Users/jonesdevlin/Projects/CivMCP", "civmcp"]
    }
  }
}

Live reads (optional but needed for “what should I build?”)

  1. Quit Civ VI.

  2. In ~/Library/Application Support/Sid Meier's Civilization VI/Firaxis Games/Sid Meier's Civilization VI/AppOptions.txt, under [Debug], set EnableTuner 1.

  3. Launch the game, load a save. The Tuner listens on 127.0.0.1:4318 (achievements are disabled while this is on).

  4. Confirm: uv run civmcp-smoke.

Rules, logs, saves, and log-based coaching work without the Tuner. Live city/unit/map tools do not.

Usage

Typical loop:

  1. Play a few turns (or load a save).

  2. In the MCP client, ask in plain English (examples below). The model should call coach_snapshot / coach_review_turn or the game_* tools — you do not invoke Lua yourself.

  3. Take the advice in-game. Repeat next turn.

Pace is scaled by game speed: Marathon turn N ≈ standard N/3. A one-city Marathon T28 game is still the ancient settler phase.

Example commands (what to type to the AI)

Coaching:

  • Review my turn. What should I do next?

  • Diagnose my science.

  • Diagnose expansion.

  • Explain Campus adjacency.

  • Explain why a Monument is the first building.

  • How does a science victory work from here?

  • What mistakes did I already make?

State (Tuner + loaded game):

  • What should I build in my capital and why?

  • List my units and who is idle.

  • Any barbarians near my cities?

  • What are the tiles around Constantinople?

  • Who have I met and are we at war?

History / logs (game does not need to be open):

  • How has my science compared to the AI over the last 30 turns?

  • Show recent combats and eurekas.

  • List my saves.

Rules (always available after one Civ VI launch):

  • What does a Campus get from mountains and geothermal fissures?

  • Compare Swordsman and Man-At-Arms.

  • What techs do I need for Crossbowmen?

  • Look up Dromon.

If the model has MCP prompts available, these map directly:

You say

Prompt / tool

“Review my turn”

prompt coach_review_turn or tool coach_snapshot

“Diagnose my economy / science / military / expansion”

prompt coach_diagnose

“Explain X”

prompt coach_explain or tool rules_lookup

Tools

Tool

Source

What

civ_status

filesystem

Where CivMCP looks for game data and what it finds. Archives engine CSVs on each call.

civ_tuner_status

Tuner socket

Is the game reachable; current turn if a game is loaded.

rules_lookup(name, kind?)

rules DB

Tech / civic / unit / building / district / improvement / policy / government: cost, prereqs, yields, unlocks, eureka, adjacency, description.

rules_adjacency(district)

rules DB

Full adjacency bonus table for a district.

rules_compare(kind, a, b)

rules DB

Side-by-side stats.

rules_path_to(target)

rules DB

Transitive tech/civic prerequisites with costs.

rules_schema(table?)

rules DB

Tables / columns.

rules_query(sql)

rules DB

Read-only SELECT; localization attached as loc.

game_history(metric, player?, last_n?)

engine CSVs

Per-turn science/culture/gold/faith/cities/score/… for you vs other majors. Survives launch truncation via data/logs/ archives.

game_recent_events(last_n?)

engine CSVs

Combat, meetings, envoys, eurekas, disasters, production-queue changes.

saves_list(limit?)

.Civ6Save headers

Turn, leader, civ, difficulty, speed, map size, timestamp.

game_overview()

Tuner Lua

Live turn, era, yields, government, policies, research/civic + turns left, era score.

game_cities()

Tuner Lua

Cities: pop, yields, housing, amenities, queue, districts, buildings, loyalty.

game_units()

Tuner Lua

Units: type, position, HP, moves, charges, promotions, idle.

game_diplomacy()

Tuner Lua

Relationship, war, grievances, alliances, agendas.

game_threats()

Tuner Lua

Visible enemy/barbarian combat units near you.

game_map_near(city?, radius?)

Tuner Lua

Tiles around a city, unimproved resources, rough district hints.

game_lua(code)

Tuner Lua

Read-only escape hatch; mutations are rejected.

coach_snapshot()

logs + Tuner + sqlite

Record this turn; return pace targets, trends, findings.

coach_findings(area?)

same

Findings only (economy / science / military / expansion).

Prompts

Prompt

What

coach_review_turn

Snapshot + history → at most 5 actions for this turn.

coach_diagnose(area)

Economy / science / military / expansion (or all).

coach_explain(thing)

How a tech/unit/district works, tied to the current game.

Resources

URI

What

civ://coach/benchmarks

Pace table (standard-speed turns) + speed/difficulty multipliers.

civ://coach/mistakes

Common-mistakes checklist.

civ://coach/victory/{path}

Science / culture / domination / religion / diplomacy checklist.

civ://coach/snapshots

Stored per-turn snapshots (data/snapshots.sqlite).

Live Tuner tools need Civ VI running with a game loaded and EnableTuner 1. Engine logs, saves, and coaching-from-logs work without the game open. Marathon turn N is treated as ≈ standard N/3 so the coach does not demand four cities at turn 30.

Tests

uv run python -m unittest discover -s tests -v

Civ VI on this Mac (Aspyr build 1.4.6)

Root: ~/Library/Application Support/Sid Meier's Civilization VI/

Path (under root)

What

Firaxis Games/Sid Meier's Civilization VI/AppOptions.txt

Engine options. [Debug] EnableTuner 1 enables the FireTuner listener (set by us; backup at AppOptions.txt.civmcp-backup). Verified 2026-09-06: opens 127.0.0.1:4318 (126 Lua states) and a decoy :4319 with none. The game rewrites this file on launch/quit, so edit it only while the game is closed. Enabling the Tuner disables Steam achievements.

Firaxis Games/Sid Meier's Civilization VI/Logs/

Engine logs. ~40 per-turn CSVs (Player_Stats.csv, Game_PlayerScores.csv, City_BuildQueue.csv, CombatLog.csv, DiplomacySummary.csv, Game_Boosts.csv, AI_*.csv). Truncated on every launch — archive them. No Lua.log on the Mac build (the string does not exist in the binary), so Lua print() is not a data channel here.

Firaxis Games/Sid Meier's Civilization VI/Cache/DebugGameplay.sqlite

Full gameplay rules DB (318 tables). Rebuilt on launch.

Firaxis Games/Sid Meier's Civilization VI/Cache/DebugLocalization.sqlite

Base-game text only (LocalizedText, BaseGameText). Expansion/DLC text comes from the install's Assets/DLC/*/Text/*.xml, indexed by textindex.py into data/dlc_text_en_US.json.

Sid Meier's Civilization VI/Saves/Single/

Manual saves; autosaves in auto/AutoSave_NNNN.Civ6Save. Magic CIV6, ~2 MB, mixed plaintext header + zlib chunks.

Sid Meier's Civilization VI/Mods/

User mods folder (where the snapshot mod goes).

Game install (read-only reference for Lua API examples): ~/Library/Application Support/Steam/steamapps/common/Sid Meier's Civilization VI/Civ6.app/Contents/Assets/Base/Assets/UI/