mcp-worldedit-craftscript
MCP server enabling AI assistants to write and run WorldEdit CraftScripts on a Minecraft server as specific players, using live selections and undo history. Supports local stdio and remote HTTPS access with in-game code verification.
README
mcp-worldedit-craftscript
An MCP (Model Context Protocol) server that lets an MCP client (e.g. Claude) write and run WorldEdit CraftScripts against a running Minecraft server, using a specific player's live selection and undo history — usable remotely by multiple people without you having to hand out credentials.
It talks to the Minecraft server two ways:
- RCON, for player-agnostic things: craftscript file management, and whispering one-time verification codes.
- A small companion NeoForge mod, weditmcpbridge, for anything that needs to act as a specific player (running a craftscript, checking a selection, undoing).
Why the companion mod is required
The original design tried to do everything over RCON alone, using
execute as <player> at <player> run ... to make commands act as a specific player. This does
not work for WorldEdit. Confirmed empirically:
- Vanilla
execute as <player>genuinely does substitute the entity (asay/tellsent this way correctly shows up as coming from that player) — so RCON's entity substitution itself is fine. - But WorldEdit's
//-prefixed commands (//size,//undo, etc.) aren't even registered in vanilla's Brigadier command tree — WorldEdit intercepts them via its own chat-handling hook, separate from Brigadier entirely. There is no command string RCON can send that reaches them, regardless of how the source entity is set. - Craftscripts (
/cs, single slash) are similarly unreachable via Brigadier.
weditmcpbridge runs inside the same JVM as WorldEdit and dispatches commands through WorldEdit's
own pipeline instead: it wraps a real ServerPlayer into a WorldEdit Actor
(NeoForgeAdapter.adaptPlayer) and posts a CommandEvent to WorldEdit's own event bus — the exact
path a genuinely typed command takes. WorldEdit then correctly recognizes it as that player, uses
their live selection, and records the edit in their own undo history.
Two entry points
dist/stdio.js— for using Claude on this same machine (Claude Desktop's "Local MCP servers", or Claude Code's.mcp.json). Spawned directly by the client over stdio, fully trusted (whoever can launch a process on this machine already controls it), no identity verification.dist/index.js— an HTTPS server for remote access (other people, other computers). This is where the in-game identity verification below applies.
Use whichever fits — you don't need both, though running the HTTPS one via run.bat (for remote
friends) doesn't conflict with also using the stdio one locally. Both talk to the same
weditmcpbridge instance for player-scoped actions.
Note on Claude Desktop's "Connectors" UI: getting this working took three separate fixes:
- It requires the server to support OAuth (does a discovery/registration handshake before ever calling
/mcp) — this server implements a minimal OAuth authorization server for that (see below).127.0.0.1never works there — Connectors routes through Anthropic's cloud, so a loopback address resolves on their servers, not yours. Use a real reachable address.- It only connects to standard port 443 — a custom port (we originally used
8787) never gets reached at all, even though the exact same URL works fine for direct HTTP clients and Claude Code. Confirmed by switchingMCP_HTTP_PORTto443.For same-machine use, skip all of this — use "Local MCP servers" (stdio) instead.
How identity works (remote/HTTPS mode only)
There's no admin-distributed password to hand out — every path ends at the same in-game whisper-code verification, just reached two different ways depending on what your MCP client supports.
Path A — MCP tools (Claude Code, or any client that lets you add a headers field to a URL-based
server config):
- Someone tells Claude their Minecraft username.
- Claude calls
request_login_code— the server checks they're actually online right now, then privately whispers them a one-time code in-game as a clickable, colored chat message (server hasonline-mode=true, so Mojang has already verified who that account really is). - They read/copy the code, Claude calls
verify_login_codewith it. - That chat session is now authenticated as that player. If they're listed in
ops.json, they also get admin access. verify_login_codealso returns a device token — add it as a permanentAuthorization: Bearer <token>header (or?token=<token>in the URL, for clients that only let you enter a URL with no headers field) in that device's MCP client config, and future sessions skip the whisper-code step entirely.
Path B — OAuth (Claude Desktop's "Connectors", or any client that does an OAuth handshake
before calling /mcp):
- The client auto-discovers this server's OAuth endpoints (
/.well-known/oauth-authorization-server) and dynamically registers itself (/oauth/register). - It opens
/oauth/authorizein a browser — a small page asking for a Minecraft username, then the same whisper-code verification as Path A, just through a web form instead of MCP tool calls. - On success it redirects back to the client with an authorization code, which the client
exchanges at
/oauth/tokenfor an access token. - That access token is a device token under the hood — same file, same semantics, same per-request online-check — Path A and Path B end up in exactly the same place.
Every action that touches the game (run_craftscript, undo, get_selection_info) re-checks
that the relevant account is currently online on every call, regardless of how identity was
established — so a saved device/access token can't be used to act as someone while they aren't
actually connected and playing.
Requirements
- Node.js 20+
- A Minecraft server running WorldEdit 7.3.x, with RCON enabled
- Java 21 + the weditmcpbridge mod built and installed (see its own
README) — required for
run_craftscript/get_selection_info/undoto work at all
Setup
1. Enable RCON on your Minecraft server
In your server's server.properties:
enable-rcon=true
rcon.password=<a strong random password>
rcon.port defaults to 25575. Restart the server — these settings are only read at startup.
RCON itself only needs to be reachable from the machine running this MCP server (typically the same
machine), not from the internet — don't forward rcon.port through your router.
2. Build and install weditmcpbridge
Follow the weditmcpbridge README, then restart the
Minecraft server again. Confirm weditmcpbridge listening on 127.0.0.1:25577 appears in the log.
3. Install and build this server
npm install
npm run build
3b. Local-only use (same machine)
Add it to Claude Desktop's Local MCP servers (Settings → Developer → Edit Config) or Claude
Code's .mcp.json:
{
"mcpServers": {
"worldedit-craftscript-local": {
"command": "C:\\Program Files\\nodejs\\node.exe",
"args": ["C:\\path\\to\\mcp-worldedit-craftscript\\dist\\stdio.js"]
}
}
}
Skip straight to "Configure environment variables" below, then you're done; the rest of this README is about the remote/HTTPS path.
4. Configure environment variables
Copy .env.example to .env and fill in the paths for your server, including WEDIT_BRIDGE_HOST/
WEDIT_BRIDGE_PORT (defaults 127.0.0.1:25577 — only change if you changed WEDIT_BRIDGE_PORT on
the mod side too).
4b. TLS (required by some clients, e.g. Claude Desktop)
Some MCP clients only accept https:// URLs for custom connectors, even for 127.0.0.1. Generate
a certificate trusted by this machine using mkcert:
mkcert -install # one-time: adds a local CA to your OS trust store — run this yourself
mkdir certs
mkcert -cert-file certs/localhost-cert.pem -key-file certs/localhost-key.pem 127.0.0.1 localhost
Then set TLS_CERT_FILE/TLS_KEY_FILE in .env to those paths. Leave both unset to serve plain
HTTP instead (fine for clients that accept http://, or when reverse-proxying TLS elsewhere).
mkcert -install modifies your system's trust store, so run it yourself rather than scripting it.
For a certificate trusted by other people's devices too (not just this machine), you need a real CA — see "Making it reachable from another computer" below.
5. Run it alongside your Minecraft server
If you added the launch line to your server's run.bat (see below), it starts and stops
automatically with the server. Otherwise, run it manually:
npm start
It listens on http(s)://<MCP_HTTP_HOST>:<MCP_HTTP_PORT>/mcp (https if TLS_CERT_FILE/
TLS_KEY_FILE are set). Use port 443 if you want Claude Desktop's Connectors to be able to
reach it — see the Connectors note above.
6. Tying it to run.bat
run.bat can start this server (minimized, titled WorldEditMCP) right before launching the
Minecraft server, and kill it after the Minecraft server process exits:
start "WorldEditMCP" /min /D "C:\path\to\mcp-worldedit-craftscript" "C:\Program Files\nodejs\node.exe" "dist\index.js"
REM ... your existing java launch line ...
taskkill /FI "WINDOWTITLE eq WorldEditMCP*" /T /F >nul 2>&1
7. Making it reachable from another computer
Same machine only: set MCP_HTTP_HOST=127.0.0.1 and skip the rest of this section.
Over the internet:
- Keep
MCP_HTTP_HOST=0.0.0.0so it accepts connections from your router, not just localhost. - Set
MCP_HTTP_PORT=443— required for Claude Desktop's Connectors (see the note above); any port works for direct HTTP clients or Claude Code, but 443 is the safe default. - Open a Windows Firewall inbound rule for
MCP_HTTP_PORTyourself (this changes a security setting, so it's not something this project does for you):New-NetFirewallRule -DisplayName "WorldEdit MCP" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow - Forward that port on your router to this machine's LAN IP (router UI, not something scriptable from here).
- Get a stable hostname (e.g. free DuckDNS) if your public IP isn't static, plus an updater that keeps it current.
- Get a certificate trusted by everyone (not just this machine) via a real CA — e.g.
win-acme + your DDNS provider's DNS-01 validation (if it has an
update API, like DuckDNS's
txt=parameter). This avoids needing port 80 open at all. PointTLS_CERT_FILE/TLS_KEY_FILEat the issued chain/key.pemfiles, and set up auto-renewal (win-acme registers its own scheduled task — needs to run elevated once) with a post-renewal hook that restarts the MCP server process so it picks up the renewed cert. - Anyone connecting from outside needs the resulting public address plus
/mcpas their MCP server URL — no token needed up front, since they verify via the in-game code flow above the first time (or the OAuth flow, for Connectors).
Tools
| Tool | Auth required | Description |
|---|---|---|
request_login_code |
none | Whisper a one-time code to an online player |
verify_login_code |
none | Complete verification; returns a persistent device token |
run_craftscript |
own username or admin | Run a craftscript as a player (via weditmcpbridge) |
get_selection_info |
own username or admin | Check a player's active selection (via weditmcpbridge) |
undo |
own username or admin | Undo a player's last N WorldEdit operations (via weditmcpbridge) |
inject_craftscript |
admin (server op) | Write a .js craftscript into the craftscripts folder (RCON-free, filesystem only) |
list_craftscripts |
admin (server op) | List available craftscripts |
read_craftscript |
admin (server op) | Read back a craftscript's source |
delete_craftscript |
admin (server op) | Delete a craftscript file |
Note: get_selection_info can currently only report whether the command succeeded, not the
selection's actual type/size/coordinates — WorldEdit sends that detail straight to the player's
own chat, and the bridge doesn't capture chat text yet. Ask the player to check their own chat, or
have them run //size themselves.
Validating your setup
Confirmed working end-to-end (2026-08-08) with a real player:
//sizevia the bridge → real selection info appeared in the player's chat./cs <script> <args>via the bridge → the script actually ran, editing real blocks, with the script's owncontext.print()output appearing in the player's chat.- The player's own
//undocorrectly reversed a bridge-triggered edit. - The
undotool (via the bridge) correctly reported "Nothing left to undo" against empty history, and successfully reversed a real edit when there was one.
If you're setting this up fresh, re-run this checklist with your own WorldEdit/NeoForge versions —
command registration details (e.g. which literal // vs / a given command uses) could differ
across WorldEdit versions.
Security notes
- Non-admin identities can only act as their own verified username; admins (server ops) can act as anyone and manage craftscript files.
run_craftscript,undo, andget_selection_infore-check the target account is currently online on every call, even for saved device tokens. Craftscript file management (inject/list/ read/delete) doesn't require anyone to be online — it has no live gameplay effect until a script is actually run.- Device tokens (
devices.json), OAuth client registrations (oauth-clients.json), and the RCON password are plaintext secrets/state — never commit them. All are gitignored. - The OAuth
/oauth/*endpoints let anyone who can reach this server register a client and start an authorization flow — that's normal for public OAuth clients (no secret required, matching the spec for native apps using PKCE), and the flow still ends at the same online-player whisper-code check as everywhere else. Registering a client costs nothing by itself; only completing verification for a real, currently-online account yields a usable token. weditmcpbridge's TCP endpoint has no authentication of its own and must only ever be bound to127.0.0.1— anything that can reach it can act as any online player with full WorldEdit access. It's protected purely by not being network-reachable; don't change that binding.- Deleting a craftscript only removes the file; it has no effect on blocks already placed in-game.
- Exposing this to the internet means anyone can attempt
request_login_codefor any username — they can't gain access without reading the whispered code in that player's own chat, but it will spam a whisper to real players if abused. There's a cooldown per username, but no broader rate-limiting.
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.