minecraft-rcon-mcp
README.md
# minecraft-rcon-mcp
An [MCP](https://modelcontextprotocol.io) server that exposes a Minecraft Java
Edition server over [RCON](https://minecraft.wiki/w/RCON) as a tool, plus an
optional in-game **AI chat listener**: players type `ai <question>` in chat and
Claude answers in-game, using RCON to read live world state.
It is configured entirely through environment variables, so it is independent of
any particular server, world, or Minecraft version.
## Features
- **`run_command` tool** — run any Minecraft server command via RCON and return
the response. Use it from any MCP client (Claude Code, VS Code / Copilot, etc.)
to inspect or modify the live world.
- **In-game AI chat** — a background thread tails the server log; chat messages
prefixed with a configurable trigger (`ai ` by default) are answered by Claude
via the Anthropic API, with an agentic RCON tool-use loop and a rolling context
window. Responses are posted back with `/tellraw`.
- **Persistent memory** — the in-game agent reads two git-tracked memory files
into its context each request and can append to them with a `remember` tool,
so it accumulates knowledge across sessions instead of relying only on the
rolling chat window. See [Persistent memory](#persistent-memory).
- **`get_ai_chat_status` tool** — report listener health, history size, model,
log path, and memory configuration.
## Requirements
- Python 3.14+
- A Minecraft server with RCON enabled (`enable-rcon=true` in `server.properties`)
- An Anthropic API key (only if you use the in-game AI chat feature)
## Install
```bash
pip install git+https://github.com/scotteratigan/minecraft-rcon-mcp
```
Or, for local development / use from a sibling repo:
```bash
pip install -e path/to/minecraft-rcon-mcp
```
## Run
```bash
minecraft-rcon-mcp # console entry point
python -m minecraft_rcon_mcp # equivalent
```
The server speaks MCP over stdio, so it is normally launched by an MCP client
rather than by hand. Example client config (`.vscode/mcp.json`):
```json
{
"servers": {
"minecraft-rcon": {
"type": "stdio",
"command": "/path/to/.venv/Scripts/python.exe",
"args": ["-m", "minecraft_rcon_mcp"],
"env": {
"RCON_HOST": "localhost",
"RCON_PORT": "25575",
"RCON_PASSWORD": "your-rcon-password",
"LOG_PATH": "/path/to/server/logs/latest.log"
}
}
}
}
```
Provide `ANTHROPIC_API_KEY` in the launching environment (not in committed files)
if you want the in-game AI chat.
## Configuration
| Variable | Default | Purpose |
|---|---|---|
| `RCON_HOST` | `localhost` | RCON host |
| `RCON_PORT` | `25575` | RCON port |
| `RCON_PASSWORD` | `changeme` | RCON password (match `server.properties`) |
| `LOG_PATH` | `./logs/latest.log` | Path to the server log to tail. **Set this explicitly** — the default is relative to the working directory. |
| `AI_CHAT_ENABLED` | `1` | Set `0`/`false` to run a pure RCON tool server (no log tailing, no Anthropic usage). |
| `AI_PREFIX` | `ai ` | Chat trigger prefix (case-insensitive). |
| `AI_MODEL` | `claude-sonnet-4-5` | Anthropic model for in-game chat. |
| `AI_MAX_CONTEXT` | `10` | Exchanges retained in the rolling history. |
| `AI_MAX_TOKENS` | `1024` | Max tokens per chat response. |
| `AI_SYSTEM_PROMPT` | *(generic built-in)* | Replace the entire system prompt. |
| `AI_SYSTEM_PROMPT_EXTRA` | *(none)* | Append server-specific context (Minecraft version, house rules) to the default prompt. |
| `AI_MEMORY_ENABLED` | `1` | Set `0`/`false` to disable persistent memory (no files read or written). |
| `SERVER_MEMORY_PATH` | `./agent_memory.md` | Path to the **server-specific** memory file (world/player facts). **Set this explicitly** to a file in your server repo so it is git-tracked there, just like `LOG_PATH`. |
| `CAPABILITY_MEMORY_PATH` | *(packaged `agent_memory/capabilities.md`)* | Path to the **server-agnostic** capability/script memory. Defaults to a file shipped inside this package; override only if you want it elsewhere. |
| `WORLD_DIR` | — | World save folder (the one with `level.dat`). Required by the file-reading and structure-building scripts run via `run_script` (it can't be derived over RCON). |
| `STRUCTURES_DIR` | — | Folder of captured `.nbt` templates. Lets `run_script` builders/capture refer to structures by bare name (e.g. `generate_monument` → `ocean_monument`). |
| `MINECRAFT_JAR` | *(auto: `versions/*/server-*.jar`)* | Server jar read for the vanilla structure catalog/sizing (`generate_structure`/`generate_piece`). Set explicitly when the working dir isn't near the jar. |
| `ANTHROPIC_API_KEY` | — | Required for in-game AI chat. |
The `run_command` + `remember` tools are always available. Two more — `list_scripts`
and `run_script` — dispatch the Python toolbox (structure builders, world queries)
without one MCP tool per script; see [Scripts & recipes](#scripts--recipes). They're
also exposed to the in-game chat agent, so players can ask it to build things.
## Persistent memory
The in-game AI agent keeps **two separate memory stores**, both intended to be
version-controlled, so it accumulates knowledge across sessions. The split is
deliberate — each store lives in a different repo:
| Scope | What goes in it | Where it lives | Written via |
|---|---|---|---|
| `server` | Facts specific to **this** server, world, or its players — base/build coordinates, player preferences, house rules, world boundaries, ongoing projects. | The **consumer (server) repo**, at `SERVER_MEMORY_PATH`. Committed there. | `remember(scope="server")` |
| `capability` | **Server-agnostic** knowledge about this MCP — useful command patterns, what a script does, gotchas, techniques that help on any server. | **This package**, at `CAPABILITY_MEMORY_PATH` (defaults to [`agent_memory/capabilities.md`](src/minecraft_rcon_mcp/agent_memory/capabilities.md)). Committed here. | `remember(scope="capability")` |
**How it works:**
- **Read** — on every chat request, both files are read fresh and appended to the
system prompt under a `# Persistent memory` heading. Editing a file (by hand or
by the agent) takes effect on the next message; no restart needed.
- **Write** — the agent has a `remember` tool that takes `content` and a
`scope` (`server` | `capability`) and appends a one-line bullet to the matching
file, creating it with a header if absent.
Because the capability store defaults to a path **inside this package**, the
agent writes into it in place. That is committable when the package is installed
**editable** (`pip install -e`), which is the intended development setup; under a
plain wheel install it would write into `site-packages` instead, so set
`CAPABILITY_MEMORY_PATH` to a writable, tracked location if you deploy that way.
Disable the whole feature with `AI_MEMORY_ENABLED=0`.
## Scripts & recipes
The package bundles server-agnostic tooling split into two layers. They live here
(not in any one server repo) because they are reusable *capabilities*. The aim is
a toolbox of small, orthogonal **primitives** that compose efficiently, plus a
few **recipes** that show how to combine them for common tasks.
> **Writing one?** See [`CLAUDE.md`](CLAUDE.md) for the authoring rules
> (primitive vs. recipe, server-agnostic requirements, shared helpers, quality
> gates).
### Primitives — [`minecraft_rcon_mcp.scripts`](src/minecraft_rcon_mcp/scripts/)
Low-level building blocks, each doing one general thing:
| Primitive | Purpose | Needs world files? |
|---|---|---|
| `rcon` | Shared RCON client + CLI for running any command. | No (RCON only) |
| `count_entities` | Run an entity selector and return the parsed count. | No (RCON only) |
| `find_block_entities` | Scan region files for block entities (spawners, chests…). | Yes |
| `check_chunk_generated` | Whether given coords are in generated chunks. | Yes |
| `find_unexplored_edges` | Nearest ungenerated region frontier to a position. | Yes |
```bash
python -m minecraft_rcon_mcp.scripts.rcon "list"
python -m minecraft_rcon_mcp.scripts.count_entities "type=minecraft:cat,distance=..48" --at Steve
python -m minecraft_rcon_mcp.scripts.find_block_entities --x 0 --z 0 --block-id minecraft:chest
python -m minecraft_rcon_mcp.scripts.check_chunk_generated 1216 237 --dimension the_nether
python -m minecraft_rcon_mcp.scripts.find_unexplored_edges 120 45
```
### Recipes — [`minecraft_rcon_mcp.recipes`](src/minecraft_rcon_mcp/recipes/)
Higher-level, task-specific tools composed from the primitives (and sometimes
coupled to a particular Minecraft version's mechanics). Each is also a worked
example of composition:
| Recipe | Composed from | Notes |
|---|---|---|
| `cat_spawn_check <player>` | `count_entities` | Village cat-spawn gates; thresholds are version-coupled (26.x). |
| `reset_trial_spawners [player]` | `find_block_entities` + `rcon` | Finds trial spawners near a player, resets cooldowns. |
```bash
python -m minecraft_rcon_mcp.recipes.cat_spawn_check Steve
python -m minecraft_rcon_mcp.recipes.reset_trial_spawners
```
### Configuration
- **RCON** — read from `RCON_HOST` / `RCON_PORT` / `RCON_PASSWORD`. As a fallback,
`rcon.py` reads `rcon.port` / `rcon.password` from a `server.properties` in the
working directory (or `SERVER_PROPERTIES`).
- **`WORLD_DIR`** — tools that read save files need the world folder (the one with
`level.dat` / `dimensions/`). This **cannot be derived over RCON** (no vanilla
command exposes the save path), so set `WORLD_DIR`, or pass `--world-dir`.
- **`--dimension`** — region-reading tools default to the overworld; pass
`the_nether` / `the_end` / a namespaced id (`mymod:custom`) for others. Both
vanilla (`DIM-1`/`DIM1`) and data-driven (`dimensions/<ns>/<name>/`) layouts
resolve automatically.
> The world data itself lives in the server deployment, not in this repo — these
> tools only carry the *logic*, and reach the world through `WORLD_DIR`.
## Development
This project uses [uv](https://docs.astral.sh/uv/) for environment and
dependency management, [Ruff](https://docs.astral.sh/ruff/) for linting and
formatting, and [ty](https://github.com/astral-sh/ty) for static type checking.
The pinned Python version lives in `.python-version`; uv installs it for you.
```bash
uv sync # create .venv and install all deps (incl. dev tools)
uv run pytest # run the test suite
uv run ruff format # auto-format
uv run ruff check # lint (add --fix to auto-fix)
uv run ty check # type-check
```
## License
MIT — see [LICENSE](LICENSE).
TDQS
A3.6/5.0
Scored across 2 tools
Disambiguation5/5
The two tools, get_ai_chat_status and run_command, have clear and distinct purposes. One retrieves chat status, the other executes arbitrary commands, leaving no ambiguity.
Naming Consistency5/5
Both tool names follow a consistent verb_noun pattern (get_ai_chat_status, run_command), making them predictable and easy to differentiate.
Tool Count3/5
With only 2 tools, the server is minimally functional. While run_command covers core RCON operations, the additional AI chat tool is specific; the count is low but acceptable for a narrow purpose.
Completeness3/5
The server provides basic RCON command execution and AI chat status, but lacks tools for managing AI chat (e.g., enable/disable) or more granular server interactions, leaving notable gaps.
Maintenance
ActivityStale
ResponsivenessNo issues