Test Minecraft plugins end to end: drive a real Paper server and real protocol bots.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent โ or use 1-click editor setup below.
๐ก Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
Minecraft automation testing MCP server plugin for AI agents.
VitaminMCP is a Paper/Purpur server plugin. Drop VitaminMCP.jar into plugins/, start the
server, and it opens an MCP endpoint from inside the running server โ so an AI agent can drive that
server and read back what happened, while real bot clients connect to it over the Minecraft
protocol.
Nothing about the plugin you are testing changes. No test framework to adopt, no source to instrument, no harness to compile against, no mock server standing in for a real one: the plugin under test runs on a real server through its real lifecycle, and VitaminMCP watches it from the next plugin slot over. Which also means it works on plugins you did not write โ anything already installed is testable.
Drive a real Minecraft server and real players through MCP tools, and run end-to-end plugin tests without opening the game.
Player objectsFull usage is in docs/usage.md. Contribution rules are in CONTRIBUTING.md, and release steps
are in docs/publishing.md.
Three jars, in three different places. Only the first is a Minecraft plugin.
| Runs | Role | |
|---|---|---|
VitaminMCP.jar | in the server, as a plugin | Listens to every event, taps the log, and serves an authenticated MCP endpoint. The only piece with a view of server internals |
mcp-server.jar | on your machine, as a child of your MCP client | Speaks stdio to the client and HTTP to the plugin, and owns the bots |
runner.mjs or a platform bot-runner-* asset | on your machine, as a child of mcp-server | Connects real clients over the real protocol โ login, packets, GUIs and all |
The plugin sees server-side events, logs, permissions and state; the Node runner sees what a real client receives. Read-only mode is the default, and bots are optional.
Ask the agent to test a plugin, or pass a scenario to bot_run_scenario:
Two groups. Session tools live in mcp-server and are always present. Agent tools are
proxied from the plugin, so which ones exist is decided by the server you connected to โ
session_start returns their real definitions in agentTools.
session_start | Connect to a server and its agent. Every other tool needs it. Several sessions can be open at once โ one per backend of a proxied network |
session_reset | Disconnect every bot, keeping the connection. Use between independent tests. World state is not rolled back. close: true ends the session instead |
bot_spawn | Connect a bot and wait until it is standing in the world. UUID derives from the name |
bot_inspect | What the bot's client was actually sent: menu contents, messages (chat, action bar, title, subtitle) with the millisecond each arrived and a cursor to read only what came after an action, boss bars, sidebar scoreboard, health, food, experience and active effects |
bot_view | Open a localhost-only live world or inventory view for a bot. The inventory view needs nothing extra; the world view downloads an optional asset the first time it is asked for, published for Windows x64 |
bot_run_scenario | Run a whole scenario. Stops at the first failure with evidence attached |
server_info | Version, TPS, players online, installed plugins, capture statistics |
command_exec | Run a command as the console or as a player, vanilla commands included. Changes the server โ absent entirely unless read-only: false. When nothing takes the command it says why, rather than only that it did not |
state_query kind="player" | Position, gamemode, op, IP, and any permission nodes you name |
state_query kind="block" | The block at a coordinate |
state_query kind="inventory" | The menu a player has open โ the only place a plugin GUI's contents exist |
events_summary | Counts by event type. Call this before events_query โ it stays small however busy the server is |
events_query | Individual events, filtered by type and player, paged by cursor |
logs_query | Logs by minimum severity and regular expression |
exceptions_recent | Distinct exceptions with occurrence counts and first-seen times. Pass hash for a stack trace |
wait_for blocks until a condition holds, checked every tick inside the server.
| Condition | |
|---|---|
inventory_open | a menu opened, optionally matching a title |
inventory_contains | an item reached a slot โ for GUIs filled after they open |
event | an event fired, optionally for one player |
player_online / player_offline | a player joined or left |
player_state | online / gameMode / op reached a value |
player_near | a player came within a radius |
block_is / block_is_not | a block became, or stopped being, a material |
log_matches | a log line matched a regex โ for async work that changes nothing observable |
ticks | the server advanced N ticks |
There is no sleep, and there will not be one. A fixed wait is a guess about timing that is right
on an idle server and wrong on a busy one โ that is the entire mechanism by which flaky tests are
made. On timeout, wait_for returns the events and logs from that moment.
Available inside bot_run_scenario.
spawn / despawn | connect or disconnect a bot |
move_to | walk to coordinates by default; use mode: "teleport" for fast setup placement. Optional timeoutMillis distinguishes a sealed route from a walk that did not arrive in time |
break_block / use_block | break, or right-click a block โ use_block is how you open a chest |
use_entity | right-click an NPC, villager or armour stand, named by the coordinates it stands at |
attack_entity | left-click the nearest NPC, mob or armour stand at coordinates |
hold_item / drop_item | select a hotbar slot, or drop the held item/one held item |
place_block | place the held item against a block face |
jump / sneak / sprint | perform one jump, or set the movement state on/off |
look_at | look at world coordinates directly |
assert_reachable | ask whether a loaded path exists without moving; set reachable: false for sealed-region assertions |
click_slot | click a slot: left, right, shift_left, shift_right |
close_menu | close the open menu |
chat / command | say something, or run a command as the bot |
console | run a command as the console |
wait_for | any condition above |
Verification is the point, so this is where the surface is widest.
| Checks | |
|---|---|
assert_inventory | per slot: material, name, amount, lore, customModelData, modelDataString, empty โ plus the menu's title and size |
assert_player | online, gameMode, op. Waits rather than reads, because /op resolves asynchronously |
assert_block | the material at a coordinate |
assert_event | an event fired, optionally for one player, since the scenario began |
assert_message | the server told this bot something containing a string |
Use bot_inspect for messages, screen state and effects; use state_query for server state. Pass
proxied parameters flat at the top level. Full parameters are in docs/usage.md.
These are the requirements for using a prebuilt release:
| Minecraft server | Paper 1.21 or later (Purpur and other Paper forks work) |
| Java | 21, for the Paper server and local MCP server |
| Node | 18.17 or later, for npx |
| Minecraft version | Windows | Linux | macOS | Status |
|---|---|---|---|---|
| 1.18 โ 1.20.6 | ๐ด | ๐ด | ๐ด | Below the Paper agent floor |
| 1.21 โ 1.21.11 | ๐ข | ๐ข | ๐ข | Supported and live-tested |
| 26.1, 26.2 and later | ๐ก | ๐ก | ๐ก | Released; each needs a compatibility run before it is added |
No reviews yet โ be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/vitaminmcp)<a href="https://allmcps.com/mcp/vitaminmcp"><img src="https://allmcps.com/api/badge/vitaminmcp?style=directory" alt="VitaminMCP on AllMCPs" /></a>