Harden /ask helper, UDP replies and run_lua in multiplayer

- Pass the /ask question to claude on stdin so it can't be parsed as a CLI option.
- Block run_lua in multiplayer unless an admin enables the new
  "Allow Lua queries in multiplayer" map setting.
- Ignore UDP packets that don't come from the game's port, in both the
  MCP server and the ask helper.
- Build the screenshot path from our own name instead of the game's reply,
  and restrict screenshot names in the mod.
- Validate ask packets, cap question length and limit concurrent claude runs.
- Replace hard-coded home paths in the README and systemd unit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
faabandClaude Opus 5.5 committed 2026-10-29 21:40:39 +01:00
1 parent 1a5cc7426e
commit c5b2f6d603
8 files changed
+79 -28

No files matched your search

+17 -10
View File
@@ -33,20 +33,21 @@ The game only listens on 127.0.0.1.
**3. Register the MCP server.** Requires [uv](https://docs.astral.sh/uv/).
Claude Code:
Claude Code (run from this repo's root):
```bash
claude mcp add factorio --scope user -e FACTORIO_UDP_PORT=34200 -- uv run --directory /home/faab/Documents/Code/Factorio/claude-co-engineer/server claude-co-engineer-mcp
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), then restart it:
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", "/home/faab/Documents/Code/Factorio/claude-co-engineer/server", "claude-co-engineer-mcp"],
"args": ["run", "--directory", "/path/to/claude-co-engineer/server", "claude-co-engineer-mcp"],
"env": { "FACTORIO_UDP_PORT": "34200" }
}
}
@@ -86,6 +87,10 @@ default, and are purely visual.
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 <question>` in the game chat (e.g. `/ask why is my green science slow?`). The answer
@@ -100,16 +105,17 @@ the places it mentions get highlighted. Follow-up questions continue the same co
This needs:
- the `claude` CLI logged in with your subscription (`claude auth login`, once);
- the helper running. Either start it by hand:
- the helper running. Either start it by hand from this repo's root:
```bash
~/Documents/Code/Factorio/claude-co-engineer/server/.venv/bin/claude-co-engineer-ask
uv run --directory server claude-co-engineer-ask
```
or install it as a systemd user service that starts at login:
or install it as a systemd user service that starts at login (from this repo's root; this fills in
its path):
```bash
cp server/claude-co-engineer-ask.service ~/.config/systemd/user/ && systemctl --user daemon-reload && systemctl --user enable --now claude-co-engineer-ask
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`.
@@ -120,7 +126,7 @@ 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 `server/claude-co-engineer-ask.service` (an alias or a full model ID)
`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.
@@ -128,7 +134,8 @@ Claude only gets the Factorio tools in these sessions: no shell, files or web. I
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_CLAUDE` (path to the CLI).
`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