# Claude Co-Engineer Ask Claude questions about your live Factorio game — "what should I do next?", "why is my science slow?", "where's the nearest iron?" — from Claude Desktop or Claude Code, using your subscription instead of API tokens. Works in singleplayer; no RCON needed. It's read-only by design: Claude looks, explains and suggests; you play. ``` Claude Desktop / Claude Code ──stdio(MCP)──▶ server/ (Python) ──UDP localhost──▶ mod/ (in-game Lua) ``` The mod uses Factorio 2.x's Lua UDP API (`helpers.recv_udp` / `send_udp`), which is enabled per game instance with `--enable-lua-udp `. ## Setup **1. Install the mod** (symlinked, so edits apply on the next save load): ```bash ln -s "$PWD/mod/claude-co-engineer" ~/.factorio/mods/claude-co-engineer ``` Then enable "Claude Co-Engineer" in the in-game Mods menu. **2. Launch Factorio with UDP enabled.** In Steam: Factorio → Properties → Launch Options, add: ``` --enable-lua-udp 34200 ``` The game only listens on 127.0.0.1. **3. Register the MCP server.** Requires [uv](https://docs.astral.sh/uv/). Claude Code (run from this repo's root): ```bash claude mcp add factorio --scope user -e FACTORIO_UDP_PORT=34200 -- uv run --directory "$PWD/server" claude-co-engineer-mcp ``` Claude Desktop — add to `claude_desktop_config.json` (Settings → Developer → Edit Config), with `/path/to/claude-co-engineer` replaced by where you cloned this repo, then restart it: ```json { "mcpServers": { "factorio": { "command": "uv", "args": ["run", "--directory", "/path/to/claude-co-engineer/server", "claude-co-engineer-mcp"], "env": { "FACTORIO_UDP_PORT": "34200" } } } } ``` Local (stdio) MCP servers only work in the desktop app and Claude Code, not claude.ai in a browser or the mobile apps. ## Tools | Tool | Answers | |---|---| | `get_overview` | Where am I, what am I hovering, what's researching, what's broken — start here | | `get_player` | Inventory, cursor, hand-crafting queue, hovered/opened entity | | `inspect_entity` | Everything about the hovered entity (or one at x,y): status, recipe, contents, fuel, power | | `find_problems` | Machines not working, grouped by status (no_ingredients, full_output, low_power, …) with nearest examples | | `find_entities` | What's around a point; ore patches with total amounts | | `get_production` | Produced/consumed/net per minute per item and fluid | | `get_power` | kW consumption and production per electric network | | `trace_belt` | Follows a belt (the hovered one by default) through undergrounds, side-loads and splitters: fill and motion per section (backed up vs full and flowing), what inserters and drills put on or take off, and where it ends | | `get_trends` | How production, consumption and power changed over the last 10 min / hour / 10 hours; finds the biggest movers by itself | | `get_research` | Current/queued research, what's researchable now, the path to any technology | | `get_recipe` | How to make something, in which machines, whether it's unlocked, what uses it | | `calculate_ratios` | Machines, drills, belts and power for a target rate (or machine count), using your unlocked recipes and machines, research productivity, and what you've already built | | `screenshot` | An image of part of the map (Alt mode on, always daylight) for layout questions | | `highlight` / `clear_highlights` | Outline places in your game, with labels, guide lines from you, and clickable map links in chat | | `run_lua` | Read-only Lua query for anything else | "This" usually works: hover over a machine and ask "why isn't this working?". When Claude points you at something, it outlines it in your world and posts a `[gps]` link in chat (click it to open the map there). Highlights are visible only to you, expire after a minute by default, and are purely visual. `run_lua` is instructed to only read, but Lua can't be sandboxed read-only. To guarantee nothing in your world changes, turn off **Allow Lua queries** in Settings → Mod settings → Map. Every query is logged to `factorio-current.log`. In multiplayer, `run_lua` is off unless an admin also turns on **Allow Lua queries in multiplayer**: the Lua runs for everyone, and text other players put in the world (station names, labels) ends up in what Claude reads, so it could be talked into changing things. ## Asking from inside the game Type `/ask ` in the game chat (e.g. `/ask why is my green science slow?`). The answer appears in chat a few seconds to a minute later, with clickable map links and item icons, and the places it mentions get highlighted. Follow-up questions continue the same conversation; `/ask-new` starts a fresh one. ``` /ask ──UDP──▶ claude-co-engineer-ask ──▶ claude -p (+ this MCP server) ──▶ answer ──UDP──▶ chat ``` This needs: - the `claude` CLI logged in with your subscription (`claude auth login`, once); - the helper running. Either start it by hand from this repo's root: ```bash uv run --directory server claude-co-engineer-ask ``` or install it as a systemd user service that starts at login (from this repo's root; this fills in its path): ```bash uv sync --directory server && mkdir -p ~/.config/systemd/user && sed "s|/path/to/claude-co-engineer|$PWD|" server/claude-co-engineer-ask.service > ~/.config/systemd/user/claude-co-engineer-ask.service && systemctl --user daemon-reload && systemctl --user enable --now claude-co-engineer-ask ``` Its log shows each question and answer: `journalctl --user -u claude-co-engineer-ask -f`. Pick the model under Settings → Mod settings → Per player → **/ask model**: Haiku, Sonnet (default), Opus or Fable. Bigger models give more thorough answers but are slower and use more of your plan's usage. It's per player, so in multiplayer everyone picks their own. The dropdown entries are aliases, which the `claude` CLI resolves to the newest model of that name, so a new Sonnet or Opus is used automatically. To force any other model, uncomment `FACTORIO_ASK_MODEL_OVERRIDE` in `~/.config/systemd/user/claude-co-engineer-ask.service` (an alias or a full model ID) and run `systemctl --user daemon-reload && systemctl --user restart claude-co-engineer-ask`. It wins over the in-game setting for everyone. Claude only gets the Factorio tools in these sessions: no shell, files or web. If the helper isn't running, the game tells you after 3 seconds. The helper's port is a map setting (Ask helper port, default 34201). Helper environment variables: `FACTORIO_ASK_PORT`, `FACTORIO_ASK_MODEL` (model when the game doesn't send one, default `sonnet`), `FACTORIO_ASK_MODEL_OVERRIDE` (always use this model), `FACTORIO_ASK_TIMEOUT` (300 s), `FACTORIO_ASK_MAX_CONCURRENT` (Claude runs at once across all players, default 2), `FACTORIO_ASK_CLAUDE` (path to the CLI). The helper only accepts packets from the game's UDP port. ## Ratio calculator Ask things like "how many assemblers for 1 green science per second?" or "what does 10 red science assemblers need?". `calculate_ratios` works from your game, not a generic table: - **Recipe:** the unlocked one for each item (never recycling). Mineable items count as mined, so Space Age asteroid ore doesn't sneak in. - **Machine:** the type you already use for that recipe, otherwise the fastest one you've unlocked. - **Productivity:** research and machine bonuses are included. Modules and beacons aren't (yet). - **Output:** per step, how many machines you need, how many you've already built on that recipe, and how much you currently make. Ore becomes mining drill and belt counts. Tell it what you already supply ("plates come from my main bus") to stop the breakdown there, or override the recipe or machine for any item. Byproducts are listed but not subtracted from demand. ## Configuration Environment variables for the server: `FACTORIO_UDP_PORT` (default 34200), `FACTORIO_UDP_HOST` (127.0.0.1), `FACTORIO_TIMEOUT` seconds (5), `FACTORIO_SCRIPT_OUTPUT` (`~/.factorio/script-output`). Screenshots are rendered off-screen with `game.take_screenshot` (your camera doesn't move), written to `script-output/claude-co-engineer/`, and deleted once sent to Claude. ## Troubleshooting - **"No reply from Factorio"**: the game must be running a save, launched with `--enable-lua-udp` on the same port, with the mod enabled — and not paused. Singleplayer pauses while the Esc menu is open. - **Headless servers** pause with no players connected unless `auto_pause` is false in server settings. With nobody connected, queries use the `player` force and the first surface. - **Screenshots** need a game client that renders; a headless server can't take them. - Changes to `control.lua` take effect after reloading the save; changes to `settings.lua` need a full game restart.