MCP-rogal
Drive Minecraft from an AI assistant while you build mods and datapacks: real command results, searchable live logs, keyboard and mouse control, sandboxed datapack files, and fake players for testing multiplayer rules.
截图
介绍
MCP-rogal
An MCP server for building Minecraft mods and datapacks.
Point an AI assistant at your running game and it can write a datapack, reload it, run it, read
the error the game actually produced, and fix it — without you relaying anything by hand.
26 tools, Fabric, Minecraft 26.2.
The idea
Most of the time lost writing a datapack goes to one thing: something did not work and the game
would not say why. A macro missing one $(key) aborts the whole function. /reload reports
success while the pack it just tried to load failed. A trigger that was never armed looks exactly
like a button that does nothing.
So every command comes back with what really happened:
time set day → success=true result=1000
setblock ~ ~ ~ minecraft:not_a_block → errorType=parse cursor=15
execute if block ~ ~ ~ bedrock run say → success=false error=null
Three different outcomes, told apart: it worked and returned 1000; it never parsed, and here is
the character where parsing stopped; it ran fine and did nothing at all.
That last line is the one that matters. It is what a silent failure looks like, and it is now
visible instead of indistinguishable from success.
What it can do
Commands and timing
execute_commands— real status, return value, parse errors with a cursor position.
run_as: {player, permission_level}runs at a chosen permission level:execute as Xrebinds
@sbut keeps your permissions, so an operator-gated path looks fine until a real player
hits it. This tests the path a real player takes.advance_ticks, and await_ticksargument — state written this tick is not visible to a
read until the next one, so a read/write pair issued together silently sees stale values.validate_command— parse without running; also returns the completions available at the
cursor, which is how you discover what an argument accepts.
Logs
get_logs— cursor-based. The response carriesnextId; pass it back and you get only
what arrived since. Reportsmissedwhen the buffer overflowed past your cursor, so a gap is
visible rather than silent. Covers both the log file and in-game chat, which never reaches it.wait_for_log— blocks until a pattern appears. Trigger something, then wait for the line
that tells you whether it worked, instead of polling.get_crash_reports— for when the game died along with the buffer.
Datapacks
files— read, write, list, inside an allow-listed set of directories.reload_datapacks— runs/reloadand returns the log it produced, because/reload
succeeds even when a pack fails to load.get_world_info— save folder, datapack folder, and the pack formats this build
expects. A wrongpack_formatgets the pack rejected with nothing but a vague "Error reading
pack metadata", while every function inside it quietly does nothing.list_ids,describe_block_state— valid ids by registry, and the exact properties a
block accepts in[brackets]with their allowed values and defaults. No more guessing whether
a door needshalf=upperorpart=head.
Fake players
fake_players — real ServerPlayers in the player list, for testing rules that only exist
with more than one player. @a selects them, scoreboards score them, their UUID is derived from
their name so scores survive death, kill respawns them rather than leaving them dead, despawn
fires a genuine leave event, and /tp moves them between dimensions.
Nothing in game logic checks "is this one fake, skip it" — a test against special-cased code
proves nothing about the real thing.
What they cannot do: press a button in a dialog. That needs a client.
Client control
press_key,type_text,send_keybind,mouse— input goes through the same
entry points real input does, so it behaves identically in the world, in menus and in text
fields.get_open_screen— every widget with its rendered text and rectangle. Inspect a menu
without reading a screenshot; missing translations show up immediately, because an untranslated
widget renders its raw key.click_widget— click by the button’s visible label. An ambiguous match clicks nothing and
returns the candidates. Labels like "Delete World" are refused without explicit permission.open_screen,options— jump straight to a screen, or change a setting without
dragging a slider.reload_resources— F3+T, which has no command.rejoin_world— dynamic registries (dialog/,enchantment/,worldgen/) are only read
when a world loads./reloadleaves the old definitions in place, which looks exactly like
your edit having no effect.
Setup
Requires: Minecraft 26.2 · Fabric Loader 0.19.3+ · Fabric API · Java 25+
- Install Fabric Loader for 26.2
- Put Fabric API in
mods/ - Put this mod’s jar there too
- Start the game
The server starts on its own and logs:
HTTP MCP Server started on http://localhost:8080/mcp with 26 tools
Works on a client and on a dedicated server. On a dedicated server the tools that need a screen
are simply not registered.
Connecting an assistant
Claude Code:
claude mcp add --transport http minecraft http://localhost:8080/mcp
Cursor, Windsurf, VS Code — in your MCP config:
{
"mcpServers": {
"minecraft": {
"url": "http://localhost:8080/mcp"
}
}
}
A world has to be loaded. Without one the tools say so plainly.
In practice
The whole datapack loop, without leaving the game:
Write a function that gives every hunter a compass, put it in a datapack, reload it, and tell
me whether it loaded.
get_world_info for the folder and pack format → files write → reload_datapacks → read the
log. A pack that failed to load is reported, not assumed away.
Testing the non-operator path:
Check that
/dialog showis refused for an ordinary player but works through/trigger.
execute_commands with run_as: {permission_level: 0}.
A multiplayer rule:
Spawn two fake players, assign roles, and check each hunter gets their own compass.
Menu navigation:
Open the video settings and tell me what they are set to.
open_screen, then get_open_screen returns the text of every widget.
Configuration
config/mcp.json, created on first run:
{
"server": { "port": 8080, "host": "localhost", "requestTimeoutMs": 30000 },
"input": { "enabled": true, "allowDestructiveUi": false,
"preventPauseOnLostFocus": true },
"logs": { "bufferSize": 5000, "maxWaitMs": 60000, "maxBodyLogChars": 2000 },
"files": { "enabled": true, "allowDelete": false,
"allowedRoots": ["saves","config","datapacks","resourcepacks",
"logs","crash-reports"] },
"fakePlayers": { "enabled": true, "maxCount": 8 },
"auth": { "token": null }
}
preventPauseOnLostFocus — singleplayer normally pauses the moment you click into another
window, and the pause menu covers the view. Every screenshot and every screen read would then
report the pause menu instead of the game. This is off by default here; Escape still pauses.
Security
This endpoint runs commands, injects input and writes files. Treat it accordingly.
auth.token— when set, requires anAuthorization: Bearer <token>header.- The server refuses to start on a non-loopback host without a token.
- Files — confined to the allow list; paths resolving outside it, through
..or a symlink,
are refused. Deleting is off by default. - Destructive buttons — clicking "Delete World" and the like needs both a config flag and an
explicit argument. - Commands still pass a configurable safety validator.
Technical notes
- Input goes through the private
KeyboardHandlerandMouseHandlercallbacks via mixin
invokers rather thanKeyMapping, which is why it works in menus and text fields and not only
in the world. - Commands run on the server thread through
CommandSourceStack.withCallback, with parse errors
separated from runtime errors. In singleplayer that means the integrated server, so results are
real rather than inferred from chat. - Logs are captured by a Log4j appender attached programmatically, with a reentrancy guard.
- Tools live in a registry — adding one is a single class.
- Everything touching the loader sits behind a
Platforminterface, so a NeoForge port is the
entry point, the tick subscription and the mixin config; the rest is plain Minecraft API.
Troubleshooting
It will not connect — look for HTTP MCP Server started in the log. Port 8080 may be taken;
change server.port.
"No server is running" — no world is loaded.
A command returns success=false with no error — it ran and did nothing. Usually a condition
that did not match, or a function that returned early. Not a tool failure.
/function is always success=false — vanilla behaviour: a function returns 0 unless it
ends with /return. Check the world state, or add a /return.
A datapack is not picked up — check pack_format against get_world_info.
An edit does nothing after /reload — if it is under dialog/, enchantment/ or
worldgen/, use rejoin_world.
A click did not register — screens that fade out switch a few ticks later. Raise
settle_ticks or read get_open_screen again.
Credits and license
Built on top of mcp-server-mod by cuspymd, which
provided the original HTTP MCP bridge, the command safety validator and the block scanner.
Released under CC0-1.0, the same as the original — public domain, no strings.
Full tool reference: TOOLS.md · Русское описание: DESCRIPTION.ru.md
常见问题
MCP-rogal 支持哪些 Minecraft 版本?
MCP-rogal 支持 Minecraft Java 版 26.2,可用的加载器:Fabric。下载时注意选择和你游戏版本一致的文件。
MCP-rogal 怎么安装?
先用 PCL2 或 HMCL 启动器安装对应版本的 Fabric,再把下载的 .jar 文件放进游戏目录的 mods 文件夹,重新启动游戏即可。开启了版本隔离的,mods 文件夹在 versions/版本名 下面。
Roga1 的其他作品
查看全部 →Beter Ultra Hardcore
Improving hardcore redim for playing both on a server with friends and in the local world in hardcore mode
Dimension tracker + Afk display
Allows you to track in which dimension a player is tabbed, and find out if they are afk.
OneHP Challenge
HP Challenge, without the ability to resurrect even using commands.
评论
登录后评论和评分